Skip to content
CodeAtlas UI

Inputs

ToggleGroup

A set of toggle buttons with single or multiple selection, roving focus and arrow-key navigation.

<script>
  import { ToggleGroup } from "@codeatlasdev/ui";
  let format = $state(["bold"]);
</script>

<ToggleGroup type="multiple" aria-label="Text formatting" bind:value={format} items={items} />

In single mode the user can press the active item again to clear the selection, so value can be an empty string. Use SegmentedControl when a choice is required. Icon-only items need an aria-label.

Single and multiple

type="single" binds a string. type="multiple" binds a string array.

value: left

value: ["bold"]

Code
svelte
<script lang="ts">
  import { ToggleGroup } from '@codeatlasdev/ui';
  import { AlignCenter, AlignLeft, AlignRight, Bold, Italic, Underline } from '@lucide/svelte';

  let align = $state('left');
  let format = $state<string[]>(['bold']);
</script>

<div class="col">
  <div>
    <ToggleGroup
      type="single"
      aria-label="Text alignment"
      bind:value={align}
      items={[
        { value: 'left', icon: AlignLeft, 'aria-label': 'Align left' },
        { value: 'center', icon: AlignCenter, 'aria-label': 'Align center' },
        { value: 'right', icon: AlignRight, 'aria-label': 'Align right' },
      ]}
    />
    <p class="out">value: {align || '–'}</p>
  </div>
  <div>
    <ToggleGroup
      type="multiple"
      aria-label="Text formatting"
      bind:value={format}
      items={[
        { value: 'bold', icon: Bold, 'aria-label': 'Bold' },
        { value: 'italic', icon: Italic, 'aria-label': 'Italic' },
        { value: 'underline', icon: Underline, 'aria-label': 'Underline' },
      ]}
    />
    <p class="out">value: {JSON.stringify(format)}</p>
  </div>
</div>

<style>
  .col {
    display: flex;
    flex-direction: column;
    gap: var(--ca-space-5);
  }

  .out {
    margin: var(--ca-space-3) 0 0;
    font-size: var(--ca-font-size-caption);
    color: var(--ca-text-secondary);
  }
</style>

Variants and orientation

outlined and ghost variants, sizes, a disabled item and a vertical layout.

Code
svelte
<script lang="ts">
  import { ToggleGroup } from '@codeatlasdev/ui';

  let view = $state('list');
</script>

<ToggleGroup
  variant="outlined"
  size="md"
  aria-label="Outlined"
  bind:value={view}
  items={[
    { value: 'list', label: 'List' },
    { value: 'grid', label: 'Grid' },
    { value: 'board', label: 'Board', disabled: true },
  ]}
/>
<ToggleGroup
  variant="ghost"
  size="sm"
  aria-label="Ghost"
  bind:value={view}
  items={[
    { value: 'list', label: 'List' },
    { value: 'grid', label: 'Grid' },
  ]}
/>
<ToggleGroup
  orientation="vertical"
  aria-label="Vertical"
  bind:value={view}
  items={[
    { value: 'list', label: 'List' },
    { value: 'grid', label: 'Grid' },
  ]}
/>

Props

PropTypeDefaultDescription
type'single' | 'multiple''single'Selection mode.
valuestring | string[]–Bindable. A string for single, an array for multiple.
itemsToggleGroupItem[]–{ value, label?, icon?, disabled?, 'aria-label'? }. Icon-only items need aria-label.
size'sm' | 'md''md'Item height.
variant'outlined' | 'ghost''outlined'Container style.
disabledbooleanfalseDisables the whole group.
orientation'horizontal' | 'vertical''horizontal'Layout and arrow-key axis.
aria-labelstring–Accessible name of the group.
classstring–Extra classes on the root.
onchange(value: string | string[]) => void–Called on every change.