# Alert (/docs/alert)





`Alert` has the look of [`Notification`](/docs/notification) — the same `type` presets, the same `Icon` / `Title` / `Description` / `ActionTrigger` / `CloseTrigger` parts — but it's full-width, un-animated, and static by default (`withCloseButton={false}`). Reach for it when the content should just sit in the page rather than float above it and self-dismiss.

The surface is where the two differ. A toast floats over arbitrary content, so it keeps an opaque, blurred panel. An alert lives on the page, so it's translucent: a faint wash of its `color` across the whole card and a translucent edge in the same hue. It blends into whatever it sits on, and the status reads from the whole card, not just its outline.

`Alert`'s root takes a `testId`, and — since these parts are literally re-exported from `Notification` — so does every one of `Alert.Icon` / `Alert.Title` / `Alert.Description` / `Alert.ActionTrigger` / `Alert.CloseTrigger`, each landing on its own rendered element. See [Testing](/docs/testing).

```tsx
import { Alert } from '@42-central/ui-react/alert';

<Alert type="warning" title="Breaking change" description="Update your imports." />
```

## Playground [#playground]

<story.Playground />

### Full prop browser [#full-prop-browser]

<story.WithControl />

## Types [#types]

Four status presets — the same hues and icons as `Notification`, minus the toast-only `loading`.

<Preview align="block" code="&#x22;<Alert type=\&#x22;info\&#x22; title=\&#x22;Info\&#x22; description=\&#x22;A neutral status preset.\&#x22; />\n<Alert type=\&#x22;success\&#x22; title=\&#x22;Success\&#x22; description=\&#x22;Your changes are live.\&#x22; />\n<Alert type=\&#x22;warning\&#x22; title=\&#x22;Warning\&#x22; description=\&#x22;Double-check before continuing.\&#x22; />\n<Alert type=\&#x22;error\&#x22; title=\&#x22;Error\&#x22; description=\&#x22;Something went wrong.\&#x22; />&#x22;">
  <div className="flex w-full flex-col gap-3">
    <Alert type="info" title="Info" description="A neutral status preset." />

    <Alert type="success" title="Success" description="Your changes are live." />

    <Alert type="warning" title="Warning" description="Double-check before continuing." />

    <Alert type="error" title="Error" description="Something went wrong." />
  </div>
</Preview>

## Custom colors [#custom-colors]

There is one surface — a wash and an edge tinted by `color` — so a look outside the four presets is just another hue. Pass `color` (and your own `icon`, or none) instead of a `type`. The two are mutually exclusive: passing both is a type error, since `type` already sets the hue.

<Preview align="block" code="&#x22;<Alert color=\&#x22;blue\&#x22; title=\&#x22;Blue\&#x22; description=\&#x22;Any palette color works.\&#x22; />\n<Alert color=\&#x22;purple\&#x22; title=\&#x22;Purple\&#x22; description=\&#x22;No type, so no default icon.\&#x22; />&#x22;">
  <div className="flex w-full flex-col gap-3">
    <Alert color="blue" title="Blue" description="Any palette color works." />

    <Alert color="purple" title="Purple" description="No type, so no default icon." />
  </div>
</Preview>

## Anatomy [#anatomy]

