Checkbox

A control that allows the user to toggle between checked and not checked.

PreviousNext
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
 
import { ZardCheckboxComponent } from '../checkbox.component';
 
@Component({
  selector: 'z-demo-checkbox-default',
  standalone: true,
  imports: [ZardCheckboxComponent, FormsModule],
  template: `
    <span z-checkbox></span>
    <span z-checkbox [(ngModel)]="checked">Default Checked</span>
  `,
})
export class ZardDemoCheckboxDefaultComponent {
  checked = true;
}
 

Installation

1

Run the CLI

Use the CLI to add the component to your project.

npx @ngzard/ui add checkbox
1

Add the component files

Create the component directory structure and add the following files to your project.

checkbox.component.ts
checkbox.component.ts
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, forwardRef, inject, input, output, ViewEncapsulation } from '@angular/core';
import { type ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import type { ClassValue } from 'clsx';
 
import { checkboxLabelVariants, checkboxVariants, type ZardCheckboxVariants } from './checkbox.variants';
import { mergeClasses, transform } from '../../shared/utils/utils';
import { ZardIconComponent } from '../icon/icon.component';
 
type OnTouchedType = () => any;
type OnChangeType = (value: any) => void;
 
@Component({
  selector: 'z-checkbox, [z-checkbox]',
  standalone: true,
  imports: [ZardIconComponent],
  exportAs: 'zCheckbox',
  template: `
    <span
      tabindex="0"
      class="flex items-center gap-2"
      [class]="disabled() ? 'cursor-not-allowed' : 'cursor-pointer'"
      (click)="onCheckboxChange()"
      (keyup)="onKeyboardEvent($event)"
    >
      <main class="flex relative">
        <input #input type="checkbox" [class]="classes()" [checked]="checked" [disabled]="disabled()" (blur)="onCheckboxBlur()" name="checkbox" />
        <z-icon
          zType="check"
          [class]="
            'absolute flex items-center justify-center text-primary-foreground top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none transition-opacity ' +
            (checked ? 'opacity-100' : 'opacity-0')
          "
        />
      </main>
      <label [class]="labelClasses()" for="checkbox">
        <ng-content></ng-content>
      </label>
    </span>
  `,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => ZardCheckboxComponent),
      multi: true,
    },
  ],
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
})
export class ZardCheckboxComponent implements ControlValueAccessor {
  private cdr = inject(ChangeDetectorRef);
 
  readonly checkChange = output<boolean>();
  readonly class = input<ClassValue>('');
  readonly disabled = input(false, { transform });
  readonly zType = input<ZardCheckboxVariants['zType']>('default');
  readonly zSize = input<ZardCheckboxVariants['zSize']>('default');
  readonly zShape = input<ZardCheckboxVariants['zShape']>('default');
  /* eslint-disable-next-line @typescript-eslint/no-empty-function */
  private onChange: OnChangeType = () => {};
  /* eslint-disable-next-line @typescript-eslint/no-empty-function */
  private onTouched: OnTouchedType = () => {};
 
  protected readonly classes = computed(() => mergeClasses(checkboxVariants({ zType: this.zType(), zSize: this.zSize(), zShape: this.zShape() }), this.class()));
  protected readonly labelClasses = computed(() => mergeClasses(checkboxLabelVariants({ zSize: this.zSize() })));
  checked = false;
 
  writeValue(val: boolean): void {
    this.checked = val;
    this.cdr.markForCheck();
  }
 
  registerOnChange(fn: OnChangeType): void {
    this.onChange = fn;
  }
 
  registerOnTouched(fn: OnTouchedType): void {
    this.onTouched = fn;
  }
 
  onCheckboxBlur(): void {
    this.onTouched();
    this.cdr.markForCheck();
  }
 
  onCheckboxChange(): void {
    if (this.disabled()) return;
 
    this.checked = !this.checked;
    this.onChange(this.checked);
    this.checkChange.emit(this.checked);
    this.cdr.markForCheck();
  }
 
