Skip to main content

Theme config

Theme mode

Color palette

Grays

Border radii/radiuses/radiopedes/you know
Border radius
Field border radius
Button border radius
All
Components
Guides
API
Recent

Components

Tooltip

Built on top of Anchor.

Wrap the trigger in <Tooltip> and pass a stable id. Set interestfor, commandfor, and command="toggle-popover" on the trigger element itself (these attributes are only valid on real invokers like <button> or <a>). Pass a label prop for plain text or use the content slot for richer markup.

Full support Supported since v144. Full support Supported since v149. Partial support Missing: popover-hint.

Basics

Pass plain text via the label prop.

Save your changes
---
import { Button, Tooltip } from "@opui/astro"
---
<Tooltip label="Save your changes" id="tooltip-basic">
<Button
interestfor="tooltip-basic"
commandfor="tooltip-basic"
command="toggle-popover">Save</Button
>
</Tooltip>
<span class="anchor tooltip" style="">
<span interestfor="tooltip-basic"
><button
interestfor="tooltip-basic"
commandfor="tooltip-basic"
command="toggle-popover"
class="button"
>
Save
</button>
</span>
<span class="anchor-floating" id="tooltip-basic" popover="hint">
Save your changes
</span>
</span>

Alignment

Set the alignment prop to any valid position-area value to control where the tooltip appears.

Above Before After Below
---
import { Button, Tooltip } from "@opui/astro"
---
<div class="tooltip-alignment-grid">
<Tooltip label="Above" alignment="block-start" id="tooltip-top">
<Button
interestfor="tooltip-top"
commandfor="tooltip-top"
command="toggle-popover">Top</Button
>
</Tooltip>
<Tooltip label="Before" alignment="inline-start" id="tooltip-start">
<Button
interestfor="tooltip-start"
commandfor="tooltip-start"
command="toggle-popover">Start</Button
>
</Tooltip>
<Tooltip label="After" alignment="inline-end" id="tooltip-end">
<Button
interestfor="tooltip-end"
commandfor="tooltip-end"
command="toggle-popover">End</Button
>
</Tooltip>
<Tooltip label="Below" alignment="block-end" id="tooltip-bottom">
<Button
interestfor="tooltip-bottom"
commandfor="tooltip-bottom"
command="toggle-popover">Bottom</Button
>
</Tooltip>
</div>
<style>
.tooltip-alignment-grid {
display: grid;
gap: var(--size-3);
grid-template-areas:
". top . "
"start . end"
". bottom . ";
justify-items: center;
align-items: center;
}
.tooltip-alignment-grid > :nth-child(1) {
grid-area: top;
}
.tooltip-alignment-grid > :nth-child(2) {
grid-area: start;
}
.tooltip-alignment-grid > :nth-child(3) {
grid-area: end;
}
.tooltip-alignment-grid > :nth-child(4) {
grid-area: bottom;
}
</style>
<div class="tooltip-alignment-grid">
<span class="anchor tooltip" style="--anchor-position-area: block-start">
<span interestfor="tooltip-top"
><button
interestfor="tooltip-top"
commandfor="tooltip-top"
command="toggle-popover"
class="button"
>
Top
</button>
</span>
<span class="anchor-floating" id="tooltip-top" popover="hint"> Above </span>
</span>
<span class="anchor tooltip" style="--anchor-position-area: inline-start">
<span interestfor="tooltip-start"
><button
interestfor="tooltip-start"
commandfor="tooltip-start"
command="toggle-popover"
class="button"
>
Start
</button>
</span>
<span class="anchor-floating" id="tooltip-start" popover="hint">
Before
</span>
</span>
<span class="anchor tooltip" style="--anchor-position-area: inline-end">
<span interestfor="tooltip-end"
><button
interestfor="tooltip-end"
commandfor="tooltip-end"
command="toggle-popover"
class="button"
>
End
</button>
</span>
<span class="anchor-floating" id="tooltip-end" popover="hint"> After </span>
</span>
<span class="anchor tooltip" style="--anchor-position-area: block-end">
<span interestfor="tooltip-bottom"
><button
interestfor="tooltip-bottom"
commandfor="tooltip-bottom"
command="toggle-popover"
class="button"
>
Bottom
</button>
</span>
<span class="anchor-floating" id="tooltip-bottom" popover="hint">
Below
</span>
</span>
</div>

Arrow

Set the arrow prop to render a small arrow pointing from the tooltip toward the trigger. The arrow tracks the configured alignment — it does not currently track position-try-fallbacks flips at runtime.

