Skip to content
Auto

Checkbox

The Checkbox component provides a binary choice input with support for indeterminate states.

Terminal window
pnpm add @aetherui-kit/core
Accept terms and conditions
<ae-checkbox>Accept terms and conditions</ae-checkbox>
Checked checkbox Unchecked checkbox Indeterminate checkbox Disabled checkbox Disabled checked checkbox Disabled indeterminate checkbox
<div style="display: flex; flex-direction: column; gap: 1rem;">
<!-- Checked state -->
<ae-checkbox checked>Checked checkbox</ae-checkbox>
<!-- Unchecked state (default) -->
<ae-checkbox>Unchecked checkbox</ae-checkbox>
<!-- Indeterminate state -->
<ae-checkbox indeterminate>Indeterminate checkbox</ae-checkbox>
<!-- Disabled states -->
<ae-checkbox disabled>Disabled checkbox</ae-checkbox>
<ae-checkbox checked disabled>Disabled checked checkbox</ae-checkbox>
<ae-checkbox indeterminate disabled>Disabled indeterminate checkbox</ae-checkbox>
</div>

Adjust the checkbox size using the --ae-checkbox-size custom property.

Small checkbox Default size checkbox Large checkbox Extra large checkbox
<div style="display: flex; flex-direction: column; gap: 1rem;">
<ae-checkbox style="--ae-checkbox-size: 0.875rem;">Small checkbox</ae-checkbox>
<ae-checkbox>Default size checkbox</ae-checkbox>
<ae-checkbox style="--ae-checkbox-size: 1.25rem;">Large checkbox</ae-checkbox>
<ae-checkbox style="--ae-checkbox-size: 1.5rem;">Extra large checkbox</ae-checkbox>
</div>

Customize the checkbox appearance using CSS custom properties and parts.

Round purple checkbox (checked) Round purple checkbox (indeterminate) Square checkbox with red indicator (checked) Square checkbox with red indicator (indeterminate) Orange indeterminate indicator
<style>
.custom-checkbox {
--ae-checkbox-size: 1.25rem;
--ae-checkbox-checked-bg: #8b5cf6;
--ae-checkbox-checked-border-color: #8b5cf6;
--ae-checkbox-indeterminate-bg: #8b5cf6;
--ae-checkbox-indeterminate-border-color: #8b5cf6;
}
.custom-checkbox::part(control) {
border-radius: 50%;
}
.square-checkbox::part(control) {
border-radius: 0;
border-width: 2px;
}
.square-checkbox::part(icon) {
color: #ef4444;
}
.square-checkbox::part(indeterminate-icon) {
color: #ef4444;
}
.square-checkbox::part(label) {
font-weight: 600;
}
.orange-indeterminate {
--ae-checkbox-indeterminate-bg: #f59e0b;
--ae-checkbox-indeterminate-border-color: #f59e0b;
--ae-checkbox-indeterminate-icon-color: #ffffff;
}
</style>
<div style="display: flex; flex-direction: column; gap: 1rem;">
<ae-checkbox class="custom-checkbox" checked>Round purple checkbox (checked)</ae-checkbox>
<ae-checkbox class="custom-checkbox" indeterminate>Round purple checkbox (indeterminate)</ae-checkbox>
<ae-checkbox class="square-checkbox" checked>Square checkbox with red indicator (checked)</ae-checkbox>
<ae-checkbox class="square-checkbox" indeterminate>Square checkbox with red indicator (indeterminate)</ae-checkbox>
<ae-checkbox class="orange-indeterminate" indeterminate>Orange indeterminate indicator</ae-checkbox>
</div>

The indeterminate state is commonly used for “Select All” checkboxes that control multiple child checkboxes.

