{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "checkbox",
  "title": "Checkbox",
  "description": "Form-associated checkbox for independent choices, acknowledgment, or consent, with optional supporting description, checked, unchecked, mixed, and four density states.",
  "type": "registry:ui",
  "meta": {
    "library": "@ds-mo/ui",
    "distribution": "npm",
    "storybook": "https://zainadeel.github.io/compomo/?path=/story/checkbox",
    "source": "src/wc/components/Checkbox/Checkbox.tsx",
    "intentStatus": "complete",
    "intent": {
      "audience": "general",
      "status": "stable",
      "summary": "Form-associated checkbox for independent choices, acknowledgment, or consent, with optional supporting description, checked, unchecked, mixed, and four density states.",
      "useWhen": [
        "A user may independently select zero or more choices.",
        "A form requires acknowledgment, consent, or an opt-in value before submission.",
        "A composite multi-select option needs a presentation-only checkbox indicator."
      ],
      "avoidWhen": [
        "Exactly one option must be chosen from a mutually exclusive set.",
        "A binary setting takes effect immediately rather than being submitted or confirmed.",
        "The control triggers a one-time command instead of maintaining selection state."
      ],
      "alternatives": [
        {
          "when": "Exactly one option must be chosen from a mutually exclusive set.",
          "component": "component:ds-radio",
          "reason": "Radio communicates one-of-many selection."
        },
        {
          "when": "A binary setting takes effect immediately.",
          "component": "component:ds-switch",
          "reason": "Switch communicates an immediately applied on/off setting."
        },
        {
          "when": "The interaction triggers a one-time command.",
          "component": "component:ds-button-filled",
          "reason": "Button semantics communicate an action rather than persistent selection."
        }
      ],
      "commonlyComposedWith": [
        "component:ds-field",
        "component:ds-select",
        "component:ds-text"
      ],
      "accessibility": [
        "Every interactive checkbox requires a visible label that provides its accessible name; an optional visible description is associated as supporting context.",
        "Enter and Space activate the checkbox; checked and mixed state are exposed through aria-checked.",
        "Disabled and inactive checkboxes leave the tab order and are omitted from form submission.",
        "Use presentation mode only inside a composite option that owns selection semantics, focus, and interaction."
      ],
      "states": [
        "Unchecked boxes use a tertiary-foreground inset stroke: 1.5px at lg, 1.25px at md, 1px at sm, and 0.75px at xs. Selected and mixed boxes remove the border, use a brand fill, and draw a component-owned filled check or subtract outline that scales with the box.",
        "Activating an indeterminate checkbox clears the mixed state, toggles checked, and emits dsChange with the resulting boolean.",
        "The initial checked and indeterminate values are restored by native form reset; checked values submit under name and unchecked values submit nothing.",
        "Sizes are lg with a 20px box in a 24px placement, md with a 16px box in a 20px placement, sm with a 12px box in a 16px placement, and xs with an 8px box in a 12px placement.",
        "Presentation mode removes checkbox semantics, focus, interaction, label rendering, description rendering, and form submission while preserving the visual state.",
        "Description-rich checkboxes grow beyond the fixed density height while retaining its minimum target size and primitive-owned selection anatomy."
      ],
      "responsiveBehavior": [
        "Choose size from the density of the containing row; labels and descriptions may wrap while the placement box stays fixed.",
        "Use the same density as the shared option icon zone in multi-select rows."
      ],
      "frameworkCaveats": {
        "customElements": [
          "Bind checked and indeterminate as properties for application state updates and listen for dsChange.",
          "Use the form attribute on the host when associating a checkbox rendered outside its owning form or isolating it from an ancestor form."
        ],
        "react": [
          "Use DsCheckbox and handle onDsChange; checked and indeterminate are mutable and update after user activation."
        ],
        "vue": [
          "Use DsCheckbox with v-model for checked, bind indeterminate as a property, and listen for dsChange."
        ],
        "angular": [
          "Use DsCheckbox with checked binding and dsChange, or the generated boolean value accessor in Angular forms."
        ]
      },
      "references": [
        {
          "label": "Storybook examples",
          "path": "src/wc/components/Checkbox/Checkbox.stories.ts"
        },
        {
          "label": "Cross-browser form and accessibility coverage",
          "path": "tests/e2e/forms.spec.ts"
        }
      ]
    },
    "api": {
      "props": {
        "checked": {
          "type": "boolean",
          "resolvedType": "boolean",
          "attribute": "checked",
          "default": "false",
          "required": false,
          "mutable": true,
          "description": "Current checked state."
        },
        "description": {
          "type": "string",
          "resolvedType": "string | undefined",
          "attribute": "description",
          "required": false,
          "mutable": false,
          "description": "Optional supporting description associated with the checkbox."
        },
        "disabled": {
          "type": "boolean",
          "resolvedType": "boolean",
          "attribute": "disabled",
          "default": "false",
          "required": false,
          "mutable": false,
          "description": "Native disabled state."
        },
        "indeterminate": {
          "type": "boolean",
          "resolvedType": "boolean",
          "attribute": "indeterminate",
          "default": "false",
          "required": false,
          "mutable": true,
          "description": "Mixed visual state. Activation clears it before toggling checked."
        },
        "isInactive": {
          "type": "boolean",
          "resolvedType": "boolean",
          "attribute": "is-inactive",
          "default": "false",
          "required": false,
          "mutable": false,
          "description": "Design-system inactive state."
        },
        "label": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "label",
          "required": true,
          "mutable": false,
          "description": "Visible label and accessible name. Omitted only in presentation mode."
        },
        "name": {
          "type": "string | undefined",
          "resolvedType": "string | undefined",
          "attribute": "name",
          "required": false,
          "mutable": false,
          "description": "Native form field name."
        },
        "presentation": {
          "type": "boolean",
          "resolvedType": "boolean",
          "attribute": "presentation",
          "default": "false",
          "required": false,
          "mutable": false,
          "description": "Visual-only indicator for a composite control that owns selection semantics."
        },
        "required": {
          "type": "boolean",
          "resolvedType": "boolean",
          "attribute": "required",
          "default": "false",
          "required": false,
          "mutable": false,
          "description": "Require the checkbox to be checked for form validity."
        },
        "requiredMessage": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "required-message",
          "default": "'This field is required.'",
          "required": false,
          "mutable": false,
          "description": "Validation message used when a required checkbox is unchecked."
        },
        "size": {
          "type": "CheckboxSize",
          "resolvedType": "\"lg\" | \"md\" | \"sm\" | \"xs\"",
          "attribute": "size",
          "default": "'md'",
          "required": false,
          "mutable": false,
          "description": "Visual and placement density."
        },
        "value": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "value",
          "default": "'on'",
          "required": false,
          "mutable": false,
          "description": "Submitted value when checked."
        }
      },
      "events": [
        {
          "name": "dsChange",
          "detail": "boolean",
          "bubbles": true,
          "cancelable": true,
          "composed": true,
          "description": "Emitted after user activation with the new checked state."
        }
      ],
      "methods": [],
      "slots": []
    },
    "props": {
      "checked": {
        "type": "boolean",
        "resolvedType": "boolean",
        "attribute": "checked",
        "default": "false",
        "required": false,
        "mutable": true,
        "description": "Current checked state."
      },
      "description": {
        "type": "string",
        "resolvedType": "string | undefined",
        "attribute": "description",
        "required": false,
        "mutable": false,
        "description": "Optional supporting description associated with the checkbox."
      },
      "disabled": {
        "type": "boolean",
        "resolvedType": "boolean",
        "attribute": "disabled",
        "default": "false",
        "required": false,
        "mutable": false,
        "description": "Native disabled state."
      },
      "indeterminate": {
        "type": "boolean",
        "resolvedType": "boolean",
        "attribute": "indeterminate",
        "default": "false",
        "required": false,
        "mutable": true,
        "description": "Mixed visual state. Activation clears it before toggling checked."
      },
      "isInactive": {
        "type": "boolean",
        "resolvedType": "boolean",
        "attribute": "is-inactive",
        "default": "false",
        "required": false,
        "mutable": false,
        "description": "Design-system inactive state."
      },
      "label": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "label",
        "required": true,
        "mutable": false,
        "description": "Visible label and accessible name. Omitted only in presentation mode."
      },
      "name": {
        "type": "string | undefined",
        "resolvedType": "string | undefined",
        "attribute": "name",
        "required": false,
        "mutable": false,
        "description": "Native form field name."
      },
      "presentation": {
        "type": "boolean",
        "resolvedType": "boolean",
        "attribute": "presentation",
        "default": "false",
        "required": false,
        "mutable": false,
        "description": "Visual-only indicator for a composite control that owns selection semantics."
      },
      "required": {
        "type": "boolean",
        "resolvedType": "boolean",
        "attribute": "required",
        "default": "false",
        "required": false,
        "mutable": false,
        "description": "Require the checkbox to be checked for form validity."
      },
      "requiredMessage": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "required-message",
        "default": "'This field is required.'",
        "required": false,
        "mutable": false,
        "description": "Validation message used when a required checkbox is unchecked."
      },
      "size": {
        "type": "CheckboxSize",
        "resolvedType": "\"lg\" | \"md\" | \"sm\" | \"xs\"",
        "attribute": "size",
        "default": "'md'",
        "required": false,
        "mutable": false,
        "description": "Visual and placement density."
      },
      "value": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "value",
        "default": "'on'",
        "required": false,
        "mutable": false,
        "description": "Submitted value when checked."
      }
    },
    "events": [
      {
        "name": "dsChange",
        "detail": "boolean",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "description": "Emitted after user activation with the new checked state."
      }
    ],
    "methods": [],
    "slots": [],
    "exports": {
      "customElement": "ds-checkbox",
      "react": "DsCheckbox",
      "vue": "DsCheckbox",
      "angular": "DsCheckbox"
    },
    "consumption": {
      "install": "npm install @ds-mo/ui @ds-mo/tokens @ds-mo/icons",
      "cssSetup": "import '@ds-mo/tokens';\nimport '@ds-mo/tokens/reset';\nimport '@ds-mo/tokens/globals';",
      "customElements": {
        "import": "import '@ds-mo/ui/dist/components/ds-checkbox.js';",
        "example": "<ds-checkbox></ds-checkbox>"
      },
      "react": {
        "import": "import { DsCheckbox } from '@ds-mo/ui/react';",
        "example": "<DsCheckbox />"
      },
      "vue": {
        "import": "import { DsCheckbox } from '@ds-mo/ui/vue';",
        "example": "<DsCheckbox />"
      },
      "angular": {
        "import": "import { DsCheckbox } from '@ds-mo/ui/angular/ds-checkbox';",
        "example": "<ds-checkbox></ds-checkbox>"
      },
      "peerDependencies": {
        "required": [
          "@ds-mo/tokens ^6.5.0",
          "@ds-mo/icons ^7.0.0"
        ],
        "frameworks": "Custom Elements; React 18/19 wrappers; Vue 3 wrappers; Angular 19-22 standalone adapters."
      }
    }
  },
  "dependencies": [
    "@ds-mo/ui",
    "@ds-mo/tokens"
  ],
  "registryDependencies": [
    "text"
  ],
  "files": [
    {
      "path": "src/wc/components/Checkbox/Checkbox.css",
      "content": "@import '../../utils/control-inactive.css';\n@import '../../utils/control-density.css';\n@import '../../utils/focus-ring.css';\n@import '../../utils/interaction-fill.css';\n@import '../../utils/forced-colors.css';\n\n:host {\n  display: inline-flex;\n  align-items: center;\n  box-sizing: border-box;\n  gap: var(--ds-control-gap);\n  height: var(--ds-control-height);\n  padding: 0 var(--ds-control-padding-inline);\n  border-radius: var(--ds-control-radius);\n  cursor: default;\n  user-select: none;\n}\n\n:host(.checkbox--described) {\n  height: auto;\n  min-height: var(--ds-control-height);\n  padding-block: var(--dimension-space-075);\n}\n\n:host(.checkbox--presentation) {\n  width: var(--ds-control-icon);\n  height: var(--ds-control-icon);\n  padding: 0;\n  gap: 0;\n  pointer-events: none;\n}\n\n/* Inactive: `.ds-control-inactive` (50% opacity). */\n\n:host(.checkbox--lg) {\n  --_checkbox-box: var(--dimension-iconography-md);\n  --_checkbox-stroke: var(--dimension-stroke-width-018);\n}\n\n:host(.checkbox--md) {\n  --_checkbox-box: var(--dimension-iconography-sm);\n  --_checkbox-stroke: var(--dimension-stroke-width-015);\n}\n\n:host(.checkbox--sm) {\n  --_checkbox-box: var(--dimension-iconography-xs);\n  --_checkbox-stroke: var(--dimension-stroke-width-012);\n}\n\n:host(.checkbox--xs) {\n  --_checkbox-box: var(--dimension-size-100);\n  --_checkbox-stroke: calc(var(--dimension-stroke-width-base) * 3 / 32);\n}\n\n.checkbox__placement {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  flex-shrink: 0;\n  width: var(--ds-control-icon);\n  height: var(--ds-control-icon);\n}\n\n.box {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  box-sizing: border-box;\n  width: var(--_checkbox-box);\n  height: var(--_checkbox-box);\n  border: 0;\n  border-radius: var(--dimension-radius-025);\n  box-shadow: inset 0 0 0 var(--_checkbox-stroke) var(--color-foreground-tertiary);\n  transition:\n    background-color var(--effect-motion-short-2),\n    box-shadow var(--effect-motion-short-2);\n}\n\n.box--marked {\n  color: var(--color-foreground-on-bold-background-primary);\n  background-color: var(--color-background-bold-brand);\n  box-shadow: none;\n}\n\n.checkbox__mark {\n  width: 100%;\n  height: 100%;\n  flex-shrink: 0;\n  fill: currentColor;\n}\n\n.checkbox__copy {\n  display: grid;\n  flex: 1;\n  gap: var(--dimension-space-025);\n  min-width: 0;\n  padding: 0 var(--ds-control-label-inset);\n}\n\n@media (forced-colors: active) {\n  .box {\n    border: var(--_checkbox-stroke) solid var(--ds-forced-color-content);\n    box-shadow: none;\n  }\n\n  .box--marked {\n    color: var(--ds-forced-color-on-selected);\n    background-color: var(--ds-forced-color-selected);\n    border-color: var(--ds-forced-color-selected);\n  }\n}\n",
      "type": "registry:ui"
    },
    {
      "path": "src/wc/components/Checkbox/Checkbox.tsx",
      "content": "import { AttachInternals, Component, Prop, State, Event, EventEmitter, Watch, h, Host } from '@stencil/core';\nimport {\n  CONTROL_SUPPORTING_TEXT_VARIANT,\n  CONTROL_TEXT_VARIANT,\n  DEFAULT_REQUIRED_MESSAGE,\n  setFormControlValue,\n  setRequiredValidity,\n} from '../../utils';\n\nexport type CheckboxSize = 'lg' | 'md' | 'sm' | 'xs';\n\nlet idCounter = 0;\n\n@Component({\n  tag: 'ds-checkbox',\n  styleUrl: 'Checkbox.css',\n  scoped: true,\n  formAssociated: true,\n})\nexport class Checkbox {\n  @AttachInternals() internals!: ElementInternals;\n  private labelId = `ds-checkbox-label-${++idCounter}`;\n  private descriptionId = `${this.labelId}-description`;\n\n  /** Visible label and accessible name. Omitted only in presentation mode. */\n  @Prop() label!: string;\n  /** Optional supporting description associated with the checkbox. */\n  @Prop() description?: string;\n  /** Current checked state. */\n  @Prop({ mutable: true }) checked: boolean = false;\n  /** Visual and placement density. */\n  @Prop() size: CheckboxSize = 'md';\n  /** Native form field name. */\n  @Prop({ reflect: true }) name: string | undefined;\n  /** Submitted value when checked. */\n  @Prop() value: string = 'on';\n  /** Native disabled state. */\n  @Prop({ reflect: true }) disabled: boolean = false;\n  /** Require the checkbox to be checked for form validity. */\n  @Prop({ reflect: true }) required: boolean = false;\n  /** Validation message used when a required checkbox is unchecked. */\n  @Prop() requiredMessage: string = DEFAULT_REQUIRED_MESSAGE;\n  /** Mixed visual state. Activation clears it before toggling checked. */\n  @Prop({ mutable: true }) indeterminate: boolean = false;\n  /** Design-system inactive state. */\n  @Prop() isInactive: boolean = false;\n  /** Visual-only indicator for a composite control that owns selection semantics. */\n  @Prop() presentation: boolean = false;\n\n  /** Emitted after user activation with the new checked state. */\n  @Event() dsChange!: EventEmitter<boolean>;\n\n  private initialChecked = false;\n  private initialIndeterminate = false;\n  @State() private formDisabled = false;\n\n  componentWillLoad() {\n    this.initialChecked = this.checked;\n    this.initialIndeterminate = this.indeterminate;\n    this.syncFormValue();\n  }\n\n  @Watch('checked')\n  @Watch('value')\n  @Watch('disabled')\n  @Watch('isInactive')\n  @Watch('required')\n  @Watch('presentation')\n  syncFormValue() {\n    const inactive = this.isInactive || this.disabled || this.formDisabled || this.presentation;\n    setFormControlValue(this.internals, this.checked ? this.value : null, { inactive });\n    const missing = this.required && !inactive && !this.checked;\n    setRequiredValidity(this.internals, missing, this.requiredMessage);\n  }\n\n  formDisabledCallback(disabled: boolean) {\n    this.formDisabled = disabled;\n    this.syncFormValue();\n  }\n\n  formResetCallback() {\n    this.checked = this.initialChecked;\n    this.indeterminate = this.initialIndeterminate;\n  }\n\n  private handleActivate = () => {\n    if (this.isInactive || this.disabled || this.formDisabled || this.presentation) return;\n    if (this.indeterminate) this.indeterminate = false;\n    this.checked = !this.checked;\n    this.dsChange.emit(this.checked);\n  };\n\n  private handleKeyDown = (e: KeyboardEvent) => {\n    if (e.key === 'Enter' || e.key === ' ') {\n      e.preventDefault();\n      this.handleActivate();\n    }\n  };\n\n  render() {\n    const inactive = this.isInactive || this.disabled || this.formDisabled;\n    const isMarked = this.checked || this.indeterminate;\n    const invalid = this.required && !inactive && !this.checked;\n\n    return (\n      <Host\n        role={this.presentation ? undefined : 'checkbox'}\n        aria-checked={this.presentation ? undefined : this.indeterminate ? 'mixed' : String(this.checked)}\n        aria-disabled={!this.presentation && inactive ? 'true' : undefined}\n        aria-required={!this.presentation && this.required ? 'true' : undefined}\n        aria-invalid={!this.presentation && invalid ? 'true' : undefined}\n        aria-labelledby={this.presentation ? undefined : this.labelId}\n        aria-describedby={\n          !this.presentation && this.description ? this.descriptionId : undefined\n        }\n        aria-hidden={this.presentation ? 'true' : undefined}\n        tabIndex={this.presentation || inactive ? -1 : 0}\n        class={{\n          checkbox: true,\n          'checkbox--presentation': this.presentation,\n          'checkbox--described': Boolean(this.description),\n          [`checkbox--${this.size}`]: true,\n          [`ds-control--${this.size}`]: true,\n          'ds-control-inactive': inactive && !this.presentation,\n          'ds-focus-ring-inset': !this.presentation,\n          'ds-interaction-fill': !inactive && !this.presentation,\n        }}\n        onClick={this.presentation ? undefined : this.handleActivate}\n        onKeyDown={this.presentation ? undefined : this.handleKeyDown}\n      >\n        <span class=\"checkbox__placement ds-interaction-fill__content\" aria-hidden=\"true\">\n          <span class={{ box: true, 'box--marked': isMarked }}>\n            {isMarked && (\n              // eslint-disable-next-line local/prefer-ds-icon -- Checkbox owns this fixed state-mark geometry.\n              <svg\n                class=\"checkbox__mark\"\n                viewBox=\"0 0 16 16\"\n                fill=\"currentColor\"\n                focusable=\"false\"\n              >\n                <path\n                  d={\n                    this.indeterminate\n                      ? 'M12 7.375V8.625H4V7.375H12Z'\n                      : 'M12.9756 4.65527L7.22559 11.4053C7.11258 11.5379 6.94946 11.6169 6.77539 11.624C6.60111 11.631 6.43095 11.5657 6.30762 11.4424L3.05762 8.19238L3.94238 7.30762L6.71289 10.0781L12.0244 3.84473L12.9756 4.65527Z'\n                  }\n                />\n              </svg>\n            )}\n          </span>\n        </span>\n        {!this.presentation && (\n          <span class=\"checkbox__copy ds-interaction-fill__content\">\n            <ds-text\n              class=\"checkbox__label\"\n              as=\"span\"\n              variant={CONTROL_TEXT_VARIANT[this.size]}\n              textId={this.labelId}\n            >\n              {this.label}\n            </ds-text>\n            {this.description ? (\n              <ds-text\n                as=\"span\"\n                variant={CONTROL_SUPPORTING_TEXT_VARIANT[this.size]}\n                color=\"secondary\"\n                textId={this.descriptionId}\n              >\n                {this.description}\n              </ds-text>\n            ) : null}\n          </span>\n        )}\n      </Host>\n    );\n  }\n}\n",
      "type": "registry:ui"
    }
  ]
}
