Data display
Drag and drop
Drag to reorder rows, move them between lists, rearrange a grid of cards or the rows of a table, with handles, drop lines and the same moves from the keyboard and screen readers. Tree, Kanban and file drop zones use the same system.
import { ListView, ListItem, DragHandle, DropIndicator, useDragAndDrop, useListData, reorderItems } from '@alea/ui';
Examples
Reorder a list
Pass items and onItemsChange: rows get a handle and can be dragged. With the keyboard: Tab to a handle, Enter to pick up, arrows to choose where, Enter to drop.
Between lists
Lists with the same dragGroup accept each other's rows: drag a task from To do to Done, or drop it in an empty list.
To do (3)
Done (1)
A grid of cards
layout="grid" puts items in columns (arrow keys move in two directions) and drag reorders them: dashboards, photo sets, pinned items.
Table rows
For tables, pass dragAndDropHooks from useDragAndDrop (with useListData for the rows): a handle column appears by itself, with the same keyboard and screen reader support.
| Drag to move | Page | Owner |
|---|---|---|
| Homepage | Ana | |
| Pricing | Bruno | |
| Docs | Carla | |
| Blog | Dario |
Tokens
The design tokens this component reads, with their value in the current theme. Override any of them to restyle it.
Color
--alea-accent…--alea-accent-subtle…--alea-border…--alea-focus…--alea-surface…
Space
--alea-space-2…--alea-space-3…
Radius
--alea-radius-md…--alea-radius-sm…
Shadow
--alea-shadow-card…
Component
--alea-list-min…
Props
ListView props
A list of rich items people can select, open or act on, with keyboard navigation. Rows can be dragged to reorder, or between lists; cards can sit in a grid.
| Prop | Type | Default | Description |
|---|---|---|---|
dragGroup | string | - | Lists with the same dragGroup accept each other's rows. Items must be plain data (they travel as JSON). |
layout | "grid" | "stack" | 'stack' | stack (rows, default) or grid (cards in columns, arrow keys move in two directions). Set the column width with --alea-list-min. |
onItemsChange | ((items: T[]) => void) | - | With items: rows can be dragged to reorder (and moved between lists with the same dragGroup). Called with the new array. |
variant | "separated" | "joined" | "plain" | 'joined' | Lines between items (joined), separate cards, or nothing (plain). |
DragHandle props
The handle that starts a drag with the keyboard (Enter) or a screen reader. Put it in rows of a draggable list or table.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | |
label | string | - |
DropIndicator props
The line that shows where a dragged row will land. Use it in renderDropIndicator of your own drag and drop.
| Prop | Type | Default | Description |
|---|---|---|---|
targetrequired | DropTarget | - | The drop target that the drop indicator represents. (inherited) |
children | ChildrenOrFunction<DisclosureGroupRenderProps> | - | The children of the component. A function may be provided to alter the children based on component state. (inherited) |
className | ClassNameOrFunction<DropIndicatorRenderProps> | - | The CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the element. A function may be provided to compute the class based on component state. (inherited) |
style | StyleOrFunction<DisclosureGroupRenderProps> | - | The inline [style](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style) for the element. A function may be provided to compute the style based on component state. (inherited) |
Specs
Generated from the source: the variants in the types, the states and tokens in the CSS, and the motion patterns that apply. The grids render the real component in both themes; the numbers are measured from the page.
ListView
- Variants
layoutgridstackvariantseparatedjoinedplain- States
- Keyboard focusDrop target
- Dark and light
- Every color comes from theme tokens, so it follows data-theme (and presets like Graphite) on the page or any wrapper. Contrast is checked in both themes.
- Styling hooks
.alea-list- Data attributes
data-variant=joineddata-variant=separateddata-variant=plaindata-layout=griddata-empty
DragHandle
- States
- Hover
- Motion
- press
- Dark and light
- Every color comes from theme tokens, so it follows data-theme (and presets like Graphite) on the page or any wrapper. Contrast is checked in both themes.
- Styling hooks
.alea-drag-handle
DropIndicator
- States
- Drop target
- Dark and light
- Every color comes from theme tokens, so it follows data-theme (and presets like Graphite) on the page or any wrapper. Contrast is checked in both themes.
- Styling hooks
.alea-drop-indicator- Data attributes
data-layout=grid
Accessibility
- Every drag works without a mouse: Tab to a handle, press Enter to pick up, arrows to choose where, Enter to drop, Escape to cancel.
- Screen readers hear what was picked up, where it would land, and where it landed.
- Drop lines and highlighted targets show where the item will go; they never rely on color alone (a line and an outline).
Keyboard
| Key | Does |
|---|---|
| Tab | Moves to a drag handle |
| Enter | Picks up, then drops |
| Arrow keys | Choose where to drop |
| Escape | Cancels the drag |
Do and don't
Do
- Give every draggable row a handle so keyboard and screen reader people can move it.
- Use dragGroup for lists that trade rows; keep items as plain data.
- Offer a menu action too (Move to…) for long moves.
Don't
- Don't make drag the only way to do something important.
- Don't make the whole row a drag target and also a link.