Playground
A short hint that appears on hover and keyboard focus, with a small pixel arrow. Wrap any trigger element.
Examples
Placement
<div style="display: flex; gap: 24px; padding-block: 48px">
<sb-tooltip content="Top" placement="top"><sb-button variant="outline" size="sm">Top</sb-button></sb-tooltip>
<sb-tooltip content="Bottom" placement="bottom"><sb-button variant="outline" size="sm">Bottom</sb-button></sb-tooltip>
<sb-tooltip content="Left" placement="left"><sb-button variant="outline" size="sm">Left</sb-button></sb-tooltip>
<sb-tooltip content="Right" placement="right"><sb-button variant="outline" size="sm">Right</sb-button></sb-tooltip>
</div>
Dynamic content
content is a normal attribute, so data-attr keeps it live.
<div data-signals:_fuel="72" style="padding-block-start: 48px">
<sb-tooltip data-attr:content="'Fuel: ' + $_fuel + '%'">
<sb-button size="sm" data-on:click="$_fuel = Math.max(0, $_fuel - 9)">Burn fuel</sb-button>
</sb-tooltip>
</div>
Accessibility
The tooltip shows on focus as well as hover, and Escape dismisses it. Keep tooltips short and supplementary: never put the only copy of important information in one.
Installation
Add Datastar with Rocket and the Starbase autoloader once per page, then use the tag. The autoloader imports each component the first time its tag appears, including tags added later by a Datastar morph.
<!-- Once per page: Datastar with Rocket, and the Starbase autoloader.
It loads every <sb-…> component the first time its tag appears. -->
<script type="importmap">
{ "imports": { "datastar": "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.4/bundles/datastar-rocket.js" } }
</script>
<script type="module" src="https://starbase.zweiundeins.gmbh/c/autoloader.js"></script>
<!-- Optional, no flash of undefined elements: class="sb-cloak" on <html>, and -->
<style>.sb-cloak :not(:defined) { visibility: hidden }</style>
<sb-tooltip content="More info" open><img src="/art/info.svg" alt="Info" width="32" height="32" style="image-rendering: pixelated"></sb-tooltip>
<!-- In production, pin today's catalog instead of the latest: the browser then
refuses any file that changed. Add "integrity" to the import map above: the
hashes from https://starbase.zweiundeins.gmbh/c/@0a1ad1bf98a4/importmap.json and Datastar's, below. -->
<!--
<script type="importmap">
{ "imports": { "datastar": "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.4/bundles/datastar-rocket.js" },
"integrity": { "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.4/bundles/datastar-rocket.js": "sha384-vUxZojLrF1Ar3de5h7VINqhJXBgjyZS4U49pHvGa87kum6j5Xn6JRziuARNw5ELG", "…": "…from importmap.json" } }
</script>
<script type="module" src="https://starbase.zweiundeins.gmbh/c/@0a1ad1bf98a4/autoloader.js" integrity="sha384-IvSCUjEWPS+wwXunU+48x96KmyWDx/Y4LeCwCL8cWFqJ/zHmTsTOsSMrzTOcpW3D"></script>
-->
<!-- Or load just this component, pinned to this version: -->
<!-- <script type="module" src="https://starbase.zweiundeins.gmbh/c/tooltip@d0bc385049b7/tooltip.js" integrity="sha384-k5KOv1P9ATtrKqRIl2VajanUC6OreSbiL2x31BQNHL2n5QyJp1d97DP5oXBmjw/G"></script> -->Size
Each file compressed on its own, the way it is served (gzip -9, brotli -11). Datastar and Rocket are shared by every component and not counted.
| File | Original | gzip | brotli |
|---|---|---|---|
tooltip.js | 3.1 kB | 1.3 kB | 1.1 kB |
API reference
Props
| Attribute | Type | Default | Description |
|---|---|---|---|
content | string | "" | Tooltip text. |
placement | "top" | "bottom" | "left" | "right" | "top" | Side of the trigger. |
open | boolean | false | Keep the tooltip visible. |
Slots
| Name | Description |
|---|---|
default | The trigger element. |