shadcn-remix
GitHub

Checkbox

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

By clicking this checkbox, you agree to the terms and conditions.

import { css } from 'remix/component'

import { Checkbox } from '#app/ui/checkbox.tsx'
import { Label } from '#app/ui/label.tsx'

const stackStyles = css({ display: 'flex', flexDirection: 'column', gap: '1.5rem' })
import { css } from 'remix/component'

import { Checkbox } from '#app/ui/checkbox.tsx'
import { Label } from '#app/ui/label.tsx'

const stackStyles = css({ display: 'flex', flexDirection: 'column', gap: '1.5rem' })
const rowCenterStyles = css({ display: 'flex', alignItems: 'center', gap: '0.75rem' })
const rowStartStyles = css({ display: 'flex', alignItems: 'flex-start', gap: '0.75rem' })
const textStackStyles = css({ display: 'grid', gap: '0.5rem' })
const mutedStyles = css({
  fontSize: '0.875rem',
  lineHeight: 'calc(1.25 / 0.875)',
  color: 'var(--muted-foreground)',
})
const cardStyles = css({
  display: 'flex',
  alignItems: 'flex-start',
  gap: '0.75rem',
  borderRadius: 'var(--radius)',
  borderWidth: '1px',
  padding: '0.75rem',
  '&:hover': { backgroundColor: 'color-mix(in oklab, var(--accent) 50%, transparent)' },
  '&:has([aria-checked="true"])': {
    borderColor: 'oklch(54.6% 0.245 262.881)',
    backgroundColor: 'oklch(97% 0.014 254.604)',
  },
  '.dark &:has([aria-checked="true"])': {
    borderColor: 'oklch(37.9% 0.146 265.522)',
    backgroundColor: 'oklch(28.2% 0.091 267.935)',
  },
})
const blueCheckboxStyles = css({
  '&[data-state="checked"]': {
    borderColor: 'oklch(54.6% 0.245 262.881)',
    backgroundColor: 'oklch(54.6% 0.245 262.881)',
    color: 'white',
  },
  '.dark &[data-state="checked"]': {
    borderColor: 'oklch(48.8% 0.243 264.376)',
    backgroundColor: 'oklch(48.8% 0.243 264.376)',
  },
})
const cardTextStyles = css({ display: 'grid', gap: '0.375rem', fontWeight: 400 })
const cardTitleStyles = css({ fontSize: '0.875rem', lineHeight: 1, fontWeight: 500 })

export function CheckboxDemo() {
  return () => (
    <div mix={stackStyles}>
      <div mix={rowCenterStyles}>
        <Checkbox id="terms" />
        <Label htmlFor="terms">Accept terms and conditions</Label>
      </div>
      <div mix={rowStartStyles}>
        <Checkbox id="terms-2" defaultChecked />
        <div mix={textStackStyles}>
          <Label htmlFor="terms-2">Accept terms and conditions</Label>
          <p mix={mutedStyles}>By clicking this checkbox, you agree to the terms and conditions.</p>
        </div>
      </div>
      <div mix={rowStartStyles}>
        <Checkbox id="toggle" disabled />
        <Label htmlFor="toggle">Enable notifications</Label>
      </div>
      <Label mix={cardStyles}>
        <Checkbox id="toggle-2" defaultChecked mix={blueCheckboxStyles} />
        <div mix={cardTextStyles}>
          <p mix={cardTitleStyles}>Enable notifications</p>
          <p mix={mutedStyles}>You can enable or disable notifications at any time.</p>
        </div>
      </Label>
    </div>
  )
}

Installation

$ pnpm dlx shadcn@latest add https://www.shadcn-remix.com/r/checkbox.json

Usage

import { Checkbox } from '#app/ui/checkbox.tsx'
<Checkbox />

Examples

Disabled

Use the disabled prop to prevent interaction and add the data-disabled attribute to the <Field> component for disabled styles.

import { css } from 'remix/component'

import { Checkbox } from '#app/ui/checkbox.tsx'

const rowStyles = css({
  display: 'flex',
import { css } from 'remix/component'

import { Checkbox } from '#app/ui/checkbox.tsx'

const rowStyles = css({
  display: 'flex',
  alignItems: 'center',
  '& > :not(:last-child)': { marginInlineEnd: '0.5rem' },
})
const labelStyles = css({
  fontSize: '0.875rem',
  lineHeight: 1,
  fontWeight: 500,
  '.peer:disabled ~ &': { cursor: 'not-allowed', opacity: 0.7 },
})

export function CheckboxDisabled() {
  return () => (
    <div mix={rowStyles}>
      <Checkbox id="terms2" disabled />
      <label htmlFor="terms2" mix={labelStyles}>
        Accept terms and conditions
      </label>
    </div>
  )
}

With text

You agree to our Terms of Service and Privacy Policy.

import { css } from 'remix/component'

import { Checkbox } from '#app/ui/checkbox.tsx'

const rowStyles = css({ display: 'flex', gap: '0.5rem' })
const textStyles = css({ display: 'grid', gap: '0.375rem', lineHeight: 1 })
import { css } from 'remix/component'

import { Checkbox } from '#app/ui/checkbox.tsx'

const rowStyles = css({ display: 'flex', gap: '0.5rem' })
const textStyles = css({ display: 'grid', gap: '0.375rem', lineHeight: 1 })
const labelStyles = css({
  fontSize: '0.875rem',
  lineHeight: 1,
  fontWeight: 500,
  '.peer:disabled ~ &': { cursor: 'not-allowed', opacity: 0.7 },
})
const mutedStyles = css({
  fontSize: '0.875rem',
  lineHeight: 'calc(1.25 / 0.875)',
  color: 'var(--muted-foreground)',
})

export function CheckboxWithText() {
  return () => (
    <div mix={rowStyles}>
      <Checkbox id="terms1" />
      <div mix={textStyles}>
        <label htmlFor="terms1" mix={labelStyles}>
          Accept terms and conditions
        </label>
        <p mix={mutedStyles}>You agree to our Terms of Service and Privacy Policy.</p>
      </div>
    </div>
  )
}

API Reference

Checkbox

A control that allows the user to toggle between checked and not checked. Renders a <button role="checkbox">; when it belongs to a form, a hidden native checkbox mirrors its state so name/value/required work with native form submission and validation.

PropTypeDefault
checkedCheckedState-
defaultCheckedCheckedState-
onCheckedChange((checked: CheckedState) => void)-
requiredboolean-
valuestring"on"
mixMixValue-