Actions Core Stable
ToggleGroup
A segmented row of toggle buttons with roving-tabindex keyboard navigation and single or multiple selection.
Preview
svelte
<script lang="ts">
import { ToggleGroup, ToggleGroupItem } from "fancy-ui-svelte";
let alignment = $state("left");
</script>
<ToggleGroup bind:value={alignment} label="Text alignment">
<ToggleGroupItem value="left" label="Align left">
<svg
class="size-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
aria-hidden="true"
>
<line x1="3" y1="6" x2="21" y2="6" />
<line x1="3" y1="12" x2="15" y2="12" />
<line x1="3" y1="18" x2="18" y2="18" />
</svg>
</ToggleGroupItem>
<ToggleGroupItem value="center" label="Align center">
<svg
class="size-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
aria-hidden="true"
>
<line x1="3" y1="6" x2="21" y2="6" />
<line x1="6" y1="12" x2="18" y2="12" />
<line x1="4" y1="18" x2="20" y2="18" />
</svg>
</ToggleGroupItem>
<ToggleGroupItem value="right" label="Align right">
<svg
class="size-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
aria-hidden="true"
>
<line x1="3" y1="6" x2="21" y2="6" />
<line x1="9" y1="12" x2="21" y2="12" />
<line x1="6" y1="18" x2="21" y2="18" />
</svg>
</ToggleGroupItem>
</ToggleGroup>Installation
pnpm add fancy-ui-svelte
import { ToggleGroup } from 'fancy-ui-svelte'
Usage
svelte
<script lang="ts">
import { ToggleGroup } from 'fancy-ui-svelte';
</script>
<ToggleGroup />Examples
Basic Usage
svelte
<script lang="ts">
import { ToggleGroup, ToggleGroupItem } from "$lib/fancy-ui/toggle-group";
let alignment = $state("left");
</script>
<ToggleGroup bind:value={alignment} label="Text alignment">
<ToggleGroupItem value="left" label="Align left">
<svg
class="size-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
aria-hidden="true"
>
<line x1="3" y1="6" x2="21" y2="6" />
<line x1="3" y1="12" x2="15" y2="12" />
<line x1="3" y1="18" x2="18" y2="18" />
</svg>
</ToggleGroupItem>
<ToggleGroupItem value="center" label="Align center">
<svg
class="size-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
aria-hidden="true"
>
<line x1="3" y1="6" x2="21" y2="6" />
<line x1="6" y1="12" x2="18" y2="12" />
<line x1="4" y1="18" x2="20" y2="18" />
</svg>
</ToggleGroupItem>
<ToggleGroupItem value="right" label="Align right">
<svg
class="size-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
aria-hidden="true"
>
<line x1="3" y1="6" x2="21" y2="6" />
<line x1="9" y1="12" x2="21" y2="12" />
<line x1="6" y1="18" x2="21" y2="18" />
</svg>
</ToggleGroupItem>
</ToggleGroup>Single Selection
Activating the active item again clears it.
svelte
<script lang="ts">
import { ToggleGroup, ToggleGroupItem } from "$lib/fancy-ui/toggle-group";
let view = $state("day");
</script>
<div class="flex flex-col items-start gap-2">
<ToggleGroup bind:value={view} label="Calendar view">
<ToggleGroupItem value="day">Day</ToggleGroupItem>
<ToggleGroupItem value="week">Week</ToggleGroupItem>
<ToggleGroupItem value="month">Month</ToggleGroupItem>
</ToggleGroup>
<!-- Activating the active item again clears it — the one state a native
radio group cannot express. -->
<p class="text-muted-foreground text-sm">
{view === ""
? "No view selected — click one, then click it again to clear it."
: `Showing the ${view} view.`}
</p>
</div>Multiple Selection
Independent on/off marks with type="multiple".
svelte
<script lang="ts">
import { ToggleGroup, ToggleGroupItem } from "$lib/fancy-ui/toggle-group";
let marks = $state<string[]>(["bold"]);
</script>
<div class="flex flex-col gap-3">
<ToggleGroup type="multiple" bind:value={marks} label="Formatting">
<ToggleGroupItem value="bold" label="Bold"><strong>B</strong></ToggleGroupItem>
<ToggleGroupItem value="italic" label="Italic"><em>I</em></ToggleGroupItem>
<ToggleGroupItem value="underline" label="Underline">
<span class="underline">U</span>
</ToggleGroupItem>
</ToggleGroup>
<p
class="text-sm"
class:font-bold={marks.includes("bold")}
class:italic={marks.includes("italic")}
class:underline={marks.includes("underline")}
>
Toggle the marks above to preview how this sentence would look.
</p>
</div>Vertical
A vertical rail — both arrow-key pairs still work.
svelte
<script lang="ts">
import { ToggleGroup, ToggleGroupItem } from "$lib/fancy-ui/toggle-group";
let tool = $state("select");
</script>
<ToggleGroup bind:value={tool} orientation="vertical" label="Tool">
<ToggleGroupItem value="select" label="Select">
<svg
class="size-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path d="m3 3 7.07 16.97 2.51-7.39 7.39-2.51L3 3z" />
</svg>
</ToggleGroupItem>
<ToggleGroupItem value="pan" label="Pan">
<svg
class="size-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path d="M18 11V6a2 2 0 0 0-2-2v0a2 2 0 0 0-2 2v0" />
<path d="M14 10V4a2 2 0 0 0-2-2v0a2 2 0 0 0-2 2v2" />
<path d="M10 10.5V6a2 2 0 0 0-2-2v0a2 2 0 0 0-2 2v8" />
<path
d="M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15"
/>
</svg>
</ToggleGroupItem>
<ToggleGroupItem value="zoom" label="Zoom">
<svg
class="size-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<circle cx="11" cy="11" r="8" />
<line x1="21" y1="21" x2="16.65" y2="16.65" />
</svg>
</ToggleGroupItem>
</ToggleGroup>Disabled Items
One item unavailable; the keyboard model skips it.
svelte
<script lang="ts">
import { ToggleGroup, ToggleGroupItem } from "$lib/fancy-ui/toggle-group";
let plan = $state("starter");
</script>
<div class="flex flex-col items-start gap-2">
<ToggleGroup bind:value={plan} label="Plan">
<ToggleGroupItem value="starter">Starter</ToggleGroupItem>
<ToggleGroupItem value="team" disabled>Team</ToggleGroupItem>
<ToggleGroupItem value="enterprise">Enterprise</ToggleGroupItem>
</ToggleGroup>
<p class="text-muted-foreground text-sm">
"Team" is unavailable on this account — the arrow keys and Home/End step around it, and it can
never end up focused or selected.
</p>
</div>Props
| Prop | Type | Default | Description |
|---|---|---|---|
type | "single" | "multiple" | "single" | Whether one item can be active at a time, or several. |
value | string | string[] | "" | The active value(s), bindable — a string when type="single", an array of strings when type="multiple". |
onValueChange | (value: string | string[]) => void | - | Called with the new value, shaped to match `type`, whenever the selection changes. |
disabled | boolean | false | Disables every item in the group. |
size | "sm" | "md" | "lg" | "md" | Sizes every item. |
orientation | "horizontal" | "vertical" | "horizontal" | The rail's stacking axis; both arrow-key pairs work either way. |
label | string | - | Accessible name for the group. |
class | string | - | Additional CSS classes, merged onto the root. |
ref | HTMLDivElement | null | null | Bindable reference to the root element. |
ToggleGroupItem.value * | string | - | The item's value — what gets added to or removed from the group's selection. |
ToggleGroupItem.disabled | boolean | false | Disables just this item, independent of the group's own `disabled`. |
ToggleGroupItem.label | string | - | Accessible name for icon-only content on this item. Also the text fallback. |
ToggleGroupItem.class | string | - | Additional CSS classes, merged onto the item's button. |
ToggleGroupItem.ref | HTMLButtonElement | null | null | Bindable reference to the item's button element. |
Slots
| Slot | Description |
|---|---|
children | The ToggleGroup's content — the ToggleGroupItems. |
ToggleGroupItem.children | The item's content, typically a glyph or a short label. |
Links
Related components
Bu
Button
The foundational push-button: six variants, three sizes, a loading state, and a polymorphic href/anchor mode
Actions Stable
Bu
ButtonGroup
Joins a row of adjacent actions into one seamless control — one border, one divider, no doubled edges
Actions Stable
Co
CopyButton
Button preset wired to the clipboard, swapping its icon and label to a success skin for a moment after a successful copy
Actions Stable