Field
Combine labels, controls, and help text to compose accessible form fields and grouped inputs.
use leptos::prelude::*; use singlestage::*; #[component] pub fn FieldExample() -> impl IntoView { let billing_same_as_shipping = RwSignal::new(true); view! { <FieldSet class="max-w-md"> <FieldLegend>"Payment Method"</FieldLegend> <FieldDescription>"All transactions are secure and encrypted"</FieldDescription> <FieldGroup> <Field> <Input placeholder="Evil Rabbit">"Name on Card"</Input> </Field> <Field> <Input placeholder="1234 5678 9012 3456">"Card Number"</Input> <FieldDescription>"Enter your 16-digit card number"</FieldDescription> </Field> <FieldGroup class="grid grid-cols-3"> <Field> <FieldLabel>"Month"</FieldLabel> <Select placeholder="MM"> <SelectOption value="01">"01"</SelectOption> <SelectOption value="02">"02"</SelectOption> <SelectOption value="03">"03"</SelectOption> <SelectOption value="04">"04"</SelectOption> <SelectOption value="05">"05"</SelectOption> <SelectOption value="06">"06"</SelectOption> <SelectOption value="07">"07"</SelectOption> <SelectOption value="08">"08"</SelectOption> <SelectOption value="09">"09"</SelectOption> <SelectOption value="10">"10"</SelectOption> <SelectOption value="11">"11"</SelectOption> <SelectOption value="12">"12"</SelectOption> </Select> </Field> <Field> <FieldLabel>"Year"</FieldLabel> <Select placeholder="YYYY"> <SelectOption value="2024">"2024"</SelectOption> <SelectOption value="2025">"2025"</SelectOption> <SelectOption value="2026">"2026"</SelectOption> <SelectOption value="2027">"2027"</SelectOption> <SelectOption value="2028">"2028"</SelectOption> <SelectOption value="2029">"2029"</SelectOption> </Select> </Field> <Field> <Input placeholder="123">"CVV"</Input> </Field> </FieldGroup> </FieldGroup> <FieldSeparator /> <FieldSet> <FieldLegend>"Billing Address"</FieldLegend> <FieldDescription> "The billing address associated with your payment method" </FieldDescription> <FieldGroup> <Field orientation="horizontal"> <Checkbox checked=billing_same_as_shipping> "Same as shipping address" </Checkbox> </Field> <Field> <Textarea class="resize-none" placeholder="Add any additional comments"> "Comments" </Textarea> </Field> <Field orientation="horizontal"> <Button>"Submit"</Button> <Button variant="outline">"Cancel"</Button> </Field> </FieldGroup> </FieldSet> </FieldSet> } }
Input
Choose a unique username for your account.
Must be at least 8 characters long.
use leptos::prelude::*; use singlestage::*; #[component] pub fn FieldInputExample() -> impl IntoView { view! { <FieldSet class="max-w-xs"> <Field> <Input placeholder="Max Leiter">"Username"</Input> <FieldDescription>"Choose a unique username for your account."</FieldDescription> </Field> <Field> <FieldLabel>"Password"</FieldLabel> <FieldDescription>"Must be at least 8 characters long."</FieldDescription> <Input input_type="password" placeholder="••••••••" /> </Field> </FieldSet> } }
Textarea
Share your thoughts about our service.
use leptos::prelude::*; use singlestage::*; #[component] pub fn FieldTextareaExample() -> impl IntoView { view! { <Field class="max-w-xs"> <Textarea placeholder="Your feedback helps us improve..." rows=4> "Feedback" </Textarea> <FieldDescription>"Share your thoughts about our service."</FieldDescription> </Field> } }
Select
Select your department or area of work.
use leptos::prelude::*; use singlestage::*; #[component] pub fn FieldSelectExample() -> impl IntoView { view! { <Field class="max-w-xs"> <FieldLabel>"Department"</FieldLabel> <Select placeholder="Choose department"> <SelectOption value="engineering">"Engineering"</SelectOption> <SelectOption value="design">"Design"</SelectOption> <SelectOption value="marketing">"Marketing"</SelectOption> <SelectOption value="sales">"Sales"</SelectOption> <SelectOption value="support">"Customer Support"</SelectOption> <SelectOption value="hr">"Human Resources"</SelectOption> <SelectOption value="finance">"Finance"</SelectOption> <SelectOption value="operations">"Operations"</SelectOption> </Select> <FieldDescription>"Select your department or area of work."</FieldDescription> </Field> } }
Slider
Set your budget range ($0 - $0).
use leptos::prelude::*; use singlestage::*; #[component] pub fn FieldSliderExample() -> impl IntoView { let value = RwSignal::new(0.); view! { <Field class="max-w-xs"> <FieldTitle>"Price Range"</FieldTitle> <FieldDescription> "Set your budget range ($" <span class="font-medium tabular-nums">"0"</span> " - $" <span class="font-medium tabular-nums">{move || value.get()}</span>")." </FieldDescription> <Slider class="mt-2 w-full" max=1000. min=0. step=10. value /> </Field> } }
Fieldset
We need your address to deliver your order.
use leptos::prelude::*; use singlestage::*; #[component] pub fn FieldSetExample() -> impl IntoView { view! { <FieldSet class="max-w-sm"> <FieldLegend>"Address Information"</FieldLegend> <FieldDescription>"We need your address to deliver your order."</FieldDescription> <FieldGroup> <Field> <Input placeholder="123 Main St">"Street Address"</Input> </Field> <FieldGroup class="grid grid-cols-2"> <Field> <Input placeholder="New York">"City"</Input> </Field> <Field> <Input placeholder="90502">"Postal Code"</Input> </Field> </FieldGroup> </FieldGroup> </FieldSet> } }
Checkbox
Select the items you want to show on the desktop.
Your Desktop & Documents folders are being synced with iCloud Drive. You can access them from other devices.
use leptos::prelude::*; use singlestage::*; #[component] pub fn FieldCheckboxExample() -> impl IntoView { let items_to_show = RwSignal::new(vec!["hard_disks".to_string()]); let sync_folders = RwSignal::new(true); view! { <FieldSet class="max-w-xs"> <FieldLegend variant="label">"Show these items on the desktop"</FieldLegend> <FieldDescription>"Select the items you want to show on the desktop."</FieldDescription> <FieldGroup> <FieldCheckboxGroup value=items_to_show> <Field orientation="horizontal"> <Checkbox value="hard_disks">"Hard disks"</Checkbox> </Field> <Field orientation="horizontal"> <Checkbox value="external_disks">"External disks"</Checkbox> </Field> <Field orientation="horizontal"> <Checkbox value="cd_dvd_ipod">"CDs, DVDs, and iPods"</Checkbox> </Field> <Field orientation="horizontal"> <Checkbox value="connected_servers">"Connected servers"</Checkbox> </Field> </FieldCheckboxGroup> </FieldGroup> <FieldSeparator /> <Field orientation="horizontal"> <Checkbox checked=sync_folders /> <FieldContent> <FieldLabel>"Sync Desktop & Documents folders"</FieldLabel> <FieldDescription> "Your Desktop & Documents folders are being synced with iCloud Drive. You can access them from other devices." </FieldDescription> </FieldContent> </Field> </FieldSet> } }
Radio
Yearly and lifetime plans offer significant savings.
use leptos::prelude::*; use singlestage::*; #[component] pub fn FieldRadioExample() -> impl IntoView { let selected_plan = RwSignal::new("monthly".to_string()); view! { <FieldSet class="max-w-xs"> <FieldLegend variant="label">"Subscription Plan"</FieldLegend> <FieldDescription> "Yearly and lifetime plans offer significant savings." </FieldDescription> <FieldGroup> <FieldRadioGroup value=selected_plan> <Field orientation="horizontal"> <Radio value="monthly">"Monthly ($9.99/month)"</Radio> </Field> <Field orientation="horizontal"> <Radio value="yearly">"Yearly ($99.99/year)"</Radio> </Field> <Field orientation="horizontal"> <Radio value="lifetime">"Lifetime ($299.99)"</Radio> </Field> </FieldRadioGroup> </FieldGroup> </FieldSet> } }
Switch
use leptos::prelude::*; use singlestage::*; #[component] pub fn FieldSwitchExample() -> impl IntoView { view! { <Field orientation="horizontal" class="w-fit"> <FieldLabel>"Multi-factor authentication"</FieldLabel> <Switch /> </Field> } }
Choice Card
Use the button variant to create selectable field buttons. This works with Radio, Checkbox and Switch components.
Select the compute environment for your cluster.
use leptos::prelude::*; use singlestage::*; #[component] pub fn FieldChoiceCardExample() -> impl IntoView { let selected_environment = RwSignal::new("kubernetes".to_string()); view! { <FieldSet class="max-w-xs"> <FieldLegend variant="label">"Compute Environment"</FieldLegend> <FieldDescription>"Select the compute environment for your cluster."</FieldDescription> <FieldGroup> <FieldRadioGroup value=selected_environment> <FieldLabel> <Field orientation="horizontal"> <FieldContent> <FieldTitle>"Kubernetes"</FieldTitle> <FieldDescription> "Run GPU workloads on a K8s cluster." </FieldDescription> </FieldContent> <Radio value="kubernetes" /> </Field> </FieldLabel> <FieldLabel> <Field orientation="horizontal"> <FieldContent> <FieldTitle>"Virtual Machine"</FieldTitle> <FieldDescription> "Access a cluster to run GPU workloads." </FieldDescription> </FieldContent> <Radio value="vm" /> </Field> </FieldLabel> </FieldRadioGroup> </FieldGroup> </FieldSet> } }
Field Group
Stack Field components with FieldGroup. Add Separator to divide them.
Get notified when ChatGPT responds to requests that take time, like research or image generation.
Get notified when tasks you've created have updates. Manage tasks
use leptos::prelude::*; use singlestage::*; #[component] pub fn FieldGroupExample() -> impl IntoView { view! { <FieldGroup class="max-w-xs"> <FieldGroup> <FieldLabel>"Responses"</FieldLabel> <FieldDescription> "Get notified when ChatGPT responds to requests that take time, like research or image generation." </FieldDescription> <Field disabled=true orientation="horizontal"> <Checkbox checked=true>"Push notifications"</Checkbox> </Field> </FieldGroup> <FieldSeparator /> <FieldGroup> <FieldLabel>"Tasks"</FieldLabel> <FieldDescription> "Get notified when tasks you've created have updates. " <Link href="#">"Manage tasks"</Link> </FieldDescription> <CheckboxGroup> <Field orientation="horizontal"> <Checkbox>"Push notifications"</Checkbox> </Field> <Field orientation="horizontal"> <Checkbox>"Email notifications"</Checkbox> </Field> </CheckboxGroup> </FieldGroup> </FieldGroup> } }
Responsive Layout
Fill in your profile information.
Provide your full name for identification
You can write your message here. Keep it short, preferably under 100 characters.
use leptos::prelude::*; use singlestage::*; #[component] pub fn FieldResponsiveLayoutExample() -> impl IntoView { view! { <FieldSet class="max-w-lg"> <FieldLegend>"Profile"</FieldLegend> <FieldDescription>"Fill in your profile information."</FieldDescription> <FieldSeparator /> <FieldGroup> <Field orientation="responsive"> <FieldContent> <FieldLabel>"Name"</FieldLabel> <FieldDescription> "Provide your full name for identification" </FieldDescription> </FieldContent> <Input placeholder="Evil Rabbit" /> </Field> <FieldSeparator /> <Field orientation="responsive"> <FieldContent> <FieldLabel>"Message"</FieldLabel> <FieldDescription> "You can write your message here. Keep it short, preferably under 100 characters." </FieldDescription> </FieldContent> <Textarea placeholder="Hello, world!" class="min-h-[100px] resize-none sm:min-w-[300px]" /> </Field> <FieldSeparator /> <Field orientation="responsive"> <Button>"Submit"</Button> <Button variant="outline">"Cancel"</Button> </Field> </FieldGroup> </FieldSet> } }
Errors
- Password is required
- Password must be at least 8 characters long
- Password must contain a number
- Password must contain uppercase letters
- Password must contain lowercase letters
use leptos::prelude::*; use singlestage::*; #[component] pub fn FieldErrorsExample() -> impl IntoView { let username_invalid = RwSignal::new(true); let password_invalid = RwSignal::new(true); let password_errors = RwSignal::new(vec![ "Password is required".to_string(), "Password must be at least 8 characters long".to_string(), "Password must contain a number".to_string(), "Password must contain uppercase letters".to_string(), "Password must contain lowercase letters".to_string(), ]); let validate_username = move |ev| { if event_target_value(&ev).is_empty() { username_invalid.set(true) } else { username_invalid.set(false) } }; let validate_password = move |ev| { let password = event_target_value(&ev); let mut errors = vec![]; if password.is_empty() { errors.push("Password is required".to_string()); }; if password.len() < 8 { errors.push("Password must be at least 8 characters long".to_string()); }; if !password.chars().any(|char| char.is_numeric()) { errors.push("Password must contain a number".to_string()); }; if !password.chars().any(|char| char.is_uppercase()) { errors.push("Password must contain uppercase letters".to_string()); }; if !password.chars().any(|char| char.is_lowercase()) { errors.push("Password must contain lowercase letters".to_string()); }; password_invalid.set(!errors.is_empty()); password_errors.set(errors); }; view! { <FieldGroup class="max-w-xs"> <Field invalid=username_invalid> <Input on:input=validate_username required=true> "Username" </Input> <FieldError>"Username is required"</FieldError> </Field> <Field invalid=password_invalid> <Input input_type="password" on:input=validate_password required=true> "Password" </Input> <FieldError errors=password_errors /> </Field> </FieldGroup> } }
Anatomy
Import all parts and piece them together.
use leptos::prelude::*; use singlestage::*; #[component] pub fn FieldAnatomy() -> impl IntoView { view! { <FieldSet> <FieldLegend /> <FieldDescription /> <FieldGroup> <Field> <FieldLabel /> <FieldError /> <Input /> <FieldDescription /> </Field> </FieldGroup> <FieldSeparator /> <FieldGroup> <Field> <FieldLabel> <FieldContent> <FieldTitle /> <FieldDescription /> </FieldContent> </FieldLabel> <Checkbox /> </Field> </FieldGroup> </FieldSet> } }
API Reference
Field
The core wrapper for a single field. Provides orientation control, invalid state styling, and spacing.
| Name | Type | Default | Description |
|---|---|---|---|
| disabled | bool | false | Sets whether this Field is disabled. |
| invalid | bool | false | Sets whether this Field is invalid. |
| orientation | String | "vertical" | Sets the display orientation. Accepted values: "vertical" | "horizontal" | "responsive". |
| required | bool | false | Provides a visual indication that this field is required when true. |
FieldCheckboxGroup
A checkbox group component for use with Field components.
| Name | Type | Default | Description |
|---|---|---|---|
| invalid | bool | false | A reactive signal that toggles whether all the children Checkboxes appear invalid or not. |
| value | Vec<String> | [] | A dynamic list of all the values of checked children Checkboxes. |
FieldContent
Flex column that groups control and descriptions when the label sits beside the control. Not required if you have no description.
FieldDescription
Helper text slot that automatically balances long lines in horizontal layouts.
FieldError
Accessible error container that accepts children or a reactive list of errors.
| Name | Type | Default | Description |
|---|---|---|---|
| errors | Vec<String> | [] | A reactive list of errors to display. |
FieldGroup
Layout wrapper that stacks Field components and enables queries for responsive orientations.
FieldLabel
A styled label associated with the input for a Field.
| Name | Type | Default | Description |
|---|---|---|---|
| disabled | bool | false | Sets whether the element renders as disabled. |
| invalid | bool | false | Sets whether the element renders as invalid. |
| label_for | String | "" | Renamed <label> `for` attribute to avoid name collisions. |
FieldLegend
Legend element for a FieldSet. Use the label variant to align with label sizing.
| Name | Type | Default | Description |
|---|---|---|---|
| variant | String | "legend" | Set the display style of the FieldLegend. Accepted values: "label" | "legend". |
FieldRadioGroup
A radio group component for use with Field components.
| Name | Type | Default | Description |
|---|---|---|---|
| default | String | "" | Set or update the default value. |
| invalid | bool | false | Renders the group with invalid styling. |
| value | String | "" | A reactive signal coupled to the current selected value of the radio group. |
FieldSeparator
Visual divider to separate sections inside a FieldSet. Accepts optional inline content.
| Name | Type | Default | Description |
|---|---|---|---|
| orientation | String | "horizontal" | A visual divider to separate sections inside a FieldSet. Accepts optional inline content. |
FieldSet
Container that renders a semantic fieldset with spacing presets.