Skip to content

Callout

A high-contrast popover to draw attention to features and information.

To create a callout, import and compose the following <Callout> components:

import { Button } from "stylus-ui/Button";
import {
Callout,
CalloutContent,
CalloutDescription,
CalloutTitle,
CalloutTrigger,
} from "stylus-ui/Callout";
export default () => (
<Callout defaultOpen>
<CalloutTrigger asChild>
<Button variant="secondary">Open Callout</Button>
</CalloutTrigger>
<CalloutContent>
<CalloutTitle title="Callout" />
<CalloutDescription>
Callouts bring attention to a particular element or feature.
</CalloutDescription>
</CalloutContent>
</Callout>
);

For scenarios where you want to position the callout without a trigger, you can use <CalloutAnchor>.

import { Button } from "stylus-ui/Button";
import {
Callout,
CalloutContent,
CalloutDescription,
CalloutTitle,
CalloutAnchor,
} from "stylus-ui/Callout";
export default () => (
<Callout defaultOpen>
<CalloutAnchor />
<CalloutContent>
<CalloutTitle title="Callout" />
<CalloutDescription>
Callouts bring attention to a particular element or feature.
</CalloutDescription>
</CalloutContent>
</Callout>
);

You can pass a Font Awesome icon into <CalloutTitle>.

import { Button } from "stylus-ui/Button";
import {
Callout,
CalloutContent,
CalloutDescription,
CalloutTitle,
CalloutTrigger,
} from "stylus-ui/Callout";
import { faSparkles } from "@fortawesome/pro-regular-svg-icons";
export default () => (
<Callout>
<CalloutTrigger asChild>
<Button variant="secondary">Open Callout</Button>
</CalloutTrigger>
<CalloutContent>
<CalloutTitle title="Callout with icon" icon={faSparkles} />
<CalloutDescription>
Import your Font Awesome icon and pass it to{" "}
<code>&lt;CalloutTitle&gt;</code>.
</CalloutDescription>
</CalloutContent>
</Callout>
);

To display buttons in your callout, you can pass primaryAction, primaryActionText, secondaryAction, and secondaryActionText to <CalloutContent>.

import { Button } from "stylus-ui/Button";
import {
Callout,
CalloutContent,
CalloutDescription,
CalloutTitle,
CalloutTrigger,
} from "stylus-ui/Callout";
import { useToast } from "stylus-ui/Toast";
export default () => {
const { toast } = useToast();
const handlePrimaryAction = () => toast({ title: "Clicked primary action" });
const handleSecondaryAction = () =>
toast({ title: "Clicked secondary action" });
return (
<Callout>
<CalloutTrigger asChild>
<Button variant="secondary">Open Callout</Button>
</CalloutTrigger>
<CalloutContent
primaryAction={handlePrimaryAction}
primaryActionText="Primary Action"
secondaryAction={handleSecondaryAction}
secondaryActionText="Secondary Action"
>
<CalloutTitle title="Callout with buttons" />
<CalloutDescription>
Buttons defined in <code>&lt;CalloutContent&gt;</code> will display
below.
</CalloutDescription>
</CalloutContent>
</Callout>
);
};

To display a close button on the callout, set showCloseButton on <CalloutContent>.

import { Button } from "stylus-ui/Button";
import {
Callout,
CalloutContent,
CalloutDescription,
CalloutTitle,
CalloutTrigger,
} from "stylus-ui/Callout";
export default () => (
<Callout>
<CalloutTrigger asChild>
<Button variant="secondary">Open Callout</Button>
</CalloutTrigger>
<CalloutContent showCloseButton>
<CalloutTitle title="Callout with close button" />
<CalloutDescription>
A close icon will display in the top right.
</CalloutDescription>
</CalloutContent>
</Callout>
);

To display an arrow pointing to the trigger, set withArrow on <CalloutContent>.

