Group
The Group
mixin lets you create a container of toggleables, track which ones are
active, and manage keyboard focus easily. Tabs, Paginations, Disclosures, Accordion, Carousel etc.
are all groups of Toggleables.
Example: Toggle group
Let’s build a simple toggle group to see the Group
mixin in action. A toggle group is
a group of toggle buttons, so we can apply the Group
mixin to the ToggleButton
class.
The Group
mixin will internally extend the ToggleButton
class to manage
focus, track active elements etc. and store this extended class in the Item
property.
As a convention, every group of the library defines a createItem
function wrapping
the new this.Item(options)
instantiation. It allows to add a bit of logic if needed
and pass around the group.createItem
function to components and context in a homogeneous
way.
import { Group } from "chocobytes/blocks/group.svelte.js";
import { ToggleButton, type ToggleOptions } from "chocobytes/headless/toggle.svelte.js";
// It's that simple. You get roving focus and tracking for free
export class ToggleGroup extends Group(ToggleButton) {
createItem = (options: ToggleOptions) => {
return new this.Item(options);
};
}
Individual items would typically be instantiated by child components calling the group.createItem
function. What follows is a simple demo showcasing the focus options. With these particular options
the end result is almost like a radio group, except we can uncheck a checked item. But you can easily
build anything with other options!
Try playing around with your Arrow, Home and End keys, and check the roving tab sequence by tabbing back and forth from A to B.
<script lang="ts">
import { choco } from "chocobytes";
import { ToggleGroup } from "./toggleGroupExample.js";
const toppings = new ToggleGroup({
loop: true,
roving: true,
exclusive: true,
activateOnNext: true,
preventInactivation: false,
});
toppings.createItem({ value: "small", active: true });
toppings.createItem({ value: "medium" });
toppings.createItem({ value: "large" });
</script>
<button>A</button>
<p>
Topping amount:
{#if toppings.group.length === 0}
none
{:else}
{toppings.group[0]}
{/if}
</p>
<div class="my-8 flex gap-4">
{#each toppings.items as item}
<button class="rounded py-2 px-4 outline" class:underline={item.active} use:choco={item}>
{item.value}
</button>
{/each}
</div>
<button>B</button>
Topping amount: small
API
Constructor
loop
?: boolean- Specifies if the keyboard focus cycles from the last item to the first
- Default:
false
roving
?: boolean- Enables roving focus, where only one item in the list is in the tab sequence, and arrow keys shift focus between items
- Default:
false
preventInactivation
?: boolean- Prevents having no active elements. Toggling off a single active item will have no effect
- Default:
false
exclusive
?: boolean- Specifies whether only one item can be active at a time
- Default:
false
activateOnNext
?: boolean- Determines whether arrows immediately activate the next or previous item, typically when the
group is
exclusive
- Default:
false
group
?: string[] | (() => string[])- Lists the
value
s of active items. Can be bound - Default:
[]
setGroup
?: (v: string[]) => void- Setter allowing to bind the
value
s of the active items orientation
?: "horizontal" | "vertical"- The orientation of the group. For a vertically oriented group, the Up and Down keyboard arrows will behave as the Left and Right keys, and prevent scrolling
- Default:
"horizontal"