OverflowCluster
A row of actions that moves its lowest-priority items into a "More" menu instead of wrapping, overlapping or shrinking.
import { OverflowCluster } from "@butteryui/core";Demo
Last tool: None yet
When to use it
Use it for
- Toolbars, header actions and nav bars that have to fit from 390px phones to wide desktops
Not for
- Rows that may wrap, such as tags or chips: use Inline wrap
- Content that should scroll horizontally: use a scroll container
Examples
Header actions
A header's actions, which fold into a More menu as the header narrows, Help first.
No changes yet
Sizes
The More button at each size, matching the items beside it, in rows too narrow for all six actions.
sm, 28px
control, 34px
button, 36px
Last action: Nothing yet
Text toolbar
Photo tools that keep their full labels and fold into the More menu from the end when the row runs out of room.
Last tool: None yet
Variants and states
Collapsing by priority
The same six actions at three widths. Help goes first, then Share and Download; Undo and Redo stay longest.
Wide, 400px
Medium, 160px
Narrow, 128px
Props
OverflowCluster
| Prop | Type | Default | Description |
|---|---|---|---|
moreLabel | string | "More" | Accessible name of the "More" button. Defaults to "More". |
justify | "start" | "end" | "start" | Where the items sit in the space the cluster fills. Defaults to "start". |
size | "sm" | "control" | "button" | Height of the "More" button, to match the items: "sm" (28), "control" (34) or "button" (36, the
default). Compact density shortens them like any control. | |
menu | ReactNode | Your own items for the "More" menu, which then always shows, such as every choice with actions on them. Without it, the menu lists the items that don't fit and shows only when something doesn't. | |
gap | SpaceValue | Space between children. |
It also takes ComponentPropsWithRef<"div">.
OverflowCluster.Item
| Prop | Type | Default | Description |
|---|---|---|---|
priority | number | 0 | Higher stays visible longer. Among equal priorities, later items move into the menu first. Defaults to 0. |
menuItemrequired | OverflowMenuItem | The item's entry in the "More" menu once it no longer fits. | |
children | ReactNode | What the row shows while the item fits, such as a button. |
It also takes Omit<ComponentPropsWithRef<"div">, "hidden">.
OverflowMenuItem
How a cluster item appears in the "More" menu once it no longer fits.
| Field | Type | Default | Description |
|---|---|---|---|
labelrequired | string | The menu item's text, usually the item's own label or tooltip. | |
onSelectrequired | () => void | Runs when the menu item is chosen; usually the item's own action. | |
icon | ComponentType<IconComponentProps> | Icon before the label, such as the icon the item shows in the row. | |
disabled | boolean | false | Shows the menu item but stops it being chosen. Defaults to false. |
shortcut | Shortcut | The item's keyboard shortcut, shown at the menu item's end, as the item shows it in the row. | |
dot | boolean | Draws the accent dot the item shows in the row for something new; the menu item's name says so too. | |
dotLabel | string | "new" | What the dot adds to the menu item's name. Defaults to "new". |
selected | boolean | For items that are choices among each other, such as tabs: whether this one is chosen. The menu lists items that say either way as radio items, the chosen one checked. |
Accessibility
Hidden items leave the tab order and the accessibility tree; their actions stay reachable through the More button, a menu button with arrow-key navigation, Enter to choose and Escape to close. Items that say whether they're chosen are listed as radio items, the others as menu items with their icons, shortcuts and dots; the More button shows a dot, and says so in its name, while a folded item has one.
| Keys | What they do |
|---|---|
| Enter, Space or Down arrow | Opens the More menu from its button, with focus on the first item |
| Up and Down arrows | Moves between the menu's items |
| Home and End | Moves to the first or the last item |
| A letter | Moves to the next item that starts with it |
| Enter or Space | Chooses the item in focus, which runs its onSelect, and closes the menu |
| Escape | Closes the menu and puts focus back on the More button |
Motion
It appears with a `Presence` preset and leaves faster than it came, in about 60% of the time.
With reduced motion: The More button still shrinks to 97% while it's pressed, but at once instead of easing, and its menu fades in and out over 100ms without growing from the button; with entrance="instant" the menu shows and goes at once either way.
Layout
It fills the space its parent gives it and keeps its items on one row at their own size, never wrapping, overlapping or shrinking them: what doesn't fit moves into the More menu, lowest priority first, and comes back as the row grows. The More button is a circle as tall as its size, --bt-h-sm (28px), --bt-h-control (34px) or --bt-h-button (36px, the default), and that circle is its hit area.