Options
All options are passed as the second argument to
Sorta11y.create(), and every one of them can be read or changed
at runtime with list.option(name, value).
Structure
Section titled “Structure”| Option | Default | What it does |
|---|---|---|
itemSelector | "> li" | Which children count as items. Changing it re-resolves the list. |
handle | null | Selector for a drag handle inside each item (a real <button> is recommended). Without one, the whole item is the grab target. |
dataIdAttr | "data-id" | Attribute that identifies items for toArray() and sort(). |
Interaction layers
Section titled “Interaction layers”| Option | Default | What it does |
|---|---|---|
keyboard | true | The keyboard grab / move / drop layer. See Keyboard. |
pointer | true | The pointer/touch drag layer. See Pointer & touch. |
clickToGrab | true | A pointer tap (no drag) picks up / drops. false = the pointer can only drag, which removes the WCAG 2.5.7 path. |
dragOnItem | false | With a handle: pointer drags/taps may start anywhere on the item. Keyboard and AT semantics stay on the handle. |
dragOnItemTouch | false | Widen the touch/pen drag surface to the whole item — only for short, non-scrolling lists. |
Accessibility
Section titled “Accessibility”| Option | Default | What it does |
|---|---|---|
applicationRole | true | Toggle role="application" on a wrapper only while an item is held, so NVDA/JAWS pass the arrow keys through. |
announceTotal | true | Include “of Y” in position announcements. |
liveness | "polite" | aria-live value for the announcement region. Applied immediately when changed. |
labels | null | Your own announcement strings — always wins over locale. |
locale | null | Pick a registered locale for the announcements. |
rtl | "auto" | Reserved — currently has no effect. See RTL. |
Presentation
Section titled “Presentation”| Option | Default | What it does |
|---|---|---|
animation | 150 | FLIP slide duration in ms; 0 disables it. |
easing | "cubic-bezier(0.2, 0, 0, 1)" | Easing for the slide. |
grabbedClass | null | Extra class(es) on the item while it is held (keyboard or tap pickup). |
draggingClass | null | Extra class(es) on the item during a pointer drag. |
Both class options accept a space-separated list and are additive — the
built-in .s11y-item--grabbed / .s11y-item--dragging hooks stay on. See
Styling.
Callbacks
Section titled “Callbacks”| Option | Fires |
|---|---|
onStart | When an item is picked up, by keyboard or pointer. |
onChange | After a committed reorder — only when the position actually changed. |
onEnd | After every drop and every cancel, whether or not anything moved. |
All three receive the same event object:
const evt = { item, // HTMLElement — the item that moved oldIndex, // number — 0-indexed position before newIndex, // number — 0-indexed position after (-1: removed, see below) order, // (string | null)[] — the data-ids afterwards (null: no id) source, // "keyboard" | "pointer"};Use onChange to persist. Use onEnd for teardown that has to run either way
(clearing a busy flag, say), and remember it fires on cancels too.
Timing
Section titled “Timing”The library finishes its own work before it calls you. After a keyboard or tap
pickup, onStart fires once focus has moved and the pickup has been announced;
after a drop, onChange and onEnd fire once focus is back on the grab target
and the grab has been cleaned up. So a callback that throws cannot leave the
list half-grabbed, and focus you move inside a callback stays where you put it.
A pointer drag moves no focus and is announced only when it ends.
source
Section titled “source”source names the input that performed the step:
onStartreports how the item was picked up.onChangeandonEndafter a drop report how it was dropped — a tap pickup followed by a keyboard drop gives"pointer", then"keyboard".onEndafter a cancel reports how the item was picked up, since a cancel (Esc, a press elsewhere, focus leaving the list) is no input of its own.
Mouse, touch and pen drags and taps are "pointer"; keys and a <button>
handle’s activation click are "keyboard". source describes the input path,
not the person: a screen reader’s activation arrives as a click in Firefox
("keyboard") but as a synthetic pointer tap in Chromium ("pointer"), so don’t
use it to detect assistive technology.
When the held item disappears
Section titled “When the held item disappears”If the app removes the held or dragged item and calls refresh(), the
interaction ends: onEnd fires with newIndex: -1, onChange does not fire,
and nothing is announced (the stale “Picked up…” text is cleared). See
refresh().
Declarative markup
Section titled “Declarative markup”Sorta11y.autoInit() enhances every element carrying [data-sorta11y]. It reads
three attributes from the markup:
| Attribute | Maps to |
|---|---|
data-handle | handle |
data-rtl | rtl (reserved, currently no effect) |
data-application-role | applicationRole (only "false" has an effect) |
<ul data-sorta11y data-handle=".drag-handle" aria-label="Reorder tasks"> …</ul>Changing options at runtime
Section titled “Changing options at runtime”option(name, value) applies changes immediately and does whatever re-wiring is
needed:
livenessupdates the live region’saria-livein place.labels/localere-resolve the label set and re-render the hidden instructions text.keyboard/pointerattach or detach their listeners, first cancelling a held item (keyboard) or a drag in progress (pointer), so the flag is never a lie.applicationRolecancels a live grab and re-syncs the container role.handle,itemSelector,dataIdAttr,dragOnItem,dragOnItemTouchtrigger arefresh()to re-resolve items and grab targets.- Everything else —
animation,easing,announceTotal,clickToGrab, the class options and the callbacks — is read when it is used, so a change applies from the next step. ChangegrabbedClass/draggingClassonly while nothing is held, or the old classes stay on the held item.
list.option("animation"); // readlist.option("animation", 0); // write