Lumenv0.2

Components/Data Display

Tooltip

A quiet aside. Hover or focus the trigger to read it; set in mono, small.

On hover

Props

PropTypeDefaultDescription
contentstringLabel shown on hover or focus
childrenReactNodeThe trigger element
side'top' | 'bottom' | 'left' | 'right''top'Placement relative to trigger

Installation

Paste the source into components/tooltip.tsx. Opens on hover and keyboard focus — no dependencies required.

'use client';

import { useState } from 'react';
import type { CSSProperties, ReactNode } from 'react';

type TooltipSide = 'top' | 'bottom' | 'left' | 'right';

interface TooltipProps {
  content: string;
  children: ReactNode;
  side?: TooltipSide;
}

const positions: Record<TooltipSide, CSSProperties> = {
  top: { bottom: 'calc(100% + 6px)', left: '50%', transform: 'translateX(-50%)' },
  bottom: { top: 'calc(100% + 6px)', left: '50%', transform: 'translateX(-50%)' },
  left: { right: 'calc(100% + 6px)', top: '50%', transform: 'translateY(-50%)' },
  right: { left: 'calc(100% + 6px)', top: '50%', transform: 'translateY(-50%)' },
};

export function Tooltip({ content, children, side = 'top' }: TooltipProps) {
  const [visible, setVisible] = useState(false);

  return (
    <span
      style={{ position: 'relative', display: 'inline-flex' }}
      onMouseEnter={() => setVisible(true)}
      onMouseLeave={() => setVisible(false)}
      onFocus={() => setVisible(true)}
      onBlur={() => setVisible(false)}
    >
      {children}
      {visible && (
        <span
          role="tooltip"
          style={{
            position: 'absolute',
            whiteSpace: 'nowrap',
            backgroundColor: 'var(--color-surface)',
            color: 'var(--color-text)',
            border: '0.5px solid var(--color-border)',
            borderRadius: 'var(--radius-sm)',
            padding: '4px 8px',
            fontFamily: 'var(--font-mono)',
            fontSize: '11px',
            letterSpacing: '0.02em',
            zIndex: 30,
            ...positions[side],
          }}
        >
          {content}
        </span>
      )}
    </span>
  );
}

Built from Lumen tokens. Edit the tokens