JavaScript API
Initialize and control interactive Byteion components with the behavior-only runtime.
Overview
@byteion/js is an optional, behavior-only runtime for interactive Byteion components. It activates modals, dropdowns, popovers, tabs, accordions, drawers, tooltips, and toasts by scanning for data-bi-* attributes in the DOM.
The runtime does not inject design styles — component appearance is governed by Tailwind utility classes. It does not manage application or business state. It manages DOM interaction state: open/closed UI, active tabs, ARIA attributes, keyboard navigation, focus trapping, and click-outside dismissal.
Static components such as Button, Card, Badge, Input, and Table do not require JavaScript. You can build complete layouts without loading the JS runtime. JavaScript is only needed when you want interactive behavior (modal open/close, dropdown toggle, tab switching, etc.).
Installation
npm
Requires@byteion/core (peer dependency).
npm install @byteion/js@0.2.0-beta.1
ESM import and initialization
import ByteionCore from '@byteion/js';
document.addEventListener('DOMContentLoaded', () => {
ByteionCore.init();
});
Initialization
ByteionCore.init() is called automatically on DOMContentLoaded. You only need to call it manually if you are using a module bundler or injecting HTML dynamically.
Full initialization
ByteionCore.init(); // Initialize all modules on the page
ByteionCore.init(rootElement); // Initialize only within a specific container
Initializing a single module
ByteionCore.Modal.init(); // Initialize only modals
ByteionCore.Dropdown.init(); // Initialize only dropdowns
ByteionCore.Popover.init(); // Initialize only popovers
ByteionCore.Tabs.init(); // Initialize only tab sets
ByteionCore.Accordion.init(); // Initialize only accordions
ByteionCore.Drawer.init(); // Initialize only drawers
ByteionCore.Tooltip.init(); // Initialize only tooltips
ByteionCore.Toast.init(); // Initialize only toasts
// Each accepts an optional root element for scoped initialization
ByteionCore.Modal.init(sectionElement);
init() is idempotent — calling it multiple times on the same element will not re-initialize already wired components. However, repeated unnecessary calls should be avoided for performance. After injecting new HTML with data-bi-* attributes, call init() again to wire the new content — the MutationObserver handles this automatically when enabled.
Data attributes
Interactive components are activated by adding data-bi-* attributes to HTML elements. The runtime scans for these attributes and wires behavior automatically.
Modal
| Attribute | On element | Purpose |
|---|---|---|
| data-bi-modal | Overlay <div> | Identifies the modal container. Value is used as the modal ID. |
| data-bi-modal-content | Inner <div> | Focus-trap boundary inside the modal. |
| data-bi-modal-toggle | <button> | Value = modal ID. Click toggles the modal. |
| data-bi-modal-hide | <button> | Value = modal ID (optional). Click hides the modal or the closest [data-bi-modal] ancestor. |
| data-bi-modal-static | Modal overlay | "true" disables backdrop-click and Escape dismiss. |
| data-bi-modal-keyboard | Modal overlay | "false" disables Escape dismiss only. |
Dropdown
| Attribute | On element | Purpose |
|---|---|---|
| data-bi-dropdown | Menu <div> | Identifies the dropdown menu container. |
| data-bi-dropdown-toggle | <button> | Value = dropdown ID. Click toggles the menu. |
Popover
| Attribute | On element | Purpose |
|---|---|---|
| data-bi-popover | Popover <div> | Identifies the popover container. |
| data-bi-popover-toggle | <button> | Value = popover ID. Click toggles the popover. |
Tabs
| Attribute | On element | Purpose |
|---|---|---|
| data-bi-tabs | Wrapper <div> | Identifies a tabset container. |
| data-bi-tabs-toggle | <button> | Value = panel ID. Click activates that panel. |
| data-bi-tabs-panel | Panel <div> | Identifies a tab panel. Value used as panel ID. |
Accordion
| Attribute | On element | Purpose |
|---|---|---|
| data-bi-accordion | Wrapper <div> | Identifies the accordion container. |
| data-bi-accordion-toggle | <button> | Value = panel ID. Click toggles that panel. |
| data-bi-accordion-panel | Panel <div> | Identifies a collapsible panel. |
| data-bi-accordion-multiple | Accordion wrapper | "true" allows multiple panels open simultaneously. |
| data-bi-accordion-chevron | Icon inside toggle | Gets rotate-180 class toggled on expand/collapse. |
Drawer
| Attribute | On element | Purpose |
|---|---|---|
| data-bi-drawer | Overlay <div> | Identifies the drawer container. |
| data-bi-drawer-toggle | <button> | Value = drawer ID. Click toggles the drawer. |
| data-bi-drawer-hide | <button> | Value = drawer ID (optional). Click hides the drawer or the closest [data-bi-drawer] ancestor. |
| data-bi-drawer-placement | Drawer overlay | "left" | "right" | "top" | "bottom". Default: "right". |
| data-bi-drawer-static | Drawer overlay | "true" disables backdrop-click and Escape dismiss. |
| data-bi-drawer-keyboard | Drawer overlay | "false" disables Escape dismiss only. |
Tooltip
| Attribute | On element | Purpose |
|---|---|---|
| data-bi-tooltip | Any element | Value = tooltip text content. The tooltip <div> is created programmatically. |
| data-bi-tooltip-placement | Any element | "top" | "right" | "bottom" | "left". Default: "top". |
Toast (declarative)
| Attribute | On element | Purpose |
|---|---|---|
| data-bi-toast | <div> | Identifies a declarative toast element in the DOM. |
| data-bi-toast-hide | <button> | Value = toast ID (optional). Click hides the referenced toast or the closest [data-bi-toast] ancestor. |
| data-bi-toast-fire | <button> | Value = JSON matching ToastInput. Click creates and shows a programmatic toast. |
Universal
| Attribute | On element | Purpose |
|---|---|---|
| data-bi-dismiss | <button> | Value = CSS selector. Click removes the closest matching ancestor element. If empty, removes the direct parent. |
Programmatic API
Each module exposes show, hide, toggle, and destroy methods for programmatic control. Targets can be an element reference, an ID string, or a CSS selector.
Modal
ByteionCore.Modal.show('#my-modal');
ByteionCore.Modal.hide('#my-modal');
ByteionCore.Modal.toggle('#my-modal');
Dropdown
ByteionCore.Dropdown.show('#menu-1');
ByteionCore.Dropdown.hide('#menu-1');
ByteionCore.Dropdown.toggle('#menu-1');
Popover
ByteionCore.Popover.show('#popover-1');
ByteionCore.Popover.hide('#popover-1');
ByteionCore.Popover.toggle('#popover-1');
Tabs
ByteionCore.Tabs.show('panel-2'); // Activate panel by panel ID
ByteionCore.Tabs.toggle('panel-2'); // Alias for show()
Accordion
ByteionCore.Accordion.show('section-1'); // Open panel (closes others unless multiple mode)
ByteionCore.Accordion.hide('section-1'); // Close panel
ByteionCore.Accordion.toggle('section-1'); // Toggle panel
Drawer
ByteionCore.Drawer.show('#my-drawer');
ByteionCore.Drawer.hide('#my-drawer');
ByteionCore.Drawer.toggle('#my-drawer');
Tooltip
ByteionCore.Tooltip.show(triggerElement); // Pass the trigger element
ByteionCore.Tooltip.hide(triggerElement);
Toast (programmatic)
Toasts are created programmatically via ByteionCore.Toast.show(). Accept a ToastInput object with title, message, variant (or tone), and optional duration:
// Success toast
ByteionCore.Toast.show({
title: 'Saved',
message: 'Your changes were saved.',
variant: 'success',
duration: 4000
});
// Error toast
ByteionCore.Toast.show({
title: 'Error',
message: 'Something went wrong.',
variant: 'danger',
duration: 8000
});
// Info toast (sticky — does not auto-dismiss)
ByteionCore.Toast.show({
title: 'New version',
message: 'v0.2.0 is available.',
variant: 'info',
duration: 0
});
// Hide a specific toast by its element reference
const toast = ByteionCore.Toast.show({ title: 'Hello', variant: 'primary' });
ByteionCore.Toast.hide(toast);
Not supported (use the declarative API instead)
- There is no
ByteionCore.init('modal')string-based dispatch. CallByteionCore.Modal.init()instead. - There is no
ByteionCore.toast.success()shortcut. UseByteionCore.Toast.show({ variant: 'success', ... }).
Events
The runtime dispatches CustomEvent instances on component elements. All events bubble and are cancelable. Use e.detail to access event-specific data.
| Event | Target | When it fires |
|---|---|---|
| bi:modal:show | Modal element | After the modal becomes visible. detail.modal contains the element. |
| bi:modal:hide | Modal element | After the modal becomes hidden. |
| bi:dropdown:show | Dropdown element | After the menu becomes visible. |
| bi:dropdown:hide | Dropdown element | After the menu becomes hidden. |
| bi:popover:show | Popover element | After the popover becomes visible. |
| bi:popover:hide | Popover element | After the popover becomes hidden. |
| bi:tabs:show | Tabset root | After a panel is activated. detail.panelId and detail.root available. |
| bi:accordion:show | Accordion root | After a panel is opened. detail.panelId available. |
| bi:accordion:hide | Accordion root | After a panel is collapsed. |
| bi:drawer:show | Drawer element | After the drawer becomes visible. |
| bi:drawer:hide | Drawer element | After the drawer becomes hidden. |
| bi:tooltip:show | Tooltip element | After the tooltip is created and positioned. |
| bi:tooltip:hide | Tooltip element | When the tooltip starts its hide animation. |
| bi:toast:show | Toast element | After the toast is appended to the container. |
| bi:toast:hide | Toast element | After the hide animation completes and the element is removed. |
Listening to events
// Track modal open/close for analytics
document.addEventListener('bi:modal:show', (e) => {
console.log('Modal opened:', e.detail.modal.id);
});
document.addEventListener('bi:modal:hide', (e) => {
console.log('Modal closed:', e.detail.modal.id);
});
// React to tab changes
document.addEventListener('bi:tabs:show', (e) => {
console.log('Tab activated:', e.detail.panelId);
});
Triggering behavior via custom events
You can also show or hide a component by dispatching the corresponding event on its element:
// Open a modal by dispatching an event
const modal = document.querySelector('[data-bi-modal="my-modal"]');
modal.dispatchEvent(new CustomEvent('bi:modal:show'));
// Close it
modal.dispatchEvent(new CustomEvent('bi:modal:hide'));
Accessibility behavior
The runtime manages ARIA attributes and keyboard behavior for interactive components. Here is what each module handles:
- Modal — Sets
role="dialog",aria-modal="true",aria-hidden, andtabindex="-1". Creates a focus trap inside[data-bi-modal-content]. Locks body scroll when open. Supports Escape key and backdrop-click to dismiss (configurable viadata-bi-modal-staticanddata-bi-modal-keyboard). - Dropdown — Sets
role="menu",aria-hidden. On the toggle:aria-haspopup="true",aria-controls, andaria-expanded. Supports Escape key to close (refocuses trigger) and click-outside dismissal. - Popover — Sets
role="dialog",aria-hidden. On the toggle:aria-haspopup="dialog",aria-controls,aria-expanded. Supports Escape key and click-outside dismissal. - Tabs — Sets
role="tab"on toggles withtabindexfor roving tabindex navigation. Setsrole="tabpanel"on panels. Supports arrow-key navigation (horizontal) and Enter/Space activation. Setsaria-selectedon the active toggle. - Accordion — Sets
aria-controlson each toggle. Togglesaria-expandedon open/close. No built-in keyboard navigation (relies on native button focus). - Drawer — Sets
role="dialog",aria-modal="true",aria-hidden. Creates a focus trap. Locks body scroll. Supports Escape key and backdrop-click to dismiss (configurable viadata-bi-drawer-staticanddata-bi-drawer-keyboard). - Tooltip — Sets
role="tooltip"on the generated tooltip element andaria-describedbyon the trigger. Activates on mouse enter and focus. Removes on mouse leave and blur. - Toast — Sets
role="status"on each toast. The toast container usesaria-live="polite"andaria-atomic="true". Toasts auto-dismiss after a configurable duration. Do not use toasts as the only indicator for critical validation errors.
Framework lifecycle examples
The runtime auto-initializes on DOMContentLoaded. If you are using a module bundler, you need to import and ensure init() runs. For frameworks like React and Vue that use @byteion/react or @byteion/vue, behavior initialization is handled internally by the framework packages. The examples below are only needed when using raw HTML with data-bi-* attributes inside a framework project.
Plain HTML
<script type="module">
import ByteionCore from '@byteion/js';
document.addEventListener('DOMContentLoaded', () => {
ByteionCore.init();
});
</script>
React (raw HTML usage)
import { useEffect, useRef } from 'react';
import ByteionCore from '@byteion/js';
function ModalContainer() {
const ref = useRef(null);
useEffect(() => {
ByteionCore.init(ref.current); // Scope init to this container
}, []);
return (
<div ref={ref}>
<button data-bi-modal-toggle="my-modal">Open</button>
<div id="my-modal" data-bi-modal class="...">...</div>
</div>
);
}
Vue (raw HTML usage)
<script setup>
import { onMounted, ref } from 'vue';
import ByteionCore from '@byteion/js';
const container = ref(null);
onMounted(() => {
ByteionCore.init(container.value);
});
</script>
<template>
<div ref="container">
<button data-bi-modal-toggle="my-modal">Open</button>
<div id="my-modal" data-bi-modal class="...">...</div>
</div>
</template>
Do and Don't
Do
- Call
ByteionCore.init()after the DOM is ready - Use
data-bi-*attributes for declarative behavior activation - Re-run
init()after injecting dynamic HTML — or rely on the built-inMutationObserver - Listen to
bi:*events for analytics, logging, and side effects - Keep styling in Tailwind/CSS — the JS runtime handles only behavior
Don't
- Use JS to patch design tokens or component styles — use Tailwind/CSS variables
- Initialize before the DOM exists — use
DOMContentLoadedor framework lifecycle hooks - Depend on toast messages for critical validation errors — toasts auto-dismiss and are not persistent
- Invent custom
data-bi-*attributes that the runtime does not recognize — they will be ignored - Duplicate behavior manually (e.g., writing your own focus trap) when the runtime already manages it
Related
- Modal Component — Modal markup and data attributes
- Dropdown Component — Dropdown with click-outside behavior
- Tabs Component — Tab set with arrow-key navigation
- Accordion Component — Collapsible panels
- Drawer Component — Off-canvas panel
- Tooltip Component — Hover/focus tooltips
- Toast Component — Notification toasts
- Accessibility — Keyboard and ARIA patterns
Unlock Premium Patterns
Get access to copy-paste ready Pro blocks, SaaS templates, and advanced component patterns.
Explore Pro Components