component

Alert

A contextual notification component for displaying important messages. Alert is card-based — a shortcut for a Card: the tone stamp and the title head it, the message is its content and the actions sit in its footer. tone and emphasis tint the whole card.

Tone Colors

Alerts default to a neutral (primary) color palette and support semantic tone colors: success, warning, and danger. Each tone type automatically selects an appropriate icon.

This is a general information alert. Use it to surface important context or status updates to the user.
Your changes have been saved successfully. The update is now live.
Your session is about to expire. Save your work to avoid losing any changes.
Unable to complete the request. Please check your connection and try again.
---
// GENERATED from packages/demos/alert/tone.demo.tsx — edit the source, not this file.
import Alert from "@pindoba/astro-alert";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "md", direction: "column", width: "100%" })}>
  <Alert>
    This is a general information alert. Use it to surface important context or
    status updates to the user.
  </Alert>
  <Alert tone="success">
    Your changes have been saved successfully. The update is now live.
  </Alert>
  <Alert tone="warning">
    Your session is about to expire. Save your work to avoid losing any changes.
  </Alert>
  <Alert tone="danger">
    Unable to complete the request. Please check your connection and try again.
  </Alert>
</div>

Emphasis

The emphasis prop controls the visual weight of the outer container:

  • primary (default) — full-color outer ring using the tone color (500) with contrast text, and a tinted content area
  • secondary — neutral surface outer container with a full-color icon, keeping the background quiet
  • tertiary — transparent outer container with a neutral-background icon tinted by the tone color

Primary

Full-color outer container — the tone color (500) fills the outer ring with contrast text. The content area uses a tinted surface.
Full-color outer container — warning color fills the outer ring.
Full-color outer container — danger color fills the outer ring.

Secondary

Neutral sunken outer container with a colored icon. Provides clear tone without a dominant colored background.
Neutral sunken outer container with a warning-colored icon.
Neutral sunken outer container with a danger-colored icon.

Tertiary

Neutral sunken container with a subtle content area. The icon uses a neutral background with the tone color as the icon tint.
Neutral sunken container with a warning-tinted icon on a neutral background.
Neutral sunken container with a danger-tinted icon on a neutral background.
---
// GENERATED from packages/demos/alert/emphasis.demo.tsx — edit the source, not this file.
import Alert from "@pindoba/astro-alert";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "xl", direction: "column", width: "100%" })}>
  <div>
    <h3>Primary</h3>
    <div class={stack({ gap: "md", direction: "column", width: "100%" })}>
      <Alert tone="success" emphasis="primary">
        Full-color outer container — the tone color (500) fills the outer ring
        with contrast text. The content area uses a tinted surface.
      </Alert>
      <Alert tone="warning" emphasis="primary">
        Full-color outer container — warning color fills the outer ring.
      </Alert>
      <Alert tone="danger" emphasis="primary">
        Full-color outer container — danger color fills the outer ring.
      </Alert>
    </div>
  </div>

  <div>
    <h3>Secondary</h3>
    <div class={stack({ gap: "md", direction: "column", width: "100%" })}>
      <Alert tone="success" emphasis="secondary">
        Neutral sunken outer container with a colored icon. Provides clear tone
        without a dominant colored background.
      </Alert>
      <Alert tone="warning" emphasis="secondary">
        Neutral sunken outer container with a warning-colored icon.
      </Alert>
      <Alert tone="danger" emphasis="secondary">
        Neutral sunken outer container with a danger-colored icon.
      </Alert>
    </div>
  </div>

  <div>
    <h3>Tertiary</h3>
    <div class={stack({ gap: "md", direction: "column", width: "100%" })}>
      <Alert tone="success" emphasis="tertiary">
        Neutral sunken container with a subtle content area. The icon uses a
        neutral background with the tone color as the icon tint.
      </Alert>
      <Alert tone="warning" emphasis="tertiary">
        Neutral sunken container with a warning-tinted icon on a neutral
        background.
      </Alert>
      <Alert tone="danger" emphasis="tertiary">
        Neutral sunken container with a danger-tinted icon on a neutral
        background.
      </Alert>
    </div>
  </div>
</div>

Icon

Alerts display a tone-appropriate icon by default. Use noIcon to hide it when the content provides sufficient visual context.

