Field handbook
v1.4.1 · @snowui-design-system/components
License: Before reading component documentation, source, or npm usage instructions for the first time, read the full LICENSE. Reuse that review for the same task and version. Public API configuration and internal implementation changes have different license implications. All components use the unified runtime package; source rights remain governed by the license.
Overview
Combine input controls, labels, icons, and validation feedback into a complete form field with consistent appearance and spacing.
When to use it
Use Field to combine labels, controls, help text, and errors. Inside Field, Input, Select, and Textarea share one visual surface; mark connected input sections with as="segment" so borders and error regions are not duplicated.
labelanderrorsupply default text;invalidandreadonlyexpress field state.Use
childrento compose Input, Select, Textarea, and accessories.partsconfigures generated label and error Text; configure explicit children directly.
Quick start
This example shows the recommended basic composition. See the sections below for more cases and composition limits.
API
See the base component documentation for inherited capabilities not redeclared here. This table lists only named public Props declared by this component.
Usage boundaries and details
Form composition and spacing
Default rhythm: Field padding is 12px vertical / 16px horizontal; gap is 8px.
Standalone Input, Select, and Textarea each have their own 12px / 16px padding and 8px gap.
Inside Field, first decide whether a child has
as="segment".Without
as="segment", Field owns 12px / 16px padding and 8px gap. Input, Select, or Textarea drops its own padding but keeps its internal gap.With
as="segment", the child is part of a connected field surface and retains its own padding and gap.The final position of the icon in
Inputis controlled byInputitself;Fielddoes not add new offset rules to the icon.For
Input as="segment", the icon remains 16px from the nearest border or divider.Adjacent segments receive a vertical divider in a row or a horizontal divider in a column.
Draw only one divider between adjacent segments.
labelanddescriptionare content only; they do not own padding, gaps, or dividers.A segmented Field’s shared error appears beneath the whole input surface, outside segment and divider layout.
Input, Select, or Textarea segments declare
invalid; Field owns the sharederrortext.The
label + host + errorpattern describes content; it does not decide padding or gap.For connected inputs in
Field roworField column, mark each child explicitly withas="segment".
Component role
Field is the form system’s surface container:
It owns the field’s background, radius, border, focus ring, and dividers.
It combines Input, Select, Textarea, Icon, Text, Checkbox, or Switch into one field surface.
It owns padding and gaps for ordinary fields, and dividers between connected segments.
This means that:
Input, Select, and Textarea remain interactive field hosts.
Field provides the shared visual container.
Declare structure explicitly: place a standard host inside Field, or mark connected hosts with
as="segment".
Inherited Frame capabilities
Field is built on Frame and retains:
responsive / stateStyle / customStates / variants / CSS behavior / stylesHover / Click / Focus / whileAppear / timeline / orchestrateloading / skeleton / renderHintsas / use / layoutId / itemId / scope / access
Field is a Frame container with field semantics, not a static form box.
Keywords
Container protocol
Field exposes a context marker indicating that a host is inside a field container.
When Input, Select, or Textarea detects that marker, it yields its outer surface to Field.
The host gains
.snowui-field-host; Field supplies shared padding, dividers, background, and focus ring.invalid,readonly, ordisabledmay be declared on Field or the host. Field aggregates these states with:has().
This keeps a single visual field surface while each host retains its input behavior and internal rules.
Error feedback and shake
Field invalid shows a stable error border, error region, and combined state of child hosts. A submission or input error also triggers the built-in one-shot shake; consumers need no extra Prop or private CSS class.
Declare the ordinary invalid state; Field then supplies the surface feedback:
If an inner Input, Select, or Textarea becomes invalid without explicit Field invalid, Field also enters the shared invalid state and shakes once. The embedded host does not shake separately.
Invalid styling and shake do not focus an input or simulate focus-within. Focus comes only from actual user focus, autofocus, or an explicit application call to focus().
Layout model
Main layout model: slot host layout. See LayoutProtocol §12.3 (specs/maintainers/LayoutProtocol.md).
Field owns external Leading / Content / Trailing regions, continuous surfaces and dividers. Input, Select and explicit singleLine content rows retain their internal layout, alignment and spacing. A singleLine Field or direct leading/trailing attachments retain at least 4 CSS px; ordinary row, col and segment structural zero gaps and multiline descriptions are preserved.
Field specializes the slot host layout for a form surface:
The root fixes
enableAutoLayout={true}; ordinary callers cannot disable Field’s three-slot protocol.Without
error, Frame remains the only root. Witherror, the visual-free.snowui-field-error-layoutwraps the real Field Frame surface and an external error Text. The wrapper owns no border, background, or interaction styling.leading,host, andtrailingmap to Leading, Content, and Trailing. The host fills available space withmin-width: 0.label,description,error,row,col, andsegmentare Field regions outside the generic three-slot core.For connected segments, Field owns the common surface, divider, and corner clipping; these rules stay in Field rather than generic
auto-layout.css.Inside Field, Input, Select, and Textarea become
.snowui-field-host;as="segment"determines whether each keeps its own padding.
Child role contract (as)
Field itself does not limit the subcomponent type, but identifies different parts through the as role.
Recommended composition
Simple field:
Field > Input.For a horizontal whole-field layout:
Field row > host + host.For a vertical whole-field layout:
Field column > host + row.Label and error:
Field > label + host + error.For content before and after the host:
Field > leading + host + trailing.For a local vertical group:
Field > col > host / row / description.A simple
Field > host + trailingis also supported.Connected inputs:
Field > row > segment + segment.label + host + errordescribes a single control’s error content; it does not itself change padding, gap, or requiresegment.Only multiple hosts or explicit segments sharing one surface need a divider. Do not add dividers around accessories of a single host.
as="segment"explicitly marks a connected field surface, assigning padding and dividers without guessing from DOM shape.Without segments, Field owns 12px / 16px padding and 8px gap; the host drops its padding but keeps its internal gap.
Segments retain their own padding and gap and participate in the common dividers.
label,description, anderrorare content, not padding or divider owners.FM-01address fields are vertical connected sections. Each owns its side borders and required rounded corners, with exactly one shared divider between neighbors.FM-02credit-card fields are horizontal explicit segments. Field owns the full surface; internal dividers separate segments.In a horizontal
Frame as="segment" row, content and inline elements align vertically. After responsive padding compression, MM/YY remains centered with its neighboring Input segment.FM-03notification methods are side-by-side content rows under a label. Field owns the shell; inner Frame uses its explicitgapwithout dividers.
leading and trailing are not restricted to Icon. Any Frame-based component can participate when marked with the corresponding as role.
Using trailing in complex layouts
as="trailing"marks the end of the current local row, not one global slot.For
Field > Input + Button as="trailing", Field places the children in one row.For complex layouts, introduce an explicit local container such as
Frame as="row"; do not rely on an arbitrarydivto infer the trailing role.For nested vertical grouping, use
Frame as="col" column.A date-picker button can still use
as="trailing"inside a complex local container; its role is inferred there without an extra Prop.
Root row and column shorthand
Field rowis shorthand for whole-field horizontal composition, such as paired controls or host + trailing.Field columnis shorthand for whole-field vertical composition, such as a host above a row.Prefer
Field roworField columnwhen the layout applies to the whole root.Use
Frame as="row"orFrame as="col"for a local subgroup within Field.
Usage examples
Status and interaction boundaries
Field owns surface states: default, hover, focus-within, invalid, disabled, and readonly.
The host owns values, native input events, and browser validation details.
Field can display error text but does not create it; get messages from native validation, form state, or application validation.
Focus target area
The whole Field container is a focus target area, not just the inner control.
Clicking label text, padding, or border forwards focus to the first focusable control (
<input>,<textarea>, or Select trigger), unless the clicked target is already focusable.After forwarding, real
:focus-withinactivates the Field focus ring.Clicking a focusable Input, Select, or Textarea keeps its native browser focus behavior.
No forwarding occurs when Field is disabled.
Accessibility and form guidance
Let the host carry native attributes such as
id,name,aria-*, andform.For errors, point the host’s
aria-describedbyto the Field error or description node.Field does not replace
<label>semantics; renderText as="label"or native<label>explicitly when needed.
Field style overlay
Read the full LICENSE first; reuse that review for the same task, version, and scope.
First use public component Props to match the desired appearance, preserving the existing look where possible. If changes are necessary, follow the style selection and override order: use your own class (including Tailwind already in the project) or an instance style. The names below are public overrides actually consumed by source; check their scope and do not modify private DOM. Choose the correct SnowUI token family. External apps need not install SnowUI website utilities.
Field type and status
Required Props: no named required Props.
Bindable Props: this component declares no named two-way binding; handle state updates through public callbacks or its host.
Inheritance: FrameProps. Consult the base class public documentation; fields excluded by Omit cannot be passed through unchanged.
The following type declarations are actually referenced by public Props and come from source. A Svelte Snippet denotes a content fragment; ComponentProps denotes the Props of the corresponding component.
ComponentPartsOf
Source: components/src/logic/component-parts.svelte.ts
ConfigurableComponentPartProps
Source: components/src/logic/component-parts.svelte.ts
ComponentPartControlledKey
Source: components/src/logic/component-parts.svelte.ts