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.
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.
---
// 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>The emphasis prop controls the visual weight of the outer container:
---
// 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>Alerts display a tone-appropriate icon by default. Use noIcon to hide it when the content provides sufficient visual context.
---
// 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>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.---
// 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>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, …).data-card-flushable).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={false}</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 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 withcard={false}).actionsmoved from the header row to the card footer: move a dismiss button you placed inactionstodismissible(orcard.trailingfor other header-level controls).paddingis ignored in card mode (the card size owns the spacing),passThrough.root/header/title/content/iconnow address the card root, header Banner, heading, message and Stamp, and the Svelteelementbinding is typedHTMLElement(it binds the card root).
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.
---
// 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={{ size: "md" }}</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>