Checkbox Group

Groups multiple checkboxes and emits a list of selected values.
Permissions[ "tenant:read" ]
vue
<script setup lang="ts">
import { ref } from 'vue'
import { CheckboxGroup, Checkbox } from '@typlog/ui'

const permissions = ref(['tenant:read'])
</script>

<template>
  <div>
    <div class="flex items-center gap-2 mb-2">
      <span class="font-medium">Permissions</span>
      <span>{{ permissions }}</span>
    </div>
    <CheckboxGroup v-model="permissions">
      <label class="flex items-center gap-1 mb-1">
        <Checkbox value="tenant:read" />
        <span>Tenant Read Permission</span>
      </label>
      <label class="flex items-center gap-1 mb-1">
        <Checkbox value="tenant:write" />
        <span>Tenant Write Permission</span>
      </label>
      <label class="flex items-center gap-1 mb-1">
        <Checkbox value="tenant:admin" />
        <span>Tenant Admin Permission</span>
      </label>
    </CheckboxGroup>
  </div>
</template>

CheckboxGroup coordinates multiple Checkbox components and exposes their selected value props as an array. Bind the array with v-model, and wrap each checkbox in a label so its visible text is part of the accessible control.

API Reference ​

CheckboxGroup ​

CheckboxGroup wraps the Reka UI CheckboxGroupRoot. Use orientation to match the visual layout when enabling arrow-key navigation, and use name when the group participates in a native form.

PropDefaultType
allValues
–
T[]

All values controlled by the select-all checkbox. Values outside this list remain unchanged when the group is cleared.

as"div"
AsTagComponent

The outer element or component.

contentAs"div"
AsTagComponent

The element or component that wraps the default slot.

Each child Checkbox must provide a unique value. Visual props such as size, variant, color, and highContrast belong to the child checkbox rather than the group.

as controls the outer component element. contentAs controls the element that wraps the default slot and receives the group behavior.

Examples ​

Nested groups and select all ​

Keep each related set of values in its own CheckboxGroup. Pass the complete set to allValues, then bind checkboxProps from the select-all slot to a parent checkbox. The parent is checked when every value is selected and indeterminate when only some values are selected.

Clearing the parent removes only values listed in allValues, so multiple groups can safely share the same v-model array.

Token Scopes[ "tenant:read" ]
vue
<script setup lang="ts">
import { ref } from 'vue'
import { CheckboxGroup, Checkbox } from '@typlog/ui'

const tenantScopes = ['tenant:read', 'tenant:write', 'tenant:admin']
const userScopes = ['user:read', 'user:write', 'user:tenants']
const scopes = ref(['tenant:read'])
</script>

<template>
  <div>
    <div class="flex items-center gap-2 mb-2">
      <span class="font-medium">Token Scopes</span>
      <span>{{ scopes }}</span>
    </div>
    <CheckboxGroup
      v-model="scopes"
      :all-values="tenantScopes"
      orientation="vertical"
      class="mb-4"
    >
      <template #select-all="{ checkboxProps }">
        <label class="flex items-center gap-1 mb-1">
          <Checkbox v-bind="checkboxProps" />
          <span>Tenant Permissions</span>
        </label>
      </template>
      <label class="pl-4 flex items-center gap-1">
        <Checkbox value="tenant:read" />
        <span>Tenant Read Permission</span>
      </label>
      <label class="pl-4 flex items-center gap-1">
        <Checkbox value="tenant:write" />
        <span>Tenant Write Permission</span>
      </label>
      <label class="pl-4 flex items-center gap-1">
        <Checkbox value="tenant:admin" />
        <span>Tenant Admin Permission</span>
      </label>
    </CheckboxGroup>
    <CheckboxGroup
      v-model="scopes"
      :all-values="userScopes"
      orientation="vertical"
    >
      <template #select-all="{ checkboxProps }">
        <label class="flex items-center gap-1 mb-1">
          <Checkbox v-bind="checkboxProps" />
          <span>User Profile</span>
        </label>
      </template>
      <label class="pl-4 flex items-center gap-1">
        <Checkbox value="user:read" />
        <span>Read user profile</span>
      </label>
      <label class="pl-4 flex items-center gap-1">
        <Checkbox value="user:write" />
        <span>Update user profile</span>
      </label>
      <label class="pl-4 flex items-center gap-1">
        <Checkbox value="user:tenants" />
        <span>Fetch user's tenants</span>
      </label>
    </CheckboxGroup>
  </div>
</template>

Table ​

Set the outer component to Typlog UI's Table and the default-slot container to tbody. The select-all slot can then render a sibling thead without placing its checkbox inside the selection context, while retaining the Table component's scrolling and visual styles.

Permission
read
write
publish
vue
<script setup lang="ts">
import { ref } from 'vue'
import { Checkbox, CheckboxGroup, Table } from '@typlog/ui'

const permissions = ['read', 'write', 'publish']
const selected = ref(['read'])
</script>

<template>
  <CheckboxGroup
    v-model="selected"
    :all-values="permissions"
    :as="Table"
    content-as="tbody"
    orientation="vertical"
    variant="surface"
  >
    <template #select-all="{ checkboxProps }">
      <thead>
        <tr>
          <th class="w-8">
            <Checkbox v-bind="checkboxProps" aria-label="Select all permissions" />
          </th>
          <th>Permission</th>
        </tr>
      </thead>
    </template>

    <tr v-for="permission in permissions" :key="permission">
      <td>
        <Checkbox
          :value="permission"
          :aria-label="`Select ${permission} permission`"
        />
      </td>
      <td class="capitalize">
        {{ permission }}
      </td>
    </tr>
  </CheckboxGroup>
</template>
Last updated Sep 15, 2026