Primitives
10

Checkbox

A real <input type="checkbox"> under a custom paint job. The label wraps the input rather than pointing at it, so no id is needed and two on a page cannot collide.

plain markup — no library on the page
rendered by aura-react
rendered by aura-vue
rendered by aura-svelte
built from aura-angular's own class helpers

Code

index.html
<div class="aura-stack" style="--aura-dir:column;--aura-gap:var(--space-3)">
  <label class="aura-check">
    <input type="checkbox" class="aura-checkbox" />
    <span>Run all tests</span>
  </label>
  <div style="padding-inline-start: var(--space-5)">
    <div class="aura-stack" style="--aura-dir:column;--aura-gap:var(--space-3)">
      <label class="aura-check">
        <input type="checkbox" class="aura-checkbox" checked />
        <span>Unit</span>
      </label>
      <label class="aura-check">
        <input type="checkbox" class="aura-checkbox" />
        <span>Integration</span>
      </label>
      <label class="aura-check">
        <input type="checkbox" class="aura-checkbox" />
        <span>Browser</span>
      </label>
    </div>
  </div>
  <label class="aura-check">
    <input type="checkbox" class="aura-checkbox" checked disabled />
    <span>Locked by policy</span>
  </label>
</div>
Demo.tsx
import { useState } from 'react';
import { Checkbox, Stack } from '@ilomee/aura-react';

const TESTS = ['Unit', 'Integration', 'Browser'];

/**
 * Indeterminate is the "some, but not all" state, and it only means anything against a set —
 * so the demo is a set. The parent holds no value of its own: it reads the children, showing a
 * tick when every one is checked, the bar when only some are, and nothing when none are. A
 * click commits whichever way it is not already.
 *
 * Shown this way because a lone indeterminate checkbox cannot demonstrate itself. The state has
 * no HTML attribute — only a DOM property — and a click always clears it, so the bar would
 * disappear on first use and never come back.
 */
export default function Demo() {
  const [checked, setChecked] = useState<string[]>(['Unit']);

  const all = checked.length === TESTS.length;
  const none = checked.length === 0;

  return (
    <Stack gap={3}>
      <Checkbox
        label="Run all tests"
        checked={all}
        indeterminate={!all && !none}
        onCheckedChange={() => setChecked(all ? [] : TESTS)}
      />
      {/* A plain div carries the indent so the nesting is visible; the four packages merge a
          caller's `style` into a layout component in their own order, and this keeps the markup
          identical across all of them for the parity diff. */}
      <div style={{ paddingInlineStart: 'var(--space-5)' }}>
        <Stack gap={3}>
          {TESTS.map((name) => (
            <Checkbox
              key={name}
              label={name}
              checked={checked.includes(name)}
              onCheckedChange={(on) =>
                setChecked((prev) => (on ? [...prev, name] : prev.filter((x) => x !== name)))
              }
            />
          ))}
        </Stack>
      </div>
      <Checkbox label="Locked by policy" defaultChecked disabled />
    </Stack>
  );
}

A real native input under a custom paint job: it submits with a form, pairs with its label, and already carries its keyboard and screen-reader behaviour. (Switch is the deliberate exception — a <button role="switch">, which is why it does not take part in form submission.)

Demo.vue
<script setup lang="ts">
import { ref } from 'vue';
import { Checkbox } from '@ilomee/aura-vue';

const ok = ref(true);
</script>

<template>
  <Checkbox v-model="ok" label="Ship on Friday" />
</template>

A real native input under a custom paint job: it submits with a form, pairs with its label, and already carries its keyboard and screen-reader behaviour. (Switch is the deliberate exception — a <button role="switch">, which is why it does not take part in form submission.)

Demo.svelte
<script lang="ts">
  import { Checkbox } from '@ilomee/aura-svelte';

  let ok = $state(true);
</script>

<Checkbox bind:checked={ok} label="Ship on Friday" />

A real native input under a custom paint job: it submits with a form, pairs with its label, and already carries its keyboard and screen-reader behaviour. (Switch is the deliberate exception — a <button role="switch">, which is why it does not take part in form submission.)

Used as aura-checkbox.

demo.component.ts
import { AuraCheckbox } from '@ilomee/aura-angular';

@Component({
  standalone: true,
  imports: [AuraCheckbox],
  template: `<aura-checkbox label="Ship on Friday" [(checked)]="ok" />`,
})
export class DemoComponent {
  ok = true;
}

A real native input under a custom paint job: it submits with a form, pairs with its label, and already carries its keyboard and screen-reader behaviour. (Switch is the deliberate exception — a <button role="switch">, which is why it does not take part in form submission.)

Props

Plain markup has no props — the classes below are the whole API. The four packages do nothing more than set these same classes for you.
NameTypeDefaultNotes
labelstringRenders the wrapping row.
checkedbooleanControlled value.
defaultCheckedbooleanfalse
indeterminatebooleanfalseThere is no indeterminate HTML attribute — it exists only as a DOM property, so every package sets it imperatively after render.
onCheckedChange(checked: boolean) => void
disabledboolean
NameTypeDefaultNotes
labelstring
modelValuetwo-waybooleanUse with v-model.
defaultCheckedbooleanfalse
indeterminatebooleanfalseThere is no indeterminate HTML attribute — it exists only as a DOM property, so every package sets it imperatively after render.
disabledbooleanfalse
update:modelValueevent(checked: boolean) => void
NameTypeDefaultNotes
labelstring
checkedtwo-waybooleanfalse$bindable — use bind:checked.
indeterminatebooleanfalseThere is no indeterminate HTML attribute — it exists only as a DOM property, so every package sets it imperatively after render.
disabledbooleanfalse
onchange(checked: boolean) => void
NameTypeDefaultNotes
labelstring
checkedbooleanfalse
indeterminatebooleanfalseThere is no indeterminate HTML attribute — it exists only as a DOM property, so every package sets it imperatively after render.
disabledbooleanfalse
checkedChangeeventEventEmitter<boolean>

Emitted classes

Every framework emits the same classes — that is what makes the four libraries look identical. You can use them directly, without any component library.

ClassRoleNotes
.aura-checkboxbaseRequired. A modifier does nothing without it.
.aura-checkbaseRequired. A modifier does nothing without it.

Tokens and rules

components.css
box
var(--checkbox-size) · var(--checkbox-radius)
unchecked
var(--surface) · var(--field-border)
checked
var(--accent)
tick
clip-path polygon — no icon set needed
focus
var(--focus-ring)