UNPKG

@spark-web/text-input

Version:

--- title: Text Input storybookPath: forms-textinput--default isExperimentalPackage: false ---

123 lines (100 loc) 6.29 kB
# @spark-web/text-input — AI Context ## What this is A styled single-line text input. Must always be wrapped in a `Field` from `@spark-web/field` — `Field` provides the label, description, message, and all accessibility wiring. Supports leading/trailing adornments (icons, buttons, secondary selects) via `InputAdornment`. ## What this is NOT - Not a textarea — for multi-line input, use a different component - Not usable without `Field` — always wrap in `<Field label="…">` - Not responsible for its own label or validation message ## Exports - `TextInput` — the input element - `InputAdornment` — wrapper for icons/elements placed inside the input ## TextInput props | Prop | Type | Notes | | ------------------ | ------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | | `type` | `'text' \| 'password' \| 'email' \| 'search' \| 'number' \| 'tel' \| 'url'` | Defaults to `'text'` | | `placeholder` | `string` || | `value` | `string` | Controlled value | | `onChange` | `ChangeEventHandler<HTMLInputElement>` || | `name` | `string` || | `autoComplete` | `string` || | `onBlur` | `FocusEventHandler<HTMLInputElement>` || | `onFocus` | `FocusEventHandler<HTMLInputElement>` || | `onInput` | `FormEventHandler<HTMLInputElement>` || | `inputMode` | `'none' \| 'text' \| 'tel' \| 'url' \| 'email' \| 'numeric' \| 'decimal' \| 'search'` | Virtual keyboard hint for mobile | | `required` | `boolean` || | `children` | `InputAdornment` elements | Adornments; must be `InputAdornment` — anything else is filtered out | | `overflowStrategy` | `'truncate' \| 'nowrap'` | Defaults to `'truncate'` | | `data` | `DataAttributeMap` | Test/analytics attributes | `disabled` and `readOnly` are injected via `Field` context — do not pass them directly to `TextInput`. ## InputAdornment props | Prop | Type | Notes | | ------------ | ------------------ | ---------------------------------------------------------------------------- | | `placement` | `'start' \| 'end'` | required — where to place the adornment | | `children` | `ReactElement` | The adornment element (icon, button, etc.) | | `raw` | `boolean` | Opt out of automatic alignment/spacing wrapper | | `fieldLabel` | `string` | Override the parent field label for an inner input (e.g. a select adornment) | Only one adornment per placement is allowed. ## Common patterns ### Search field with icon and clear button ```tsx <Field label="Search users" labelVisibility="hidden"> <TextInput placeholder="Search users" value={search} onChange={e => setSearch(e.target.value)} > <InputAdornment placement="start"> <SearchIcon size="xsmall" tone="placeholder" /> </InputAdornment> {search && ( <InputAdornment placement="end"> <Button label="Clear search" prominence="none" tone="neutral" onClick={() => setSearch('')} > <XIcon /> </Button> </InputAdornment> )} </TextInput> </Field> ``` ### Plain search (icon only, no clear) ```tsx <Field label="Search" labelVisibility="hidden"> <TextInput placeholder="Search…" value={q} onChange={e => setQ(e.target.value)} > <InputAdornment placement="start"> <SearchIcon size="xsmall" tone="placeholder" /> </InputAdornment> </TextInput> </Field> ``` ### With react-hook-form (via ui-components) Prefer `TextInputField` from `@brighte/ui-components` when used with `react-hook-form`. Pass `placeholder` directly, and use `FieldProps` to pass `description` (renders as muted hint text below the label): ```tsx <TextInputField control={control} name="subject" label="Subject" placeholder="Type here..." FieldProps={{ description: 'Enter a brief summary of the issue' }} /> ``` ## Do NOTs - NEVER use `TextInput` without a parent `Field` - NEVER pass non-`InputAdornment` elements as children — they will not render - NEVER put more than one `InputAdornment` at the same placement - NEVER manage `disabled` state directly on `TextInput` — set it on `Field` - NEVER use a raw `<input>` element — always use `TextInput`