Skip to content

Alert

A message block for information, success, warnings and errors. It renders as plain content by default; make it a live region only when it appears in response to something the user did.

Scheduled maintenance
The dashboard will be read-only on Sunday from 02:00 to 03:00 UTC.

Installation

Add Alert to your project with the CK-UI CLI. It copies the source into your project, so the code is yours to change.

Terminal
npx ck-ui-cli@latest add alert
Adds
Alert.tsxto your CK-UI folder (src/components/ck-ui by default)
Installs
@radix-ui/react-slotreact-iconsif your project does not have them yet

First time with CK-UI in this project? Run npx ck-ui-cli@latest init once before adding components. The installation guide explains what it sets up.

Manual installationInstall the packages and copy the files yourself.

Install the following dependencies

Run these commands in your terminal to install the required packages

Terminal
npm install @radix-ui/react-slot react-icons

Create or update your Alert component

Copy this code to create your Alert component

/components/ui/Alert.tsx
"use client";

import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { RiAlertLine, RiCheckboxCircleLine, RiErrorWarningLine, RiInformationLine } from "react-icons/ri";
import { cn } from "@/lib/utils";

/*
 * A static message block. It is not a live region by default: pass role="alert" only when the alert is
 * inserted in response to something the user did and must interrupt, or role="status" for polite news.
 * Parts: Root, Icon, Title, Description, Actions.
 */

export type AlertColor = "neutral" | "info" | "success" | "warning" | "destructive";

const AlertContext = React.createContext<AlertColor>("neutral");

const colorClasses: Record<AlertColor, string> = {
    neutral: "border-border bg-surface",
    info: "border-info-border bg-info-subtle",
    success: "border-success-border bg-success-subtle",
    warning: "border-warning-border bg-warning-subtle",
    destructive: "border-destructive-border bg-destructive-subtle",
};

const iconColorClasses: Record<AlertColor, string> = {
    neutral: "text-muted-foreground",
    info: "text-info-strong",
    success: "text-success-strong",
    warning: "text-warning-strong",
    destructive: "text-destructive-strong",
};

const defaultIcons: Record<AlertColor, React.ElementType> = {
    neutral: RiInformationLine,
    info: RiInformationLine,
    success: RiCheckboxCircleLine,
    warning: RiAlertLine,
    destructive: RiErrorWarningLine,
};

export interface AlertRootProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "color"> {
    /** Intent. Sets the surface, border and icon colour. */
    color?: AlertColor;
}

const Root = React.forwardRef<HTMLDivElement, AlertRootProps>(({ color = "neutral", className, ...props }, ref) => (
    <AlertContext.Provider value={color}>
        <div
            ref={ref}
            data-color={color}
            className={cn(
                // Two columns when an Alert.Icon is present; the text parts sit in the second column.
                "relative grid w-full grid-cols-[0_1fr] items-start gap-y-1 rounded-2xl border p-4 text-foreground",
                "has-[>[data-slot=alert-icon]]:grid-cols-[auto_1fr] has-[>[data-slot=alert-icon]]:gap-x-3",
                colorClasses[color],
                className
            )}
            {...props}
        />
    </AlertContext.Provider>
));
Root.displayName = "Alert.Root";

export interface AlertIconProps extends React.HTMLAttributes<HTMLSpanElement> {
    /** Icon component to render instead of the colour's default icon. */
    as?: React.ElementType;
}

/** Decorative icon. Without `as` or children it shows the default icon for the alert's colour. */
const Icon = React.forwardRef<HTMLSpanElement, AlertIconProps>(({ as, className, children, ...props }, ref) => {
    const color = React.useContext(AlertContext);
    const Glyph = as ?? defaultIcons[color];

    return (
        <span
            ref={ref}
            data-slot="alert-icon"
            aria-hidden="true"
            className={cn("col-start-1 row-start-1 flex size-5 shrink-0 items-center justify-center [&>svg]:size-5", iconColorClasses[color], className)}
            {...props}
        >
            {children ?? <Glyph />}
        </span>
    );
});
Icon.displayName = "Alert.Icon";

