Field
A compound component that provides consistent wrapper structure for form fields with label, helper text, and error messaging. Handles all a11y wiring automatically.
Usage
<Field error={hasError} required>
<Field.Label>Email</Field.Label>
<Field.Control>
<input type="email" />
</Field.Control>
<Field.HelperText>We'll never share your email.</Field.HelperText>
<Field.Error>Please enter a valid email address.</Field.Error>
</Field>
Accessibility
Field automatically wires up:
htmlForon the label pointing to the controlaria-labelledbyon the control whenField.Labelis present (essential for non-labelable elements like<button>,role="switch")aria-describedbyon the control referencing helper text and erroraria-invalidon the control when in error statearia-requiredon the control when required- Screen reader text for required indicator
Self-labelling controls (e.g. Checkbox with label prop): omit Field.Label — the control provides its own accessible name and Field.Control will not inject a phantom aria-labelledby.
import { Field } from '@tangible/ui';
Field props
| Prop | Type | Default | Description |
|---|---|---|---|
children? |
React.ReactNode |
||
className? |
string |
Additional class name for the field wrapper | |
disabled? |
boolean |
false |
Whether the field is disabled |
error? |
boolean |
false |
Whether the field has an error state |
inline? |
boolean |
false |
Inline layout: label and control on same row |
labels? |
FieldLabels |
Overridable strings for i18n. | |
required? |
boolean |
false |
Whether the field is required |
Field.Label
| Prop | Type | Default | Description |
|---|---|---|---|
as? |
"label" | "span" |
'label' |
Element to render. Use 'span' for group controls (RadioGroup, SegmentedControl — anything rendering role="radiogroup"/"group" on a ) where would reference a non-labelable element. The aria-labelledby wiring via Field.Control is unaffected. |
children? |
React.ReactNode |
||
className? |
string |
||
hidden? |
boolean |
false |
Visually hide the label while keeping it accessible |
htmlFor? |
string |
Only in some variants; the others reject it. |
Also accepts the standard attributes of LabelHTMLAttributes (data-*, aria-*, event handlers), passed to the element it renders.
Field.Control
| Prop | Type | Default | Description |
|---|---|---|---|
children |
React.ReactElement |
Field.HelperText
| Prop | Type | Default | Description |
|---|---|---|---|
children? |
React.ReactNode |
||
className? |
string |
Also accepts the standard attributes of HTMLAttributes (data-*, aria-*, event handlers), passed to the element it renders.
Field.Error
| Prop | Type | Default | Description |
|---|---|---|---|
children? |
React.ReactNode |
||
className? |
string |
Also accepts the standard attributes of HTMLAttributes (data-*, aria-*, event handlers), passed to the element it renders.
Examples
-
Hidden Label: Use
hiddenon Field.Label to visually hide the label while keeping it accessible to screen readers. -
Interactive Validation: Field handles the error state display - validation logic stays in the consuming component.
-
Inline: Use
inlineprop to place label and control on the same row. -
Helper Text Above: Slot order determines layout. Place HelperText before Control to show it above the input.
Other stories: Default, Required, With Error, Disabled, With Textarea, Layout Comparison, Multiple Fields.
Component API tokens
Read via fallback, never declared. Set one on an ancestor to restyle every instance under it.
--tui-field-gap--tui-field-label-fg--tui-field-helper-fg--tui-field-error-fg