๐ŸŸข Checkbox


Basic

use NCheckbox component to create a checkbox.

AttributeDescription
v-modelReactive value of checkbox if checked or not.
labelThe label of the checkbox.

To view the full list of attributes, see the Props section.

<script setup lang="ts">
const off = ref(false)
</script>

<template>
<NCheckbox v-model="off" label="Checkbox" />
</template>

Color

checkbox="{color}" - change the color of the checkbox.

You can use breakpoints such as sm:red, xs:green to change color based on screen size.

You can use any color provided by the Tailwind CSS color palette, the default is primary. You can also add your own colors to the palette through the Configuration section.
<script setup lang="ts">
const colors = [
{
  checkbox: 'red sm:primary',
},
{
  checkbox: 'info',
},
{
  checkbox: 'error',
},
{
  checkbox: 'warning',
},
{
  checkbox: 'success',
},
{
  checkbox: 'purple',
},
{
  checkbox: 'pink',
},
{
  checkbox: 'violet',
},
{
  checkbox: 'fuchsia',
},
{
  checkbox: 'indigo',
},
]
</script>

<template>
<div class="flex flex-wrap gap-4">
  <NCheckbox
    v-for="color in colors"
    :key="color.checkbox"
    :model-value="true"
    :label="color.checkbox"
    :checkbox="color.checkbox"
  />
</div>
</template>

Form Group

You can use the NFormGroup component to create a checkbox group for the checkbox,

Read more about the NFormGroup component here.

Remember to set for to false to disable for behavior on the label since we have a custom implementation for the checkbox input.
Participating, @mentions and custom
Notifications for the conversations you are participating in, or if someone cites you with an @mention. Also for all activity when subscribed to specific events.

Participating, @mentions and custom
Notifications for the conversations you are participating in, or if someone cites you with an @mention. Also for all activity when subscribed to specific events.

You must choose at least one event

<script setup lang="ts">
const notifications = ref([
{
  label: 'On github',
  value: false,
  checkbox: 'gray',
},
{
  label: 'Email',
  value: false,
  checkbox: 'yellow',
},
{
  label: 'Discord',
  value: false,
  checkbox: 'indigo',
},
])
</script>

<template>
<div class="flex flex-col space-y-6">
  <!-- Vertical -->
  <NFormGroup
    :for="false"
    label="Participating, @mentions and custom"
    description="Notifications for the conversations you are participating in, or if someone cites you with an @mention. Also for all activity when subscribed to specific events."
  >
    <NCheckbox
      v-for="option in notifications"
      :key="option.label"
      v-model="option.value"
      :label="option.label"
      :checkbox="option.checkbox"
    />
  </NFormGroup>

  <hr class="border-base">

  <!-- Horizontal -->
  <NFormGroup
    :for="false"
    required
    message="You must choose at least one event"
    label="Participating, @mentions and custom"
    description="Notifications for the conversations you are participating in, or if someone cites you with an @mention. Also for all activity when subscribed to specific events."
  >
    <div class="flex flex-wrap gap-8">
      <NCheckbox
        v-for="option in notifications"
        :key="option.label"
        v-model="option.value"
        :label="option.label"
        :checkbox="option.checkbox"
      />
    </div>
  </NFormGroup>
</div>
</template>

Size

size="{size}" - change the size of the checkbox.

๐Ÿš€ You can freely adjust the size of the checkbox using any size imaginable. No limits exist, and you can use breakpoints such as sm:sm, xs:lg to change size based on screen size.

<script setup lang="ts">
const items = [
{
  label: '0.8cm',
  size: '0.8cm',
},
{
  label: 'xs md:2xl',
  size: 'xs md:2xl',
},
{
  label: 'sm',
  size: 'sm',
},
]
</script>

<template>
<div class="flex gap-4">
  <NCheckbox
    v-for="item in items"
    :key="item.size"
    :model-value="true"
    v-bind="item"
  />
</div>
</template>

Disabled

disabled - disable the checkbox.

<script setup lang="ts">
const checkbox = ref()
</script>

<template>
<div class="flex gap-4">
  <NCheckbox v-model="checkbox" label="Disabled" disabled />

  <NCheckbox v-model="checkbox" label="Not disabled" />
</div>
</template>

Reverse

reverse - Switch the position of the checkbox and the label.

<script setup lang="ts">
const options = ref([
{ label: 'Checkbox A', value: false },
{ label: 'Checkbox B', value: false },
{ label: 'Checkbox C', value: false },
])
</script>

