{
  "name": "Input",
  "type": "component",
  "description": "Single-line text field with optional start and end addons and four visual states.",
  "export": "@gtmi/strix-react/atoms/input",
  "path": "@gtmi/strix-react/atoms/input",
  "figma": {
    "file": "zT3vGm4QlFEI2Jp9nxyFKI",
    "fileName": "Demo components library",
    "nodes": [
      {
        "node": "22:3936",
        "name": ".input-text",
        "section": "Atoms"
      }
    ]
  },
  "props": [
    {
      "name": "state",
      "type": "completed | error | success | warning",
      "description": "Visual state. `error` also sets aria-invalid, so the visual and assistive-tech signals cannot drift apart."
    },
    {
      "name": "startAddon",
      "type": "ReactNode",
      "description": "Slot before the input: a currency symbol, an icon, a fixed prefix. Its presence moves the visual boundary to a container."
    },
    {
      "name": "endAddon",
      "type": "ReactNode",
      "description": "Slot after the input: units, a clear button, a fixed suffix."
    },
    {
      "name": "containerClassName",
      "type": "string",
      "description": "Applied to the addon container, which only exists when an addon is present."
    },
    {
      "name": "className",
      "type": "string",
      "description": "Applied to the input element and merged through cn()."
    }
  ],
  "ai_tags": ["input", "text-field", "form", "primitive"],
  "since": "0.2.0",
  "tokens_used": [
    "--color-surface-field",
    "--color-surface-disabled",
    "--color-border-field-figma",
    "--color-border-field-focus",
    "--color-border-field-error",
    "--color-border-success",
    "--color-border-warning",
    "--color-text-primary",
    "--color-text-muted-figma",
    "--color-text-disabled-on-surface",
    "--spacing-borders-sm",
    "--spacing-borders-md",
    "--spacing-padding-vertical-sm",
    "--spacing-padding-horizontal-md",
    "--spacing-padding-horizontal-med-sm",
    "--radius-large",
    "--text-size-figma-14",
    "--leading-height-figma-14"
  ],
  "notes": "Form-library agnostic: a native <input> under Base UI's Input primitive, driven by value/defaultValue/onChange and a forwarded ref. With an addon present the input switches to an `unstyled` variant and the container paints the background, outline and corners, so the two boundaries never stack.\n\nPORTED FROM FIGMA .input-text (22:3936), and this port emptied FIGMA_DECLINED in build-tokens.mjs. Three values had been refused on accessibility grounds under the rule that an a11y floor outranks the design authority; CLAUDE.md rule 1 reverses exactly that, so all three ship as logged conflicts recorded in docs/FIGMA-EXCEPTIONS.md: the unstroked resting field (fill edge 1.39:1 against the page vs 1.4.11's 3:1), the gray-700 filled boundary (1.40:1 on its own fill) and the gray-400 placeholder (3.84:1 on the fill vs 1.4.3's 4.5 for text). None of the three substitutions was fixing a failure the port introduced.\n\nFIGMA'S `Active` IS THE FILLED STATE, NOT THE FOCUS STATE, and mis-reading it is what made a gray-700 stroke look like a bad focus ring. Dev Mode shows the variant swapping a grey [FieldLabel] placeholder layer for a white value layer, the same way .cellphone-input-text spells `has content`, so the stroke sits on :not(:placeholder-shown) and on state=\"completed\". Error is Figma's only genuine prop. That means Figma draws NO focus and NO hover: both are rule-2 gaps derived from .input-dropdown, the neighbouring field atom, which strokes color/blue/blue-200 #3acefa on hover and when open (7.58:1 on this same fill). success and warning are gaps too and keep their existing roles.\n\nGEOMETRY IS ALL FOUR OF FIGMA'S VALUES: 8px vertical, 16px horizontal, radius/large 10px (which --radius-large already carried -- the exceptions doc's `mint radius-10` item was asking for a token that existed) and a stated 36px frame as h-9. The height is explicit rather than padding-derived because 20px of line height plus 16px of padding plus two 1px borders is 38px under border-box. pointer-coarse:min-h-touch-target still overrides it to 44px, which is a rule-4 addition rather than a conflict.\n\nTHE FILL IS MINTED, NOT RE-POINTED. --color-surface-field is gray-800 #232b45 where --color-surface-secondary is #232e47 -- three points of blue apart -- but Tabs, Sidebar, Avatar, ScenarioCard and Textarea also read the shared surface and none of them is a field. Same reasoning for --color-border-field-error over --color-border-error: the existing #e1948f measures 5.88:1 on this fill, MORE contrast than Figma's #ef223a at 3.30:1, so it was never failing; it simply was not Figma's colour.\n\nA SPECIFICITY DEFECT 1853 PASSING TESTS COULD NOT SEE. The filled-state stroke compiles to :enabled:not(:placeholder-shown), specificity (0,3,0), against a bare .border-border-field-error at (0,1,0) -- so the error border rendered GREY on any field with a value, which is nearly every error field. jsdom applies no CSS, so every state class is repeated at the filled selector's specificity and build.storybook.test.ts asserts that against the compiled stylesheet. Found by decoding the captured PNG.\n\nInput was REMOVED from border-control.test.ts, because --color-border-control is now the boundary for the controls Figma draws no atom for (Checkbox, Radio, Textarea, ToggleGroup) and measuring Figma's 1.40:1 boundary against a 3:1 floor would assert a value this system has decided not to hold. The guard test in each block of that file is what made the removal safe."
}
