Getting StartedComponentsDesign TokensThemingTheme SynthesizerFrameworksAccessibilityUtilitiesServer RenderingBrowser SupportContributingChangelog App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip
ARC UI ARC Radiant Components
v3.2 Docs Components Tokens Synthesizer
Getting StartedFrameworksServer Rendering Design TokensThemingTheme SynthesizerTypographyUtilities All ComponentsAccessibilityBrowser SupportChangelogContributingStats App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip

Sortable List

Drag-and-drop reorderable list with grip handles, keyboard reordering support, and visual insertion indicators.

Components Sortable List
input interactive
<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

disabled boolean false
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