Form Field
A presentational layout wrapper — label row, control slot, and hint/error text. Pure .astro with no runtime JS; drop any control into the slot. Error text replaces help text when present.
Preview
We will never share your email.
<FormField label="Email" helpText="We will never share your email.">
<input type="email" placeholder="you@example.com" />
</FormField> States
Mark a field required, surface an errorText in place of help text, or disabled the whole field.
Permit ID is required.
This field cannot be edited.
<FormField label="Project name" required>
<input type="text" />
</FormField>
<FormField label="Permit ID" errorText="Permit ID is required." required>
<input type="text" aria-invalid="true" />
</FormField>
<FormField label="Locked field" helpText="This field cannot be edited." disabled>
<input type="text" disabled value="Read only" />
</FormField> Sizes
The size prop scales the label; size the control yourself to match.
<FormField label="Extra small label" size="xs"> … </FormField>
<FormField label="Small label" size="sm"> … </FormField>
<FormField label="Medium label" size="md"> … </FormField>
<FormField label="Large label" size="lg"> … </FormField> API
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | '' | Label rendered above the control slot. |
helpText | string | '' | Helper text shown below the control. |
errorText | string | '' | Error message; replaces help text when present. |
required | boolean | false | Renders an asterisk on the label. |
disabled | boolean | false | Dims the field and blocks pointer events. |
size | 'xs' | 'sm' | 'md' | 'lg' | 'md' | Scales the label font size. |
The control goes in the default slot — the wrapper makes no assumptions about it.
Accessibility
- The wrapper is presentational only; associate the label and control yourself (e.g. a
for/idpair) since the slot content is opaque to it. - The required asterisk carries an
aria-label="required". - Set
aria-invalid="true"on the slotted control whenevererrorTextis shown. disableddims the field and blocks pointer events; also disable the underlying control for keyboard users.
Theming surface
Every public token this component reads, extracted from its source at build time.
The Resolves to column walks each token's real lineage —
component → semantic → primitive → raw value — so you
can see exactly where re-pointing it lands. A spoke re-skins by overriding these in
its theme-<slug>.css; component internals are never edited. No
hook for what you need? File it with /request-lego.
| Token | Tier | Resolves to |
|---|---|---|
--form-error-color | component | #ce2c31 via --color-danger-strong → --color-red-11 |
--form-font-size-lg | component | clamp(0.875rem, 0.77rem + 0.52vw, 1.125rem) via --type-size-300 |
--form-font-size-md | component | clamp(0.75rem, 0.66rem + 0.44vw, 0.9375rem) via --type-size-200 |
--form-font-size-sm | component | clamp(0.625rem, 0.56rem + 0.32vw, 0.75rem) via --type-size-100 |
--form-font-size-xs | component | clamp(0.5rem, 0.44rem + 0.3vw, 0.625rem) via --type-size-050 |
--form-help-color | component | #838383 via --color-text-muted → --color-gray-10 |
--form-help-gap | component | 0.25rem via --spacing-100 |
--form-label-color | component | #646464 via --color-text-secondary → --color-gray-11 |
--form-label-gap | component | 0.25rem via --spacing-100 |
--color-danger-strong | semantic | #ce2c31 via --color-red-11 |
--type-size-100 | semantic | clamp(0.625rem, 0.56rem + 0.32vw, 0.75rem) |
--font-weight-medium | primitive | 500 |