Checkbox
A control element that allows for multiple selections within a set.
Usage
import { Checkbox, type CheckboxProps } from '~/components/ui'
export const Demo = (props: CheckboxProps) => {
return (
<Checkbox defaultChecked {...props}>
Label
</Checkbox>
)
}
Examples
Indeterminate
The indeterminate
state signifies a checkbox with only some of its related options selected.
<Checkbox checked="indeterminate" />
With a different color
By default, the checkbox uses the accent
color from the theme. To render a checkbox with a different color, use the
colorPalette
prop.
<Checkbox colorPalette="red" defaultChecked />
Installation
npx @park-ui/cli components add checkbox
1
Styled Primitive
Copy the code snippet below into ~/components/ui/primitives/checkbox.tsx
'use client'
import type { Assign } from '@ark-ui/react'
import { Checkbox } from '@ark-ui/react/checkbox'
import { type CheckboxVariantProps, checkbox } from 'styled-system/recipes'
import type { ComponentProps, HTMLStyledProps } from 'styled-system/types'
import { createStyleContext } from '~/lib/create-style-context'
const { withProvider, withContext } = createStyleContext(checkbox)
export type RootProviderProps = ComponentProps<typeof RootProvider>
export const RootProvider = withProvider<
HTMLLabelElement,
Assign<Assign<HTMLStyledProps<'label'>, Checkbox.RootProviderBaseProps>, CheckboxVariantProps>
>(Checkbox.RootProvider, 'root')
export type RootProps = ComponentProps<typeof Root>
export const Root = withProvider<
HTMLLabelElement,
Assign<Assign<HTMLStyledProps<'label'>, Checkbox.RootBaseProps>, CheckboxVariantProps>
>(Checkbox.Root, 'root')
export const Control = withContext<
HTMLDivElement,
Assign<HTMLStyledProps<'div'>, Checkbox.ControlBaseProps>
>(Checkbox.Control, 'control')
export const Group = withContext<
HTMLDivElement,
Assign<HTMLStyledProps<'div'>, Checkbox.GroupBaseProps>
>(Checkbox.Group, 'group')
export const Indicator = withContext<
HTMLDivElement,
Assign<HTMLStyledProps<'div'>, Checkbox.IndicatorBaseProps>
>(Checkbox.Indicator, 'indicator')
export const Label = withContext<
HTMLSpanElement,
Assign<HTMLStyledProps<'span'>, Checkbox.LabelBaseProps>
>(Checkbox.Label, 'label')
export {
CheckboxContext as Context,
CheckboxHiddenInput as HiddenInput,
} from '@ark-ui/react/checkbox'
import { type Assign, Checkbox } from '@ark-ui/solid'
import type { ComponentProps } from 'solid-js'
import { type CheckboxVariantProps, checkbox } from 'styled-system/recipes'
import type { HTMLStyledProps } from 'styled-system/types'
import { createStyleContext } from '~/lib/create-style-context'
const { withProvider, withContext } = createStyleContext(checkbox)
export type RootProviderProps = ComponentProps<typeof RootProvider>
export const RootProvider = withProvider<
Assign<Assign<HTMLStyledProps<'label'>, Checkbox.RootProviderBaseProps>, CheckboxVariantProps>
>(Checkbox.RootProvider, 'root')
export type RootProps = ComponentProps<typeof Root>
export const Root = withProvider<
Assign<Assign<HTMLStyledProps<'label'>, Checkbox.RootBaseProps>, CheckboxVariantProps>
>(Checkbox.Root, 'root')
export const Control = withContext<Assign<HTMLStyledProps<'div'>, Checkbox.ControlBaseProps>>(
Checkbox.Control,
'control',
)
export const Group = withContext<Assign<HTMLStyledProps<'div'>, Checkbox.GroupBaseProps>>(
Checkbox.Group,
'group',
)
export const Indicator = withContext<Assign<HTMLStyledProps<'div'>, Checkbox.IndicatorBaseProps>>(
Checkbox.Indicator,
'indicator',
)
export const Label = withContext<Assign<HTMLStyledProps<'span'>, Checkbox.LabelBaseProps>>(
Checkbox.Label,
'label',
)
export {
CheckboxContext as Context,
CheckboxHiddenInput as HiddenInput,
} from '@ark-ui/solid'
No snippet found
Extend ~/components/ui/primitives/index.ts
with the following line:
export * as Checkbox from './checkbox'
2
Add Composition
Copy the code snippet below into ~/components/ui/checkbox.tsx
import { forwardRef } from 'react'
import { Checkbox as ArkCheckbox } from '~/components/ui/primitives'
export interface CheckboxProps extends ArkCheckbox.RootProps {}
export const Checkbox = forwardRef<HTMLLabelElement, CheckboxProps>((props, ref) => {
const { children, ...rootProps } = props
return (
<ArkCheckbox.Root ref={ref} {...rootProps}>
<ArkCheckbox.Control>
<ArkCheckbox.Indicator>
<CheckIcon />
</ArkCheckbox.Indicator>
<ArkCheckbox.Indicator indeterminate>
<MinusIcon />
</ArkCheckbox.Indicator>
</ArkCheckbox.Control>
{children && <ArkCheckbox.Label>{children}</ArkCheckbox.Label>}
<ArkCheckbox.HiddenInput />
</ArkCheckbox.Root>
)
})
Checkbox.displayName = 'Checkbox'
const CheckIcon = () => (
<svg viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<title>Check Icon</title>
<path
d="M11.6666 3.5L5.24992 9.91667L2.33325 7"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)
const MinusIcon = () => (
<svg viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<title>Minus Icon</title>
<path
d="M2.91675 7H11.0834"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)
import { Show, children } from 'solid-js'
import { Checkbox as ArkCheckbox } from '~/components/ui/primitives'
export interface CheckboxProps extends ArkCheckbox.RootProps {}
export const Checkbox = (props: CheckboxProps) => {
const getChildren = children(() => props.children)
return (
<ArkCheckbox.Root {...props}>
<ArkCheckbox.Control>
<ArkCheckbox.Indicator>
<CheckIcon />
</ArkCheckbox.Indicator>
<ArkCheckbox.Indicator indeterminate>
<MinusIcon />
</ArkCheckbox.Indicator>
</ArkCheckbox.Control>
<Show when={getChildren()}>
<ArkCheckbox.Label>{getChildren()}</ArkCheckbox.Label>
</Show>
<ArkCheckbox.HiddenInput />
</ArkCheckbox.Root>
)
}
const CheckIcon = () => (
<svg viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<title>Check Icon</title>
<path
d="M11.6666 3.5L5.24992 9.91667L2.33325 7"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
)
const MinusIcon = () => (
<svg viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<title>Minus Icon</title>
<path
d="M2.91675 7H11.0834"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
)
Extend ~/components/ui/index.ts
with the following line:
export * from './primitives'
export { Checkbox, type CheckboxProps } from './checkbox'
3
Integrate Recipe
If you're not using @park-ui/preset
, add the following recipe to yourpanda.config.ts
:
import { checkboxAnatomy } from '@ark-ui/anatomy'
import { defineSlotRecipe } from '@pandacss/dev'
export const checkbox = defineSlotRecipe({
className: 'checkbox',
slots: checkboxAnatomy.keys(),
base: {
root: {
alignItems: 'center',
colorPalette: 'accent',
display: 'flex',
},
label: {
color: 'fg.default',
fontWeight: 'medium',
},
control: {
alignItems: 'center',
borderColor: 'border.default',
borderWidth: '1px',
color: 'colorPalette.fg',
cursor: 'pointer',
display: 'flex',
justifyContent: 'center',
transitionDuration: 'normal',
transitionProperty: 'border-color, background',
transitionTimingFunction: 'default',
_hover: {
background: 'bg.subtle',
},
_checked: {
background: 'colorPalette.default',
borderColor: 'colorPalette.default',
_hover: {
background: 'colorPalette.default',
},
},
_indeterminate: {
background: 'colorPalette.default',
borderColor: 'colorPalette.default',
_hover: {
background: 'colorPalette.default',
},
},
'&:has(+ :focus-visible)': {
outlineOffset: '2px',
outline: '2px solid',
outlineColor: 'border.outline',
_checked: {
outlineColor: 'colorPalette.default',
},
},
},
},
defaultVariants: {
size: 'md',
},
variants: {
size: {
sm: {
root: {
gap: '2',
},
control: {
width: '4',
height: '4',
borderRadius: 'l1',
'& svg': {
width: '3',
height: '3',
},
},
label: {
textStyle: 'sm',
},
},
md: {
root: {
gap: '3',
},
control: {
width: '5',
height: '5',
borderRadius: 'l1',
'& svg': {
width: '3.5',
height: '3.5',
},
},
label: {
textStyle: 'md',
},
},
lg: {
root: {
gap: '4',
},
control: {
width: '6',
height: '6',
borderRadius: 'l1',
'& svg': {
width: '4',
height: '4',
},
},
label: {
textStyle: 'lg',
},
},
},
},
})