Select All Items
Item 1 Item 2 Item 3 Item 4
<style>
.select-all-container {
border: 1px solid #e2e8f0;
border-radius: 0.5rem;
padding: 1rem;
}
.child-list {
margin-top: 1rem;
display: flex;
flex-direction: column;
gap: 0.5rem;
padding-left: 1.5rem;
}
</style>
<script>
document.addEventListener('DOMContentLoaded', () => {
const parentCheckbox = document.querySelector('#parent-checkbox');
const childCheckboxes = document.querySelectorAll('.child-checkbox');
// Update parent based on children
function updateParentState() {
const totalChildren = childCheckboxes.length;
const checkedCount = Array.from(childCheckboxes).filter(cb => cb.checked).length;
if (checkedCount === 0) {
parentCheckbox.checked = false;
parentCheckbox.indeterminate = false;
} else if (checkedCount === totalChildren) {
parentCheckbox.checked = true;
parentCheckbox.indeterminate = false;
} else {
parentCheckbox.checked = false;
parentCheckbox.indeterminate = true;
}
}
// Add event listeners to child checkboxes
childCheckboxes.forEach(checkbox => {
checkbox.addEventListener('ae-checkbox-change', updateParentState);
});
// Add event listener to parent checkbox
parentCheckbox.addEventListener('ae-checkbox-change', (e) => {
const newCheckedState = e.detail.checked;
childCheckboxes.forEach(checkbox => {
checkbox.checked = newCheckedState;
});
});
// Initialize parent state
updateParentState();
});
</script>
<div class="select-all-container">
<ae-checkbox id="parent-checkbox">Select All Items</ae-checkbox>
<div class="child-list">
<ae-checkbox class="child-checkbox">Item 1</ae-checkbox>
<ae-checkbox class="child-checkbox" checked>Item 2</ae-checkbox>
<ae-checkbox class="child-checkbox">Item 3</ae-checkbox>
<ae-checkbox class="child-checkbox">Item 4</ae-checkbox>
</div>
</div>

The checkbox emits an ae-change event when its state changes.

Toggle me
Toggle the checkbox to see events
<script>
document.addEventListener('DOMContentLoaded', () => {
const checkbox = document.querySelector('#event-demo');
const status = document.querySelector('#event-status');
const setIndeterminateBtn = document.querySelector('#set-indeterminate');
if (checkbox && status) {
checkbox.addEventListener('ae-checkbox-change', (e) => {
status.textContent = `Checkbox is now ${e.detail.indeterminate ? 'indeterminate' : e.detail.checked ? 'checked' : 'unchecked'}`;
});
if (setIndeterminateBtn) {
setIndeterminateBtn.addEventListener('click', () => {
checkbox.indeterminate = true;
});
}
}
});
</script>
<div style="display: flex; flex-direction: column; gap: 1rem;">
<ae-checkbox id="event-demo">Toggle me</ae-checkbox>
<button id="set-indeterminate" style="align-self: flex-start; padding: 0.5rem 1rem; background: #4f46e5; color: white; border: none; border-radius: 0.25rem; cursor: pointer;">Set to indeterminate</button>
<div id="event-status">Toggle the checkbox to see events</div>
</div>
Name Type Default Description
checked boolean false Controlled checked state
defaultChecked boolean false Initial checked state for uncontrolled usage
indeterminate boolean false Sets the checkbox to an indeterminate/mixed state
disabled boolean false Disables the checkbox
Name Detail Description
ae-checkbox-change { checked: boolean, indeterminate: boolean } Fired when the checkbox state changes
Name Description
base The label container wrapping the checkbox
control The checkbox control (box that contains the checkmark)
icon The checkmark icon when checked
indeterminate-icon The dash icon when in indeterminate state
label The label text container
input The native checkbox input (visually hidden)
Name Description
--ae-checkbox-size Size of the checkbox control
--ae-checkbox-border-color Border color for the unchecked state
--ae-checkbox-bg Background color for the unchecked state
--ae-checkbox-border-radius Border radius of the checkbox control
--ae-checkbox-checked-border-color Border color for the checked state
--ae-checkbox-checked-bg Background color for the checked state
--ae-checkbox-checked-icon-color Color of the checkmark icon
--ae-checkbox-indeterminate-border-color Border color for the indeterminate state
--ae-checkbox-indeterminate-bg Background color for the indeterminate state
--ae-checkbox-indeterminate-icon-color Color of the indeterminate dash icon
--ae-checkbox-disabled-border-color Border color when disabled
--ae-checkbox-disabled-bg Background color when disabled
--ae-checkbox-disabled-text-color Text color when disabled
--ae-checkbox-text-color Text color for the label
--ae-checkbox-font-size Font size for the label
--ae-checkbox-focus-ring-color Color of the focus ring

The checkbox component follows WAI-ARIA guidelines:

  • Uses native <input type="checkbox"> to maintain accessibility
  • Properly syncs aria-checked="mixed" for indeterminate states
  • Supports keyboard navigation and focus management
  • Associates the label text with the checkbox input for clear context