Tooltips
A complete tooltip system built on Floating UI with custom SDS styling and automatic initialization.
Features
- 🎨 Custom SDS Theme - Matches design system colors
- ⚡ Performance Optimized - Delegation pattern handles thousands of tooltips efficiently
- 🔄 Astro View Transitions - Automatic re-initialization on navigation
- 🎯 Simple API - Just add a data attribute
- 📦 Bundled - No need to install Floating UI separately in your project
- 🔍 SEO Friendly - Content rendered in HTML, enhanced progressively
- 🪶 Lightweight - ~3 KB gzip (Floating UI) vs ~14 KB (tippy.js + popper)
Installation
Step 1: Create a tooltip initialization script
In your project, create a script file (e.g., src/scripts/tooltips.ts):
That’s it! This single import includes:
- ✅ Floating UI positioning engine
- ✅ SDS tooltip CSS
- ✅ Auto-initialization logic
- ✅ Astro View Transitions support
Step 2: Import in your layout
Add the script to your main layout’s <head>:
Usage
Basic Tooltip
Add the data-sds-tooltip attribute to any element:
HTML Content
Tooltips support HTML content:
HTML tooltip
Structured Tooltips
For complex tooltips with headers and multiple sections:
Product Info
Custom Placement
Override the default top placement per element:
Supported placements: top, bottom, left, right, top-start, top-end, bottom-start, bottom-end, left-start, left-end, right-start, right-end.
Components with Built-in Tooltips
These SDS components automatically include tooltips:
ProductEngine & ProductEngines
Engine codes with detailed specification tooltips:
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="astro"><code><span class="line"><span style="color:#E1E4E8">import { ProductEngines } from 'spoko-design-system';</span></span> <span class="line"></span> <span class="line"><span style="color:#E1E4E8"><</span><span style="color:#79B8FF">ProductEngines</span><span style="color:#B392F0"> engines</span><span style="color:#E1E4E8">={product.part_engines} /></span></span></code></pre>See ProductEngine documentation for details.
ProductCodes
PR codes with description tooltips (when available):
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="astro"><code><span class="line"><span style="color:#E1E4E8">import { ProductCodes } from 'spoko-design-system';</span></span> <span class="line"></span> <span class="line"><span style="color:#E1E4E8"><</span><span style="color:#79B8FF">ProductCodes</span><span style="color:#B392F0"> prcodes</span><span style="color:#E1E4E8">={product.pr_codes} </span><span style="color:#B392F0">isPdp</span><span style="color:#E1E4E8">={</span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8">} /></span></span></code></pre>Styling
SDS Theme
The default SDS theme uses these design tokens:
| Property | Value | Token |
|---|---|---|
| Background | #f3f4f6 |
neutral-lightest |
| Text Color | #1e293b |
slate-darkest |
| Border | #e5e7eb |
neutral-lighter |
| Header Background | #001e50 |
accent-deepBlue |
| Max Width | 280px |
- |
| Border Radius | 0.5rem |
- |
Custom Styling
To customize the tooltip appearance, override these CSS classes:
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code><span class="line"><span style="color:#6A737D">/* Main tooltip box */</span></span> <span class="line"><span style="color:#B392F0">.sds-tooltip</span><span style="color:#E1E4E8"> {</span></span> <span class="line"><span style="color:#79B8FF"> background-color</span><span style="color:#E1E4E8">: your-color;</span></span> <span class="line"><span style="color:#79B8FF"> color</span><span style="color:#E1E4E8">: your-text-color;</span></span> <span class="line"><span style="color:#E1E4E8">}</span></span> <span class="line"></span> <span class="line"><span style="color:#6A737D">/* Tooltip content area */</span></span> <span class="line"><span style="color:#B392F0">.sds-tooltip-content</span><span style="color:#E1E4E8"> {</span></span> <span class="line"><span style="color:#79B8FF"> padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.5</span><span style="color:#F97583">rem</span><span style="color:#79B8FF"> 0.75</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span> <span class="line"><span style="color:#E1E4E8">}</span></span> <span class="line"></span> <span class="line"><span style="color:#6A737D">/* Structured tooltip header */</span></span> <span class="line"><span style="color:#B392F0">.sds-tooltip</span><span style="color:#B392F0"> .tooltip-header</span><span style="color:#E1E4E8"> {</span></span> <span class="line"><span style="color:#79B8FF"> background-color</span><span style="color:#E1E4E8">: your-header-color;</span></span> <span class="line"><span style="color:#79B8FF"> color</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">white</span><span style="color:#E1E4E8">;</span></span> <span class="line"><span style="color:#79B8FF"> padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.375</span><span style="color:#F97583">rem</span><span style="color:#79B8FF"> 0.5</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span> <span class="line"><span style="color:#E1E4E8">}</span></span> <span class="line"></span> <span class="line"><span style="color:#6A737D">/* Tooltip specs rows */</span></span> <span class="line"><span style="color:#B392F0">.sds-tooltip</span><span style="color:#B392F0"> .tooltip-row</span><span style="color:#E1E4E8"> {</span></span> <span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">flex</span><span style="color:#E1E4E8">;</span></span> <span class="line"><span style="color:#79B8FF"> justify-content</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">space-between</span><span style="color:#E1E4E8">;</span></span> <span class="line"><span style="color:#79B8FF"> padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.25</span><span style="color:#F97583">rem</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">;</span></span> <span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>Available CSS Classes
For structured tooltips:
| Class | Purpose |
|---|---|
.tooltip-header |
Dark blue header section |
.tooltip-specs |
Container for specification rows |
.tooltip-row |
Single specification row |
.tooltip-label |
Left-aligned label text |
.tooltip-value |
Right-aligned value text |
Configuration
The tooltip system uses these default settings:
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#E1E4E8">{</span></span> <span class="line"><span style="color:#B392F0"> selector</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">'[data-sds-tooltip]'</span><span style="color:#E1E4E8">, </span><span style="color:#6A737D">// Target selector</span></span> <span class="line"><span style="color:#B392F0"> placement</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">'top'</span><span style="color:#E1E4E8">, </span><span style="color:#6A737D">// Default placement</span></span> <span class="line"><span style="color:#B392F0"> offset</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">8</span><span style="color:#E1E4E8">, </span><span style="color:#6A737D">// Gap between trigger and tooltip (px)</span></span> <span class="line"><span style="color:#B392F0"> maxWidth</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">280</span><span style="color:#E1E4E8">, </span><span style="color:#6A737D">// Maximum width (px)</span></span> <span class="line"><span style="color:#B392F0"> showDelay</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">80</span><span style="color:#E1E4E8">, </span><span style="color:#6A737D">// Delay before showing (ms)</span></span> <span class="line"><span style="color:#B392F0"> hideDelay</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">60</span><span style="color:#E1E4E8">, </span><span style="color:#6A737D">// Delay before hiding (ms)</span></span> <span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>Floating UI middleware used:
offset(8)— gap between trigger and tooltipflip()— flips placement when insufficient spaceshift({ padding: 5 })— shifts along axis to stay in viewportarrow()— positions the arrow element
Technical Details
Delegation Pattern
The tooltip system uses event delegation:
- Single event listener on
bodyhandles all tooltips - No re-initialization needed when DOM changes
- Efficient memory usage - one shared tooltip element reused for all triggers
- Dynamic content support - works with client-side rendering
How It Works
- Global event listeners on
body(capture phase) watch formouseenter/mouseleave/focusin/focusout - When user hovers over a
[data-sds-tooltip]element, a single shared tooltip element is positioned using Floating UI’scomputePosition autoUpdatekeeps the tooltip position in sync during scroll/resize- On mouse leave, tooltip fades out and cleanup runs
Astro View Transitions
The system automatically handles Astro’s View Transitions:
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#E1E4E8">document.</span><span style="color:#B392F0">addEventListener</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'astro:page-load'</span><span style="color:#E1E4E8">, () </span><span style="color:#F97583">=></span><span style="color:#E1E4E8"> {</span></span> <span class="line"><span style="color:#B392F0"> initTooltips</span><span style="color:#E1E4E8">();</span></span> <span class="line"><span style="color:#E1E4E8">});</span></span> <span class="line"></span> <span class="line"><span style="color:#E1E4E8">document.</span><span style="color:#B392F0">addEventListener</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'astro:before-swap'</span><span style="color:#E1E4E8">, () </span><span style="color:#F97583">=></span><span style="color:#E1E4E8"> {</span></span> <span class="line"><span style="color:#6A737D"> // Cleanup tooltip element before page swap</span></span> <span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>This ensures tooltips work correctly after client-side navigation.
API Reference
initTooltips()
Initializes the global tooltip delegation. Safe to call multiple times — only attaches listeners once.
Import:
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { initTooltips } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> 'spoko-design-system'</span><span style="color:#E1E4E8">;</span></span></code></pre>Usage:
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#B392F0">initTooltips</span><span style="color:#E1E4E8">();</span></span></code></pre>Note: Usually not needed if you import 'spoko-design-system/scripts/tooltips' which auto-initializes.
showTooltip(target)
Programmatically show tooltip on a target element.
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { showTooltip } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> 'spoko-design-system/scripts/tooltips'</span><span style="color:#E1E4E8">;</span></span> <span class="line"></span> <span class="line"><span style="color:#B392F0">showTooltip</span><span style="color:#E1E4E8">(document.</span><span style="color:#B392F0">querySelector</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'[data-sds-tooltip]'</span><span style="color:#E1E4E8">));</span></span></code></pre>hideTooltip()
Programmatically hide the current tooltip.
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { hideTooltip } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> 'spoko-design-system/scripts/tooltips'</span><span style="color:#E1E4E8">;</span></span> <span class="line"></span> <span class="line"><span style="color:#B392F0">hideTooltip</span><span style="color:#E1E4E8">();</span></span></code></pre>getEngineTooltipContent()
Generates HTML content for engine tooltips.
Import:
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { getEngineTooltipContent } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> 'spoko-design-system'</span><span style="color:#E1E4E8">;</span></span></code></pre>Usage:
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> tooltipHTML</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> getEngineTooltipContent</span><span style="color:#E1E4E8">(engine, translations);</span></span></code></pre>Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
engine |
Engine |
Yes | Engine object with nested structure |
translations |
EngineTranslations |
No | Optional translation overrides |
Returns: HTML string for tooltip content
See ProductEngine documentation for Engine interface details.
Dependencies
SDS includes @floating-ui/dom as a dependency. Your project does not need to install it separately.
If you have tippy.js in your project’s package.json, you can safely remove it:
Troubleshooting
Tooltips not showing
Check these items:
- ✅ Script imported in layout:
<script src="/src/scripts/tooltips.ts"></script> - ✅ Elements have
data-sds-tooltipattribute - ✅ Content is not empty or “undefined”
- ✅ Hard refresh browser (Ctrl+Shift+R) to clear cache
Double tooltips or conflicts
If you see duplicate tooltips:
- Only import the tooltip script once in your layout
- Don’t call
initTooltips()manually if using auto-initialization - Remove any local
tippy.jsinstallations that might conflict
Tooltips not working after navigation
If tooltips break after Astro View Transitions:
- Verify
astro:page-loadevent listener is registered (included in SDS script) - Check browser console for errors
- Make sure View Transitions are properly configured in Astro
Styling not applied
- Verify SDS tooltip CSS is imported (included in SDS tooltip script)
- Check CSS specificity
- Ensure your build process handles CSS imports from
node_modules
Browser Support
Tooltips work in all modern browsers:
- ✅ Chrome/Edge (latest)
- ✅ Firefox (latest)
- ✅ Safari (latest)
- ✅ Mobile browsers (iOS Safari, Chrome Android)
Note: Requires JavaScript. Content is still visible if JS is disabled (progressive enhancement).
Examples
Product Specification
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="astro"><code><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">dl</span><span style="color:#E1E4E8">></span></span> <span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">dt</span><span style="color:#E1E4E8">>Weight</</span><span style="color:#85E89D">dt</span><span style="color:#E1E4E8">></span></span> <span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">dd</span><span style="color:#E1E4E8">></span></span> <span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> data-sds-tooltip</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"Includes packaging"</span><span style="color:#E1E4E8">></span></span> <span class="line"><span style="color:#E1E4E8"> 2.5 kg</span></span> <span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span> <span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">dd</span><span style="color:#E1E4E8">></span></span> <span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">dl</span><span style="color:#E1E4E8">></span></span></code></pre>Help Icons
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="astro"><code><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">label</span><span style="color:#E1E4E8">></span></span> <span class="line"><span style="color:#E1E4E8"> Email</span></span> <span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span></span> <span class="line"><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"inline-block ml-1 text-gray-400 cursor-help"</span></span> <span class="line"><span style="color:#B392F0"> data-sds-tooltip</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"We'll never share your email"</span><span style="color:#E1E4E8">></span></span> <span class="line"><span style="color:#E1E4E8"> ⓘ</span></span> <span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span> <span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">label</span><span style="color:#E1E4E8">></span></span></code></pre>Technical Terms
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="astro"><code><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span> <span class="line"><span style="color:#E1E4E8"> The part fits all</span></span> <span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">abbr</span></span> <span class="line"><span style="color:#B392F0"> data-sds-tooltip</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"Volkswagen Aktiengesellschaft Group"</span></span> <span class="line"><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"cursor-help underline decoration-dotted"</span><span style="color:#E1E4E8">></span></span> <span class="line"><span style="color:#E1E4E8"> VAG</span></span> <span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">abbr</span><span style="color:#E1E4E8">></span></span> <span class="line"><span style="color:#E1E4E8"> vehicles from 2009-2014.</span></span> <span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>Best Practices
Do
- Use semantic HTML with tooltips as enhancement
- Keep tooltip content concise (< 50 words)
- Use structured tooltips for multiple data points
- Include proper ARIA labels when needed
- Test on mobile devices
Don’t
- Put critical information only in tooltips
- Use tooltips for large blocks of text
- Nest interactive elements inside hover tooltips (use click trigger instead)
- Initialize tooltips multiple times
Migration from tippy.js
If migrating from a tippy.js implementation:
- Remove
tippy.jsfrom yourpackage.json - Update SDS to latest version
- Replace
data-tippy-contentwithdata-sds-tooltipon all elements - Update custom styles from
.tippy-box[data-theme~='sds']to.sds-tooltip - Remove any tippy.js imports or initialization code
Related Documentation
- ProductEngine Component - Engine codes with tooltips
- ProductCodes Component - PR codes with tooltips
- Floating UI Documentation - Positioning engine