Installation
Theme
Mode

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-dock

Overview

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.

Appears on selection
Zero chrome at rest. The moment you select something the dock rises with a live count; clearing it slides it away.
Built-in timer
Start and pause a work timer right in the dock — the running clock follows you while you act on the selection.
Quick batch actions
Status, assignee and priority open upward-anchored menus and apply to everything selected, with a confirming toast.
Set aside
Park the selection in the Task Tray with one tap — a place to hold work without losing it or finishing it.

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.

Selection:The dock hides itself at 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.

PropTypeDefaultDescription
countnumberSelection size. The dock renders nothing while 0.
labelstring"selected"Word after the count badge.
actionsBottomDockAction[][]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?) => voidFired for any resolved action, alongside the per-item handlers.
showTimerbooleantrueShow the work-timer segment.
timerRunning / defaultTimerRunningbooleanfalseControlled / uncontrolled timer state; onTimerRunningChange reports toggles.
elapsed / defaultElapsednumber0Elapsed seconds. Leave elapsed undefined and the dock ticks on its own while running.
onSetAside() => voidTray button clicked. The button hides when omitted.
onClear() => void× clicked or Escape pressed — clear the selection. The × hides when omitted.
clearOnEscapebooleantrueListen for Escape while visible (open menus consume Escape first).
fixedbooleanfalseposition: fixed for a real app dock instead of absolute.
…restHTMLAttributesForwarded 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.

Do

Center it, clear of content

Float the dock bottom-center with breathing room so it reads as separate from the list it acts on.

Don’t

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.

Do

Always offer an exit

A visible × and the Esc key both clear the selection, so the dock never feels like a trap.

Don’t

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.

TabMoves through timer, actions, set aside, and ×
Enter / SpaceActivates the focused control or opens its menu
↑ ↓Move through an open menu's items
EscCloses an open menu, then clears the selection