Sortable List
Drag-and-drop reorderable list with grip handles, keyboard reordering support, and visual insertion indicators.
<arc-sortable-list> Overview
>
SortableList enables users to reorder a set of items through intuitive drag-and-drop or keyboard interaction. 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 subtle borders. When dragging, the source item fades to 50% opacity with an elevated shadow, while a blue insertion line appears above or below the target position to indicate where the item will land.
Beyond mouse-based reordering, SortableList provides a complete 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 ensures that screen reader users and keyboard-only users have full control over item ordering.
The component fires a single `arc-change` event after every reorder, providing the new order as an array of original indices in the event detail. This makes it straightforward to sync the visual order back to your data model without tracking individual move operations.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
- Full 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
Design tokens
Components
Patterns
Utilities
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 Table A data-driven table component that renders rows from a JavaScript array. Declarative column definitions via `arc-column` children control which fields appear, their headers, widths, and sort behavior. Built-in support for column sorting, row selection with checkboxes, and an empty-state fallback.
- Tree View Hierarchical tree structure with expandable/collapsible nodes, selection tracking, keyboard navigation, and indentation guide lines.