API reference
Headless checkbox is a single directive surface. Attach tngCheckbox to a native <input> element and let the directive normalize checkbox semantics, tri-state ARIA, and styling hooks for you.
tngCheckbox (directive)
Attach to input[tngCheckbox]. The directive itself writes type="checkbox" on the host, so adding type manually is optional.
Directive attachment
html
<input tngCheckbox />
| Input | Type | Default | Notes |
|---|---|---|---|
checked | boolean | '' | string | false | Controls the committed checked state. |
indeterminate | boolean | '' | string | false | Enables mixed mode and resolves aria-checked="mixed". |
disabled | boolean | '' | string | false | Blocks interaction and reflects the native disabled attribute. |
readonly | boolean | '' | string | false | Keeps the checkbox focusable, but user toggles are reverted after the native change event fires. |
required | boolean | '' | string | false | Reflects the native required attribute and emits data-required. |
invalid | boolean | null | '' | 'true' | 'false' | null | Explicit invalid override for styling and ARIA. |
ariaInvalid | boolean | null | '' | 'true' | 'false' | null | Alternative invalid signal when validation is owned outside the checkbox itself. |
ariaDescribedBy | string | null | null | Connects helper, description, or error text by id. |
name, value | string | null | null | Supports native form submission with stable attribute reflection. |
Output attributes
| Attribute | When set | Purpose |
|---|---|---|
type | Always | Forces the host to be a checkbox input. |
aria-checked | Always | Resolves to true, false, or mixed. |
data-state | Always | Unified state selector: checked | unchecked | mixed. |
data-checked, data-unchecked, data-mixed | State specific | Convenient hooks for visuals that target exactly one state. |
data-focused, data-focus-visible | During focus lifecycle | Lets pointer and keyboard focus styling diverge cleanly. |
data-disabled, data-readonly, data-required, data-invalid | When active | Mirrors interaction and validation state on the native input. |
aria-describedby, aria-invalid, aria-readonly | When configured | Reflects assistive state without requiring a wrapper component. |
disabled, required, name, value | When configured | Preserves native form behavior and submission semantics. |
Change handling
The directive does not emit a custom Angular output. Read the next state from the native change event target and persist it in your own signal or store.
If the checkbox is readonly, the native event still fires, but the directive restores the previous checked and mixed values on the same event cycle.
Read native change events
ts
import { Component, signal } from '@angular/core';
import { TngCheckbox } from '@tailng-ui/primitives';
@Component({
selector: 'app-release-flags',
imports: [TngCheckbox],
templateUrl: './release-flags.component.html',
})
export class ReleaseFlagsComponent {
readonly marketingOptIn = signal(false);
onMarketingOptInChange(event: Event): void {
const target = event.target;
if (!(target instanceof HTMLInputElement)) {
return;
}
this.marketingOptIn.set(target.checked);
}
}
<label>
<input tngCheckbox (change)="onMarketingOptInChange($event)" />
<span>Marketing release email</span>
</label>