Skip to content
PorabuildHeroGPUI component library
v0.14.0 ยท Apache-2.0

Forms

Checkbox

Select one or more values from a set.

Rust
use herogpui::components::checkbox::Checkbox;

Checkbox on docs.rsSource at v0.14.0

Usage

Showing Usage, live: HeroGPUI compiled to WebAssembly. The canvas has no accessibility tree; each example's description and code below carry the same information.

Usage

Label content uses 14px medium text with 20px lines, independent of surrounding line height. Toggling animates: the accent fill scales and fades in while the check stroke draws, and unselecting undraws it; reduced motion snaps. Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{ActiveTheme, Checkbox, FieldVariant};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

let (basic, colored) = (self.cb_basic, self.cb_color);

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        Checkbox::new("checkbox-1")
            .is_selected(basic)
            .hover_bg(cx.colors().accent.soft_hover())
            .label(gpui::div().child("Accept the terms"))
            .on_change(cx.listener(|this, v: &bool, _, cx| {
                this.cb_basic = *v;
                cx.notify();
            }))
            .into_any_element(),
        Checkbox::new("checkbox-2")
            .is_selected(colored)
            .variant(FieldVariant::Secondary)
            .label(gpui::div().child("Subscribe to updates"))
            .on_change(cx.listener(|this, v: &bool, _, cx| {
                this.cb_color = *v;
                cx.notify();
            }))
            .into_any_element(),
    ])

Label Size

`text_size` replaces the label's `text-sm`; a 12/14/16px size takes v3's 16/20/24 leading. The control keeps its size step. An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::Checkbox;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

Checkbox::new("checkbox-label-size")
    .text_size(px(16.))
    .label(gpui::div().child("Larger label"))
    .description("The 16px control is unchanged")

Sizes

`size` is additive, not a prop: `Md` is the 16px control; `Sm` is a 14px control with a 10px indicator and 12px label text. Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{Checkbox, CheckboxSize};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        Checkbox::new("checkbox-sz-sm")
            .size(CheckboxSize::Sm)
            .label(gpui::div().child("Small"))
            .description("Supporting text aligns with this label")
            .into_any_element(),
        Checkbox::new("checkbox-sz-md")
            .size(CheckboxSize::Md)
            .label(gpui::div().child("Medium"))
            .description("Supporting text aligns with this label")
            .into_any_element(),
    ])

Variants

`radius(px)` replaces the control's default `rounded-md`; `is_round` keeps its documented circle either way. An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{Checkbox, FieldVariant};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        Checkbox::new("checkbox-primary")
            .default_selected(true)
            .radius(px(4.))
            .label(gpui::div().child("Primary"))
            .into_any_element(),
        Checkbox::new("checkbox-secondary")
            .default_selected(true)
            .variant(FieldVariant::Secondary)
            .label(gpui::div().child("Secondary"))
            .into_any_element(),
    ])

Full Rounded

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::Checkbox;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        Checkbox::new("checkbox-round-1")
            .is_round(true)
            .default_selected(true)
            .label(gpui::div().child("Round control"))
            .into_any_element(),
        Checkbox::new("checkbox-round-2")
            .is_round(true)
            .label(gpui::div().child("Round, unchecked"))
            .into_any_element(),
    ])

Disabled

A disabled checkbox keeps its value visible but rejects presses and leaves the tab order. An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::Checkbox;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_wrap()
    .items_center()
    .justify_center()
    .gap(px(12.))
    .children(vec![Checkbox::new("checkbox-disabled-feature")
        .label("Premium Feature")
        .description("This feature is coming soon")
        .is_disabled(true)
        .into_any_element()])

External Label

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{Checkbox, Label};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_wrap()
    .items_center()
    .justify_center()
    .gap(px(12.))
    .children(vec![gpui::div()
        .flex()
        .items_center()
        .gap(px(12.))
        .child(Checkbox::new("checkbox-external"))
        .child(Label::new("Send me marketing emails"))
        .into_any_element()])

With Description

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::Checkbox;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![Checkbox::new("checkbox-desc")
        .default_selected(true)
        .label(gpui::div().child("Weekly digest"))
        .description("One email every Monday morning.")
        .into_any_element()])

Default Selected

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::Checkbox;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![Checkbox::new("checkbox-default")
        .default_selected(true)
        .label(gpui::div().child("On by default"))
        .into_any_element()])

