Skip to content
buttery

v1.0.0

Source on GitHub

Version 1.0.0

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.

Spring launch

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

PropTypeDefaultDescription
moreLabelstring"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.
menuReactNodeYour 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.
gapSpaceValueSpace between children.

It also takes ComponentPropsWithRef<"div">.

OverflowCluster.Item

PropTypeDefaultDescription
prioritynumber0Higher stays visible longer. Among equal priorities, later items move into the menu first. Defaults to 0.
menuItem

required

OverflowMenuItemThe item's entry in the "More" menu once it no longer fits.
childrenReactNodeWhat 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.

FieldTypeDefaultDescription
label

required

stringThe menu item's text, usually the item's own label or tooltip.
onSelect

required

() => voidRuns when the menu item is chosen; usually the item's own action.
iconComponentType<IconComponentProps>Icon before the label, such as the icon the item shows in the row.
disabledbooleanfalseShows the menu item but stops it being chosen. Defaults to false.
shortcutShortcutThe item's keyboard shortcut, shown at the menu item's end, as the item shows it in the row.
dotbooleanDraws the accent dot the item shows in the row for something new; the menu item's name says so too.
dotLabelstring"new"What the dot adds to the menu item's name. Defaults to "new".
selectedbooleanFor 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.

KeysWhat they do
Enter, Space or Down arrowOpens the More menu from its button, with focus on the first item
Up and Down arrowsMoves between the menu's items
Home and EndMoves to the first or the last item
A letterMoves to the next item that starts with it
Enter or SpaceChooses the item in focus, which runs its onSelect, and closes the menu
EscapeCloses 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.