> ## Documentation Index
> Fetch the complete documentation index at: https://api.fanvue.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Alert

> Displays a contextual feedback message to the user.

```tsx theme={null}
import { Alert } from "@fanvue/ui";
import type { AlertProps, AlertVariant } from "@fanvue/ui";
```

## Examples

## Interactive Dismissible

<Frame>
  <iframe src={"https://main--697a1b6dd4dad73ee9c0e5f5.chromatic.com/iframe.html?id=components-alert--interactive-dismissible&viewMode=story&shortcuts=false&singleStory=true&globals=theme:light"} width="100%" height="220" style={{border: "none", borderRadius: "8px"}} loading="lazy" title="Alert — Interactive Dismissible" />
</Frame>

```tsx theme={null}
import { useState } from "react";
import { Alert } from "@fanvue/ui";

function Example() {
  const [visible, setVisible] = useState(true);

  return (
    <div className="space-y-4">
      {visible ? (
        <Alert variant="info" closable onClose={() => setVisible(false)}>
          Click the close button to dismiss this alert. It will disappear.
        </Alert>
      ) : (
        <div className="text-gray-500 text-sm">
          Alert dismissed!{" "}
          <button
            type="button"
            onClick={() => setVisible(true)}
            className="cursor-pointer text-info-content underline"
          >
            Show again
          </button>
        </div>
      )}
    </div>
  );
}
```

## With Link

The `action` slot is composable: pass any element and it receives the variant-appropriate link styling via Radix `Slot`. For a Next.js app, pass a router-aware link instead of a plain anchor, e.g. `action={<Link href="/changelog">See what's new</Link>}` where `Link` is imported from `next/link`.

<Frame>
  <iframe src={"https://main--697a1b6dd4dad73ee9c0e5f5.chromatic.com/iframe.html?id=components-alert--with-link&viewMode=story&shortcuts=false&singleStory=true&globals=theme:light"} width="100%" height="220" style={{border: "none", borderRadius: "8px"}} loading="lazy" title="Alert — With Link" />
</Frame>

```tsx theme={null}
import { Alert } from "@fanvue/ui";

<Alert
  variant="info"
  title="Alert title"
  action={<a href="#learn-more">Learn more</a>}
>
  This is the body text for an info in-app alert with a link to more detail.
</Alert>
```

## All Variants

<Frame>
  <iframe src={"https://main--697a1b6dd4dad73ee9c0e5f5.chromatic.com/iframe.html?id=components-alert--all-variants&viewMode=story&shortcuts=false&singleStory=true&globals=theme:light"} width="100%" height="220" style={{border: "none", borderRadius: "8px"}} loading="lazy" title="Alert — All Variants" />
</Frame>

```tsx theme={null}
import { Alert } from "@fanvue/ui";

const VARIANTS = ["info", "success", "warning", "error", "neutral"] as const;

<div className="flex flex-col gap-8">
  {VARIANTS.map((variant) => (
    <div key={variant} className="flex flex-col gap-3">
      <h3 className="typography-body-small-14px-semibold text-content-primary capitalize">
        {variant}
      </h3>
      <Alert variant={variant}>Body text only.</Alert>
      <Alert variant={variant} title="Alert title">
        Body text with a title above it.
      </Alert>
      <Alert variant={variant} closable>
        Body text with a close button.
      </Alert>
      <Alert variant={variant} title="Alert title" closable action={<a href="#more">More</a>}>
        Title, close button and an action link.
      </Alert>
    </div>
  ))}
</div>
```

## Info Closable

<Frame>
  <iframe src={"https://main--697a1b6dd4dad73ee9c0e5f5.chromatic.com/iframe.html?id=components-alert--info-closable&viewMode=story&shortcuts=false&singleStory=true&globals=theme:light"} width="100%" height="220" style={{border: "none", borderRadius: "8px"}} loading="lazy" title="Alert — Info Closable" />
</Frame>

```tsx theme={null}
import { useState } from "react";
import { Alert } from "@fanvue/ui";

function Example() {
  const [visible, setVisible] = useState(true);
  return visible ? (
    <Alert variant="info" closable onClose={() => setVisible(false)}>
      This is a closable info alert.
    </Alert>
  ) : (
    <div className="text-gray-500 text-sm">
      Alert dismissed!{" "}
      <button
        type="button"
        onClick={() => setVisible(true)}
        className="cursor-pointer text-info-content underline"
      >
        Show again
      </button>
    </div>
  );
}
```

## With Link Closable

<Frame>
  <iframe src={"https://main--697a1b6dd4dad73ee9c0e5f5.chromatic.com/iframe.html?id=components-alert--with-link-closable&viewMode=story&shortcuts=false&singleStory=true&globals=theme:light"} width="100%" height="220" style={{border: "none", borderRadius: "8px"}} loading="lazy" title="Alert — With Link Closable" />
</Frame>

```tsx theme={null}
import { useState } from "react";
import { Alert } from "@fanvue/ui";

function Example() {
  const [visible, setVisible] = useState(true);
  return visible ? (
    <Alert
      variant="warning"
      title="Subscription expiring"
      closable
      action={<a href="#renew-now">Renew now</a>}
      onClose={() => setVisible(false)}
    >
      Your subscription will expire in 3 days.
    </Alert>
  ) : (
    <div className="text-gray-500 text-sm">
      Alert dismissed!{" "}
      <button
        type="button"
        onClick={() => setVisible(true)}
        className="cursor-pointer text-warning-content underline"
      >
        Show again
      </button>
    </div>
  );
}
```

## Props

## Alert

Displays a contextual feedback message to the user.

Supports `info`, `success`, `warning`, `error`, and `neutral` variants with a default icon per variant, optional title, description, dismiss button, and an optional composable `action` slot.

Each variant renders a default icon automatically. Pass a custom `icon` to override, or `icon={null}` to hide the icon entirely.

Only the title and description live inside the `role="alert"` live region. The icon, `action`, and close button are rendered outside it so interactive controls are announced and navigated consistently by screen readers.

<ParamField path="action" type="ReactNode">
  Composable action slot rendered beneath the description, outside the `role="alert"` live region. Pass your own element (an `<a>`, a `next/link` `<Link>`, or a `<Button>`) and it receives the variant-appropriate link styling via the Radix `Slot` pattern while remaining a real link/button.
</ParamField>

<ParamField path="closable" type="boolean" default="false">
  Whether to show the close button.
</ParamField>

<ParamField path="closeLabel" type="string" default="Close alert">
  Accessible label for the close button.
</ParamField>

<ParamField path="icon" type="ReactNode">
  Custom icon override. Pass `null` to hide the icon entirely. Each variant shows a default icon when left `undefined`.
</ParamField>

<ParamField path="onClose" type="(() => void)">
  Callback fired when the close button is clicked.
</ParamField>

<ParamField path="title" type="string">
  Optional title text displayed in bold above the description.
</ParamField>

<ParamField path="variant" type="&#x22;info&#x22; | &#x22;success&#x22; | &#x22;warning&#x22; | &#x22;error&#x22; | &#x22;neutral&#x22;" default="info">
  Visual style variant of the alert.
</ParamField>

## Exported types

Also exported from `@fanvue/ui`: `AlertProps`, `AlertVariant`.

***

**Setup:** [Installation](/docs/ui/installation) · [Theming](/docs/ui/theming)
