JavaScript

How Byteion's vanilla-JS behaviour layer works — auto-init, subpath imports, manual control, utilities.

Overview

@byteion/js is the vanilla-JS behaviour layer. Zero dependencies, no framework, no virtual DOM. You declare what an element is with a data-bi-* attribute; the JS finds it and wires it up.

For the full API surface, see the JavaScript API reference.

Auto-init

The simplest path. Import the package once at the top of your app — every data-bi-* element is wired automatically when the DOM is ready.

// In your app entry file
import '@byteion/js';

From the CDN bundle, auto-init runs automatically inside ByteionCore.init().

Subpath imports (tree-shake-friendly)

If you only need a handful of components, skip the auto-init entry and pull each behaviour from its own subpath. Bundlers tree-shake the rest:

// Per-component imports - only what you use ends up in the bundle
import { Modal }     from '@byteion/js/modal';
import { Dropdown }  from '@byteion/js/dropdown';
import { Popover }   from '@byteion/js/popover';
import { Tabs }      from '@byteion/js/tabs';
import { Accordion } from '@byteion/js/accordion';
import { Tooltip }   from '@byteion/js/tooltip';
import { Drawer }    from '@byteion/js/drawer';
import { Toast }     from '@byteion/js/toast';

// Wire one up manually
const modal = new Modal(document.querySelector('#confirm'));
modal.show();

All eight component subpaths ship their own .d.ts next to the JS, so you get types without any extra config.

Data attributes

AttributeUsed on
data-bi-modal="id"The modal container
data-bi-modal-toggle="id"A button that opens the modal
data-bi-modal-hideA button inside the modal that closes it
data-bi-dropdown="id"The dropdown menu
data-bi-tabsA tab list root
data-bi-tab-target="id"A tab trigger pointing at a panel
data-bi-drawer="id"An off-canvas drawer
data-bi-popover-toggle="id"A button that opens a popover

Manual init

If you are dynamically injecting markup, ask Byteion to re-scan a subtree:

import { ByteionCore } from '@byteion/js';

ByteionCore.init({ root: document.querySelector('#dynamic-content') });

Already-initialised elements are skipped, so calling init() repeatedly is safe.

Lifecycle

import { Modal } from '@byteion/js/modal';

const modal = new Modal(document.querySelector('#confirm'));
modal.show();
modal.hide();
modal.destroy();

Events

Components dispatch native CustomEvents on their root element:

document.querySelector('#confirm').addEventListener('bi:modal:show', (e) => {
  console.log('Modal opening', e.detail);
});

document.querySelector('#confirm').addEventListener('bi:modal:hidden', () => {
  console.log('Modal fully closed');
});

Utility subpaths

The same primitives the built-in components use are exported as standalone subpaths:

SubpathUse it for
@byteion/js/focus-trapTrap keyboard focus inside an overlay
@byteion/js/aria-helpersHelpers for ARIA state and live regions
@byteion/js/click-outsideClose popovers, dropdowns, comboboxes on outside click
@byteion/js/keyboard-navigationRoving tabindex + arrow-key nav for menus, tab lists
@byteion/js/dom-helpersMount/unmount hooks, dataset parsing, event delegation
import { createFocusTrap } from '@byteion/js/focus-trap';
import { onClickOutside } from '@byteion/js/click-outside';

const trap = createFocusTrap(panelEl);
trap.activate();

const stop = onClickOutside(panelEl, () => trap.deactivate());

Unlock Premium Patterns

Get access to copy-paste ready Pro blocks, SaaS templates, and advanced component patterns.

Explore Pro Components