# Hover Card

Preview additional context on hover or keyboard focus without forcing a full click-to-open interaction.

The Angular hover card follows the shadcn composition model with a root container for shared defaults, a trigger directive on the interactive host, and a template-backed content surface rendered through the CDK overlay.

## Import

```ts
import {
  HoverCardComponent,
  HoverCardContentDirective,
  HoverCardTriggerDirective,
} from '@edsis/component/hover-card';
import { ButtonComponent } from '@edsis/component/button';
```

## Composition

```text
HoverCard
├── [HoverCardTrigger]
└── ng-template[HoverCardContent]
```

## Basic usage

```html
<HoverCard [openDelay]="100" [closeDelay]="150">
  <button Button variant="link" [HoverCardTrigger]="profileCard">@nextjs</button>

  <ng-template HoverCardContent #profileCard="HoverCardContent">
    <div
      class="flex w-72 flex-col gap-1 rounded-lg border border-border bg-popover p-4 text-popover-foreground shadow-md"
    >
      <div class="font-semibold">@nextjs</div>
      <p class="text-sm text-muted-foreground">
        The React Framework - created and maintained by @vercel.
      </p>
      <p class="text-xs text-muted-foreground">Joined December 2021</p>
    </div>
  </ng-template>
</HoverCard>
```

## Common patterns

### Trigger delays

Use the root or trigger inputs to control when the preview opens and closes.

```html
<HoverCard [openDelay]="150" [closeDelay]="200">
  <a href="/profiles/vercel" [HoverCardTrigger]="card">Hover profile</a>
  <ng-template HoverCardContent #card="HoverCardContent">...</ng-template>
</HoverCard>
```

### Positioning

Set `side`, `align`, and `sideOffset` on the root for shared defaults or override them on an individual trigger.

```html
<HoverCard side="top" align="start" [sideOffset]="12">
  <button Button variant="outline" [HoverCardTrigger]="card">Top start</button>
  <ng-template HoverCardContent #card="HoverCardContent">...</ng-template>
</HoverCard>
```

### Interactive content

The overlay remains open while either the trigger or the rendered content is hovered or focused, so links and buttons inside the card remain usable.

```html
<HoverCard>
  <a href="/products/headphones" [HoverCardTrigger]="productCard">Wireless Headphones</a>
  <ng-template HoverCardContent #productCard="HoverCardContent">
    <div
      class="flex w-64 flex-col gap-3 rounded-lg border border-border bg-popover p-4 text-popover-foreground shadow-md"
    >
      <div>
        <div class="font-semibold">Wireless Headphones</div>
        <p class="text-sm text-muted-foreground">Noise cancelling with 30-hour battery life.</p>
      </div>
      <a Button href="/products/headphones" size="sm">View product</a>
    </div>
  </ng-template>
</HoverCard>
```

## API reference

### `HoverCardComponent`

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

### `HoverCardTriggerDirective` (`[HoverCardTrigger]`)

| Input              | Type                                     | Default             |
| ------------------ | ---------------------------------------- | ------------------- |
| `HoverCardTrigger` | `HoverCardContentDirective`              | -                   |
| `side`             | `'top' \| 'right' \| 'bottom' \| 'left'` | Inherited from root |
| `align`            | `'start' \| 'center' \| 'end'`           | Inherited from root |
| `sideOffset`       | `number`                                 | Inherited from root |
| `openDelay`        | `number`                                 | Inherited from root |
| `closeDelay`       | `number`                                 | Inherited from root |
| `disabled`         | `boolean`                                | `false`             |

Exposes `isOpen()` and `openedChange`. The host reflects `aria-expanded` and `aria-haspopup="dialog"`.

### `HoverCardContentDirective`

Use `ng-template[HoverCardContent]` with `exportAs="HoverCardContent"` to provide the overlay body.

## Styling and theming

The hover card does not force a panel shell. Apply width, border, background, radius, and elevation classes inside the projected template so the content can match compact profile cards, product previews, or custom dashboards.

Use `border-border` for visible borders and `bg-popover text-popover-foreground` for the body shell to stay aligned with the theme tokens used across the library.

## Accessibility

- Open the card from a real interactive host such as `<button>`, `<a>`, or another focusable control.
- The card opens on hover and keyboard focus, then remains available while the trigger or overlay content stays hovered or focused.
- Press `Escape` while the trigger or overlay is focused to dismiss the preview.
- Keep essential actions available outside the hover card as well; hover cards are best for supplemental context, not critical flows.

## Keyboard interactions

- `Tab` moves focus to the trigger and opens the card after the configured `openDelay`.
- `Tab` continues into focusable content inside the overlay without forcing an immediate close.
- `Shift+Tab` back to the trigger keeps the preview open.
- `Escape` closes the preview.

## Angular notes

- The root `HoverCard` provides shared defaults. Override placement or timing on an individual trigger only when one example needs different behavior.
- The content stays template-backed instead of adding a dedicated content component so the overlay body can remain fully custom.
- Because the content renders through the CDK overlay container, set `dir` on the projected body when an individual card needs RTL behavior independent of the application shell.
- If you need click-to-open behavior instead of hover and focus, use the Popover primitive instead.

## Source parity

This implementation preserves the shadcn structure, trigger delay inputs, side and alignment controls, and interactive hover path between trigger and content, while adapting the API to Angular selectors and CDK overlay primitives.
