Panel API
Everything you can call on a Panel.
Constructor
new Panel(elementOrSelector: HTMLElement | string, options?: PanelConfig)
Builds a Panel on a single element, from a selector or an element reference. Reach for this when you want a handle on one panel. To wire up many at once, Panel.init() (further down) is less typing.
Parameters:
- elementOrSelector
- A CSS selector string or HTMLElement reference to the
[data-panel] element. - options (optional)
- A configuration object. See Panel - Configuration for all options.
const panel = new Panel('#my-panel');
const panel = new Panel('#my-panel', { axis: 'horizontal' });
const panel = new Panel(document.getElementById('my-panel'));
Instance methods
panel.open(event?): Promise<void>
OOpen the panel. Nothing happens if it is already open.
Parameters:
- event (optional)
- The triggering event. When passed,
autoFocusonly fires on keyboard events. Mouse clicks are ignored, preventing unwanted scroll.
Returns:
A promise that resolves once the opening transition has finished.
panel.close(): void
Close the panel. Nothing happens if it is already closed.
panel.toggle(event?): void
Open the panel if it is closed, close it if it is open. If you catch it mid-close, toggle reverses and opens it again.
Parameters:
- event (optional)
- The triggering event. Used for keyboard detection.
panel.onBeforeOpen(handler, options?): void
Register a handler that runs just before the panel opens, which is where content loading goes. Return a promise from it and the open waits for that promise to settle. It runs before every open unless you pass once: true.
Parameters:
- handler
(el: HTMLElement, signal: AbortSignal) => Promise<void> | void: Return a promise to delay opening.- options (optional)
{ once?: boolean }: Iftrue, the handler is skipped after the first successful load (dataset.loaded === 'true').
panel.onBeforeOpen(async (el, signal) => {
const html = await fetch('/api/content', { signal }).then(r => r.text());
el.querySelector('.panel-wrapper').innerHTML = html;
}, { once: true });
You can pass a named function instead of an inline one. It keeps the call site tidy, and it lets you reuse the same loader across several panels.
async function loadContent(el, signal) {
const html = await fetch('/api/content', { signal }).then(r => r.text());
el.querySelector('.panel-wrapper').innerHTML = html;
}
panel.onBeforeOpen(loadContent, { once: true });
panel.setStatic(value: boolean): void
Force the panel into (or out of) its static state: plain expanded content instead of a collapsible disclosure. This overrides the static media query, so use it for a breakpoint the library cannot see, such as a container query or your own breakpoint system.
Switching never animates, and going back to collapsible lands the panel closed. See the static option.
panel.destroy(): void
Destroy it. It aborts any animation in progress, removes its event listeners (including the static media query watcher), resets the element to its closed state, and clears the element.panel reference so the element can be initialised again.
Instance properties
panel.isOpen: boolean
Read-only. true while the panel is open, or part-way through opening.
panel.isStatic: boolean
Read-only. true while the panel is plain expanded content rather than a disclosure.
panel.element: HTMLElement
Read-only. The [data-panel] element itself.
panel.config: PanelConfig
Read-only. The merged configuration. Precedence runs least specific to most: defaults first, then constructor options, then data attributes.
Static methods
Panel.init(selectorOrOptions?, options?): Panel[]
Find every panel matching the selector and initialise the lot in one call. It also connects implicit [data-panel-trigger] / [data-panel] pairs that sit next to each other.
Parameters:
- selectorOrOptions (optional)
- CSS selector string, or a config object (uses
'[data-panel'] selector). - options (optional)
- Config object, only used when the first argument is a selector string.
Returns:
An array of the Panel instances it created.
Panel.init();
Panel.init({ debug: true });
Panel.init('[data-panel]', { axis: 'vertical' });
Panel.defaults: PanelConfig
Static property. The default config handed to every new instance. Change it here to move the defaults for the whole page at once.
Panel.defaults.axis = 'vertical';
Panel.defaults.debug = true;
TypeScript types
import {
Panel,
type PanelConfig,
type PanelBeforeOpenEventDetail,
type PanelEventDetail,
type AsyncOpenHandler,
} from 'panelset';
const panel = new Panel('#my-panel');
panel.element.addEventListener('panel:opened', e => {
const event = e as CustomEvent<PanelEventDetail>;
console.log(event.detail.trigger);
});
const config: PanelConfig = {
axis: 'horizontal',
transitions: true,
autoFocus: 'first',
returnFocus: true,
persist: true,
};
const panel = new Panel('#my-panel', config);