> man sorta11y

Sorting,
out loud.

A vanilla-JS sortable list that works with a mouse, a keyboard, and a screen reader — out of the box. Every move is spoken. No framework, no dependencies.

$ npm i sorta11y@alpha▍ try the demos ↓

v0.1.0-alpha — pre-release: install via the alpha tag, or grab src/sorta11y.js from GitHub.

Playground

// PLAYGROUND — FLIP THE SETTINGS, WATCH THE CODE

every move is spoken through the live region

Basic list

Sorta11y.create()

Plain items, no handle — the whole item is the grab target. Toggle animation, add a grabbedClass / draggingClass state hook, or turn off clickToGrab so the pointer can only drag — a tap no longer picks up.

Options

    ▸ spoken: —

    // ARIA-LIVE · POLITE

    Drag handle

    handle: "…"

    A real <button> braille handle (⠿) becomes the grab target — the recommended path for full screen-reader support. Turn it off and the whole item becomes the grab target instead. Or keep the handle and add dragOnItem: pointer drags and taps may then start anywhere on the item, while keyboard and screen readers keep working through the handle. On touch and pen, the body stays tap-only so long lists still scroll — add dragOnItemTouch to make the whole item a finger/stylus drag surface too (best for short, unscrollable lists).

    Handle

      ▸ spoken: —

      // ARIA-LIVE · POLITE

      From <select multiple>

      Sorta11y.fromSelect()

      Point fromSelect at a <select multiple> and it builds an accessible sortable list, hides the select but keeps it submittable, and mirrors the new order back. Choose which side the handle sits on with handlePosition.

      Handle side
      Handle

      ▸ spoken: —

      // ARIA-LIVE · POLITE

      Announcements & i18n

      labels / locale

      Every move is spoken through one polite live region. Switch the language and the same interactions announce in English or German — the real locale option, swapped live.

      TAB focus · SPACE grab · ↑↓ move · HOME/END jump · SPACE drop · ESC cancel

        ▸ spoken: —

        // ARIA-LIVE · POLITE

        // WHY

        One list, done well — for everyone.

        Popular drag-and-drop libraries were built mouse-first; a keyboard or screen-reader user was often left stranded. sorta11y treats those paths as first-class — the same grab / move / drop model, spoken every step of the way.

        It grew out of a real-world form integration at ConfTool, where those paths were exercised hands-on with a screen reader rather than against a checklist.

        Capability Typical drag lib sorta11y
        Reorder with the keyboard partial yes
        Screen-reader announcements no yes
        Single-pointer (tap) path · WCAG 2.5.7 no yes
        Zero runtime dependencies partial yes
        No build step no yes
        i18n announcement labels no yes

        // KEYBOARD MODEL

        Grab · move · drop.

        Tab / Shift+Tab move focus between items
        Space pick up the focused item, or drop it
        Enter same as Space on a <button> handle (its native activation) — plain items stay Enter-inert
        ↑ / ↓ move the held item one position
        Home / End jump the held item to start / end
        Esc cancel and restore the original order

        // QUICKSTART

        Progressive enhancement.

        The server renders a plain list; sorta11y enhances it in place. No build step — one script, one stylesheet, and go.

        app.js
        index.html

        Label precedence, lowest to highest: built-in English → setDefaultLabels → { locale } → { labels }.

        What you get

        Zero deps · no build

        One hand-written file. No framework, no bundler, no runtime deps.

        Grab · move · drop

        The same model for mouse, touch, and keyboard.

        One polite live region

        Every reorder is spoken — drops and cancels alike.

        Focus stays put

        Focus stays on the moved item — the same element — after keyboard, pointer and programmatic reorders, so it never falls to <body>.

        Reduced-motion aware

        Respects prefers-reduced-motion — instant, no slide.

        i18n locales

        Swap announcement languages, or supply your own labels.