Skip to content

Toolbar

Single-row action toolbar that measures its own width and collapses lower-priority items into an overflow menu when they no longer fit.

  • Category: Actions & controls
  • Status: stable public Registry/export-map component family
  • Targets: iOS · Android · Web, subject to the compatibility contract
  • Prerequisites: @beemvp/beeui-ui installed (or this component’s source copied via the Registry CLI below) and, on Web, the BeeUI Tailwind/Uniwind theme CSS loaded — see Start for full platform setup.
  • Source: packages/ui/src/components/toolbar.tsx
import { Toolbar, ToolbarItem } from '@beemvp/beeui-ui';

There is no documented deep/private source import. For source ownership from a BeeUI checkout:

Terminal window
pnpm beeui add toolbar

Registry (used throughout this page) is BeeUI’s source-ownership manifest — registry/registry.json — that the pnpm beeui/@beemvp/beeui-cli CLI reads to copy a component’s real source into your app and rewrite its internal imports; it is not an npm package index. This component’s own Registry entry: registry/registry.json.

  • Family exports: Toolbar ToolbarItem
    • Also routed here, outside the Registry family:
      • toolbar
    • Package export subpath: @beemvp/beeui-ui/toolbar

Exported types: ToolbarItemProps, ToolbarProps

The generated API inventory is mechanically joined to packages/ui/src/index.ts, Registry metadata, and the component reference contract. Each type’s field table below is parsed directly from that source, not a second hand-maintained copy; for the fuller behavior narrative see the canonical component behavior catalog.

Stateless layout primitive with no owned selection state. Toolbar measures its own container width and every child ToolbarItem’s natural (never-collapsed) width, then moves whichever items do not fit into a trailing overflow DropdownMenu — lowest priority collapses first, items omitting priority never collapse even if the row still overflows, and widening the container automatically restores previously collapsed items on the next render (no separate collapsed-state store). A collapsed item keeps its onPress/label/icon inside the overflow menu; ToolbarItem itself is a config-only element Toolbar reads props from and never mounts as a component, so a ToolbarItem rendered outside a Toolbar renders nothing.

Prop Type Default Description
children (required) React.ReactNode — Rendered in the toolbar row while this item fits. A single element is expected — an IconButton/Button is the common case — since Toolbar reads its rendered width to decide what fits, and (on Web) clones it to wire ref/tabIndex/onFocus for arrow-key roving-tabindex navigation, preserving any ref/onFocus the element already carries. Also clones disabled/onPress onto it per this item’s own metadata — see ToolbarItemProps.disabled/.onPress. Every other prop is left untouched.
className string — Applied to this item’s own wrapper in the toolbar row. Has no effect on the overflow menu row (which has no equivalent wrapper) or on the child element itself — compose a class directly on the child for that.
disabled boolean — Disables this item everywhere it renders: cloned onto the child in the toolbar row (overriding whatever disabled the child element itself declares) and passed to the overflow menu row when this item is collapsed. Defaults to false — omitting it (or passing false) never clears a disabled the child sets on itself.
icon React.ReactNode — Icon shown next to label when this item renders inside the overflow menu instead of the row.
label (required) string — Accessible label and overflow-menu row text for this item. Required — the overflow menu has no other way to describe a collapsed item’s action.
onPress () => void — Called when this item is activated. In the overflow menu this is always the row’s own activation handler. In the toolbar row it is cloned onto the child only when the child does not already declare its own onPress — an onPress the child element sets itself always wins there instead (a dev warning fires once if both are set to different functions, since that combination is otherwise silently ambiguous about which one runs).
priority number — Collapse priority: an item with a lower number collapses first when the row does not fit. Items that omit priority never collapse — they always render in the row, even if that means the row itself overflows. Items sharing the same priority collapse in trailing-to-leading order (the later item in children order collapses first).
Prop Type Default Description
children React.ReactNode — Content rendered inside this element. The family’s composition section states which children it expects.
className string — Extra utility classes, merged after the component’s own via cn(...), so they win on conflict. An escape hatch for source-owned and application work, not a cross-engine portability guarantee.
overflowAccessibilityLabel string — Accessible name for the trailing overflow menu button. Required whenever any child ToolbarItem declares a priority (only a prioritized item can ever collapse) — a dev warning fires if it is missing once the overflow menu actually renders.

Also carries every prop of Omit<ViewProps, 'children' | 'role'> — that upstream contract is not reproduced here.

The executable fixtures below are the source-grounded usage examples; consumers should not infer state ownership from DOM structure or another UI library.

  • BeeUIProvider is required above this family because it participates in shared overlay/toast runtime infrastructure.
  • Peer/native dependencies visible to this Registry item: react, react-native
  • Registry dependency closure: core-cn, dropdown-menu
  • Safe-area ownership remains explicit: shell surfaces touching system edges opt into SafeArea; components do not silently invent app-shell insets.
  • Web consumers load the BeeUI semantic theme CSS as documented in Web onboarding.