An alert without an icon. Useful when the content itself provides enough visual context.
Operation completed. The icon is hidden — the tone color alone conveys the status.
Proceeding may have unintended side effects. Review before continuing.
This action cannot be undone. All associated data will be permanently deleted.
---
// GENERATED from packages/demos/alert/noIcon.demo.tsx — edit the source, not this file.
import Alert from "@pindoba/astro-alert";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "md", direction: "column", width: "100%" })}>
  <Alert noIcon>
    An alert without an icon. Useful when the content itself provides enough
    visual context.
  </Alert>
  <Alert tone="success" noIcon>
    Operation completed. The icon is hidden — the tone color alone conveys the
    status.
  </Alert>
  <Alert tone="warning" emphasis="secondary" noIcon>
    Proceeding may have unintended side effects. Review before continuing.
  </Alert>
  <Alert tone="danger" emphasis="tertiary" noIcon>
    This action cannot be undone. All associated data will be permanently
    deleted.
  </Alert>
</div>

Title, Dismiss and Actions

A title turns the alert into a full card: the tone stamp leads the card header, the title is the heading (an <h3>), and the message becomes the card content. Without a title the alert is the compact single row — stamp, message, then the dismiss button.

  • dismissible renders a dismiss button — the last entry of the header’s trailing slot (the end of the row in the compact layout). Clicking it calls onDismiss (React / Svelte, @dismiss in Vue); without a handler the alert hides itself. In Astro a small script hides it and dispatches a cancelable pindoba:alert:dismiss event on the alert first (preventDefault() keeps it). dismissLabel sets the button’s accessible name (default "Dismiss").
  • actions render in the card footer, trailing. In Svelte actions is a snippet; in Astro use slot="actions"; in Vue the #actions slot.

Heads up

A title turns the alert into a full card: the tone stamp and the title head it, and the message becomes the card content.

Changes saved

Your profile has been updated and the changes are now live.

Session expiring

Your session will expire in 5 minutes. Save your work or extend the session.

Permission denied

You do not have permission to perform this action. Contact your administrator for access.
---
// GENERATED from packages/demos/alert/title.demo.tsx — edit the source, not this file.
import Alert from "@pindoba/astro-alert";
import Button from "@pindoba/astro-button";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "md", direction: "column", width: "100%" })}>
  <Alert title="Heads up">
    A title turns the alert into a full card: the tone stamp and the title head
    it, and the message becomes the card content.
  </Alert>

  <Alert tone="success" title="Changes saved" dismissible>
    Your profile has been updated and the changes are now live.
  </Alert>

  <Alert
    tone="warning"
    emphasis="secondary"
    title="Session expiring"
    dismissible
  >
    <Button slot="actions" size="xs" tone="warning" emphasis="secondary">
      Extend
    </Button>
    Your session will expire in 5 minutes. Save your work or extend the session.
  </Alert>

  <Alert
    tone="danger"
    emphasis="tertiary"
    title="Permission denied"
    dismissible
  >
    You do not have permission to perform this action. Contact your
    administrator for access.
  </Alert>
</div>

Card

The card prop takes the Card’s surface props and header / footer content (CardFrameProps). The alert’s own props are its defaults: tone, emphasis, background, border, radius, shadow, translucent and rhythm style the card, and size picks the card size one step denser than a plain card (sm → xs, md → sm, lg → md). A field set on card wins.

  • card.contentBackground puts the message on an inset panel inside the tinted shell.
  • card.heading / eyebrow / subheading add to (or replace) the title; card.leading replaces the tone stamp; card.trailing renders before the dismiss button; card.footer.leading / trailing render before the actions. Without a heading, card.leading / card.trailing move into the compact row. Astro takes rich content through the forwarded card-* slots (card-trailing, card-footer-leading, …).
  • An alert that is the only child of another card’s content is flushable: it dissolves into that card (data-card-flushable).

orders-db · 02:00 UTC

Nightly backup complete

A 14.2 GB snapshot was written to cold storage in 3m 12s and verified against the primary.

Build storage at 91%

