# Input _(no submodules)_ - [input-number](./input-number/input-number.md) — _(no submodules)_- [input](./input.md) — _(no submodules)_- input-number — _(no submodu… - [input.variants](./input.variants.md) — `inputVariants` is the cva (class-variance-authority) configuration that powers every `` render. It is split fro… - [input-number](./input-number/input-number.md) — _(no submodules)_- [input](./input.md) — _(no submodules)_- [input.variants](./input.variants.md) — `inputVariants` is the cva (class-variance-authority) configuration that powers every `` render. It is split fro… - [input-number](./input-number/input-number.md) — _(no submodules)_- [input](./input.md) — _(no submodules)_- input-number — _(no submodules)_- [input](./input.md) — _(no submodules)_- input-number — _(no submod… - [input.variants](./input.variants.md) — `inputVariants` is the cva (class-variance-authority) configuration that powers every `` render. It is split fro… - [input-number](./input-number/input-number.md) — _(no submodules)_- [input](./input.md) — _(no submodules)_- [input.variants](./input.variants.md) — `inputVariants` is the cva (class-variance-authority) configuration that powers every `` render. It is split fro… ## Purpose `` is the chassis primitive form input for `@suaveplan/react-ui`. It renders a native `` element with theme-driven variant resolution, forwards refs to the underlying DOM node, and threads its `placeholder` through the active i18n instance so consumers can never accidentally ship a hardcoded English placeholder. The component is intentionally thin — the shadcn upstream Input recipe is structurally simple and the chassis follows suit, exposing a single `default` variant + `default` size at the cva level so themes carry the visual variation rather than forcing the component to enumerate it. `` participates in the same `data-*` attribute convention as the rest of `@suaveplan/react-ui`: `data-invalid="true"` and `data-disabled="true"` are written when the corresponding props are set, so theme overrides can target error state via a single CSS selector without depending on `aria-invalid` (which the consumer may or may not have set independently). ## Features - Forwards refs to the underlying `` so consumers can focus, select, measure, or animate it directly. - All native `InputHTMLAttributes` are forwarded as-is (`onChange`, `value`, `defaultValue`, `name`, `autoComplete`, `inputMode`, `pattern`, etc.). - `placeholder` typed as `TranslationKey | undefined` — the chassis enforces that the placeholder text is a registered translation key, never a raw English literal. Passing `undefined` skips the attribute entirely. - `invalid` boolean prop drives `data-invalid="true"` on the rendered element so the cva config's `data-[invalid=true]:border-destructive` rule activates. - `disabled` mirrors as `data-disabled="true"` for the parity with shadcn's selector convention. - Theme variant overrides via `useThemedVariants("Input", inputVariants)`. A `ThemePlugin.variantOverrides.Input` may add brand-new size or appearance variants (see the type-safety trade-off in `proposal.md` §"Type-safety trade-off"). - `motion-reduce:transition-none` collapses focus/border transitions for users with `prefers-reduced-motion: reduce`. - Focus styling via `focus-visible:ring-2 focus-visible:ring-ring` — keyboard users get a visible ring; pointer focus does not. - File-input styling via `file:border-0 file:bg-transparent file:text-sm file:font-medium` so `` inherits a sensible button look. ## Usage: Basic Example ```tsx import { Input } from "@suaveplan/react-ui"; export function NameField({ onChange, }: { onChange: (next: string) => void; }) { return ( onChange(event.currentTarget.value)} /> ); } ``` ## Usage: Advanced Example ```tsx import { Input } from "@suaveplan/react-ui"; export function EmailField({ value, error, onChange, }: { value: string; error: string | undefined; onChange: (next: string) => void; }) { return ( onChange(event.currentTarget.value)} /> ); } ``` ## API Reference ### `` `forwardRef` — renders a `` (default `"text"`). #### `InputProps` | Prop | Type | Default | Description | |---|---|---|---| | `variant` | `"default"` | `"default"` | Visual variant. The chassis ships only `default`; themes may extend. | | `size` | `"default"` | `"default"` | Sizing variant. The chassis ships only `default`; themes may extend. | | `placeholder` | `TranslationKey \| undefined` | `undefined` | Translation key resolved against the active i18n instance. Hardcoded literals are rejected at compile time. | | `invalid` | `boolean` | `undefined` | When `true`, writes `data-invalid="true"` on the element so the cva error rules activate. | | `disabled` | `boolean` | `undefined` | Forwarded to the native `` AND mirrored as `data-disabled="true"`. | | `type` | _native_ | `"text"` | Native input type. | | _all native_ `InputHTMLAttributes` | _native_ | _native_ | Forwarded as-is. | #### `inputVariants` The bare cva resolver. Exported so external consumers (`@suaveplan/react-ui-theme-*`, ejected source under `npx shadcn@latest add @suaveplan/input`) can re-use the variants directly without going through `useThemedVariants`. #### Errors - `useTranslation()` is called unconditionally inside the component. When the surrounding tree lacks a `` (or ``), the hook returns its identity-fallback shape — `t(key)` returns the key as the literal. This matches the `react-i18n` "no-throw in production" contract; the component renders, but the rendered placeholder is the raw key. ## Implementation Notes - The variants module is intentionally separate (`input.variants.ts`) so an ejected source copy keeps the cva config in a dedicated file, mirroring the upstream shadcn convention. - `useThemedVariants("Input", inputVariants)` is called unconditionally so the hook order is stable across renders. The hook's memoisation key is `(themeName, "Input")` so a re-render with the same theme returns the same resolver reference. - `placeholder` is omitted entirely when `undefined`, NOT set to the empty string. An empty placeholder attribute would still allocate the placeholder pseudo-element in the user-agent stylesheet and could collide with screen-reader heuristics. - `data-invalid` and `data-disabled` are written when `true`, omitted entirely when `false` or `undefined`. The CVA selector convention is `data-[invalid=true]:…` so an explicit `data-invalid="false"` would not match, but it would clutter the rendered HTML. - The chassis does NOT inject any `aria-invalid` attribute. Consumers who want `aria-invalid="true"` MUST pass it themselves alongside `invalid`. This separation lets the component represent purely visual error state (e.g. "the user has not yet attempted to submit, but we want to indicate the field is required"). - `` inherits the file-input styling rules from the cva base; consumers do not need to layer additional classes for the upload button.