{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "input-group",
  "title": "Input Group",
  "description": "Composable input shell: InputGroup carries the field appearance with 3 variants (outline, soft, ghost), 3 sizes (sm, md, lg) and 3 tones (neutral, success, danger); InputGroupInput/InputGroupTextarea render transparent controls inside; InputGroupAddon places icons, text or buttons at inline-start, inline-end, block-start or block-end; InputGroupText and InputGroupButton for addon content.",
  "dependencies": [
    "class-variance-authority@^0.7.1"
  ],
  "registryDependencies": [
    "@ai2/button",
    "@ai2/tokens"
  ],
  "files": [
    {
      "path": "registry/ai2/ui/input-group.tsx",
      "content": "\"use client\"\n\nimport type * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/registry/ai2/ui/button\"\n\nconst inputGroupVariants = cva(\n  \"group/input-group relative flex w-full min-w-0 items-center outline-none transition-[color,box-shadow] duration-(--motion-fast) has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-[3px] has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot=input-group-control]:disabled]:pointer-events-none has-[[data-slot=input-group-control]:disabled]:opacity-50 has-[[data-slot=input-group-control][aria-invalid=true]]:border-danger has-[>textarea]:h-auto has-[>textarea]:items-start has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:items-stretch has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:items-stretch has-[>[data-align=inline-start]]:[&>[data-slot=input-group-control]]:ps-2 has-[>[data-align=inline-end]]:[&>[data-slot=input-group-control]]:pe-2 [&_svg]:size-4 [&_svg]:shrink-0 [&_i]:text-base [&_i]:leading-none\",\n  {\n    variants: {\n      variant: {\n        outline: \"border border-field-border bg-transparent shadow-xs dark:bg-input/30\",\n        soft: \"border border-transparent bg-surface-3 dark:bg-input/50\",\n        ghost: \"border border-transparent bg-transparent hover:bg-surface-3\",\n      },\n      size: {\n        sm: \"h-8 rounded-md [&>[data-slot=input-group-control]]:text-sm\",\n        md: \"h-9 rounded-lg [&>[data-slot=input-group-control]]:text-sm\",\n        lg: \"h-10 rounded-lg [&>[data-slot=input-group-control]]:text-base md:[&>[data-slot=input-group-control]]:text-sm\",\n      },\n      tone: {\n        neutral: \"\",\n        success:\n          \"border-success has-[[data-slot=input-group-control]:focus-visible]:border-success has-[[data-slot=input-group-control]:focus-visible]:ring-success/20 dark:has-[[data-slot=input-group-control]:focus-visible]:ring-success/40\",\n        danger:\n          \"border-danger has-[[data-slot=input-group-control]:focus-visible]:border-danger has-[[data-slot=input-group-control]:focus-visible]:ring-danger/20 dark:has-[[data-slot=input-group-control]:focus-visible]:ring-danger/40\",\n      },\n    },\n    defaultVariants: { variant: \"outline\", size: \"md\", tone: \"neutral\" },\n  }\n)\n\ninterface InputGroupProps\n  extends React.ComponentProps<\"div\">,\n    VariantProps<typeof inputGroupVariants> {}\n\nfunction InputGroup({ className, variant, size, tone, ...props }: InputGroupProps) {\n  return (\n    <div\n      role=\"group\"\n      data-slot=\"input-group\"\n      data-variant={variant ?? \"outline\"}\n      data-tone={tone ?? \"neutral\"}\n      className={cn(inputGroupVariants({ variant, size, tone, className }))}\n      {...props}\n    />\n  )\n}\n\nconst inputGroupAddonVariants = cva(\n  \"flex select-none items-center justify-center gap-2 whitespace-nowrap text-sm text-muted-foreground\",\n  {\n    variants: {\n      align: {\n        \"inline-start\": \"order-first ps-3\",\n        \"inline-end\": \"order-last pe-3\",\n        \"block-start\": \"order-first w-full justify-start px-3 pt-2\",\n        \"block-end\": \"order-last w-full justify-start px-3 pb-2\",\n      },\n    },\n    defaultVariants: { align: \"inline-start\" },\n  }\n)\n\ninterface InputGroupAddonProps\n  extends React.ComponentProps<\"div\">,\n    VariantProps<typeof inputGroupAddonVariants> {}\n\nfunction InputGroupAddon({\n  className,\n  align = \"inline-start\",\n  onClick,\n  ...props\n}: InputGroupAddonProps) {\n  return (\n    <div\n      data-slot=\"input-group-addon\"\n      data-align={align}\n      onClick={(event) => {\n        // Clicking passive addon chrome focuses the control; real buttons keep their job.\n        if (!(event.target as HTMLElement).closest(\"button\")) {\n          event.currentTarget.parentElement\n            ?.querySelector<HTMLElement>(\"[data-slot=input-group-control]\")\n            ?.focus()\n        }\n        onClick?.(event)\n      }}\n      className={cn(inputGroupAddonVariants({ align, className }))}\n      {...props}\n    />\n  )\n}\n\nfunction InputGroupText({ className, ...props }: React.ComponentProps<\"span\">) {\n  return (\n    <span\n      data-slot=\"input-group-text\"\n      className={cn(\"flex items-center gap-1.5 text-sm text-muted-foreground\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction InputGroupButton({\n  className,\n  variant = \"ghost\",\n  size = \"icon-xs\",\n  type = \"button\",\n  ...props\n}: React.ComponentProps<typeof Button>) {\n  return (\n    <Button\n      data-slot=\"input-group-button\"\n      variant={variant}\n      size={size}\n      type={type}\n      className={cn(\"shadow-none\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction InputGroupInput({ className, ...props }: React.ComponentProps<\"input\">) {\n  return (\n    <input\n      data-slot=\"input-group-control\"\n      className={cn(\n        \"h-full w-full flex-1 bg-transparent px-3 outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction InputGroupTextarea({\n  className,\n  ...props\n}: React.ComponentProps<\"textarea\">) {\n  return (\n    <textarea\n      data-slot=\"input-group-control\"\n      className={cn(\n        \"field-sizing-content min-h-16 w-full flex-1 resize-none bg-transparent px-3 py-2 outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport {\n  InputGroup,\n  InputGroupAddon,\n  InputGroupText,\n  InputGroupButton,\n  InputGroupInput,\n  InputGroupTextarea,\n  inputGroupVariants,\n  type InputGroupProps,\n  type InputGroupAddonProps,\n}\n",
      "type": "registry:ui"
    }
  ],
  "docs": "Use for icons or actions inside a text field: leading search icon, trailing clear button, kbd hints, prefixes like https://. Focus and invalid state lift from the inner control to the group border. Use FileInput for file uploads instead.",
  "categories": [
    "form"
  ],
  "type": "registry:ui"
}