Checkbox#

A labelled checkbox for binary on/off input.

Checkbox — light theme Checkbox — dark theme

Usage#

A checkbox holds a boolean checked state — read it with .value or bind a Signal with signal=, and on_change fires each time it toggles. Pass tristate=True for a third, indeterminate state.

Basic#

bs.Checkbox("Accept terms",    value=False)
bs.Checkbox("Send newsletter", value=True)

Accent colors#

bs.Checkbox("Primary",   accent="primary",   value=True)
bs.Checkbox("Secondary", accent="secondary", value=True)
bs.Checkbox("Info",      accent="info",      value=True)
bs.Checkbox("Success",   accent="success",   value=True)
bs.Checkbox("Warning",   accent="warning",   value=True)
bs.Checkbox("Danger",    accent="danger",    value=True)
Checkbox accent colors — light theme Checkbox accent colors — dark theme

Custom state icons#

Use on_icon= and off_icon= to show different icons for the checked and unchecked states. Set show_indicator=False to replace the box entirely with the icon pair.

bs.Checkbox("Checked",
    on_icon="check-circle-fill", off_icon="circle",
    show_indicator=False, accent="success", value=True)
bs.Checkbox("Unchecked",
    on_icon="check-circle-fill", off_icon="circle",
    show_indicator=False, accent="success", value=False)
Checkbox custom state icons — light theme Checkbox custom state icons — dark theme

Tristate#

Set tristate=True to enable a third indeterminate state (dash indicator). When no value= is given, the checkbox starts indeterminate. value returns None in that state.

bs.Checkbox("Indeterminate", tristate=True)
bs.Checkbox("Checked",       tristate=True, value=True)
bs.Checkbox("Unchecked",     tristate=True, value=False)

chk = bs.Checkbox("Option", tristate=True)
print(chk.value)   # → None (indeterminate)
chk.checked = True
print(chk.value)   # → True
Checkbox tristate — light theme Checkbox tristate — dark theme

Reactive binding#

Bind a Signal with signal=. The checkbox and signal stay in sync. When signal= is provided, value= is ignored — seed the Signal directly.

agreed = bs.Signal(False)
bs.Checkbox("I agree to the terms", signal=agreed)
agreed.subscribe(lambda v: submit_btn.disabled = not v)

A bound signal carries True or False. tristate=True combines with signal= — the checkbox starts at the signal’s value and reports every change back — but the indeterminate state itself does not travel. It is held by the checkbox, so a signal bound to an indeterminate checkbox reads False; read that state from the checkbox’s value, which is None there. Only code can put a checkbox into it, since clicking cycles between checked and unchecked, so this comes up in the “select all” pattern where indeterminate is computed from other boxes. For the same reason a signal created with allow_empty=True is refused at the binding.

Custom values#

Use checked_value= and unchecked_value= when the logical values are not True/False.

bs.Checkbox("Theme", checked_value="dark", unchecked_value="light")

Disabled#

bs.Checkbox("Disabled",         disabled=True)
bs.Checkbox("Disabled checked", value=True, disabled=True)
Checkbox disabled — light theme Checkbox disabled — dark theme

Events#

chk = bs.Checkbox("Option")

# Fires on every toggle
chk.on_change(lambda e: print("changed:", chk.checked))

# Fires only when checked
chk.on_check(lambda e: print("checked"))

# Fires only when unchecked
chk.on_uncheck(lambda e: print("unchecked"))

# As a Stream
chk.on_change().debounce(200).listen(lambda e: save())

Widget sizing#

All widgets accept self-placement kwargs via **kwargs. The parent container determines which options apply — Column / Row parents use the layout kwargs below, grid-based parents use grid kwargs.

Column (vertical layout)

Used inside a Column, App, or any other container with a column layout. Children are arranged top-to-bottom, so horizontal aligns each child across the width and grow shares the vertical space. (vertical does not apply — the order of the children sets their top-to-bottom position.)

horizontal

Cross-axis placement of the widget: 'left', 'center', 'right', or 'stretch' to fill the available width.

grow

Claim and fill a share of the leftover vertical space (the layout direction). True or False.

margin

External spacing in pixels. Accepts an integer (equal on all sides), a 2-tuple (horizontal, vertical), or a 4-tuple (left, top, right, bottom).

margin_x

Horizontal external spacing (left and right). Accepts an integer or a 2-tuple (left, right) for asymmetric spacing. Overrides the horizontal component of margin=.

margin_y

Vertical external spacing (top and bottom). Accepts an integer or a 2-tuple (top, bottom) for asymmetric spacing. Overrides the vertical component of margin=.

Row (horizontal layout)

Used inside a Row or any other container with a row layout. Children are arranged left-to-right, so vertical aligns each child across the height and grow shares the horizontal space. (horizontal does not apply — the order of the children sets their left-to-right position.)

