پرش به محتوا

هشدار

یک کادر فراخوانی خطی برای خطاهای فرم، هشدارها و تأییدهای موفقیت — پنل‌هایی با رنگ وضعیت و حاشیه‌های نئوبروتالیست و سایه‌های تند.

import { CheckCircle2Icon, InfoIcon } from "lucide-react"

import {

هشدار یک callout درون‌خطی است: آیکون، عنوان، توضیح و یک اقدام اختیاری، چیده روی یک CSS grid. یک div با role="alert" بدون وابستگی — بدون primitive زیرین، یکسان در هر دو backend — با دستور پخت نئوبروتالیستی: حاشیه‌های ضخیم، سایه‌های سخت و تایپوگرافی پررنگ، به‌همراه محور status برای رنگ‌های error، success، warning و info.

برای این موارد از آن استفاده کنید:

  • خطاهای فرم و درخواست — شکست اعتبارسنجی یا API ناموفق را درست کنار همان چیزی که خراب شده نشان دهید.
  • تأیید موفقیت و وضعیت — «تنظیمات ذخیره شد»، «دورهٔ آزمایشی در حال اتمام است»، «پرداخت دریافت شد»، رنگی‌شده با propِ status.
  • Callout با اقدام بعدی — هشدار یا پیشنهاد ارتقا که دکمهٔ AlertAction دارد («فعال‌سازی»، «لغو»، «ارتقا»).

نصب

pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/alert.json
npx shadcn@latest add https://neobrutalism.com/r/base/alert.json
yarn dlx shadcn@latest add https://neobrutalism.com/r/base/alert.json
bunx --bun shadcn@latest add https://neobrutalism.com/r/base/alert.json

کد زیر را کپی کنید و در پروژهٔ خود بچسبانید.

components/ui/alert.tsx
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/utils"

// CSS-grid layout (shadcn-style): drop an icon as a direct child and the alert
// auto-arranges into an icon column + a content column — no manual flex wrapper.
// `has-[>svg]` adds the icon column only when an icon is present. NeoBrutalist
// chrome: hard 2px border, square corners, hard offset shadow.
const alertVariants = cva(
  cn(
    "group/alert relative grid w-full grid-cols-[0_1fr] items-start gap-y-1 rounded border-2 px-4 py-3 text-left text-sm shadow-md",
    "has-[>svg]:grid-cols-[1.25rem_1fr] has-[>svg]:gap-x-3",
    "has-data-[slot=alert-action]:pr-14",
    "[&>svg]:size-5 [&>svg]:translate-y-0.5 [&>svg]:shrink-0 [&>svg]:text-current"
  ),
  {
    variants: {
      // shadcn's variant axis (kept for API compatibility). `solid` is a Neobrutalism
      // addition.
      variant: {
        default:
          "border-border bg-background text-foreground *:data-[slot=alert-description]:text-muted-foreground",
        destructive:
          "border-red-900 bg-red-300 text-red-900 *:data-[slot=alert-description]:text-red-900/80",
        solid:
          "border-border bg-foreground text-background *:data-[slot=alert-description]:text-background/80",
      },
      // Neobrutalism status axis — additive; overrides the variant's colors when set.
      status: {
        error:
          "border-red-900 bg-red-300 text-red-900 *:data-[slot=alert-description]:text-red-900/80",
        success:
          "border-green-900 bg-green-300 text-green-900 *:data-[slot=alert-description]:text-green-900/80",
        warning:
          "border-yellow-900 bg-yellow-300 text-yellow-900 *:data-[slot=alert-description]:text-yellow-900/80",
        info: "border-blue-900 bg-blue-300 text-blue-900 *:data-[slot=alert-description]:text-blue-900/80",
      },
    },
    defaultVariants: {
      variant: "default",
    },
  }
)

function Alert({
  className,
  variant,
  status,
  ...props
}: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
  return (
    <div
      data-slot="alert"
      role="alert"
      className={cn(alertVariants({ variant, status }), className)}
      {...props}
    />
  )
}

function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="alert-title"
      className={cn(
        "col-start-2 min-h-5 font-head text-base leading-tight tracking-tight [&_a]:underline [&_a]:underline-offset-3",
        className
      )}
      {...props}
    />
  )
}

