Components
Form
A way to build structured forms.
Usage
<script setup lang="ts">import { FieldDescription, FieldGroup, FieldLegend, FieldSet, Form,} from "opui-css/vue"</script>
<template> <Form> <FieldSet> <FieldLegend><!-- --></FieldLegend> <FieldDescription><!-- --></FieldDescription> <FieldGroup> <!-- --> </FieldGroup> <FieldGroup> <!-- --> </FieldGroup> </FieldSet> </Form></template>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.
<script setup lang="ts">import { FieldDescription, FieldLegend, FieldSet, Form } from "opui-css/vue"</script>
<template> <Form as="div"> <FieldSet as="div"> <FieldLegend as="p">Using as prop</FieldLegend> <FieldDescription> Renders as div and p elements. </FieldDescription> </FieldSet> </Form></template>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.
<script setup lang="ts">import { FieldDescription, FieldGroup, FieldLegend, FieldSet, Radio,} from "opui-css/vue"</script>
<template> <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></template><fieldset class="ui-fieldset"> <!--[--> <legend class=""><!--[-->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" value="dog" aria-describedby="s0-0" /><span class="ui-label" ><!--[-->Dog<!--]--></span ><!----></label ><label class="ui-radio" ><input type="radio" value="cat" aria-describedby="s0-1" /><span class="ui-label" ><!--[-->Cat<!--]--></span ><!----></label ><label class="ui-radio" ><input type="radio" value="hamster" aria-describedby="s0-2" /><span class="ui-label" ><!--[-->Hamster<!--]--></span ><!----></label ><!--]--> </div> <!--]--></fieldset>Required
<script setup lang="ts">import { FieldDescription, FieldGroup, FieldLegend, FieldSet, Textarea, TextField,} from "opui-css/vue"</script>
<template> <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></template><fieldset class="ui-fieldset"> <!--[--> <legend class=""><!--[-->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="s1-0" type="text" /><!----><!----><!----><!----></span ><!----><!--[--><!--]--></label ><label class="ui-textarea" ><span class="ui-label"><!--[-->Life story<!--]--></span ><!----><span class="ui-field"> <textarea id="s1-1" required></textarea ><!----><!----><!----><!----></span ><!----><!--[--><!--]--></label ><!--]--> </div> <!--]--></fieldset>Disabled
Turns out you can disable an entire fieldset.
<script setup lang="ts">import { Checkbox, FieldDescription, FieldGroup, FieldLegend, FieldSet,} from "opui-css/vue"</script>
<template> <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></template><fieldset class="ui-fieldset" disabled> <!--[--> <legend class=""><!--[-->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 type="checkbox" value="horse-tinder" /><span class="ui-label" ><!--[-->Horse Tinder<!--]--></span ><!----></label ><label class="ui-checkbox" ><input type="checkbox" value="onlyhorsefans" /><span class="ui-label" ><!--[-->OnlyHorseFans<!--]--></span ><!----></label ><!--]--> </div> <!--]--></fieldset>Field Legend
Use FieldLegend (or <legend>) to describe
the fieldset.
<script setup lang="ts">import { FieldLegend, FieldSet } from "opui-css/vue"</script>
<template> <FieldSet> <FieldLegend>Legend</FieldLegend> </FieldSet></template><fieldset class="ui-fieldset"> <!--[--> <legend class=""><!--[-->Legend<!--]--></legend> <!--]--></fieldset>Field Description
Use FieldDescription (or .ui-field-description)
to give extra context about the fieldset.
<script setup lang="ts">import { FieldDescription, FieldLegend, FieldSet } from "opui-css/vue"</script>
<template> <FieldSet> <FieldLegend>Legend</FieldLegend> <FieldDescription>This is a field description.</FieldDescription> </FieldSet></template><fieldset class="ui-fieldset"> <!--[--> <legend class=""><!--[-->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.
<script setup lang="ts">import { Checkbox, FieldDescription, FieldGroup, FieldLegend, FieldSet, Form, Radio,} from "opui-css/vue"</script>
<template> <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 <template #end-text >Thom Yorke, Jonny Greenwood, Tom Skinner</template > </Checkbox> <Checkbox value="atoms-for-peace"> Atoms for Peace <template #end-text>Thom Yorke, Flea, Nigel Godrich</template> </Checkbox> <Checkbox value="eob"> EOB <template #end-text>Ed O'Brien solo</template> </Checkbox> <Checkbox value="jonny-scores"> Film Scores <template #end-text>Film compositions by Jonny Greenwood</template> </Checkbox> <Checkbox value="selway-solo"> Philip Selway <template #end-text>Philip Selway solo albums</template> </Checkbox> </FieldGroup> </FieldSet> </Form></template><form class="ui-form"> <!--[--> <fieldset class="ui-fieldset"> <!--[--> <legend class=""> <!--[-->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" value="ok-computer" aria-describedby="s5-0" /><span class="ui-label" ><!--[-->OK Computer<!--]--></span ><!----></label ><label class="ui-radio" ><input type="radio" value="kid-a" aria-describedby="s5-1" /><span class="ui-label" ><!--[-->Kid A<!--]--></span ><!----></label ><label class="ui-radio" ><input type="radio" value="in-rainbows" aria-describedby="s5-2" /><span class="ui-label" ><!--[-->In Rainbows<!--]--></span ><!----></label ><label class="ui-radio" ><input type="radio" value="king-of-limbs" aria-describedby="s5-3" /><span class="ui-label"><!--[-->The King of Limbs<!--]--></span ><!----></label ><!--]--> </div> <!--]--> </fieldset> <fieldset class="ui-fieldset"> <!--[--> <legend class=""><!--[-->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" value="the-smile" aria-describedby="s5-4" /><span class="ui-label" ><!--[--> The Smile <!--]--></span ><span id="s5-4" class="ui-end-text" ><!--[-->Thom Yorke, Jonny Greenwood, Tom Skinner<!--]--></span ></label ><label class="ui-checkbox" ><input type="checkbox" value="atoms-for-peace" aria-describedby="s5-5" /><span class="ui-label" ><!--[--> Atoms for Peace <!--]--></span ><span id="s5-5" class="ui-end-text" ><!--[-->Thom Yorke, Flea, Nigel Godrich<!--]--></span ></label ><label class="ui-checkbox" ><input type="checkbox" value="eob" aria-describedby="s5-6" /><span class="ui-label" ><!--[--> EOB <!--]--></span ><span id="s5-6" class="ui-end-text" ><!--[-->Ed O'Brien solo<!--]--></span ></label ><label class="ui-checkbox" ><input type="checkbox" value="jonny-scores" aria-describedby="s5-7" /><span class="ui-label" ><!--[--> Film Scores <!--]--></span ><span id="s5-7" class="ui-end-text" ><!--[-->Film compositions by Jonny Greenwood<!--]--></span ></label ><label class="ui-checkbox" ><input type="checkbox" value="selway-solo" aria-describedby="s5-8" /><span class="ui-label" ><!--[--> Philip Selway <!--]--></span ><span id="s5-8" class="ui-end-text" ><!--[-->Philip Selway solo albums<!--]--></span ></label ><!--]--> </div> <!--]--> </fieldset> <!--]--></form>Row
Use the direction="row" prop to lay out fields horizontally.
<script setup lang="ts">import { Checkbox, FieldGroup, FieldLegend, FieldSet, Form } from "opui-css/vue"</script>
<template> <Form> <FieldSet> <FieldLegend>Options</FieldLegend> <FieldGroup direction="row"> <Checkbox>Option 1</Checkbox> <Checkbox>Option 2</Checkbox> <Checkbox>Option 3</Checkbox> </FieldGroup> </FieldSet> </Form></template><form class="ui-form"> <!--[--> <fieldset class="ui-fieldset"> <!--[--> <legend class=""><!--[-->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.
<script setup lang="ts">import { Button, Divider, FieldGroup, FieldLegend, FieldSet, Form, TextField,} from "opui-css/vue"</script>
<template> <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></template><form class="ui-form"> <!--[--> <fieldset class="ui-fieldset"> <!--[--> <legend class=""><!--[-->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="s7-0" type="text" placeholder="My new post" /><!----><!----><!----><!----></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.
<script setup lang="ts">import { Button, Checkbox, Divider, FieldDescription, FieldGroup, FieldLegend, FieldSet, Form, Radio, Range, Select, Switch, TextField, Textarea,} from "opui-css/vue"import { ref } from "vue"
const roleItems = [ { text: "Developer", value: "dev" }, { text: "Designer", value: "design" }, { text: "Manager", value: "manager" },]
const emailNotifs = ref(true)const smsNotifs = ref(false)const theme = ref("light")const experience = ref(5)</script>
<template> <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="roleItems" /> </FieldGroup> </FieldSet>
<Divider />
<FieldSet> <FieldLegend>Notifications</FieldLegend> <FieldDescription> Configure how you want to receive updates. </FieldDescription> <FieldGroup name="notifications"> <Switch v-model="emailNotifs" name="email_notifs" >Email Notifications</Switch > <Switch v-model="smsNotifs" 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 v-model="theme" value="light">Light Theme</Radio> <Radio v-model="theme" value="dark">Dark Theme</Radio> <Radio v-model="theme" 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" v-model="experience" start-text="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 <template #end-text>Support this text</template> </Checkbox> </FieldGroup> </FieldSet>
<Divider />
<FieldGroup> <Button variant="filled" type="submit">Send</Button> <Button>Cancel</Button> </FieldGroup> </Form></template><form class="ui-form" id="kitchen-sink-example"> <!--[--> <fieldset class="ui-fieldset"> <!--[--> <legend class=""><!--[-->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="s8-0" type="text" placeholder="Jane Doe" required /><!----><!----><!----><!----></span ><!----><!--[--><!--]--></label ><label class="ui-text-field" ><span class="ui-label"><!--[-->Email Address<!--]--></span ><!----><span class="ui-field" ><input id="s8-1" type="email" placeholder="jane@example.com" required /><!----><!----><!----><!----></span ><!----><!--[--><!--]--></label ><label class="ui-select" ><span class="ui-label" id="s8-3"><!--[-->Role<!--]--></span ><!----><span class="ui-field" ><select aria-labelledby="s8-3" id="s8-2"> <button><selectedcontent></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 class=""><!--[-->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" aria-describedby="s8-5" checked /><span class="ui-label"><!--[-->Email Notifications<!--]--></span ><!----></label ><label class="ui-switch" ><!----><!----><input type="checkbox" role="switch" name="sms_notifs" aria-describedby="s8-6" /><span class="ui-label"><!--[-->SMS Notifications<!--]--></span ><!----></label ><!--]--> </div> <!--]--> </fieldset> <hr class="ui-divider" /> <fieldset class="ui-fieldset"> <!--[--> <legend class=""><!--[-->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" value="light" aria-describedby="s8-7" checked /><span class="ui-label"><!--[-->Light Theme<!--]--></span ><!----></label ><label class="ui-radio" ><input type="radio" value="dark" aria-describedby="s8-8" /><span class="ui-label" ><!--[-->Dark Theme<!--]--></span ><!----></label ><label class="ui-radio" ><input type="radio" value="system" aria-describedby="s8-9" /><span class="ui-label" ><!--[-->System Default<!--]--></span ><!----></label ><!--]--> </div> <!--]--> </fieldset> <hr class="ui-divider" /> <fieldset class="ui-fieldset"> <!--[--> <legend class=""><!--[-->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="s8-11" ><!--[-->Professional Experience<!--]--></span ><!----><span class="ui-start-text" id="s8-12" ><!--[-->Drag the slider to match your total tenure.<!--]--></span ><input aria-describedby="s8-12" aria-labelledby="s8-11" id="s8-10" type="range" min="0" max="20" step="1" value="5" /><!----><!----></label ><!--]--> </div> <!--]--> </fieldset> <hr class="ui-divider" /> <fieldset class="ui-fieldset"> <!--[--> <legend class=""><!--[-->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="s8-14" placeholder="Tell us about yourself..." rows="4" ></textarea ><!----><!----><!----><!----></span ><!----><!--[--><!--]--></label ><!--]--> </div> <!--]--> </fieldset> <hr class="ui-divider" /> <fieldset class="ui-fieldset"> <!--[--> <legend class=""><!--[-->Legal<!--]--></legend> <div class="ui-field-group" role="group"> <!--[--><label class="ui-checkbox" ><input type="checkbox" name="terms" required aria-describedby="s8-15" /><span class="ui-label" ><!--[--> I agree to the terms and conditions <!--]--></span ><span id="s8-15" class="ui-end-text" ><!--[-->Support this text<!--]--></span ></label ><!--]--> </div> <!--]--> </fieldset> <hr class="ui-divider" /> <div class="ui-field-group" role="group"> <!--[--><button class="ui-button ui-filled" type="submit"> <!--[-->Send<!--]--></button ><button class="ui-button"><!--[-->Cancel<!--]--></button ><!--]--> </div> <!--]--></form>Row
Everything all at once, but horizontally.
<script setup lang="ts">import { Button, Checkbox, Divider, FieldDescription, FieldGroup, FieldLegend, FieldSet, Form, Radio, Range, Select, Switch, TextField, Textarea,} from "opui-css/vue"import { ref } from "vue"
const roleItems = [ { text: "Developer", value: "dev" }, { text: "Designer", value: "design" }, { text: "Manager", value: "manager" },]
const emailNotifs = ref(true)const smsNotifs = ref(false)const theme = ref("light")const experience = ref(5)</script>
<template> <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> <template #label>Full Name</template> </TextField> <TextField type="email" placeholder="jane@example.com" required spread> <template #label>Email Address</template> </TextField> <Select :items="roleItems" spread> <template #label>Role</template> </Select> </FieldGroup> </FieldSet>
<Divider />
<FieldSet> <FieldLegend>Notifications</FieldLegend> <FieldDescription> Configure how you want to receive updates. </FieldDescription> <FieldGroup name="notifications"> <Switch v-model="emailNotifs" name="email_notifs" spread >Email Notifications</Switch > <Switch v-model="smsNotifs" 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 v-model="theme" value="light">Light Theme</Radio> <Radio v-model="theme" value="dark">Dark Theme</Radio> <Radio v-model="theme" 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" v-model="experience" spread> Professional Experience <template #start-text >Drag the slider to match your total tenure.</template > </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> <template #label>Biography</template> </Textarea> </FieldGroup> </FieldSet>
<Divider />
<FieldSet> <FieldLegend>Legal</FieldLegend> <FieldGroup name="legal"> <Checkbox name="terms" required spread> I agree to the terms and conditions <template #end-text>Support this text</template> </Checkbox> </FieldGroup> </FieldSet>
<Divider />
<FieldGroup> <Button variant="filled" type="submit">Send</Button> <Button>Cancel</Button> </FieldGroup> </Form></template><form class="ui-form" id="kitchen-sink-example-row"> <!--[--> <fieldset class="ui-fieldset"> <!--[--> <legend class=""><!--[-->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="s9-0" type="text" placeholder="Jane Doe" required /><!----><!----><!----><!----></span ><!----><!--[--><!--]--></label ><label class="ui-text-field ui-spread" ><span class="ui-label"><!--[-->Email Address<!--]--></span ><!----><span class="ui-field" ><input id="s9-1" type="email" placeholder="jane@example.com" required /><!----><!----><!----><!----></span ><!----><!--[--><!--]--></label ><label class="ui-select ui-spread" ><span class="ui-label" id="s9-3"><!--[-->Role<!--]--></span ><!----><span class="ui-field" ><select id="s9-2"> <button><selectedcontent></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 class=""><!--[-->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" aria-describedby="s9-5" checked /><span class="ui-label"><!--[-->Email Notifications<!--]--></span ><!----></label ><label class="ui-switch ui-spread" ><!----><!----><input type="checkbox" role="switch" name="sms_notifs" aria-describedby="s9-6" /><span class="ui-label"><!--[-->SMS Notifications<!--]--></span ><!----></label ><!--]--> </div> <!--]--> </fieldset> <hr class="ui-divider" /> <fieldset class="ui-fieldset"> <!--[--> <legend class=""><!--[-->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" value="light" aria-describedby="s9-7" checked /><span class="ui-label"><!--[-->Light Theme<!--]--></span ><!----></label ><label class="ui-radio" ><input type="radio" value="dark" aria-describedby="s9-8" /><span class="ui-label" ><!--[-->Dark Theme<!--]--></span ><!----></label ><label class="ui-radio" ><input type="radio" value="system" aria-describedby="s9-9" /><span class="ui-label" ><!--[-->System Default<!--]--></span ><!----></label ><!--]--> </div> <!--]--> </fieldset> <hr class="ui-divider" /> <fieldset class="ui-fieldset"> <!--[--> <legend class=""><!--[-->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="s9-11" ><!--[--> Professional Experience <!--]--></span ><!----><span class="ui-start-text" id="s9-12" ><!--[-->Drag the slider to match your total tenure.<!--]--></span ><input aria-describedby="s9-12" aria-labelledby="s9-11" id="s9-10" type="range" min="0" max="20" step="1" value="5" /><!----><!----></label ><!--]--> </div> <!--]--> </fieldset> <hr class="ui-divider" /> <fieldset class="ui-fieldset"> <!--[--> <legend class=""><!--[-->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="s9-14" placeholder="Tell us about yourself..." rows="4" ></textarea ><!----><!----><!----><!----></span ><!----><!--[--><!--]--></label ><!--]--> </div> <!--]--> </fieldset> <hr class="ui-divider" /> <fieldset class="ui-fieldset"> <!--[--> <legend class=""><!--[-->Legal<!--]--></legend> <div class="ui-field-group" role="group"> <!--[--><label class="ui-checkbox ui-spread" ><input type="checkbox" name="terms" required aria-describedby="s9-15" /><span class="ui-label" ><!--[--> I agree to the terms and conditions <!--]--></span ><span id="s9-15" class="ui-end-text" ><!--[-->Support this text<!--]--></span ></label ><!--]--> </div> <!--]--> </fieldset> <hr class="ui-divider" /> <div class="ui-field-group" role="group"> <!--[--><button class="ui-button ui-filled" type="submit"> <!--[-->Send<!--]--></button ><button class="ui-button"><!--[-->Cancel<!--]--></button ><!--]--> </div> <!--]--></form>API
Form
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); } } }}