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) |
| space | skip: the card goes to the back of the pile |
| β« | undo, and unlearn the filing that undo removes |
| esc | leave 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 β§ alone | latch the mode β tap again to leave, or file with β΅ |
| β΅ | file the stack |
| esc | drop 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 threshold | file into the region under the card |
| a throw | file where the throw lands β the flick plugin |
| double tap | accept the suggestion, the touch equivalent of β΅ |
| press and hold a card | open the multi-zone stack, then sweep across zones |
| press and hold the stage | summon the round pad under the thumb (multiPad: 'dynamic') |
| tap a zone | file into it β no drag at all, on by default (tapZones) |
| hold a card | open 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.