# Tooltip

Tooltips display informative text when users hover over or focus an element. They provide supplementary information about an element without cluttering the interface.

## When to Use

- Provide brief descriptions of buttons, icons, or other UI elements
- Show keyboard shortcuts or additional context for actions
- Display truncated text or labels in full
- Explain unfamiliar terms or provide helpful hints
- Add supplementary information without overwhelming the interface

## Components

This module exports three components that work together:

- **`TooltipProvider`** - Convenience wrapper for simple tooltip use cases (recommended)
- **`TooltipTrigger`** - Lower-level component for advanced tooltip scenarios
- **`Tooltip`** - The tooltip content container (used with `TooltipTrigger`)

## TooltipProvider (Recommended)

The simplest way to add tooltips to your components. It combines `TooltipTrigger` and `Tooltip` for convenience.

See TooltipProvider for full documentation.

## TooltipTrigger

Lower-level component that wraps a trigger element and a `Tooltip`. Use this when you need more control over the tooltip content or behavior.

See TooltipTrigger for full documentation.

## Tooltip

Display container for tooltip content. Has a directional arrow dependent on its placement. This component is typically used as a child of `TooltipTrigger` or automatically rendered by `TooltipProvider`.

---

### Properties

- **`tipStyles`** `Styles` — Custom styles for the tooltip arrow (tip) element
- **`showIcon`** `boolean` — Controls whether an icon should be displayed in the tooltip
- **`placement`** `PlacementAxis` (default: `'top'`) — Position of the tooltip relative to its trigger. Options: `top`, `bottom`, `left`, `right`
- **`isMaterial`** `boolean` — Enables material-style tooltip with auto pointer events
- **`isLight`** `boolean` — Uses light color scheme for the tooltip
- **`isOpen`** `boolean` — Controlled open state of the tooltip
- **`defaultOpen`** `boolean` — Whether the tooltip is open by default (uncontrolled)
- **`onOpenChange`** `(isOpen: boolean) => void` — Callback when the tooltip open state changes
- **`shouldFlip`** `boolean` — Whether the tooltip should flip position when there is insufficient space

### Base Properties

Supports [Base properties](../../BaseProperties.md)

### Styling Properties

#### styles

Customizes the root element of the tooltip.

**Sub-elements:**
- None

### Style Properties

These properties allow direct style application without using the `styles` prop:

- **Base:** `display`, `font`, `preset`, `hide`, `whiteSpace`, `opacity`, `transition`
- **Position:** `gridArea`, `order`, `gridColumn`, `gridRow`, `placeSelf`, `alignSelf`, `justifySelf`, `zIndex`, `margin`, `inset`, `position`
- **Dimension:** `width`, `height`, `flexBasis`, `flexGrow`, `flexShrink`, `flex`
- **Block:** `border`, `radius`, `shadow`, `outline`, `padding`, `paddingInline`, `paddingBlock`, `overflow`, `scrollbar`, `textAlign`
- **Color:** `color`, `fill`, `fade`, `image`
- **Flow:** `flow`, `placeItems`, `placeContent`, `alignItems`, `alignContent`, `justifyItems`, `justifyContent`, `align`, `justify`, `gap`, `columnGap`, `rowGap`, `gridColumns`, `gridRows`, `gridTemplate`, `gridAreas`

### Modifiers

The `mods` property on the tooltip accepts the following modifiers you can override:

- **`material`** `boolean` — Enables material-style tooltip with pointer events
- **`light`** `boolean` — Uses light color scheme instead of dark
- **`open`** `boolean` — Indicates whether the tooltip is currently visible

## Usage Patterns

### Standard Pattern (Active Elements)

For focusable and hoverable elements like `Button`, `Link`, `IconButton`, etc., use the standard pattern with `TooltipProvider`:

```jsx
<TooltipProvider title="Click to save">
  <Button>Save</Button>
</TooltipProvider>
```

Or with `TooltipTrigger`:

```jsx
<TooltipTrigger>
  <Button>Save</Button>
  <Tooltip>Click to save</Tooltip>
</TooltipTrigger>
```

### Function Pattern (Non-Focusable Elements)

For elements that don't have native DOM focus or hover support (like `div`, `span`, or custom components), use the function-as-child pattern:

```jsx
<TooltipProvider title="Additional information">
  {(triggerProps, ref) => (
    <div ref={ref} {...triggerProps}>
      Hoverable content
    </div>
  )}
</TooltipProvider>
```

With `TooltipTrigger`:

```jsx
<TooltipTrigger>
  {(triggerProps, ref) => (
    <span ref={ref} {...triggerProps}>
      Custom element
    </span>
  )}
  <Tooltip>Tooltip content</Tooltip>
</TooltipTrigger>
```

### Different Placements

Control where the tooltip appears relative to its trigger:

```jsx
<TooltipProvider title="Tooltip on the right" placement="right">
  <Button>Hover me</Button>
</TooltipProvider>
```

### Light Theme

Use the light theme for tooltips on dark backgrounds:

```jsx
<TooltipProvider title="Light tooltip" isLight>
  <Button>Hover me</Button>
</TooltipProvider>
```

