Checkbox
A checkbox component for binary choices. Supports labels, disabled state, and different sizes.
Use on_change for requested values. The owner stores the value and calls cx.notify(). The existing on_click name remains a compatibility alias; setting either replaces the same handler, so the last call wins.
#Import
use gpui_kit::component::checkbox::Checkbox;// Installed in ui/components. That directory is on the Slint include path, so import by file name:
import { Checkbox } from "checkbox.slint";use iced::widget::{column, container, mouse_area, row, scrollable, svg, text};
use iced::{Alignment, Element, Length, Task, Theme};#Usage
#Basic
Checkbox::new("my-checkbox")
.label("Accept terms and conditions")
.checked(false)
.on_change(|checked, _, _| {
println!("Checkbox is now: {}", checked);
})Checkbox {
label: "Accept terms and conditions";
checked: true;
}
Checkbox {
label: "Receive product updates";
description: "Occasional emails about new releases.";
}
Checkbox {
label: "Indeterminate";
indeterminate: true;
}
Checkbox {
label: "Disabled";
enabled: false;
}// The four looks the Slint example opens with: the plain choice, the one
// with a supporting line, the indeterminate dash, and a disabled control.
let basic = column![
Checkbox::new(app.terms)
.label("Accept terms and conditions")
.on_toggle(Message::Terms),
Checkbox::new(app.product_updates)
.label("Receive product updates")
.description("Occasional emails about new releases.")
.on_toggle(Message::ProductUpdates),
// `indeterminate(true)` draws the minus while the box is unchecked;
// toggling it on draws the tick, as Slint's does.
Checkbox::new(app.some)
.indeterminate(true)
.label("Indeterminate")
.on_toggle(Message::Indeterminate),
// No message is how iced draws a control that cannot be pressed.
Checkbox::new(false).label("Disabled"),
]
.spacing(12.0);The on_change callback is triggered when the user toggles the checkbox, receiving the new checked state.
#Default
// Checked and unchecked options mixed freely in one column.
let default = column![
Checkbox::new(app.default_updates)
.label("Product updates")
.on_toggle(Message::DefaultUpdates),
Checkbox::new(app.default_remember)
.label("Remember this device")
.on_toggle(Message::DefaultRemember),
]
.spacing(12.0);Checked and unchecked options can be mixed freely.
Checkbox::new("updates")
.label("Product updates")
.checked(false)
Checkbox::new("remember")
.label("Remember this device")
.checked(true)Checkbox {
label: "Product updates";
}
Checkbox {
label: "Remember this device";
checked: true;
}#Sizes
use gpui_kit::component::Sizable as _;
Checkbox::new("cb").text_xs().label("Extra Small")
Checkbox::new("cb").text_sm().label("Small")
Checkbox::new("cb").label("Medium") // default
Checkbox::new("cb").text_lg().label("Large")GridLayout {
horizontal-stretch: 1;
spacing: 16px;
Checkbox {
horizontal-stretch: 0;
label: "XS";
size: ControlSize.xsmall;
checked: true;
}
Checkbox {
horizontal-stretch: 0;
label: "SM";
size: ControlSize.small;
checked: true;
}
Checkbox {
horizontal-stretch: 0;
label: "MD";
checked: true;
}
Checkbox {
horizontal-stretch: 0;
label: "LG";
size: ControlSize.large;
checked: true;
}
}// The box's side is 12 / 14 / 16 / 18 across the size ladder.
let sizes = row![
Checkbox::new(app.size_xs)
.size(ControlSize::XSmall)
.label("XS")
.on_toggle(Message::SizeXs),
Checkbox::new(app.size_sm)
.size(ControlSize::Small)
.label("SM")
.on_toggle(Message::SizeSm),
Checkbox::new(app.size_md)
.size(ControlSize::Medium)
.label("MD")
.on_toggle(Message::SizeMd),
Checkbox::new(app.size_lg)
.size(ControlSize::Large)
.label("LG")
.on_toggle(Message::SizeLg),
]
.spacing(16.0);#Controlled Checkbox
// The value lives on the application: `on_toggle` reports the requested
// value, `update` stores it, and the next frame draws it — what Slint's
// `checked <=> root.updates` binding does.
let controlled = column![
Checkbox::new(app.controlled)
.label("Receive product updates")
.on_toggle(Message::Controlled),
muted_line(if app.controlled {
"Subscribed"
} else {
"Not subscribed"
}),
]
.spacing(8.0);This complete Tested consumer recipe keeps the value on the rendering owner and applies the requested value from on_change before notifying:
use gpui_kit::component::checkbox::Checkbox;
use gpui_kit::{Context, IntoElement, Render, Window};
pub struct ControlledCheckbox {
checked: bool,
}
impl ControlledCheckbox {
pub fn new() -> Self {
Self { checked: false }
}
pub fn is_checked(&self) -> bool {
self.checked
}
}
impl Render for ControlledCheckbox {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
Checkbox::new("marketing-emails")
.label("Receive product updates")
.checked(self.checked)
.on_change(cx.listener(|this, checked, _, cx| {
this.checked = *checked;
cx.notify();
}))
}
}Checkbox {
label: "Receive product updates";
checked <=> root.updates;
}
Text {
text: root.updates ? "Subscribed" : "Not subscribed";
color: Theme.muted-foreground;
font-size: Theme.font-size-xs;
}#Disabled State
use gpui_kit::component::Disableable as _;
Checkbox::new("disabled-checked")
.label("Checked")
.checked(true)
.disabled(true)
Checkbox::new("disabled-unchecked")
.label("Unchecked")
.checked(false)
.disabled(true)Checkbox {
label: "Checked";
checked: true;
enabled: false;
}
Checkbox {
label: "Unchecked";
enabled: false;
}// The two disabled looks, one on and one off.
let disabled = column![
Checkbox::new(true).label("Checked"),
Checkbox::new(false).label("Unchecked"),
]
.spacing(12.0);#Without Label
Checkbox::new("checkbox")
.checked(true)Checkbox {
checked: true;
}// The box alone, with no line beside it.
let without_label = Checkbox::new(app.without_label).on_toggle(Message::WithoutLabel);#Labels
// iced has one supporting slot under the label, `description`, where Slint
// nests a second `Text`. The page's wrapping and markdown children have no
// iced counterpart, so the supporting sentence is the description here.
let labels = column![
Checkbox::new(app.label_updates)
.label("Automatic updates")
.description("Download updates when the application is idle.")
.on_toggle(Message::LabelUpdates),
Checkbox::new(app.label_notify)
.label("Notify me when a new device signs in to my account")
.on_toggle(Message::LabelNotify),
Checkbox::new(app.label_terms)
.label("Accept the terms")
.description("Read the terms of service before continuing.")
.on_toggle(Message::LabelTerms),
]
.spacing(12.0);Labels can wrap and include supporting content.
Checkbox::new("description")
.label("Automatic updates")
.child(
div()
.text_xs()
.child("Download updates when the application is idle."),
)
Checkbox::new("wrapping")
.label("Notify me when a new device signs in to my account")
Checkbox::new("markdown")
.label("Accept the terms")
.child(markdown(
"Read the [terms of service](https://github.com) before continuing.",
))Checkbox {
label: "Automatic updates";
description: "Download updates when the application is idle.";
checked: true;
}
Checkbox {
label: "Notify me when a new device signs in to my account";
}
Checkbox {
label: "Accept the terms";
description: "Read the terms of service before continuing.";
}#Custom Tab Order
Checkbox::new("checkbox")
.label("Custom tab order")
.tab_index(2)
.tab_stop(true)#Checkbox List
v_flex()
.gap_2()
.child(Checkbox::new("cb1").label("Option 1").checked(true))
.child(Checkbox::new("cb2").label("Option 2").checked(false))
.child(Checkbox::new("cb3").label("Option 3").checked(false))Checkbox {
label: "Option 1";
checked: true;
}
Checkbox {
label: "Option 2";
}
Checkbox {
label: "Option 3";
}// Independent choices: each box carries its own value.
let list = column![
Checkbox::new(app.option_1)
.label("Option 1")
.on_toggle(Message::Option1),
Checkbox::new(app.option_2)
.label("Option 2")
.on_toggle(Message::Option2),
Checkbox::new(app.option_3)
.label("Option 3")
.on_toggle(Message::Option3),
]
.spacing(12.0);#Form Integration
struct FormView {
agree_terms: bool,
subscribe: bool,
}
v_flex()
.gap_3()
.child(
Checkbox::new("terms")
.label("I agree to the terms and conditions")
.checked(self.agree_terms)
.on_change(cx.listener(|view, checked, _, cx| {
view.agree_terms = *checked;
cx.notify();
}))
)
.child(
Checkbox::new("subscribe")
.label("Subscribe to newsletter")
.checked(self.subscribe)
.on_change(cx.listener(|view, checked, _, cx| {
view.subscribe = *checked;
cx.notify();
}))
)Checkbox {
label: "I agree to the terms and conditions";
checked <=> root.terms;
}
Checkbox {
label: "Subscribe to newsletter";
checked <=> root.newsletter;
}// Two boxes of one form, each with its own value on the owner.
let form = column![
Checkbox::new(app.form_terms)
.label("I agree to the terms and conditions")
.on_toggle(Message::FormTerms),
Checkbox::new(app.form_newsletter)
.label("Subscribe to newsletter")
.on_toggle(Message::FormNewsletter),
]
.spacing(12.0);#API Reference
#Styling
Implements Sizable and Disableable traits:
text_xs()- Extra small texttext_sm()- Small texttext_base()- Base text (default)text_lg()- Large textdisabled(bool)- Disabled state
#Checkbox
A binary choice. Mirrors GPUI Component's `Checkbox`: a label, optional description, indeterminate dash, sizes, and a disabled state.
| Name | Kind | Type | Default |
|---|---|---|---|
checked | in-out | bool | |
indeterminate | in | bool | |
label | in | string | |
description | in | string | |
enabled | in | bool | true |
size | in | ControlSize | ControlSize.medium |
changed | callback | (checked: bool) |