{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "filter-bar",
  "title": "Filter bar",
  "description": "A wrapping row of FilterPills — the active-filters strip above an inventory/collection grid.",
  "registryDependencies": [
    "@engram/chip",
    "@engram/cn",
    "@engram/tokens"
  ],
  "files": [
    {
      "path": "src/components/filter-bar.tsx",
      "content": "\"use client\";\n\nimport type { CSSProperties, HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../lib/cn.js\";\nimport type { ChipTone } from \"./chip.js\";\n\nconst TONE_VAR: Record<ChipTone, string> = {\n  neutral: \"var(--engram-muted)\",\n  accent: \"var(--engram-accent-2)\",\n  gold: \"var(--engram-gold)\",\n  ok: \"var(--engram-ok)\",\n  warn: \"var(--engram-warn)\",\n  bad: \"var(--engram-bad)\",\n};\n\nexport interface FilterPillProps {\n  /** Pill text. */\n  label: ReactNode;\n  /** Whether the toggle is on (tinted) — for filter toggles. */\n  active?: boolean;\n  /** Toggle handler; when set the body is a button. */\n  onToggle?: () => void;\n  /** Remove handler; when set a trailing × button is shown (removable chips). */\n  onRemove?: () => void;\n  /** Right-aligned count (e.g. matches under this filter). */\n  count?: number | string;\n  /** Active tone color. Defaults to accent. */\n  tone?: ChipTone;\n  className?: string;\n}\n\n/**\n * A single filter pill — a toggle (`onToggle`/`active`) and/or a removable chip\n * (`onRemove` shows a trailing ×). Active pills tint with `tone`. The unit of a\n * {@link FilterBar}; the consumer owns the filter state and predicate.\n */\nexport function FilterPill({\n  label,\n  active = false,\n  onToggle,\n  onRemove,\n  count,\n  tone = \"accent\",\n  className,\n}: FilterPillProps) {\n  const c = TONE_VAR[tone];\n  const activeStyle: CSSProperties = active\n    ? {\n        background: `color-mix(in oklch, ${c} 18%, transparent)`,\n        color: c,\n        borderColor: c,\n      }\n    : {};\n  const body = (\n    <>\n      <span>{label}</span>\n      {count != null ? (\n        <span className=\"text-engram-faint tabular-nums\">{count}</span>\n      ) : null}\n    </>\n  );\n  const bodyClass = cn(\n    \"inline-flex items-center gap-1.5 border px-2 py-0.5 font-engram-display text-[11px] uppercase tracking-[0.08em] transition-colors\",\n    active\n      ? \"border-transparent\"\n      : \"border-engram-border bg-engram-raised text-engram-muted hover:text-engram-fg\",\n  );\n  return (\n    <span className={cn(\"inline-flex items-stretch\", className)}>\n      {onToggle ? (\n        <button\n          type=\"button\"\n          aria-pressed={active}\n          onClick={onToggle}\n          className={bodyClass}\n          style={activeStyle}\n        >\n          {body}\n        </button>\n      ) : (\n        <span className={bodyClass} style={activeStyle}>\n          {body}\n        </span>\n      )}\n      {onRemove ? (\n        <button\n          type=\"button\"\n          aria-label=\"Remove filter\"\n          onClick={onRemove}\n          className=\"inline-flex items-center border border-engram-border border-l-0 bg-engram-raised px-1.5 text-engram-faint transition-colors hover:text-engram-bad\"\n        >\n          <svg viewBox=\"0 0 10 10\" aria-hidden=\"true\" className=\"size-2.5\">\n            <path\n              d=\"M1 1l8 8M9 1l-8 8\"\n              stroke=\"currentColor\"\n              strokeWidth=\"1.6\"\n              fill=\"none\"\n            />\n          </svg>\n        </button>\n      ) : null}\n    </span>\n  );\n}\n\nexport interface FilterBarProps extends HTMLAttributes<HTMLDivElement> {\n  /** Optional \"clear all\" handler; renders a trailing clear button. */\n  onClear?: () => void;\n}\n\n/**\n * A wrapping row of {@link FilterPill}s — the active-filters strip above an\n * inventory/collection grid. Pass pills as `children`; an optional `onClear`\n * adds a trailing clear-all button.\n */\nexport function FilterBar({\n  onClear,\n  className,\n  children,\n  ...props\n}: FilterBarProps) {\n  return (\n    <div\n      className={cn(\"flex flex-wrap items-center gap-1.5\", className)}\n      {...props}\n    >\n      {children}\n      {onClear ? (\n        <button\n          type=\"button\"\n          onClick={onClear}\n          className=\"ml-1 font-engram-display text-[11px] text-engram-faint uppercase tracking-[0.08em] transition-colors hover:text-engram-fg\"\n        >\n          Clear\n        </button>\n      ) : null}\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/engram/filter-bar.tsx"
    }
  ],
  "meta": {
    "level": "component"
  },
  "docs": "Extend without forking: edit the copied source, use `asChild` (Radix Slot) to change the rendered element, pass the typed `annotations` prop for curated data (verdict/tags/per-plug), or use slot / render-prop props for arbitrary content. Requires the @engram/tokens theme (--engram-* CSS variables).",
  "categories": [
    "interaction"
  ],
  "type": "registry:component"
}