Components
Form
A way to build structured forms.
Usage
---import { Form } from "@opui/astro"import { FieldSet } from "@opui/astro"import { FieldLegend } from "@opui/astro"import { FieldGroup } from "@opui/astro"import { FieldDescription } from "@opui/astro"---
<Form> <FieldSet> <FieldLegend><!-- --></FieldLegend> <FieldDescription><!-- --></FieldDescription> <FieldGroup> <!-- --> </FieldGroup> <FieldGroup> <!-- --> </FieldGroup> </FieldSet></Form>
<!-- or -->
<Form as="div"> <FieldSet as="div"> <FieldLegend as="p"><!-- --></FieldLegend> <FieldDescription><!-- --></FieldDescription> <FieldGroup> <!-- --> </FieldGroup> <FieldGroup> <!-- --> </FieldGroup> </FieldSet></Form>Non-semantic elements
Sometimes you can't use semantic form elements like <fieldset> and <legend>. Use the as prop on FieldSet and FieldLegend to render non-semantic alternatives.
---import { FieldDescription, FieldLegend, FieldSet, Form } from "@opui/astro"---
<Form as="div"> <FieldSet as="div"> <FieldLegend as="p">Using as prop</FieldLegend> <FieldDescription> Renders as div and p elements. </FieldDescription> </FieldSet></Form>Fieldset
Used to show a relationship between form elements.
FieldLegend- to describe what it's about.
FieldDescription(optional)- to give extra context about the fieldset.
FieldGroup- groups related fields.
---import { FieldSet } from "@opui/astro"import { FieldLegend } from "@opui/astro"import { FieldDescription } from "@opui/astro"import { FieldGroup } from "@opui/astro"import { Radio } from "@opui/astro"---
<FieldSet> <FieldLegend>Favorite Pet</FieldLegend> <FieldDescription>Please select your favorite type of pet.</FieldDescription> <FieldGroup name="pet"> <Radio value="dog">Dog</Radio> <Radio value="cat">Cat</Radio> <Radio value="hamster">Hamster</Radio> </FieldGroup></FieldSet><fieldset class="ui-fieldset"> <legend>Favorite Pet</legend> <p class="ui-field-description">Please select your favorite type of pet.</p> <div class="ui-field-group" role="group"> <label class="ui-radio" ><input name="pet" type="radio" value="dog" /><span class="ui-label" >Dog</span ></label ><label class="ui-radio" ><input name="pet" type="radio" value="cat" /><span class="ui-label" >Cat</span ></label ><label class="ui-radio" ><input name="pet" type="radio" value="hamster" /><span class="ui-label" >Hamster</span ></label > </div></fieldset>Required
---import { FieldSet } from "@opui/astro"import { FieldLegend } from "@opui/astro"import { FieldDescription } from "@opui/astro"import { FieldGroup } from "@opui/astro"import { Textarea } from "@opui/astro"import { TextField } from "@opui/astro"---
<FieldSet> <FieldLegend>Pet info</FieldLegend> <FieldDescription>We must know your pet's information.</FieldDescription> <FieldGroup name="bio"> <TextField label="Name" name="name" /> <Textarea required label="Life story" /> </FieldGroup></FieldSet><fieldset class="ui-fieldset"> <legend>Pet info</legend> <p class="ui-field-description">We must know your pet's information.</p> <div class="ui-field-group" role="group"> <label class="ui-text-field" ><span class="ui-label">Name</span ><span class="ui-field"><input name="name" type="text" /></span></label ><label class="ui-textarea" ><span class="ui-label">Life story</span ><span class="ui-field"><textarea name="bio" required></textarea></span ></label> </div></fieldset>Disabled
Turns out you can disable an entire fieldset.
---import { FieldSet } from "@opui/astro"import { FieldLegend } from "@opui/astro"import { FieldDescription } from "@opui/astro"import { FieldGroup } from "@opui/astro"import { Checkbox } from "@opui/astro"---
<FieldSet disabled> <FieldLegend>Pet dating</FieldLegend> <FieldDescription>You can't change these settings</FieldDescription> <FieldGroup name="notifications"> <Checkbox value="horse-tinder" checked>Horse Tinder</Checkbox> <Checkbox value="onlyhorsefans" checked>OnlyHorseFans</Checkbox> </FieldGroup></FieldSet><fieldset disabled class="ui-fieldset"> <legend>Pet dating</legend> <p class="ui-field-description">You can't change these settings</p> <div class="ui-field-group" role="group"> <label class="ui-checkbox" ><input name="notifications" type="checkbox" value="horse-tinder" checked /> <script type="module"> function e(e = document) { e.querySelectorAll( `input[type="checkbox"][data-indeterminate]`, ).forEach((e) => { e.indeterminate = !0; }); } function t() { (e(), document.addEventListener(`astro:after-swap`, () => e())); } t(); </script> <span class="ui-label">Horse Tinder</span></label ><label class="ui-checkbox" ><input name="notifications" type="checkbox" value="onlyhorsefans" checked /><span class="ui-label">OnlyHorseFans</span></label > </div></fieldset>Field Legend
Use FieldLegend (or <legend>) to describe the fieldset.
---import { FieldSet } from "@opui/astro"import { FieldLegend } from "@opui/astro"---
<FieldSet> <FieldLegend>Legend</FieldLegend></FieldSet><fieldset class="ui-fieldset"><legend>Legend</legend></fieldset>Field Description
Use FieldDescription (or .ui-field-description) to give extra context about the fieldset.
---import { FieldSet } from "@opui/astro"import { FieldLegend } from "@opui/astro"import { FieldDescription } from "@opui/astro"---
<FieldSet> <FieldLegend>Legend</FieldLegend> <FieldDescription>This is a field description.</FieldDescription></FieldSet><fieldset class="ui-fieldset"> <legend>Legend</legend> <p class="ui-field-description">This is a field description.</p></fieldset>Field Group
Use FieldGroup to wrap related fields. It provides a sharedname to all nested inputs.
---import { Checkbox } from "@opui/astro"import { FieldDescription } from "@opui/astro"import { FieldGroup } from "@opui/astro"import { FieldLegend } from "@opui/astro"import { FieldSet } from "@opui/astro"import { Form } from "@opui/astro"import { Radio } from "@opui/astro"---
<Form> <FieldSet> <FieldLegend>Choose your favorite Radiohead album</FieldLegend> <FieldDescription>There are no wrong answers.</FieldDescription> <FieldGroup name="albums"> <Radio value="ok-computer">OK Computer</Radio> <Radio value="kid-a">Kid A</Radio> <Radio value="in-rainbows">In Rainbows</Radio> <Radio value="king-of-limbs">The King of Limbs</Radio> </FieldGroup> </FieldSet>
<FieldSet> <FieldLegend>Which side projects do you follow?</FieldLegend> <FieldDescription>Some are better than others.</FieldDescription> <FieldGroup name="projects"> <Checkbox value="the-smile"> The Smile <Fragment slot="end-text" >Thom Yorke, Jonny Greenwood, Tom Skinner</Fragment > </Checkbox> <Checkbox value="atoms-for-peace"> Atoms for Peace <Fragment slot="end-text">Thom Yorke, Flea, Nigel Godrich</Fragment> </Checkbox> <Checkbox value="eob"> EOB <Fragment slot="end-text">Ed O'Brien solo</Fragment> </Checkbox> <Checkbox value="jonny-scores"> Film Scores <Fragment slot="end-text">Film compositions by Jonny Greenwood</Fragment > </Checkbox> <Checkbox value="selway-solo"> Philip Selway <Fragment slot="end-text">Philip Selway solo albums</Fragment> </Checkbox> </FieldGroup> </FieldSet></Form><form class="ui-form"> <fieldset class="ui-fieldset"> <legend>Choose your favorite Radiohead album</legend> <p class="ui-field-description">There are no wrong answers.</p> <div class="ui-field-group" role="group"> <label class="ui-radio" ><input name="albums" type="radio" value="ok-computer" /><span class="ui-label" >OK Computer</span ></label ><label class="ui-radio" ><input name="albums" type="radio" value="kid-a" /><span class="ui-label" >Kid A</span ></label ><label class="ui-radio" ><input name="albums" type="radio" value="in-rainbows" /><span class="ui-label" >In Rainbows</span ></label ><label class="ui-radio" ><input name="albums" type="radio" value="king-of-limbs" /><span class="ui-label" >The King of Limbs</span ></label > </div> </fieldset> <fieldset class="ui-fieldset"> <legend>Which side projects do you follow?</legend> <p class="ui-field-description">Some are better than others.</p> <div class="ui-field-group" role="group"> <label class="ui-checkbox" ><input name="projects" type="checkbox" aria-describedby="end-text-1" value="the-smile" /><span class="ui-label">The Smile</span ><span id="end-text-1" class="ui-end-text" >Thom Yorke, Jonny Greenwood, Tom Skinner</span ></label ><label class="ui-checkbox" ><input name="projects" type="checkbox" aria-describedby="end-text-2" value="atoms-for-peace" /><span class="ui-label">Atoms for Peace</span ><span id="end-text-2" class="ui-end-text" >Thom Yorke, Flea, Nigel Godrich</span ></label ><label class="ui-checkbox" ><input name="projects" type="checkbox" aria-describedby="end-text-3" value="eob" /><span class="ui-label">EOB</span ><span id="end-text-3" class="ui-end-text">Ed O'Brien solo</span></label ><label class="ui-checkbox" ><input name="projects" type="checkbox" aria-describedby="end-text-4" value="jonny-scores" /><span class="ui-label">Film Scores</span ><span id="end-text-4" class="ui-end-text" >Film compositions by Jonny Greenwood</span ></label ><label class="ui-checkbox" ><input name="projects" type="checkbox" aria-describedby="end-text-5" value="selway-solo" /><span class="ui-label">Philip Selway</span ><span id="end-text-5" class="ui-end-text" >Philip Selway solo albums</span ></label > </div> </fieldset></form>Row
Use the direction="row" prop to lay out fields horizontally.
---import { Form } from "@opui/astro"import { FieldSet } from "@opui/astro"import { FieldLegend } from "@opui/astro"import { FieldGroup } from "@opui/astro"import { Checkbox } from "@opui/astro"---
<Form> <FieldSet> <FieldLegend>Options</FieldLegend> <FieldGroup direction="row"> <Checkbox>Option 1</Checkbox> <Checkbox>Option 2</Checkbox> <Checkbox>Option 3</Checkbox> </FieldGroup> </FieldSet></Form><form class="ui-form"> <fieldset class="ui-fieldset"> <legend>Options</legend> <div class="ui-field-group ui-row" role="group"> <label class="ui-checkbox" ><input type="checkbox" /><span class="ui-label">Option 1</span></label ><label class="ui-checkbox" ><input type="checkbox" /><span class="ui-label">Option 2</span></label ><label class="ui-checkbox" ><input type="checkbox" /><span class="ui-label">Option 3</span></label > </div> </fieldset></form>Divider
Use the Divider component to create a visual break between sections of your form.
---import { Form } from "@opui/astro"import { FieldSet } from "@opui/astro"import { FieldLegend } from "@opui/astro"import { FieldGroup } from "@opui/astro"import { TextField } from "@opui/astro"import { Button } from "@opui/astro"import { Divider } from "@opui/astro"---
<Form> <FieldSet> <FieldLegend>Post Content</FieldLegend> <FieldGroup> <TextField label="Title" placeholder="My new post" /> </FieldGroup> </FieldSet>
<Divider />
<FieldGroup> <Button variant="filled">Publish</Button> </FieldGroup></Form><form class="ui-form"> <fieldset class="ui-fieldset"> <legend>Post Content</legend> <div class="ui-field-group" role="group"> <label class="ui-text-field" ><span class="ui-label">Title</span ><span class="ui-field" ><input placeholder="My new post" type="text" /></span ></label> </div> </fieldset> <hr class="ui-divider" /> <div class="ui-field-group" role="group"> <button class="ui-button ui-filled">Publish</button> </div></form>Kitchen Sink
Everything all at once.
---import { Form } from "@opui/astro"import { FieldSet } from "@opui/astro"import { FieldLegend } from "@opui/astro"import { FieldDescription } from "@opui/astro"import { FieldGroup } from "@opui/astro"import { TextField } from "@opui/astro"import { Select } from "@opui/astro"import { Switch } from "@opui/astro"import { Radio } from "@opui/astro"import { Textarea } from "@opui/astro"import { Checkbox } from "@opui/astro"import { Range } from "@opui/astro"import { Button } from "@opui/astro"import { Divider } from "@opui/astro"---
<Form id="kitchen-sink-example"> <FieldSet> <FieldLegend>User Profile</FieldLegend> <FieldDescription> Please provide your basic contact details. </FieldDescription> <FieldGroup> <TextField label="Full Name" placeholder="Jane Doe" required /> <TextField label="Email Address" type="email" placeholder="jane@example.com" required /> <Select label="Role" items={[ { text: "Developer", value: "dev" }, { text: "Designer", value: "design" }, { text: "Manager", value: "manager" }, ]} /> </FieldGroup> </FieldSet>
<Divider />
<FieldSet> <FieldLegend>Notifications</FieldLegend> <FieldDescription> Configure how you want to receive updates. </FieldDescription> <FieldGroup name="notifications"> <Switch name="email_notifs" checked>Email Notifications</Switch> <Switch name="sms_notifs">SMS Notifications</Switch> </FieldGroup> </FieldSet>
<Divider />
<FieldSet> <FieldLegend>Theme Preference</FieldLegend> <FieldDescription>Select your preferred visual style.</FieldDescription> <FieldGroup name="theme"> <Radio value="light" checked>Light Theme</Radio> <Radio value="dark">Dark Theme</Radio> <Radio value="system">System Default</Radio> </FieldGroup> </FieldSet>
<Divider />
<FieldSet> <FieldLegend>Experience Level</FieldLegend> <FieldDescription >How many years of experience do you have?</FieldDescription > <FieldGroup> <Range label="Professional Experience" min="0" max="20" step="1" value="5" startText="Drag the slider to match your total tenure." /> </FieldGroup> </FieldSet>
<Divider />
<FieldSet> <FieldLegend>Additional Info</FieldLegend> <FieldDescription>Anything else we should know?</FieldDescription> <FieldGroup name="details"> <Textarea label="Biography" placeholder="Tell us about yourself..." rows={4} /> </FieldGroup> </FieldSet>
<Divider />
<FieldSet> <FieldLegend>Legal</FieldLegend> <FieldGroup name="legal"> <Checkbox name="terms" required> I agree to the terms and conditions <Fragment slot="end-text">Support this text</Fragment> </Checkbox> </FieldGroup> </FieldSet>
<Divider />
<FieldGroup> <Button variant="filled" type="submit">Send</Button> <Button>Cancel</Button> </FieldGroup></Form><form id="kitchen-sink-example" class="ui-form"><fieldset class="ui-fieldset"><legend>User Profile</legend><p class="ui-field-description">Please provide your basic contact details.</p><div class="ui-field-group" role="group"><label class="ui-text-field"><span class="ui-label">Full Name</span><span class="ui-field"><input placeholder="Jane Doe" required type="text"></span></label><label class="ui-text-field"><span class="ui-label">Email Address</span><span class="ui-field"><input placeholder="jane@example.com" required type="email"></span></label><label class="ui-select"><span class="ui-label" id="select-label-3">Role</span><span class="ui-field"><select aria-labelledby="select-label-3"><button><selectedcontent></button><div class="ui-list"><option value="dev">Developer</option><option value="design">Designer</option><option value="manager">Manager</option></div></select></span></label></div></fieldset><hr class="ui-divider"><fieldset class="ui-fieldset"><legend>Notifications</legend><p class="ui-field-description">Configure how you want to receive updates.</p><div class="ui-field-group" role="group"><label class="ui-switch"><input type="checkbox" role="switch" name="email_notifs" checked><span class="ui-label">Email Notifications</span></label><label class="ui-switch"><input type="checkbox" role="switch" name="sms_notifs"><span class="ui-label">SMS Notifications</span></label></div></fieldset><hr class="ui-divider"><fieldset class="ui-fieldset"><legend>Theme Preference</legend><p class="ui-field-description">Select your preferred visual style.</p><div class="ui-field-group" role="group"><label class="ui-radio"><input name="theme" type="radio" value="light" checked><span class="ui-label">Light Theme</span></label><label class="ui-radio"><input name="theme" type="radio" value="dark"><span class="ui-label">Dark Theme</span></label><label class="ui-radio"><input name="theme" type="radio" value="system"><span class="ui-label">System Default</span></label></div></fieldset><hr class="ui-divider"><fieldset class="ui-fieldset"><legend>Experience Level</legend><p class="ui-field-description">How many years of experience do you have?</p><div class="ui-field-group" role="group"><label class="ui-range"><span class="ui-label" id="range-label-6">Professional Experience</span><span class="ui-start-text" id="range-start-1">Drag the slider to match your total tenure.</span><input aria-describedby="range-start-1" aria-labelledby="range-label-6" max="20" min="0" step="1" type="range" value="5"></label><script type="module">for(let e of document.querySelectorAll(`.ui-range`)){let t=e.querySelector(`input[type="range"]`),n=e.querySelector(`:scope > output.ui-value`);if(!t||!n)continue;let r=n.dataset.suffix??``,i=()=>{n.textContent=`${t.value}${r}`};t.addEventListener(`input`,i),i()}</script></div></fieldset><hr class="ui-divider"><fieldset class="ui-fieldset"><legend>Additional Info</legend><p class="ui-field-description">Anything else we should know?</p><div class="ui-field-group" role="group"><label class="ui-textarea"><span class="ui-label">Biography</span><span class="ui-field"><textarea name="details" placeholder="Tell us about yourself..." rows="4"></textarea></span></label></div></fieldset><hr class="ui-divider"><fieldset class="ui-fieldset"><legend>Legal</legend><div class="ui-field-group" role="group"><label class="ui-checkbox"><input type="checkbox" aria-describedby="end-text-6" name="terms" required><span class="ui-label">I agree to the terms and conditions</span><span id="end-text-6" class="ui-end-text">Support this text</span></label></div></fieldset><hr class="ui-divider"><div class="ui-field-group" role="group"><button type="submit" class="ui-button ui-filled">Send</button><button class="ui-button">Cancel</button></div></form>Row
Everything all at once, but horizontally.
---import { Button, Checkbox, Divider, FieldDescription, FieldGroup, FieldLegend, FieldSet, Form, Radio, Range, Select, Switch, TextField, Textarea,} from "@opui/astro"---
<Form id="kitchen-sink-example-row"> <FieldSet> <FieldLegend>User Profile</FieldLegend> <FieldDescription> Please provide your basic contact details. </FieldDescription> <FieldGroup> <TextField placeholder="Jane Doe" required spread> <Fragment slot="label">Full Name</Fragment> </TextField> <TextField type="email" placeholder="jane@example.com" required spread> <Fragment slot="label">Email Address</Fragment> </TextField> <Select items={[ { text: "Developer", value: "dev" }, { text: "Designer", value: "design" }, { text: "Manager", value: "manager" }, ]} spread > <Fragment slot="label">Role</Fragment> </Select> </FieldGroup> </FieldSet>
<Divider />
<FieldSet> <FieldLegend>Notifications</FieldLegend> <FieldDescription> Configure how you want to receive updates. </FieldDescription> <FieldGroup name="notifications"> <Switch name="email_notifs" checked spread>Email Notifications</Switch> <Switch name="sms_notifs" spread>SMS Notifications</Switch> </FieldGroup> </FieldSet>
<Divider />
<FieldSet> <FieldLegend>Theme Preference</FieldLegend> <FieldDescription>Select your preferred visual style.</FieldDescription> <FieldGroup direction="row" name="theme"> <Radio value="light" checked>Light Theme</Radio> <Radio value="dark">Dark Theme</Radio> <Radio value="system">System Default</Radio> </FieldGroup> </FieldSet>
<Divider />
<FieldSet> <FieldLegend>Experience Level</FieldLegend> <FieldDescription >How many years of experience do you have?</FieldDescription > <FieldGroup> <Range min="0" max="20" step="1" value="5" spread> Professional Experience <Fragment slot="start-text" >Drag the slider to match your total tenure.</Fragment > </Range> </FieldGroup> </FieldSet>
<Divider />
<FieldSet> <FieldLegend>Additional Info</FieldLegend> <FieldDescription>Anything else we should know?</FieldDescription> <FieldGroup name="details"> <Textarea placeholder="Tell us about yourself..." rows={4} spread> <Fragment slot="label">Biography</Fragment> </Textarea> </FieldGroup> </FieldSet>
<Divider />
<FieldSet> <FieldLegend>Legal</FieldLegend> <FieldGroup name="legal"> <Checkbox name="terms" required spread> I agree to the terms and conditions <Fragment slot="end-text">Support this text</Fragment> </Checkbox> </FieldGroup> </FieldSet>
<Divider />
<FieldGroup> <Button variant="filled" type="submit">Send</Button> <Button>Cancel</Button> </FieldGroup></Form><form id="kitchen-sink-example-row" class="ui-form"><fieldset class="ui-fieldset"><legend>User Profile</legend><p class="ui-field-description">Please provide your basic contact details.</p><div class="ui-field-group" role="group"><label class="ui-text-field ui-spread"><span class="ui-label">Full Name</span><span class="ui-field"><input placeholder="Jane Doe" required type="text"></span></label><label class="ui-text-field ui-spread"><span class="ui-label">Email Address</span><span class="ui-field"><input placeholder="jane@example.com" required type="email"></span></label><label class="ui-select ui-spread"><span class="ui-label" id="select-label-4">Role</span><span class="ui-field"><select aria-labelledby="select-label-4"><button><selectedcontent></button><div class="ui-list"><option value="dev">Developer</option><option value="design">Designer</option><option value="manager">Manager</option></div></select></span></label></div></fieldset><hr class="ui-divider"><fieldset class="ui-fieldset"><legend>Notifications</legend><p class="ui-field-description">Configure how you want to receive updates.</p><div class="ui-field-group" role="group"><label class="ui-switch ui-spread"><input type="checkbox" role="switch" name="email_notifs" checked><span class="ui-label">Email Notifications</span></label><label class="ui-switch ui-spread"><input type="checkbox" role="switch" name="sms_notifs"><span class="ui-label">SMS Notifications</span></label></div></fieldset><hr class="ui-divider"><fieldset class="ui-fieldset"><legend>Theme Preference</legend><p class="ui-field-description">Select your preferred visual style.</p><div class="ui-field-group ui-row" role="group"><label class="ui-radio"><input name="theme" type="radio" value="light" checked><span class="ui-label">Light Theme</span></label><label class="ui-radio"><input name="theme" type="radio" value="dark"><span class="ui-label">Dark Theme</span></label><label class="ui-radio"><input name="theme" type="radio" value="system"><span class="ui-label">System Default</span></label></div></fieldset><hr class="ui-divider"><fieldset class="ui-fieldset"><legend>Experience Level</legend><p class="ui-field-description">How many years of experience do you have?</p><div class="ui-field-group" role="group"><label class="ui-range ui-spread"><span class="ui-label" id="range-label-7">Professional Experience</span><span class="ui-start-text" id="range-start-2">Drag the slider to match your total tenure.</span><input aria-describedby="range-start-2" aria-labelledby="range-label-7" max="20" min="0" step="1" type="range" value="5"></label></div></fieldset><hr class="ui-divider"><fieldset class="ui-fieldset"><legend>Additional Info</legend><p class="ui-field-description">Anything else we should know?</p><div class="ui-field-group" role="group"><label class="ui-textarea ui-spread"><span class="ui-label">Biography</span><span class="ui-field"><textarea name="details" placeholder="Tell us about yourself..." rows="4"></textarea></span></label></div></fieldset><hr class="ui-divider"><fieldset class="ui-fieldset"><legend>Legal</legend><div class="ui-field-group" role="group"><label class="ui-checkbox ui-spread"><input type="checkbox" aria-describedby="end-text-7" name="terms" required><span class="ui-label">I agree to the terms and conditions</span><span id="end-text-7" class="ui-end-text">Support this text</span></label></div></fieldset><hr class="ui-divider"><div class="ui-field-group" role="group"><button type="submit" class="ui-button ui-filled">Send</button><button class="ui-button">Cancel</button></div></form>API
Form API
| Prop | Type | Default | Description |
|---|---|---|---|
as | "div", "form" | "form" | The element to render. |
Slots
| Slot | Description |
|---|---|
default | The fieldsets and fields. |
Field set API
| Prop | Type | Default | Description |
|---|---|---|---|
as | "div", "fieldset" | "fieldset" | The element to render. |
disabled | boolean | false | Disables every field inside. |
Slots
| Slot | Description |
|---|---|
default | The legend, description and fields. |
Field legend API
| Prop | Type | Default | Description |
|---|---|---|---|
as | "p", "legend" | "legend" | The element to render. Adds .ui-legend when not "legend". |
Slots
| Slot | Description |
|---|---|
default | The label. |
Field description API
Slots
| Slot | Description |
|---|---|
default | The text. |
Field group API
| Prop | Type | Default | Description |
|---|---|---|---|
direction | "row", "column" | - | The orientation of the element. |
name | string | - | Sets name on every input, select and textarea inside. |
Slots
| Slot | Description |
|---|---|
default | The fields, such as checkboxes, radios or switches. |
Browser support
See also the full browser support guide.
Installation
This doesn't include all the styles for all form elements, just the scaffolding around them.
See also
@layer components.extended { /* Form */ :where(.ui-form) { display: grid; gap: var(--size-8);
hr { margin-block: 0; } }
/* Fieldset */ :where(.ui-fieldset) { all: unset; border: 0; border-radius: 0; display: grid; gap: var(--size-1); margin: 0; min-inline-size: 0; padding: 0;
/* Legend */ :where(legend, .ui-legend) { all: unset; color: var(--text-primary); font-weight: 600; margin-block-end: var(--size-3); padding: 0;
&:has(+ :where(.ui-field-description)) { margin-block-end: 0; } }
/* Field description / supporting text */ :where(.ui-field-description) { color: var(--text-muted); font-size: var(--font-size-05); line-height: var(--font-lineheight-3);
&:has(+ *) { margin-block-end: var(--size-3); } }
/* End text */ :where(.ui-end-text) { color: var(--text-muted); font-size: var(--font-size-0); line-height: var(--font-lineheight-3); }
&:has(.ui-text-field.ui-row) { row-gap: var(--size-7); }
/* Disabled */ &[disabled] { opacity: 0.64; user-select: none;
input, label, .ui-label { cursor: not-allowed; } }
/* Error / validation */ &[data-invalid] { :where(.ui-end-text) { color: var(--critical); }
:where(.ui-checkbox, .ui-radio, .ui-switch) { --primary: var(--critical);
:where(.ui-end-text) { color: var(--critical); } }
:where(.ui-switch) { input { border-radius: var(--radius-round); outline: 2px solid var(--critical); } } }
/* Required */ &:has(:invalid) { :where(legend, .ui-legend) { padding-inline-end: 1ex; position: relative;
&::after { color: var(--red); content: "*"; inset: 0 -0.25ex auto auto; position: absolute; } } } }
/* Field group */ :where(.ui-field-group) { display: flex; flex-direction: column; gap: var(--size-4);
/* If it only has checkboxes, radios, or switches */ &:has(> :where(.ui-checkbox, .ui-radio, .ui-switch)):not( :has(> :not(.ui-checkbox, .ui-radio, .ui-switch)) ) { gap: var(--size-2); }
/* If it only has buttons */ &:has(.ui-button):not(:has(*:not(.ui-button))) { align-items: center; flex-direction: row; gap: var(--size-2);
/* If it's not preceded by an hr */ &:not(hr + &) { margin-block-start: var(--size-4); } }
& + & { margin-block-start: var(--size-5); }
/* Directions */ &.ui-row { flex-direction: row; flex-wrap: wrap;
&:has(> :where(.ui-checkbox, .ui-radio, .ui-switch)) { gap: var(--size-4); } } }}