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-react
import { Field } from "@wizeworks/silicaui-react";

Props

FieldProps
PropTypeRequiredDescription
statusFieldStatusValuenoValidation status; drives the control's accent, trailing icon, and (with statusMessage) the message panel.
statusMessageReact.ReactNodenoShown via an auto-rendered FieldStatus when set (in addition to any FieldStatus you compose manually).
loadingbooleannoShows a spinner in the control's trailing slot, independent of status.
disabledMessageReact.ReactNodenoShown next to a disabled control instead of a Tooltip (disabled elements don't fire hover events).
floatingbooleannoFloats the auto-rendered status message out of flow so it never pushes sibling fields — see FieldStatus's floating prop.
FieldLabelProps
PropTypeRequiredDescription
requiredbooleannoAppends a required-field asterisk after the label text.
FieldStatusProps
PropTypeRequiredDescription
statusFieldStatusValuenoOverrides the ambient Field status; only needed outside a Field or to show a different color than the field's own.
attachedbooleannoFlush, colored panel directly under a bordered control (default, when inside a Field).
floatingbooleannoTakes 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-behaviors
import { 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.