export interface AlertTextProps extends React.HTMLAttributes<HTMLDivElement> {
    /** Render the single child (e.g. an <h3>) instead of a <div>. */
    asChild?: boolean;
}

const Title = React.forwardRef<HTMLDivElement, AlertTextProps>(({ asChild = false, className, ...props }, ref) => {
    const Comp = asChild ? Slot : "div";
    return <Comp ref={ref} className={cn("col-start-2 size-label-sm text-foreground", className)} {...props} />;
});
Title.displayName = "Alert.Title";

const Description = React.forwardRef<HTMLDivElement, AlertTextProps>(({ asChild = false, className, ...props }, ref) => {
    const Comp = asChild ? Slot : "div";
    return <Comp ref={ref} className={cn("col-start-2 size-p-sm text-muted-foreground [&_p]:leading-relaxed", className)} {...props} />;
});
Description.displayName = "Alert.Description";

const Actions = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(({ className, ...props }, ref) => (
    <div ref={ref} className={cn("col-start-2 mt-2 flex flex-wrap items-center gap-2", className)} {...props} />
));
Actions.displayName = "Alert.Actions";

export { Root, Icon, Title, Description, Actions };

Test Your Component

  • 1. Add the component to a test page
  • 2. Check all props and variants work as expected
  • 3. Verify responsive behavior
  • 4. Test with different content/data
  • 5. Ensure accessibility features work correctly

Colors

Use color for intent: info, success, warning and destructive. The default is neutral.

New version available
Version 2.4 adds keyboard shortcuts to every list.
Domain verified
Emails from acme.com are now signed.
Storage almost full
You have used 92% of your 20 GB plan.
Payment method declined
Update your card to keep your workspace active.

With Icon

Alert.Icon shows the default icon for the color, or your own icon passed as children (or with as inside a client component). Title and description are both optional.

Your site is live
Deployments now go out automatically on every push to main.
Only an icon and a description: useful for short inline notes.

With Action

Alert.Actions holds buttons or links under the text.

Your trial ends in 3 days
Choose a plan to keep your projects and team members.

Announcing an alert

When an alert appears because of something the user just did (a failed save), add role="alert" so screen readers announce it immediately. Use role="status" for news that can wait.

Accessibility

  • No role by default: alerts that are part of the page when it loads are read in document order, not announced. Adding role="alert" to every alert would interrupt users on every page load.
  • Add role="alert" (assertive) or role="status" (polite) to an alert that is inserted after a user action. Render the alert into the page at that moment; changing an existing alert's role later is not announced reliably.
  • The icon is decorative (aria-hidden). The title and description carry the meaning, so color is never the only signal.
  • Text uses the foreground and muted-foreground tokens; icons use the -strong intent tokens, which keep at least 4.5:1 contrast on the tinted backgrounds in light and dark mode.
  • Use Alert.Title asChild with a heading element when the alert starts a new section of the page.

API Reference

Import the parts with import * as Alert from "@/components/ui/Alert".

Alert.Root

The container. Other HTML attributes, including role, are passed to the div.

PropTypeDefaultDescription
color
"neutral""info""success""warning""destructive"
"neutral"

Intent: sets the surface, border and icon color.

role
"alert""status"
"undefined"

Only for alerts inserted after a user action. Omit for static content.

className"string""undefined"

Additional classes, merged last.

Alert.Icon

Decorative icon in the first column.

PropTypeDefaultDescription
as"React.ElementType""color icon"

Icon component to render, e.g. RiRocketLine. Client components only: from a Server Component, pass the icon as children.

children"ReactNode""undefined"

Custom icon element. Takes precedence over as.

className"string""undefined"

Additional classes, merged last.

Alert.Title

PropTypeDefaultDescription
asChild"boolean""false"

Render a heading (or other element) instead of a div.

className"string""undefined"

Additional classes, merged last.

Alert.Description

PropTypeDefaultDescription
asChild"boolean""false"

Render the single child element instead, merging this part's props and behaviour onto it.

className"string""undefined"

Additional classes, merged last.

Alert.Actions

A wrapping row for buttons and links.

PropTypeDefaultDescription
className"string""undefined"

Additional classes, merged last.