Comic Tooltip
A speech-bubble tooltip with a tail pointing at its trigger, that pops in with a bounce.
betaComicTooltip.tsx
Examples
Tones and sides
Hover or tab to each button.
Ding! New stuff.Share the love!Tweak things
comic-tooltip/basic.tsx
import { Bell, Settings, Share2 } from "lucide-react";
import { Button, ComicTooltip } from "@streamuilib/react";
export default function ComicTooltipBasic() {
return (
<div className="flex gap-5 pt-12 pb-12">
<ComicTooltip content="Ding! New stuff.">
<Button size="icon" variant="secondary" aria-label="Notifications">
<Bell aria-hidden />
</Button>
</ComicTooltip>
<ComicTooltip content="Share the love!" tone="lime">
<Button size="icon" variant="secondary" aria-label="Share">
<Share2 aria-hidden />
</Button>
</ComicTooltip>
<ComicTooltip content="Tweak things" tone="pink" side="bottom">
<Button size="icon" variant="secondary" aria-label="Settings">
<Settings aria-hidden />
</Button>
</ComicTooltip>
</div>
);
}Installation
bun add @streamuilib/reactusage.tsx
import { ComicTooltip } from "@streamuilib/react";
<ComicTooltip content="Share the love!">
<button aria-label="Share">...</button>
</ComicTooltip>API
| Prop | Type | Default | Description |
|---|---|---|---|
| content | ReactNode | — | The hint. Keep it short. |
| children | ReactElement | — | One focusable trigger, e.g. an icon button. |
| tone | "paper" | "lime" | "pink" | "blue" | "orange" | "paper" | Bubble fill. |
| side | "top" | "bottom" | "top" | Where the bubble sits. |
| delay | number | 150 | Hover delay in ms. Focus shows it right away. |
Accessibility
- Built on Tooltip: it shows on hover and keyboard focus, and hides on Esc, blur, or pointer leave (WCAG 1.4.13).
- The trigger gets aria-describedby, so screen readers read the hint after its name.
- The pop-in stops when the user prefers reduced motion.
Source
packages/react/src/ComicTooltip.tsx
"use client";
import { cn } from "./cn";
import { Tooltip, type TooltipProps } from "./Tooltip";
export type ComicTooltipProps = TooltipProps & {
/** Bubble fill. */
tone?: "paper" | "lime" | "pink" | "blue" | "orange";
};
const fills = {
paper: "bg-paper-raised text-ink [--sui-tip:var(--paper-raised)]",
lime: "bg-lime text-on-bright [--sui-tip:var(--lime)]",
pink: "bg-pink text-on-bright [--sui-tip:var(--pink)]",
blue: "bg-blue text-on-bright [--sui-tip:var(--blue)]",
orange: "bg-orange text-on-bright [--sui-tip:var(--orange)]",
};
/**
* A comic-book tooltip: a speech bubble with a tail pointing at its trigger,
* that pops in with a little bounce. The same behavior as Tooltip: hover and
* keyboard focus show it, Esc, blur, or pointer leave hide it (WCAG 1.4.13),
* and the trigger gets aria-describedby. Motion stops for reduced motion.
*/
export function ComicTooltip({ tone = "paper", side = "top", className, ...props }: ComicTooltipProps) {
return (
<Tooltip
side={side}
className={cn(
"sui-comic-tip rounded-xl border-[3px] px-3 py-1.5 font-sans text-sm font-bold shadow-[3px_3px_0_var(--ink)]",
side === "top" ? "sui-comic-tip-top mb-4" : "sui-comic-tip-bottom mt-4",
fills[tone],
className,
)}
{...props}
/>
);
}