Invalid

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::Checkbox;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![Checkbox::new("checkbox-invalid")
        .is_required(true)
        .is_invalid(true)
        .validation_errors(["You must accept the terms"])
        .label(gpui::div().child("Accept the terms"))
        .into_any_element()])

Controlled

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{ActiveTheme, Checkbox};
use herogpui::gpui::prelude::*;
use herogpui::gpui::{App, px};
use herogpui::gpui;

let cb_controlled = self.demo_flag("cb-controlled", false);

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        Checkbox::new("checkbox-controlled")
            .is_selected(cb_controlled)
            .label(gpui::div().child("Notifications"))
            .on_change(cx.listener(|this, v: &bool, _, cx| {
                this.set_demo_flag("cb-controlled", *v);
                cx.notify();
            }))
            .into_any_element(),
        para(
            if cb_controlled {
                "Status: selected"
            } else {
                "Status: not selected"
            },
            cx,
        ),
    ])

Also calls para (included when you copy).

Indeterminate

A "select all" checkbox: it starts indeterminate, and the first change clears the dash and follows the press. Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::Checkbox;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        Checkbox::new("checkbox-indeterminate-select-all")
            .label("Select all")
            .description("Shows indeterminate state (dash icon)")
            .is_selected(self.cb_select_all_selected)
            .is_indeterminate(self.cb_select_all_indeterminate)
            .on_change(cx.listener(
                |this, selected: &bool, _, cx| {
                    this.cb_select_all_selected = *selected;
                    this.cb_select_all_indeterminate = false;
                    cx.notify();
                },
            ))
            .into_any_element(),
    ])

Form Integration

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::Checkbox;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![Checkbox::new("checkbox-form")
        .name("terms")
        .value("accepted")
        .is_required(true)
        .label(gpui::div().child("Accept the terms"))
        .into_any_element()])

Render Props

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::Checkbox;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

let cb_controlled = self.demo_flag("cb-controlled", false);

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![Checkbox::new("checkbox-render")
        .is_selected(cb_controlled)
        .on_change(cx.listener(|this, v: &bool, _, cx| {
            this.set_demo_flag("cb-controlled", *v);
            cx.notify();
        }))
        .content(|state| {
            gpui::div()
                .child(if state.is_selected {
                    "Terms accepted"
                } else {
                    "Accept terms"
                })
                .into_any_element()
        })
        .into_any_element()])

Custom Indicator

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{Checkbox, icons};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_wrap()
    .items_center()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        Checkbox::new("checkbox-ind-heart")
            .default_selected(true)
            .indicator(move |state| {
                if state.is_selected {
                    gpui::svg()
                        .size(px(10.))
                        .path(icons::HEART_FILL)
                        .text_color(gpui::white())
                        .into_any_element()
                } else {
                    gpui::div().into_any_element()
                }
            })
            .label(gpui::div().child("Heart"))
            .into_any_element(),
        Checkbox::new("checkbox-ind-plus")
            .default_selected(true)
            .indicator(move |state| {
                if state.is_selected {
                    gpui::svg()
                        .size(px(10.))
                        .path(icons::PLUS)
                        .text_color(gpui::white())
                        .into_any_element()
                } else {
                    gpui::div().into_any_element()
                }
            })
            .label(gpui::div().child("Plus"))
            .into_any_element(),
        Checkbox::new("checkbox-ind-minus")
            .is_indeterminate(true)
            .indicator(move |state| {
                if state.is_indeterminate {
                    gpui::div()
                        .w(px(10.))
                        .h(px(2.))
                        .rounded_full()
                        .bg(gpui::white())
                        .into_any_element()
                } else {
                    gpui::div().into_any_element()
                }
            })
            .label(gpui::div().child("Indeterminate"))
            .into_any_element(),
    ])

Helpers used by these examples

Plain functions over the public API, defined once here and copied with each example that calls them.

para
fn para(text: &str, cx: &App) -> gpui::AnyElement {
    let colors = cx.colors();
    gpui::div()
        .text_size(px(14.5))
        .line_height(px(24.))
        .text_color(colors.foreground)
        .max_w(px(720.))
        .child(text.to_owned())
        .into_any_element()
}

Anatomy

Rust types

Checkbox

Checkbox is assembled from these builders. The API reference lists each one.

Customization

Shared appearance belongs on ThemeBuilder::components and .recipe("name"). Typed builders change how Checkbox looks at one call site. Every builder also carries sx for placement, width and flex: it takes GPUI's own styling methods and refines them over the component's root after the theme, so an instance override wins. Behaviour builders live in the API reference below.

Styling

