KQ-1488 · BRANCH/OUT

Branch Out

A menu that grows its options like branches: opening grows a short stem out of the trigger, then a branch per option draws along a curve whose bend you set, nearest the centre line first and staggered, and as each arrives a bud swells at its end and the option opens out of it on springs.snap. Hovering or focusing an option thickens and tints its branch and grows a leaf at its middle, and closing retracts everything in reverse on the exit ease. It is a real menu button: arrows move a roving focus, Home and End jump, letters type ahead, Enter or Space chooses and Escape closes and returns focus to the trigger.

KQ-1488 · BRANCH/OUT

menu closed · press add a block

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/branch-out

Props

items
{ id: string; label: string; icon?: ReactNode; hint?: string; disabled?: boolean }[]
default —
The options, top to bottom; disabled ones are aria-disabled and skipped by the arrow keys.
onSelect
(id: string) => void
default —
Called with the chosen option's id.
open / defaultOpen
boolean
default — / false
Whether the menu is open, controlled or uncontrolled.
onOpenChange
(open: boolean) => void
default —
Fires from the press, key or outside click that opened or closed it.
label
string
default "Add"
The trigger's accessible name and the menu's; also shown beside the trigger while closed.
icon
ReactNode
default a plus
The trigger's icon; it turns 45° on springs.snap while open.
side
"right" | "left"
default "right"
Which way the branches grow from the trigger.
spread
number
default 0.5
How wide the fan opens, 0 to 1: the options' spacing and the radius of the arc they sit on.
curve
number
default 0.6
How the branches bend, 0 to 1: straight twigs to S-shaped tendrils.
stagger
number
default 60
Time between one branch and the next as they grow, in ms; capped so the whole growth stays near 600ms.
color
string
default "var(--accent-bright)"
The trigger's fill and the colour a branch, bud and leaf take when their option is hot; any CSS colour.
branchColor
string
default "var(--hairline-strong)"
The branches and buds at rest; any CSS colour.
closeOnSelect
boolean
default true
Close the menu (and return focus to the trigger) after an option is chosen.
showLabel
boolean
default true
Show `label` beside the trigger while closed; it gives way as the branches grow.
size
"sm" | "md" | "lg"
default "md"
Max width (280, 320 or 360px), trigger and option height.
sound
boolean
default false
Play a pop as each option buds (rising in pitch), a tick as focus moves and a lower tick on choose and close; only in answer to a press or key.
disabled
boolean
default false
Disables the trigger.
className
string
default —
Classes for the root box, whose height follows the item count and spread.