Composing the parts by hand is for a bespoke body — the same compound parts as `Notification` (they're literally the same components; only the root surface differs):

<Preview align="block" code="&#x22;<Alert.Root color=\&#x22;green\&#x22;>\n  <div className=\&#x22;flex flex-row gap-3\&#x22;>\n    <Alert.Icon><CircleCheck /></Alert.Icon>\n    <Alert.Title>Profile updated</Alert.Title>\n    <Alert.CloseTrigger />\n  </div>\n  <Alert.Description>Your changes are live across all 42 campuses.</Alert.Description>\n  <div className=\&#x22;mt-2 flex flex-wrap items-center gap-2\&#x22;>\n    <Alert.ActionTrigger>Undo</Alert.ActionTrigger>\n  </div>\n</Alert.Root>&#x22;">
  <AnatomyCard />
</Preview>

## Ready-made card [#ready-made-card]

For the common case, the bare &#x2A;*`Alert`** builds the whole card from props — a `type` or a `color` (never both), an optional `icon`, a `title`, and optional `description` and `action`. Unlike `Notification`, it renders with no close button by default; pass `withCloseButton` to opt in.

<Preview align="block" code="&#x22;<Alert\n  type=\&#x22;warning\&#x22;\n  withCloseButton\n  title=\&#x22;Breaking change\&#x22;\n  description=\&#x22;Two breaking changes this release — see the changelog.\&#x22;\n/>&#x22;">
  <Alert type="warning" title="Breaking change" description="Two breaking changes this release — see the changelog." />
</Preview>

<TypeTable
  type="{
  type: { type: '&#x22;success&#x22; | &#x22;error&#x22; | &#x22;warning&#x22; | &#x22;info&#x22;', description: 'Status preset — maps to a hue + a default leading icon. Omit for a neutral card. Exclusive with color.' },
  color: { type: 'Color', description: 'Custom hue for a card with no type. Exclusive with type (a type error if both are passed).' },
  title: { type: 'ReactNode', description: 'The header row content. When omitted, description renders there instead (still in description styling) rather than sitting alone below.' },
  description: { type: 'ReactNode', description: 'Secondary line, below the header row — or in it, if there is no title.' },
  action: { type: 'ReactNode', description: 'Action row (e.g. an ActionTrigger), below the description.' },
  icon: { type: 'ReactNode | null', description: 'Override the leading glyph; null hides it.' },
  withCloseButton: { type: 'boolean', default: 'false', description: 'Render the close (×) button; onClose fires when pressed.' },
  onClose: { type: '() => void', description: 'Invoked when the close (×) button is pressed.' },
  asChild: { type: 'boolean', default: 'false', description: 'Render the card as its only child (e.g. a router link), with the card\'s content inside it. See As a link below.' },
}"
/>

## As a link [#as-a-link]

When the whole card leads somewhere (release notes, the record it reports on), make it a link with `asChild`: pass your router's link as the only child, and the card renders as that link, with its icon, title, description and action inside. Keep `withCloseButton` and interactive `action`s off a linked card, since a button can't sit inside a link.

<Preview align="block" code="&#x22;<Alert\n  asChild\n  type=\&#x22;info\&#x22;\n  title=\&#x22;A new release is out\&#x22;\n  description=\&#x22;See what changed in the changelog.\&#x22;\n>\n  <Link href=\&#x22;/docs/changelog\&#x22; />\n</Alert>&#x22;">
  <Alert type="info" title="A new release is out" description="See what changed in the changelog.">
    <a href="/docs/changelog" />
  </Alert>
</Preview>

## API [#api]

`Alert.Root` — the card surface (the compound primitive). Accepts every `div`/Ark prop (`asChild`, `id`, `style`, …) plus:

<TypeTable
  type="{
  color: { type: 'Color', description: 'Accent palette; drives the --c-* slot vars for the whole card.' },
  asChild: { type: 'boolean', default: 'false', description: 'Render children as the root element (Ark UI polymorphism).' },
  testId: { type: 'string', description: 'Renders as `data-testid` on the root element — works the same whether set via `Alert.Root` or the top-level `Alert` shorthand, since the two render the same node. See [Testing](/docs/testing).' },
}"
/>

## Accessibility [#accessibility]

`Alert` doesn't manage focus or announce itself — it's meant for content that's already present when the page loads, not something that needs to grab attention. If you mount one dynamically in response to a user action (e.g. a form validation error), add your own `role="alert"` (or wrap it in a live region) — `Alert.Root` forwards arbitrary props straight through to the underlying `div`.

To spawn floating, self-dismissing toasts instead, see [**Notification**](/docs/notification) and the [**Notifier**](/docs/notifier).
