hover-card

Rich hover preview cards

Use ng-hover-card with a keyboard-focusable trigger and preview content. Pointer disclosure honors optional open-delay and close-delay values in milliseconds. Set side on the content to left, top, bottom, or right.

<span ng-hover-card open-delay="100" close-delay="100">
  <a href="#">@angularcss</a>
  <aside side="bottom">Preview</aside>
</span>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Hover Card</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="hover-card-demo">
    <main class="visual-example">
      <span ng-hover-card open-delay="10" close-delay="100">
        <button type="button" variant="link">Hover Here</button>
        <aside>
          <h3>@nextjs</h3>
          <p>The React Framework - created and maintained by @vercel.</p>
          <footer>Joined December 2021</footer>
        </aside>
      </span>
    </main>
  </body>
</html>

Physical sides

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Hover Card Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="hover-card-sides">
    <main class="hover-card-workflow">
      <header class="hover-card-workflow-header">
        <h2>Physical sides</h2>
      </header>
      <div class="hover-card-side-grid">
        <section class="hover-card-stage hover-card-stage-left">
          <span ng-hover-card open-delay="20" close-delay="100">
            <button type="button" variant="outline">Left</button>
            <aside side="left">
              <h3>Hover Card</h3>
              <p>This hover card appears on the left side of the trigger.</p>
            </aside>
          </span>
        </section>

        <section class="hover-card-stage hover-card-stage-top">
          <span ng-hover-card open-delay="20" close-delay="100">
            <button type="button" variant="outline">Top</button>
            <aside side="top">
              <h3>Hover Card</h3>
              <p>This hover card appears on the top side of the trigger.</p>
            </aside>
          </span>
        </section>

        <section class="hover-card-stage hover-card-stage-bottom">
          <span ng-hover-card open-delay="20" close-delay="100">
            <button type="button" variant="outline">Bottom</button>
            <aside side="bottom">
              <h3>Hover Card</h3>
              <p>This hover card appears on the bottom side of the trigger.</p>
            </aside>
          </span>
        </section>

        <section class="hover-card-stage hover-card-stage-right">
          <span ng-hover-card open-delay="20" close-delay="100">
            <button type="button" variant="outline">Right</button>
            <aside side="right">
              <h3>Hover Card</h3>
              <p>This hover card appears on the right side of the trigger.</p>
            </aside>
          </span>
        </section>
      </div>

      <footer class="hover-card-disabled-example">
        <span ng-hover-card open-delay="0" close-delay="0">
          <button type="button" variant="outline" disabled>Disabled</button>
          <aside>
            <p>Unavailable preview</p>
          </aside>
        </span>
      </footer>
    </main>
  </body>
</html>

Right-to-left

Physical left and right placement stays physical while text direction and content alignment follow the nearest authored dir attribute.

View source
<!doctype html>
<html lang="ar" dir="rtl">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Hover Card Rtl</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="hover-card-rtl">
    <main class="hover-card-workflow" dir="rtl">
      <header class="hover-card-workflow-header">
        <h2>الجوانب الفعلية</h2>
      </header>
      <div class="hover-card-side-grid">
        <section class="hover-card-stage hover-card-stage-left">
          <span ng-hover-card open-delay="20" close-delay="100">
            <button type="button" variant="outline">يسار</button>
            <aside side="left">
              <h3>سماعات لاسلكية</h3>
              <p>٩٩.٩٩ $</p>
            </aside>
          </span>
        </section>

        <section class="hover-card-stage hover-card-stage-top">
          <span ng-hover-card open-delay="20" close-delay="100">
            <button type="button" variant="outline">أعلى</button>
            <aside side="top">
              <h3>سماعات لاسلكية</h3>
              <p>٩٩.٩٩ $</p>
            </aside>
          </span>
        </section>

        <section class="hover-card-stage hover-card-stage-bottom">
          <span ng-hover-card open-delay="20" close-delay="100">
            <button type="button" variant="outline">أسفل</button>
            <aside side="bottom">
              <h3>سماعات لاسلكية</h3>
              <p>٩٩.٩٩ $</p>
            </aside>
          </span>
        </section>

        <section class="hover-card-stage hover-card-stage-right">
          <span ng-hover-card open-delay="20" close-delay="100">
            <button type="button" variant="outline">يمين</button>
            <aside side="right">
              <h3>سماعات لاسلكية</h3>
              <p>٩٩.٩٩ $</p>
            </aside>
          </span>
        </section>
      </div>
    </main>
  </body>
</html>

Installation

Install AngularCSS, load its stylesheet, and include the angular.css module in your AngularTS application. See Installation for the complete setup.

This component’s root directive is [ng-hover-card]. Importing the package registers it with the AngularCSS angular.css module; there is no per-component JavaScript registration step.

Anatomy

Directive selectors

  • ng-hover-card

Semantic structure

A keyboard-focusable trigger and one preview content element are required. Title and description slots are optional semantic styling hooks inside the preview.

API

Attributes and state

AttributeAccessPurpose
aria-controlsOutputID of the element controlled by a trigger.
aria-expandedOutputOpen or expanded state exposed to assistive technology.
aria-hiddenOutputWhether generated or collapsed content is hidden from assistive technology.
close-delayInputPointer close delay in milliseconds.
openInputInitial or controlled open state.
open-delayInputPointer open delay in milliseconds.
sideInput/outputPhysical placement: left, top, bottom, or right.

Input attributes are read from authored HTML. Output attributes are maintained by AngularCSS for CSS and testing. Input/output attributes may be authored for a controlled initial state and are then synchronized by the directive.

CSS custom properties

This directive does not write component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

The directive owns delayed pointer and focus disclosure, physical side placement, Escape closure, and synchronized open state. It is non-modal and does not trap focus. Applications own preview content and may control the concise authored open attribute.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

The trigger exposes aria-controls and aria-expanded; the preview exposes its hidden state without becoming modal. Keep the trigger keyboard focusable, preserve readable content order, and do not place essential information only inside a hover card.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target [ng-hover-card], semantic descendants, component classes, and generated state with ordinary CSS. Keep behavior and accessible state in the TypeScript directive; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.