Basic usage
SortableList renders each item with renderItem and adds a drag handle after it. It is
controlled: keep the items in state and update them in onSortEnd, which receives the items in
their new order.
Every item needs a unique id. It is used to track the item while it is dragged.
import {SortableList, Text} from '@pleo-io/telescope'
const ColumnOrder = () => {
const [columns, setColumns] = React.useState([
{id: 'name', label: 'Name'},
{id: 'email', label: 'Email'},
{id: 'role', label: 'Role'},
])
return (
<SortableList
items={columns}
onSortEnd={setColumns}
renderItem={(column) => <Text>{column.label}</Text>}
/>
)
}Items can only be dragged vertically, and only within the list.
Interactive items
renderItem can return interactive content, such as a Checkbox to show or hide a column. Only the
drag handle starts a drag, so the content stays usable.
<SortableList
items={columns}
onSortEnd={setColumns}
renderItem={(column) => (
<Checkbox
name={column.id}
checked={column.visible}
onChange={(event) => toggleColumn(column.id, event.target.checked)}
>
{column.label}
</Checkbox>
)}
/>Separators
Use renderSeparator to render content between two items, for example a divider. It is not rendered
after the last item and is not draggable.
<SortableList
items={rules}
onSortEnd={setRules}
renderItem={(rule) => <RuleCard rule={rule} />}
renderSeparator={() => <Divider />}
/>Accessibility
- Each drag handle is a
button, labelled withSortableList.DragHandle, that can be reached with Tab. Press Space to pick up the item, the arrow keys to move it, Space to drop it and Escape to cancel. - The handle is described by
SortableList.ScreenReaderInstructions, which explains these keys. - Screen readers announce when an item is picked up, moved, dropped or put back. The announcements
read out the item's
id, its position and the number of items.
Localisation
The handle label, instructions and announcements come from the SortableList keys of the
translations passed to TelescopeProvider. The announcements are functions that receive the
item's id, its position (starting at 1) and the number of items:
<TelescopeProvider
translations={{
...translations,
SortableList: {
DragHandle: 'Drag to reorder.',
ScreenReaderInstructions: 'To pick up a sortable item, press the space bar. …',
PickedUp: (id, position, count) =>
`Picked up sortable item ${id}. Sortable item ${id} is in position ${position} of ${count}`,
Moved: (id, position, count) =>
`Sortable item ${id} was moved into position ${position} of ${count}`,
Dropped: (id, position, count) =>
`Sortable item ${id} was dropped at position ${position} of ${count}`,
Cancelled: (id, position, count) =>
`Sorting was cancelled. Sortable item ${id} was dropped and returned to position ${position} of ${count}.`,
},
}}
>API reference
| Prop | Type | Default |
|---|---|---|
items (required)The items to render, in their current order. Each | T[]T[] | |
onSortEnd (required)Called with the reordered items when an item is dropped in a new position. | function(items: T[]) => void | |
renderItem (required)Renders the content of an item. The drag handle is rendered after it. | function(data: T) => Element | |
renderSeparatorRendered between two consecutive items (never after the last one), for example an "if no match, try next" divider for a list whose items are evaluated in order. It sits outside each item's draggable wrapper, so it isn't itself draggable. | enum(item: T, index: number) => ReactNode |