Tooltip
Short supplementary hint on hover or focus. Never the only place essential information lives — for that use inline text or a Popover.
Added 14 October 2026
React
Codecomponents/react/tooltip-demo.tsx
import {Button, Tooltip, TooltipContent, TooltipTrigger} from '@stroeer-labs/design-library/react';
import {CircleHelpIcon} from 'lucide-react';
const sides = ['top', 'right', 'bottom', 'left'] as const;
export function TooltipDemo() {
return (
<div className="space-y-6">
<div className="space-y-2">
<p className="text-xs font-medium text-muted-foreground">Sides</p>
<div className="flex flex-wrap gap-3">
{sides.map((side) => (
<Tooltip key={side}>
<TooltipTrigger render={<Button variant="outline" />}>{side}</TooltipTrigger>
<TooltipContent side={side}>Add to library</TooltipContent>
</Tooltip>
))}
</div>
</div>
<div className="space-y-2">
<p className="text-xs font-medium text-muted-foreground">Long content (wraps at max-w-xs)</p>
<div className="flex flex-wrap gap-3">
<Tooltip>
<TooltipTrigger render={<Button variant="secondary" />}>Hover me</TooltipTrigger>
<TooltipContent>Locked while the campaign is live</TooltipContent>
</Tooltip>
</div>
</div>
<div className="space-y-2">
<p className="text-xs font-medium text-muted-foreground">Icon trigger — needs its own aria-label</p>
<div className="flex flex-wrap gap-3">
<Tooltip>
<TooltipTrigger render={<Button variant="ghost" size="icon" aria-label="Help" />}>
<CircleHelpIcon />
</TooltipTrigger>
<TooltipContent side="right">Help</TooltipContent>
</Tooltip>
</div>
</div>
<div className="space-y-2">
{/* The canonical supplementary tooltip: the value is already on screen, the tooltip only
un-truncates it. Nothing is lost if the tooltip never opens, which is the test for whether
a tooltip is the right component at all — see docs/components/tooltip.md. */}
<p className="text-xs font-medium text-muted-foreground">Truncated value shown in full</p>
<div className="flex flex-wrap gap-3">
<Tooltip>
<TooltipTrigger
render={<Button variant="ghost" aria-label="Q3 Outdoor Billboard Retargeting — Prague and Central Bohemia" />}
className="max-w-40 justify-start truncate"
>
Q3 Outdoor Billboard Retargeting — Prague and Central Bohemia
</TooltipTrigger>
<TooltipContent>Q3 Outdoor Billboard Retargeting — Prague and Central Bohemia</TooltipContent>
</Tooltip>
</div>
</div>
</div>
);
}Angular
Codecomponents/angular/tooltip-demo.ts
import {Component} from '@angular/core';
import {HlmButtonImports, HlmTooltipImports} from '@stroeer-labs/design-library/angular';
import {NgIcon, provideIcons} from '@ng-icons/core';
import {lucideCircleHelp} from '@ng-icons/lucide';
// Mirrors the React tooltip demo. Note the API shape difference documented in the component's
// PARITY NOTE: brain takes the tooltip text as an input on the trigger (`[hlmTooltip]`) rather than as a
// separate content element, and its `position` has no `align` and no logical sides.
@Component({
selector: 'dl-tooltip-demo',
standalone: true,
imports: [HlmTooltipImports, HlmButtonImports, NgIcon],
providers: [provideIcons({lucideCircleHelp})],
template: `
<div class="space-y-6">
<div class="space-y-2">
<p class="text-xs font-medium text-muted-foreground">Sides</p>
<div class="flex flex-wrap gap-3">
<button hlmBtn variant="outline" hlmTooltip="Add to library" position="top">top</button>
<button hlmBtn variant="outline" hlmTooltip="Add to library" position="right">right</button>
<button hlmBtn variant="outline" hlmTooltip="Add to library" position="bottom">bottom</button>
<button hlmBtn variant="outline" hlmTooltip="Add to library" position="left">left</button>
</div>
</div>
<div class="space-y-2">
<p class="text-xs font-medium text-muted-foreground">Long content (wraps at max-w-xs)</p>
<div class="flex flex-wrap gap-3">
<button hlmBtn variant="secondary" hlmTooltip="Locked while the campaign is live">Hover me</button>
</div>
</div>
<div class="space-y-2">
<p class="text-xs font-medium text-muted-foreground">Icon trigger — needs its own aria-label</p>
<div class="flex flex-wrap gap-3">
<button hlmBtn variant="ghost" size="icon" aria-label="Help" hlmTooltip="Help" position="right">
<ng-icon name="lucideCircleHelp" />
</button>
</div>
</div>
<div class="space-y-2">
<!-- The canonical supplementary tooltip: the value is already on screen, the tooltip only
un-truncates it. Nothing is lost if it never opens, which is the test for whether a
tooltip is the right component at all — see docs/components/tooltip.md. -->
<p class="text-xs font-medium text-muted-foreground">Truncated value shown in full</p>
<div class="flex flex-wrap gap-3">
<button
hlmBtn
variant="ghost"
class="max-w-40 justify-start truncate"
[hlmTooltip]="longName"
[attr.aria-label]="longName"
>
{{ longName }}
</button>
</div>
</div>
</div>
`,
})
export class TooltipDemoComponent {
protected readonly longName = 'Q3 Outdoor Billboard Retargeting — Prague and Central Bohemia';
}