Checkbox
Component

Checkbox

A control that allows the user to toggle between checked and not checked.

Demo

Indeterminate State

The indeterminate state is useful for "Select All" patterns where some but not all items are selected. Click the parent checkbox to toggle all children, or click individual items to see the parent update automatically.

Checkbox Group

Use CheckboxGroup to manage multiple related checkboxes. The selected values are displayed below in real-time.

Choose your interests
Selected: technology

Disabled State

Disabled checkboxes prevent user interaction and display with reduced opacity. Try clicking the disabled checkboxes below.

Disabled Group

Controlled Mode

Control the checkbox state programmatically using external buttons. This pattern is useful for complex UIs requiring external state management.

Current state: Unchecked

Custom Styling Example

Checkboxes are completely headless - style them however you want using data attributes and Tailwind utility classes.

Features

  • Three states: checked, unchecked, and indeterminate
  • Keyboard navigation (Space to toggle)
  • Controlled and uncontrolled modes
  • Support for HTML forms (hidden input)
  • Blazor EditForm integration with validation
  • Grouping capabilities via CheckboxGroup
  • WCAG compliant with proper ARIA attributes

Installation

bash
dotnet add package SummitUI

Anatomy

Import the components and structure them as follows:

razor
<SmCheckboxRoot>
    <SmCheckboxIndicator>
        <span>✓</span>
    </SmCheckboxIndicator>
</SmCheckboxRoot>

Sub-components

CheckboxRoot

The root checkbox component containing the button element.

CheckboxIndicator

Renders when the checkbox is in a checked or indeterminate state.

CheckboxGroup

A wrapper for managing a group of checkboxes.

CheckboxGroupLabel

Accessible label for the checkbox group.

API Reference

CheckboxRoot

Property Type Default Description
Checked bool? null Controlled checked state
DefaultChecked bool false Default checked state for uncontrolled mode
CheckedChanged EventCallback<bool> - Callback when checked state changes
CheckedExpression Expression<Func<bool>>? null Expression for EditForm binding and validation
Indeterminate bool false Controlled indeterminate state
IndeterminateChanged EventCallback<bool> - Callback when indeterminate state changes
Disabled bool false Prevents interaction with the checkbox
Required bool false Indicates checkbox must be checked for form submission
Name string? null Form field name for hidden input
Value string? "on" Value submitted with form data
AriaLabel string? null Accessible label for the checkbox when not wrapped in a label element

CheckboxIndicator

Property Type Default Description
ForceMount bool false Always render in DOM (useful for CSS animations)
ChildContent RenderFragment? - Content to render when checked or indeterminate

CheckboxGroup

Property Type Default Description
Values IReadOnlyList<string>? null Controlled values of checked items
DefaultValues IReadOnlyList<string>? null Default values for uncontrolled mode
ValuesChanged EventCallback<IReadOnlyList<string>> - Callback when values change
ValuesExpression Expression<Func<IReadOnlyList<string>?>>? null Expression for EditForm binding and validation
Disabled bool false Disable entire group
Name string? null Form name for hidden inputs

CheckboxGroupLabel

Property Type Default Description
ChildContent RenderFragment? - Label content for the checkbox group

Examples

Basic Usage

razor
<SmCheckboxRoot DefaultChecked="true">
    <SmCheckboxIndicator>
        <span>✓</span>
    </SmCheckboxIndicator>
</SmCheckboxRoot>

With Label

Wrap the checkbox in a label for better accessibility and click handling.

razor
<label style="display: flex; gap: 0.5rem; align-items: center;">
    <SmCheckboxRoot id="c1">
        <SmCheckboxIndicator>
            <span>✓</span>
        </SmCheckboxIndicator>
    </SmCheckboxRoot>
    Accept terms and conditions
</label>

Controlled Mode

Control the checked state externally.

razor
@code {
    private bool isChecked = true;
}

<SmCheckboxRoot @bind-Checked="isChecked">
    <SmCheckboxIndicator>
        <span>✓</span>
    </SmCheckboxIndicator>
</SmCheckboxRoot>

Indeterminate State

Use the indeterminate state for parent checkboxes with partially selected children.

razor
@code {
    private bool isIndeterminate = true;
}

<SmCheckboxRoot @bind-Indeterminate="isIndeterminate">
    <SmCheckboxIndicator>
        @if (isIndeterminate)
        {
            <span>-</span>
        }
        else
        {
            <span>✓</span>
        }
    </SmCheckboxIndicator>
</SmCheckboxRoot>

Checkbox Group

