Skip to content

SortableList

Rows that editors reorder by dragging, like list fields.

HeroAutumn collection
ProductsNew in linen
QuoteFrom the workshop
SortableList.tsx
import {
  Badge,
  type DragMoveEvent,
  SortableList,
  SortableListHandle,
  SortableListItem,
  SortableListItemDescription,
  SortableListItemHeader,
  SortableListItemTitle
} from 'alinea/components'
import {useState} from 'react'

const initial = [
  {id: 'hero', type: 'Hero', label: 'Autumn collection'},
  {id: 'products', type: 'Products', label: 'New in linen'},
  {id: 'quote', type: 'Quote', label: 'From the workshop'}
]

export function SortableListExample() {
  const [sections, setSections] = useState(initial)
  function reorder({keys, target}: DragMoveEvent) {
    const moved = sections.filter(section => keys.has(section.id))
    const rest = sections.filter(section => !keys.has(section.id))
    const index = rest.findIndex(section => section.id === target.key)
    rest.splice(target.position === 'before' ? index : index + 1, 0, ...moved)
    setSections(rest)
  }
  return (
    <SortableList
      aria-label="Sections"
      onReorder={reorder}
      style={{width: 400}}
    >
      {sections.map(section => (
        <SortableListItem key={section.id} id={section.id} role="listitem">
          <SortableListItemHeader>
            <SortableListHandle aria-label={`Drag ${section.label}`} />
            <SortableListItemTitle>
              <Badge size="sm">{section.type}</Badge>
              <SortableListItemDescription>
                {section.label}
              </SortableListItemDescription>
            </SortableListItemTitle>
          </SortableListItemHeader>
        </SortableListItem>
      ))}
    </SortableList>
  )
}

Props

<SortableList>

PropTypeDefaultDescription
onReorder(event: DragMoveEvent) => voidDefault –Enables reordering: items with an id can be dragged by their SortableListHandle, with a pointer or with the keyboard (Enter on the handle, Tab to an item, Enter to drop). Called with the key of the dragged item and the item it was dropped before or after. Items only drop within the list they were dragged from.
dragTypestringDefault –Mime type the dragged items carry, defaults to alinea/sortable-list-item

Also accepts every prop of Surface.

<SortableListItem>

PropTypeDefaultDescription
idKeyDefault –Identifies the item within its list. Items with an id can be dragged when the list has onReorder. The id is not rendered as a DOM id.
dragPreviewReactNodeDefault –Rendered under the pointer while dragging, eg. a SortableListDragPreview

Also accepts every prop of a <div> element.

<SortableListItemHeader>

Top bar of an item, holds its handle, title and actions

Accepts every prop of a <div> element.

<SortableListHandle>

Drags its SortableListItem when the list has onReorder. Focusable in that case: press Enter to start a keyboard drag. Place it in the SortableListItemHeader, it shows while the header is hovered or focused.

Accepts every prop of a <span> element.

<SortableListItemTitle>

Row of the toggle, badges and description of an item, fills the header

Accepts every prop of a <div> element.

<SortableListItemDescription>

Muted, truncated text next to the badges of an item, eg. its label

Accepts every prop of a <span> element.

<SortableListItemActions>

Accepts every prop of a <div> element.

<SortableListItemToggle>

Folds the content of an item

PropTypeDefaultDescription
expanded*booleanDefault –Whether the item content is shown, rotates the fold icon

Also accepts every prop of Button.

<SortableListItemContent>

The fields of an expanded item

Accepts every prop of a <div> element.

<SortableListItemFooter>

A summary under the header, eg. of a folded item

Accepts every prop of a <div> element.

<SortableListItemSettings>

A group of settings or actions in the popover of an item

PropTypeDefaultDescription
variant'default' | 'actions'Default 'default'actions removes the padding around a group of ghost buttons

Also accepts every prop of a <div> element.

<SortableListDragPreview>

Card shown under the pointer while dragging an item

PropTypeDefaultDescription
iconIconTypeDefault –
label*ReactNodeDefault –

Also accepts every prop of a <div> element.

<SortableListAdd>

Last row of the list holding the buttons that add items

Accepts every prop of a <div> element.