Toolbar

A bar of icon buttons for one subject, such as an editor's formatting, in a row or a column.

BetaSince 1.0.0
On this page

Import

import { Toolbar } from '@envsemble/envui';

Usage

Toolbar.Root, named by its aria-label, holds Toolbar.Button, Toolbar.Link, Toolbar.Group and Toolbar.Separator.

  • A Toolbar.Button takes its icon and its label, which names it and shows in its tooltip with its shortcut, such as Ctrl+B, announced as aria-keyshortcuts.
  • With pressed it is a toggle, announced as pressed and drawn selected.
  • Its variant is Button's, ghost by default from the toolbar, and pending replaces the icon with a spinner.
  • A Toolbar.Link takes an href, through the link component of LinkProvider, with its icon and label.
  • A Toolbar.Group, named by its own aria-label, holds controls that belong together.
FormattingToolbar.tsx
import { useState } from 'react';
import { Toolbar } from '@envsemble/envui';
import { IconFormatBold } from '@envsemble/envui/icons/FormatBold';
import { IconFormatItalic } from '@envsemble/envui/icons/FormatItalic';
import { IconFormatListBulleted } from '@envsemble/envui/icons/FormatListBulleted';
import { IconFormatListNumbered } from '@envsemble/envui/icons/FormatListNumbered';
import { IconRedo } from '@envsemble/envui/icons/Redo';
import { IconUndo } from '@envsemble/envui/icons/Undo';

export default function FormattingToolbar() {
  const [bold, setBold] = useState(false);
  const [italic, setItalic] = useState(true);
  return (
    <Toolbar.Root aria-label="Formatting">
      <Toolbar.Group aria-label="Text style">
        <Toolbar.Button
          icon={<IconFormatBold />}
          label="Bold"
          shortcut="Ctrl+B"
          pressed={bold}
          onClick={() => setBold((current) => !current)}
        />
        <Toolbar.Button
          icon={<IconFormatItalic />}
          label="Italic"
          shortcut="Ctrl+I"
          pressed={italic}
          onClick={() => setItalic((current) => !current)}
        />
      </Toolbar.Group>
      <Toolbar.Separator />
      <Toolbar.Group aria-label="Lists">
        <Toolbar.Button icon={<IconFormatListBulleted />} label="Bulleted list" />
        <Toolbar.Button icon={<IconFormatListNumbered />} label="Numbered list" />
      </Toolbar.Group>
      <Toolbar.Separator />
      <Toolbar.Button icon={<IconUndo />} label="Undo" shortcut="Ctrl+Z" />
      <Toolbar.Button icon={<IconRedo />} label="Redo" shortcut="Ctrl+Shift+Z" disabled />
    </Toolbar.Root>
  );
}

Orientation and size

orientation is horizontal, the default, or vertical, and sets which arrow keys move.

  • size is sm, md or lg; without it the buttons take their container's control height.
  • loopFocus, on by default, moves from the last control to the first and back.
  • tooltipDelay is how long, in milliseconds, the pointer rests on a button or link before its tooltip opens, 400 by default, as Tooltip's delay; keyboard focus opens it at once.
  • disabled on Toolbar.Root or a Toolbar.Group disables every control inside, links included.

A Surface with radius="full" floats a small toolbar over content, as the ViewControls example does:

<Surface
  padding={1}
  radius="full"
  render={<Toolbar.Root aria-label="Diagram view" size="sm" tooltipDelay={0} />}
  style={{ inlineSize: 'fit-content' }}
>
  <Toolbar.Button icon={<IconZoomOut />} label="Zoom out" shortcut="Ctrl+-" />
  <Toolbar.Button icon={<IconZoomIn />} label="Zoom in" shortcut="Ctrl+=" />
  <Toolbar.Separator />
  <Toolbar.Link href="/help/diagrams" icon={<IconHelp />} label="Diagram help" />
</Surface>

Buttons of your own

Buttons inside a toolbar take the ghost variant unless they set another.

  • A Button of the application's own keeps its own tab stop, outside the arrow keys' path.
  • A Toolbar.Button can be the trigger of a Menu.Root or a Popover, for a dropdown in the toolbar: it stays in the arrow keys' path, with its name in its tooltip, which stays closed while its popup is open.

Other bars

A bar with a field, a Select or labelled actions is a Row:

  • <Row wrap align="center" justify="between"> for a section's heading and its actions.
  • PageHeader's toolbar for a page's search, filters and primary action, as the PageToolbar example does: a Row whose field keeps its arrow keys, every control a tab stop, the primary action at the end.
  • A TopBar with titleBar for a window's title bar, with small ghost buttons in its actions.
<PageHeader
  title="Tasks"
  toolbar={
    <Row wrap align="center" justify="between" gap={3}>
      <Row wrap align="center" gap={3}>
        <SearchField label="Search tasks" placeholder="Search tasks" />
        <SegmentedControl
          aria-label="Status"
          value={status}
          onValueChange={setStatus}
          items={statuses}
        />
      </Row>
      <Button startIcon={<IconAdd />}>New task</Button>
    </Row>
  }
