Accordion Checkbox
A compound disclosure widget that pairs a checkbox option with a revealable panel. The user sees a vertical list of checkbox options; checking a box reveals an accordion panel of additional content beneath that option. Common use cases include conditional follow-up questions, opt-in disclosures, and form sections that only apply once selected.
Unlike Details, which uses a <summary> toggle, this component uses a real form control. The checkbox state is the source of truth — checked controls whether the panel is visible. Multiple AccordionCheckbox instances can stack vertically to make a list of independent toggleable options.
Implementation Notes
- Renders a
<div class="accordion-checkbox">containing an<input type="checkbox">, its<label>, and a<div class="accordion-checkbox-panel">that is hidden when unchecked - Auto-generates a unique id linking the checkbox (
<id>-checkbox) and the panel (<id>-panel) soaria-controlsand<label for>resolve correctly - Sets
aria-controlson the checkbox pointing at the panel andaria-expandedmatching the checked state - Sets
role="region"andaria-labelledbyon the panel so screen readers identify the revealed area as a labeled region - Applies the native
hiddenattribute to the panel when unchecked so it is removed from the layout and the accessibility tree - Supports two-way binding on the
checkedprop for parent components to control or react to the state - Spreads
restPropsonto the root<div>for consumer customization
Props
label: string (required) — the checkbox label textchecked: boolean (default: false) — whether the checkbox is checked and the panel is revealed; bindableid: string (optional) — base id for the checkbox/panel link; auto-generated if not providedchildren: slot (required) — content shown when the checkbox is checked
Usage
<AccordionCheckbox label="I have a follow-up question">
<p>Tell us more in the text-area-input below.</p>
<textarea aria-label="Your question"></textarea>
</AccordionCheckbox>
<AccordionCheckbox label="Subscribe to optional updates" checked>
<fieldset>
<legend>Topics</legend>
<label><input type="checkbox" name="topic" value="news"> News</label>
<label><input type="checkbox" name="topic" value="events"> Events</label>
</fieldset>
</AccordionCheckbox>
Keyboard Interactions
- Tab: moves focus onto the checkbox
- Space: toggles the checkbox checked state, which reveals or hides the panel
- Native checkbox keyboard behavior applies; no custom handlers required
ARIA
aria-controlson the<input>references the panel id so assistive technology can navigate from the trigger to its targetaria-expandedon the<input>reflects the checked state, so screen readers announce open/closedrole="region"andaria-labelledbyon the panel identify it as a labeled landmark region tied to the checkboxhiddenon the panel removes it from the accessibility tree when unchecked
When to Use
- Use when an option introduces follow-up content the user only needs to see if they opt in
- Use for conditional sections of forms (for example, "I have additional comments" → text-area-input)
- Use when stacking several independent opt-in disclosures vertically as a list
- Use when the trigger should be a real form control, so the value is part of form submission
When Not to Use
- Do not use when the trigger is informational only — use
Details(<details>/<summary>) instead - Do not use to switch a setting on/off without revealing additional content — use
SwitchButtonor a plainCheckboxInput - Do not use for mutually exclusive options — use
RadioGroup - Do not use when only one of many options can be expanded at a time — use
AccordionList/AccordionListItem
Headless
This headless component renders semantic HTML (<div> wrapping a <label> + <input type="checkbox"> + revealable panel) with all required ARIA wiring. The consumer provides all visual styling — including spacing, indentation, focus rings, and any animation on the reveal.
Styles
The consumer provides all CSS styling. The component renders with these class hooks:
.accordion-checkboxon the root<div>.accordion-checkbox-inputon the<input type="checkbox">.accordion-checkbox-labelon the<label>.accordion-checkbox-panelon the revealable<div>
No default styles are included — this is a fully headless component.
Testing
- Verify the root
<div>has classaccordion-checkbox - Verify the checkbox toggles
aria-expandedand the panelhiddenattribute together - Verify
aria-controlson the checkbox matches the panelid - Verify the panel content is in the accessibility tree only when checked
- Verify two-way binding on
checkedreflects parent state - Verify keyboard activation via Space toggles the panel
Advice
- Designers: Indicate that the option reveals more content (a chevron or "+/–" cue helps). Make sure the revealed panel is visually grouped with its trigger so the relationship is unambiguous.
- Developers: Keep the panel content lightweight; if it grows large, consider lazy rendering tied to the
checkedprop. Validate any inputs inside the panel only when the checkbox is checked.
Related components
accordion-list— an accordion ordered list of list item componentsaccordion-list-item— an accordion list item componentdetails— a disclosure widget that shows and hides contentswitch-button— a toggle switch for turning a setting on or offcheckbox-input— a checkbox input for toggling a boolean value <input type="checkbox">
References
- WAI-ARIA Disclosure Pattern: https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/
- MDN input type=checkbox: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox
- MDN aria-controls: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls
- MDN hidden attribute: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/hidden