Checkbox & Radio

Clean, Apple-inspired checkbox and radio button components with smooth animations, group management, selection limits, and comprehensive dark mode support.

Basic Usage

Use apple-checkbox for multiple selections and apple-radio for single selections within a group. Each input is hidden and replaced with a custom-styled control.

Standalone Checkbox

<div class="apple-input-group">
  <label class="apple-input-wrapper apple-checkbox">
    <input type="checkbox" name="standalone" value="agree">
    <span class="apple-control"></span>
    <span class="apple-label">I agree to the terms and conditions</span>
  </label>
</div>

Standalone Radio Button

<div class="apple-input-group">
  <label class="apple-input-wrapper apple-radio">
    <input type="radio" name="gender" value="male">
    <span class="apple-control"></span>
    <span class="apple-label">Male</span>
  </label>
  <label class="apple-input-wrapper apple-radio">
    <input type="radio" name="gender" value="female">
    <span class="apple-control"></span>
    <span class="apple-label">Female</span>
  </label>
  <label class="apple-input-wrapper apple-radio">
    <input type="radio" name="gender" value="other">
    <span class="apple-control"></span>
    <span class="apple-label">Other</span>
  </label>
</div>

Checkbox Group

Select your interests
<div class="apple-input-group">
  <span class="apple-input-group-title">Select your interests</span>
  <label class="apple-input-wrapper apple-checkbox">
    <input type="checkbox" name="interests" value="design">
    <span class="apple-control"></span>
    <span class="apple-label">Design</span>
  </label>
  <!-- More checkboxes... -->
</div>

Radio Group

Choose your plan
<div class="apple-input-group">
  <span class="apple-input-group-title">Choose your plan</span>
  <label class="apple-input-wrapper apple-radio">
    <input type="radio" name="plan" value="free">
    <span class="apple-control"></span>
    <span class="apple-label">Free Plan</span>
  </label>
  <label class="apple-input-wrapper apple-radio">
    <input type="radio" name="plan" value="pro" checked>
    <span class="apple-control"></span>
    <span class="apple-label">Pro Plan - $9/month</span>
  </label>
</div>

Selection Limits

Use data-max on the group container to limit how many checkboxes can be selected. When the limit is reached, remaining unchecked boxes become disabled.

Choose up to 2 toppings (max: 2)
<div class="apple-input-group" data-max="2">
  <span class="apple-input-group-title">Choose up to 2 toppings</span>
  <label class="apple-input-wrapper apple-checkbox">
    <input type="checkbox" name="toppings" value="cheese">
    <span class="apple-control"></span>
    <span class="apple-label">Extra Cheese</span>
  </label>
  <!-- More checkboxes... -->
</div>

Disabled State

Account Settings
<!-- Disabled checkbox -->
<label class="apple-input-wrapper apple-checkbox">
  <input type="checkbox" disabled>
  <span class="apple-control"></span>
  <span class="apple-label">Disabled option</span>
</label>

<!-- Disabled radio -->
<label class="apple-input-wrapper apple-radio">
  <input type="radio" disabled>
  <span class="apple-control"></span>
  <span class="apple-label">Disabled option</span>
</label>

Component Structure

Every checkbox/radio consists of these elements:

  • .apple-input-group — Container with optional data-max
  • .apple-input-group-title — Optional group title
  • .apple-input-wrapper — Label wrapper with apple-checkbox or apple-radio
  • <input> — Hidden native input (checkbox or radio)
  • .apple-control — Custom styled control
  • .apple-label — Text label

Animations

All interactions use smooth cubic-bezier transitions. The checkmark and radio dot appear with a satisfying animation when selected.

/* Smooth transitions for all states */
.apple-control {
  transition: all 0.2s cubic-bezier(0.25, 0.8, 0.25, 1);
}

.apple-input-wrapper:hover input:not(:disabled) ~ .apple-control {
  border-color: rgba(0, 0, 0, 0.4);
}

Dark Mode

Automatic dark mode support with appropriate color adjustments and Apple-inspired dark blue accent color.

Toggle to dark mode to see the dark theme styling.

Dark Mode Example

Initialisation

// Checkboxes and radios are automatically initialized with initAll()
// No manual initialization needed!

import('@kerkhoff-ict/solora/dist/index.js')
  .then(sol => sol.initAll());

Selection Limit Logic

The initAll() function automatically enforces selection limits by:

  • Monitoring checkbox changes within groups that have data-max
  • Counting currently selected checkboxes
  • Disabling unchecked boxes when the limit is reached
  • Re-enabling boxes when selections drop below the limit
// Example: Limit to 3 selections
const limitedGroups = document.querySelectorAll('.apple-input-group[data-max]');

limitedGroups.forEach(group => {
  const maxAllowed = parseInt(group.getAttribute('data-max'), 10);
  const checkboxes = group.querySelectorAll('input[type="checkbox"]');

  checkboxes.forEach(checkbox => {
    checkbox.addEventListener('change', () => {
      const checkedCount = group.querySelectorAll('input[type="checkbox"]:checked').length;

      if (checkedCount >= maxAllowed) {
        checkboxes.forEach(cb => {
          if (!cb.checked) cb.disabled = true;
        });
      } else {
        checkboxes.forEach(cb => cb.disabled = false);
      }
    });
  });
});

CSS Classes Reference

ClassTypeDescription
.apple-input-groupContainerWrapper for related inputs with optional data-max
.apple-input-group-titleTitleGroup heading text
.apple-input-wrapperWrapperLabel wrapper that contains input, control, and label
.apple-checkboxTypeStyles wrapper for checkbox (square control)
.apple-radioTypeStyles wrapper for radio button (round control)
.apple-controlControlCustom styled checkbox/radio visual
.apple-labelLabelText label for the input
data-maxAttributeLimits checkbox selections in a group

Form Integration

Native inputs are preserved for proper form submission. Use standard name and value attributes for form processing.

<form action="/submit" method="POST">
  <div class="apple-input-group">
    <label class="apple-input-wrapper apple-checkbox">
      <input type="checkbox" name="preferences[]" value="newsletter">
      <span class="apple-control"></span>
      <span class="apple-label">Subscribe to newsletter</span>
    </label>
  </div>
  <button type="submit">Save</button>
</form>

Accessibility

♿ Best practices
  • Use proper <label> elements to wrap inputs for screen readers
  • Native inputs remain focusable and keyboard accessible
  • Disabled states are properly communicated to assistive technologies
  • Use semantic name attributes for form grouping
  • Radio buttons with the same name are automatically grouped

Common Use Cases

🎯 Perfect for
  • Terms and conditions agreements
  • Feature preference selection
  • Multi-step form options
  • Settings panels
  • Survey and questionnaire forms
  • Subscription plan selection

Browser Support

Works in all modern browsers. The custom styling is a progressive enhancement over native browser checkboxes and radio buttons.

⚠️ Fallback If CSS fails to load, users still see functional native inputs. The custom styling is purely visual enhancement.