# Next.js Bootstrap Alerts

A Next.js Bootstrap alert for App Router pages: theme colors, icons and outline styles, and a dismissible variant that a server component can render.

Alerts tell the user what just happened, or what needs their attention, right where it matters on the page. `Alert` brings Bootstrap's alert to your Next.js pages, in any theme color and with an optional close button. It is in the free and PRO versions of [AdminKit for Next.js](/nextjs/).

`Alert` is a client component: its file starts with `"use client"`, so it also runs in the browser. That is how a dismissible alert keeps its own open state and fades out with Bootstrap's transition, without Bootstrap's JavaScript.

Your page does not need to be a client component for that. In the App Router, pages are server components. They can pass plain values to a client component, but not functions. `variant` and `dismissible` are a string and a boolean, so your page renders `Alert` directly, dismissible or not, as the demo's alerts page does. Only `onClose` is a function, so only an alert with `onClose` needs a client component of your own.

## Example

The alert itself has no padding in AdminKit. Wrap the text in `.alert-message`:

```html
<div class="alert alert-primary" role="alert">
  <div class="alert-message">Your trial ends in 7 days.</div>
</div>
<div class="alert alert-success" role="alert">
  <div class="alert-message">Your changes have been saved.</div>
</div>
<div class="alert alert-danger" role="alert">
  <div class="alert-message">The payment failed. Check your card details.</div>
</div>
<div class="alert alert-warning" role="alert">
  <div class="alert-message">Your storage is almost full.</div>
</div>
```
```tsx code title="src/app/(dashboard)/billing/page.tsx"
import { Alert } from "@/components/bootstrap/alert";
import { pageMetadata } from "@/lib/site";

export const metadata = pageMetadata("/billing");

export default function BillingPage() {
  return (
    <>
      <h1 className="h3 mb-3">Billing</h1>
      <Alert variant="primary">
        <div className="alert-message">Your trial ends in 7 days.</div>
      </Alert>
      <Alert variant="success">
        <div className="alert-message">Your changes have been saved.</div>
      </Alert>
      <Alert variant="danger">
        <div className="alert-message">The payment failed. Check your card details.</div>
      </Alert>
      <Alert variant="warning">
        <div className="alert-message">Your storage is almost full.</div>
      </Alert>
    </>
  );
}
```

`pageMetadata()` reads the page's title and description from `src/data/pages.json`, so a new page needs an entry there (see [Add a page](/nextjs/docs/getting-started/project-structure/#add-a-page)).

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `variant` | `string` | `"primary"` | The color: adds `.alert-<variant>`, such as `success` or `danger` |
| `dismissible` | `boolean` | | Adds a close button; the alert fades out when it is clicked |
| `onClose` | `() => void` | | Called once a dismissed alert has faded out; needs a client component |

Other props, such as `className` and `id`, go to the `.alert` element, which has `role="alert"`. The component is in `src/components/bootstrap/alert.tsx`.

## Dismissing

Let the user close an alert they have read with `dismissible`. It adds a [close button](/nextjs/docs/components/close-button/) before the children, with `.alert-dismissible` and `.fade`. After a click, the alert fades out and renders nothing.

```html
<div class="alert alert-warning alert-dismissible fade show" role="alert">
  <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
  <div class="alert-message">
    <strong>Heads up!</strong> Two invoices are past their due date.
  </div>
</div>
```
```tsx code
<Alert variant="warning" dismissible>
  <div className="alert-message">
    <strong>Heads up!</strong> Two invoices are past their due date.
  </div>
</Alert>
```

Closing an alert only lasts until the next page load, when the alert is back. To keep it closed, store that yourself from `onClose`, for example in `localStorage`. That takes a client component:

```tsx title="src/components/storage-notice.tsx"
"use client";

import { Alert } from "@/components/bootstrap/alert";

export function StorageNotice() {
  return (
    <Alert
      variant="warning"
      dismissible
      onClose={() => localStorage.setItem("storage-notice", "closed")}
    >
      <div className="alert-message">Your storage is almost full.</div>
    </Alert>
  );
}
```

