East Blue
FixReady
Checkbox Component link

A selection control for binary and partial choices. 33 variants across isSelected (true/false/indeterminate) × State (Default/Pressed/Focused/Disabled/Error) × Size (Small/Medium/Large).

Fix — Reusable and Composable are partial
All five interaction states and indeterminate exist across three sizes. The control is icon-only by design, so label composition depends on CheckboxItem.
In Context

How the checkbox appears in real product screens — single and multi-select options on a loan Disclosure Statement (Schedule of Payment, Collateral), and checkboxes toggling which services a user can access.

Checkbox component shown on two GCash screens: a Disclosure Statement with checked and unchecked options under Schedule of Payment and Collateral, and a Services screen where checkboxes turn Cash In and Buy Load on and GLife and Non-Telco Load off
Live Preview
Properties
isSelected
State
Size
DS Health
Reusable
Partial
All 5 interaction states and indeterminate defined across 3 sizes (C5 resolved). Checkbox is icon-only by design — CheckboxItem compound component provides label + description pairing.
Self-contained
Pass
Checkmark is a separable icon-check child layer (C6 resolved). All 5 interaction states and indeterminate defined across 3 sizes (C5 resolved). Carries its own visual states and token bindings.
Consistent
Pass
Token naming follows DS convention (main/checkbox/color/...). isSelected uses true/false/indeterminate. All property values follow boolean and enum standards (C2 resolved).
Composable
Partial
Nests in form layouts, list rows, and select-all patterns. Indeterminate state defined. CheckboxItem compound component wraps Checkbox + Label + Description for accessible form groups.
Behavior
State iOS Android Figma Property Notes
Unchecked Yes Yes isSelected=false Border-only container. 3 sizes.
Checked Yes Yes isSelected=true Blue fill + separable icon-check layer.
Indeterminate Yes Yes isSelected=indeterminate Blue fill + icon-indeterminate dash.
Disabled Yes Yes State=Disabled 40% opacity. Checked: #9BC5FD fill.
Pressed Yes Yes State=Pressed Unchecked: #EBF2FF bg. Checked: #0F57C8.
Focused Yes Yes State=Focused Blue #1972F9 border stroke.
Error Yes Yes State=Error Red border / red #D81E1E fill.
Issues
  • isSelected=Yes/No renamed to isSelected=true/false in Figma — now maps correctly to Swift Bool and Kotlin Boolean C2 Fixed
  • Checkmark rebuilt as a separable icon-check child layer inside each checked container — engineers can now tint, swap, and reference it in code C6 Fixed
  • Added 27 new variants — State (Pressed/Focused/Disabled/Error) × isSelected (true/false) × Size, plus isSelected=indeterminate per size with icon-indeterminate dash layer. 6 → 33 total variants C5 Fixed
Recommendations
  • CheckboxItem compound component created. Composes Checkbox + Label (Proxima Soft Bold) + Description (BarkAda Medium). 4 variants: isSelected (true/false) × Size (Small 14px label / Medium 18px label). Node: 17734:161220. Created Docs

Component Playground

Layout

Typography

Colors

Installation Planned API

iOS — Swift Package Manager

.package(url: "https://github.com/AY-Org/eb-ds-ios", from: "1.0.0")

Android — Gradle (Kotlin DSL)

implementation("com.eastblue.ds:checkbox:1.0.0")

Import

import EastBlueDS
import com.eastblue.ds.checkbox.*
Property Mapping
Figma PropertySwiftUICompose
State — Default, Pressed, Focused, Disabled, Error Disabled .disabled(true) · Focused .focused() · Error .ebError(true) · Pressed — Disabled enabled = false · Pressed, Focused interactionSource · Error isError = true
isSelected — false, true, indeterminate isOn: Binding<Bool> · indeterminate toggleIndeterminate checked: Boolean · indeterminate TriStateCheckbox
Size — Small, Medium, Large .controlSize() size = EBCheckboxSize.*
SwiftUI
ios/Components/Checkbox/EBCheckbox.swift
Jetpack Compose
android/components/checkbox/EBCheckbox.kt
Usage Snippets Planned API
Unchecked
// Unchecked (default state)
EBCheckbox(isOn: $isSelected)
    .controlSize(.regular)

// Small size
EBCheckbox(isOn: $isSelected)
    .controlSize(.mini)
// Unchecked (default state)
EBCheckbox(
    checked = false,
    onCheckedChange = { isSelected = it },
    size = EBCheckboxSize.Medium
)

// Small size
EBCheckbox(
    checked = false,
    onCheckedChange = { isSelected = it },
    size = EBCheckboxSize.Small
)
Checked
// Checked (selected state)
EBCheckbox(isOn: .constant(true))
    .controlSize(.regular)

