Overlays & feedback
Bottom dock
A floating action bar that rises from the bottom when you have a selection — a dark, focused dock with the selection count, a live work timer, the batch actions you reach for most, and a one-tap “set aside” to the tray. It stays out of the way until there’s something to act on.
npx shadcn@latest add @orbit/bottom-dockOverview
Live — tick rows to grow the selection, start the timer, open Status / Assign / Priority, set tasks aside, or clear with the × (or Esc while the demo has focus).
Capabilities
It combines a selection toolbar with a focus timer, so the thing you’re doing right now always has a home at the bottom of the screen.
Composition
Every segment is optional: hide the timer, pass plain actions without menus, or drop set-aside — the dock only renders the pieces you wire up, and hides entirely at count 0.
Props
The dock positions absolutely inside the nearest relative container by default, which keeps docs demos framed. In a real app pass fixed so it floats bottom-center over every view.
| Prop | Type | Default | Description |
|---|---|---|---|
| count | number | — | Selection size. The dock renders nothing while 0. |
| label | string | "selected" | Word after the count badge. |
| actions | BottomDockAction[] | [] | Batch actions: { id, label, icon?, items?, menuTitle?, onSelect? }. With items the action opens an upward menu (each item: { id, label, color?, onSelect? }); without, it fires onSelect. |
| onActionSelect | (actionId, itemId?) => void | — | Fired for any resolved action, alongside the per-item handlers. |
| showTimer | boolean | true | Show the work-timer segment. |
| timerRunning / defaultTimerRunning | boolean | false | Controlled / uncontrolled timer state; onTimerRunningChange reports toggles. |
| elapsed / defaultElapsed | number | 0 | Elapsed seconds. Leave elapsed undefined and the dock ticks on its own while running. |
| onSetAside | () => void | — | Tray button clicked. The button hides when omitted. |
| onClear | () => void | — | × clicked or Escape pressed — clear the selection. The × hides when omitted. |
| clearOnEscape | boolean | true | Listen for Escape while visible (open menus consume Escape first). |
| fixed | boolean | false | position: fixed for a real app dock instead of absolute. |
| …rest | HTMLAttributes | — | Forwarded to the root <div> (role=toolbar), including ref. |
Usage
A dock is for the active selection or task. For row-level options use a context menu; for a persistent bulk toolbar tied to a table, the Bulk Actions toolbar is the lighter choice.
Center it, clear of content
Float the dock bottom-center with breathing room so it reads as separate from the list it acts on.
Crowd it with every action
Three or four high-frequency actions plus a timer. Push the rest into an overflow so the dock stays scannable.
Always offer an exit
A visible × and the Esc key both clear the selection, so the dock never feels like a trap.
Block the bottom row
Leave room beneath, or lift the content, so the dock doesn’t cover the last items people are trying to reach.
Keyboard & accessibility
The dock is a labelled toolbar of real buttons: the timer toggle carries aria-pressed, menus build on Base UI Menu (roving focus, ARIA menu roles, Escape), and the selection count is announced through the toolbar's accessible name.