Field
An accessible form field. Base UI wires the label, control, description, and error together (ids, aria, validity tracking); Silica styles them. Wrap any Silica control.
Real use · required field with description
As it appears on your ID.
Non-input control via render (Textarea)
Shown on your public profile.
Disabled
Contact your admin to change this.
FieldStatus · attached (border+icon+message panel)
Please enter a valid email address.
This username is already taken — try adding a number.
URL is valid and reachable.
Key is required.
Immutable URL-safe identifier (lowercase, underscores).
FieldStatus · floating (overlays instead of pushing sibling fields)
FieldStatus · detached (for checkboxes/switches/custom controls)
This field is required
Your changes have been saved
Using Field
Silica ships one design system through three paths. They share a class vocabulary but are not interchangeable — pick the one that matches what you are building.
Plain HTML — CSS classes
The Tailwind v4 plugin. Works in any framework or none — Rails, Django, PHP, Go, a static file. This path is complete for Field — it needs no JavaScript, so the classes below are the whole story.
/* in your CSS */
@import "tailwindcss";
@plugin "@wizeworks/silicaui";Root class field, with 13 modifiers:
.field.field-description.field-error.field-label.field-status.field-status-attached.field-status-detached.field-status-error.field-status-floating.field-status-success.field-status-warning.input.select.textarea
React
Typed components over those same classes, with behavior and accessibility from Base UI.
npm i @wizeworks/silicaui-reactimport { Field } from "@wizeworks/silicaui-react";Props
FieldProps
| Prop | Type | Required | Description |
|---|---|---|---|
| status | FieldStatusValue | no | Validation status; drives the control's accent, trailing icon, and (with statusMessage) the message panel. |
| statusMessage | React.ReactNode | no | Shown via an auto-rendered FieldStatus when set (in addition to any FieldStatus you compose manually). |
| loading | boolean | no | Shows a spinner in the control's trailing slot, independent of status. |
| disabledMessage | React.ReactNode | no | Shown next to a disabled control instead of a Tooltip (disabled elements don't fire hover events). |
| floating | boolean | no | Floats the auto-rendered status message out of flow so it never pushes sibling fields — see FieldStatus's floating prop. |
FieldLabelProps
| Prop | Type | Required | Description |
|---|---|---|---|
| required | boolean | no | Appends a required-field asterisk after the label text. |
FieldStatusProps
| Prop | Type | Required | Description |
|---|---|---|---|
| status | FieldStatusValue | no | Overrides the ambient Field status; only needed outside a Field or to show a different color than the field's own. |
| attached | boolean | no | Flush, colored panel directly under a bordered control (default, when inside a Field). |
| floating | boolean | no | Takes the panel out of flow (position: absolute, anchored under the Field) so it never pushes sibling fields up or down as it appears, changes, or disappears — it overlays whatever's below instead. |
Source of the demo above
The exact file that renders the examples above, so it can never drift from them. It imports a few of this site’s own layout helpers (../lib/…), so read it for the component calls rather than copying it whole.
Show source
import { useState } from "react";
import {
Button,
Field,
FieldLabel,
FieldControl,
FieldDescription,
FieldError,
FieldStatus,
Textarea,
} from "@wizeworks/silicaui-react";
import { Section, Stack } from "../lib/Section";
export function FieldDemo() {
const [floatingError, setFloatingError] = useState(false);
return (
<>
<Section title="Real use · required field with description">
<Field className="max-w-sm">
<FieldLabel required>Full name</FieldLabel>
<FieldControl required placeholder="Ada Lovelace" />
<FieldDescription>As it appears on your ID.</FieldDescription>
<FieldError />
</Field>
</Section>
<Section title="Non-input control via render (Textarea)">
<Field className="max-w-sm">
<FieldLabel>Bio</FieldLabel>
<FieldControl render={<Textarea rows={3} />} />
<FieldDescription>Shown on your public profile.</FieldDescription>
</Field>
</Section>
<Section title="Disabled">
<Stack className="max-w-sm">
<Field disabled>
<FieldLabel>Organization</FieldLabel>
<FieldControl defaultValue="Silica UI" />
</Field>
<Field disabled disabledMessage="Contact your admin to change this.">
<FieldLabel>Billing plan</FieldLabel>
<FieldControl defaultValue="Enterprise" />
</Field>
</Stack>
</Section>
<Section title="FieldStatus · attached (border+icon+message panel)">
<Stack className="max-w-sm">
<Field status="error" statusMessage="Please enter a valid email address.">
<FieldLabel>Email</FieldLabel>
<FieldControl defaultValue="sarah@" />
</Field>
<Field status="warning" statusMessage="This username is already taken — try adding a number.">
<FieldLabel>Username</FieldLabel>
<FieldControl defaultValue="sarah_chen" />
</Field>
<Field status="success" statusMessage="URL is valid and reachable.">
<FieldLabel>Website</FieldLabel>
<FieldControl defaultValue="https://sarahchen.dev" />
</Field>
<Field status="error">
<FieldLabel>Status without message</FieldLabel>
<FieldControl defaultValue="test" />
</Field>
<Field status="error" statusMessage="Key is required.">
<FieldLabel required>Key</FieldLabel>
<FieldControl placeholder="case_study" />
<FieldDescription>
Immutable URL-safe identifier (lowercase, underscores).
</FieldDescription>
</Field>
<Field loading>
<FieldLabel>Loading field</FieldLabel>
<FieldControl defaultValue="sarahc" />
</Field>
</Stack>
</Section>
<Section title="FieldStatus · floating (overlays instead of pushing sibling fields)">
<Stack className="max-w-sm">
<Button size="sm" onClick={() => setFloatingError((v) => !v)}>
Toggle error
</Button>
<Field
floating
status={floatingError ? "error" : undefined}
statusMessage={
floatingError ? "Please enter a valid email address." : undefined
}
>
<FieldLabel>Email</FieldLabel>
<FieldControl defaultValue="sarah@" />
</Field>
<Field>
<FieldLabel>Next field (stays put either way)</FieldLabel>
<FieldControl defaultValue="unaffected" />
</Field>
</Stack>
</Section>
<Section title="FieldStatus · detached (for checkboxes/switches/custom controls)">
<Stack className="max-w-sm">
<FieldStatus status="error" attached={false}>
This field is required
</FieldStatus>
<FieldStatus status="success" attached={false}>
Your changes have been saved
</FieldStatus>
</Stack>
</Section>
</>
);
}Vanilla — node tree to HTML
Field — a form-row container (label + control as children). Build a node tree, project it with toHtml(), and let the zero-dependency runtime hydrate it. This is the path for generated or user-authored documents — a site builder, CMS output, a static export.
npm i @wizeworks/silicaui-html @wizeworks/silicaui-behaviorsimport { atom, toHtml } from "@wizeworks/silicaui-html";
const node = atom("Field", "field", { /* props */ }, [/* children */]);
const markup = toHtml(node);Styling on this path is the class string in the second argument — the same classes as the Plain HTML section above. There is no color prop here; write "field field-primary" rather than passing a colour as a prop.
- Takes children
- yes
- Hydrated by
- nothing — this one is static markup
The full API for Field, on every path, is available through the Silica MCP server.