Checkbox Group
A group of checkboxes for multiple selections
Basic Usage
Simple checkbox group with label and description.
Selected values: None
1
2<script lang="ts">
3 import { CheckboxGroup, CheckboxPrimitives } from "@kareyes/aether";
4
5 type CheckboxGroupOption = CheckboxPrimitives.CheckboxGroupOption;
6
7 let basicValues = $state<string[]>([]);
8
9 const basicOptions: CheckboxGroupOption[] = [
10 { id: "1", label: "Option 1", value: "option1" },
11 { id: "2", label: "Option 2", value: "option2" },
12 { id: "3", label: "Option 3", value: "option3" },
13 ];
14</script>
15
16<CheckboxGroup
17 options={basicOptions}
18 bind:values={basicValues}
19 label="Choose your options"
20 description="Select one or more options from the list"
21/>
22<p class="text-sm text-muted-foreground">
23 Selected values: {basicValues.length > 0 ? basicValues.join(", ") : "None"}
24</p>Horizontal Orientation
Checkbox group displayed in a horizontal layout.
Selected: None
1
2<script lang="ts">
3 import { CheckboxGroup, CheckboxPrimitives } from "@kareyes/aether";
4
5 type CheckboxGroupOption = CheckboxPrimitives.CheckboxGroupOption;
6
7 let preferencesValues = $state<string[]>([]);
8
9 const preferencesOptions: CheckboxGroupOption[] = [
10 { id: "email", label: "Email notifications", value: "email" },
11 { id: "sms", label: "SMS notifications", value: "sms" },
12 { id: "push", label: "Push notifications", value: "push" },
13 { id: "newsletter", label: "Newsletter", value: "newsletter", disabled: true },
14 ];
15</script>
16
17<CheckboxGroup
18 options={preferencesOptions}
19 bind:values={preferencesValues}
20 orientation="horizontal"
21 label="Notification Preferences"
22/>
23<p class="text-sm text-muted-foreground">
24 Selected: {preferencesValues.length > 0 ? preferencesValues.join(", ") : "None"}
25</p>With Descriptions
Checkbox options with descriptive text for each item.
Skills: javascript, svelte
1
2<script lang="ts">
3 import { CheckboxGroup, CheckboxPrimitives } from "@kareyes/aether";
4
5 type CheckboxGroupOption = CheckboxPrimitives.CheckboxGroupOption;
6
7 let skillsValues = $state<string[]>(["javascript", "svelte"]);
8
9 const skillsOptions: CheckboxGroupOption[] = [
10 { id: "js", label: "JavaScript", value: "javascript", description: "ES6+ and modern JS frameworks" },
11 { id: "ts", label: "TypeScript", value: "typescript", description: "Strongly typed JavaScript" },
12 { id: "svelte", label: "Svelte", value: "svelte", description: "Modern reactive framework" },
13 { id: "react", label: "React", value: "react", description: "Popular UI library" },
14 ];
15</script>
16
17<CheckboxGroup
18 options={skillsOptions}
19 bind:values={skillsValues}
20 label="Technical Skills"
21 description="Select the technologies you're proficient in"
22 checkboxSize="lg"
23/>
24<p class="text-sm text-muted-foreground">
25 Skills: {skillsValues.length > 0 ? skillsValues.join(", ") : "None"}
26</p>Todo List with Line Through
Checkbox group with line-through effect on checked items.
1
2<script lang="ts">
3 import { CheckboxGroup, CheckboxPrimitives } from "@kareyes/aether";
4
5 type CheckboxGroupOption = CheckboxPrimitives.CheckboxGroupOption;
6
7 let todosValues = $state<string[]>(["task1"]);
8
9 const todosOptions: CheckboxGroupOption[] = [
10 { id: "task1", label: "Set up development environment", value: "task1" },
11 { id: "task2", label: "Create component library", value: "task2" },
12 { id: "task3", label: "Write documentation", value: "task3" },
13 { id: "task4", label: "Add unit tests", value: "task4" },
14 ];
15</script>
16
17<CheckboxGroup
18 options={todosOptions}
19 bind:values={todosValues}
20 label="Project Tasks"
21 description="Track your progress"
22 lineThrough={true}
23 variant="success"
24/>
25<div class="text-sm text-muted-foreground">
26 Progress: {todosValues.length} / {todosOptions.length} completed
27</div>Different Sizes and Variants
Various checkbox sizes and color variants.
Small Size
Large Size
Warning Variant
Destructive Variant
1
2<script lang="ts">
3 import { CheckboxGroup, CheckboxPrimitives } from "@kareyes/aether";
4
5 type CheckboxGroupOption = CheckboxPrimitives.CheckboxGroupOption;
6
7 const basicOptions: CheckboxGroupOption[] = [
8 { id: "1", label: "Option 1", value: "option1" },
9 { id: "2", label: "Option 2", value: "option2" },
10 ];
11</script>
12
13<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
14 <div>
15 <h3 class="text-lg font-medium mb-4">Small Size</h3>
16 <CheckboxGroup options={basicOptions} values={[]} checkboxSize="sm" label="Small checkboxes" />
17 </div>
18
19 <div>
20 <h3 class="text-lg font-medium mb-4">Large Size</h3>
21 <CheckboxGroup options={basicOptions} values={[]} checkboxSize="xl" label="Extra large checkboxes" />
22 </div>
23
24 <div>
25 <h3 class="text-lg font-medium mb-4">Warning Variant</h3>
26 <CheckboxGroup
27 options={[
28 { id: "warn1", label: "Proceed with caution", value: "warn1" },
29 { id: "warn2", label: "Delete all data", value: "warn2" },
30 ]}
31 values={[]}
32 variant="warning"
33 label="Warning actions"
34 />
35 </div>
36
37 <div>
38 <h3 class="text-lg font-medium mb-4">Destructive Variant</h3>
39 <CheckboxGroup
40 options={[
41 { id: "del1", label: "Delete account", value: "del1" },
42 { id: "del2", label: "Remove all files", value: "del2" },
43 ]}
44 values={[]}
45 variant="destructive"
46 label="Destructive actions"
47 />
48 </div>
49</div>Settings Panel Example
A practical settings panel using checkbox groups.
Current Settings:
- • Enable notifications
1
2<script lang="ts">
3 import { CheckboxGroup, CheckboxPrimitives } from "@kareyes/aether";
4
5 type CheckboxGroupOption = CheckboxPrimitives.CheckboxGroupOption;
6
7 let settingsValues = $state<string[]>(["notifications"]);
8
9 const settingsOptions: CheckboxGroupOption[] = [
10 { id: "notifications", label: "Enable notifications", value: "notifications", description: "Receive app notifications" },
11 { id: "darkmode", label: "Dark mode", value: "darkmode", description: "Use dark theme" },
12 { id: "analytics", label: "Usage analytics", value: "analytics", description: "Help improve our product" },
13 { id: "marketing", label: "Marketing emails", value: "marketing", description: "Receive product updates" },
14 ];
15</script>
16
17<div class="bg-card p-6 rounded-lg border space-y-4">
18 <CheckboxGroup
19 options={settingsOptions}
20 bind:values={settingsValues}
21 label="App Settings"
22 description="Customize your app experience"
23 checkboxSize="default"
24 class="space-y-4"
25 />
26
27 <div class="pt-4 border-t">
28 <h4 class="font-medium mb-2">Current Settings:</h4>
29 <div class="text-sm text-muted-foreground">
30 {#if settingsValues.length > 0}
31 <ul class="space-y-1">
32 {#each settingsValues as setting}
33 <li>• {settingsOptions.find(opt => opt.value === setting)?.label}</li>
34 {/each}
35 </ul>
36 {:else}
37 No settings enabled
38 {/if}
39 </div>
40 </div>
41</div>Required Field
Checkbox group marked as required with validation styling.
1
2<script lang="ts">
3 import { CheckboxGroup } from "@kareyes/aether";
4</script>
5
6<CheckboxGroup
7 options={[
8 { id: "terms", label: "I accept the terms and conditions", value: "terms" },
9 { id: "privacy", label: "I accept the privacy policy", value: "privacy" },
10 ]}
11 values={[]}
12 label="Legal Agreement"
13 description="You must accept both agreements to continue"
14 required={true}
15 variant="destructive"
16/>Error States
Checkbox groups with error indicators and validation feedback.
Simple Error State
Conditional Error (Required)
❌ Please select at least one option
1
2<script lang="ts">
3 import { CheckboxGroup, CheckboxPrimitives } from "@kareyes/aether";
4
5 type CheckboxGroupOption = CheckboxPrimitives.CheckboxGroupOption;
6
7 let errorValues = $state<string[]>([]);
8 let termsValues = $state<string[]>([]);
9 let customError = $state(true);
10 let termsError = $derived(termsValues.length === 0);
11</script>
12
13<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
14 <div>
15 <h3 class="text-lg font-medium mb-4">Simple Error State</h3>
16 <CheckboxGroup
17 options={[
18 { id: "e1", label: "Option 1", value: "e1" },
19 { id: "e2", label: "Option 2", value: "e2" },
20 { id: "e3", label: "Option 3", value: "e3" },
21 ]}
22 bind:values={errorValues}
23 label="Select at least one option"
24 description="This field is required"
25 error={customError}
26 required
27 />
28 <button class="mt-2 text-sm text-primary underline" onclick={() => customError = !customError}>
29 Toggle error state
30 </button>
31 </div>
32
33 <div>
34 <h3 class="text-lg font-medium mb-4">Conditional Error (Required)</h3>
35 <CheckboxGroup
36 options={[
37 { id: "terms2", label: "I agree to the terms", value: "terms2" },
38 { id: "privacy2", label: "I agree to the privacy policy", value: "privacy2" },
39 ]}
40 bind:values={termsValues}
41 label="Required Agreements"
42 description="You must accept at least one agreement"
43 error={termsError}
44 required
45 />
46 <p class="mt-2 text-sm text-muted-foreground">
47 {termsError ? "Please select at least one option" : "Valid"}
48 </p>
49 </div>
50</div>With Field Component
Checkbox groups wrapped in Field for labels, descriptions, and error handling.
Select all technologies you're proficient in
1
2<script lang="ts">
3 import { CheckboxGroup, CheckboxPrimitives, Field } from "@kareyes/aether";
4
5 type CheckboxGroupOption = CheckboxPrimitives.CheckboxGroupOption;
6
7 let skillsValues = $state<string[]>(["javascript", "svelte"]);
8 let preferencesValues = $state<string[]>([]);
9
10 const skillsOptions: CheckboxGroupOption[] = [
11 { id: "js", label: "JavaScript", value: "javascript", description: "ES6+ and modern JS frameworks" },
12 { id: "ts", label: "TypeScript", value: "typescript", description: "Strongly typed JavaScript" },
13 { id: "svelte", label: "Svelte", value: "svelte", description: "Modern reactive framework" },
14 ];
15
16 const preferencesOptions: CheckboxGroupOption[] = [
17 { id: "email", label: "Email notifications", value: "email" },
18 { id: "sms", label: "SMS notifications", value: "sms" },
19 { id: "push", label: "Push notifications", value: "push" },
20 ];
21</script>
22
23<div class="space-y-6">
24 <Field label="Skills Selection" description="Select all technologies you're proficient in" required>
25 <CheckboxGroup options={skillsOptions} bind:values={skillsValues} checkboxSize="lg" />
26 </Field>
27
28 <Field
29 label="Notification Preferences"
30 error={preferencesValues.length === 0 ? "Please select at least one notification method" : undefined}
31 required
32 >
33 <CheckboxGroup
34 options={preferencesOptions}
35 bind:values={preferencesValues}
36 orientation="horizontal"
37 error={preferencesValues.length === 0}
38 />
39 </Field>
40</div>Disabled State
Checkbox group in a fully disabled state.
1
2<script lang="ts">
3 import { CheckboxGroup, CheckboxPrimitives } from "@kareyes/aether";
4
5 type CheckboxGroupOption = CheckboxPrimitives.CheckboxGroupOption;
6
7 const basicOptions: CheckboxGroupOption[] = [
8 { id: "1", label: "Option 1", value: "option1" },
9 { id: "2", label: "Option 2", value: "option2" },
10 { id: "3", label: "Option 3", value: "option3" },
11 ];
12</script>
13
14<CheckboxGroup
15 options={basicOptions}
16 values={["option1"]}
17 label="Disabled Group"
18 description="This entire group is disabled"
19 disabled={true}
20/>Features
- ✅ Multiple Selection Management: Handles arrays of selected values
- ✅ Flexible Layout: Vertical or horizontal orientation
- ✅ Rich Options: Support for labels, descriptions, and disabled states
- ✅ Error Handling: Built-in error state with visual feedback and aria-invalid
- ✅ Field Integration: Works seamlessly with Field component for form structure
- ✅ Consistent Styling: Inherits all checkbox variants and sizes
- ✅ Accessibility: Proper fieldset/legend structure and ARIA support
- ✅ TypeScript Support: Comprehensive type definitions
- ✅ Form Integration: Works seamlessly with form libraries
Basic Usage
Simple Checkbox Group
<script>
import { CheckboxGroup } from "@kareyes/aether";
let selectedValues = $state([]);
const options = [
{ id: "1", label: "Option 1", value: "option1" },
{ id: "2", label: "Option 2", value: "option2" },
{ id: "3", label: "Option 3", value: "option3" },
];
</script>
<CheckboxGroup
{options}
bind:values={selectedValues}
label="Choose your options"
/>
With Descriptions
<script>
const skillsOptions = [
{
id: "js",
label: "JavaScript",
value: "javascript",
description: "ES6+ and modern JS frameworks"
},
{
id: "ts",
label: "TypeScript",
value: "typescript",
description: "Strongly typed JavaScript"
},
];
let skills = $state(["javascript"]);
</script>
<CheckboxGroup
options={skillsOptions}
bind:values={skills}
label="Technical Skills"
description="Select the technologies you're proficient in"
/>
Layout Options
Horizontal Layout
<CheckboxGroup
{options}
bind:values={selectedValues}
orientation="horizontal"
label="Notification Preferences"
/>
Different Sizes
<!-- Small checkboxes -->
<CheckboxGroup
{options}
checkboxSize="sm"
label="Compact options"
/>
<!-- Large checkboxes -->
<CheckboxGroup
{options}
checkboxSize="xl"
label="Large options"
/>
Error States
Basic Error State
<script>
let selectedOptions = $state([]);
let hasError = $derived(selectedOptions.length === 0);
</script>
<CheckboxGroup
options={termsOptions}
bind:values={selectedOptions}
error={hasError}
required
label="Terms and Conditions"
description="Please accept the terms to continue"
/>
With Field Component
<script>
import { CheckboxGroup } from "@kareyes/aether";
import type { CheckboxGroupOption } from "@kareyes/aether";
import { Field } from "@kareyes/aether";
let interests = $state([]);
const interestOptions: CheckboxGroupOption[] = [
{ id: "tech", label: "Technology", value: "tech" },
{ id: "design", label: "Design", value: "design" },
{ id: "business", label: "Business", value: "business" },
];
</script>
<Field
label="Select Your Interests"
description="Choose at least one interest"
error={interests.length === 0 ? "Please select at least one interest" : undefined}
required
>
<CheckboxGroup
options={interestOptions}
bind:values={interests}
error={interests.length === 0}
/>
</Field>
Multiple CheckboxGroups with Field.Set
<script>
import { CheckboxGroup } from "@kareyes/aether";
import { FieldPrimitives } from "@kareyes/aether";
let communication = $state(["email"]);
let interests = $state([]);
</script>
<FieldPrimitives.Set>
<FieldPrimitives.Legend>Account Preferences</FieldPrimitives.Legend>
<FieldPrimitives.Description>Configure your account settings</FieldPrimitives.Description>
<FieldPrimitives.Separator />
<FieldPrimitives.Group class="gap-6">
<Field
label="Communication Preferences"
description="How should we contact you?"
required
>
<CheckboxGroup
options={[
{ id: "email", label: "Email", value: "email", description: "Receive updates via email" },
{ id: "sms", label: "SMS", value: "sms", description: "Receive text messages" },
{ id: "push", label: "Push Notifications", value: "push", description: "Browser notifications" },
]}
bind:values={communication}
/>
</Field>
<Field
label="Interests"
description="What topics interest you?"
>
<CheckboxGroup
options={[
{ id: "tech", label: "Technology", value: "tech" },
{ id: "design", label: "Design", value: "design" },
{ id: "business", label: "Business", value: "business" },
]}
bind:values={interests}
orientation="horizontal"
/>
</Field>
</FieldPrimitives.Group>
</FieldPrimitives.Set>
With Validation
<script>
import { CheckboxGroup } from "@kareyes/aether";
import { FieldPrimitives } from "@kareyes/aether";
let permissions = $state([]);
let error = $derived(permissions.length === 0);
</script>
<Field
label="User Permissions"
description="Select at least one permission to continue"
required
error={error ? "Please select at least one permission" : undefined}
>
<CheckboxGroup
options={[
{ id: "read", label: "Read", value: "read" },
{ id: "write", label: "Write", value: "write" },
{ id: "delete", label: "Delete", value: "delete" },
]}
bind:values={permissions}
error={error}
/>
</Field>
Error Callback
<script>
let values = $state([]);
function handleError(hasError: boolean) {
console.log('Error state:', hasError);
// Perform side effects when error state changes
}
</script>
<CheckboxGroup
{options}
bind:values
error={values.length === 0}
onError={handleError}
label="Required Checkboxes"
/>
Variants and Styling
Success Variant (Great for Todo Lists)
<CheckboxGroup
options={todoOptions}
bind:values={completedTasks}
variant="success"
lineThrough={true}
label="Project Tasks"
description="Track your progress"
/>
Warning and Destructive Variants
<!-- Warning variant -->
<CheckboxGroup
options={warningOptions}
variant="warning"
label="Proceed with Caution"
/>
<!-- Destructive variant -->
<CheckboxGroup
options={deleteOptions}
variant="destructive"
label="Destructive Actions"
/>
Option Structure
Each option in the options array should follow this structure:
interface CheckboxGroupOption {
id: string; // Unique identifier
label: string; // Display text
value: string; // Value to be stored in the selected array
description?: string; // Optional description text
disabled?: boolean; // Whether this specific option is disabled
}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
options |
CheckboxGroupOption[] |
[] |
Array of checkbox options |
values |
string[] |
[] |
Array of selected values (bindable) |
orientation |
'vertical' | 'horizontal' |
'vertical' |
Layout direction |
size |
'sm' | 'default' | 'lg' |
'default' |
Group text size |
checkboxSize |
'sm' | 'default' | 'lg' | 'xl' |
'default' |
Individual checkbox size |
variant |
'default' | 'destructive' | 'success' | 'warning' |
'default' |
Visual variant |
lineThrough |
boolean |
false |
Strike through text when checked |
disabled |
boolean |
false |
Disable entire group |
error |
boolean |
false |
Error state with visual feedback |
label |
string |
undefined |
Group label |
description |
string |
undefined |
Group description |
required |
boolean |
false |
Whether field is required |
class |
string |
undefined |
Additional CSS classes |
onValuesChange |
(values: string[]) => void |
undefined |
Callback when values change |
onError |
(error: boolean) => void |
undefined |
Callback when error state changes |
Examples
Todo List
<script>
let todos = $state([
{ id: "1", label: "Set up project", value: "setup" },
{ id: "2", label: "Create components", value: "components" },
{ id: "3", label: "Write tests", value: "tests" },
]);
let completed = $state(["setup"]);
</script>
<CheckboxGroup
options={todos}
bind:values={completed}
variant="success"
lineThrough={true}
label="Project Tasks"
description="Track your progress"
/>
<p>Progress: {completed.length} / {todos.length} completed</p>
Settings Panel
<script>
let settings = $state(["notifications"]);
const settingsOptions = [
{
id: "notif",
label: "Enable notifications",
value: "notifications",
description: "Receive app notifications"
},
{
id: "dark",
label: "Dark mode",
value: "darkmode",
description: "Use dark theme"
},
{
id: "analytics",
label: "Usage analytics",
value: "analytics",
description: "Help improve our product"
},
];
</script>
<CheckboxGroup
options={settingsOptions}
bind:values={settings}
label="App Settings"
description="Customize your experience"
checkboxSize="lg"
/>
Form Integration
<script>
import { enhance } from '$app/forms';
let interests = $state([]);
const interestOptions = [
{ id: "tech", label: "Technology", value: "technology" },
{ id: "design", label: "Design", value: "design" },
{ id: "business", label: "Business", value: "business" },
];
</script>
<form method="POST" use:enhance>
<CheckboxGroup
options={interestOptions}
bind:values={interests}
label="Interests"
description="What topics interest you?"
required={true}
/>
<!-- Hidden inputs for form submission -->
{#each interests as interest}
<input type="hidden" name="interests" value={interest} />
{/each}
<button type="submit">Submit</button>
</form>
Dynamic Options
<script>
let availableSkills = $state([
{ id: "js", label: "JavaScript", value: "javascript" },
{ id: "python", label: "Python", value: "python" },
{ id: "rust", label: "Rust", value: "rust" },
]);
let selectedSkills = $state([]);
function addSkill() {
const newId = Date.now().toString();
availableSkills = [...availableSkills, {
id: newId,
label: `New Skill ${newId}`,
value: `skill_${newId}`
}];
}
function handleSkillsChange(newSkills) {
console.log('Skills changed:', newSkills);
// Perform side effects here
}
</script>
<CheckboxGroup
options={availableSkills}
bind:values={selectedSkills}
label="Your Skills"
onValuesChange={handleSkillsChange}
/>
<button onclick={addSkill}>Add Skill</button>
Accessibility
- ✅ Uses
<fieldset>and<legend>for proper grouping - ✅ Each checkbox has unique IDs for screen readers
- ✅ Proper ARIA attributes and relationships
- ✅ Keyboard navigation support
- ✅ Focus management
- ✅ Required field indicators
Best Practices
- Use descriptive labels for better UX
- Group related options logically
- Provide context with group descriptions
- Use appropriate variants for different actions
- Consider orientation based on available space
- Handle empty states gracefully
- Validate selections when required
Browser Support
Works in all modern browsers with full accessibility support.