Artifacts from the last 30 days use 45.5 of 50 GB. New builds start failing at the limit.
Resets on the 1st
card={false} renders the pre-card alert markup, exactly.
---
// GENERATED from packages/demos/alert/card.demo.tsx — edit the source, not this file.
import Alert from "@pindoba/astro-alert";
import Button from "@pindoba/astro-button";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "md", direction: "column", width: "100%" })}>
  <Alert
    tone="success"
    emphasis="secondary"
    title="Nightly backup complete"
    card={{
      background: "surface.base",
      contentBackground: "surface.peak",
      eyebrow: "orders-db · 02:00 UTC",
    }}
  >
    <Fragment slot="actions">
      <Button size="xs" emphasis="secondary">
        View snapshot
      </Button>
      <Button size="xs" tone="success">
        Restore
      </Button>
    </Fragment>
    A 14.2 GB snapshot was written to cold storage in 3m 12s and verified
    against the primary.
  </Alert>

  <Alert
    tone="warning"
    emphasis="secondary"
    title="Build storage at 91%"
    dismissible
    card={{ footer: { leading: "Resets on the 1st" } }}
  >
    <Fragment slot="actions">
      <Button size="xs" emphasis="ghost">
        Archive old builds
      </Button>
      <Button size="xs" tone="warning">
        Raise limit
      </Button>
    </Fragment>
    Artifacts from the last 30 days use 45.5 of 50 GB. New builds start failing
    at the limit.
  </Alert>

  <Alert tone="neutral" emphasis="secondary" card={false}>
    <code>card=&#123;false&#125;</code> renders the pre-card alert markup,
    exactly.
  </Alert>
</div>

card={false} renders the legacy bare alert — the pre-card DOM, exactly (a [data-component="alert"] root with a <header> row and a content <div>); actions stay at the end of that header row.

<Alert tone="warning" card={false}
  >Inside a surface that already frames it.</Alert
>

Live Regions

live makes the alert a live region without hand-writing ARIA: live="polite" renders role="status" (announced when the reader is idle), live="assertive" renders role="alert" (interrupts). An explicit role wins. Toasts render their rows with it.

Migrating from the pre-card alert: the root is now a Card — select it with [data-card-kind="alert"] ([data-component="alert"] only matches with card={false}). actions moved from the header row to the card footer: move a dismiss button you placed in actions to dismissible (or card.trailing for other header-level controls). padding is ignored in card mode (the card size owns the spacing), passThrough.root / header / title / content / icon now address the card root, header Banner, heading, message and Stamp, and the Svelte element binding is typed HTMLElement (it binds the card root).

Custom Styling

The surface props (border, radius, background…) style the card, card.size tunes its spacing, and the passThrough prop provides escape hatches for advanced customization: style accepts any Panda CSS SystemStyleObject applied to any slot, and props forwards arbitrary HTML attributes.

Using border="bold" and radius="lg" to override the default border and corner rounding.
Using card={{ size: "md" }} for roomier card spacing.
Using passThrough to constrain the width and italicize the message.
Using live="polite" — the alert is a role="status" region screen readers announce when it changes.
---
// GENERATED from packages/demos/alert/custom.demo.tsx — edit the source, not this file.
import Alert from "@pindoba/astro-alert";
import { stack } from "@pindoba/styled-system/patterns";
import { css } from "@pindoba/styled-system/css";
---

<div class={stack({ gap: "md", direction: "column", width: "100%" })}>
  <Alert tone="success" border="bold" radius="lg">
    Using <code>border="bold"</code> and <code>radius="lg"</code> to override
    the default border and corner rounding.
  </Alert>

  <Alert tone="warning" emphasis="secondary" card={{ size: "md" }}>
    Using <code>card=&#123;&#123; size: "md" &#125;&#125;</code> for roomier
    card spacing.
  </Alert>

  <Alert
    tone="danger"
    emphasis="tertiary"
    passThrough={{
      root: { style: css.raw({ maxWidth: "480px" }) },
      content: { style: css.raw({ fontStyle: "italic" }) },
    }}
  >
    Using <code>passThrough</code> to constrain the width and italicize the
    message.
  </Alert>

  <Alert tone="success" emphasis="secondary" live="polite">
    Using <code>live="polite"</code> — the alert is a <code>role="status"</code>{" "}
    region screen readers announce when it changes.
  </Alert>
</div>
  • Components
  • Blocks