{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "empty-search",
  "title": "Search empty",
  "description": "Styled empty: the Search set. 5 decorative empty variations (QueryEmpty, FilterEmpty, SuggestEmpty, RecentEmpty, ClearEmpty) on the ai2 token system, driven by CSS token transitions and sized sm to xl. Part of the free styled layer.",
  "dependencies": [
    "lucide-react@^1.23.0"
  ],
  "registryDependencies": [
    "@ai2/tokens"
  ],
  "files": [
    {
      "path": "registry/ai2/styled/empty-search.tsx",
      "content": "\"use client\"\n\nimport type * as React from \"react\"\nimport {\n  Clock,\n  Filter,\n  Lightbulb,\n  Search,\n  SearchX,\n  X,\n} from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* Search empty family: 5 \"no results\" empty states. All are specific to a search context: an echo of the query, active filter badges, suggestion chips, recent searches and a clear-filters action. Colour comes ONLY from semantic tokens (transparency via color-mix), size = the padding plus icon and text scale. Renders without props too: the default title, description and a sample query come filled in. Static - no motion. */\n\nexport type StyledSize = \"sm\" | \"md\" | \"lg\" | \"xl\"\n\ntype Scale = {\n  root: string\n  icon: string\n  badge: string\n  title: string\n  description: string\n}\n\nconst scales: Record<StyledSize, Scale> = {\n  sm: {\n    root: \"gap-2 p-6\",\n    icon: \"size-6\",\n    badge: \"size-12\",\n    title: \"text-sm\",\n    description: \"text-xs\",\n  },\n  md: {\n    root: \"gap-3 p-8\",\n    icon: \"size-8\",\n    badge: \"size-16\",\n    title: \"text-base\",\n    description: \"text-sm\",\n  },\n  lg: {\n    root: \"gap-3.5 p-10\",\n    icon: \"size-10\",\n    badge: \"size-20\",\n    title: \"text-lg\",\n    description: \"text-sm\",\n  },\n  xl: {\n    root: \"gap-4 p-12\",\n    icon: \"size-12\",\n    badge: \"size-24\",\n    title: \"text-xl\",\n    description: \"text-base\",\n  },\n}\n\ninterface EmptyProps {\n  className?: string\n  size?: StyledSize\n  icon?: React.ReactNode\n  title?: React.ReactNode\n  description?: React.ReactNode\n  action?: React.ReactNode\n  /** Yankilanan arama sorgusu. */\n  query?: string\n}\n\nconst rootBase = \"flex flex-col items-center justify-center text-center\"\n\nconst iconBase = \"[&_i]:leading-none [&_svg]:size-full\"\n\nconst badgeBase =\n  \"flex items-center justify-center rounded-full border border-border text-muted-foreground [background:color-mix(in_oklab,var(--color-foreground)_6%,transparent)]\"\n\n/* Ortak aksiyon butonu: focus ring + ikon uyumu (svg + i). */\nconst actionBtn =\n  \"inline-flex h-9 items-center justify-center gap-2 rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground outline-none transition-colors duration-(--motion-base) ease-(--motion-ease) hover:bg-primary/90 focus-visible:ring-[3px] focus-visible:ring-ring/50 motion-reduce:transition-none [&_i]:text-base [&_i]:leading-none [&_svg]:size-4 [&_svg]:shrink-0\"\n\nconst ghostBtn =\n  \"inline-flex h-9 items-center justify-center gap-2 rounded-md border border-border bg-transparent px-4 text-sm font-medium text-foreground outline-none transition-colors duration-(--motion-base) ease-(--motion-ease) hover:bg-[color-mix(in_oklab,var(--color-foreground)_6%,transparent)] focus-visible:ring-[3px] focus-visible:ring-ring/50 motion-reduce:transition-none [&_i]:text-base [&_i]:leading-none [&_svg]:size-4 [&_svg]:shrink-0\"\n\n/* A small clickable chip: used in the suggestion / recent-search lists. */\nconst chip =\n  \"inline-flex items-center gap-1.5 rounded-full border border-border px-3 py-1 text-xs text-muted-foreground outline-none transition-colors duration-(--motion-base) ease-(--motion-ease) hover:border-[color-mix(in_oklab,var(--color-primary)_40%,transparent)] hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 motion-reduce:transition-none [&_i]:text-xs [&_i]:leading-none [&_svg]:size-3 [&_svg]:shrink-0\"\n\n/* QueryEmpty: sorguyu basligin icinde tirnak icinde yankilar. */\nexport function QueryEmpty({\n  className,\n  size = \"md\",\n  icon,\n  title,\n  description = \"We could not match that search. Check the spelling or try a broader term.\",\n  action,\n  query = \"quarterly report\",\n}: EmptyProps) {\n  const s = scales[size]\n  return (\n    <div data-slot=\"styled-empty\" className={cn(rootBase, s.root, className)}>\n      <span\n        aria-hidden=\"true\"\n        className={cn(\"text-muted-foreground\", iconBase, s.icon)}\n      >\n        {icon ?? <SearchX />}\n      </span>\n      <p className={cn(\"font-semibold text-foreground\", s.title)}>\n        {title ?? (\n          <>\n            No results for{\" \"}\n            <span className=\"text-primary\">&ldquo;{query}&rdquo;</span>\n          </>\n        )}\n      </p>\n      {description ? (\n        <p className={cn(\"max-w-prose text-muted-foreground\", s.description)}>\n          {description}\n        </p>\n      ) : null}\n      {action ? <div className=\"mt-2\">{action}</div> : null}\n    </div>\n  )\n}\n\n/* FilterEmpty: aktif filtreleri rozet olarak listeler + tumunu temizle aksiyonu. */\nexport function FilterEmpty({\n  className,\n  size = \"md\",\n  icon,\n  title = \"No items match your filters\",\n  description = \"Your current filters are too narrow. Remove one to widen the results.\",\n  action,\n}: EmptyProps) {\n  const s = scales[size]\n  const filters = [\"Status: Archived\", \"Owner: Me\", \"Last 7 days\"]\n  return (\n    <div data-slot=\"styled-empty\" className={cn(rootBase, s.root, className)}>\n      <span aria-hidden=\"true\" className={cn(badgeBase, s.badge)}>\n        <span className={cn(iconBase, s.icon)}>{icon ?? <Filter />}</span>\n      </span>\n      <p className={cn(\"font-semibold text-foreground\", s.title)}>{title}</p>\n      {description ? (\n        <p className={cn(\"max-w-prose text-muted-foreground\", s.description)}>\n          {description}\n        </p>\n      ) : null}\n      <div className=\"mt-1 flex flex-wrap items-center justify-center gap-1.5\">\n        {filters.map((f) => (\n          <span\n            key={f}\n            className=\"inline-flex items-center gap-1.5 rounded-full border border-border px-3 py-1 text-xs text-muted-foreground [background:color-mix(in_oklab,var(--color-foreground)_4%,transparent)]\"\n          >\n            {f}\n          </span>\n        ))}\n      </div>\n      <div className=\"mt-2\">\n        {action ?? (\n          <button type=\"button\" data-slot=\"styled-empty-action\" className={ghostBtn}>\n            <X />\n            Clear all filters\n          </button>\n        )}\n      </div>\n    </div>\n  )\n}\n\n/* SuggestEmpty: sorgu yankisi + tiklanabilir alternatif arama cipleri. */\nexport function SuggestEmpty({\n  className,\n  size = \"md\",\n  icon,\n  title = \"No results found\",\n  description = \"Nothing matched that search. One of these might be what you meant.\",\n  action,\n  query = \"invoicing\",\n}: EmptyProps) {\n  const s = scales[size]\n  const suggestions = [\"invoices\", \"billing\", \"payments\"]\n  return (\n    <div data-slot=\"styled-empty\" className={cn(rootBase, s.root, className)}>\n      <span\n        aria-hidden=\"true\"\n        className={cn(\"text-muted-foreground\", iconBase, s.icon)}\n      >\n        {icon ?? <Lightbulb />}\n      </span>\n      <p className={cn(\"font-semibold text-foreground\", s.title)}>{title}</p>\n      {description ? (\n        <p className={cn(\"max-w-prose text-muted-foreground\", s.description)}>\n          {description}\n        </p>\n      ) : null}\n      <p className=\"text-xs text-muted-foreground\">\n        You searched for &ldquo;{query}&rdquo;\n      </p>\n      <div className=\"mt-1 flex flex-wrap items-center justify-center gap-1.5\">\n        {suggestions.map((sug) => (\n          <button key={sug} type=\"button\" className={chip}>\n            <Search />\n            {sug}\n          </button>\n        ))}\n      </div>\n      {action ? <div className=\"mt-2\">{action}</div> : null}\n    </div>\n  )\n}\n\n/* RecentEmpty: sonuc yokken son aramalari hatirlatir. */\nexport function RecentEmpty({\n  className,\n  size = \"md\",\n  icon,\n  title = \"Nothing to show yet\",\n  description = \"Start typing to search, or pick up one of your recent searches.\",\n  action,\n}: EmptyProps) {\n  const s = scales[size]\n  const recents = [\"design tokens\", \"release notes\", \"team roster\"]\n  return (\n    <div data-slot=\"styled-empty\" className={cn(rootBase, s.root, className)}>\n      <span aria-hidden=\"true\" className={cn(badgeBase, s.badge)}>\n        <span className={cn(iconBase, s.icon)}>{icon ?? <Clock />}</span>\n      </span>\n      <p className={cn(\"font-semibold text-foreground\", s.title)}>{title}</p>\n      {description ? (\n        <p className={cn(\"max-w-prose text-muted-foreground\", s.description)}>\n          {description}\n        </p>\n      ) : null}\n      <div className=\"mt-1 flex flex-wrap items-center justify-center gap-1.5\">\n        {recents.map((r) => (\n          <button key={r} type=\"button\" className={chip}>\n            <Clock />\n            {r}\n          </button>\n        ))}\n      </div>\n      {action ? <div className=\"mt-2\">{action}</div> : null}\n    </div>\n  )\n}\n\n/* ClearEmpty: sorgu rozeti + birincil \"temizle ve tekrar dene\" aksiyonu. */\nexport function ClearEmpty({\n  className,\n  size = \"md\",\n  icon,\n  title = \"That search came up empty\",\n  description = \"Clear the query to browse everything, or refine it and try again.\",\n  action,\n  query = \"acme corp 2025\",\n}: EmptyProps) {\n  const s = scales[size]\n  return (\n    <div data-slot=\"styled-empty\" className={cn(rootBase, s.root, className)}>\n      <span\n        aria-hidden=\"true\"\n        className={cn(\n          \"flex items-center justify-center rounded-2xl border text-primary [background:color-mix(in_oklab,var(--color-primary)_10%,transparent)] [border-color:color-mix(in_oklab,var(--color-primary)_28%,transparent)]\",\n          s.badge\n        )}\n      >\n        <span className={cn(iconBase, s.icon)}>{icon ?? <Search />}</span>\n      </span>\n      <p className={cn(\"font-semibold text-foreground\", s.title)}>{title}</p>\n      <span className=\"inline-flex items-center gap-1.5 rounded-md border border-border px-2.5 py-1 font-mono text-xs text-muted-foreground [background:color-mix(in_oklab,var(--color-foreground)_4%,transparent)]\">\n        {query}\n      </span>\n      {description ? (\n        <p className={cn(\"max-w-prose text-muted-foreground\", s.description)}>\n          {description}\n        </p>\n      ) : null}\n      <div className=\"mt-2\">\n        {action ?? (\n          <button type=\"button\" data-slot=\"styled-empty-action\" className={actionBtn}>\n            <X />\n            Clear search\n          </button>\n        )}\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/ui/empty-search.tsx"
    }
  ],
  "categories": [
    "styled",
    "empty"
  ],
  "type": "registry:component"
}