{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "empty-state",
  "title": "Empty State",
  "description": "Centered placeholder for empty lists, tables, and search results with sm/md/lg sizes.",
  "dependencies": [
    "@vllnt/ui@^0.3.0",
    "class-variance-authority"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/empty-state/empty-state.tsx",
      "content": "import { cva, type VariantProps } from \"class-variance-authority\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\n\nimport { cn } from \"@vllnt/ui\";\n\nconst emptyStateVariants = cva(\n  \"flex flex-col items-center justify-center gap-3 text-center text-foreground\",\n  {\n    defaultVariants: {\n      size: \"md\",\n    },\n    variants: {\n      size: {\n        lg: \"px-6 py-16\",\n        md: \"px-4 py-10\",\n        sm: \"px-3 py-6\",\n      },\n    },\n  },\n);\n\nconst titleVariants = cva(\"font-semibold tracking-tight\", {\n  defaultVariants: {\n    size: \"md\",\n  },\n  variants: {\n    size: {\n      lg: \"text-xl\",\n      md: \"text-lg\",\n      sm: \"text-base\",\n    },\n  },\n});\n\nconst descriptionVariants = cva(\"max-w-prose text-muted-foreground\", {\n  defaultVariants: {\n    size: \"md\",\n  },\n  variants: {\n    size: {\n      lg: \"text-base\",\n      md: \"text-sm\",\n      sm: \"text-xs\",\n    },\n  },\n});\n\nconst iconVariants = cva(\n  \"mb-1 flex items-center justify-center rounded-full bg-muted text-muted-foreground [&_svg]:h-1/2 [&_svg]:w-1/2\",\n  {\n    defaultVariants: {\n      size: \"md\",\n    },\n    variants: {\n      size: {\n        lg: \"size-16\",\n        md: \"size-12\",\n        sm: \"size-8\",\n      },\n    },\n  },\n);\n\n/**\n * Visual size for {@link EmptyState}.\n *\n * - `sm` — inline, suitable for compact lists or cards\n * - `md` — section-level (default)\n * - `lg` — full-page placeholder\n *\n * @public\n */\nexport type EmptyStateSize = \"lg\" | \"md\" | \"sm\";\n\n/**\n * Props for {@link EmptyState}.\n *\n * @public\n */\nexport type EmptyStateProps = {\n  /**\n   * Action slot rendered below the description. Compose with `Button` or any\n   * interactive element.\n   */\n  children?: ReactNode;\n  /** Optional secondary text describing the empty condition. */\n  description?: ReactNode;\n  /** Optional icon or illustration shown above the title. */\n  icon?: ReactNode;\n  /** Headline rendered as a heading element. */\n  title?: ReactNode;\n} & ComponentPropsWithoutRef<\"div\"> &\n  VariantProps<typeof emptyStateVariants>;\n\n/**\n * Placeholder for empty lists, tables, and search results. Composes a\n * centered icon, title, description, and an action slot. Announces itself\n * via `role=\"status\"` so assistive tech can pick up state changes\n * (e.g. when filters clear results).\n *\n * @example\n * ```tsx\n * <EmptyState\n *   icon={<Inbox />}\n *   title=\"No results found\"\n *   description=\"Try adjusting your search or filters.\"\n * >\n *   <Button variant=\"outline\" onClick={clearFilters}>Clear filters</Button>\n * </EmptyState>\n * ```\n *\n * @public\n */\nexport const EmptyState = ({\n  children,\n  className,\n  description,\n  icon,\n  ref,\n  role: roleOverride,\n  size,\n  title,\n  ...rest\n}: EmptyStateProps & { ref?: React.Ref<HTMLDivElement> }) => {\n  return (\n    <div\n      className={cn(emptyStateVariants({ size }), className)}\n      ref={ref}\n      role={roleOverride ?? \"status\"}\n      {...rest}\n    >\n      {icon ? (\n        <span aria-hidden=\"true\" className={cn(iconVariants({ size }))}>\n          {icon}\n        </span>\n      ) : null}\n      {title ? <h3 className={cn(titleVariants({ size }))}>{title}</h3> : null}\n      {description ? (\n        <p className={cn(descriptionVariants({ size }))}>{description}</p>\n      ) : null}\n      {children ? (\n        <div className=\"mt-2 flex flex-wrap items-center justify-center gap-2\">\n          {children}\n        </div>\n      ) : null}\n    </div>\n  );\n};\nEmptyState.displayName = \"EmptyState\";\n\nexport { emptyStateVariants };\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component",
  "version": "0.3.0",
  "stability": "stable",
  "examples": [
    {
      "title": "Default",
      "description": "Empty state for an empty list — explain what's empty + offer a single primary action.",
      "code": "import { Button, EmptyState } from \"@vllnt/ui\";\nimport { Inbox } from \"lucide-react\";\n\nexport function Demo() {\n  return (\n    <EmptyState\n      icon={<Inbox className=\"h-8 w-8\" />}\n      title=\"No tickets yet\"\n      description=\"Create your first support ticket to start tracking conversations.\"\n      action={<Button>Create ticket</Button>}\n    />\n  );\n}\n",
      "framework": "react"
    }
  ]
}
