Empty State
ilinxa/empty-stateFreeBlock
The designed answer for empty surfaces — icon or illustration, title, description, capability-gated actions, and a hint, across 6 variants and 3 sizes.
Install it
npx shadcn@latest add https://ui.ilinxa.com/r/empty-state.jsonSource
1"use client";23import { isValidElement, type ReactNode } from "react";4import {5 Inbox,6 Lock,7 SearchX,8 Sparkles,9 TriangleAlert,10 WifiOff,11} from "lucide-react";12import { Button, buttonVariants } from "@/components/ui/button";13import { cn } from "@/lib/utils";14import type {15 EmptyStateAction,16 EmptyStateActionConfig,17 EmptyStateProps,18 EmptyStateSize,19 EmptyStateVariant,20} from "./types";2122/** Per-variant default lucide icon (used when `icon`/`media` are both omitted). */23const VARIANT_ICON: Record<EmptyStateVariant, typeof Inbox> = {24 default: Inbox,25 search: SearchX,26 error: TriangleAlert,27 offline: WifiOff,28 permission: Lock,29 "first-use": Sparkles,30};3132/** Variants that render `role="status" aria-live="polite"` — transient, state-change-driven (I4). */33const TRANSIENT_VARIANTS: ReadonlySet<EmptyStateVariant> = new Set([34 "search",35 "error",36 "offline",37]);3839const SIZE_ROOT_CLASS: Record<EmptyStateSize, string> = {40 sm: "max-w-sm py-6",41 md: "max-w-md py-10",42 lg: "max-w-lg py-16",43};4445const SIZE_TILE_CLASS: Record<EmptyStateSize, string> = {46 sm: "size-12 rounded-xl",47 md: "size-14 rounded-2xl",48 lg: "size-16 rounded-2xl",49};5051const SIZE_ICON_CLASS: Record<EmptyStateSize, string> = {52 sm: "size-5",53 md: "size-6",54 lg: "size-7",55};5657const SIZE_TITLE_CLASS: Record<EmptyStateSize, string> = {58 sm: "text-sm",59 md: "text-base",60 lg: "text-xl",61};6263const SIZE_DESCRIPTION_CLASS: Record<EmptyStateSize, string> = {64 sm: "text-xs",65 md: "text-sm",66 lg: "text-base",67};6869/** 60ms-stagger entrance reveal (tw-animate-css). Never the app-level `reveal-up` keyframe — P-F5. */70const REVEAL = "motion-safe:animate-in motion-safe:fade-in-0 motion-safe:slide-in-from-bottom-2";7172function isActionConfig(action: EmptyStateAction): action is EmptyStateActionConfig {73 return (74 typeof action === "object" &&75 action !== null &&76 !isValidElement(action) &&77 "label" in action78 );79}8081function renderAction(action: EmptyStateAction | undefined, kind: "primary" | "secondary") {82 // Also swallow `false`/`true`/`""` so the conditional-render idiom83 // `action={isAdmin && {…}}` doesn't mount an empty actions row (C5 F2).84 if (action == null || typeof action === "boolean" || action === "") return null;8586 if (!isActionConfig(action)) {87 return action as ReactNode;88 }8990 const { label, onClick, href, disabled } = action;91 const variant = kind === "primary" ? "default" : "outline";9293 if (href) {94// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from ilinxa
All 184 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Account Switcheraccount-switcher | ilinxa | Blocks | Free | 1 dep · 10 files | |
| Account Switcher (deprecated alias)account-switcher-01 | ilinxa | Blocks | Free | no deps | |
| Account Switcher — fixturesaccount-switcher-fixtures | ilinxa | Blocks | Free | no deps | |
| App Sidebarapp-sidebar | ilinxa | Blocks | Free | 1 dep · 37 files | |
| App Sidebar — fixturesapp-sidebar-fixtures | ilinxa | Blocks | Free | no deps | |
| Rich Text Editor (deprecated alias)article-body-01 | ilinxa | Blocks | Free | no deps | |
| Article Metaarticle-meta | ilinxa | Blocks | Free | 1 dep · 4 files | |
| Article Meta (deprecated alias)article-meta-01 | ilinxa | Blocks | Free | no deps |