/>

Composition

The parts are the toolbar, env-toolbar; its groups, env-toolbar-group; its buttons and links, env-toolbar-button; its separators, env-toolbar-separator; and a button's tooltip, env-toolbar-tooltip. render on Toolbar.Root or Toolbar.Group renders it as another element, such as a ButtonGroup that connects its buttons, or onto a Surface that floats it.

Accessibility

You provide

  • An aria-label on the toolbar, and on groups that share a name.
  • The behaviour behind each button and shortcut.

envUI provides

  • role="toolbar" with aria-orientation, and a group role on each group.
  • One tab stop, with disabled buttons and links out of the arrow keys' path.
  • Names from label, aria-pressed on toggles and aria-keyshortcuts from shortcut.

Props

Toolbar.Root

A row, or a column, of controls for one subject, such as a text editor's formatting: one tab stop, with the arrow keys moving between its controls (the APG toolbar pattern). Buttons the application puts inside take the ghost variant unless they set another.

PropTypeDescription
aria-label
string
Names the toolbar for assistive technology, such as Formatting.
orientationDefault 'horizontal'
'horizontal''vertical'
The direction the controls run in, and which arrow keys move between them.
size
'sm''md''lg'
The height of the buttons inside, as on every control: sm, md or lg in the current scale. Without it, the control height of the container.
disabledDefault false
boolean
Disables every control inside.
loopFocusDefault true
boolean
Whether the arrow keys move from the last control to the first and back.
tooltipDelayDefault 400
number
Milliseconds the pointer rests on a button or link before its tooltip opens, as Tooltip's delay; keyboard focus opens it at once. 0 shows every name at once, for a toolbar people scan by pointing, such as a canvas's view controls.
render
ReactElement
Another element to render the toolbar as, such as a ButtonGroup that connects its buttons; the toolbar's class, attributes and keyboard handling merge into its props.
children
ReactNode
The controls: Toolbar.Button, Toolbar.Link, Toolbar.Group and Toolbar.Separator.

Also accepts the native props of <div>, such as ref, className and aria-* attributes.

Toolbar.Group

Controls of a toolbar that belong together, such as the text styles.

PropTypeDescription
aria-label
string
Names the group, such as Text style, where its controls belong together.
disabledDefault false
boolean
Disables every control in the group.
render
ReactElement
Another element to render the group as, such as a ButtonGroup.

Also accepts the native props of <div>, such as ref, className and aria-* attributes.

Toolbar.Separator

A line between groups of a toolbar's controls, across the toolbar's direction.

No props of its own.

Also accepts the native props of <div>, such as ref, className and aria-* attributes.

Toolbar.Button

An icon-only button of a toolbar, named by its label, which a tooltip shows; disabled, it leaves the arrow keys' path.

PropTypeDescription
iconrequired
ReactNode
The icon, such as FormatBold.
labelrequired
string
The action's name, such as Bold: assistive technology announces it, and the tooltip shows it on hover and focus.
pressed
boolean
For a button that turns something on and off, such as Bold: whether it is on. It is announced as pressed and drawn selected. Leave it out for a button that acts once, such as Undo.
shortcut
string
The keyboard shortcut that does the same, such as Ctrl+B, with keys joined by +: the tooltip shows it, and aria-keyshortcuts announces it, in ARIA's key names, such as Control+B. A sequence, such as Ctrl+K Ctrl+B, shows its keys without the attribute, as in Menu.
variant
'primary''secondary''outline''ghost''text'
As Button's; ghost by default, from the toolbar.
toneDefault 'neutral'
'neutral''danger'
As Button's: danger for an action that destroys, such as Delete, so it keeps its warning without a label.
pendingDefault false
boolean
As Button's: a spinner replaces the icon while the work runs.

Also accepts the native props of <button>, such as ref, className and aria-* attributes.

An icon-only link of a toolbar, named by its label, which a tooltip shows. In a disabled toolbar or group it has no destination: it reports aria-disabled, leaves the arrow keys' path and has no tooltip, as a disabled button does.

PropTypeDescription

Also accepts the native props of <a>, such as ref, className and aria-* attributes.

Part names

Each part's class and state attributes are public and versioned, for an application's CSS to style.

env-toolbar
The toolbar.
env-toolbar-button
A button.
env-toolbar-group
A group of buttons.
env-toolbar-separator
The line between groups.
env-toolbar-tooltip
A button's tooltip.
data-orientation
horizontal · vertical on env-toolbar, env-toolbar-group, env-toolbar-separator
data-size
lg · md · sm

Changelog

1.0.0

Toolbar, on Base UI's Toolbar.

1.0.0-prerelease.6

Toolbar.Button takes tone="danger" for an action that destroys, such as Delete.

A disabled toolbar or group disables its Toolbar.Link too: the link reports aria-disabled, has no destination and leaves the arrow keys' path.

1.0.0-prerelease.4

tooltipDelay on Toolbar.Root sets how long the pointer rests on a button or link before its tooltip opens; 0 shows every name at once.