Callout
A framed block explaining the state of something — why an action is offered, why it is
not, or what the reader is waiting for. One name for every such block, so a brand
styles [data-component="callout"] once instead of learning five.
import { Callout } from "@evolve-storefront/ui/callout";Design notes
tone is always emitted, its default included. Appearance is in styles.css under
@layer components; a background utility added here would beat the layer.
Preview
Usage
<Callout title={t("approval-title")} headingLevel={3}> <p>{t("approval-body")}</p></Callout>;Props
| Prop | Type | Description |
|---|---|---|
title | ReactNode | The heading. A callout without one is a paragraph; use a |
headingLevel? | HeadingLevel | The heading's level. A feature cannot know its own document depth, so this is passed rather than guessed — an unlevelled heading is how an outline gains a gap. |
tone? | CalloutTone | |
data-component? | undefined | A callout's identity is not a caller's to rename. Typed away so a call site
renaming it fails to compile rather than silently shadowing the selector a
brand was told to use — the same reason |
data-tone? | undefined | The tone comes from |
Any other props go to the root element, like on a plain HTML element.
Examples
VariantsThe three tones, which name roles rather than looks: neutral carries an action the reader can take now, info a state they are waiting on, critical one that has closed off.
<Callout title={t("pay-title")}>…</Callout><Callout tone="info" title={t("approval-title")}>…</Callout><Callout tone="critical" title={t("cancelled-title")}>…</Callout>Publishes Its ToneThe tone is published, its default included, so a brand reaches one kind of callout without knowing which value is the default and without publishing a :not([data-tone]).
/* every callout, whatever a feature calls the block */[data-component="callout"] { background: var(--color-muted) }
/* just the ones the reader is waiting on */[data-component="callout"][data-tone="info"] { … }
