پرش به محتوا

خالی

یک نگه‌دارندهٔ جای خالی برای جستجوهای بدون نتیجه، داشبوردهای خالی و صفحه‌های راه‌اندازی اولیه — آیکون، عنوان و اقدام در قاب‌های نئوبروتالیست.

import { IconFolderCode } from "@tabler/icons-react"
import { ArrowUpRightIcon } from "lucide-react"

حالت خالی جای خالی را وقتی چیزی برای رندر نیست پر می‌کند — اسلات برای آیکون یا آواتار، عنوان، توضیح و فراخوان به اقدام. مجموعه‌ای از divهای ترکیبی بدون‌وابستگی (بدون primitive زیرین) با دستور پخت نئوبروتالیستی: حاشیه‌های ضخیم و تایپ heading پررنگ.

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

  • جستجو و فیلتر بدون نتیجه — بگویید چرا فهرست خالی است و راه reset یا گسترش query را پیشنهاد دهید.
  • صفحهٔ اولین‌اجرا — «هنوز پروژه‌ای نیست» با دکمهٔ ساخت که به قدم بعدی اشاره می‌کند.
  • صندوق و صف خالی‌شده — تأیید کنید فهرست خالی موفقیت است نه خطا.

نصب

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

کد زیر را کپی کرده و در پروژهٔ خود جای‌گذاری کنید.

components/ui/empty.tsx
import { cva, type VariantProps } from "class-variance-authority"

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

function Empty({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="empty"
      className={cn(
        "flex w-full min-w-0 flex-1 flex-col items-center justify-center gap-4 rounded border-2 bg-card p-6 text-center text-balance",
        className
      )}
      {...props}
    />
  )
}

function EmptyHeader({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="empty-header"
      className={cn("flex max-w-sm flex-col items-center gap-2", className)}
      {...props}
    />
  )
}

const emptyMediaVariants = cva(
  "mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0",
  {
    variants: {
      variant: {
        default: "bg-transparent",
        icon: "flex size-8 shrink-0 items-center justify-center rounded-lg bg-muted text-foreground [&_svg:not([class*='size-'])]:size-4",
      },
    },
    defaultVariants: {
      variant: "default",
    },
  }
)

function EmptyMedia({
  className,
  variant = "default",
  ...props
}: React.ComponentProps<"div"> & VariantProps<typeof emptyMediaVariants>) {
  return (
    <div
      data-slot="empty-icon"
      data-variant={variant}
      className={cn(emptyMediaVariants({ variant, className }))}
      {...props}
    />
  )
}

function EmptyTitle({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="empty-title"
      className={cn(
        "cn-font-heading text-sm font-medium tracking-tight",
        className
      )}
      {...props}
    />
  )
}

function EmptyDescription({ className, ...props }: React.ComponentProps<"p">) {
  return (
    <div
      data-slot="empty-description"
      className={cn(
        "text-sm/relaxed text-muted-foreground [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",
        className
      )}
      {...props}
    />
  )
}

function EmptyContent({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="empty-content"
      className={cn(
        "flex w-full max-w-sm min-w-0 flex-col items-center gap-2.5 text-sm text-balance",
        className
      )}
      {...props}
    />
  )
}

export {
  Empty,
  EmptyHeader,
  EmptyTitle,
  EmptyDescription,
  EmptyContent,
  EmptyMedia,
}

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

استفاده

import {
  Empty,
  EmptyContent,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from "@/components/ui/empty"
<Empty>
  <EmptyHeader>
    <EmptyMedia variant="icon">
      <Icon />
    </EmptyMedia>
    <EmptyTitle>No data</EmptyTitle>
    <EmptyDescription>No data found</EmptyDescription>
  </EmptyHeader>
  <EmptyContent>
    <Button>Add data</Button>
  </EmptyContent>
</Empty>

ترکیب

برای ساخت یک حالت Empty از ترکیب زیر استفاده کنید:

Empty
├── EmptyHeader
│   ├── EmptyMedia
│   ├── EmptyTitle
│   └── EmptyDescription
└── EmptyContent

نمونه‌ها

طرح‌کلی

برای ایجاد یک حالت خالی با طرح‌کلی از کلاس کاربردی border استفاده کنید.

import { IconCloud } from "@tabler/icons-react"

import { Button } from "@/components/ui/button"

پس‌زمینه

برای افزودن یک پس‌زمینه به حالت خالی از کاربردی‌های bg-* و bg-gradient-* استفاده کنید.

import { IconBell } from "@tabler/icons-react"
import { RefreshCcwIcon } from "lucide-react"

Avatar

برای نمایش یک آواتار در حالت خالی از کامپوننت EmptyMedia استفاده کنید.

import {
  Avatar,
  AvatarFallback,

گروه آواتار

برای نمایش یک گروه آواتار در حالت خالی از کامپوننت EmptyMedia استفاده کنید.

import { PlusIcon } from "lucide-react"

import {

InputGroup

می‌توانید یک کامپوننت InputGroup را به کامپوننت EmptyContent اضافه کنید.

import { SearchIcon } from "lucide-react"

import {

RTL

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

"use client"

import * as React from "react"

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

حالت خالی presentational است — divهای ساده بدون role یا رفتار صفحه‌کلید، پس چیزی برای سیم‌کشی نیست. آیکون تزئینی EmptyMedia را با aria-hidden="true" علامت بزنید و اقدامات داخل EmptyContent را به‌صورت Button یا لینک واقعی نگه دارید تا focusable بمانند. وقتی empty state بعد از عملیات async جایگزین محتوا می‌شود (جستجویی که بدون نتیجه برمی‌گردد)، از طریق live region اعلامش کنید — خودِ تعویض DOM برای صفحه‌خوان خاموش است.

مرجع API

Empty

کامپوننت اصلی حالت خالی. کامپوننت‌های EmptyHeader و EmptyContent را در بر می‌گیرد.

PropTypeDefault
classNamestring
<Empty>
  <EmptyHeader />
  <EmptyContent />
</Empty>

EmptyHeader

کامپوننت EmptyHeader رسانه، عنوان و توضیحات حالت خالی را در بر می‌گیرد.

PropTypeDefault
classNamestring
<EmptyHeader>
  <EmptyMedia />
  <EmptyTitle />
  <EmptyDescription />
</EmptyHeader>

EmptyMedia

برای نمایش رسانهٔ حالت خالی مانند یک آیکون یا یک تصویر از کامپوننت EmptyMedia استفاده کنید. همچنین می‌توانید از آن برای نمایش کامپوننت‌های دیگر مانند یک آواتار استفاده کنید.

PropTypeDefault
variant"default" | "icon"default
classNamestring
<EmptyMedia variant="icon">
  <Icon />
</EmptyMedia>
<EmptyMedia>
  <Avatar>
    <AvatarImage src="..." />
    <AvatarFallback>CN</AvatarFallback>
  </Avatar>
</EmptyMedia>

EmptyTitle

برای نمایش عنوان حالت خالی از کامپوننت EmptyTitle استفاده کنید.

PropTypeDefault
classNamestring
<EmptyTitle>No data</EmptyTitle>

EmptyDescription

برای نمایش توضیحات حالت خالی از کامپوننت EmptyDescription استفاده کنید.

PropTypeDefault
classNamestring
<EmptyDescription>You do not have any notifications.</EmptyDescription>

EmptyContent

برای نمایش محتوای حالت خالی مانند یک دکمه، ورودی یا یک لینک از کامپوننت EmptyContent استفاده کنید.

PropTypeDefault
classNamestring
<EmptyContent>
  <Button>Add Project</Button>
</EmptyContent>