Form Components
Field
Field wires a control to its label, help text and error message. It owns the id, points the label at the control, and links both messages with aria-describedby.
Basic usage
Field wires a control to its label, help text and error message. It generates one id, points the label at the control with htmlFor, and links the description and error with aria-describedby. Pass any control as the child. disabled, required and readOnly set on the Field reach the child control (and every Radio of a child RadioGroup); a prop set on the child itself wins.
We will never share it.
<Field label="Email" description="We will never share it."> <Input type="email" placeholder="you@company.com"/></Field>Label on its own associates text with a control, but nothing links help text or an error message to it. That is what Field adds: without it, a screen reader announces that a control is invalid and never says why.
Rendering the control
Field can render the control itself instead of wrapping one passed as a child. Pass type (a control kind such as select, or a native input type such as email or date) or one of six booleans: textInput, textarea, select, checkbox, switch, radiogroup. Naming none of them keeps the children mode above unchanged.
We never share it.
Sets your default currency.
<Col> <Field type="email" label="Email" description="We never share it." placeholder="you@company.com"/> <Field select label="Region" description="Sets your default currency."> <option>Cyprus</option> <option>Estonia</option> <option>Portugal</option> </Field></Col>Children still reach the rendered control, so an <option> works with select and a <Radio> works with radiogroup, the same way they do when passed to a standalone Select or RadioGroup.
In this self-rendering mode, surface props (appearance, variant, shape, border, ring, shadow, transparent) route to the control rather than the wrapper, and native attributes such as placeholder or defaultValue go to the control too. Layout props and className stay on the wrapper, and ref points at the control. Field's own size still becomes the control's default, the same as in children mode.
Filled and secondary route to the input, not the wrapper.
<Field type="text" filled secondary label="Name" description="Filled and secondary route to the input, not the wrapper."/>Three details are worth knowing before you reach for them.
onChange is typed for whichever control Field might render, so its event target is the union of an input, a select and a textarea. Reading a property that only one of them has needs a cast:
<Field checkbox label="Subscribe" onChange={(e) => setSubscribed((e.target as HTMLInputElement).checked)}/>ref points at the rendered control for every kind except checkbox, where it lands on the element wrapping the box. A form library that reads .checked straight off the ref will not find it there; pass the control as a child and put the ref on it instead.
className stays on the wrapper, but style goes to the control, since only className and tag are treated as wrapper props. Use className to size or place the whole field block.
Checkbox and switch
checkbox and switch lay out inline: the control first, the label beside it, with the description and error below the row. Any explicit direction prop (row, column, rowReverse or columnReverse) drops the inline row and falls back to the plain stacked layout used by every other control.
One email a month.
<Col> <Field checkbox label="Subscribe to the newsletter" description="One email a month."/> <Field switch label="Beta features"/></Col>Error state
Passing error renders the message and marks the control invalid, so the danger cue and the message can never disagree. You do not set invalid yourself.
This name is already taken.
At least 12 characters.
Too short.
<Col> <Field label="Display name" error="This name is already taken."> <Input defaultValue="alex.rivera"/> </Field>
<Field label="Password" description="At least 12 characters." error="Too short." > <Input type="password" defaultValue="short"/> </Field></Col>When both description and error are present, the control is described by both, in that order.
An invalid control gets a danger border and ring plus aria-invalid="true", and on Input a trailing alert icon, so the state is never signalled by colour alone.
Any control
Every form control reads the Field it sits in: Input, Textarea, Select, Checkbox, Radio and Switch.
Sets your default currency.
Markdown is supported.
<Col> <Field label="Region" description="Sets your default currency."> <Select> <option>Cyprus</option> <option>Estonia</option> <option>Portugal</option> </Select> </Field>
<Field label="Release notes" description="Markdown is supported."> <Textarea placeholder="What changed?"/> </Field></Col>Radio groups
A radiogroup is not a labelable element, so Field labels it by reference with aria-labelledby instead of htmlFor, and leaves the individual radios alone.
Change it any time.
<Field label="Billing period" description="Change it any time."> <RadioGroup name="billing" defaultValue="yearly"> <Label row itemsCenter><Radio value="monthly"/> Monthly</Label> <Label row itemsCenter><Radio value="yearly"/> Yearly</Label> </RadioGroup></Field>Sizes
Field's size sets the whole block: the label and the control both take it, and the help and error text sit one step below so they stay subordinate. You set it once, and an explicit size on the control still wins.
<Col> <Field xs label="Extra small"> <Input placeholder="xs"/> </Field> <Field sm label="Small"> <Input placeholder="sm"/> </Field> <Field label="Medium (default)"> <Input placeholder="md"/> </Field> <Field lg label="Large"> <Input placeholder="lg"/> </Field> <Field xl label="Extra large"> <Input placeholder="xl"/> </Field></Col>Shape, variant and appearance
Field is a layout wrapper, so it takes the same surface props as Col: it paints nothing by default (sharp, outline, no padding), and an appearance only shows once you give it a surface with filled or border. Useful for marking a field block that needs attention without touching the control inside it.
No surface of its own.
A border plus an appearance.
A surface plus an appearance.
<Col> <Field label="Default" description="No surface of its own."> <Input placeholder="you@company.com"/> </Field> <Field rounded border danger padding label="Bordered danger" description="A border plus an appearance."> <Input placeholder="you@company.com"/> </Field> <Field rounded filled secondary padding label="Filled secondary" description="A surface plus an appearance."> <Input placeholder="you@company.com"/> </Field></Col>On a dark surface
A field's label, help text and error read off the surface they sit on, so putting the block on a filled Card or Row carries all three with it instead of leaving them in the colours they pin for a light page. filled on a self-rendering Field routes to the control, as every surface prop does.
Visible to your team.
Enter a valid address.
<Card filled> <Field label="Display name" description="Visible to your team."> <Input defaultValue="alex.rivera"/> </Field> <Field textInput filled secondary label="Recovery email" error="Enter a valid address." defaultValue="alex@"/></Card>Only the message text follows the surface. The control keeps its danger border, ring and alert icon, so the error is still marked where it happened. The pinned danger red is tuned for a light page and loses contrast on a dark one.
Bringing your own id
If the control already carries an id, Field adopts it rather than generating one, so the label still points at the right element. Useful with form libraries that own the id.
Case sensitive.
<Field label="Coupon code" description="Case sensitive."> <Input id="coupon" defaultValue="LAUNCH25"/></Field>Field Props
| Prop | Category | Default | Description |
|---|---|---|---|
accent | Appearance | Accent color appearance (rose) | |
danger | Appearance | Danger color appearance (red) | |
info | Appearance | Info color appearance (cyan) | |
inheritAppearance | Appearance | Inherit appearance from parent — suppresses own data-appearance/data-variant, uses parent's CSS variables | |
primary | Appearance | Primary color appearance (gray) | |
secondary | Appearance | Secondary color appearance (gray) | |
success | Appearance | Success color appearance (green) | |
tertiary | Appearance | Tertiary color appearance | |
warning | Appearance | Warning color appearance (amber) | |
desktopStack | Breakpoint | Stack into a column at desktop width and below (max-desktop: 80rem) | |
mobileStack | Breakpoint | Stack into a column at mobile width and below (max-mobile: 48rem) | |
tabletStack | Breakpoint | Stack into a column at tablet width and below (max-tablet: 64rem) | |
checkbox | Control | Render a checkbox, laid out inline with its label | |
radiogroup | Control | Render a radio group; pass the radios as children | |
select | Control | Render a select; pass the options as children | |
switch | Control | Render a switch, laid out inline with its label | |
textarea | Control | Render a multi-line textarea | |
textInput | Control | Render a text input (the default control kind); pair with | |
flex1 | Flex | Take up remaining space (= | |
flexAuto | Flex | Grow but respect intrinsic size (= | |
flexNone | Flex | Don't grow and don't shrink (= | |
margin | Margin | Enable margin on all sides | |
marginB | Margin | Enable only bottom margin | |
marginT | Margin | Enable only top margin | |
marginX | Margin | Enable only horizontal (inline) margin | |
marginY | Margin | Enable only vertical (block) margin | |
noMargin | Margin | Disable margin (reset to 0) | |
noPadding | Padding | ✓ | Disable internal padding |
padding | Padding | Enable internal padding | |
paddingX | Padding | Enable only horizontal padding | |
paddingY | Padding | Enable only vertical padding | |
pill | Shape | Fully rounded corners (circular) | |
rounded | Shape | Medium rounded corners (default) | |
sharp | Shape | ✓ | No rounded corners (square) |
noShrink | Shrink | Prevent the flex item from shrinking below its content size (= | |
lg | Size | Large size | |
md | Size | ✓ | Medium size (default) |
sm | Size | Small size | |
xl | Size | Extra large size | |
xs | Size | Extra small size | |
textCenter | Text Align | Align text to center | |
textEnd | Text Align | Align text to the reading-direction end (right in LTR, left in RTL) | |
textJustify | Text Align | Justify text | |
textLeft | Text Align | Align text to left (physical side, does not flip under RTL) | |
textRight | Text Align | Align text to right (physical side, does not flip under RTL) | |
textStart | Text Align | Align text to the reading-direction start (left in LTR, right in RTL) | |
filled | Variant | Filled variant - solid background with contrasting text color | |
ghost | Variant | Ghost variant - transparent background, no border, appearance-colored text, tinted hover background | |
outline | Variant | ✓ | Outline variant - transparent background with border and colored text (default) |
Layout & utility props (gap, padding, hide, items, justify, ...) — documented on Common Props
| Prop | Category | Default | Description |
|---|---|---|---|
border | Border | Enable border on all sides | |
borderB | Border | Enable border on bottom | |
borderEnd | Border | Enable border on the inline-end side (right in LTR, left in RTL) | |
borderL | Border | Enable border on left | |
borderR | Border | Enable border on right | |
borderStart | Border | Enable border on the inline-start side (left in LTR, right in RTL) | |
borderT | Border | Enable border on top | |
borderX | Border | Enable border on left and right | |
borderY | Border | Enable border on top and bottom | |
noBorder | Border | ✓ | Disable all borders |
block | Display | Block display - takes full width, new line | |
contents | Display | Contents display - element's box is removed, children display as if parent didn't exist | |
flex | Display | ✓ | Flex display - flexbox container |
grid | Display | Grid display - CSS grid container | |
hidden | Display | Hidden display - element is not visible | |
inline | Display | Inline display - flows with text | |
inlineBlock | Display | Inline-block display - inline but with block properties | |
inlineFlex | Display | Inline-flex display - inline flexbox container | |
inlineGrid | Display | Inline-grid display - inline grid container | |
table | Display | Table display - behaves like table element | |
tableCell | Display | Table-cell display - behaves like td element | |
column | Flex Direction | ✓ | Flex direction column (vertical) |
columnReverse | Flex Direction | Flex direction column-reverse | |
row | Flex Direction | Flex direction row (horizontal) | |
rowReverse | Flex Direction | Flex direction row-reverse | |
gap | Gap | ✓ | Enable gap spacing between children |
noGap | Gap | Disable gap spacing | |
hAuto | Height | Set height to auto | |
hFit | Height | Set height to fit-content | |
hFull | Height | Set height to 100% | |
hScreen | Height | Set height to 100vh (viewport height), removes max-height constraint | |
desktopHide | Hide | Hide element on desktop devices and below (max-desktop: 80rem) | |
mobileHide | Hide | Hide element on mobile devices and below (max-mobile: 48rem) | |
tabletHide | Hide | Hide element on tablet devices and below (max-tablet: 64rem) | |
itemsBaseline | Items | Align items to baseline | |
itemsCenter | Items | Align items to center | |
itemsEnd | Items | Align items to end (bottom/right) | |
itemsStart | Items | ✓ | Align items to start (top/left) |
itemsStretch | Items | Stretch items to fill container | |
justifyAround | Justify | Distribute items with space around them | |
justifyBaseline | Justify | Align items along their baseline on main axis | |
justifyBetween | Justify | Distribute items with space between them | |
justifyCenter | Justify | Center items along the main axis | |
justifyEnd | Justify | Pack items toward the end of the main axis | |
justifyEvenly | Justify | Distribute items with equal space around them | |
justifyStart | Justify | Pack items toward the start of the main axis | |
justifyStretch | Justify | Stretch items to fill the main axis | |
overflowAuto | Overflow | Auto overflow - show scrollbars if needed | |
overflowClip | Overflow | Clip overflow - hard clip without scrollbars | |
overflowHidden | Overflow | Hidden overflow - clip content without scrollbars | |
overflowScroll | Overflow | Scroll overflow - always show scrollbars | |
overflowVisible | Overflow | Visible overflow - content extends beyond bounds | |
overflowXAuto | Overflow | Auto overflow on X-axis only | |
overflowXClip | Overflow | Clip overflow on X-axis only | |
overflowXHidden | Overflow | Hidden overflow on X-axis only | |
overflowXScroll | Overflow | Scroll overflow on X-axis only | |
overflowXVisible | Overflow | Visible overflow on X-axis only | |
overflowYAuto | Overflow | Auto overflow on Y-axis only | |
overflowYClip | Overflow | Clip overflow on Y-axis only | |
overflowYHidden | Overflow | Hidden overflow on Y-axis only | |
overflowYScroll | Overflow | Scroll overflow on Y-axis only | |
overflowYVisible | Overflow | Visible overflow on Y-axis only | |
absolute | Position | Absolute positioning | |
fixed | Position | Fixed positioning | |
relative | Position | Relative positioning | |
static | Position | Static positioning | |
sticky | Position | Sticky positioning | |
responsiveSizing | Responsive Sizing | Enable responsive sizing - uses breakpoint-specific classes for font size, padding, and gap | |
insetRing | Ring | Enable the inset ring — emits ring-inset | |
noInsetRing | Ring | ✓ | Disable the inset ring |
noShadow | Shadow | Disable drop shadow | |
shadow | Shadow | Enable drop shadow | |
transparent | Transparent | Disable background color - makes component background transparent | |
wAuto | Width | Set width to auto | |
wFit | Width | Set width to fit-content | |
wFull | Width | ✓ | Set width to 100% |
wScreen | Width | Set width to 100vw (viewport width), removes max-width constraint | |
flexNoWrap | Wrap | Force flex items to stay on single line (may overflow) | |
flexWrap | Wrap | Allow flex items to wrap to new lines when container is too narrow | |
flexWrapReverse | Wrap | Wrap flex items in reverse order (last items wrap first) |