KQ-1135 · TOOL/DOCK

Tool Dock

The tool rail of a drawing canvas and the canvas it drives: the active tool sits on an indicator that slides to each new choice on the snap spring with a tick pitched up the rail, and a tool with variants unfolds its options beside it with a swish — a panel revealed from the rail's edge whose entries step out on snap, or a drawer that glides open inside the rail on glide. Single-letter shortcuts switch tools while focus or the pointer is on the dock (never while typing), the key of the active tool cycles its variants, and the canvas shows the tool's own cursor, drawn 1:1 under the pointer and popping to each new shape on snap. The rail is a toolbar of pressed buttons with one tab stop: arrows move, Space or Enter choose, and the arrow toward the options opens them as a menu of radio items with focus inside.

KQ-1135 · TOOL/DOCK

tool Move · key v

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/tool-dock

Props

tools
{ id: string; label: string; glyph?: ToolDockGlyph; icon?: ReactNode; cursor?: ReactNode; key?: string; variants?: { id: string; label: string; glyph?: ToolDockGlyph; icon?: ReactNode; cursor?: ReactNode; key?: string }[] }[]
default —
The rail, top to bottom (or left to right). A tool with variants shows the last one used; key is a single letter. Built-in glyphs, each with a cursor: move, hand, frame, rect, ellipse, line, polygon, pen, pencil, brush, text, eraser, comment.
value / defaultValue
string
default the first tool (its first variant)
The active tool's id, or the active variant's id for a tool that has them.
onValueChange
(id: string) => void
default —
Fires from the press, key or shortcut that changed the tool.
orientation
"vertical" | "horizontal"
default "vertical"
A rail down the canvas's left, or centred along its foot.
shortcuts
boolean
default true
Single-letter keys switch tools and each button shows its letter (and names it in aria-keyshortcuts). Keys act while focus is in the dock, or while the pointer is over it and nothing else has focus; never in a field or with Ctrl, Cmd or Alt, and a handled key is claimed.
flyout
"side" | "tray"
default "side"
A tool's options float in a panel beside the rail (over the canvas, placed inside the component's box), or open as a drawer inside the rail that pushes the tools after it.
labels
boolean
default false
A label under each icon; the rail widens to fit. Off, the name is still each button's accessible name.
children
ReactNode
default —
What is on the canvas, laid out inside it (position it absolutely to fill).
canvasHeight
number
default 400
The canvas's height in px.
label
string
default "Tools"
The rail's accessible name.
canvasLabel
string
default "Canvas"
The canvas's accessible name.
sound
boolean
default false
A tick on every tool or variant change, pitched up the rail on a pentatonic scale and panned to the button; a swish as options unfold and a lower, quieter one as they fold. Nothing plays, and no audio context exists, unless this is on.
disabled
boolean
default false
Dims the dock, disables its buttons and stops the shortcuts; the system cursor comes back over the canvas.
className
string
default —
Merged onto the wrapper that holds the rail and the canvas.