SvField
The shared field chrome for every value-bearing editor in the kit - the label, hint, and error line that make any control behave consistently.
SvField renders an optional label (wired to your control via for / id),
the control itself as children, and an optional hint or error line whose ids
match aria-describedby conventions. Every editor in the kit (inputs, selects,
SvFileUpload, and more) wraps its control box in it, so
label / hint / error / RTL behave identically everywhere - and you can use it
directly to give a custom control the same chrome.
Related: SvForm ยท Layout & composite overview
Installation
Add it with the CLI - this drops a ready-to-edit SvField starter into your app:
Prefer to see it first? npx @svgrid/ui try field opens it in a throwaway sandbox - no project needed.
Or install the package and import it directly. SvField ships free in
@svgrid/grid (dependency-free):
import { SvField } from '@svgrid/grid'
Example
<script lang="ts">
import { SvField } from '@svgrid/grid'
const id = 'ticket-priority'
</script>
<SvField {id} label="Priority" hint="How urgent is this?" required>
<select {id} class="my-control">
<option>Low</option><option>High</option>
</select>
</SvField>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
id |
string |
- | Control id. The label's for, and the hint / error ids, derive from it. |
label |
string |
- | Visible label, rendered above the control. |
hint |
string |
- | Helper text under the control (shown when there is no error). |
error |
string |
- | Error message; when set it replaces the hint and gets role="alert". |
required |
boolean |
false |
Adds a required marker to the label. |
dir |
EditorDir (ltr | rtl | auto) |
- | Text direction. rtl mirrors alignment; auto inherits the page. |
block |
boolean |
false |
Stretch the field and its control to the container width. |
loading |
boolean |
false |
Busy state; shows a small spinner beside the label. |
children |
Snippet |
- | The control to wrap (required). |
When both error and hint are set, the error takes precedence and is the line
announced to assistive tech.
Framed mode (shared control chrome)
Pass frame and SvField owns the bordered control box - the border, focus ring,
invalid state, size (sm / md / lg), a shared clear button, adornments and
floating label - so editors stop re-implementing them. The whole text-input family
uses this; you only need it directly when building a custom framed control.
| Prop | Type | Default | Description |
|---|---|---|---|
frame |
boolean |
false |
Own the bordered control box (opt-in). |
invalid |
boolean |
false |
Error styling on the box + border. |
size |
sm | md | lg |
md |
Control height / density. |
disabled / readonly |
boolean |
false |
Dim / read-only box styling. |
leading / trailing |
Snippet |
- | Icon/button adornment at the start / end of the box. |
prefix / suffix |
string |
- | Plain-text affix at the start / end (units). |
clearable + showClear + onclear |
- | - | Render the shared clear (x) button and handle the clear. |
actions |
EditorAction[] |
- | Compact in-field action buttons - the general form of clear/reveal (lookup, generate, copy). EditorAction is { label; onClick; icon?; disabled? }. |
width |
number | string |
220 |
Control width (block overrides to 100%). |
labelMode |
static | floating |
static |
floating rests the label in the box and animates it up on focus/value. |
filled |
boolean |
false |
Floating mode: whether the control holds a value (keeps the label up). |
Examples
Wrap a custom control
Give any input the kit's label / hint / error treatment by matching the control's
id to the field id:
<SvField id="color" label="Brand color" hint="Hex or named color">
<input id="color" type="text" />
</SvField>
Drive the error from validation
Pass a reactive error string; clearing it swaps back to the hint automatically:
<SvField id="qty" label="Quantity" error={qtyError}>
<input id="qty" type="number" bind:value={qty} />
</SvField>
Full-width fields
Set block so the field fills a form column rather than shrinking to the label
width.
A native select that matches the kit
Give a plain <select> the same label, required marker, hint, and full-width
behaviour every kit editor has by sharing one id, and drive error reactively:
<script lang="ts">
import { SvField } from '@svgrid/grid'
let role = $state('')
const err = $derived(role ? undefined : 'Pick a role')
</script>
<SvField id="role" label="Role" hint="Sets the default permissions"
error={err} required block>
<select id="role" bind:value={role}>
<option value="">Choose...</option>
<option value="admin">Admin</option>
<option value="member">Member</option>
</select>
</SvField>
Tip: when both hint and error are set the error wins and gets
role="alert", so clearing the error string swaps the hint back in
automatically.
Accessibility
- The label is a real
<label for={id}>, so clicking it focuses the control and screen readers announce the name. - The hint and error ids follow the editor contract, so a control that sets
aria-describedbyto them has its helper or error text announced. - The error line uses
role="alert"so it is read out when it appears.
Wrapping a control you own
SvField is the label / hint / error chrome without an input of its own, so a
native control or a third-party widget gets the same treatment as the built-in
editors. Match id to the control's id and the label points at the right
thing.
<script lang="ts">
import { SvField } from '@svgrid/grid'
let colour = $state('#2563eb')
</script>
<SvField id="brand" label="Brand colour" hint="Any CSS colour" required>
<input id="brand" type="color" bind:value={colour} />
</SvField>
<SvField id="notes" label="Notes" error="Say something before saving">
<textarea id="notes" rows="3"></textarea>
</SvField>
See also
- SvForm - a schema-driven form that applies this chrome across many fields at once.
- Layout overview - the whole layout family at a glance.