Manage multiple checkboxes as a group.

razor
@code {
    private IReadOnlyList<string> values = new[] { "apple" };
}

<SmCheckboxGroup @bind-Values="values">
    <SmCheckboxGroupLabel>Favorite Fruits</SmCheckboxGroupLabel>
    
    <label>
        <SmCheckboxRoot Value="apple">
            <SmCheckboxIndicator>✓</SmCheckboxIndicator>
        </SmCheckboxRoot>
        Apple
    </label>
    
    <label>
        <SmCheckboxRoot Value="banana">
            <SmCheckboxIndicator>✓</SmCheckboxIndicator>
        </SmCheckboxRoot>
        Banana
    </label>
</SmCheckboxGroup>

EditForm Integration (Single Checkbox)

Use with Blazor EditForm for model binding and validation support.

razor
@using System.ComponentModel.DataAnnotations

<EditForm Model="model" OnValidSubmit="HandleSubmit">
    <DataAnnotationsValidator />
    
    <label style="display: flex; gap: 0.5rem; align-items: center;">
        <SmCheckboxRoot @bind-Checked="model.AcceptTerms">
            <SmCheckboxIndicator>✓</SmCheckboxIndicator>
        </SmCheckboxRoot>
        Accept Terms and Conditions
    </label>
    <ValidationMessage For="@(() => model.AcceptTerms)" />
    
    <button type="submit">Submit</button>
</EditForm>

@code {
    private FormModel model = new();

    public class FormModel
    {
        [Range(typeof(bool), "true", "true", 
            ErrorMessage = "You must accept the terms")]
        public bool AcceptTerms { get; set; }
    }

    private void HandleSubmit() { /* handle submission */ }
}

EditForm Integration (Checkbox Group)

Use CheckboxGroup with EditForm for multi-select validation.

razor
@using System.ComponentModel.DataAnnotations

<EditForm Model="model" OnValidSubmit="HandleSubmit">
    <DataAnnotationsValidator />
    
    <SmCheckboxGroup @bind-Values="model.Interests">
        <SmCheckboxGroupLabel>Select your interests</SmCheckboxGroupLabel>
        
        <label>
            <SmCheckboxRoot Value="technology">
                <SmCheckboxIndicator>✓</SmCheckboxIndicator>
            </SmCheckboxRoot>
            Technology
        </label>
        
        <label>
            <SmCheckboxRoot Value="sports">
                <SmCheckboxIndicator>✓</SmCheckboxIndicator>
            </SmCheckboxRoot>
            Sports
        </label>
        
        <label>
            <SmCheckboxRoot Value="music">
                <SmCheckboxIndicator>✓</SmCheckboxIndicator>
            </SmCheckboxRoot>
            Music
        </label>
    </SmCheckboxGroup>
    <ValidationMessage For="@(() => model.Interests)" />
    
    <button type="submit">Submit</button>
</EditForm>

@code {
    private FormModel model = new();

    public class FormModel
    {
        [MinLength(1, ErrorMessage = "Select at least one interest")]
        public IReadOnlyList<string>? Interests { get; set; } = [];
    }

    private void HandleSubmit() { /* handle submission */ }
}

Styling

Data Attributes

Use these data attributes to style checkboxes based on their state.

Attribute Values Description
data-state "checked" | "unchecked" | "indeterminate" Current state of the checkbox
data-disabled Present when disabled Indicates disabled state

Tailwind CSS Examples

Style checkboxes using Tailwind utility classes and data attribute selectors.

Size Variants

razor
<!-- Small (16px) -->
<SmCheckboxRoot class="w-4 h-4 flex items-center justify-center bg-transparent border-2 border-su-border rounded cursor-pointer data-[state=checked]:bg-su-primary data-[state=checked]:border-su-primary">
    <SmCheckboxIndicator class="text-su-primary-foreground">
        <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
            <path d="M20 6 9 17l-5-5"/>
        </svg>
    </SmCheckboxIndicator>
</SmCheckboxRoot>

<!-- Medium (20px - default) -->
<SmCheckboxRoot class="w-5 h-5 flex items-center justify-center bg-transparent border-2 border-su-border rounded cursor-pointer data-[state=checked]:bg-su-primary data-[state=checked]:border-su-primary">
    <SmCheckboxIndicator class="text-su-primary-foreground">
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
            <path d="M20 6 9 17l-5-5"/>
        </svg>
    </SmCheckboxIndicator>
</SmCheckboxRoot>

