# Tooltip

Displays a small, supplemental text label when a focusable element receives hover or keyboard focus.

This Angular implementation now supports a composition-based tooltip surface with `Tooltip`, `[TooltipTrigger]`, and `ng-template[TooltipContent]`, while keeping the older `[Tooltip]` string directive as a lightweight shortcut for one-line hints.

## Import

```ts
import {
  TooltipComponent,
  TooltipContentDirective,
  TooltipDirective,
  TooltipTriggerDirective,
} from '@edsis/component/tooltip';
```

## Composition

```text
Tooltip
├── focusable host[TooltipTrigger]
└── ng-template[TooltipContent]

Optional convenience shortcut:
button[Tooltip]
```

## Basic usage

Use the composed surface when you want shadcn-style trigger and content structure or richer overlay content.

```html
<Tooltip [openDelay]="0">
  <ng-template TooltipContent #tooltipContent="TooltipContent">
    <span>Add to library</span>
  </ng-template>

  <button Button type="button" variant="outline" [TooltipTrigger]="tooltipContent">Hover</button>
</Tooltip>
```

## Common patterns

### Side and alignment

Use `side="top|right|bottom|left"` and `align="start|center|end"` on `[TooltipTrigger]` to control placement.

```html
<Tooltip side="top" [openDelay]="0">
  <ng-template TooltipContent #startContent="TooltipContent">
    <span>Start aligned tooltip</span>
  </ng-template>

  <button Button type="button" variant="outline" [TooltipTrigger]="startContent" align="start">
    Start
  </button>
</Tooltip>
```

### Rich content

The overlay template can include small layout fragments, emphasized text, or keyboard shortcut chips.

```html
<Tooltip [openDelay]="0">
  <ng-template TooltipContent #shortcutContent="TooltipContent">
    <span class="inline-flex items-center gap-1.5">
      Save changes
      <kbd
        class="border-primary-foreground/30 bg-primary-foreground/10 text-primary-foreground shadow-none"
      >
        Cmd
      </kbd>
      <kbd
        class="border-primary-foreground/30 bg-primary-foreground/10 text-primary-foreground shadow-none"
      >
        S
      </kbd>
    </span>
  </ng-template>

  <button Button type="button" variant="outline" [TooltipTrigger]="shortcutContent">Save</button>
</Tooltip>
```

### Disabled buttons

Disabled native buttons do not emit hover or focus events. Wrap them with a focusable element and attach `[TooltipTrigger]` to the wrapper.

```html
<Tooltip [openDelay]="0">
  <ng-template TooltipContent #disabledContent="TooltipContent">
    <span>This feature is currently unavailable</span>
  </ng-template>

  <span
    class="inline-block rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
    tabindex="0"
    [TooltipTrigger]="disabledContent"
  >
    <button Button type="button" variant="outline" disabled>Disabled</button>
  </span>
</Tooltip>
```

### Quick string API

For simple one-line hints, the original directive remains available.

```html
<button
  Button
  type="button"
  variant="outline"
  [Tooltip]="'Quick text hint'"
  TooltipPosition="above"
>
  String directive
</button>
```

### Programmatic control

Export the trigger as `TooltipTrigger` when a flow needs to open or close the composed tooltip imperatively.

```html
<Tooltip [openDelay]="0">
  <ng-template TooltipContent #saveContent="TooltipContent">
    <span>Saved</span>
  </ng-template>

  <button
    Button
    type="button"
    variant="outline"
    #saveTrigger="TooltipTrigger"
    [TooltipTrigger]="saveContent"
    (click)="saveTrigger.open()"
  >
    Save
  </button>
</Tooltip>
```

## API reference

### `TooltipComponent`

| Input        | Type                                     | Default    |
| ------------ | ---------------------------------------- | ---------- |
| `side`       | `'top' \| 'right' \| 'bottom' \| 'left'` | `'top'`    |
| `align`      | `'start' \| 'center' \| 'end'`           | `'center'` |
| `sideOffset` | `number`                                 | `4`        |
| `openDelay`  | `number`                                 | `150`      |
| `closeDelay` | `number`                                 | `0`        |

### `TooltipTriggerDirective`

| Input            | Type                                     | Notes                                               |
| ---------------- | ---------------------------------------- | --------------------------------------------------- |
| `TooltipTrigger` | `TooltipContentDirective`                | Required content template ref for the overlay body. |
| `side`           | `'top' \| 'right' \| 'bottom' \| 'left'` | Overrides the root side for this trigger.           |
| `align`          | `'start' \| 'center' \| 'end'`           | Overrides the root alignment for this trigger.      |
| `sideOffset`     | `number`                                 | Overrides the root offset for this trigger.         |
| `openDelay`      | `number`                                 | Overrides the root open delay for this trigger.     |
| `closeDelay`     | `number`                                 | Overrides the root close delay for this trigger.    |
| `disabled`       | `boolean`                                | Suppresses tooltip opening for the trigger.         |

### `TooltipTriggerDirective` methods

- `open()`: opens the composed tooltip.
- `close()`: closes the composed tooltip.

### `TooltipContentDirective`

- Applied as `ng-template[TooltipContent]`.
- Supplies the portal content rendered inside the tooltip overlay.

### `TooltipDirective`

| Input                  | Type                      | Notes                                                    |
| ---------------------- | ------------------------- | -------------------------------------------------------- |
| `Tooltip`              | `string`                  | Message rendered inside the Material tooltip overlay.    |
| `TooltipPosition`      | `TooltipPosition`         | `left`, `right`, `above`, `below`, `before`, or `after`. |
| `TooltipDisabled`      | `boolean`                 | Temporarily suppresses tooltip display.                  |
| `TooltipShowDelay`     | `number`                  | Delay in milliseconds before the tooltip opens.          |
| `TooltipHideDelay`     | `number`                  | Delay in milliseconds before the tooltip closes.         |
| `TooltipTouchGestures` | `'auto' \| 'on' \| 'off'` | Controls touch gesture behavior on mobile devices.       |

For the original primitive contract, see the Radix Tooltip API: <https://www.radix-ui.com/primitives/docs/components/tooltip#api-reference>.

## Styling and theming

The composed tooltip applies its visual shell directly on the overlay pane and keeps the stable `tooltip-panel` class hook.

Projected content inherits the library theme tokens, so small layout helpers such as `inline-flex`, gap utilities, and subtle emphasis classes can be used without rebuilding the panel wrapper.

The string directive continues to force the `tooltip-panel` class on the Material tooltip overlay for backward-compatible styling.

## Accessibility

- The composed overlay pane uses `role="tooltip"`.
- Trigger hosts receive `aria-describedby` while the tooltip is open.
- Tooltip content should stay supplemental and should not be the only place that important instructions live.
- Use focusable hosts so keyboard users can reveal the tooltip without relying on hover.
- Disabled controls still need a focusable wrapper if you expect keyboard users to reach the explanation.

## Keyboard interactions

- Focusing the trigger opens the tooltip after the configured delay.
- Moving focus away closes it again.
- Pressing Escape closes the currently open composed tooltip.
- Native hosts keep their default Enter and Space behavior.

## Angular notes

- Prefer the composition-based surface when you need richer content or closer shadcn parity.
- Keep the string directive for quick one-line hints or for existing code that already relies on `MatTooltip` semantics.
- The composed trigger is exported as `TooltipTrigger`, so template refs can call `open()` and `close()` directly.
- For interactive overlay content, use Popover or Hover Card instead of Tooltip.

## Source parity

This Angular version now mirrors the shadcn runtime more closely with an explicit root, trigger, and content surface while preserving a compact Angular convenience directive for minimal text hints.