  onKeyboardEvent(event: KeyboardEvent): void {
    if (event.key === ' ' || event.key === 'Enter') {
      event.preventDefault();
      this.onCheckboxChange();
    }
  }
}
 
checkbox.variants.ts
checkbox.variants.ts
import { cva, type VariantProps } from 'class-variance-authority';
 
export const checkboxVariants = cva(
  'cursor-[unset] peer appearance-none border transition shadow hover:shadow-md focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',
  {
    variants: {
      zType: {
        default: 'border-primary checked:bg-primary',
        destructive: 'border-destructive checked:bg-destructive',
      },
      zSize: {
        default: 'h-4 w-4',
        lg: 'h-6 w-6',
      },
      zShape: {
        default: 'rounded',
        circle: 'rounded-full',
        square: 'rounded-none',
      },
    },
    defaultVariants: {
      zType: 'default',
      zSize: 'default',
      zShape: 'default',
    },
  },
);
 
export const checkboxLabelVariants = cva('cursor-[unset] text-current empty:hidden', {
  variants: {
    zSize: {
      default: 'text-base',
      lg: 'text-lg',
    },
  },
  defaultVariants: {
    zSize: 'default',
  },
});
 
export type ZardCheckboxVariants = VariantProps<typeof checkboxVariants>;
export type ZardCheckLabelVariants = VariantProps<typeof checkboxLabelVariants>;
 

Examples

default

import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
 
import { ZardCheckboxComponent } from '../checkbox.component';
 
@Component({
  selector: 'z-demo-checkbox-default',
  standalone: true,
  imports: [ZardCheckboxComponent, FormsModule],
  template: `
    <span z-checkbox></span>
    <span z-checkbox [(ngModel)]="checked">Default Checked</span>
  `,
})
export class ZardDemoCheckboxDefaultComponent {
  checked = true;
}
 

destructive

import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
 
import { ZardCheckboxComponent } from '../checkbox.component';
 
@Component({
  selector: 'z-demo-checkbox-destructive',
  standalone: true,
  imports: [ZardCheckboxComponent, FormsModule],
  template: `
    <span z-checkbox zType="destructive"></span>
    <span z-checkbox zType="destructive" [(ngModel)]="checked">Destructive Checked</span>
  `,
})
export class ZardDemoCheckboxDestructiveComponent {
  checked = true;
}
 

size

import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
 
import { ZardCheckboxComponent } from '../checkbox.component';
 
@Component({
  selector: 'z-demo-checkbox-size',
  standalone: true,
  imports: [ZardCheckboxComponent, FormsModule],
  template: `
    <span z-checkbox>Default</span>
    <span z-checkbox zSize="lg" [(ngModel)]="checked">Large</span>
  `,
})
export class ZardDemoCheckboxSizeComponent {
  checked = true;
}
 

shape

import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
 
import { ZardCheckboxComponent } from '../checkbox.component';
 
@Component({
  selector: 'z-demo-checkbox-shape',
  standalone: true,
  imports: [ZardCheckboxComponent, FormsModule],
  template: `
    <span z-checkbox zShape="circle" [(ngModel)]="checked">Cicle</span>
    <span z-checkbox zShape="square" [(ngModel)]="checked">Square</span>
  `,
})
export class ZardDemoCheckboxShapeComponent {
  checked = true;
}
 

disabled

import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
 
import { ZardCheckboxComponent } from '../checkbox.component';
 
@Component({
  selector: 'z-demo-checkbox-disabled',
  standalone: true,
  imports: [ZardCheckboxComponent, FormsModule],
  template: `
    <span z-checkbox disabled>Disabled</span>
    <span z-checkbox disabled [(ngModel)]="checked">Disabled</span>
  `,
})
export class ZardDemoCheckboxDisabledComponent {
  checked = true;
}
 

API

[z-checkbox] Directive

z-checkbox is a Directive that brings you a customizable checkbox with minimal configuration

To get a customized checkbox, just pass the following props to the directive.

Property Description Type Default
zType chekbox type default | destructive default
zSize chekbox size default | sm | lg | icon default
zShape chekbox shape default | circle | square default