This family ships no platform-specific file, but its source branches on Platform, so some behavior differs by target.

The same public family is exposed across the supported target matrix; meaningful platform differences remain governed by the compatibility contract.

Evidence classes are not equal and this page does not blur them: Web behavior is exercised in a real browser, while iOS and Android carry package/export and native-compile evidence, which is not device-runtime proof. The compatibility contract records which class each claim rests on.

  • Roles this family assigns: toolbar — set in toolbar.tsx by the components themselves, not by the caller.
  • Accessibility states and properties it sets: accessibilityElementsHidden, accessibilityLabel, hidden — read from toolbar.tsx.

Keyboard/focus behavior, announcements, Dynamic Type/Web zoom, RTL and reduced-motion expectations are not derived here — see Accessibility overview, Keyboard & focus, RTL/localization and Large text & zoom. BeeUI does not claim universal accessibility certification from automated tests.

  • Style axes: none of its own — its appearance comes from tokens and your own classes; it also carries Omit<ViewProps, 'children' | 'role'>.
  • Class-name surfaces: className.

Colors, spacing and typography come from semantic tokens rather than from values written here — see Theming and Density. A className is an escape hatch for source-owned and application work, not a cross-engine portability guarantee.

Each link below opens the Showcase at that exact example, not at the top of the gallery:

  • basic — smallest meaningful complete usage

The Showcase links demonstrate Web behavior; use the native-preview guide for real simulator/emulator/device paths.

This frame loads the real BeeUI Web Showcase on demand; it is not a second docs-only implementation. It proves browser behavior only. Use native preview for iOS/Android simulator, emulator or device paths.

  • Family root / primary export: Toolbar
    • Public composition parts / helpers:
      • ToolbarItem
    • Exported type surface:
      • ToolbarItemProps
      • ToolbarProps

The tree above is ordinary document structure so it remains readable with keyboard and assistive technology; it is derived from the real public export family rather than a canvas-only diagram.

The following is the exact typechecked runtime Showcase fixture selected for this live preview: apps/showcase/component-gallery/toolbar-showcase.tsx. Runtime gallery/pattern sources are preferred over test harnesses, and the displayed source and executable source are the same file; there is no separately maintained demo snippet.

import { Card, IconButton, Section, Text, Toolbar, ToolbarItem, VStack } from '@beemvp/beeui-ui';
import * as React from 'react';
import { View } from 'react-native';
// A fixed, narrow width forces every viewport (including a wide desktop
// browser) to overflow the same two lowest-priority items into the overflow
// menu, so this fixture's collapse behavior is deterministic rather than
// depending on the surrounding page layout.
const NARROW_TOOLBAR_WIDTH = 220;
function OrderToolbar() {
const [lastAction, setLastAction] = React.useState('none');
return (
<VStack className="gap-3" testID="toolbar-showcase">
<View style={{ width: NARROW_TOOLBAR_WIDTH }}>
<Toolbar overflowAccessibilityLabel="More actions" testID="toolbar-showcase-toolbar">
<ToolbarItem label="Search" onPress={() => setLastAction('search')}>
<IconButton accessibilityLabel="Search" variant="ghost">
🔍
</IconButton>
</ToolbarItem>
<ToolbarItem label="Filter" onPress={() => setLastAction('filter')} priority={2}>
<IconButton accessibilityLabel="Filter" variant="ghost">
▤
</IconButton>
</ToolbarItem>
<ToolbarItem label="Export" onPress={() => setLastAction('export')} priority={1}>
<IconButton accessibilityLabel="Export" variant="ghost">
⇩
</IconButton>
</ToolbarItem>
</Toolbar>
</View>
<Text testID="toolbar-showcase-last-action" tone="muted" variant="caption">
{`Last action: ${lastAction}`}
</Text>
</VStack>
);
}
export function ToolbarShowcase() {
return (
<Card className="gap-4" testID="toolbar-showcase-card" variant="raised">
<Section
description="A single-row toolbar that measures its own width and collapses the lowest-priority items (Export, then Filter) into an overflow menu once the row no longer fits; Search never collapses because it declares no priority."
title="Priority collapse and overflow menu"
>
<OrderToolbar />
</Section>
</Card>
);
}

Use the code block’s copy affordance to copy the exact fixture. For a smaller app-specific example, start from the public imports shown above and keep only the state your screen owns.

overflowAccessibilityLabel is required only once the overflow menu actually renders (i.e. once any prioritized item collapses) — a dev warning fires if it is missing at that point, not before. ToolbarItem.children must be a single element (typically an IconButton/Button) — Toolbar reads it for measurement, clones disabled onto it whenever this item is disabled and onPress onto it whenever the child declares none of its own (an onPress the child sets itself always wins instead), and, on Web, further clones its focus/keyboard-navigation wiring for roving-tabindex support; every other prop on the child is left untouched.

Implementation note: The overflow menu is a DropdownMenu composition, so it inherits that family’s full keyboard/dismiss behavior and aria-haspopup="menu" for free — there is no second, bespoke popover implementation.