One boolean, wired through .change(), gives your demo a feature switch — no JS, no state mgmt.
The humble checkbox is Gradio's smallest input — and the cheapest way to make a demo feel configurable instead of frozen.
gr.Checkbox() renders a single HTML checkbox with its label to the right. Its value is a Python bool: True when checked, False when not. As an input it hands that bool straight to your function — no parsing, no coercion. As an output it displays whatever bool you return. Preprocess returns the bool verbatim; postprocess passes bools through untouched. It also carries the standard component toolkit: label, info (a smaller markdown line under the label), scale, visible, interactive, elem_id, and the event listeners .change, .input and .select.
Every ML demo eventually needs a toggle: cache results, redact names, verbose logging, agree to terms before running. A Checkbox plus one .change() listener is the shortest path from 'static demo' to 'demo that responds to the user'. Because the value is a real bool, your function reads like the logic it implements — if agree: — instead of comparing strings like "on" or "yes". And because it's a component, it participates in everything else: put it in a Row, gate other components' visibility, carry it in gr.State.
import gradio as gr
with gr.Blocks() as demo:
agree = gr.Checkbox(label="I agree to the terms", info="Required before running")
status = gr.Textbox(label="status")
agree.change(lambda c: "ready" if c else "waiting for consent...",
inputs=agree, outputs=status)
demo.launch(prevent_thread_lock=True)* Running on local URL: http://127.0.0.1:7861 * To create a public link, set `share=True` in `launch()`. Rendered UI: a checkbox labeled "I agree to the terms" with smaller gray helper text "Required before running", above a single-line Textbox labeled "status" showing "waiting for consent...". Checking the box flips the Textbox to "ready" without a page reload — the bool arrives in Python as True, the lambda returns "ready", Gradio pushes it back to the Textbox.
The canonical agree-gate. Run and verified with gradio 6.28.0: the demo built and launched, printing exactly the 'Running on local URL' line shown here.
import gradio as gr
with gr.Blocks() as demo:
steps = gr.CheckboxGroup(
choices=["retrieval", "summarize", "translate"],
value=["retrieval"],
label="Pipeline steps",
show_select_all=True)
picked = gr.Textbox(label="selected")
steps.change(lambda xs: " -> ".join(xs) or "(none)",
inputs=steps, outputs=picked)
demo.launch(prevent_thread_lock=True)* Running on local URL: http://127.0.0.1:7862 * To create a public link, set `share=True` in `launch()`. Rendered UI: three checkboxes "retrieval" (pre-checked), "summarize", "translate", with a select-all control next to the "Pipeline steps" label. The "selected" Textbox below shows "retrieval"; checking summarize turns it into "retrieval -> summarize"; unchecking everything shows "(none)".
CheckboxGroup is Checkbox's plural sibling: value is a list of the selected choice strings (or indices with type="index"). show_select_all=True adds a master toggle in the group header — verified present on gr.CheckboxGroup's signature in gradio 6.28.0.
import gradio as gr
with gr.Blocks() as demo:
adv = gr.Checkbox(label="Show advanced options", value=False)
temp = gr.Slider(0, 2, value=0.7, label="temperature", visible=False)
adv.change(lambda v: gr.update(visible=v), inputs=adv, outputs=temp)
demo.launch(prevent_thread_lock=True)* Running on local URL: http://127.0.0.1:7863 * To create a public link, set `share=True` in `launch()`. Rendered UI: a single checkbox "Show advanced options" and, hidden, a temperature slider. Tick the box and the slider appears in the same slot; untick and it's gone. Your function never touches the Slider's value — the Checkbox only flips its visibility.
The show/hide pattern: one Checkbox drives gr.update(visible=...) on another component. Verified launch on port 7863. Cheap progressive disclosure without custom JS.
import gradio as gr
CORPUS = {
"docs": ["QMS manual rev 4", "audit checklist"],
"tickets": ["printer offline x3", "VPN drops"],
"wiki": ["on-call rota", "deploy runbook"],
}
def search(query, sources):
hits = [h for s in sources for h in CORPUS.get(s, [])]
return f"{len(hits)} hits: " + ", ".join(hits) if hits else "no hits"
with gr.Blocks() as demo:
query = gr.Textbox(label="query")
sources = gr.CheckboxGroup(choices=["docs", "tickets", "wiki"], value=["docs"], label="sources")
btn = gr.Button("Search")
results = gr.Textbox(label="results")
btn.click(search, inputs=[query, sources], outputs=results)
demo.launch(prevent_thread_lock=True)* Running on local URL: http://127.0.0.1:7864 * To create a public link, set `share=True` in `launch()`. Rendered UI: a Textbox "query", a three-checkbox row "sources" with "docs" pre-checked, a "Search" button, and a "results" Textbox. Query "deploy" with docs+wiki checked prints "4 hits: QMS manual rev 4, audit checklist, on-call rota, deploy runbook" in results; with no sources checked it prints "no hits" — empty list in, your empty-case branch out.
CheckboxGroup as a filter panel in a working mini-search demo — the function receives the selected source names as a list, which is why the search logic stays three lines. All four demos verified by executing them with gradio 6.28.0.
| Flag | Meaning |
|---|---|
value=True | Set the initial state; checked on load. Pass a function and Gradio calls it each time the app loads to compute the initial value. |
label=... | Text shown to the RIGHT of the box (most Gradio inputs put the label on top) — a signature quirk worth knowing before you restyle. |
info=... | Smaller helper line under the label, supports markdown; use for the 'why' while label stays the 'what'. |
interactive=False | Display-only checkbox for read-only panels; otherwise inferred — Gradio decides from whether the component is used as input or output. |
visible=False | "hidden" | False removes it but keeps its layout slot; "hidden" keeps it in the DOM but invisible — handy for state-carrier checkboxes. |
show_select_all=True (CheckboxGroup) | Adds a select/deselect-all master checkbox next to the group label; only available when show_label is True. |
type="index" (CheckboxGroup) | Makes the listener receive the indices of the selected choices instead of their strings — preprocess(["a"]) returned [0] when verified. |
Checkbox ships in Gradio from the earliest releases — it's part of the core input set documented alongside Textbox, Number, Radio and Dropdown in the 1.x era, and it has survived every major rewrite (2.x to 6.x) with its bool-in/bool-out contract unchanged.
In the 3.x/4.x redesign the Checkbox label moved to the right of the box (with info text under it), while elem_id/elem_classes/key/preserved_by_key grew around it — today you can target its DOM node with CSS or re-bind it across gr.render re-renders.