{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "input",
  "type": "registry:ui",
  "title": "Input",
  "description": "A text field built on Base UI's Field, which connects the label, help text and error message to the input. The border has a contrast of at least 3:1.",
  "categories": [
    "atom"
  ],
  "dependencies": [
    "@base-ui-components/react@1.0.0-rc.0"
  ],
  "registryDependencies": [
    "https://facadeui.dev/r/utils.json"
  ],
  "files": [
    {
      "path": "src/ui/input.tsx",
      "type": "registry:ui",
      "target": "components/ui/input.tsx",
      "content": "/**\n * Input — a text field built on Base UI's Field, so the label, description and\n * error are wired to the control for you.\n *\n * Base UI's `Field` generates the ids and the `aria-labelledby`,\n * `aria-describedby` and `aria-invalid` links between the parts. Doing that by\n * hand is where accessible forms usually go wrong — a visually associated label\n * that is not programmatically associated is invisible to assistive tech.\n *\n * a11y notes worth keeping:\n *\n *  - The border uses `--input`, which the token layer holds at 3:1 against the\n *    background (WCAG 1.4.11). It is noticeably darker than `--border`, because\n *    the edge is the only thing identifying the control as a field.\n *  - A required field is marked with the word \"required\" in the label, not with\n *    a bare asterisk whose meaning is a convention rather than information.\n *  - The error is rendered by `Field.Error`, which Base UI associates with the\n *    control, so it is announced rather than merely appearing underneath.\n *  - `aria-invalid` is set explicitly when `error` is passed in. Base UI derives\n *    it from the control's own `ValidityState`, which knows nothing about an\n *    error that came back from a server — so without this, an externally\n *    supplied message is described but the field is not marked invalid.\n *  - 44px tall, matching every other control in the registry.\n *\n * `label` is required. Pass `hideLabel` for a search or subscribe field where\n * the design calls for a placeholder instead — the label stays in the\n * accessibility tree, which a placeholder alone never does.\n *\n * Dependencies: @base-ui-components/react, react, @/lib/utils.\n */\n\nimport { Field } from \"@base-ui-components/react/field\"\nimport { Input as BaseInput } from \"@base-ui-components/react/input\"\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport interface InputProps extends Omit<ComponentPropsWithoutRef<\"input\">, \"size\"> {\n  /** Required. Use `hideLabel` if it should not be visible. */\n  label: ReactNode\n  /** Hides the label visually but keeps it for screen readers. */\n  hideLabel?: boolean\n  /** Help text below the field. It is linked to the field for you. */\n  description?: ReactNode\n  /** Error message. Base UI links it to the field and announces it. */\n  error?: ReactNode\n  /** Shown inside the field at its end, such as a button or a unit. */\n  trailing?: ReactNode\n  /** Classes for the outer Field.Root. */\n  className?: string\n  /** Classes for the `<input>` itself. */\n  inputClassName?: string\n}\n\nexport function Input({\n  label,\n  hideLabel = false,\n  description,\n  error,\n  trailing,\n  className,\n  inputClassName,\n  required,\n  ...props\n}: InputProps) {\n  return (\n    <Field.Root className={cn(\"flex w-full flex-col gap-1.5\", className)}>\n      <Field.Label\n        className={cn(\"text-foreground text-sm font-medium\", hideLabel && \"sr-only\")}\n      >\n        {label}\n        {/* Spelled out, because an asterisk is a convention, not information. */}\n        {required ? <span className=\"text-muted-foreground\"> (required)</span> : null}\n      </Field.Label>\n\n      <div className=\"relative flex w-full items-center\">\n        <BaseInput\n          required={required}\n          // See the header: Base UI cannot infer this from an external error.\n          aria-invalid={error ? true : undefined}\n          className={cn(\n            \"border-input bg-background text-foreground placeholder:text-muted-foreground\",\n            \"h-11 w-full rounded-md border px-3.5 text-base\",\n            \"duration-facade-fast ease-facade-out transition-[border-color,box-shadow]\",\n            \"focus-visible:ring-ring focus-visible:border-ring outline-none focus-visible:ring-2\",\n            \"disabled:cursor-not-allowed disabled:opacity-60\",\n            \"data-[invalid]:border-destructive data-[invalid]:focus-visible:ring-destructive\",\n            trailing && \"pr-28\",\n            inputClassName,\n          )}\n          {...props}\n        />\n        {trailing ? (\n          <span className=\"absolute inset-y-1 right-1 flex items-center\">{trailing}</span>\n        ) : null}\n      </div>\n\n      {description ? (\n        <Field.Description className=\"text-muted-foreground text-pretty text-sm\">\n          {description}\n        </Field.Description>\n      ) : null}\n\n      {/* `match` lets an externally-supplied error show regardless of the\n          control's own ValidityState, which is what a server-side error is. */}\n      <Field.Error\n        className=\"text-destructive text-pretty text-sm\"\n        match={Boolean(error) || undefined}\n      >\n        {error}\n      </Field.Error>\n    </Field.Root>\n  )\n}\n"
    }
  ],
  "docs": "Import styles/facade-tokens.css in your global stylesheet, after @import \"tailwindcss\". Docs: https://facadeui.dev/components/input"
}
