Tooltip
Supplementary plain-text tooltip for focusable interactive triggers. Requires @alpinejs/anchor.
Requires Alpine.js
Button trigger
1{{ partial:components/primitives/tooltip text="Archived projects stay searchable." }}
2 <button
3 type="button"
4 class="focus-visible:border-focus-text focus-visible:outline-focus active:border-focus active:bg-focus active:text-focus-text border-foreground hover:bg-muted inline-flex h-10 items-center border-2 px-3 text-sm font-medium focus-visible:outline focus-visible:outline-4"
5 >
6 Archive
7 </button>
8{{ /partial:components/primitives/tooltip }}
{{ partial:components/primitives/tooltip text="Archived projects stay searchable." }}
<button
type="button"
class="focus-visible:border-focus-text focus-visible:outline-focus active:border-focus active:bg-focus active:text-focus-text border-foreground hover:bg-muted inline-flex h-10 items-center border-2 px-3 text-sm font-medium focus-visible:outline focus-visible:outline-4"
>
Archive
</button>
{{ /partial:components/primitives/tooltip }}
Link trigger
1{{ partial:components/primitives/tooltip text="Opens the public changelog in this window." }}
2 <a
3 href="#"
4 class="text-primary focus-visible:border-focus-text focus-visible:outline-focus active:border-focus active:bg-focus active:text-focus-text inline-flex border-2 border-transparent px-1 text-sm font-medium underline underline-offset-4 hover:border-current focus-visible:outline focus-visible:outline-4"
5 >
6 View changelog
7 </a>
8{{ /partial:components/primitives/tooltip }}
{{ partial:components/primitives/tooltip text="Opens the public changelog in this window." }}
<a
href="#"
class="text-primary focus-visible:border-focus-text focus-visible:outline-focus active:border-focus active:bg-focus active:text-focus-text inline-flex border-2 border-transparent px-1 text-sm font-medium underline underline-offset-4 hover:border-current focus-visible:outline focus-visible:outline-4"
>
View changelog
</a>
{{ /partial:components/primitives/tooltip }}
Wrapper class
1{{ partial:components/primitives/tooltip text="The class prop targets only the inline-block wrapper." class="align-middle" }}
2 <button
3 type="button"
4 class="focus-visible:border-focus-text focus-visible:outline-focus active:border-focus active:bg-focus active:text-focus-text border-foreground hover:bg-muted inline-flex size-10 items-center justify-center border-2 text-sm font-bold focus-visible:outline focus-visible:outline-4"
5 aria-label="More information"
6 >
7 ?
8 </button>
9{{ /partial:components/primitives/tooltip }}
{{ partial:components/primitives/tooltip text="The class prop targets only the inline-block wrapper." class="align-middle" }}
<button
type="button"
class="focus-visible:border-focus-text focus-visible:outline-focus active:border-focus active:bg-focus active:text-focus-text border-foreground hover:bg-muted inline-flex size-10 items-center justify-center border-2 text-sm font-bold focus-visible:outline focus-visible:outline-4"
aria-label="More information"
>
?
</button>
{{ /partial:components/primitives/tooltip }}
Props
| Name | Type | Default | Description |
|---|---|---|---|
text
|
string
|
Required plain-text tooltip content | |
class
|
string
|
Additional classes merged via tw_merge (root element only) |
Slots
| Name | Fallback / Default | Description |
|---|---|---|
default
|
Trigger content; must contain a focusable interactive element such as a button, link, or input |
Source
1{{#
2 @name Tooltip
3 @desc Supplementary plain-text tooltip for focusable interactive triggers. Requires @alpinejs/anchor.
4 @param text string - Required plain-text tooltip content
5 @param class string - Additional classes merged via tw_merge (root element only)
6 @slot default - Trigger content; must contain a focusable interactive element such as a button, link, or input
7#}}
8{{ _class = 'inline-block {class}'
9 | tw_merge }}
10<div
11 class="{{ _class }}"
12 x-data="{
13 open: false,
14 trigger: null,
15 focusableSelector: `button:not([disabled]), a[href], input:not([type=hidden]):not([disabled]), select:not([disabled]), textarea:not([disabled])`
16 }"
17 x-id="['kern-tooltip']"
18 x-init="
19 trigger = $el.querySelector(focusableSelector);
20 if (trigger) trigger.setAttribute('aria-describedby', $id('kern-tooltip'));
21 "
22 @mouseenter="open = true"
23 @mouseleave="open = false"
24 @focusin="open = true"
25 @focusout="open = false"
26 @keydown.escape.window="if (open) open = false"
27>
28 {{ slot }}
29 <div
30 x-show="open"
31 x-anchor.top.offset.8="trigger"
32 :id="$id('kern-tooltip')"
33 role="tooltip"
34 class="bg-foreground text-background z-50 px-2.5 py-1 text-sm"
35 style="display: none"
36 >
37 {{ text | entities }}
38 </div>
39</div>
{{#
@name Tooltip
@desc Supplementary plain-text tooltip for focusable interactive triggers. Requires @alpinejs/anchor.
@param text string - Required plain-text tooltip content
@param class string - Additional classes merged via tw_merge (root element only)
@slot default - Trigger content; must contain a focusable interactive element such as a button, link, or input
#}}
{{ _class = 'inline-block {class}'
| tw_merge }}
<div
class="{{ _class }}"
x-data="{
open: false,
trigger: null,
focusableSelector: `button:not([disabled]), a[href], input:not([type=hidden]):not([disabled]), select:not([disabled]), textarea:not([disabled])`
}"
x-id="['kern-tooltip']"
x-init="
trigger = $el.querySelector(focusableSelector);
if (trigger) trigger.setAttribute('aria-describedby', $id('kern-tooltip'));
"
@mouseenter="open = true"
@mouseleave="open = false"
@focusin="open = true"
@focusout="open = false"
@keydown.escape.window="if (open) open = false"
>
{{ slot }}
<div
x-show="open"
x-anchor.top.offset.8="trigger"
:id="$id('kern-tooltip')"
role="tooltip"
class="bg-foreground text-background z-50 px-2.5 py-1 text-sm"
style="display: none"
>
{{ text | entities }}
</div>
</div>
Dependencies
Packages
1composer require marcorieser/tailwind-merge-statamic
2npm install alpinejs @alpinejs/anchor
composer require marcorieser/tailwind-merge-statamic npm install alpinejs @alpinejs/anchor