Skip to main content
Kaleidoscope

Toolbar

Useful for configuring options for a particular item in an editor or a form, when you don't want the options to be in-line with the item

Default

What you get out of the box with this component:

Editable example
<Toolbar visible={true} positionType={ToolbarPositionType.None}>
  <ToolbarButton
    tooltip={{content: "move up"}}
    onClick={() => {}}
    icon={<ArrowUp />}
  />
  <ToolbarButton
    tooltip={{content: "move down"}}
    onClick={() => {}}
    icon={<ArrowDown />}
  />
  <ToolbarButton
    tooltip={{content: "delete"}}
    onClick={() => {}}
    icon={<Delete />}
    isDestructive={true}
  />
</Toolbar>

Auto-positioned relative to an element

Using the ToolbarPositionType.Element position type, you can set an element for the toolbar to position relative to, and it will automatically update. Pass a DOM node as the element prop for this to work.

Editable example
() => {
  const ref = React.useRef();
  const [showToolbar, setShowToolbar] = React.useState(false);
  const [text, setText] = React.useState("Focus inside me to see the toolbar");

  return (
    <div>
      <Toolbar visible={showToolbar} positionType={ToolbarPositionType.Element} element={ref.current}>
        <ToolbarButton
          icon={<ListMarkerDash />}
          tooltip={{content: "Add dash"}}
          onClick={() => setText(text + "- ")}
        />
        <ToolbarButton
          icon={<ListMarkerCircle />}
          tooltip={{content: "Add circle"}}
          onClick={() => setText(text + "* ")}
        />
      </Toolbar>
      <TextInput
        label="Sample text input"
        multiline
        value={text}
        onFocus={() => setShowToolbar(true)}
        onBlur={() => setShowToolbar(false)}
        onChange={setText}
        ref={ref}
      />
    </div>
  )
}

Toolbar children

We provide three out-of-the-box toolbar children:

  • ToolbarButton
  • ToolbarPopover
  • ToolbarSeparator

ToolbarButton

Toolbar buttons are simple extensions to the IconButton component; they also take an optional selected prop to indicate whether or not the button is active.

Editable example
() => {
  const [italicSelected, setItalicSelected] = React.useState(false);
  return (
    <Toolbar visible={true} positionType={ToolbarPositionType.None}>
      <ToolbarButton
        icon={<Italic />}
        selected={italicSelected}
        aria-label="Italic"
        onClick={() => setItalicSelected(!italicSelected)}
      />
      <ToolbarButton
        icon={<Bold />}
        aria-label="Bold"
      />
      <ToolbarSeparator />
      <ToolbarButton
        icon={<Delete />}
        aria-label="Delete"
        isDestructive={true}
      />
    </Toolbar>
  )
}

ToolbarPopover

The ToolbarPopover is a regular Popover with better defaults for use within a Toolbar. Refer to the for usage instructions.

Editable example
() => {
  return (
    <Toolbar positionType={ToolbarPositionType.None} visible>
      <ToolbarButton icon={<ArrowUp />} disabled />
      <ToolbarButton icon={<ArrowDown />} disabled />
      <ToolbarPopover button={(buttonProps) => <ToolbarButton {...buttonProps} icon={<Styles />} />}>
        You found me!
      </ToolbarPopover>
    </Toolbar>
  )
}

ToolbarSeparator

A simple way to segment the toolbar is using a separator:

Editable example
<Toolbar visible={true} positionType={ToolbarPositionType.None}>
  <ToolbarButton
    icon={<Styles />}
    aria-label="Contextual styles"
  />
  <ToolbarSeparator />
  <ToolbarButton
    icon={<Delete />}
    aria-label="Delete"
  />
</Toolbar>

Best practices

  • Only make use of a Toolbar when you are okay with controls being hidden behind selection or hover. By default, these controls won't have very strong discoverability or ease of access.
  • When using the ToolbarButton component, always provide a label, either through the tooltip prop, or passing an aria-label prop if not

Accessibility

  • This component doesn't provide any accessibility provisions for screen readers