# Alert

> An in-page live region that surfaces info, success, warning, or danger messages with the correct ARIA role out of the box.

- Category: data-display
- Status: stable (since 1.0.0)
- A11y pattern: https://www.w3.org/WAI/ARIA/apg/patterns/alert/
- Tokens: --cta-background, --foreground-primary, --background-secondary, --foreground-info, --foreground-success, --foreground-warning, --foreground-danger
- Playground: https://design.freecodecamp.org/playground#alert
- npm dependencies: `react@>=18 <20`
- Registry dependencies: [theme](https://design.freecodecamp.org/registry/theme.md)
- Files:
  - `Alert.tsx` → `src/ui/alert/Alert.tsx` (raw: https://design.freecodecamp.org/registry/alert/Alert.tsx)
  - `alert.css` → `src/ui/alert/alert.css` (raw: https://design.freecodecamp.org/registry/alert/alert.css)

## Install (copy source)

1. Ensure the theme is installed once per project - tokens.css + base.css imported globally, fonts available. See https://design.freecodecamp.org/registry/theme.md and https://design.freecodecamp.org/registry/starter.md.
2. Copy the files below into `src/ui/alert/` (adjust to your project layout) and import the CSS once from your global stylesheet, e.g. `@import './ui/alert/alert.css';`.
3. Colors, spacing and type come from tokens - tailor the component by editing the copied source; recolour by editing tokens.css, not the component CSS.

## Usage

Alerts broadcast state changes the user must notice but not always act on.
They render with `role="alert"` so assistive tech announces the content the
moment it appears.

## Usage

```tsx
import { Alert } from './ui/alert/Alert';
<Alert variant='success' title='Saved'>
  Your progress is synced across every device.
</Alert>;
```

## Accessibility

Renders a `div` with `role="alert"` - assistive tech announces the content
immediately. Keep the message concise: screen readers interrupt the user as
soon as the node mounts. For non-urgent feedback reach for `<Callout>` or
`<Toast>` instead.

## Example

```tsx
import { Alert } from './ui/alert/Alert';

<Alert variant="success">All 28 tests pass. Next challenge unlocked.</Alert>
<Alert variant="warning">You have one unsaved edit.</Alert>
<Alert variant="danger">Sign-in failed - check your email address.</Alert>
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `variant` | `enum` | no | `info` |  |
| `title` | `ReactNode` | no | - |  |
| `icon` | `ReactNode` | no | - |  |

## Source: Alert.tsx

```tsx
import React, { forwardRef } from 'react';

export type AlertVariant = 'info' | 'success' | 'warning' | 'danger';

export interface AlertProps extends Omit<
  React.HTMLAttributes<HTMLDivElement>,
  'title'
> {
  variant?: AlertVariant;
  title?: React.ReactNode;
  icon?: React.ReactNode;
}

export const Alert = forwardRef<HTMLDivElement, AlertProps>(
  (
    { variant = 'info', title, icon, className = '', children, ...rest },
    ref
  ) => {
    const classes = ['alert', `alert--${variant}`, className]
      .filter(Boolean)
      .join(' ');
    const structured = title !== undefined || icon !== undefined;
    return (
      <div ref={ref} role='alert' className={classes} {...rest}>
        {icon !== undefined && (
          <span className='alert__icon' aria-hidden='true'>
            {icon}
          </span>
        )}
        {structured ? (
          <div className='alert__body'>
            {title !== undefined && <p className='alert__title'>{title}</p>}
            {children}
          </div>
        ) : (
          children
        )}
      </div>
    );
  }
);
Alert.displayName = 'Alert';
```

## Source: alert.css

```css
.alert {
  display: flex;
  gap: 12px;
  padding: 14px 16px;
  border-left: var(--border-width-thick) solid var(--foreground-quaternary);
  background: var(--background-secondary);
  color: var(--foreground-primary);
}
.alert__icon {
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: var(--fs-lg);
  line-height: 1.2;
}
.alert__body {
  flex: 1 1 auto;
}
.alert__title {
  font-weight: 700;
  margin: 0 0 4px;
  font-size: var(--fs-md);
}
.alert--info {
  border-left-color: var(--highlight-color);
}
.alert--info .alert__icon {
  color: var(--highlight-color);
}
.alert--success {
  border-left-color: var(--success-color);
}
.alert--success .alert__icon {
  color: var(--success-color);
}
.alert--warning {
  border-left-color: var(--warning-color);
}
.alert--warning .alert__icon {
  color: var(--warning-color);
}
.alert--danger {
  border-left-color: var(--danger-color);
}
.alert--danger .alert__icon {
  color: var(--danger-color);
}
```

## HTML / vanilla variant

```html
<div class="alert alert--info">All 28 tests pass.</div>
<div class="alert alert--warning">You have one unsaved edit.</div>
<div class="alert alert--danger">Sign-in failed - check your email address.</div>
```

Interactive behaviours for plain HTML come from the vanilla runtime (data-uikit-* attributes): https://design.freecodecamp.org/registry/vanilla.md - or download https://design.freecodecamp.org/cdn/uikit.global.js once and self-host it (do not hotlink).

## For coding agents

This library is distributed as copyable source, not an npm package. Start at https://design.freecodecamp.org/registry/starter.md, discover components via https://design.freecodecamp.org/llms.txt, and copy files into the consuming project. Keep token names intact; recolour by editing the copied tokens.css.