Save your changes
---
import { Button, Tooltip } from "@opui/astro"
---
<Tooltip arrow label="Save your changes" id="tooltip-arrow">
<Button
interestfor="tooltip-arrow"
commandfor="tooltip-arrow"
command="toggle-popover">Save</Button
>
</Tooltip>
<span class="anchor tooltip with-arrow" style="">
<span interestfor="tooltip-arrow"
><button
interestfor="tooltip-arrow"
commandfor="tooltip-arrow"
command="toggle-popover"
class="button"
>
Save
</button>
</span>
<span class="anchor-floating" id="tooltip-arrow" popover="hint">
Save your changes
</span>
</span>

Rich content

Use the content slot to render markup such as <kbd> shortcuts inside the tooltip.

Press + K to open the command palette.
---
import { Button, Tooltip } from "@opui/astro"
---
<Tooltip id="tooltip-rich">
<Button
interestfor="tooltip-rich"
commandfor="tooltip-rich"
command="toggle-popover">Keyboard shortcuts</Button
>
<Fragment slot="content">
Press <kbd></kbd> + <kbd>K</kbd> to open the command palette.
</Fragment>
</Tooltip>
<span class="anchor tooltip" style="">
<span interestfor="tooltip-rich"
><button
interestfor="tooltip-rich"
commandfor="tooltip-rich"
command="toggle-popover"
class="button"
>
Keyboard shortcuts
</button>
</span>
<span class="anchor-floating" id="tooltip-rich" popover="hint">
Press <kbd></kbd> + <kbd>K</kbd> to open the command palette.
</span>
</span>

API

Prop Type Default Description
alignment string "block-start" Any valid position-area value. Controls where the tooltip is placed relative to the trigger.
arrow boolean false When true, renders an arrow pointing from the tooltip toward the trigger. The arrow flips automatically with the tooltip via position-try-fallbacks.
id string auto-generated Identifier used to wire interestfor on the trigger to the floating element.
label string Plain-text tooltip content. For richer markup, use the content slot instead.

Browser support

Full support Supported since v144. Full support Supported since v149. Partial support Missing: popover-hint.

See also the full browser support guide.

Installation

@layer components.extended {
:where(.tooltip) {
--_tooltip-bg: light-dark(var(--gray-13), var(--gray-3));
--_tooltip-color: light-dark(var(--gray-1), var(--gray-15));
--_tooltip-offset: var(--size-2);
&>.anchor-floating {
background-color: var(--_tooltip-bg);
border-radius: var(--radius-2);
color: var(--_tooltip-color);
font-size: var(--font-size-05);
line-height: 1.3;
margin: var(--_tooltip-offset);
max-inline-size: 240px;
/* UA sets overflow: auto on [popover], which clips the arrow. */
overflow: visible;
padding-block: var(--size-1);
padding-inline: var(--size-2);
position-area: var(--anchor-position-area, block-start);
position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
position-visibility: anchors-visible;
text-align: center;
text-wrap: pretty;
}
/* Optional arrow pointing from the tooltip toward the trigger.
Anchored to the same --anchor so it flips together with the
tooltip when position-try-fallbacks kicks in. */
&.with-arrow {
--_arrow-size: var(--size-2);
&>.anchor-floating {
/* Reserve space so the arrow doesn't overlap the trigger. */
--_tooltip-offset: calc(var(--size-2) + var(--_arrow-size) / 2);
}
&>.anchor-floating::before {
background-color: var(--_tooltip-bg);
block-size: var(--_arrow-size);
content: "";
inline-size: var(--_arrow-size);
inset-block-end: calc(var(--_arrow-size) / -2);
inset-inline-start: 50%;
position: absolute;
rotate: 45deg;
translate: -50% 0;
}
}
/* Fade */
&>.anchor-floating[popover] {
opacity: 0;
transition:
display 0.15s allow-discrete,
opacity 0.15s var(--ease-out-1),
overlay 0.15s allow-discrete;
&:popover-open {
opacity: 1;
@starting-style {
opacity: 0;
}
}
}
}
}
@layer components.root {
:where(.anchor) {
anchor-name: --anchor;
anchor-scope: --anchor;
display: inline-block;
inline-size: fit-content;
/* Always-visible */
&>.anchor-floating:not([popover]) {
block-size: max-content;
inline-size: max-content;
position: absolute;
position-anchor: --anchor;
position-area: var(--anchor-position-area, start end);
translate: var(--_anchor-tx, 0) var(--_anchor-ty, 0);
}
/* Hover-triggered */
&>.anchor-floating[popover] {
inset: unset;
margin: 0;
position: absolute;
position-area: var(--anchor-position-area, start end);
translate: var(--_anchor-tx, 0) var(--_anchor-ty, 0);
}
}
}

See also