nili/ui
All components

Tooltip

Overview
13 exports9 variant axes26 props4 files
import { Tooltip, TooltipAlign, TooltipPlacement, TooltipSide } from '@nili/ui';

This is the library’s own overview page, rendered live. Switch the language or the theme in the header and it follows.

Sizes

Three bubble sizes. The trigger must be focusable — a tooltip on a plain span is invisible to keyboard users, so wrap text in a button.

import { Tooltip, Button } from "@nili/ui"

export function Example() {
  return (
    <>
      <Tooltip size="2xs" content={t('copyLink')}>
        <Button appearance="stroke">2X-Small</Button>
      </Tooltip>
      <Tooltip size="xs" content={t('copyLink')}>
        <Button appearance="stroke">X-Small</Button>
      </Tooltip>
      <Tooltip size="lg" content="Copy link" description="Anyone with the link can view.">
        <Button appearance="stroke">Large</Button>
      </Tooltip>
    </>
  )
}

Sides and alignment

side is logical: start and end follow reading direction. Top and bottom also take an align; start and end do not, and the type makes that unrepresentable rather than accepting a prop that does nothing.

sides
alignment (top / bottom only)
import { Tooltip, Button } from "@nili/ui"

export function Example() {
  return (
    <>
      <Tooltip side="top" content="Top" />
      <Tooltip side="bottom" align="start" content="Bottom start" />
      <Tooltip side="start" content="Start" />
      <Tooltip side="end" content="End" />
    </>
  )
}

Light bubble, arrow and leading icon

A tooltip is inverted against its surface, so darkMode is a per-tooltip choice rather than a theme decision. It is on by default — the dark bubble on a light page.

import { Tooltip, CompactButton, Icon } from "@nili/ui"
import { RiInformationLine } from "@remixicon/react"

export function Example() {
  return (
    <>
      <Tooltip content={t('style.dark')}>
        <CompactButton aria-label="Info"><Icon icon={RiInformationLine} /></CompactButton>
      </Tooltip>

      <Tooltip darkMode={false} content={t('style.light')}>
        <CompactButton aria-label="Info"><Icon icon={RiInformationLine} /></CompactButton>
      </Tooltip>

      <Tooltip arrow={false} content={t('style.noTail')}>
        <CompactButton aria-label="Info"><Icon icon={RiInformationLine} /></CompactButton>
      </Tooltip>

      <Tooltip
        content="With a leading icon"
        startIcon={<Icon icon={RiInformationLine} />}
      >
        <CompactButton aria-label="Info"><Icon icon={RiInformationLine} /></CompactButton>
      </Tooltip>
    </>
  )
}

Delay and dismissal

delay holds the bubble back on hover; focus always opens it immediately. The large tooltip can carry a close button — keep that for content people need a moment with.

import { Tooltip, Button } from "@nili/ui"

export function Example() {
  return (
    <>
      <Tooltip delay={600} content={t('delay.waited')}>
        <Button appearance="stroke">Slow</Button>
      </Tooltip>

      <Tooltip
        size="lg"
        dismissible
        dismissLabel="Close"
        content="Keyboard shortcuts"
        description="Press ⌘K to open the command palette from anywhere."
      >
        <Button appearance="stroke">{t('delay.dismissible')}</Button>
      </Tooltip>

      <Tooltip disabled content={t('delay.offBody')}>
        <Button appearance="stroke" disabled>Disabled</Button>
      </Tooltip>
    </>
  )
}