پرش به محتوا

Sonner

اخطارهای تودرتوی toast برای تأیید ذخیره‌سازی، بارگذاری‌ها و پنجره‌های لغو — با جلوه‌های نئوبروتالیستی مرزها و سایه‌ها.

"use client"

import { toast } from "sonner"

Sonner toastهای روی‌هم‌چیده و auto-dismiss را با یک فراخوانی toast() روی صفحه می‌گذارد — یک <Toaster /> mount کنید و از هر جا اعلان بفرستید، بدون سیم‌کشی context. این primitiveِ Radix یا Base UI نیست: هر دو variant بک‌اند همان کتابخانهٔ Sonner از emilkowalski را می‌پیچند، با دستور پخت نئوبروتالیستی: حاشیه‌های ضخیم، سایه‌های سخت و تایپوگرافی پررنگ.

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

  • بازخورد اقدام — «ذخیره شد»، «در کلیپ‌بورد کپی شد»، «تنظیمات به‌روز شد» بعد از resolve شدن mutation.
  • عملیات asynctoast.promise() یک آپلود یا deploy را از loading تا success یا error در یک toast ردیابی می‌کند.
  • پنجرهٔ undo — حذف و بایگانی با دکمهٔ اقدام، تا عملیات مخرب دورهٔ ارفاقی بگیرند.

درباره

Sonner توسط emilkowalski توسعه یافته و نگهداری می‌شود.

نصب

دستور زیر را اجرا کنید:

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

کامپوننت Toaster را اضافه کنید.

app/layout.tsx
import { Toaster } from "@/components/ui/sonner"
 
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <head />
      <body>
        <main>{children}</main>
        <Toaster />
      </body>
    </html>
  )
}

وابستگی‌های زیر را نصب کنید:

pnpm add sonner next-themes
npm install sonner next-themes
yarn add sonner next-themes
bun add sonner next-themes

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

components/ui/sonner.tsx
"use client"

import {
  CircleCheckIcon,
  InfoIcon,
  Loader2Icon,
  OctagonXIcon,
  TriangleAlertIcon,
} from "lucide-react"
import { useTheme } from "next-themes"
import { Toaster as Sonner, type ToasterProps } from "sonner"

const Toaster = ({ ...props }: ToasterProps) => {
  const { theme = "system" } = useTheme()

  return (
    <Sonner
      theme={theme as ToasterProps["theme"]}
      className="toaster group"
      icons={{
        success: <CircleCheckIcon className="size-4" />,
        info: <InfoIcon className="size-4" />,
        warning: <TriangleAlertIcon className="size-4" />,
        error: <OctagonXIcon className="size-4" />,
        loading: <Loader2Icon className="size-4 animate-spin" />,
      }}
      toastOptions={{
        // Fully unstyled so the neobrutalist recipe below owns every surface:
        // hard offset shadow, 2px border, square corners, press-down buttons.
        unstyled: true,
        classNames: {
          toast:
            "group/toast relative flex w-(--width) items-center gap-3 rounded border-2 border-border bg-popover p-4 font-sans text-popover-foreground shadow-md",
          content: "flex min-w-0 flex-col gap-0.5",
          title: "font-head text-sm font-medium",
          description: "text-sm text-muted-foreground",
          icon: "shrink-0",
          actionButton:
            "ms-auto h-fit min-w-fit shrink-0 rounded border-2 border-border bg-primary px-2 py-1 text-xs font-medium text-primary-foreground shadow-sm transition-all duration-200 hover:translate-x-0.5 hover:translate-y-0.5 hover:shadow-none",
          cancelButton:
            "ms-auto h-fit min-w-fit shrink-0 rounded border-2 border-border bg-muted px-2 py-1 text-xs font-medium text-foreground shadow-sm transition-all duration-200 hover:translate-x-0.5 hover:translate-y-0.5 hover:shadow-none",
          closeButton:
            "absolute -top-2 -start-2 rounded-full border-2 border-border bg-background p-0.5 transition-colors hover:bg-muted",
          success: "[&_[data-icon]]:text-chart-2",
          warning: "[&_[data-icon]]:text-chart-1",
          error: "[&_[data-icon]]:text-destructive",
        },
      }}
      {...props}
    />
  )
}

export { Toaster }

کامپوننت Toaster را اضافه کنید.

app/layout.tsx
import { Toaster } from "@/components/ui/sonner"
 
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <head />
      <body>
        <Toaster />
        <main>{children}</main>
      </body>
    </html>
  )
}

استفاده

import { toast } from "sonner"
toast("Event has been created.")

نمونه‌ها

انواع

"use client"

import { toast } from "sonner"

توضیح

"use client"

import { toast } from "sonner"

موقعیت

برای تغییر موقعیت toast از پراپ position استفاده کنید.

"use client"

import { toast } from "sonner"

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

الگوی اختصاصی WAI-ARIA APG برای toast وجود ندارد؛ نزدیک‌ترین راهنما الگوی Alert است. Sonner toastها را در live region مودب ARIA رندر می‌کند تا صفحه‌خوان بدون دزدیدن فوکوس اعلامشان کند. ناحیه بیرون ترتیب tab عادی است — فقط از طریق hotkey در دسترس — و تایمر dismiss وقتی stack hover، فوکوس یا تب پنهان است مکث می‌کند.

تعاملات صفحه‌کلید:

کلیدعمل
Alt + Tفوکوس و گسترش stack toast (از طریق propِ hotkey روی Toaster قابل‌پیکربندی)
Tab / Shift + Tabحرکت در toastها و دکمه‌های اقدام / بستن
Enter / Spaceفعال‌سازی دکمهٔ اقدام یا بستن فوکوس‌شده
Escapeجمع کردن stack toast وقتی فوکوس داخل آن است

مرجع API

برای اطلاعات بیشتر، مرجع API Sonner را ببینید.