Enhancement
Toggle
Show and hide a target element from one or more trigger buttons
- Import
@parallelogram-js/core/components/Toggle- Selector
[data-toggle]- Stylesheet
@parallelogram-js/core/styles/toggle.css
Playground
Toggles in the same group close each other.
Yes, up to 48 hours before your booking.
Tables of up to twelve can be booked online.
<div class="accordion">
<button type="button" data-toggle data-toggle-target="#refunds" data-toggle-group="faq">Can I get a refund?</button>
<div id="refunds"><p>Yes, up to 48 hours before your booking.</p></div>
<button type="button" data-toggle data-toggle-target="#groups" data-toggle-group="faq">Do you take group bookings?</button>
<div id="groups"><p>Tables of up to twelve can be booked online.</p></div>
</div>
Use the example to see the events it sends.
Yes, up to 48 hours before your booking.
Tables of up to twelve can be booked online.
About
This is the disclosure pattern: triggers get aria-expanded and an aria-controls link to the target, which is given an id when it has none. The target has the open class while open and the hidden attribute while closed. The shipped stylesheet keeps closed targets hidden whatever display page styles give them, leaves open targets their own display, and animates the change. Toggle waits for those animations instead of a fixed delay, so the duration lives only in CSS.
Toggles are independent unless they share a group, in which case opening one closes the others. A capture toggle, such as a dropdown, also closes when the user clicks or moves focus outside it. Escape closes the open toggle that holds focus and returns focus to its trigger, and following a page link inside an open target closes it. Unmounting a trigger puts back the attributes Toggle gave it, and unmounting the last trigger for a target does the same for the target.
Toggle closes targets when it mounts, so a target that starts closed shows until then and the page jumps. Write data-toggle-state="closed" on the target in the markup to hide it from the first paint instead. The stylesheet only hides it while scripts are enabled, so it still shows without JavaScript, and it shows again if Toggle fails to load, though not if Toggle is never registered.
For new dropdowns consider <button popovertarget> with popover, and for accordions Accordion, which animates <details name="…">; both work without JavaScript.
Accessibility
Triggers must be buttons. Toggle sets aria-expanded and aria-controls, closes on Escape and returns focus to the trigger that opened the target.
Usage
Register the component and the framework loads it the first time a page contains [data-toggle].
import { Parallelogram } from '@parallelogram-js/core';
const app = Parallelogram.create();
app.components.add('[data-toggle]', () => import('@parallelogram-js/core/components/Toggle'));
app.run();
The framework is optional. Toggle.enhanceAll() mounts the component on every matching element by itself, for a page that wants one enhancement rather than a framework:
import Toggle from '@parallelogram-js/core/components/Toggle';
Toggle.enhanceAll();
It takes a selector and the component's options, and returns the instance it mounted them with. What it leaves out is what the framework adds: loading a component only on the pages that use it, mounting again after a page swap, and ordering with dependsOn.
Its styles come from the package stylesheet:
@import '@parallelogram-js/core/styles/toggle.css';
Attributes
| Name | Type | Default | Description |
|---|---|---|---|
data-toggle | flag | none | Marks a button as a trigger |
data-toggle-targetrequired | selector | none | The element the trigger shows and hides |
data-toggle-group | string | none | Toggles that share a group name close each other |
data-toggle-capture | boolean | false | Close on a click or focus outside the trigger and target For every instance, Toggle.defaults.capture. |
data-toggle-close-navigation | boolean | true | Close when a page link inside the target is followed For every instance, Toggle.defaults.closeOnNavigation. |
data-toggle-close-escape | boolean | true | Close with Escape while focus is in the trigger or target, or rests on the page For every instance, Toggle.defaults.closeOnEscape. |
data-toggle-manual | boolean | false | Close only from a trigger or the group; also allowed on the target For every instance, Toggle.defaults.manual. |
data-toggle-animate | boolean | true | Wait for the stylesheet's animations before changing state For every instance, Toggle.defaults.animateToggle. |
data-toggle-enhancedset by the component | flag | none | Present on a trigger while Toggle is mounted on it |
data-toggle-stateset by the component | closed | opening | open | closing | none | The target's state. Write closed in the markup to hide a target that starts closed before Toggle loads On target. |
Events
| Name | Detail | Description |
|---|---|---|
toggle:show | { target: HTMLElement; trigger: HTMLElement; timestamp: number } | Dispatched on the trigger when its target opens DOM event and event bus |
toggle:hide | { target: HTMLElement; trigger: HTMLElement; timestamp: number } | Dispatched on the trigger when its target closes DOM event and event bus |
toggle:mount | { element: HTMLElement; target: HTMLElement; isOpen: boolean; timestamp: number } | A trigger was set up Event bus |
CSS custom properties
| Name | Default | Description |
|---|---|---|
--toggle-transition-duration | 0.75s | Length of the open and close animations |
--toggle-transition-easing | none | Easing of the open and close animations |