<template>
<div class="flex flex-wrap space-x-8">
  <NCheckbox
    v-for="option in options"
    :key="option.label"
    v-model="option.value"
    :label="option.label"
    reverse
  />
</div>
</template>

Rules

You can use the following rules to customize the checkbox if it is checked.

You can also globally customize the checkbox preset if you want to have a different default style. See Configuration section for more details.
Rule NameDescriptionExample
n-checkedOnly apply the class if the checkbox is checked.n-checked:3xl
<script setup lang="ts">
const options = [
{
  value: true,
  radio: 'green',
},
{
  value: false,
  radio: 'blue',
},
{
  value: false,
  radio: 'red',
},
]
</script>

<template>
<div class="flex flex-wrap gap-4">
  <NCheckbox
    v-for="option in options"
    v-bind="option"
    :key="option.radio"
    v-model="option.value"
    size="xl n-checked:3xl"
  />
</div>
</template>

Customization

You can customize the checkbox using the una prop and utility classes.

You can also globally customize the checkbox preset if you want to have a different default style. See Configuration section for more details.

una.checkboxIcon - Custom icon of the checkbox when it is checked.

<script setup lang="ts">
const options = ref([
{
  value: true,
  label: '1',
},
{
  value: true,
  label: '2',
},
{
  value: false,
  label: '3',
},
])
</script>

<template>
<div class="flex flex-wrap gap-4">
  <NCheckbox
    v-for="(option, i) in options"
    :key="i"
    v-model="option.value"
    :label="option.label"
    size="xl"
    :una="{
      checkboxIcon: 'i-tabler-checks',
    }"
  />
</div>
</template>

<script setup lang="ts">
const options = ref([
{
  value: true,
  label: '1',
  checkbox: 'green',
  una: {
    checkboxIcon: 'i-tabler-circle-1-filled',
  },
},
{
  value: true,
  label: '2',
  checkbox: 'blue',
  una: {
    checkboxIcon: 'i-tabler-circle-2-filled',
  },
},
{
  value: true,
  label: '3',
  checkbox: 'red',
  una: {
    checkboxIcon: 'i-tabler-circle-3-filled',
  },
},
])
</script>

<template>
<div class="flex flex-wrap gap-4">
  <NCheckbox
    v-for="(option, i) in options"
    :key="i"
    v-model="option.value"
    :checkbox="option.checkbox"
    :label="option.label"
    size="3xl"
    class="rounded-full"
    :una="option.una"
  />
</div>
</template>

Value: [ true, false, false ]
<script setup lang="ts">
const options = ref([
{
  value: true,
  label: 'Vue',
  class: 'n-checked:bg-green-500/30 n-checked:border-green-500',
  checkbox: 'green',
  una: {
    checkboxIcon: 'i-logos-vue n-checked:scale-150 transition-transform duration-1000',
  },
},
{
  value: false,
  label: 'React',
  class: 'n-checked:bg-blue-500/30 n-checked:border-blue-500',
  checkbox: 'blue',
  una: {
    checkboxIcon: 'i-logos-react  n-checked:rotate-360 transition-transform duration-1000',
  },
},
{
  value: false,
  label: 'Angular',
  class: 'n-checked:bg-red-500/30 n-checked:border-red-500',
  checkbox: 'red',
  una: {
    checkboxIcon: 'i-logos-angular-icon n-checked:scale-120 transition-transform duration-1000',
  },
},
])

const optionsValue = computed(() => options.value.map(option => option.value))
</script>

<template>
<div class="flex flex-col space-y-6">
  <span>
    Value: {{ optionsValue }}
  </span>

  <div class="flex flex-wrap gap-4">
    <NCheckbox
      v-for="(option, i) in options"
      :key="i"
      v-model="option.value"
      :checkbox="option.checkbox"
      size="15"
      :label="option.label"
      :class="option.class"
      class="rounded-md"
      :una="option.una"
    />
  </div>
</div>
</template>

Slots

NameDescription
labelUse this slot to customize the label of the checkbox.
iconUse this slot to customize the icon of the checkbox when it is checked

Props

export interface NCheckboxProps {
  /**
   * v-model binding value if the checkbox is checked.
   */
  modelValue?: boolean | null
  /**
   * Disable the checkbox.
   */
  disabled?: boolean
  /**
   * Switch the position of label and checkbox.
   */
  reverse?: boolean

