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>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 type="radio" name="pet" value="dog" /> <span class="ui-label">Dog</span> </label> <label class="ui-radio"> <input type="radio" name="pet" value="cat" /> <span class="ui-label">Cat</span> </label> <label class="ui-radio"> <input type="radio" name="pet" 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" /> <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 id="text-field-2" name="bio" type="text" /> </span> </label> <label class="ui-textarea"> <span class="ui-label"> Life story </span> <span class="ui-field"> <textarea id="textarea-1" 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"> <script type="module"> function e(t = document) { t.querySelectorAll( 'input[type="checkbox"][data-indeterminate]', ).forEach((n) => { n.indeterminate = !0; }); } function a() { (e(), document.addEventListener("astro:after-swap", () => e())); } a(); </script> <label class="ui-checkbox"> <input type="checkbox" name="notifications" value="horse-tinder" checked /> <span class="ui-label">Horse Tinder</span> </label> <label class="ui-checkbox"> <input type="checkbox" name="notifications" 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 shared
name 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 type="radio" name="albums" value="ok-computer" /> <span class="ui-label">OK Computer</span> </label> <label class="ui-radio"> <input type="radio" name="albums" value="kid-a" /> <span class="ui-label">Kid A</span> </label> <label class="ui-radio"> <input type="radio" name="albums" value="in-rainbows" /> <span class="ui-label">In Rainbows</span> </label> <label class="ui-radio"> <input type="radio" name="albums" 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 type="checkbox" aria-describedby="end-text-1" name="projects" 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 type="checkbox" aria-describedby="end-text-2" name="projects" 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 type="checkbox" aria-describedby="end-text-3" name="projects" 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 type="checkbox" aria-describedby="end-text-4" name="projects" 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 type="checkbox" aria-describedby="end-text-5" name="projects" 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" name="projects" /> <span class="ui-label">Option 1</span> </label> <label class="ui-checkbox"> <input type="checkbox" name="projects" /> <span class="ui-label">Option 2</span> </label> <label class="ui-checkbox"> <input type="checkbox" name="projects" /> <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 id="text-field-3" name="projects" 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 id="text-field-4" name="projects" 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 id="text-field-5" name="projects" 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" id="select-3" name="projects"> <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 type="radio" name="theme" value="light" checked> <span class="ui-label">Light Theme</span> </label> <label class="ui-radio"> <input type="radio" name="theme" value="dark"> <span class="ui-label">Dark Theme</span> </label> <label class="ui-radio"> <input type="radio" name="theme" 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"><script type="module">for(const u of document.querySelectorAll(".ui-range")){const t=u.querySelector('input[type="range"]'),e=u.querySelector(":scope > output.ui-value");if(!t||!e)continue;const o=e.dataset.suffix??"",n=()=>{e.textContent=`${t.value}${o}`};t.addEventListener("input",n),n()}</script> <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" id="range-6" 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"> <span class="ui-label"> Biography </span> <span class="ui-field"> <textarea id="textarea-2" 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 id="text-field-6" name="legal" 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 id="text-field-7" name="legal" 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 id="select-4" name="legal"> <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 type="radio" name="theme" value="light" checked> <span class="ui-label">Light Theme</span> </label> <label class="ui-radio"> <input type="radio" name="theme" value="dark"> <span class="ui-label">Dark Theme</span> </label> <label class="ui-radio"> <input type="radio" name="theme" 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" id="range-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 id="textarea-3" 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
| Prop | Type | Default | Description |
|---|---|---|---|
as | "form", "div" | "form" | The HTML element to render. |
FieldSet
| Prop | Type | Default | Description |
|---|---|---|---|
as | "fieldset", "div" | "fieldset" | The HTML element to render. |
disabled | boolean | - | Whether the field set is disabled. |
FieldLegend
| Prop | Type | Default | Description |
|---|---|---|---|
as | "legend", "p" | "legend" | The HTML element to render. |
FieldDescription
| Prop | Type | Default | Description |
|---|---|---|---|
| - | - | - | Helper text for the field set. Accepts standard HTML attributes on the
rendered <p> (via ...rest). |
FieldGroup
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | - | Shared name for nested input components. |
direction | "row", "column" | - | The orientation of the field group. |
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 preceeded 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); } } }}