<!-- Large (24px) -->
<SmCheckboxRoot class="w-6 h-6 flex items-center justify-center bg-transparent border-2 border-su-border rounded cursor-pointer data-[state=checked]:bg-su-primary data-[state=checked]:border-su-primary">
    <SmCheckboxIndicator class="text-su-primary-foreground">
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
            <path d="M20 6 9 17l-5-5"/>
        </svg>
    </SmCheckboxIndicator>
</SmCheckboxRoot>

Color Variants

razor
<!-- Primary (default) -->
<SmCheckboxRoot class="w-5 h-5 flex items-center justify-center bg-transparent border-2 border-su-border rounded cursor-pointer data-[state=checked]:bg-su-primary data-[state=checked]:border-su-primary">
    <SmCheckboxIndicator class="text-su-primary-foreground">✓</SmCheckboxIndicator>
</SmCheckboxRoot>

<!-- Success (green) -->
<SmCheckboxRoot class="w-5 h-5 flex items-center justify-center bg-transparent border-2 border-green-500 rounded cursor-pointer data-[state=checked]:bg-green-500 data-[state=checked]:border-green-500">
    <SmCheckboxIndicator class="text-white">✓</SmCheckboxIndicator>
</SmCheckboxRoot>

<!-- Warning (yellow) -->
<SmCheckboxRoot class="w-5 h-5 flex items-center justify-center bg-transparent border-2 border-yellow-500 rounded cursor-pointer data-[state=checked]:bg-yellow-500 data-[state=checked]:border-yellow-500">
    <SmCheckboxIndicator class="text-white">✓</SmCheckboxIndicator>
</SmCheckboxRoot>

<!-- Danger (red) -->
<SmCheckboxRoot class="w-5 h-5 flex items-center justify-center bg-transparent border-2 border-red-500 rounded cursor-pointer data-[state=checked]:bg-red-500 data-[state=checked]:border-red-500">
    <SmCheckboxIndicator class="text-white">✓</SmCheckboxIndicator>
</SmCheckboxRoot>

Interactive States

razor
<!-- With focus ring and hover effects -->
<SmCheckboxRoot class="w-5 h-5 flex items-center justify-center bg-transparent border-2 border-su-border rounded cursor-pointer transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-su-ring focus-visible:ring-offset-2 hover:border-su-primary hover:scale-105 data-[state=checked]:bg-su-primary data-[state=checked]:border-su-primary data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed">
    <SmCheckboxIndicator class="text-su-primary-foreground">✓</SmCheckboxIndicator>
</SmCheckboxRoot>

<!-- With shadow on hover -->
<SmCheckboxRoot class="w-5 h-5 flex items-center justify-center bg-transparent border-2 border-su-border rounded cursor-pointer transition-all hover:shadow-lg hover:border-su-primary data-[state=checked]:bg-su-primary data-[state=checked]:border-su-primary data-[state=checked]:shadow-md">
    <SmCheckboxIndicator class="text-su-primary-foreground">✓</SmCheckboxIndicator>
</SmCheckboxRoot>

<!-- Disabled state -->
<SmCheckboxRoot Disabled="true" class="w-5 h-5 flex items-center justify-center bg-transparent border-2 border-su-border rounded cursor-not-allowed opacity-50 data-[state=checked]:bg-su-primary data-[state=checked]:border-su-primary">
    <SmCheckboxIndicator class="text-su-primary-foreground">✓</SmCheckboxIndicator>
</SmCheckboxRoot>

Custom Shapes and Effects

razor
<!-- Circular checkbox -->
<SmCheckboxRoot class="w-5 h-5 flex items-center justify-center bg-transparent border-2 border-su-border rounded-full cursor-pointer transition-all hover:border-su-primary data-[state=checked]:bg-su-primary data-[state=checked]:border-su-primary">
    <SmCheckboxIndicator class="text-su-primary-foreground">✓</SmCheckboxIndicator>
</SmCheckboxRoot>

<!-- With gradient background -->
<SmCheckboxRoot class="w-5 h-5 flex items-center justify-center bg-transparent border-2 border-su-border rounded cursor-pointer transition-all data-[state=checked]:bg-gradient-to-br data-[state=checked]:from-blue-500 data-[state=checked]:to-purple-600 data-[state=checked]:border-transparent">
    <SmCheckboxIndicator class="text-white">✓</SmCheckboxIndicator>
</SmCheckboxRoot>

