Logo

Hover Card

Delayed hover previews for links and actions with configurable timing, positioning, styling, and RTL support.

Preview

Usage

TS

import { FrAvatarModule } from '@frame-ui-ng/components/avatar';
import { FrButtonModule } from '@frame-ui-ng/components/button';
import { FrHoverCardModule } from '@frame-ui-ng/components/hover-card';

HTML

<frame-hover-card>
  <button frButton appearance="ghost" [frHoverCardTrigger]="card" type="button">
    @angular
  </button>

  <ng-template #card="frHoverCardContent" frHoverCardContent side="bottom" align="center">
    <div frHoverCardPanel>
      <div class="flex gap-3">
        <span frAvatar>
          <span frAvatarFallback>NG</span>
        </span>
        <div>
          <p class="frame-hover-card__title">@angular</p>
          <p class="frame-hover-card__description">
            The web development framework for building modern applications.
          </p>
          <p class="frame-hover-card__meta">Joined January 2010</p>
        </div>
      </div>
    </div>
  </ng-template>
</frame-hover-card>

Examples

Basic

A basic hover card that previews content behind a trigger.

Trigger Delays

Use `openDelay` and `closeDelay` on the root to control hover timing.

Positioning

Use `side`, `align`, `sideOffset`, and `alignOffset` to place the card on any side of the trigger.

Custom Styling

Override hover-card tokens from the trigger tree to customize the overlay panel.

RTL

Hover cards inherit text direction from their surrounding context.

Token Inspector

Inspect the hover card surface, title, description, and supporting metadata.

FrameUI

@FrameUI

Reusable Angular primitives with token-first styling.

2,048 contributors

Design Tokens

Hover card tokens style the floating content shell and common text affordances while leaving nested primitives such as Avatar and Button to their own token contracts.

SCSS


  --frame-hover-card-content-width: 20rem;
  --frame-hover-card-content-padding: 1rem;
  --frame-hover-card-content-radius: var(--frame-radius-md);
  --frame-hover-card-content-bg: var(--frame-surface);
  --frame-hover-card-content-color: var(--frame-surface-foreground);
  --frame-hover-card-content-border: var(--frame-border);
  --frame-hover-card-content-shadow: var(--frame-shadow-md);
  --frame-hover-card-content-gap: 0.75rem;
  --frame-hover-card-title-color: var(--frame-foreground);
  --frame-hover-card-title-font-size: 0.875rem;
  --frame-hover-card-title-font-weight: 600;
  --frame-hover-card-description-color: var(--frame-muted-foreground);
  --frame-hover-card-description-font-size: 0.875rem;
  --frame-hover-card-meta-color: var(--frame-muted-foreground);
  --frame-hover-card-meta-font-size: 0.75rem;
  --frame-hover-card-motion-duration: 140ms;
  --frame-hover-card-motion-easing: cubic-bezier(0.16, 1, 0.3, 1);
  --frame-hover-card-motion-distance: 0.25rem;
  --frame-hover-card-motion-scale: 0.96;