import { Button } from "stylus-ui/Button";
import {
Callout,
CalloutContent,
CalloutDescription,
CalloutTitle,
CalloutTrigger,
} from "stylus-ui/Callout";
export default () => (
<Callout>
<CalloutTrigger asChild>
<Button variant="secondary">Open Callout</Button>
</CalloutTrigger>
<CalloutContent withArrow>
<CalloutTitle title="Callout with arrow" />
<CalloutDescription>
An arrow points to the callout trigger.
</CalloutDescription>
</CalloutContent>
</Callout>
);

To display an image in the callout, import <CalloutImg>. Pass an <img> or NextJS <Image> component as a child.

import { Button } from "stylus-ui/Button";
import {
Callout,
CalloutContent,
CalloutDescription,
CalloutImg,
CalloutTitle,
CalloutTrigger,
} from "stylus-ui/Callout";
export default () => (
<Callout>
<CalloutTrigger asChild>
<Button variant="secondary">Open Callout</Button>
</CalloutTrigger>
<CalloutContent>
<CalloutImg>
<img
src="https://cdn.prod.website-files.com/615f415173b71a5211e28de7/654ac9c921b76a875209ffbe_auto-redact.webp"
className="w-full"
/>
</CalloutImg>
<CalloutTitle title="Callout with image" />
<CalloutDescription>
Highlight product features with images.
</CalloutDescription>
</CalloutContent>
</Callout>
);

A high-contrast popover to draw attention to features and information.

defaultOpen

boolean

modal

boolean

onOpenChange

(open: boolean) => void

open

boolean

Use this to position Callout without a trigger.

asChild

boolean

virtualRef

RefObject<Measurable>

The trigger that, when clicked, opens a Callout.

asChild

boolean

asChild

boolean

asChild

boolean

A title for a Callout.

title

Required
string

Heading text.


className

string

Classes for the title wrapper.


icon

IconDefinition

Optional icon before the title.


iconClassName

string

Classes for the icon.


titleClassName

string

Classes for the title text.


An image for a Callout.

children

Required
ReactNode

Image or media content to display in the callout.


A description for a Callout.

children

Required
ReactNode

Body text or content below the title.


className

string

Optional class for the description wrapper.


The content of a Callout. Renders the container with contents, an optional close button, and optional primary and secondary actions.

children

Required
ReactNode

Main content (title, description, etc.).


align

"center" | "end" | "start" = "center"

alignOffset

number

arrowPadding

number

asChild

boolean

avoidCollisions

boolean

collisionBoundary

null | Element | Boundary[]

collisionPadding

number | Partial<Record<"bottom" | "top" | "left" | "right", number>>

forceMount

true

Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries.


hideWhenDetached

boolean

onCloseAction

MouseEventHandler<HTMLButtonElement>

Called when the user clicks the close button.


onCloseAutoFocus

(event: Event) => void

Event handler called when auto-focusing on close. Can be prevented.


onEscapeKeyDown

(event: KeyboardEvent) => void

Event handler called when the escape key is down. Can be prevented.


onFocusOutside

(event: FocusOutsideEvent) => void

Event handler called when the focus moves outside of the DismissableLayer. Can be prevented.


onInteractOutside

(event: PointerDownOutsideEvent | FocusOutsideEvent) => void

Event handler called when an interaction happens outside the DismissableLayer. Specifically, when a pointerdown event happens outside or focus moves outside of it. Can be prevented.


onOpenAutoFocus

(event: Event) => void

Event handler called when auto-focusing on open. Can be prevented.


onPointerDownOutside

(event: PointerDownOutsideEvent) => void

Event handler called when the a pointerdown event happens outside of the DismissableLayer. Can be prevented.


portalContainer

HTMLElement

DOM node to portal the callout into.


primaryAction

MouseEventHandler<HTMLButtonElement>

Click handler for the primary action button.


primaryActionText

string

Label for the primary action button.


secondaryAction

MouseEventHandler<HTMLButtonElement>

Click handler for the secondary action button.


secondaryActionText

string

Label for the secondary action button.


showCloseButton

boolean = false

Show a close (X) button in the header.


side

"bottom" | "top" | "left" | "right"

sideOffset

number = 10

sticky

"partial" | "always"

updatePositionStrategy

"always" | "optimized"

withArrow

boolean = false

Show a small arrow pointing at the trigger.