// Bound to state
@State private var isChecked = true
EBCheckbox(isOn: $isChecked)
    .controlSize(.large)
// Checked (selected state)
EBCheckbox(
    checked = true,
    onCheckedChange = { isSelected = it },
    size = EBCheckboxSize.Medium
)

// Bound to state
var isChecked by remember { mutableStateOf(true) }
EBCheckbox(
    checked = isChecked,
    onCheckedChange = { isChecked = it }
)
Indeterminate
// Indeterminate (partial selection)
EBCheckbox(isOn: $isSelected)
    .controlSize(.regular)
    .toggleIndeterminate(true)
// Indeterminate (partial selection)
TriStateCheckbox(
    state = ToggleableState.Indeterminate,
    onClick = { /* cycle state */ },
    modifier = Modifier.size(EBCheckboxSize.Medium)
)
Disabled
// Disabled unchecked
EBCheckbox(isOn: $isSelected)
    .controlSize(.regular)
    .disabled(true)

// Disabled checked
EBCheckbox(isOn: .constant(true))
    .controlSize(.regular)
    .disabled(true)
// Disabled unchecked
EBCheckbox(
    checked = false,
    onCheckedChange = {},
    enabled = false,
    size = EBCheckboxSize.Medium
)

// Disabled checked
EBCheckbox(
    checked = true,
    onCheckedChange = {},
    enabled = false,
    size = EBCheckboxSize.Medium
)
Error
// Error state (form validation)
EBCheckbox(isOn: $isSelected)
    .controlSize(.regular)
    .ebError(true)
// Error state (form validation)
EBCheckbox(
    checked = false,
    onCheckedChange = { isSelected = it },
    isError = true,
    size = EBCheckboxSize.Medium
)
Accessibility
RequirementiOSAndroid
Minimum touch target 44 x 44 pt 48 x 48 dp
Accessibility label .accessibilityLabel("Accept terms") semantics { contentDescription = "Accept terms" }
Checked state announcement VoiceOver reads "checked" / "unchecked" automatically via Toggle TalkBack reads state automatically via Checkbox semantics
Indeterminate toggleIndeterminate reads "mixed" TriStateCheckbox reads "partially checked"
Usage Guidelines

Do

Use it when people can select several options, or none.

Don't

Don’t use it for a single on/off setting that applies right away — use Toggle.

Do

Use indeterminate on a “select all” box when only some of the items below it are selected.

Don't

Don’t use indeterminate as a third answer for a single option.

Do

Pair the box with a label — use Checkbox Item for a labelled row.

Don't

Don’t place a bare box beside loose text.

Do

Give the Small (16px) box a touch area of at least 44pt / 48dp.

Don't

Don’t shrink the tap area down to the box.

Criteria Scorecard
ID Criterion Status Notes
C1 Layer Structure & Naming Ready Root frame named container. Simple, semantic hierarchy. No generic layer names.
C2 Variant & Property Naming Ready isSelected now uses true/false — corrected in Figma. Maps directly to Swift Bool / Kotlin Boolean. indeterminate property is a C5 concern (missing state variant).
C3 Token Coverage Ready All states have defined color values. Default, Pressed, Disabled, Error, Focused, and Indeterminate containers use distinct fills/strokes. Separable icon-check and icon-indeterminate layers present.
C4 Native Mappability Ready Maps to Toggle(.checkbox) / Checkbox. Indeterminate maps to TriStateCheckbox. Label pairing via CheckboxItem compound component.
C5 Interaction State Coverage Ready All 5 interaction states defined (Default, Pressed, Focused, Disabled, Error) × isSelected (true/false) × 3 sizes. Indeterminate added as isSelected=indeterminate with icon-indeterminate dash layer. 33 total variants.
C6 Asset & Icon Quality Ready Checkmark rebuilt as a separable icon-check child vector layer inside each checked container. Can be tinted via selected/icon-check token and swapped natively.
Variants Inventory (33 total)

5 State × 3 isSelected × 3 Size = 45 theoretical. isSelected=indeterminate only ships State=Default, so actual count is (5 × 2 × 3) + (1 × 1 × 3) = 33 variants.

