Noctis

Callout

A static, in-flow message box for status, guidance, or feedback — an icon, a title, body text, and optional actions or a dismiss control. Its look is two orthogonal axes: variant sets the emphasis and tone sets the colour, and the tone is carried by the icon, the tint, and a visually-hidden label, never by colour alone.

Basic

A Callout.Root holds a leading Callout.Icon and a Callout.Content column with a Callout.Title and Callout.Description. The default is an outline info box; the icon and tone label come from the tone automatically.

Information:

Heads up

This is a callout — a static, in-flow message for guidance, status, or feedback.

Variants

variant is the emphasis axis: a transparent outline with a coloured edge (the default), a quiet soft tint, or a filled solid. It is orthogonal to tone — every variant works with every tone. Reach for outline as the everyday default, soft when you want a filled tint that reads a touch louder, and solid only for a message that must dominate. The tone rides the saturated icon, edge, and fill; the title and body stay neutral so they read at full contrast on every tone.

Information:

The soft variant

Emphasis is orthogonal to tone — every variant works with every tone.

Information:

The outline variant

Emphasis is orthogonal to tone — every variant works with every tone.

Information:

The solid variant

Emphasis is orthogonal to tone — every variant works with every tone.

Tones

tone sets the colour identity — the five message tones: info (the default) for guidance, success for confirmation, warning for caution, danger for errors, and neutral for an un-toned note. Each paints through per-tone colour proxies that default to its status-role family, so a retheme propagates for free (and you can retune a single tone — see Design tokens). Each tone also drives the default Callout.Icon glyph plus a visually-hidden tone label (e.g. "Warning:") so the meaning reaches assistive tech.

Note:

Note

An un-toned note for plain, non-status guidance.

Information:

Good to know

Informational guidance the reader may find useful.

Success:

Saved

Your changes were saved successfully.

Warning:

Trial ending

Your trial ends in three days.

Error:

Payment failed

We couldn't process your last payment.

Without a title

Most callouts are a single line — a leading icon and a short message, no Callout.Title. Drop the title and the icon centres on the description's first line; the box stays a compact band. Works across every variant.

Success:

Your changes have been saved.

Warning:

Your free trial ends in 3 days.

Error:

We couldn't reach the server — retrying.

Without an icon

Omit Callout.Icon for a clean, text-only box — the message sits flush to the leading edge. Available on every variant and tone (switch tones below). Note the tone then reads from colour alone, so when the severity must reach assistive tech keep a Callout.Icon (it carries a visually-hidden tone label) or state it in the copy.

A text-only soft callout — no icon, just the message.

A text-only outline callout — no icon, just the message.

A text-only solid callout — no icon, just the message.

Icon alignment

The leading icon centres on the first text line, not the box as a whole: with no title it rides the first line of the description (and multi-line copy flows beneath it rather than pushing the icon to the middle); with a title it rides the title's line, the description flowing below.

Warning:

With no title, the icon badge stays level with the first line of the message — even when the copy is long enough to wrap onto a second line it never drifts to the middle of the block.

Information:

Titled callouts are unchanged

When a title is present the badge rides the title's first line and the description flows beneath it, exactly as before.

Actions

Compose a Callout.Actions row inside the content for follow-up buttons or links. Keep them low-emphasis — a secondary or ghost Button — so they support the message instead of competing with it. The row wraps on narrow widths.

Warning:

Trial ending soon

Your trial ends in three days. Upgrade now to keep your projects and data.

Dismissible

Rendering a Callout.Close makes the box dismissible — an icon-only ghost button in the corner. It works uncontrolled (internal state) or controlled via open/onOpenChange (shown here, so the box can be brought back). Don't make a callout carrying critical or required information dismissible.

Information:

New workspace settings

You can now manage members and billing from one place.

Sizes

size spans xs, sm, md (the default), and lg. The type, the icon badge, and the padding all scale with it — reach for xs/sm for dense, inline notices and lg for a prominent, page-level message.

Success:

The xs size

The type, icon, and padding scale with the size.

Success:

The sm size

The type, icon, and padding scale with the size.

Success:

The md size

The type, icon, and padding scale with the size.

Success:

The lg size

The type, icon, and padding scale with the size.

Custom icon

Callout.Icon frames the tone's default glyph in a bordered circular badge; pass children to swap the glyph for your own (it still sits inside the badge). Wrap an <Icon> (or any inline svg) inside it — don't put data-slot on the icon itself, which would drop its own token sizing. The visually-hidden tone label is kept regardless, so the severity is still announced.

Information:

Introducing AI summaries

Pass children to Callout.Icon to swap the tone’s default glyph for your own.

Announcing dynamic messages

