KQ-1107 · JIGGLE/MODE
Jiggle Mode
A grid of shortcut tiles with an edit mode entered by holding any one: the held tile sinks for the hold, pops back on the snap spring, and edit mode ripples outward from it, each tile starting to rock out of phase with its neighbours on a compositor animation and gaining a badge that pops in on snap. In edit mode a tile drags 1:1, lifts on flick, rubber-bands at the edges and parts the others on glide with a tick per slot, and a flick lands in the slot it was heading for; a remove badge takes a tile away with a pop, a check badge marks it for Done, and Undo brings the last removal back. Done or Escape settles every tile from wherever it is in its swing back to upright on snap; on the keyboard a held Space enters edit mode, Space picks a tile up, arrows move it and Delete does the badge's job.
Hold a tile to edit
Press to open. Hold for a moment, with a finger or with Space, to edit.
8 shortcuts · hold one to edit
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/jiggle-mode
Props
- items
- { id: string; label: string; glyph?: ReactNode; tone?: "cobalt" | "signal" | "success" | "warn" | "danger" | "ink" }[]
- default —
- Every tile that can appear. The label is shown under the tile and is its accessible name; the tile is a wash of its tone and the glyph is drawn in it.
- value / defaultValue
- string[]
- default every item id, in order
- The ids shown, in order.
- onValueChange
- (ids: string[]) => void
- default —
- Fires with the new order once per drop, removal, Done in check mode, or Undo.
- editing / defaultEditing
- boolean
- default false
- Whether the grid is in edit mode.
- onEditingChange
- (editing: boolean) => void
- default —
- Fires when a hold enters edit mode, and when Done or Escape leaves it.
- onOpen
- (id: string) => void
- default —
- A tile pressed outside edit mode: a tap, or a quick Space or Enter.
- label
- string
- default "Shortcuts"
- The grid's accessible name.
- columns
- number
- default 4
- Tiles per row, 2 to 6. Each column is 68px; four fit a 320px phone column.
- wiggle
- number
- default 2
- How far each tile rocks either side in edit mode, in degrees.
- frequency
- number
- default 3.5
- How fast the tiles rock, in cycles per second; each tile varies it by a few percent so neighbours drift apart.
- badge
- "remove" | "check"
- default "remove"
- A minus badge that removes a tile at once, or a check badge that marks it (the tile dims) so Done removes every marked tile together.
- delay
- number
- default 500
- How long a hold takes to enter edit mode, in ms, for a finger or a held Space or Enter.
- sound
- boolean
- default false
- Play the wobble as edit mode starts, a tick per slot and a pop per removal. Nothing plays, and no audio context exists, unless this is on.
- disabled
- boolean
- default false
- Dims the tiles and blocks presses, holds and drags; while disabled the grid is shown out of edit mode.
- className
- string
- default —
- Merged onto the wrapper that holds the grid and its toolbar.
| Prop | Type | Default | Description |
|---|---|---|---|
| items | { id: string; label: string; glyph?: ReactNode; tone?: "cobalt" | "signal" | "success" | "warn" | "danger" | "ink" }[] | — | Every tile that can appear. The label is shown under the tile and is its accessible name; the tile is a wash of its tone and the glyph is drawn in it. |
| value / defaultValue | string[] | every item id, in order | The ids shown, in order. |
| onValueChange | (ids: string[]) => void | — | Fires with the new order once per drop, removal, Done in check mode, or Undo. |
| editing / defaultEditing | boolean | false | Whether the grid is in edit mode. |
| onEditingChange | (editing: boolean) => void | — | Fires when a hold enters edit mode, and when Done or Escape leaves it. |
| onOpen | (id: string) => void | — | A tile pressed outside edit mode: a tap, or a quick Space or Enter. |
| label | string | "Shortcuts" | The grid's accessible name. |
| columns | number | 4 | Tiles per row, 2 to 6. Each column is 68px; four fit a 320px phone column. |
| wiggle | number | 2 | How far each tile rocks either side in edit mode, in degrees. |
| frequency | number | 3.5 | How fast the tiles rock, in cycles per second; each tile varies it by a few percent so neighbours drift apart. |
| badge | "remove" | "check" | "remove" | A minus badge that removes a tile at once, or a check badge that marks it (the tile dims) so Done removes every marked tile together. |
| delay | number | 500 | How long a hold takes to enter edit mode, in ms, for a finger or a held Space or Enter. |
| sound | boolean | false | Play the wobble as edit mode starts, a tick per slot and a pop per removal. Nothing plays, and no audio context exists, unless this is on. |
| disabled | boolean | false | Dims the tiles and blocks presses, holds and drags; while disabled the grid is shown out of edit mode. |
| className | string | — | Merged onto the wrapper that holds the grid and its toolbar. |