Components · Forms
Checkbox
A native checkbox in the Caseroom style. No JavaScript.
0.34% of the 2,062 sites in The UI Index have a checkbox (7 sites).
Both previews render the same markup; the HTML tab below is that markup without a framework.
Install
- React
- npx shadcn@
latest add https:// www.themes.dev/ caseroom/ r/ checkbox.json - Astro
- npx shadcn@
latest add https:// www.themes.dev/ caseroom/ r/ astro/ checkbox.json
Or copy the files below into your project. They need clsx, tailwind-merge, and the Caseroom theme. The HTML needs only the compiled CSS.
import type { InputHTMLAttributes } from 'react';
import { cn } from '@/lib/utils';
import { CHECK_PATH, checkboxClasses, checkboxMark, checkboxWrap } from './checkbox.variants';
export type CheckboxProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'type'>;
/** A native checkbox: works in forms, with the keyboard and without JavaScript. Pair it with a Label. */
export function Checkbox({ className, ...props }: CheckboxProps) {
return (
<span className={cn(checkboxWrap, className)}>
<input type="checkbox" className={checkboxClasses} {...props} />
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" className={checkboxMark}>
<path d={CHECK_PATH} />
</svg>
</span>
);
}export const checkboxWrap = 'relative inline-flex size-4 shrink-0';
export const checkboxClasses =
'peer size-4 shrink-0 cursor-pointer appearance-none rounded-[4px] border border-input bg-background transition-[color,background-color,border-color,transform] enabled:not-checked:hover:border-foreground enabled:not-checked:hover:bg-accent enabled:active:scale-90 enabled:not-checked:active:bg-pressed checked:border-primary checked:enabled:hover:border-[color-mix(in_oklab,var(--primary)_var(--hover-amount),var(--background))] checked:enabled:hover:bg-[color-mix(in_oklab,var(--primary)_var(--hover-amount),var(--background))] checked:enabled:active:border-[color-mix(in_oklab,var(--primary)_var(--press-amount),var(--press-mix))] checked:enabled:active:bg-[color-mix(in_oklab,var(--primary)_var(--press-amount),var(--press-mix))] checked:bg-primary indeterminate:border-primary indeterminate:bg-primary disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive';
export const checkboxMark =
'pointer-events-none absolute inset-0 hidden size-4 text-primary-foreground peer-checked:block';
export const CHECK_PATH = 'M3.5 8.5l3 3 6-7';---
import type { HTMLAttributes } from 'astro/types';
import { cn } from '@/lib/utils';
import { CHECK_PATH, checkboxClasses, checkboxMark, checkboxWrap } from './checkbox.variants';
type Props = Omit<HTMLAttributes<'input'>, 'type'>;
const { class: className, ...rest } = Astro.props;
---
<span class={cn(checkboxWrap, className)}>
<input type="checkbox" class={checkboxClasses} {...rest} />
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class={checkboxMark}>
<path d={CHECK_PATH} />
</svg>
</span>export const checkboxWrap = 'relative inline-flex size-4 shrink-0';
export const checkboxClasses =
'peer size-4 shrink-0 cursor-pointer appearance-none rounded-[4px] border border-input bg-background transition-[color,background-color,border-color,transform] enabled:not-checked:hover:border-foreground enabled:not-checked:hover:bg-accent enabled:active:scale-90 enabled:not-checked:active:bg-pressed checked:border-primary checked:enabled:hover:border-[color-mix(in_oklab,var(--primary)_var(--hover-amount),var(--background))] checked:enabled:hover:bg-[color-mix(in_oklab,var(--primary)_var(--hover-amount),var(--background))] checked:enabled:active:border-[color-mix(in_oklab,var(--primary)_var(--press-amount),var(--press-mix))] checked:enabled:active:bg-[color-mix(in_oklab,var(--primary)_var(--press-amount),var(--press-mix))] checked:bg-primary indeterminate:border-primary indeterminate:bg-primary disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive';
export const checkboxMark =
'pointer-events-none absolute inset-0 hidden size-4 text-primary-foreground peer-checked:block';
export const CHECK_PATH = 'M3.5 8.5l3 3 6-7';<div class="grid gap-4">
<label class="flex items-center gap-2 text-sm leading-none font-medium has-[input]:items-start has-[input]:leading-snug has-[input]:[&>*:first-child]:mt-px select-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50">
<span class="relative inline-flex size-4 shrink-0">
<input type="checkbox" class="peer size-4 shrink-0 cursor-pointer appearance-none rounded-[4px] border border-input bg-background transition-[color,background-color,border-color,transform] enabled:not-checked:hover:border-foreground enabled:not-checked:hover:bg-accent enabled:active:scale-90 enabled:not-checked:active:bg-pressed checked:border-primary checked:enabled:hover:border-[color-mix(in_oklab,var(--primary)_var(--hover-amount),var(--background))] checked:enabled:hover:bg-[color-mix(in_oklab,var(--primary)_var(--hover-amount),var(--background))] checked:enabled:active:border-[color-mix(in_oklab,var(--primary)_var(--press-amount),var(--press-mix))] checked:enabled:active:bg-[color-mix(in_oklab,var(--primary)_var(--press-amount),var(--press-mix))] checked:bg-primary indeterminate:border-primary indeterminate:bg-primary disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive" checked>
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="pointer-events-none absolute inset-0 hidden size-4 text-primary-foreground peer-checked:block"><path d="M3.5 8.5l3 3 6-7"></path></svg>
</span>
Email me about new components
</label>
<label class="flex items-center gap-2 text-sm leading-none font-medium has-[input]:items-start has-[input]:leading-snug has-[input]:[&>*:first-child]:mt-px select-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50">
<span class="relative inline-flex size-4 shrink-0">
<input type="checkbox" class="peer size-4 shrink-0 cursor-pointer appearance-none rounded-[4px] border border-input bg-background transition-[color,background-color,border-color,transform] enabled:not-checked:hover:border-foreground enabled:not-checked:hover:bg-accent enabled:active:scale-90 enabled:not-checked:active:bg-pressed checked:border-primary checked:enabled:hover:border-[color-mix(in_oklab,var(--primary)_var(--hover-amount),var(--background))] checked:enabled:hover:bg-[color-mix(in_oklab,var(--primary)_var(--hover-amount),var(--background))] checked:enabled:active:border-[color-mix(in_oklab,var(--primary)_var(--press-amount),var(--press-mix))] checked:enabled:active:bg-[color-mix(in_oklab,var(--primary)_var(--press-amount),var(--press-mix))] checked:bg-primary indeterminate:border-primary indeterminate:bg-primary disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive">
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="pointer-events-none absolute inset-0 hidden size-4 text-primary-foreground peer-checked:block"><path d="M3.5 8.5l3 3 6-7"></path></svg>
</span>
Send a weekly summary
</label>
<label class="flex items-center gap-2 text-sm leading-none font-medium has-[input]:items-start has-[input]:leading-snug has-[input]:[&>*:first-child]:mt-px select-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50 opacity-50">
<span class="relative inline-flex size-4 shrink-0">
<input type="checkbox" class="peer size-4 shrink-0 cursor-pointer appearance-none rounded-[4px] border border-input bg-background transition-[color,background-color,border-color,transform] enabled:not-checked:hover:border-foreground enabled:not-checked:hover:bg-accent enabled:active:scale-90 enabled:not-checked:active:bg-pressed checked:border-primary checked:enabled:hover:border-[color-mix(in_oklab,var(--primary)_var(--hover-amount),var(--background))] checked:enabled:hover:bg-[color-mix(in_oklab,var(--primary)_var(--hover-amount),var(--background))] checked:enabled:active:border-[color-mix(in_oklab,var(--primary)_var(--press-amount),var(--press-mix))] checked:enabled:active:bg-[color-mix(in_oklab,var(--primary)_var(--press-amount),var(--press-mix))] checked:bg-primary indeterminate:border-primary indeterminate:bg-primary disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive" disabled>
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="pointer-events-none absolute inset-0 hidden size-4 text-primary-foreground peer-checked:block"><path d="M3.5 8.5l3 3 6-7"></path></svg>
</span>
Unavailable on the free plan
</label>
</div>