الانتقال إلى المحتوى

فارغ

عنصر بديل لعمليات البحث التي لا تسفر عن نتائج، ولوحات التحكم الفارغة، وشاشات التشغيل الأول — حيث يتم تأطير الرمز والعنوان والإجراء بحدود على الطراز «النيوبروتاليستي».

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

تملأ الحالة الفارغة الفراغ عندما لا يكون هناك ما يتم عرضه — مثل المكان المخصص لأيقونة أو صورة رمزية، أو عنوان، أو وصف، أو عبارة تحث على اتخاذ إجراء. وهي عبارة عن مجموعة من عناصر div القابلة للتركيب والخالية من التبعية (بدون عناصر أولية أساسية)، مصممة وفقًا لأسلوب النيوبروتالية: حدود سميكة وعناوين بخط عريض.

استخدمه عندما:

  • عمليات البحث والتصفية التي لا تسفر عن نتائج — اشرح سبب كون القائمة فارغة وقدم طريقة لإعادة تعيين الاستعلام أو توسيع نطاقه.
  • شاشات التشغيل الأول — «لا توجد مشاريع حتى الآن» مع زر إنشاء يشير إلى الخطوة التالية مباشرةً.
  • صناديق الوارد وقوائم الانتظار الفارغة — تأكيد أن القائمة الفارغة تعني النجاح، وليست خطأً.

التثبيت

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 {
  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,

مجموعة Avatar

استخدم مكوّن 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"

إمكانية الوصول

الحالة الفارغة هي حالة عرضية — عناصر div بسيطة لا تحتوي على أدوار أو سلوكيات لوحة المفاتيح، لذا لا يوجد ما يتعين ربطه. قم بتمييز أيقونة EmptyMedia الزخرفية البحتة باستخدام aria-hidden="true"، واحتفظ بالإجراءات الموجودة في EmptyContent كعناصر Button أو رابط حقيقية حتى تظل قابلة للتركيز. عندما تحل الحالة الفارغة محل المحتوى بعد عملية غير متزامنة (مثل عملية بحث لا تسفر عن أي نتائج)، قم بالإعلان عن ذلك عبر منطقة حية — حيث إن عملية تبديل 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>