### Custom Delay

Adjust how long the user must hover before the tooltip appears:

```jsx
<TooltipProvider title="Quick tooltip" delay={100}>
  <Button>Fast tooltip</Button>
</TooltipProvider>

<TooltipProvider title="Slower tooltip" delay={1000}>
  <Button>Slow tooltip</Button>
</TooltipProvider>
```

### Custom Styling

Customize the appearance of the tooltip:

```jsx
<TooltipProvider
  title="Styled tooltip"
  tooltipStyles={{
    fill: '#purple',
    color: '#white',
    padding: '1.5x 2x',
  }}
>
  <Button>Custom tooltip</Button>
</TooltipProvider>
```

### Controlled Tooltip

Programmatically control when the tooltip is shown:

```jsx
function ControlledExample() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <TooltipProvider
      title="Controlled tooltip"
      isOpen={isOpen}
      onOpenChange={setIsOpen}
    >
      <Button onClick={() => setIsOpen(!isOpen)}>
        Toggle tooltip
      </Button>
    </TooltipProvider>
  );
}
```

### Conditional Tooltip

Show a tooltip only when certain conditions are met:

```jsx
<TooltipProvider title={hasError ? "Fix errors first" : null}>
  <Button isDisabled={hasError}>Submit</Button>
</TooltipProvider>
```

### Focus-Only Trigger

Show tooltip only on focus, not on hover:

```jsx
<TooltipProvider title="Focus only" trigger="focus">
  <Button>Focus me</Button>
</TooltipProvider>
```

## Accessibility

### Keyboard Navigation

- `Tab` - Moves focus to the trigger element, showing the tooltip after the delay
- `Shift + Tab` - Moves focus away from the trigger, hiding the tooltip
- Tooltips automatically appear on focus for keyboard users

### Screen Reader Support

- Tooltips use the `tooltip` ARIA role
- Content is announced to screen readers when the tooltip appears
- The trigger element maintains proper focus management
- Tooltips are associated with their triggers via ARIA attributes

### ARIA Properties

- `aria-describedby` - Automatically set on the trigger to reference the tooltip
- All standard ARIA labeling props are supported

### Best Practices

1. **Keep it brief** - Tooltips should contain concise, supplementary information
   ```jsx
   {/* Good */}
   <TooltipProvider title="Save changes">
     <Button><IconDeviceFloppy /></Button>
   </TooltipProvider>

   {/* Avoid */}
   <TooltipProvider title="This button will save all your changes to the database and close the dialog. Make sure you review your changes before clicking.">
     <Button>Save</Button>
   </TooltipProvider>
   ```

2. **Don't hide critical information** - Never put essential information only in a tooltip
   ```jsx
   {/* Good - tooltip adds context */}
   <TooltipProvider title="Permanently delete this item">
     <Button theme="danger">Delete</Button>
   </TooltipProvider>

   {/* Avoid - essential action only in tooltip */}
   <TooltipProvider title="Delete item">
     <Button><IconX /></Button>
   </TooltipProvider>
   ```

3. **Use appropriate delays** - Default delay (250ms) works for most cases
   ```jsx
   {/* Good - default delay */}
   <TooltipProvider title="Info">
     <Button>Action</Button>
   </TooltipProvider>

   {/* Consider longer delay for dense interfaces */}
   <TooltipProvider title="Info" delay={500}>
     <IconButton><IconInfo /></IconButton>
   </TooltipProvider>
   ```

4. **Choose the right pattern** - Use function pattern only when necessary
   ```jsx
   {/* Good - standard pattern for active elements */}
   <TooltipProvider title="Click me">
     <Button>Action</Button>
   </TooltipProvider>

   {/* Good - function pattern for non-focusable elements */}
   <TooltipProvider title="Info">
     {(props, ref) => (
       <div ref={ref} {...props}>Content</div>
     )}
   </TooltipProvider>

   {/* Avoid - unnecessary function pattern */}
   <TooltipProvider title="Click me">
     {(props, ref) => (
       <Button ref={ref} {...props}>Action</Button>
     )}
   </TooltipProvider>
   ```

5. **Provide meaningful context** - Ensure tooltip text is descriptive
   ```jsx
   {/* Good */}
   <TooltipProvider title="Export as CSV">
     <IconButton><IconDownload /></IconButton>
   </TooltipProvider>

   {/* Avoid */}
   <TooltipProvider title="Click here">
     <IconButton><IconDownload /></IconButton>
   </TooltipProvider>
   ```

## Migration from activeWrap

The `activeWrap` prop is deprecated. If you're using it, migrate to the function pattern:

```jsx
{/* Before (deprecated) */}
<TooltipProvider title="Tooltip" activeWrap>
  <span>Text</span>
</TooltipProvider>

{/* After */}
<TooltipProvider title="Tooltip">
  {(props, ref) => (
    <span ref={ref} {...props}>
      Text
    </span>
  )}
</TooltipProvider>
```

## Related Components

- [Button](../actions/Button.md) - Primary use case for tooltips
- [Dialog](./Dialog.md) - For more complex interactive content
