{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "input-group-search",
  "title": "Group-search input",
  "description": "Styled input: the Group-search set. 5 decorative input variations (SearchGroup, ClearGroup, SubmitGroup, FilterGroup, VoiceGroup) 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/input-group-search.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Mic, Search, SlidersHorizontal, X } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* Search input group family: 5 search-bar compositions, with REAL behavior.\n   search (a plain field), clear (the clear button genuinely empties the field and\n   returns focus), submit (form submission is prevented and the query stays in local\n   state), filter (a scope selector + the field), voice (the microphone is ONLY a\n   visual affordance - no microphone/audio API is ever called and there is no fake\n   recording; clicking it merely toggles a visual \"listening\" state). Color comes\n   ONLY from tokens, via alpha color-mix. No motion. Every field has an accessible\n   label. */\n\nexport type StyledSize = \"sm\" | \"md\" | \"lg\" | \"xl\"\n\nconst height: Record<StyledSize, string> = {\n  sm: \"h-8 text-sm\",\n  md: \"h-9 text-sm\",\n  lg: \"h-10 text-base\",\n  xl: \"h-12 text-base\",\n}\n\nconst rootBase =\n  \"group inline-flex w-64 max-w-full items-center overflow-hidden rounded-lg border border-field-border bg-transparent transition-colors duration-(--motion-base) focus-within:border-primary focus-within:ring-[3px] focus-within:ring-ring/50 [&_svg]:size-4 [&_svg]:shrink-0 [&_i]:text-base [&_i]:leading-none\"\n\nconst fieldBase =\n  \"h-full w-full min-w-0 bg-transparent px-2 text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50\"\n\nconst iconBtn =\n  \"mr-1.5 inline-flex size-7 shrink-0 items-center justify-center rounded-md text-muted-foreground outline-none transition-colors hover:bg-[color-mix(in_oklab,var(--color-foreground)_8%,transparent)] hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50\"\n\ntype Props = Omit<React.ComponentProps<\"input\">, \"size\"> & { size?: StyledSize }\n\n/* Search: onde arama ikonu tasiyan yalin arama alani. */\nexport function SearchGroup({ className, size = \"md\", ...props }: Props) {\n  const id = React.useId()\n  return (\n    <div data-slot=\"styled-input-group\" className={cn(rootBase, height[size], className)}>\n      <label htmlFor={id} className=\"sr-only\">\n        Search\n      </label>\n      <Search className=\"ml-3 shrink-0 text-muted-foreground transition-colors group-focus-within:text-primary\" />\n      <input id={id} type=\"search\" placeholder=\"Search\" {...props} className={fieldBase} />\n    </div>\n  )\n}\n\n/* Clear: the button on the right REALLY clears the field and returns focus to it. The button only appears when there is a value. */\nexport function ClearGroup({ className, size = \"md\", ...props }: Props) {\n  const id = React.useId()\n  const [value, setValue] = React.useState(\"\")\n  const inputRef = React.useRef<HTMLInputElement>(null)\n\n  return (\n    <div data-slot=\"styled-input-group\" className={cn(rootBase, height[size], className)}>\n      <label htmlFor={id} className=\"sr-only\">\n        Search with clear\n      </label>\n      <Search className=\"ml-3 shrink-0 text-muted-foreground transition-colors group-focus-within:text-primary\" />\n      <input\n        id={id}\n        ref={inputRef}\n        type=\"search\"\n        placeholder=\"Search\"\n        {...props}\n        value={value}\n        onChange={(e) => setValue(e.target.value)}\n        className={cn(fieldBase, \"[&::-webkit-search-cancel-button]:appearance-none\")}\n      />\n      {value ? (\n        <button\n          type=\"button\"\n          aria-label=\"Clear search\"\n          className={iconBtn}\n          onClick={() => {\n            setValue(\"\")\n            inputRef.current?.focus()\n          }}\n        >\n          <X />\n        </button>\n      ) : null}\n    </div>\n  )\n}\n\n/* Submit: a real form; submission is prevented (no network request), the query is held in local state and announced with aria-live. */\nexport function SubmitGroup({ className, size = \"md\", ...props }: Props) {\n  const id = React.useId()\n  const [value, setValue] = React.useState(\"\")\n  const [submitted, setSubmitted] = React.useState(\"\")\n\n  return (\n    <form\n      data-slot=\"styled-input-group\"\n      className={cn(rootBase, height[size], className)}\n      onSubmit={(e) => {\n        e.preventDefault()\n        setSubmitted(value)\n      }}\n    >\n      <label htmlFor={id} className=\"sr-only\">\n        Search and submit\n      </label>\n      <Search className=\"ml-3 shrink-0 text-muted-foreground transition-colors group-focus-within:text-primary\" />\n      <input\n        id={id}\n        type=\"search\"\n        placeholder=\"Search\"\n        {...props}\n        value={value}\n        onChange={(e) => setValue(e.target.value)}\n        className={fieldBase}\n      />\n      <span aria-live=\"polite\" className=\"sr-only\">\n        {submitted ? `Searched for ${submitted}` : \"\"}\n      </span>\n      <button\n        type=\"submit\"\n        className=\"flex h-full shrink-0 select-none items-center border-l border-field-border bg-secondary px-3 text-sm font-medium text-secondary-foreground outline-none transition-colors hover:bg-surface-3 focus-visible:ring-[3px] focus-visible:ring-ring/50\"\n      >\n        Search\n      </button>\n    </form>\n  )\n}\n\n/* Filter: solda kapsam secimi, sagda filtre ikonu tasiyan arama alani. */\nexport function FilterGroup({ className, size = \"md\", ...props }: Props) {\n  const id = React.useId()\n  return (\n    <div data-slot=\"styled-input-group\" className={cn(rootBase, height[size], className)}>\n      <select\n        aria-label=\"Search scope\"\n        className=\"h-full shrink-0 select-none border-r border-field-border bg-surface-2 pl-3 pr-2 text-muted-foreground outline-none transition-colors focus-visible:ring-[3px] focus-visible:ring-ring/50\"\n      >\n        <option value=\"all\">All</option>\n        <option value=\"docs\">Docs</option>\n        <option value=\"code\">Code</option>\n      </select>\n      <label htmlFor={id} className=\"sr-only\">\n        Filtered search\n      </label>\n      <input id={id} type=\"search\" placeholder=\"Search\" {...props} className={fieldBase} />\n      <SlidersHorizontal className=\"mr-3 shrink-0 text-muted-foreground\" />\n    </div>\n  )\n}\n\n/* Voice: the microphone button is ONLY a visual affordance. No microphone,\n   MediaRecorder or SpeechRecognition API is ever called; the button merely toggles a\n   visual \"listening\" state and announces that state accessibly. */\nexport function VoiceGroup({ className, size = \"md\", ...props }: Props) {\n  const id = React.useId()\n  const [listening, setListening] = React.useState(false)\n\n  return (\n    <div\n      data-slot=\"styled-input-group\"\n      data-listening={listening ? \"true\" : undefined}\n      className={cn(\n        rootBase,\n        height[size],\n        listening && \"border-primary bg-[color-mix(in_oklab,var(--color-primary)_8%,transparent)]\",\n        className\n      )}\n    >\n      <label htmlFor={id} className=\"sr-only\">\n        Voice search\n      </label>\n      <Search className=\"ml-3 shrink-0 text-muted-foreground transition-colors group-focus-within:text-primary\" />\n      <input id={id} type=\"search\" placeholder=\"Search\" {...props} className={fieldBase} />\n      <button\n        type=\"button\"\n        aria-pressed={listening}\n        aria-label={listening ? \"Stop voice input\" : \"Start voice input\"}\n        className={cn(iconBtn, listening && \"bg-primary text-primary-foreground hover:bg-primary\")}\n        onClick={() => setListening((v) => !v)}\n      >\n        <Mic />\n      </button>\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/ui/input-group-search.tsx"
    }
  ],
  "categories": [
    "styled",
    "input"
  ],
  "type": "registry:component"
}