Checkbox styling
MethodValuesDescription
variant(FieldVariant)FieldVariant::Primary | FieldVariant::SecondaryPrimary field chrome or the flat surface treatment.
Rust
// The one slot for caller-owned low-level styling: GPUI's
// styling methods, refined over the root element last.
.sx(|el| {
    el.bg(gpui::rgba(0xffa500ff))             // background
        .text_color(gpui::rgba(0x000000ff))   // text
        .w(gpui::px(13.))                     // size
        .h(gpui::px(12.))
})

API reference

Against HeroUI v3.2.6: 32 entries ported, 3 partial, 2 not ported. Partial rows are marked in the tables; entries not ported are listed under each table with the reason.

Builders

Checkbox builders
BuilderValuesDefaultDescription
is_selected(bool)true | falsefalseWhether the checkbox is checked (controlled).
default_selected(bool)true | falsefalseWhether the checkbox is checked initially (uncontrolled).
is_indeterminate(bool)true | falsefalseWhether the checkbox displays the indeterminate mark.
is_disabled(bool)true | falsefalseDisables interaction, focus and form submission.
is_invalid(bool)true | falsefalseMarks the checkbox invalid.
is_read_only(bool)true | falsefalseKeeps the checkbox focusable while preventing selection changes.
is_required(bool)true | falsefalseRequires the checkbox to be selected for native validation.
validate(callback)Fn(value: bool) -> ValidationError | true | null | undefinedโ€”Custom validation function.
validation_behavior(ValidationBehavior)ValidationBehavior::Native | ValidationBehavior::AriaValidationBehavior::NativeWhether invalid state blocks form submission or is announced only.
variant(FieldVariant)FieldVariant::Primary | FieldVariant::SecondaryFieldVariant::PrimaryPrimary field chrome or the flat surface treatment.
name(value)stringโ€”Submitted form field name.
value(value)stringโ€”Submitted value when selected.
on_change(callback)Fn(isSelected: bool) -> ()โ€”Handler called when selection changes.
label(element) / content(|state: CheckboxState| ...)PartialAnyElement | CheckboxFieldrender closureโ€”Static children compose or a render function receives the live field state for the clickable content; Description and FieldError remain static sibling builders.
label(element)PartialAnyElement | CheckboxButtonrender closureโ€”Clickable control and label content; static content is composed by the monolithic row.
content(|state: CheckboxState| state.is_selected)true | falseโ€”Current selected state supplied to root content and the indicator renderer.
content(|state: CheckboxState| state.is_indeterminate)true | falseโ€”Current indeterminate state supplied to root content and the indicator renderer.
content(|state: CheckboxState| state.is_disabled)true | falseโ€”Current disabled state supplied to root content and the indicator renderer.
content(|state: CheckboxState| state.is_read_only)true | falseโ€”Current read-only state supplied to root content and the indicator renderer.
content(|state: CheckboxState| state.is_invalid)true | falseโ€”Current invalid state supplied to root content and the indicator renderer.
content(|state: CheckboxState| state.is_required)true | falseโ€”Current required state supplied to root content and the indicator renderer.
Not ported2 HeroUI entries not ported
Checkbox builders not ported
HeroUI v3Why it is not ported
Checkbox.renderOverrides the root element.
Checkbox.Content.classNameClasses applied to the clickable label.

Parts

Checkbox parts
PartDescription
CheckboxField root that owns value, validation, focus and form state.
CheckboxClickable row containing the control and label.
CheckboxFocusable 16px selection box.
CheckboxCheckmark, indeterminate mark or caller-drawn indicator.
CheckboxOptional field help text rendered as an indented sibling below the content row.
CheckboxValidation message rendered as an indented sibling below the content row.

States

Checkbox states
StateBuilderDescription
SelectedcheckedAccent fill and checkmark are visible; the fill scales and fades in while the stroke draws, and unselecting reverses both.
Indeterminateis_indeterminateControl background eases to the accent with a dash indicator; a selected fill remains visible.
Invalidvalidation::resolveDanger treatment reflects controlled, server or custom validation.
HoveredPartialutil::track_interaction -> fill hover colourActive control uses the accent hover fill.
Focus visibletab_stop_handleKeyboard focus rings the control.
Disabledis_disabledControl is dimmed, inert and outside the tab order.
Pressedon_click keyboard/pointer arbitrationPress activation toggles on Space or pointer release; declares no additional pressed rule body.
Read onlyis_read_only gates activation onlyControl remains focusable but selection cannot change.