Triggerable
A specialized Toggleable which also controls a target element. This control-target pattern govern things like Tabs, Accordion, Disclosure, Popover, Carousel etc.
Both the control and target element have attributes that can be correlated and triggered on and
off, and the Triggerable
class help create headless components orchestrating this.
Example: Disclosure
For a simple headless disclosure we want to toggle a button’s aria-expanded
attribute
on click, and toggle the target’s hidden
property accordingly.
We can create this Disclosure
by extending the Triggerable
class as follows:
<script lang="ts">
import { choco } from "chocobytes";
import { Triggerable } from "chocobytes/blocks/triggerable.svelte.js";
import { fly } from "svelte/transition";
class Disclosure extends Triggerable {
constructor() {
// We just have to configure the control and target booleanish states
super({
control: { "aria-expanded": "false" },
target: { hidden: true },
active: false,
// here we only want to toggle on click
toggle: "click",
});
// We can always add more attributes or new actions to a Choco class
const targetId = "123";
this.target.extendAttributes({ id: targetId });
this.extendAttributes({ "aria-controls": targetId });
}
}
const disclosure = new Disclosure();
</script>
<div class="my-8 grid grid-cols-2 items-center justify-center gap-2 text-center">
<button class="cursor-pointer py-2 px-4 outline" use:choco={disclosure}>control</button>
{#if disclosure.active}
<span class="text-coral" transition:fly={{ y: 100 }} use:choco={disclosure.target}>target</span>
{/if}
</div>
<!-- Just to see what's going on -->
<div class="grid grid-cols-2">
<pre>{JSON.stringify(disclosure.attributes, null, 2)}</pre>
<pre>{JSON.stringify(disclosure.target.attributes, null, 2)}</pre>
</div>
Notice that we used the extendAttribute
from the ChocoBase
class. Here it allows us to programmatically add correlated aria and attributes between the
control and the target. Similarly, there is an extendAction
method on ChocoBase
which allows to add more behavior to any class.
We’ve just created our simple headless Disclosure
in a few lines of code, thanks to
the Triggerable
building block. We could go further by generating the id automatically
and allowing to bind options.
API
Constructor
The options of the Triggerable
class are similar to those of the Toggleable
. The class has two type constraints Triggerable<C,T>
for the control and target HTML tags. By default C="button"
and T="generic"
for any generic HTMLElement.
control
?: Record<string, Booleanish>- Initial booleanish state of the control
target
?: Record<string, Booleanish>- Initial booleanish state of the target
active
: boolean | () => boolean- Boolean or getter labelling the state as active or not. Can be bound
- Default:
false
setActive
?: (v: boolean) => void- Setter allowing to bind the active state value
toggle
?: EventName | EventName[]- Event(s) toggling the state
on
?: EventName | EventName[]- Event(s) triggering the active state
off
?: EventName | EventName[]- Event(s) triggering the inactive state
Omit<ToggleableOptions, "initial">