Skip to content

Toolbar

Lays controls out in a bar. Use it for an application header, a page's action row, or the status strip under an editor.

tsx
import { Toolbar } from 'neba';

<Toolbar render={<header />} start={<Logo />} end={<Button>Deploy</Button>}>
  Workspace
</Toolbar>;

Props

PropTypeDefaultDescription
variantshared'solid' | 'outline' | 'text''outline'Weight of the bar, said the way a container says it: the sheet is never dyed, because a toolbar holds other people’s controls and those arrive with colours of their own
sizeshared'xs' | 'sm' | 'md' | 'lg' | 'xl''md'The scale of the padding and the radius. Not a height: a toolbar is as tall as the controls in it plus its padding
colorshared'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info''primary'Semantic colour role. Arbitrary colour values are not accepted
densityshared'default' | 'compact''default'Padding only: which is why there is no separate `dense` prop meaning the same thing
elevationshared0 | 1 | 2 | 30Drop shadow depth. `0` even when the bar is pinned: a shadow under a header says "there is content beneath this", and that is only true once the page has been scrolled
positionshared'static' | 'sticky' | 'fixed''static'How the bar sits in the page’s scroll. `sticky` takes up its own space and stops at the edge, so nothing underneath has to be padded around it; `fixed` leaves the flow entirely, so the page needs padding of its own
sideshared'top' | 'bottom''top'Which edge it is held against when `position` is not `static`
dividerbooleanfalseDraws a hairline along the edge that faces the content: under a `top` bar, over a `bottom` one
startReactNodePinned to the start of the bar: a logo, a title, a back button
endReactNodePinned to the end: the actions
renderuseRender.RenderPropRenders something other than a div (render={<header />}). Base UI's own escape hatch
childrenReactNodeThe middle. Takes whatever width `start` and `end` leave

Every native <div> attribute passes through.

There are three slots: start and end are pinned to their ends and children takes what is left, so no spacer element is needed to push things apart.

Examples

size and density

A Toolbar has no height of its own. It is as tall as the controls in it plus its padding, and size and density set that padding. density="compact" gives a dense bar without moving the type scale.

position and side

position is CSS's own three values, spelled the way CSS spells them.

  • sticky: what an application header usually wants. It takes up its own space, so nothing underneath needs padding around it.
  • fixed: leaves the flow, so the page needs padding of its own or the first screenful sits behind the bar.

side is the edge the bar pins to. A pinned bar drops its radius, because a rounded corner against the edge of the screen is a gap with nothing behind it.

divider and elevation

divider rules under the bar to show there is content beneath. elevation stays 0 even when the bar is pinned, so either raise it yourself on scroll or leave it flat and turn on divider.

color

color reaches the rule and the focus ring. A bar that holds other people's controls does not fill its own sheet.

Accessibility

  • It does not set role="toolbar". That role promises one tab stop for the bar with arrow keys inside it, and claiming it without implementing it is worse for a keyboard user than not claiming it.
  • For a page header, pass render={<header />}: a real landmark, which is what a screen reader user navigates by.
  • For a group of controls navigated with the arrow keys, use ButtonGroup.

Released under the MIT License