navius

Sortable

Headless drag-to-reorder over a list of stable keys: pointer and touch dragging from the engine, plus a full APG grab-and-move keyboard model.

Research
Design
Build
Ship

Order: a, b, c, d

Features

  • The root owns an ordered List<string> of keys and re-renders into the new order; the consumer iterates the same list to render one item per key.
  • Pointer visuals (data-dragging on the dragged item, data-drop-target on the hovered slot) are painted by the engine straight onto the DOM, so a C# re-render never fights them.
  • The keyboard reducer (Space grabs, arrows move live, Space drops, Escape restores) announces each transition through a visually-hidden live region.
  • An optional Handle scopes pointer drag to a grip; a per-item Disabled row is skipped by roving navigation. Bind with @bind-Values and hook OnReorder(old, new).

Installation

Install the brain, or copy just this primitive in with the CLI.

Anatomy

Iterate the bound key list and render one item per key. A Handle is optional.

API Reference

NaviusSortable. Owns the key order, the keyboard grab/roving state and the drag engine. Renders a div with role=list plus a visually-hidden live region. Values is two-way bindable.

Prop Type Default
Values IReadOnlyList<string>? -
ValuesChanged EventCallback<IReadOnlyList<string>> -
DefaultValues IReadOnlyList<string>? -
Orientation SortableOrientation Vertical
Disabled bool false
OnReorder EventCallback<SortableReorderEventArgs> -
ChildContent RenderFragment? -
…attributes IDictionary<string, object>? -
Data attribute Values
[data-navius-sortable] Present on the list
[data-orientation] "vertical" | "horizontal" | "grid"
[data-disabled] Present when disabled
[data-dragging] Present while a drag or grab is active

NaviusSortableItem. One reorderable row: the drag target and the roving keyboard focus target. Value is the stable key. Renders a div with role=listitem.

Prop Type Default
Value string required
Label string? Value
Disabled bool false
ChildContent RenderFragment? -
…attributes IDictionary<string, object>? -
Data attribute Values
[data-navius-sortable-item] Present on every row
[data-navius-sortable-id] Mirrors Value
[data-dragging] Painted by the engine on the dragged item
[data-drop-target] Painted by the engine on the hovered slot
[data-keyboard-grabbed] Present while grabbed for keyboard reordering
[data-disabled] Present when the row or list is disabled

NaviusSortableItemHandle. An optional drag grip; its presence scopes pointer drag to the handle. aria-hidden (keyboard reordering acts on the whole item). Renders a span.

Prop Type Default
ChildContent RenderFragment? -
…attributes IDictionary<string, object>? -
Data attribute Values
[data-navius-sortable-handle] Present on the handle; scopes pointer drag to it

Orientation is a SortableOrientation (Vertical / Horizontal / Grid). OnReorder fires a SortableReorderEventArgs(OldIndex, NewIndex). Cross-list transfer is deliberately not supported (the engine reports indices for a single container).

Accessibility

Follows the APG "grab and move" pattern. Each row is a roving tab stop (aria-roledescription="sortable item"); grabbing sets aria-grabbed and data-keyboard-grabbed. Every grab, move, drop and cancel is announced through a polite live region.

Key Description
Space / Enter Grabs the focused item, or drops a grabbed item at its new position.
Arrow keys While grabbed, moves the item live; otherwise moves the roving focus.
Home / End Moves the item (or focus) to the first / last position.
Escape Cancels a grab and restores the original order.