isSelectedStatesSizesCount
falseDefault, Pressed, Focused, Disabled, ErrorSmall, Medium, Large15
trueDefault, Pressed, Focused, Disabled, ErrorSmall, Medium, Large15
indeterminateDefault onlySmall, Medium, Large3
View full State × isSelected × Size breakdown (33 rows)
StateisSelectedSizeNode
DefaultfalseSmall17143:2465
DefaulttrueSmall17143:2468
DefaultfalseMedium17143:2471
DefaulttrueMedium17143:2473
DefaultfalseLarge17143:2476
DefaulttrueLarge17143:2478
PressedfalseSmall17733:968
FocusedfalseSmall17733:971
DisabledfalseSmall17733:974
ErrorfalseSmall17733:977
PressedtrueSmall17733:980
FocusedtrueSmall17733:984
DisabledtrueSmall17733:988
ErrortrueSmall17733:992
PressedfalseMedium17733:996
FocusedfalseMedium17733:998
DisabledfalseMedium17733:1000
ErrorfalseMedium17733:1002
PressedtrueMedium17733:1004
FocusedtrueMedium17733:1008
DisabledtrueMedium17733:1012
ErrortrueMedium17733:1016
PressedfalseLarge17733:1020
FocusedfalseLarge17733:1022
DisabledfalseLarge17733:1024
ErrorfalseLarge17733:1026
PressedtrueLarge17733:1028
FocusedtrueLarge17733:1032
DisabledtrueLarge17733:1036
ErrortrueLarge17733:1040
DefaultindeterminateSmall17733:1044
DefaultindeterminateMedium17733:1048
DefaultindeterminateLarge17733:1052
1.5.0 — March 2026Minor
Compound Component + Cleanup · node 17734:161220
CheckboxItem compound component created — 4 variants: isSelected (true/false) × Size (Small/Medium). Each contains a real Checkbox instance + Label (Proxima Soft Bold, 14px/18px) + Description (BarkAda Medium, 12px). Wraps atomic Checkbox with label pairing for accessible form use. Created
New Component
Variant property order reordered — Naming changed from isSelected=X, Size=Y, State=Z to State=X, isSelected=Y, Size=Z. State is now the first property axis in the component set. Section renamed from "Claude Testing" to "Checkbox". Updated
Cleanup
1.4.0 — March 2026Minor
C5 Fix · node 17143:2464
All interaction states added — Added 27 new variants covering State (Pressed/Focused/Disabled/Error) × isSelected (true/false) × Size (Small/Medium/Large). Variants 6 → 33. Colors: Pressed uses light blue fill + blue border (unchecked) / #0F57C8 (checked); Focused uses blue border; Disabled uses 40% opacity; Error uses red border / #D81E1E fill. Fixed
C5 Resolved
Indeterminate state added — Added isSelected=indeterminate variants for Small, Medium, and Large. Each contains a blue container frame with a named icon-indeterminate horizontal dash child layer. Maps to ToggleableState.Indeterminate (Android) and toggleIndeterminate (iOS). Fixed
C5 Indeterminate
1.3.0 — March 2026Minor
C6 Fix · node 17143:2464
Checkmark rebuilt as separable vector layer — Deleted the flattened boolean-op containers from all 3 isSelected=true variants. Created clean blue container frames (4px radius) with a named icon-check child vector inside each. Engineers can now tint via selected/icon-check token and map to a native icon slot. Nodes: 17721:962 (Small), 17721:963 (Medium), 17721:964 (Large). Fixed
C6 Resolved
1.2.0 — March 2026Minor
C2 Fix · node 17143:2464
Boolean property renamed in Figma — All 6 variants renamed from isSelected=Yes/No to isSelected=true/false. Now maps directly to Swift Bool and Kotlin Boolean for Code Connect. C2 criterion resolved. Fixed
C2 Resolved
1.1.0 — March 2026Minor
Assessment Rebuild · node 17143:2464
Full 4-tab assessment built — Overview, Style, Code, and Changelog tabs. Interactive live preview with size and state controls. Spec cards for Unchecked and Checked appearances. Full criteria scorecard and Code Connect readiness table. Updated
Documentation
Property name corrected — Existing assessment incorrectly referenced isChecked. Figma metadata confirms the property is isSelected. All documentation updated. Fixed
C2 Note
1.0.0 — March 2026Major
Initial Assessment · node 17143:2464
Component assessed — 6 variants documented across isSelected (Yes/No) x Size (Small 16px / Medium 20px / Large 24px). Token audit found 7 variables defined. Documented
Initial
Flattened checkmark icon — Checked containers had no child layers. The white checkmark was a boolean operation baked into the container frame. Cannot be extracted, tinted, or swapped as a component instance. Hard C6 blocker. Fixed in v1.3.0
C6 Resolved
Missing interaction states — Only checked/unchecked defined. No disabled, pressed, focused, indeterminate, or error state variants. Checkboxes require all of these for production form use. Fixed in v1.4.0
C5 Resolved
Boolean property uses Yes/No — isSelected=Yes/No instead of true/false. Incompatible with Swift Bool and Kotlin Boolean for Code Connect mapping. Fixed in v1.2.0
C2 Resolved
Code Connect mappings — Usage descriptions attached per variant. Was blocked by C2 and C6 (both resolved). Pending C5 (missing states) before complete CLI mapping. No CLI mappings registered yet. Open
C7 Open