A sentence of explanation that appears while the pointer rests on an element or the keyboard focus is on it (also called a hint). Reach for it to explain an abbreviation or a control; an icon button names itself as an IconButton.
import { Tooltip } from "@umriss-ui/core";
It wraps exactly one element that can take focus and a ref; on text, give a span a tabIndex of 0.
Anything that stands only in a tooltip is lost on a touch screen. Keep it to a sentence that repeats or explains what is already there.
It shows for keyboard focus, not for the focus a click leaves behind, and a tooltip that repeats its element's aria-label does not describe the element a second time.
Wrap one focusable element; the content appears on pointer contact and on keyboard focus alike.
import { Button, Tooltip } from "@umriss-ui/core";
export default function ATooltip() {
return (
<Tooltip content="Copies the board with its columns, not its cards.">
<Button size="sm">Duplicate the board</Button>
</Tooltip>
);
}
delay is 300 ms by default so a passing pointer shows nothing; set it to 0 where the reader hovers on purpose.
import { Button, Stack, Tooltip } from "@umriss-ui/core";
export default function Delay() {
return (
<Stack direction="row" gap={3}>
<Tooltip content="Appears after 300 ms.">
<Button size="sm">Default delay</Button>
</Tooltip>
<Tooltip content="Appears at once." delay={0}>
<Button size="sm">Without a delay</Button>
</Tooltip>
</Stack>
);
}
On text, make the element focusable with tabIndex={0} so a keyboard reader reaches the explanation too.
import { Stack, Text, Tooltip } from "@umriss-ui/core";
/* Focusable text owes a visible focus: the library's ring, from its token. */
const STYLE = `
.abbreviation {
text-decoration: underline dotted;
cursor: help;
border-radius: var(--u-radius-xs);
}
.abbreviation:focus-visible {
outline: none;
box-shadow: var(--u-focus-ring);
}
`;
export default function AnAbbreviation() {
return (
<Stack gap={1}>
<style>{STYLE}</style>
<Text size="xs" tone="muted">
Checkout ·{" "}
<Tooltip content="95th percentile: 95 of 100 requests were faster than this.">
<span className="abbreviation" tabIndex={0}>
p95
</span>
</Tooltip>{" "}
latency
</Text>
<Text size="xl" mono>
412 ms
</Text>
</Stack>
);
}
The content may be built from Text: inside a tooltip every tone turns round and reads on the tooltip's ground.
import { Text, Tooltip } from "@umriss-ui/core";
/* Focusable text owes a visible focus: the library's ring, from its token. */
const STYLE = `
.figure {
cursor: help;
border-radius: var(--u-radius-xs);
}
.figure:focus-visible {
outline: none;
box-shadow: var(--u-focus-ring);
}
`;
export default function ACalculation() {
return (
<>
<style>{STYLE}</style>
<Tooltip
content={
<>
<Text size="xs" mono>
3 × 12.50 € = 37.50 €
</Text>
<Text size="xs" tone="muted">
Quantity × unit price
</Text>
</>
}
>
<Text as="span" size="xl" mono className="figure" tabIndex={0}>
37.50 €
</Text>
</Tooltip>
</>
);
}
| Key | Action |
|---|---|
Tab |
Focusing the element shows its tooltip; moving focus away hides it. |
Escape |
Hides the tooltip. |
TooltipProps| Name | Type | Default | Description |
|---|---|---|---|
contentrequired | ReactNode | — | Short help text; no interaction, no long content. Shown in: A tooltip, Delay, Explain an abbreviation and 2 more |
childrenrequired | ReactElement<Record<string, unknown>> | — | Exactly one element that triggers the tooltip (must accept refs). Its
own ref keeps its element: the tooltip holds the same one beside it. Shown in: A tooltip, Delay, Explain an abbreviation and 2 more |
delay | number | 300 | Delay in ms before the tooltip appears. Shown in: Delay |
What umriss deliberately does not build, and why: ADR-0032.