@astroweb/tooltip
v0.1.0
Published
Production-ready tooltip package for Astro powered by Tippy.js
Maintainers
Readme
@astroweb/tooltip
Production-ready tooltip package for Astro powered by Tippy.js. Provides a first-class Astro developer experience while exposing 100% of Tippy.js capabilities.
Installation
npm install @astroweb/tooltip tippy.js
# or
pnpm add @astroweb/tooltip tippy.js
# or
yarn add @astroweb/tooltip tippy.jsRequirements:
- Astro >= 5.0.0
- tippy.js >= 6.0.0
Basic Astro Usage
Using the Tooltip Component
---
import Tooltip from '@astroweb/tooltip/Tooltip.astro';
---
<Tooltip content="This is a tooltip" placement="top">
<button>Hover me</button>
</Tooltip>Using the Directive (Requires Integration)
First, add the integration to your astro.config.mjs:
import { defineConfig } from 'astro/config';
import astrowebTooltip from '@astroweb/tooltip/integration';
export default defineConfig({
integrations: [
astrowebTooltip(),
],
});Then import the CSS in your page or layout:
---
import '@astroweb/tooltip/styles';
---Then use the directive in your components:
<button client:tooltip={{ content: 'This is a tooltip', placement: 'top' }}>
Hover me
</button>Advanced Astro Usage
All Available Props
The Tooltip component and directive accept all Tippy.js options:
---
import Tooltip from '@astroweb/tooltip/Tooltip.astro';
---
<Tooltip
content="Tooltip with HTML content"
placement="bottom"
trigger="click"
delay={[200, 0]}
interactive={true}
theme="light"
animation="fade"
arrow={true}
allowHTML={true}
>
<button>Advanced tooltip</button>
</Tooltip>Placement Options
<Tooltip content="Top" placement="top">
<button>Top</button>
</Tooltip>
<Tooltip content="Right" placement="right">
<button>Right</button>
</Tooltip>
<Tooltip content="Bottom" placement="bottom">
<button>Bottom</button>
</Tooltip>
<Tooltip content="Left" placement="left">
<button>Left</button>
</Tooltip>
<Tooltip content="Auto" placement="auto">
<button>Auto</button>
</Tooltip>Trigger Options
<!-- Default: mouseenter and focus -->
<Tooltip content="Hover or focus" trigger="mouseenter focus">
<button>Default</button>
</Tooltip>
<!-- Click to show -->
<Tooltip content="Click me" trigger="click">
<button>Click</button>
</Tooltip>
<!-- Manual control -->
<Tooltip content="Manual" trigger="manual">
<button>Manual</button>
</Tooltip>Interactive Tooltips
Interactive tooltips allow users to interact with the tooltip content:
<Tooltip
content="<p>You can <strong>interact</strong> with this tooltip</p>"
interactive={true}
allowHTML={true}
placement="top"
>
<button>Interactive tooltip</button>
</Tooltip>HTML Content
To render HTML in tooltips, set allowHTML={true}:
<Tooltip
content="<strong>Bold</strong> and <em>italic</em> text"
allowHTML={true}
placement="top"
>
<button>HTML tooltip</button>
</Tooltip>Security Note: Only use allowHTML with trusted content to prevent XSS attacks.
Astro Component Content
You can pass an Astro component as tooltip content using the content slot:
---
import Tooltip from '@astroweb/tooltip/Tooltip.astro';
import MyCustomComponent from './MyCustomComponent.astro';
---
<Tooltip placement="top" interactive={true}>
<button>Hover for component tooltip</button>
<Fragment slot="content">
<MyCustomComponent />
</Fragment>
</Tooltip>Or with inline content:
<Tooltip placement="top">
<button>Hover me</button>
<div slot="content">
<h3>Custom Tooltip</h3>
<p>This tooltip contains custom Astro components and markup.</p>
</div>
</Tooltip>The slot content is rendered server-side and passed to Tippy.js as an HTMLElement, allowing you to use any Astro component or markup in your tooltips.
Custom Themes
<Tooltip content="Custom theme" theme="light" placement="top">
<button>Light theme</button>
</Tooltip>Delays
<!-- Show delay only -->
<Tooltip content="Delayed" delay={500} placement="top">
<button>500ms delay</button>
</Tooltip>
<!-- Show and hide delays -->
<Tooltip content="Delayed" delay={[200, 100]} placement="top">
<button>200ms show, 100ms hide</button>
</Tooltip>Programmatic API
For programmatic control, use the client runtime:
---
import { createTooltip } from '@astroweb/tooltip/client';
---
<button id="my-button">Programmatic tooltip</button>
<script>
import { createTooltip } from '@astroweb/tooltip/client';
const button = document.getElementById('my-button');
if (button) {
const tooltip = createTooltip({
element: button,
content: 'Created programmatically',
placement: 'top',
});
// Control the tooltip
tooltip.show();
// tooltip.hide();
// tooltip.destroy();
}
</script>Accessing Tippy Instance
You can access the raw Tippy.js instance for full control:
import { createTooltip } from '@astroweb/tooltip/client';
const tooltip = createTooltip({
element: document.querySelector('button'),
content: 'Hello',
});
// Access the Tippy instance directly
const tippyInstance = tooltip.instance;
// Use any Tippy.js method
tippyInstance.setProps({ placement: 'bottom' });
tippyInstance.show();Initializing from Data Attributes
You can also initialize tooltips from data attributes:
<button
data-tooltip="Tooltip content"
data-tooltip-placement="top"
data-tooltip-trigger="click"
data-tooltip-interactive="true"
>
Data attribute tooltip
</button>
<script>
import { initTooltips } from '@astroweb/tooltip/client';
initTooltips();
</script>Plain HTML Usage
This package works in plain HTML without Astro:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="node_modules/tippy.js/dist/tippy.css">
</head>
<body>
<button
data-tooltip="Hello from HTML"
data-tooltip-placement="top"
>
Hover me
</button>
<script type="module">
import { initTooltips } from '@astroweb/tooltip/client';
initTooltips();
</script>
</body>
</html>SSR Behavior
This package is SSR-safe and follows Astro's HTML-first philosophy:
- Server-side rendering: Tooltip markup renders as valid HTML without JavaScript
- Progressive enhancement: Tooltips are initialized on the client after the DOM is ready
- Zero-JS by default: No JavaScript is executed unless tooltips are actually used
- Idempotent initialization: Safe to call initialization functions multiple times
The Tooltip component renders a wrapper div with data attributes. The tooltip functionality is added via client-side JavaScript that runs after the page loads.
DOM Structure
By default, tooltips are appended to document.body (just before the closing </body> tag) to avoid z-index stacking context issues. This ensures tooltips always appear above other content regardless of the parent element's z-index.
You can override this behavior by explicitly setting the appendTo option:
<Tooltip
content="Custom append location"
appendTo={() => document.querySelector('#my-container')}
>
<button>Button</button>
</Tooltip>Styling & Theming
Default Styles
Import Tippy.js base CSS in your page or layout:
---
import '@astroweb/tooltip/styles';
---
<Tooltip content="Styled tooltip">
<button>Button</button>
</Tooltip>Custom Themes
Create custom themes using CSS:
.tippy-box[data-theme~='custom'] {
background-color: #333;
color: #fff;
border-radius: 8px;
}
.tippy-box[data-theme~='custom'][data-placement^='top'] > .tippy-arrow::before {
border-top-color: #333;
}Then use the theme:
<Tooltip content="Custom theme" theme="custom">
<button>Button</button>
</Tooltip>Overriding Default Styles
You can override Tippy.js styles globally:
.tippy-box {
background-color: #your-color;
color: #your-text-color;
}
.tippy-arrow {
color: #your-color;
}Performance Notes
- Lazy initialization: Tooltips are only initialized when needed
- Tree-shakable: Unused code is eliminated during build
- No framework overhead: Works without React, Vue, or Svelte
- Minimal runtime: Only loads Tippy.js when tooltips are used
- Idempotent: Safe to initialize multiple times without creating duplicate instances
For best performance:
- Use the component API for simple tooltips
- Use the directive API for better tree-shaking
- Use the programmatic API only when you need dynamic control
- Avoid initializing tooltips on elements that are frequently created/destroyed
TypeScript Support
Full TypeScript support is included. All Tippy.js types are re-exported:
import type {
TippyProps,
TippyInstance,
TippyLifecycleHooks,
TooltipConfig,
CreateTooltipOptions,
} from '@astroweb/tooltip';API Reference
Tooltip Component Props
All Tippy.js Props are supported. Common ones include:
content: string | HTMLElement | ((ref: Element) => string | HTMLElement | DocumentFragment)placement: 'top' | 'bottom' | 'left' | 'right' | 'auto' | ...trigger: string (default: 'mouseenter focus')delay: number | [number, number]interactive: booleantheme: stringanimation: stringarrow: boolean | string | HTMLElementallowHTML: boolean
Client Runtime
createTooltip(options: CreateTooltipOptions): TooltipResult
Creates a tooltip instance programmatically.
initTooltips(root?: ParentNode): void
Initializes all tooltips from data attributes in the given root element.
Integration Options
interface TooltipIntegrationOptions {
injectCSS?: boolean; // Default: false
defaultProps?: Record<string, unknown>;
}License
MIT