  /**
   * Allows you to add `UnaUI` checkbox preset properties,
   * Think of it as a shortcut for adding options or variants to the preset if available.
   */
  checkbox?: string
  /**
   * Add name attribute to the checkbox.
   *
   * @default null
   */
  name?: string
  /**
   * Manually set the id attribute.
   * By default, the id attribute is generated randomly for accessibility reasons.
   *
   * @default randomId
   */
  id?: string
  /**
   * Manually set the for attribute.
   *
   * By default, the for attribute is synced with the id attribute for accessibility reasons.
   *
   * @default randomId
   * @example
   * for="options"
   */
  for?: string
  /**
   * Display label text.
   *
   * @default null
   */
  label?: string
  /**
   * Allows you to change the size of the checkbox.
   *
   * @default size="sm"
   *
   * @example
   * size="sm" | size="2cm" | size="2rem" | size="2px"
   */
  size?: string
  /**
   * `UnaUI` preset configuration
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/checkbox.ts
   */
  una?: {
    checkbox?: string
    checkboxWrapper?: string
    checkboxLabel?: string
    checkboxIconBase?: string
    checkboxIcon?: string
  }
}

Presets

import { parseColor } from '@unocss/preset-mini/utils'
import type { Theme } from '@unocss/preset-uno'
import type { RuleContext } from '@unocss/core'

type CheckboxPrefix = 'checkbox'

export const staticCheckbox: Record<`${CheckboxPrefix}-${string}` | CheckboxPrefix, string> = {
  // base
  'checkbox': 'checkbox-primary flex items-center transition-base w-1em h-1em border border-$c-ring rounded n-checked:border-brand n-checked:bg-brand',
  'checkbox-disabled': 'n-disabled',
  'checkbox-label': 'block text-sm font-medium leading-6',
  'checkbox-input': 'absolute w-full opacity-0',
  'checkbox-reverse': 'flex-row-reverse',
  'checkbox-peer-focus': 'peer-focus-(ring-2 ring-brand ring-offset-2 ring-offset-base)',

  // wrappers
  'checkbox-wrapper': 'gap-x-3 relative inline-flex items-center hover:cursor-pointer',

  // icon
  'checkbox-icon-base': 'm-auto h-full w-full opacity-0 transition-base n-checked:opacity-100 text-inverted',
  'checkbox-icon': 'i-check', // refer to general.ts
}

export const dynamicCheckbox = [
  [/^checkbox-(.*)$/, ([, body]: string[], { theme }: RuleContext<Theme>) => {
    const color = parseColor(body, theme)
    if ((color?.cssColor?.type === 'rgb' || color?.cssColor?.type === 'rgba') && color.cssColor.components)
      return `n-${body}-600 dark:n-${body}-500`
  }],
]

export const checkbox = [
  ...dynamicCheckbox,
  staticCheckbox,
]

Component

<script setup lang="ts">
import { useVModel } from '@vueuse/core'
import { computed } from 'vue'
import NIcon from '../elements/Icon.vue'
import { randomId } from '../../utils'
import type { NCheckboxProps } from '../../types/checkbox'

defineOptions({
  inheritAttrs: false,
})

const props = withDefaults(
  defineProps<NCheckboxProps>(),
  {
    modelValue: false,
    disabled: false,
    una: () => ({
      checkboxIcon: 'checkbox-icon',
    }),
  },
)
const emit = defineEmits<{ (...args: any): void }>()

const slots = defineSlots<{
  default?: void
  icon?: any
}>()

const id = computed(() => props.id ?? randomId('checkbox'))

const checked = useVModel(props, 'modelValue', emit, { passive: true })
</script>

<template>
  <label
    checkbox="wrapper"
    :for="props.for ?? id"
    :class="[
      una?.checkboxWrapper,
      {
        'checkbox-reverse': reverse,
        'checkbox-disabled': disabled,
      },
    ]"
    :checked="checked || null"
    :disabled="disabled || null"
  >
    <input
      :id="id"
      v-model="checked"
      type="checkbox"
      class="peer"
      checkbox="input"
      :disabled="disabled"
      :name="name"
      @keypress.enter="checked = !checked"
    >
    <span
      :checkbox="checkbox"
      :size="size"
      class="checkbox checkbox-peer-focus"
      v-bind="$attrs"
    >
      <slot name="icon">
        <NIcon
          checkbox="icon-base icon-checked"
          :name="una.checkboxIcon!"
          :class="[
            una.checkboxIconBase,
          ]"
        />
      </slot>
    </span>
    <div
      v-if="slots.default || label"
      checkbox="label"
      :class="una?.checkboxLabel"
    >
      <slot>
        {{ label }}
      </slot>
    </div>
  </label>
</template>