Overlays
Tooltip
A short hint about a control, shown on hover or keyboard focus.
Installation
npx sinaui add tooltipCopy src/lib/ui/Tooltip.svelte, floating.ts and tokens.css. No dependencies.
Examples
Naming icon buttons
Hover one, then slide along: once a tooltip has shown, the next opens instantly.
Annotate
Transcribe a copy
Share manuscript
<script lang="ts">
import Button from '#lib/ui/Button.svelte';
import Icon from '#lib/ui/Icon.svelte';
import Tooltip from '#lib/ui/Tooltip.svelte';
import { Copy01Icon, Edit02Icon, Share08Icon } from '@hugeicons/core-free-icons';
</script>
<!-- labels: the tooltip is the button's name, so no aria-label is needed or repeated. -->
<Tooltip text="Annotate" labels>
{#snippet trigger(props)}
<Button variant="ghost" square {...props}><Icon icon={Edit02Icon} /></Button>
{/snippet}
</Tooltip>
<Tooltip text="Transcribe a copy" labels>
{#snippet trigger(props)}
<Button variant="ghost" square {...props}><Icon icon={Copy01Icon} /></Button>
{/snippet}
</Tooltip>
<Tooltip text="Share manuscript" labels>
{#snippet trigger(props)}
<Button variant="ghost" square {...props}><Icon icon={Share08Icon} /></Button>
{/snippet}
</Tooltip>Adding a description
On a control that already has a name, the tooltip is read after it as extra detail.
Loans last forty days. Renew from your reading list.
<script lang="ts">
import Button from '#lib/ui/Button.svelte';
import Tooltip from '#lib/ui/Tooltip.svelte';
</script>
<!-- Default: the tooltip adds a description to a control that already has a name. -->
<Tooltip text="Loans last forty days. Renew from your reading list.">
{#snippet trigger(props)}
<Button {...props}>Borrow manuscript</Button>
{/snippet}
</Tooltip>Above
The default. Each tooltip prefers the side you ask for and flips to the opposite one when there isn't room; the arrow always points at the trigger.
Shown on the top
<script lang="ts">
import Button from '#lib/ui/Button.svelte';
import Tooltip from '#lib/ui/Tooltip.svelte';
</script>
<Tooltip text="Shown on the top" side="top">
{#snippet trigger(props)}
<Button variant="secondary" {...props}>Top</Button>
{/snippet}
</Tooltip>Right
Shown on the right
<script lang="ts">
import Button from '#lib/ui/Button.svelte';
import Tooltip from '#lib/ui/Tooltip.svelte';
</script>
<Tooltip text="Shown on the right" side="right">
{#snippet trigger(props)}
<Button variant="secondary" {...props}>Right</Button>
{/snippet}
</Tooltip>Below
Shown on the bottom
<script lang="ts">
import Button from '#lib/ui/Button.svelte';
import Tooltip from '#lib/ui/Tooltip.svelte';
</script>
<Tooltip text="Shown on the bottom" side="bottom">
{#snippet trigger(props)}
<Button variant="secondary" {...props}>Bottom</Button>
{/snippet}
</Tooltip>Left
Shown on the left
<script lang="ts">
import Button from '#lib/ui/Button.svelte';
import Tooltip from '#lib/ui/Tooltip.svelte';
</script>
<Tooltip text="Shown on the left" side="left">
{#snippet trigger(props)}
<Button variant="secondary" {...props}>Left</Button>
{/snippet}
</Tooltip>Props
| Prop | Type | Default |
|---|---|---|
text | string (required) | |
labels | boolean: tooltip is the trigger's name | false |
side | 'top' | 'right' | 'bottom' | 'left' | 'top' |
trigger | Snippet receiving trigger props (required) |
Accessibility
- Follows the WAI-ARIA tooltip pattern:
role="tooltip", linked witharia-describedby, oraria-labelledbywhen it's the name. - Meets WCAG 1.4.13: it can be dismissed with Escape from anywhere, the pointer can move onto it, and it stays until you leave.
- Shows at once on keyboard focus; not on touch, where hover doesn't exist. Don't hide anything essential in a tooltip.
- Plain text only: nobody could reach a link or button inside it.
| Key | Action |
|---|---|
| Tab | Focusing the trigger shows the tooltip. |
| Escape | Hides it without moving focus. |