Kosong
Tempat penampung untuk hasil pencarian kosong, dasbor kosong, dan layar saat pertama kali dijalankan — ikon, judul, dan tindakan yang dibingkai dengan garis tepi bergaya neobrutalis.
import { IconFolderCode } from "@tabler/icons-react"
import { ArrowUpRightIcon } from "lucide-react"
Empty state mengisi kekosongan saat tidak ada yang bisa dirender — slot untuk ikon atau avatar, judul, deskripsi, dan ajakan bertindak. Komponen ini berupa kumpulan div yang dapat dikomposisikan tanpa dependensi (tanpa primitif di baliknya), ditata dengan resep neobrutalis: garis tepi tebal dan judul bertipografi tegas.
Gunakan komponen ini saat:
- Pencarian dan filter tanpa hasil — jelaskan mengapa daftar kosong dan tawarkan cara mengatur ulang atau memperluas kueri.
- Layar pemakaian pertama — "Belum ada proyek" dengan tombol buat yang menunjuk langsung ke langkah berikutnya.
- Kotak masuk dan antrean yang sudah bersih — tegaskan bahwa daftar kosong adalah keberhasilan, bukan kesalahan.
Instalasi#
pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/empty.jsonnpx shadcn@latest add https://neobrutalism.com/r/base/empty.jsonyarn dlx shadcn@latest add https://neobrutalism.com/r/base/empty.jsonbunx --bun shadcn@latest add https://neobrutalism.com/r/base/empty.json
Salin dan tempel kode berikut ke dalam proyek Anda.
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,
}
Perbarui jalur impor agar sesuai dengan pengaturan proyek Anda.
Penggunaan#
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>Komposisi#
Gunakan komposisi berikut untuk membangun keadaan Empty:
Empty
├── EmptyHeader
│ ├── EmptyMedia
│ ├── EmptyTitle
│ └── EmptyDescription
└── EmptyContentContoh#
Garis Luar#
Gunakan kelas utilitas border untuk membuat keadaan kosong dengan garis luar.
import { IconCloud } from "@tabler/icons-react"
import { Button } from "@/components/ui/button"Latar Belakang#
Gunakan utilitas bg-* dan bg-gradient-* untuk menambahkan latar belakang ke keadaan kosong.
import { IconBell } from "@tabler/icons-react"
import { RefreshCcwIcon } from "lucide-react"
Avatar#
Gunakan komponen EmptyMedia untuk menampilkan avatar dalam keadaan kosong.
import {
Avatar,
AvatarFallback,Grup Avatar#
Gunakan komponen EmptyMedia untuk menampilkan grup avatar dalam keadaan kosong.
import { PlusIcon } from "lucide-react"
import {InputGroup#
Anda dapat menambahkan komponen InputGroup ke komponen EmptyContent.
import { SearchIcon } from "lucide-react"
import {RTL#
Untuk mengaktifkan dukungan RTL di Neobrutalism, lihat panduan konfigurasi RTL.
"use client"
import * as React from "react"Aksesibilitas#
Empty state bersifat presentasional — div biasa tanpa role atau perilaku keyboard, jadi tidak ada yang perlu disambungkan. Tandai ikon EmptyMedia yang murni dekoratif dengan aria-hidden="true", dan pastikan aksi di dalam EmptyContent berupa elemen Button atau tautan sungguhan agar tetap dapat difokus. Jika empty state menggantikan konten setelah operasi asinkron (pencarian yang kembali tanpa hasil), umumkan lewat live region — pergantian DOM itu sendiri tidak terdengar oleh pembaca layar.
Referensi API#
Empty#
Komponen utama dari keadaan kosong. Membungkus komponen EmptyHeader dan EmptyContent.
| Prop | Type | Default |
|---|---|---|
className | string |
<Empty>
<EmptyHeader />
<EmptyContent />
</Empty>EmptyHeader#
Komponen EmptyHeader membungkus media, judul, dan deskripsi keadaan kosong.
| Prop | Type | Default |
|---|---|---|
className | string |
<EmptyHeader>
<EmptyMedia />
<EmptyTitle />
<EmptyDescription />
</EmptyHeader>EmptyMedia#
Gunakan komponen EmptyMedia untuk menampilkan media keadaan kosong seperti ikon atau gambar. Anda juga dapat menggunakannya untuk menampilkan komponen lain seperti avatar.
| Prop | Type | Default |
|---|---|---|
variant | "default" | "icon" | default |
className | string |
<EmptyMedia variant="icon">
<Icon />
</EmptyMedia><EmptyMedia>
<Avatar>
<AvatarImage src="..." />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
</EmptyMedia>EmptyTitle#
Gunakan komponen EmptyTitle untuk menampilkan judul keadaan kosong.
| Prop | Type | Default |
|---|---|---|
className | string |
<EmptyTitle>No data</EmptyTitle>EmptyDescription#
Gunakan komponen EmptyDescription untuk menampilkan deskripsi keadaan kosong.
| Prop | Type | Default |
|---|---|---|
className | string |
<EmptyDescription>You do not have any notifications.</EmptyDescription>EmptyContent#
Gunakan komponen EmptyContent untuk menampilkan konten keadaan kosong seperti tombol, input, atau tautan.
| Prop | Type | Default |
|---|---|---|
className | string |
<EmptyContent>
<Button>Add Project</Button>
</EmptyContent>