Skip to content
Alea0.1
Pro
  1. Alea
  2. Components
  3. Data display
  4. Drag and drop

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.

Write the brief
Sketch three directions
Review with the team
Ship it

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)

Tokens audit
Tree docs
Charts motion

Done (1)

Breadcrumbs

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.

RevenueDrag to move
UsersDrag to move
PaymentsDrag to move
ActivityDrag to move
RegionsDrag to move
SpeedDrag to move

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
HomepageAna
PricingBruno
DocsCarla
BlogDario

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.

PropTypeDefaultDescription
dragGroupstring-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.

PropTypeDefaultDescription
classNamestring-
labelstring-

DropIndicator props

The line that shows where a dragged row will land. Use it in renderDropIndicator of your own drag and drop.

PropTypeDefaultDescription
targetrequiredDropTarget-The drop target that the drop indicator represents. (inherited)
childrenChildrenOrFunction<DisclosureGroupRenderProps>-The children of the component. A function may be provided to alter the children based on component state. (inherited)
classNameClassNameOrFunction<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)
styleStyleOrFunction<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
layoutgridstack
variantseparatedjoinedplain
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

KeyDoes
TabMoves to a drag handle
EnterPicks up, then drops
Arrow keysChoose where to drop
EscapeCancels 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.
Tested with axe, keyboard and screen reader roles