Form Components
Components for building forms: inputs, checkboxes, selects, and more.
Input
Text input field:
#![allow(unused)]
fn main() {
use blinc_cn::prelude::*;
input()
.placeholder("Enter your name...")
.value(name)
.on_change(|value| set_name(value))
}
Input Types
#![allow(unused)]
fn main() {
// Text (default)
input().placeholder("Name")
// Email
input().input_type("email").placeholder("Email")
// Password
input().input_type("password").placeholder("Password")
// Number
input().input_type("number").placeholder("Age")
// Search
input().input_type("search").placeholder("Search...")
}
Input States
#![allow(unused)]
fn main() {
// Disabled
input().disabled(true)
// Read-only
input().readonly(true)
// With error
input().error(true)
}
Textarea
Multi-line text input:
#![allow(unused)]
fn main() {
textarea()
.placeholder("Enter description...")
.rows(4)
.value(description)
.on_change(|value| set_description(value))
}
Checkbox
#![allow(unused)]
fn main() {
checkbox()
.checked(is_checked)
.on_change(|checked| set_checked(checked))
.child(label("Accept terms and conditions"))
}
Indeterminate State
#![allow(unused)]
fn main() {
checkbox()
.checked(some_checked)
.indeterminate(some_checked && !all_checked)
.on_change(|checked| toggle_all(checked))
.child(label("Select all"))
}
Switch
Toggle switch:
#![allow(unused)]
fn main() {
switch_()
.checked(is_enabled)
.on_change(|enabled| set_enabled(enabled))
}
With Label
#![allow(unused)]
fn main() {
div()
.flex_row()
.items_center()
.gap(8.0)
.child(switch_().checked(dark_mode).on_change(|v| set_dark_mode(v)))
.child(label("Dark mode"))
}
Radio Group
#![allow(unused)]
fn main() {
radio_group()
.value(selected)
.on_change(|value| set_selected(value))
.child(
div().flex_col().gap(8.0)
.child(radio_item("small").child(label("Small")))
.child(radio_item("medium").child(label("Medium")))
.child(radio_item("large").child(label("Large")))
)
}
Select
Dropdown selection:
#![allow(unused)]
fn main() {
select()
.value(selected)
.on_change(|value| set_selected(value))
.child(select_trigger()
.child(select_value().placeholder("Select option...")))
.child(select_content()
.child(select_item("opt1").child(text("Option 1")))
.child(select_item("opt2").child(text("Option 2")))
.child(select_item("opt3").child(text("Option 3"))))
}
Grouped Options
#![allow(unused)]
fn main() {
select()
.child(select_trigger().child(select_value()))
.child(select_content()
.child(select_group()
.child(select_label("Fruits"))
.child(select_item("apple").child(text("Apple")))
.child(select_item("banana").child(text("Banana"))))
.child(select_separator())
.child(select_group()
.child(select_label("Vegetables"))
.child(select_item("carrot").child(text("Carrot")))
.child(select_item("broccoli").child(text("Broccoli")))))
}
Combobox
Searchable select with autocomplete:
#![allow(unused)]
fn main() {
combobox()
.value(selected)
.on_change(|value| set_selected(value))
.child(combobox_trigger()
.child(combobox_input().placeholder("Search...")))
.child(combobox_content()
.child(combobox_empty().child(text("No results found")))
.child(combobox_item("react").child(text("React")))
.child(combobox_item("vue").child(text("Vue")))
.child(combobox_item("svelte").child(text("Svelte"))))
}
Slider
Range slider:
#![allow(unused)]
fn main() {
slider()
.value(volume)
.min(0.0)
.max(100.0)
.step(1.0)
.on_change(|value| set_volume(value))
}
Range Slider
#![allow(unused)]
fn main() {
slider()
.value_range(min_price, max_price)
.min(0.0)
.max(1000.0)
.on_change_range(|min, max| {
set_min_price(min);
set_max_price(max);
})
}
Label
#![allow(unused)]
fn main() {
// Associated with input via for
label("Email").for_id("email-input")
// Direct child of input
checkbox()
.child(label("Remember me"))
}
Form Layout Example
#![allow(unused)]
fn main() {
div()
.flex_col()
.gap(24.0)
.max_w(400.0)
// Name field
.child(
div().flex_col().gap(4.0)
.child(label("Name"))
.child(input()
.placeholder("John Doe")
.value(&name)
.on_change(|v| set_name(v)))
)
// Email field
.child(
div().flex_col().gap(4.0)
.child(label("Email"))
.child(input()
.input_type("email")
.placeholder("john@example.com")
.value(&email)
.on_change(|v| set_email(v)))
)
// Country select
.child(
div().flex_col().gap(4.0)
.child(label("Country"))
.child(select()
.value(&country)
.on_change(|v| set_country(v))
.child(select_trigger().child(select_value()))
.child(select_content()
.child(select_item("us").child(text("United States")))
.child(select_item("uk").child(text("United Kingdom")))
.child(select_item("ca").child(text("Canada")))))
)
// Terms checkbox
.child(
checkbox()
.checked(accepted_terms)
.on_change(|v| set_accepted_terms(v))
.child(label("I accept the terms and conditions"))
)
// Submit button
.child(
button("Submit")
.full_width(true)
.disabled(!accepted_terms)
.on_click(|| submit_form())
)
}
Validation
#![allow(unused)]
fn main() {
let email = use_state(String::new());
let email_error = use_derived(|| {
if email.is_empty() {
None
} else if !email.contains('@') {
Some("Invalid email address")
} else {
None
}
});
div().flex_col().gap(4.0)
.child(label("Email"))
.child(input()
.value(&email)
.error(email_error.is_some())
.on_change(|v| set_email(v)))
.child(
email_error.map(|err|
text(err).size(12.0).color(Color::RED)
)
)
}