Sortable List
Drag-and-drop reorderable list with grip handles, keyboard reordering support, and visual insertion indicators.
<arc-sortable-list>Overview
SortableList lets users reorder a set of items with drag-and-drop or the keyboard. Each item renders with a six-dot grip handle on the left and the item content on the right, wrapped in a card-like container with a thin border. When dragging, the source item fades to 50% opacity with a raised shadow, while a blue insertion line appears above or below the target position to indicate where the item will land.
SortableList also has a full keyboard workflow. Users can press Space to select an item (highlighted with a blue border), then Enter to enter move mode (elevated with a stronger blue glow), and finally Arrow Up/Down to shift the item through the list. Pressing Space or Enter again confirms the placement, while Escape cancels the operation. This two-phase keyboard model gives screen reader users and keyboard-only users full control over item ordering.
The component fires a single arc-change event after every reorder, with the new order as an array of original indices in the event detail, so you can sync the visual order back to your data model without tracking individual moves.
Guidelines
When to use
- Wrap plain elements (e.g. `<div>`) as direct children: the component reads their `textContent` for display
- Listen for `arc-change` to persist the new order back to your data store
- Use SortableList for short to medium lists (under ~50 items) where manual ordering matters
- Provide clear, distinguishable text content for each item so users can identify what they are reordering
- Test keyboard reordering to ensure your application handles the order array correctly
When not to use
- Do not nest interactive elements (buttons, links) inside list items: they conflict with drag handles and keyboard interaction
- Do not use SortableList for very long lists where search or filtering would be more efficient than manual reordering
- Do not rely solely on the visual grip dots to communicate draggability; ensure items have descriptive labels for screen readers
- Do not place multiple Sortable Lists adjacent without clear visual separation between them
- Avoid using SortableList for single-item lists: there is nothing to reorder
Features
- Drag-and-drop reordering with HTML5 Drag and Drop API and visual insertion indicators
- Six-dot grip handle icon rendered for each item as a drag affordance
- Keyboard reordering: Space to select, Enter to move, Arrow keys to shift, Escape to cancel
- Blue border highlight for keyboard-selected items and elevated glow for items being moved
- Dragged items fade to 50% opacity with an elevated box shadow for clear visual feedback
- Fires `arc-change` with `detail.order` containing the new index mapping after every reorder
- ARIA attributes including `role="listbox"`, `role="option"`, and `aria-grabbed` for accessibility
- Disabled state at 40% opacity with pointer events blocked
Preview
Usage
This component requires JavaScript. No pure HTML/CSS version is available. Use the Web Component directly or a framework wrapper.
<arc-sortable-list>
<div>First item</div>
<div>Second item</div>
<div>Third item</div>
</arc-sortable-list>
<script>
document.querySelector('arc-sortable-list')
.addEventListener('arc-change', e => {
console.log('New order:', e.detail.order);
});
</script>import { SortableList } from '@arclux/arc-ui-react';
export default function Example() {
return (
<SortableList onArcChange={(e) => console.log(e.detail.order)}>
<div>First item</div>
<div>Second item</div>
<div>Third item</div>
</SortableList>
);
}<script setup>
import { SortableList } from '@arclux/arc-ui-vue';
function onReorder(e) {
console.log('New order:', e.detail.order);
}
</script>
<template>
<SortableList @arc-change="onReorder">
<div>First item</div>
<div>Second item</div>
<div>Third item</div>
</SortableList>
</template><script>
import { SortableList } from '@arclux/arc-ui-svelte';
</script>
<SortableList on:arc-change={(e) => console.log(e.detail.order)}>
<div>First item</div>
<div>Second item</div>
<div>Third item</div>
</SortableList>import { Component } from '@angular/core';
import { SortableList } from '@arclux/arc-ui-angular';
@Component({
imports: [SortableList],
template: `
<arc-sortable-list (arc-change)="onReorder($event)">
<div>First item</div>
<div>Second item</div>
<div>Third item</div>
</arc-sortable-list>
`,
})
export class MyComponent {
onReorder(e: CustomEvent) {
console.log('New order:', e.detail.order);
}
}import { SortableList } from '@arclux/arc-ui-solid';
export default function Example() {
return (
<SortableList onArcChange={(e) => console.log(e.detail.order)}>
<div>First item</div>
<div>Second item</div>
<div>Third item</div>
</SortableList>
);
}import { SortableList } from '@arclux/arc-ui-preact';
export default function Example() {
return (
<SortableList onArcChange={(e) => console.log(e.detail.order)}>
<div>First item</div>
<div>Second item</div>
<div>Third item</div>
</SortableList>
);
}API
disabledbooleanfalse- Disables all interaction, reducing opacity to 40% and blocking pointer events.
Events
arc-change- Fired when items are reordered, with updated order in detail
See Also
- Data GridA spreadsheet-grade grid for working with tabular data: inline cell editing, multi-column sorting, pinned columns, row selection, and virtualized rendering. Columns are defined as a JavaScript array, and the grid implements the full WAI-ARIA grid keyboard pattern with a single tab stop.
- Tree ViewHierarchical tree structure with expandable/collapsible nodes, selection tracking, keyboard navigation, and indentation guide lines.