dotUI
dotUI
beta
  1. Components
  2. Feedback
  3. Alert

Alert

Displays a callout for user attention.

import { Alert } from "@/lib/components/core/default/alert";

function AlertDemo() {
  return <Alert>You can add components to your app using the cli.</Alert>;
}

Installation

Copy and paste the following code into your project.

import * as React from "react";
import { tv, type VariantProps } from "tailwind-variants";
import { DangerIcon, InfoIcon, SuccessIcon, WarningIcon } from "@/lib/icons";

const alertStyles = tv({
  slots: {
    root: "rounded-lg border p-4 flex items-center gap-4 [&_svg]:size-4",
    title: "font-medium leading-normal tracking-tight mr-1",
    content: "text-sm",
  },
  variants: {
    variant: {
      default: { root: "border text-fg" },
      success: { root: "border border-border-success text-fg-success" },
      warning: { root: "border border-border-warning text-fg-warning" },
      danger: { root: "border border-border-danger text-fg-danger" },
      info: { root: "border border-border-accent text-fg-accent" },
    },
    fill: {
      true: "",
    },
  },
  compoundVariants: [
    { variant: "default", fill: true, className: { root: "bg-bg-muted" } },
    { variant: "success", fill: true, className: { root: "bg-bg-success-muted" } },
    { variant: "warning", fill: true, className: { root: "bg-bg-warning-muted" } },
    { variant: "danger", fill: true, className: { root: "bg-bg-danger-muted" } },
    { variant: "info", fill: true, className: { root: "bg-bg-accent-muted" } },
  ],
  defaultVariants: {
    variant: "default",
    fill: false,
  },
});

const icons = {
  default: <InfoIcon />,
  success: <SuccessIcon />,
  warning: <WarningIcon />,
  danger: <DangerIcon />,
  info: <InfoIcon />,
};

interface AlertProps extends AlertRootProps {
  title?: React.ReactNode;
  icon?: React.ReactNode | null;
  action?: React.ReactNode;
}
const Alert = ({ variant = "default", title, children, icon, action, ...props }: AlertProps) => {
  return (
    <AlertRoot variant={variant} {...props}>
      {icon || icons[variant]}
      <div className="flex-1 space-y-0.5">
        {title && <AlertTitle>{title}</AlertTitle>}
        {children && <AlertContent>{children}</AlertContent>}
      </div>
      {action && <div className="shrink-0">{action}</div>}
    </AlertRoot>
  );
};

interface AlertRootProps
  extends Omit<React.HTMLAttributes<HTMLDivElement>, "title">,
    VariantProps<typeof alertStyles> {}
const AlertRoot = ({ className, variant, fill, ...props }: AlertRootProps) => {
  const { root } = alertStyles({ variant, fill });
  return <div role="alert" className={root({ className })} {...props} />;
};

interface AlertTitleProps
  extends React.HTMLAttributes<HTMLHeadingElement>,
    VariantProps<typeof alertStyles> {} // TODO VERIFY THIS
const AlertTitle = ({ className, ...props }: AlertTitleProps) => {
  const { title } = alertStyles();
  return <h3 className={title({ className })} {...props} />;
};

interface AlertContentProps
  extends React.HTMLAttributes<HTMLElement>,
    VariantProps<typeof alertStyles> {} // TODO VERIFY THIS
const AlertContent = ({ className, ...props }: AlertContentProps) => {
  const { content } = alertStyles();
  return <section className={content({ className })} {...props} />;
};

export type { AlertProps, AlertRootProps, AlertTitleProps, AlertContentProps };
export { Alert, AlertRoot, AlertTitle, AlertContent };

Update the import paths to match your project setup.

Examples

Variants

Use the variant and fill props to change the visual style of the alert.

"use client";

import React from "react";
import { Alert, type AlertProps } from "@/lib/components/core/default/alert";
import { RadioGroup, Radio } from "@/lib/components/core/default/radio-group";
import { Switch } from "@/lib/components/core/default/switch";

type Variant = AlertProps["variant"];

function Demo() {
  const [variant, setVariant] = React.useState<Variant>("default");
  const [fill, setFill] = React.useState(true);

  return (
    <div className="flex items-center gap-8">
      <Alert variant={variant} fill={fill}>
        You can add components to your app using the cli.
      </Alert>
      <Switch isSelected={fill} onChange={setFill}>
        Fill
      </Switch>
      <RadioGroup
        label="Variant"
        value={variant}
        onChange={(newVal) => setVariant(newVal as Variant)}
      >
        <Radio value="default">Default</Radio>
        <Radio value="success">Success</Radio>
        <Radio value="danger">Danger</Radio>
        <Radio value="warning">Warning</Radio>
        <Radio value="info">Info</Radio>
      </RadioGroup>
    </div>
  );
}

Title

Use the title prop to add a title to the alert.

import { Alert } from "@/lib/components/core/default/alert";

function AlertDemo() {
  return <Alert variant="warning" fill title="Your account has been suspended." />;
}

Content

Pass children to the alert to add content.

import { Alert } from "@/lib/components/core/default/alert";

function AlertDemo() {
  return (
    <Alert title="Payment Information">Enter your payment method to complete your purchase.</Alert>
  );
}

Custom icon

Use the icon prop to add a custom icon to the alert. An explicit null value can be used to remove the default icon.

import { Alert } from "@/lib/components/core/default/alert";
import { GlobeIcon } from "@/lib/icons";

function AlertDemo() {
  return <Alert icon={<GlobeIcon />}>Hello world!</Alert>;
}

Action

Use the action prop to add an action to the alert.

import { Alert } from "@/lib/components/core/default/alert";
import { Button } from "@/lib/components/core/default/button";

function AlertDemo() {
  return (
    <Alert
      action={
        <Button variant="primary" size="sm">
          Upgrade
        </Button>
      }
    >
      You are currently on the free plan. Upgrade to unlock more features.
    </Alert>
  );
}

Examples

Composition

If you need to customize things further, you can drop down the composition pattern.

import { AlertContent, AlertRoot, AlertTitle } from "@/lib/components/core/default/alert";
import { Button } from "@/lib/components/core/default/button";
import { WalletIcon } from "@/lib/icons";

function AlertDemo() {
  return (
    <AlertRoot>
      <WalletIcon />
      <div className="flex-1">
        <AlertTitle>Payment Information</AlertTitle>
        <AlertContent>Enter your payment method to complete your purchase.</AlertContent>
      </div>
      <Button variant="primary" size="sm">
        Upgrade
      </Button>
    </AlertRoot>
  );
}

API Reference

Alert accepts all HTML div element props and the following:

PropTypeDefaultDescription
variant
'default' | 'success | 'warning' | 'danger | 'info'
'default'
The visual style of the alert.
fill
boolean
false
Weather the visual style should be filled.

Built by mehdibha. The source code is available on GitHub.