Read the stored value in an effect, which runs after hydration: the moment the browser takes over the HTML that Next.js built. Only then decide whether to render the alert. This keeps the server HTML and the first browser render the same.

## Icons and outline styles

For an icon column, put an `.alert-icon` element before the message. `alert-outline` gives the alert a neutral background and a gray border, and keeps the icon column in the theme color. `alert-outline-coloured` colors the border too.

```html
<div class="alert alert-primary alert-dismissible fade show" role="alert">
  <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
  <div class="alert-icon">
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bell align-middle" aria-hidden="true"><path d="M10.268 21a2 2 0 0 0 3.464 0"></path><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"></path></svg>
  </div>
  <div class="alert-message">You have 3 new notifications.</div>
</div>
<div class="alert alert-primary alert-outline-coloured alert-dismissible fade show" role="alert">
  <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
  <div class="alert-icon">
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bell align-middle" aria-hidden="true"><path d="M10.268 21a2 2 0 0 0 3.464 0"></path><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"></path></svg>
  </div>
  <div class="alert-message">You have 3 new notifications.</div>
</div>
```
```tsx code
import { Bell } from "lucide-react";
import { Alert } from "@/components/bootstrap/alert";

export function NotificationAlerts() {
  return (
    <>
      <Alert variant="primary" dismissible>
        <div className="alert-icon">
          <Bell className="align-middle" />
        </div>
        <div className="alert-message">You have 3 new notifications.</div>
      </Alert>
      <Alert variant="primary" className="alert-outline-coloured" dismissible>
        <div className="alert-icon">
          <Bell className="align-middle" />
        </div>
        <div className="alert-message">You have 3 new notifications.</div>
      </Alert>
    </>
  );
}
```

## Additional content

An alert can hold a whole message: a heading with `.alert-heading`, paragraphs, a divider and links. `.alert-link` gives a link the alert's color. For links to other pages of the app, use `Link` from `next/link`:

```html
<div class="alert alert-success" role="alert">
  <div class="alert-message">
    <h2 class="h4 alert-heading">Import finished</h2>
    <p>1,240 customers were imported. 3 rows were skipped because the email address was missing.</p>
    <hr>
    <p class="mb-0"><a href="#" class="alert-link">Review the customers</a></p>
  </div>
</div>
```
```tsx code
<Alert variant="success">
  <div className="alert-message">
    <h2 className="h4 alert-heading">Import finished</h2>
    <p>1,240 customers were imported. 3 rows were skipped because the email address was missing.</p>
    <hr />
    <p className="mb-0">
      <Link href="/customers" className="alert-link">Review the customers</Link>
    </p>
  </div>
</Alert>
```

## Accessibility

- `Alert` sets `role="alert"`: screen readers announce it when it appears. Pass `role="status"` for a message that can wait. Your props override the default.
- The close button has `aria-label="Close"`.
- After a close, the focused button is gone. In a task flow, move the focus to the next relevant element from `onClose`.
- Say in the text what kind of message it is. The color alone does not tell everyone.

## Related

- [React Bootstrap alerts](/react/docs/components/alerts/): the same component in AdminKit for React (Vite)
- [Bootstrap 5 alerts](/bootstrap/docs/components/alerts/): the alerts of the HTML version
- [Close button](/nextjs/docs/components/close-button/): the button of a dismissible alert
- [Alerts demo](https://nextjs-demo.adminkit.io/ui-alerts)

---

Canonical HTML page: https://adminkit.io/nextjs/docs/components/alerts/

Site overview for agents: https://adminkit.io/llms.txt (expanded: https://adminkit.io/llms-full.txt) · Documentation: https://adminkit.io/bootstrap/docs/ · Questions: support@adminkit.io
