Selection of controls: checkbox, switch, radio button
1) Key differences (meaning, not "figure")
Rule:- Need one of the N - take the radio.
- You need any set of flags - checkboxes.
- You need one binary toggle switch that immediately changes behavior - switch.
2) Decision tree (short)
1. A few independent elections? → Checkboxes.
2. Exactly one option from the set? → Radio buttons (or segment-controls/tags).
3. One binary flag, the effect is instant and noticeable? → Switch.
4. Need a "partial" mark (subset)? → Checkbox with tri-state.
5. Risk/cost is high (payment, moderation)? → Radio/checkbox + confirmation (not switch).
3) User behavior and expectations
Switch = instant result. After switching, the user expects an immediate effect and reversibility without separate Save.
Checkbox = choice of options. It can be applied immediately or by button - it is important to explicitly show the model ("Settings saved "/" Click Save").
Radio = mode selection. The transition can rebuild the interface. Signal changes (microanimation/text).
4) States and visual semantics
Normal / Hover / Focus / Active / Disabled / Error. Contrast of text and indicators ≥ AA.
Tri-state (checkbox): blank/partially/selected. The partial state is not clickable in itself - the click changes to "selected," and not "empty."
Switch: Has a clear on/off distinction in color and runner position. Color is not the only carrier of meaning (icon/label nearby).
5) Copywriting and signatures
Verb + object or statement that becomes true when selected.
Checkbox: "Receive e-mail notifications."
Switch: "Notifications: On/Off" (label on the left, state - on the right or in the switch itself).
Radio: "Coefficient Format: Decimal/Fractional/American."
Avoid double denials: "Don't unplug..." - confuses.
For risky actions, add a secondary description: "On. Quick Bets (no confirmation) - You can cancel within 5 seconds"
6) Accessibility (A11y) and keyboard
Checkbox: 'role = "checkbox"', 'aria-checked = "true' false 'mixed"', Space - switching.
Switch: native '<input type = "checkbox">' with switch visual or 'role = "switch"' with 'aria-checked'. Checkbox-like behavior (Space).
Radio: 'role = "radiogroup"' on the container, 'role = "radio"' on the elements, arrows ↑/↓ or ←/→ - move the choice, Space/Enter - confirm.
Groups: Use 'fieldset '/' legend' for general context.
Leave focus rings visible; dimensions of click zones ≥ 44 × 44 px per touch.
html
<! -- Radio Group -->
<fieldset role="radiogroup" aria-labelledby="odds-format">
<legend id = "odds-format "> Odds format </legend>
<label><input type="radio" name="odds" value="decimal" checked> Десятичный</label>
<label><input type="radio" name="odds" value="fractional"> Дробный</label>
<label> <input type = "radio" name = "odds" value = "american"> American </label>
</fieldset>
<! -- Checkbox (tri-state via aria) -->
<div role = "checkbox" aria-checked =" mixed" tabindex =" 0" id = "cb "> Notify about tournaments </div>
<! -- Switch (role = "switch") -->
<button role="switch" aria-checked="false" aria-labelledby="live-title" class="switch" id="live">
<span class="switch__knob"></span>
</button>
<span id = "live-title "> Live updates </span>
7) Asynchronous changes and errors
Switch + network: switching → immediately optimistic UI → server confirmation → if unsuccessful, gently roll back and show the reason.
Checkbox/radio on "Save": there is no confirmation yet - do not change global behavior.
Risky actions: confirmation (modalka) or undo-panel for 5-10 seconds (if the regulations allow).
js
//Optimistic for switch const sw = document. getElementById('live');
sw. addEventListener('click', async ()=>{
const prev = sw. getAttribute('aria-checked') === 'true';
sw. setAttribute ('aria-checked', String (! prev)) ;//instantly try {
const r = await fetch('/api/live', { method:'POST', body: JSON. stringify({ enabled:!prev })});
if(!r.ok) throw new Error();
} catch {
sw. setAttribute('aria-checked', String(prev)); // откат
//show the toast "Failed to enable live"
}
});
8) Mobile patterns
Switch is the main binary control in the settings on mobile.
The radio can be replaced with segmented control for 2-4 options (finger hit is better).
Checkboxes in the lists - with a large click area and support for quick multi-selection.
9) Grouping and layout patterns
Radio: vertical list (better scanned), for 2-3 options - segments in one line.
Checkboxes: one-column alignment; for long lists - "Select all" + tri-state for the group.
Switch: label on the left, control on the right on the same line; show the current status with text as needed (On/Off).
10) Antipatterns
Switch, which does not apply changes immediately (requires "Save").
Radio buttons where multiple selections are possible.
Checkbox for mutually exclusive options ("Male/Female" as two checkboxes).
Binary switch for dangerous irreversible action (delete data).
Double negations in the text.
Change the layout on error so that focus is lost.
11) iGaming specifics (examples)
The format of the coefficients: Decimal/Fractional/American radio group - is applied immediately and saved to the profile.
Quick Bet: Quick Bets (no confirmation) switch with explicit description and undo for 5-10 seconds after each operation.
Subscriptions/notifications: checkboxes by event type (wins, tournaments, deposits). Group checkbox "Select all" - tri-state.
Live updates of coefficients: switch "Live-mode" with optimism and rollback on network error.
Responsible play limits: radio buttons for periods (day/week/month) + amount field; confirmation of the changed limit with the entry "from tomorrow."
12) Design system tokens (example)
json
{
"checkbox": { "size": 20, "radius": 4, "gap": 8 },
"radio": { "size": 20, "dot": 10, "gap": 8 },
"switch": { "width": 44, "height": 24, "knob": 20, "padding": 2 },
"focusRing": { "width": 2, "offset": 2 },
"motion": { "toggleMs": 140, "ease": "cubic-bezier(0. 2,0,0. 2,1)" },
"a11y": { "contrastAA": true }
}
CSS presets (concept):
css
.control { display:flex; align-items:center; gap:8px; min-height:36px; }
.switch { width:44px; height:24px; padding:2px; border-radius:999px; background:var(--bg-muted); position:relative; }
.switch[aria-checked="true"]{ background:var(--accent); }
.switch__knob{ position:absolute; width:20px; height:20px; border-radius:50%; left:2px; top:2px; transition: transform. 14s cubic-bezier(.2,0,.2,1); background:#fff; }
.switch[aria-checked="true"].switch__knob{ transform: translateX(20px); }
.control:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; }
13) UX logic snippets
Tri-state "Select All":js function updateMaster(master, items){
const total = items. length, checked = items. filter(i=>i. checked). length;
master. indeterminate = checked>0 && checked<total;
master. checked = checked===total;
}
Radio group with keyboard (arrows):
js const radios = [...document. querySelectorAll('[role="radio"]')];
let i = radios. findIndex(r => r. getAttribute('aria-checked')==='true');
document. addEventListener('keydown', e => {
if(!['ArrowRight','ArrowDown','ArrowLeft','ArrowUp'].includes(e. key)) return;
e. preventDefault();
const dir = (e. key==='ArrowRight' e. key==='ArrowDown')? 1: -1;
i = (i + dir + radios. length) % radios. length;
radios. forEach(r => r. setAttribute('aria-checked','false'));
radios[i].setAttribute('aria-checked','true');
radios[i].focus();
});
14) Metrics and experiments
Misclick rate and undo frequency on switches.
Time to selection and validation errors by radio groups.
Proportion "Select all" and comparison with manual selection (speed, accuracy).
A/B: label copywriting, option order, segmented vs radio, "apply immediately" vs "by button."
15) QA checklist
Meaning and choice
- Control corresponds to task (multiple → checkboxes; one of N → radios; instant binary → switch).
- For risky actions, there is confirmation/undo.
Availability
- Correct roles ('checkbox '/' switch '/' radiogroup '/' radio'), 'aria-checked '/' indeterminate'.
- Focus rings are visible, arrows work in a radio group, Space switches checkbox/switch.
Behavior
- Switch applies the changes immediately; on error - rollback and message.
- Tri-state for "Select all" is correct; label clicks work.
Visual
- Contrast ≥ AA; the state is not color-only.
- Click zones ≥ 44 × 44 px; order and alignment are stable.
Mobile
- Segmented control for 2-4 radio variants tested for touch.
- Finger hitting and scrolling do not conflict.
16) Documentation in the design system
Components: 'Checkbox', 'Switch', 'RadioGroup '/' SegmentedControl'.
Size/animation/focus tokens, examples of copywriting.
Patterns: "Select all" (tri-state), "Instant application," "Undo after risk."
Do/Don't gallery: delayed-save switch (don't), radio instead of checkboxes (don't), segments for short sets (do).
Brief Summary
The choice of control is about meaning and expectations: checkbox - independent flags and groups, switch - instant on/off function, radio - exactly one option from the set. Maintain availability, think about asynchronous states and copywriting - and users will confidently change settings without errors or surprises.