<!-- With rotation animation -->
<SmCheckboxRoot class="w-5 h-5 flex items-center justify-center bg-transparent border-2 border-su-border rounded cursor-pointer transition-all duration-300 hover:rotate-6 data-[state=checked]:bg-su-primary data-[state=checked]:border-su-primary data-[state=checked]:rotate-0">
    <SmCheckboxIndicator class="text-su-primary-foreground animate-in zoom-in-50 duration-200">✓</SmCheckboxIndicator>
</SmCheckboxRoot>

<!-- With shadow effects -->
<SmCheckboxRoot class="w-5 h-5 flex items-center justify-center bg-transparent border-2 border-su-border rounded cursor-pointer transition-all shadow-sm hover:shadow-md data-[state=checked]:bg-su-primary data-[state=checked]:border-su-primary data-[state=checked]:shadow-lg">
    <SmCheckboxIndicator class="text-su-primary-foreground">✓</SmCheckboxIndicator>
</SmCheckboxRoot>

CSS Examples

Alternative styling approaches using vanilla CSS with data attribute selectors.

Basic Styling

css
/* Checkbox styles */
.checkbox {
    width: 1.25rem;
    height: 1.25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 2px solid #ccc;
    border-radius: 4px;
    cursor: pointer;
}

.checkbox:hover {
    border-color: #666;
}

.checkbox[data-state="checked"],
.checkbox[data-state="indeterminate"] {
    background: #0066cc;
    border-color: #0066cc;
}

.checkbox[data-disabled] {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Indicator styles */
.checkbox-indicator {
    color: white;
}

Animated Checkbox

css
/* Animated checkbox with smooth transitions */
.animated-checkbox {
    width: 1.25rem;
    height: 1.25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 2px solid hsl(var(--border));
    border-radius: 0.25rem;
    cursor: pointer;
    transition: all 300ms cubic-bezier(0.4, 0, 0.2, 1);
}

.animated-checkbox:hover {
    border-color: hsl(var(--primary));
    transform: scale(1.05);
}

.animated-checkbox[data-state="checked"] {
    background: hsl(var(--primary));
    border-color: hsl(var(--primary));
    animation: checkbox-pop 300ms ease-out;
}

.animated-checkbox-indicator {
    color: hsl(var(--primary-foreground));
    animation: checkmark-appear 200ms ease-out;
}

@keyframes checkbox-pop {
    0% {
        transform: scale(1);
    }
    50% {
        transform: scale(1.1);
    }
    100% {
        transform: scale(1);
    }
}

@keyframes checkmark-appear {
    0% {
        opacity: 0;
        transform: scale(0.5);
    }
    100% {
        opacity: 1;
        transform: scale(1);
    }
}

Custom Indicator with SVG

css
/* Checkbox with custom checkmark styles */
.custom-checkbox {
    width: 1.25rem;
    height: 1.25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 2px solid hsl(var(--border));
    border-radius: 0.25rem;
    cursor: pointer;
    position: relative;
}

.custom-checkbox[data-state="checked"] {
    background: hsl(var(--primary));
    border-color: hsl(var(--primary));
}

/* Custom SVG checkmark */
.custom-checkbox[data-state="checked"]::after {
    content: '';
    position: absolute;
    width: 0.375rem;
    height: 0.75rem;
    border: solid white;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

/* For indeterminate state - horizontal line */
.custom-checkbox[data-state="indeterminate"]::after {
    content: '';
    position: absolute;
    width: 0.625rem;
    height: 2px;
    background: white;
    transform: none;
}

Themed Variants

css
/* Success theme */
.checkbox-success {
    border-color: #22c55e;
}

.checkbox-success[data-state="checked"] {
    background: #22c55e;
    border-color: #22c55e;
}

/* Warning theme */
.checkbox-warning {
    border-color: #eab308;
}

.checkbox-warning[data-state="checked"] {
    background: #eab308;
    border-color: #eab308;
}

/* Error theme */
.checkbox-error {
    border-color: #ef4444;
}

.checkbox-error[data-state="checked"] {
    background: #ef4444;
    border-color: #ef4444;
}

/* Info theme */
.checkbox-info {
    border-color: #3b82f6;
}

.checkbox-info[data-state="checked"] {
    background: #3b82f6;
    border-color: #3b82f6;
}

Accessibility

Keyboard Navigation

Key Action
Space Toggles the checkbox state

ARIA Attributes

  • role: checkbox is set on the root element
  • aria-checked: Reflects the current state (true, false, or mixed)
  • aria-label: Provides an accessible name when set via the AriaLabel parameter
  • aria-disabled: Set when the checkbox is disabled
  • aria-required: Set when the checkbox is required
An unhandled error has occurred. Reload X