Skip to the content

Kongens Nytorv

Metro M1, M2 and M3.

Variants and states

RestDisabled
Default
Default
  • Rest
  • Disabled

Toolbar styles hover, pressed and focus on its inner parts, which a still preview can't reach, so this table shows rest and disabled only.

Props

NameTypeDefaultDescription
orientation'horizontal' | 'vertical''horizontal'Which way the bar runs, and so which arrow keys move through it: Left and Right for horizontal, Up and Down for vertical.
disabledbooleanfalseWhether every button in the toolbar is disabled. The buttons stay focusable unless their focusableWhenDisabled is false.
childrenReactNode—The toolbar's ToolbarButtons, ToolbarGroups and ToolbarSeparators, in reading order.
classNamestring—Reaches the root. className is merged after pn-Toolbar.
styleCSSProperties—Reaches the root. className is merged after pn-Toolbar.
refRef<HTMLDivElement>—Reaches the root. className is merged after pn-Toolbar.
orientation'horizontal' | 'vertical', default 'horizontal'
Which way the bar runs, and so which arrow keys move through it: Left and Right for horizontal, Up and Down for vertical.
disabledboolean, default false
Whether every button in the toolbar is disabled. The buttons stay focusable unless their focusableWhenDisabled is false.
childrenReactNode, default —
The toolbar's ToolbarButtons, ToolbarGroups and ToolbarSeparators, in reading order.
classNamestring, default —
Reaches the root. className is merged after pn-Toolbar.
styleCSSProperties, default —
Reaches the root. className is merged after pn-Toolbar.
refRef<HTMLDivElement>, default —
Reaches the root. className is merged after pn-Toolbar.

Use it

import { Toolbar } from '@mylder/perron'

Ask your agent

get_reference({ library: "base-ui", component: "Toolbar" })

Keyboard and ARIA

From the Base UI reference for Toolbar and the installed ToolbarRoot, ToolbarButton, ToolbarGroup, ToolbarSeparator and the composite root they build on. "From" says who does it.

KeyDoesFrom
Tab, Shift+TabMoves focus into the toolbar, to the item that last had it (the first enabled item at first), and out of it again: the toolbar is one tab stopBase UI
ArrowRightIn a horizontal toolbar, moves focus to the next item, wrapping from the last to the first while loopFocus is on; the previous item under an rtl DirectionProvider, which Perron doesn't set upBase UI
ArrowLeftIn a horizontal toolbar, moves focus to the previous item, wrapping from the first to the last while loopFocus is on; the next item under an rtl DirectionProvider, which Perron doesn't set upBase UI
ArrowDown, ArrowUpIn a vertical toolbar, move focus to the next and the previous item, wrapping while loopFocus is onBase UI
Enter, SpaceActivate the focused button: fire onClick, or open the popup of a trigger given through renderThe browser; Base UI for a non-button render

Home and End do nothing: Base UI's toolbar doesn't turn them on (enableHomeAndEndKeys is off in the installed ToolbarRoot), and the component adds no keys of its own.

ElementRoleAccessible name fromStates announced
roottoolbar, from Base UIThe caller's aria-label or aria-labelledbyaria-orientation
buttonbutton, native; role="button" when render gives a non-buttonIts text content, the label's children; for an icon-only button, the caller's aria-labelDisabled: aria-disabled while focusable when disabled, else the native disabled; aria-pressed from selected, when given
startIcon, endIconnone: aria-hidden="true"nonenone
groupgroup, from Base UIThe caller's aria-label, when the group needs onenone
separatorseparator, from Base UInonearia-orientation, across the toolbar's

What axe won't catch, from the contract, each with how this component meets it:

  • Everything the eye is told, the ear is told, for every shape each prop accepts: a button's label is the text it is named by, and an icon-only button's aria-label says what its icon shows; the icons are aria-hidden; color carries emphasis, not meaning; a toggle's on fill is its aria-pressed; disabled is announced by aria-disabled or disabled; the separator is announced as one.
  • Every landmark and named region has an accessible name: the toolbar is named by the caller's aria-label or aria-labelledby, which every story sets, so two toolbars on a screen tell themselves apart.
  • Every default label can be overridden: none here; the toolbar owns no strings.
  • Every shape the type accepts renders, in every variant: a button's children, startIcon and endIcon render a string, an element and a list alike, in both colours and both orientations.
  • A hidden copy kept for animation is aria-hidden, and a collapsed region is inert: none here; the toolbar keeps no hidden copy and collapses nothing.
  • Native semantics first: native <button>s from Toolbar.Button, and Base UI's toolbar, group and separator roles, with ARIA only for the toolbar's and an icon-only button's names.
  • Focus moves in reading order and returns on close: the arrow keys move through the items in document order, swapped only under an rtl DirectionProvider, which Perron doesn't set up, and the toolbar opens nothing of its own; a popup opened through render returns focus to its trigger, by Base UI.
  • Every target is at least size.target-min square: the smallest target is an icon-only button, size.control (34 px) square.
  • Loops stop when the system asks for less motion: none here; the toolbar has no loop and no transition.

Owned strings

No owned strings: every word comes from the caller, as a button's children, an icon-only button's aria-label, or the toolbar's aria-label.

Do and don't

For a caller using the component, with the reason. Each row is a rule: a must row's Don't is never right, a should row's needs a reason, and Checked by says what catches the Don't in a caller's code.

RuleLevelDoDon'tChecked by
DD-1mustName every toolbar with aria-label or aria-labelledby, such as "Map controls", so a screen reader tells it from the next oneLeave a toolbar unnamed: two on a screen are both announced as "toolbar"review
DD-2mustPut each action in a ToolbarButton, so the arrow keys reach itPut a Button, an IconButton or a plain <button> straight into the toolbar: it falls out of the arrow-key order and adds a tab stopreview
DD-3mustGive an icon-only button an aria-label that names the action: "Zoom in"Leave an icon-only button without one: its icon is aria-hidden, so the button has no namereview
DD-4mustOpen a menu, popover or dialog through render, <ToolbarButton render={<Menu.Trigger />}>, and set disabled on the ToolbarButton, not the triggerDisable the trigger itself: Base UI says the button then leaves the toolbar's arrow-key orderreview
DD-5mustWrap a button in a Tooltip with <Tooltip trigger={<ToolbarButton … />}>…</Tooltip>, the tooltip around the buttonPass the tooltip's trigger to ToolbarButton's render, as for popupsreview
DD-6mustGive one button per screen color="brand", for its main actionMark several toolbar buttons brand, or use it for emphasis: a second yellow action leaves neither the main onereview
DD-7mustKeep a disabled button focusable, the default, so it can explain itself through a tooltipRestyle a disabled button with opacity: disabled is color.text.tertiary, a colourreview
DD-8mustGive a toggle in a toolbar, such as the map's 3D view, selected, held by the screen, and keep its name the same while on and offSwap a toggle's name with its state, or draw its on look in the caller's CSS: selected sets aria-pressed and the on look togetherreview
DD-9shouldPlace the toolbar over the map in a pattern, which sets its position and stackingSet a z-index or a margin from the screen edge on the toolbar itself: the component sizes to its contentreview