Help Tooltip
Click the icon trigger to reveal a balloon with a title, message, and leading icon chip. Click again, click outside, scroll, or press Escape to dismiss.
<span class="nds-tooltip">
<button type="button" class="nds-tooltip-trigger" aria-label="What is this?">
<span class="nds-feedback nds-sm" data-status="help">
<span class="nds-feedback-icon">
<i class="nds-icon" aria-hidden="true"></i>
</span>
</span>
</button>
<div class="nds-tooltip-balloon" hidden>
<span class="nds-feedback nds-sm" data-status="help">
<span class="nds-feedback-icon">
<i class="nds-icon" aria-hidden="true"></i>
</span>
</span>
<span class="nds-tooltip-body">
<span class="nds-tooltip-title">Tooltip title</span>
<p class="nds-tooltip-message">Max width of tooltips is 240px - text will wrap automatically</p>
</span>
</div>
</span>
Declarative Markup
Skip the inner DOM. Put data-tooltip-title and data-tooltip-message on a .nds-tooltip element. If the element is empty, the JS generates a chip trigger. If it already has text or children, the element itself acts as the trigger and only the balloon is generated.
<span class="nds-tooltip"
data-tooltip-title="Declarative tooltip"
data-tooltip-message="This balloon was generated from data-tooltip-title/message by the JS."></span>
The National ID field is required.
<p>
The
<span class="nds-tooltip"
data-tooltip-message="A 10-digit identifier issued to Saudi citizens by the Ministry of Interior.">National ID</span>
field is required.
</p>
Message Only
Omit the title when a single short sentence is enough. The icon chip can also be dropped for a minimal body-only balloon.
<span class="nds-tooltip">
<button type="button" class="nds-tooltip-trigger" aria-label="More info">
<span class="nds-feedback nds-sm" data-status="help">
<span class="nds-feedback-icon">
<i class="nds-icon" aria-hidden="true"></i>
</span>
</span>
</button>
<div class="nds-tooltip-balloon" hidden>
<span class="nds-tooltip-body">
<p class="nds-tooltip-message">Saudi residents can enter either their National ID or their Iqama number.</p>
</span>
</div>
</span>
Built-in Features
Every .nds-tooltip in the DOM wires itself up on page load. Click handlers, aria-describedby, and unique IDs are applied automatically.
Add data-tooltip-title and data-tooltip-message to an empty .nds-tooltip and the JS generates the trigger chip and balloon for you.
Balloons use fixed positioning so they escape clipping parents. They flip above the trigger when there is not enough room below and clamp horizontally to stay fully visible.
The feedback chip picks up its glyph and color from data-status: help, info, success, warning, error, or neutral.
Balloon surface, heading, and body text all swap to the inverse token set when the page is in dark theme, with no markup changes required.
Close by clicking the trigger again, clicking anywhere outside, pressing Escape, or scrolling the page. Only one tooltip stays open at a time.
Open, close, and observe any tooltip through the NDS.Tooltip API or the instance attached to each element.
Each balloon gets a unique id and the trigger's aria-describedby points to it, so screen readers announce the content when focus lands on the trigger.
Usage Guidelines
Best Practices
- Use tooltips to clarify unfamiliar terms or offer short, optional context next to the element they explain (form field labels, table headers, policy terms)
- For simple help text, prefer the declarative shortcut: put
data-tooltip-titleanddata-tooltip-messageon an empty.nds-tooltipand let the JS build the chip and balloon. Write the full markup only when you need rich HTML or custom content inside the body - Use the help status for advisory tips, info for neutral clarification, warning or error to call attention to a caveat next to a field
- Place the trigger immediately adjacent to the term it describes so the relationship is obvious, not buried in a label row
- Do not put essential instructions inside a tooltip: anything a user must read to complete the task belongs in the visible label, placeholder, or hint text
- Do not wrap a link or navigation element as the trigger: clicking would both follow the link and try to toggle the tooltip. Place the tooltip next to the link instead
- Prefer an Alert for non-dismissable status messages and a Modal for content that requires a user decision
- Keep the message to one or two sentences. The balloon clamps at 240px by default and wraps text automatically
- Include a short
aria-labelon the trigger button so screen reader users hear what the tooltip explains even before opening it - If many tooltips cluster in a dense form, consider moving the content into inline helper text: excessive clicking breaks flow for keyboard and touch users
Structure
A tooltip has three structural parts inside a <span class="nds-tooltip"> root.
| Class | Role |
|---|---|
nds-tooltip | Inline root wrapping the trigger and the balloon. JS toggles data-state="open" on this element while the balloon is visible. |
nds-tooltip-trigger | The clickable element. A <button> wrapping an .nds-feedback-icon chip is the canonical pattern. |
nds-tooltip-balloon | The floating panel. Marked hidden by default; JS toggles the attribute on open. |
nds-tooltip-body | Text container inside the balloon. Sits beside the optional leading icon chip. |
nds-tooltip-title | Optional bold heading placed at the top of the body stack. |
nds-tooltip-message | The body paragraph text. |
Data Attributes
| Attribute | Description |
|---|---|
data-tooltip-title | Declarative shortcut. Set on .nds-tooltip to have the JS generate the balloon title. Skipped when an explicit .nds-tooltip-balloon child is present. |
data-tooltip-message | Declarative shortcut. Set on .nds-tooltip to have the JS generate the balloon message paragraph. Either title or message (or both) is required for auto-generation to run. |
data-tooltip-status | Declarative shortcut. Set on .nds-tooltip to control the generated chips' status (defaults to help). Values match data-status. |
data-status | Set on the inner .nds-feedback wrappers (inside the trigger and inside the balloon) to drive icon glyph and color. Values: help, info, success, warning, error, neutral. Do not put data-status on .nds-tooltip itself. |
data-state | Managed by JS on .nds-tooltip. Set to open while the balloon is visible; absent when closed. Used internally for CSS styling hooks (e.g. the idle-trigger neutral background). |
hidden | Set on .nds-tooltip-balloon in source so the balloon starts closed. JS flips the attribute on open and close. |
aria-label | Set on .nds-tooltip-trigger to describe the tooltip purpose for screen readers (e.g. "What is this?"). |
CSS Custom Properties
| Property | Default | Description |
|---|---|---|
--tooltip-max-width | 240px | Clamp on balloon width. Text wraps automatically beyond this. |
--tooltip-padding | var(--spacing-2) | Inner padding around the balloon content. |
--tooltip-gap | var(--spacing-2) | Gap between the icon chip and the body, and between title and message. |
--tooltip-arrow-size | 10px | Side length of the rotated arrow square. |
--tooltip-background-light | var(--colors-base-white) | Balloon surface color in light theme. |
--tooltip-background-dark | var(--colors-neutral-800) | Balloon surface color in dark theme. |
--tooltip-text-heading-light | var(--text-display) | Title color in light theme. |
--tooltip-text-paragraph-light | var(--text-primary-paragraph) | Message body color in light theme. |
JavaScript API
The NDS.Tooltip namespace exposes initialization and factory methods. Every initialized tooltip also attaches an instance to its root element at el.ndsTooltip, with open() and close() methods. Tooltips dispatch nds:tooltip:opened and nds:tooltip:closed events that bubble to the document.