Orbex Sonar-DB Design system , home

Examples

A toolbar of icon buttons
Code
tsx
import { IconButton } from '@orbex/sonar-components/icon-button'
import { Tooltip, TooltipProvider } from '@orbex/sonar-components/tooltip'
import type { ComponentProps } from 'react'
import downloadSymbol from '@material-symbols/svg-400/rounded/download.svg?raw'
import filterSymbol from '@material-symbols/svg-400/rounded/filter_list.svg?raw'
import printSymbol from '@material-symbols/svg-400/rounded/print.svg?raw'
import refreshSymbol from '@material-symbols/svg-400/rounded/refresh.svg?raw'

/* Material Symbols Rounded, weight 400, as icon components (Foundations › Icons) */
const symbol = (svg: string) => {
  const path = svg.match(/ d="([^"]+)"/)?.[1]
  return (props: ComponentProps<'svg'>) => (
    <svg viewBox="0 -960 960 960" fill="currentColor" aria-hidden="true" focusable="false" {...props}>
      <path d={path} />
    </svg>
  )
}

const DownloadIcon = symbol(downloadSymbol)
const FilterIcon = symbol(filterSymbol)
const PrintIcon = symbol(printSymbol)
const RefreshIcon = symbol(refreshSymbol)

/* Inside one provider, once a tooltip is open the next one appears at once */
export default function Toolbar() {
  return (
    <TooltipProvider>
      <div role="toolbar" aria-label="Orders" style={{ display: 'flex', gap: 4 }}>
        <Tooltip content="Filter">
          <IconButton label="Filter" icon={<FilterIcon />} />
        </Tooltip>
        <Tooltip content="Refresh">
          <IconButton label="Refresh" icon={<RefreshIcon />} />
        </Tooltip>
        <Tooltip content="Export as CSV">
          <IconButton label="Export as CSV" icon={<DownloadIcon />} />
        </Tooltip>
        <Tooltip content="Print">
          <IconButton label="Print" icon={<PrintIcon />} />
        </Tooltip>
      </div>
    </TooltipProvider>
  )
}

Sizes, variants and states

Length

Usage

  • A name or a hint, never information someone needs to continue: touch screens show tooltips only on a long press.
  • Wrap a toolbar in a TooltipProvider: once one tooltip is open, the next appears at once.
  • The trigger must be focusable, so keyboard users get the tooltip too.

Do and don’t

DoA tooltip names an icon button, in a few words.
Don’tA tooltip that repeats a button’s own label.
DoInformation someone needs to act goes on the page, where it stays.
Don’tEssential instructions in a tooltip: hard to find, gone on touch, never interactive.

Accessibility

Keyboard

Key What it does
Tab Focusing the trigger shows the tooltip, as hovering does.
Escape Hides it.

Roles and attributes

Element or attribute What it gives
Not read separately A tooltip repeats its trigger’s name, such as an icon button’s label, for sighted people. Anything that must be read goes in the name or on the page.

Notes

  • Keyboard focus opens the tooltip without delay; Escape closes it.
  • Text on the inverse surface passes AA in both themes.

Use it

Each component is its own entry point with its own stylesheet, so an app loads only what it uses. The tokens and the cascade layers are set once for the app: see Installation.

tsx
import { Tooltip, TooltipProvider } from '@orbex/sonar-components/tooltip'
import '@orbex/sonar-components/tooltip.css'

API

Tooltip

A short label on the inverse surface, shown on hover and focus. Wrap groups of triggers in TooltipProvider so that, once one tooltip is open, moving to the next shows it without the delay.

Props of Tooltip
Prop Type Default
content Required

The text shown. Short: a name or a hint, never something the person must read to continue.

ReactNode —
children Required

The element it describes, usually an IconButton. It must be focusable, so keyboard users get the tooltip too.

ReactElement —
side

Side of the element the tooltip opens on. It flips when there is no room.

BaseTooltip.Positioner.Props['side'] 'top'
delay

Time the pointer rests on the trigger before the tooltip opens, in milliseconds. Keyboard focus opens it at once.

number 300

TooltipProvider

Shares the open delay between tooltips, so moving along a toolbar does not wait at every button.

Passes every other prop to Base UI: see the Base UI reference.