function AlertDescription({
  className,
  ...props
}: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="alert-description"
      className={cn(
        "col-start-2 grid justify-items-start gap-1 text-sm [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p]:leading-relaxed [&_p:not(:last-child)]:mb-4",
        className
      )}
      {...props}
    />
  )
}

function AlertAction({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="alert-action"
      className={cn("absolute top-2 right-2", className)}
      {...props}
    />
  )
}

export { Alert, AlertTitle, AlertDescription, AlertAction, alertVariants }

مسیرهای import را متناسب با ساختار پروژهٔ خود به‌روزرسانی کنید.

استفاده

import {
  Alert,
  AlertAction,
  AlertDescription,
  AlertTitle,
} from "@/components/ui/alert"
<Alert>
  <InfoIcon />
  <AlertTitle>Heads up!</AlertTitle>
  <AlertDescription>
    You can add components and dependencies to your app using the cli.
  </AlertDescription>
  <AlertAction>
    <Button variant="outline">Enable</Button>
  </AlertAction>
</Alert>

ترکیب

برای ساخت Alert از ترکیب زیر استفاده کنید:

Alert
├── Icon
├── AlertTitle
├── AlertDescription
└── AlertAction

نمونه‌ها

پایه

یک alert پایه با آیکون، عنوان و توضیح.

import { CheckCircle2Icon } from "lucide-react"

import {

مخرب

از variant="destructive" برای ساخت یک alert مخرب استفاده کنید.

import { AlertCircleIcon } from "lucide-react"

import {

کنش

از AlertAction برای افزودن یک دکمه یا عنصر کنش دیگر به alert استفاده کنید.

import {
  Alert,
  AlertAction,

رنگ‌های سفارشی

می‌توانید رنگ‌های alert را با افزودن کلاس‌های سفارشی مانند bg-amber-50 dark:bg-amber-950 به کامپوننت Alert سفارشی کنید.

import { AlertTriangleIcon } from "lucide-react"

import {

RTL

برای فعال‌سازی پشتیبانی RTL در Neobrutalism، راهنمای پیکربندی RTL را ببینید.

"use client"

import * as React from "react"

دسترسی‌پذیری

ریشهٔ alert مقدار role="alert" را رندر می‌کند؛ یک live region ادعایی ضمنی: صفحه‌خوان‌ها محتوایش را به‌محض درج در DOM اعلام می‌کنند. اعلام فقط با درج پویا شلیک می‌شود — هشداری که از ابتدا در صفحه باشد مثل متن معمولی خوانده می‌شود؛ پس وقتی باید شنیده شود، آن را به‌صورت شرطی رندر کنید. role="alert" هرگز فوکوس را جابه‌جا نمی‌کند؛ اگر کاربر باید قبل از ادامه پاسخ دهد، به‌جای آن از alert dialog استفاده کنید و AlertAction را میانبر بدانید نه تنها مسیر پیش‌رو.

مرجع API

Alert

کامپوننت Alert یک فراخوان برای جلب توجه کاربر نمایش می‌دهد.

PropTypeDefault
variant"default" | "destructive""default"

AlertTitle

کامپوننت AlertTitle عنوان alert را نمایش می‌دهد.

PropTypeDefault
classNamestring-

AlertDescription

کامپوننت AlertDescription توضیح یا محتوای alert را نمایش می‌دهد.

PropTypeDefault
classNamestring-

AlertAction

کامپوننت AlertAction یک عنصر کنش (مانند یک دکمه) را نمایش می‌دهد که به‌صورت مطلق در گوشهٔ بالا-راست alert قرار می‌گیرد.

PropTypeDefault
classNamestring-