A callout present on page load is static — it carries no live role by default (live="off"), which is correct: a live region present on load is neither announced by screen readers nor appropriate. For a message inserted after load — a "Saved" confirmation, a failed-request error — set live="polite" (renders role="status") for non-urgent feedback or live="assertive" (role="alert") for urgent, time-sensitive content, so assistive tech announces it.

Accessibility

  • Tone is never colour-only. The drawn Callout.Icon glyph is decorative (aria-hidden), but the part also renders a visually-hidden tone label ("Warning:", "Error:", …) so the severity reaches assistive tech, satisfying WCAG 1.4.1 (Use of Color). If you omit the icon, convey the tone in the title text.
  • Live role by arrival, not appearance. Keep live="off" (the default) for static, on-load content; opt into role="status"/role="alert" only for dynamically-inserted messages. Never hardcode an alert role on a callout that's present at load — it won't be announced and is over-assertive.
  • Dismiss is labelled and focus-safe. Callout.Close carries a localized "Dismiss" accessible name (a passed aria-label wins). After it removes the box, move focus to a sensible nearby location in your app.
  • Don't make required content dismissible. A callout the user must act on (a blocking error, a required step) should not render a Callout.Close.

Anatomy

Compose the box from its parts. Callout.Root renders a <div>; spread Callout.Root.props(...) onto an <aside> (or any element) to style it as a callout.

  • Callout.Root — the box; owns variant (emphasis), tone (colour), size, the live announcement politeness, and the open/onOpenChange dismiss model.
  • Callout.Icon — the leading status icon. Defaults to the tone's glyph (overridable) and carries the visually-hidden tone label.
  • Callout.Content — the stacked column that wraps the title, description, and actions.
  • Callout.Title — the headline.
  • Callout.Description — the body text.
  • Callout.Actions — the trailing button/link row.
  • Callout.Close — the optional dismiss control (a ghost Button); rendering it makes the box dismissible.

Every rendered part carries a data-slot (noctis-callout on the box, noctis-callout-icon, noctis-callout-content, and so on) for host-side styling — pair it with the data-variant/data-tone/data-size axes the root stamps, off which the colour grid and per-size metrics are keyed.

Theme scope

ThemeScope re-tunes a whole region's shape — corner radius, density, and type scale — through the cascade, with no per-component prop and without touching the app-wide theme. Tweak the knobs below and watch the Callout retune. See Customization for nesting, reset, and the portal caveat.

Information:

Scoped to its region

Radius, density, and type scale retune through the cascade — no per-component prop.

On surfaces

The same box re-tuned across the elevation scopes — the root canvas, an elevated panel, a menu, and a sunken well. It stays legible on every layer.

root
Warning:

Trial ending soon

Your trial ends in three days. Upgrade to keep your data.

elevated
Warning:

Trial ending soon

Your trial ends in three days. Upgrade to keep your data.

menu
Warning:

Trial ending soon

Your trial ends in three days. Upgrade to keep your data.

sunken
Warning:

Trial ending soon

Your trial ends in three days. Upgrade to keep your data.

Design tokens

Generated from the component's declaration — the same graph that mints the CSS, so a variable name or its resolution default can't drift. The minted tokens are the public override seam: set one on any ancestor and every callout in that region retunes — e.g. .notices { --noctis-callout-border-radius: var(--noctis-radius-sm); } squares the boxes beneath it.

Colour is minted too — every part is a proxy that defaults to a status role and re-points per tone, so you can retune the palette without touching the shared roles. Override one globally, or scope it to a single tone:

CSS
/* every callout: warmer soft fill + heavier outline edge */
.notices {
    --noctis-callout-background-color: var(--noctis-color-info-faint);
    --noctis-callout-border-color: var(--noctis-color-border-strong);
}

/* only the success tone, only in this region */
.notices [data-tone="success"] {
    --noctis-callout-icon-color: var(--noctis-color-success-hover);
}

The title and body default to neutral roles (--noctis-callout-title-color, --noctis-callout-description-color) for legibility — tint them here if your brand calls for it. See Customization for the full override ladder and Tokens for the whole graph.

Token

API reference

Generated from the component's types — every prop, type, default, and description comes straight from the source. Each part gets its own table. Expand a row for the full type and description.

Callout.Root

Prop

Callout.Icon

Prop

Callout.Content

Prop

Callout.Title

Prop

Callout.Description

Prop

Callout.Actions

Prop

Callout.Close

Prop

AttributeDescription
data-slotThe root box element.
data-variantThe emphasis — `soft` (tint, default) | `outline` (neutral surface, coloured edge) | `solid` (filled).
data-toneThe colour identity — a message tone (`neutral` | `info` | `success` | `warning` | `danger`).
data-sizeThe box scale — `sm` | `md` (default); the generated layer keys the per-size internals off it.