trieur.

Keyboard and gestures

The keyboard is not the accessible fallback here: it is the fast path. A mouse sorts one card at a time at the speed of an arm; a hand on a s d f sorts a hundred at the speed of reading. Everything the pointer can do has a key, and the deck never grabs a key it does not use.

Sorting

a s d …file into that zone β€” the letters follow the zone order
↡accept what the model suggests (nothing happens when it suggests nothing)
spaceskip: the card goes to the back of the pile
⌫undo, and unlearn the filing that undo removes
escleave fullscreen, or drop the multi-zone stack

The keys come from keys, a plain string handed out in order:

new Deck(el, { zones, keys: 'asdfghjkl' });   // the default
new Deck(el, { zones, keys: '123456789' });   // a numeric pad

A zone can also name its own: { id: 'dev', key: 'v' }. What matters is that the key belongs to the position, not to the folder β€” the muscle memory is spatial, and a zone that keeps its spot keeps its key even when what it holds changes.

Several zones at once

Only when multi is on. See Several zones at once.

hold ⇧ + a s …stack while held; releasing ⇧ files them all
tap ⇧ alonelatch the mode β€” tap again to leave, or file with ↡
↡file the stack
escdrop the stack, file nothing

A bare tap on Shift is a mode toggle; a Shift used as a modifier is not. The deck tells them apart by remembering whether any key was pressed while it was down, which is the only way a single physical key can be both without one meaning stealing the other.

Focus, and doing without it

The stage is a role="application" with tabindex="0": it takes focus, and the keys work while it has it. deck.focus() puts it there.

But a sorter you must click before the keyboard works hides its fastest path behind a step nobody is told about β€” so when exactly one deck is on screen (half of it visible, no other deck alongside), it also answers keys pressed anywhere on the page. Two decks fall back to focus, because the page cannot know which one you meant, and typing in a field always wins:

new Deck(el, { keyboard: 'auto' });   // the default
new Deck(el, { keyboard: 'focus' });  // only when the stage has focus
new Deck(el, { keyboard: false });    // no shortcuts at all

Fullscreen (esc to leave) also locks the page scroll behind the modal, which is why it is a modal and not the Fullscreen API: the API cannot be opened without a user gesture, and half the ways into fullscreen here are not gestures.

The pointer

drag past thresholdfile into the region under the card
a throwfile where the throw lands β€” the flick plugin
double tapaccept the suggestion, the touch equivalent of ↡
press and hold a cardopen the multi-zone stack, then sweep across zones
press and hold the stagesummon the round pad under the thumb (multiPad: 'dynamic')
tap a zonefile into it β€” no drag at all, on by default (tapZones)
hold a cardopen the multi-zone stack, then sweep

The stage is carved into regions and the drop aims at the region under the pointer, not at an approximate angle β€” what you see is what you hit. Where there is no carving (segments: false), the direction of the drag decides.

On a phone

A sorting swipe and a page scroll are the same gesture. Rather than fight the page for it, an inline deck lets the page win: vertical swipes scroll, and the deck shows a play button. Press it β€” or the card, or Expand β€” and the deck takes the gesture; Stop, beside Expand, hands the swipe back. Set touchPreview: false where the deck already is the screen (an app view, a phone-sized popup) and it takes the gesture inline from the start.

new Deck(el, { touchPreview: false });
deck.play(true);   // or take it yourself, whenever you like

The demos on this site all pass touchPreview: false, so that a phone can try the gestures without a step in the way. That is the right setting for a page whose whole subject is the deck, and the wrong one for a page where the deck is a section among others.

Showing them

The site renders these with a Kbd component (Lucide glyphs for the modifiers, a keycap for the rest) and a Shortcuts sheet the demos open from a button in the deck’s own bar. Nothing of that ships in the library β€” but the stylesheet does style .tr kbd, so a host that prints a keycap of its own gets the same one the zones use.