Switch Group
A group of switches. In the following example, the group is exclusive (the default), and items can be unselected, unlike with a traditional radio group:
<script lang="ts">
import * as SwitchGroup from "$lib/components/switch-group/index.js";
let group: string[] = $state([]);
</script>
<h2 class="text-sm">Spice level</h2>
<SwitchGroup.Root focus={{ preventInactivation: false }} bind:group>
<SwitchGroup.Item value="mild" active>Mild</SwitchGroup.Item>
<SwitchGroup.Item value="medium" variant="outline">Medium</SwitchGroup.Item>
<SwitchGroup.Item value="hot">Hot</SwitchGroup.Item>
</SwitchGroup.Root>
<span class="font-semibold">Choice: {group.length > 0 ? group : "no spice"}</span>
<p class="text-sm italic">
{#if group.includes("mild")}
Enjoy a subtle hint of spice that adds a gentle kick to your chocolate without overwhelming the
palate
{:else if group.includes("medium")}
Experience a balanced heat that complements the rich chocolate flavor for a satisfying, spicy
kick
{:else if group.includes("hot")}
Get ready for a bold and fiery experience with a strong spice kick that pairs intensely with
your chocolate
{:else if group.length === 0}
Feel free to explore other spice levels to find the perfect amount of heat for your taste
{/if}
</p>
Spice level
Choice: mildEnjoy a subtle hint of spice that adds a gentle kick to your chocolate without overwhelming the palate
Headless component
Similarly to the toggle group, the headless component is
built in a few lines of code by applying the Group
mixin to the Switch
class. So all the heavy-lifting is done by the Group
mixin, like tracking the active items
and managing focus
import { Group } from "chocobytes/blocks/group.svelte.js";
import { Switch, type SwitchOptions } from "chocobytes/headless/switch.svelte.js";
export class SwitchGroup extends Group(Switch) {
createItem = (options?: SwitchOptions) => {
return new this.Item(options);
};
}
You have access to all the Group
focus options like loop
, exclusive
etc. In the following demo the group behaves almost like a radio group except
this one doesn’t loop. You can use the keyboard arrows to play with it:
<script lang="ts">
import { choco } from "chocobytes";
import { SwitchGroup } from "chocobytes/headless/switch-group.svelte.js";
const alignment = new SwitchGroup({
loop: false,
exclusive: true,
activateOnNext: true,
preventInactivation: true,
});
alignment.createItem({ value: "mild", active: true });
alignment.createItem({ value: "medium" });
alignment.createItem({ value: "hot" });
</script>
<div class="flex justify-center gap-2">
{#each alignment.items as item}
<button class="rounded py-2 px-4 outline" class:underline={item.active} use:choco={item}>
{item.value}
</button>
{/each}
</div>
selected heat:
<pre>{alignment.group}</pre>
selected heat:
mild