vertical

Cross-axis placement of the widget: 'top', 'center', 'bottom', or 'stretch' to fill the available height.

grow

Claim and fill a share of the leftover horizontal space (the layout direction). True or False.

margin

External spacing in pixels. Accepts an integer (equal on all sides), a 2-tuple (horizontal, vertical), or a 4-tuple (left, top, right, bottom).

margin_x

Horizontal external spacing (left and right). Accepts an integer or a 2-tuple (left, right) for asymmetric spacing. Overrides the horizontal component of margin=.

margin_y

Vertical external spacing (top and bottom). Accepts an integer or a 2-tuple (top, bottom) for asymmetric spacing. Overrides the vertical component of margin=.

Grid

Used inside a Grid container.

row / column

Zero-based row and column indices.

rowspan / columnspan

Number of rows or columns to span.

horizontal

Horizontal placement within the grid cell: 'left', 'center', 'right', or 'stretch' to fill the cell width.

vertical

Vertical placement within the grid cell: 'top', 'center', 'bottom', or 'stretch' to fill the cell height.

margin

External spacing in pixels. Accepts an integer, a 2-tuple (horizontal, vertical), or a 4-tuple (left, top, right, bottom).

margin_x

Horizontal external spacing. Accepts an integer or (left, right).

margin_y

Vertical external spacing. Accepts an integer or (top, bottom).

API#

The complete reference for Checkbox lives on the Widgets API page. At a glance:

Checkbox

A labeled checkbox — checked or unchecked.

Full Example#

 1
 2with bs.App(title="Checkbox Demo", padding=20, gap=16) as app:
 3
 4    # Basic
 5    bs.Label("Basic", font="heading-sm")
 6    bs.Checkbox("Unchecked", value=False)
 7    bs.Checkbox("Checked",   value=True)
 8
 9    # Tristate — a third, indeterminate state (value is None)
10    bs.Label("Tristate", font="heading-sm")
11    with bs.Row(gap=16):
12        bs.Checkbox("Indeterminate", tristate=True)
13        bs.Checkbox("Checked",       tristate=True, value=True)
14        bs.Checkbox("Unchecked",     tristate=True, value=False)
15
16    # Accent colors
17    bs.Label("Accent Colors", font="heading-sm")
18    with bs.Row(gap=16):
19        for accent in ("primary", "secondary", "info", "success", "warning", "danger"):
20            bs.Checkbox(accent.title(), accent=accent, value=True)
21
22    # Custom state icons
23    bs.Label("Custom State Icons", font="heading-sm")
24    with bs.Row(gap=24):
25        bs.Checkbox("Checked",
26            on_icon="check-circle-fill", off_icon="circle",
27            show_indicator=False, accent="success", value=True)
28        bs.Checkbox("Unchecked",
29            on_icon="check-circle-fill", off_icon="circle",
30            show_indicator=False, accent="success", value=False)
31        bs.Checkbox("Favorite",
32            on_icon="star-fill", off_icon="star",
33            accent="warning", value=True)
34
35    # Reactive binding
36    bs.Label("Reactive Binding", font="heading-sm")
37    with bs.Column(gap=6):
38        agreed = bs.Signal(False)
39        bs.Checkbox("I agree to the terms", signal=agreed)
40        status_lbl = bs.Label("Status: not agreed", accent="secondary", font="caption")
41
42        def _update_status(v):
43            status_lbl.text = "Status: agreed" if v else "Status: not agreed"
44
45        agreed.subscribe(_update_status)
46
47    # Custom values
48    bs.Label("Custom Values", font="heading-sm")
49    with bs.Column(gap=6):
50        theme_sig = bs.Signal("light")
51        bs.Checkbox(
52            "Dark mode",
53            signal=theme_sig,
54            checked_value="dark",
55            unchecked_value="light",
56        )
57        theme_lbl = bs.Label("Theme: light", accent="secondary", font="caption")
58        def _update_theme(v):
59            theme_lbl.text = f"Theme: {v}"
60
61        theme_sig.subscribe(_update_theme)
62
63    # Disabled
64    bs.Label("Disabled", font="heading-sm")
65    with bs.Row(gap=16):
66        bs.Checkbox("Disabled unchecked", disabled=True)
67        bs.Checkbox("Disabled checked", value=True, disabled=True)
68
69    # Events
70    bs.Label("Events", font="heading-sm")
71    with bs.Column(gap=6):
72        event_lbl = bs.Label("Toggle the checkbox…", accent="secondary", font="caption")
73        event_chk = bs.Checkbox("Toggle me")
74
75        def _on_change(e):
76            state = "checked" if event_chk.checked else "unchecked"
77            event_lbl.text = f"State: {state}"
78
79        event_chk.on_change(_on_change)
80
81app.run()