Menu

Site and documentation links

Search documentation

Type to filter pages and sections. Use the arrow keys to move and Enter to open.

    Tooltip

    A short label that appears when a control is hovered or focused.

    View code
    import { Tooltip, TooltipContent, TooltipTrigger } from '@syncclouds/ui'
    
    const TOOLS = [
      { label: 'Bold', shortcut: 'Ctrl B', glyph: 'B' },
      { label: 'Italic', shortcut: 'Ctrl I', glyph: 'I' },
      { label: 'Link', shortcut: 'Ctrl K', glyph: '↗' }
    ]
    
    /* Icon-only triggers keep their own aria-label; the tooltip adds the
       shortcut as a description. */
    export function TooltipDemo() {
      return (
        <div className="flex gap-2">
          {TOOLS.map(tool => (
            <Tooltip key={tool.label}>
              <TooltipTrigger aria-label={tool.label}>{tool.glyph}</TooltipTrigger>
              <TooltipContent>
                {tool.label}, {tool.shortcut}
              </TooltipContent>
            </Tooltip>
          ))}
        </div>
      )
    }

    Installation

    npm install @syncclouds/ui

    Usage

    import { Tooltip, TooltipContent, TooltipTrigger } from '@syncclouds/ui'
    <Tooltip>
      <TooltipTrigger aria-label="Bold">B</TooltipTrigger>
      <TooltipContent>Bold, Ctrl B</TooltipContent>
    </Tooltip>

    Anatomy

    Tooltip
    ├── TooltipTrigger
    └── TooltipContent

    Delay

    delay sets how long a pointer rests on the trigger first. Keyboard focus always shows it straight away.

    View code
    import { Tooltip, TooltipContent, TooltipTrigger } from '@syncclouds/ui'
    
    export function TooltipDelay() {
      return (
        <div className="flex gap-3">
          <Tooltip delay={0}>
            <TooltipTrigger>No delay</TooltipTrigger>
            <TooltipContent>Shows at once</TooltipContent>
          </Tooltip>
          <Tooltip delay={1000}>
            <TooltipTrigger>One second</TooltipTrigger>
            <TooltipContent>Shows after a second</TooltipContent>
          </Tooltip>
        </div>
      )
    }

    Placement

    View code
    import { Tooltip, TooltipContent, TooltipTrigger } from '@syncclouds/ui'
    
    const PLACEMENTS = ['top', 'right', 'bottom', 'left'] as const
    
    export function TooltipPlacement() {
      return (
        <div className="flex flex-wrap justify-center gap-3">
          {PLACEMENTS.map(placement => (
            <Tooltip key={placement} delay={0}>
              <TooltipTrigger>{placement}</TooltipTrigger>
              <TooltipContent placement={placement}>Placed {placement}</TooltipContent>
            </Tooltip>
          ))}
        </div>
      )
    }

    Without the theme

    View code
    import { Tooltip, TooltipContent, TooltipTrigger } from '@syncclouds/ui'
    
    export function TooltipUnstyled() {
      return (
        <Tooltip delay={200}>
          <TooltipTrigger className="rounded-md border border-zinc-300 px-3 py-1.5 text-sm font-medium text-zinc-900 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 dark:border-zinc-600 dark:text-zinc-100">
            Share
          </TooltipTrigger>
          <TooltipContent className="rounded-md bg-indigo-700 px-2 py-1 text-xs font-medium text-white dark:bg-indigo-300 dark:text-indigo-950">
            Anyone with the link can view
          </TooltipContent>
        </Tooltip>
      )
    }

    Accessibility

    Follows the WAI-ARIA Tooltip pattern.

    KeysWhat they do
    TabFocusing the trigger shows the tooltip straight away. Moving on hides it.
    EscapeHides the tooltip.
    • The pointer can move onto the tooltip without it closing.
    • On touch, a long press shows it.
    • It describes the trigger, so keep it short and never put links or buttons inside. An icon-only trigger still needs its own aria-label.

    API reference

    Every part also accepts the props of the element it renders, including className and ref.

    Tooltiprenders no element

    Holds the open state and timing. Renders no element of its own.

    PropTypeDefaultDescription
    delaynumber400Milliseconds a pointer rests on the trigger before it shows.

    TooltipTriggerrenders <button>

    The control it describes. While open, aria-describedby points at the tooltip.

    PropTypeDefaultDescription
    asChildbooleanfalseUse your own element.
    Data attributeValues
    data-state"open" | "closed"

    TooltipContentrenders <div>

    The text. Rendered only while open, in the top layer, next to the trigger.

    PropTypeDefaultDescription
    placementPlacement"top"Where it shows. It flips and shifts to stay on screen.
    Data attributeValues
    data-state"open"
    data-side"top" | "right" | "bottom" | "left"
    Built by Syncclouds. Syncclouds UI is in development.