A personal note from EY:
This library is a cumulation of ~20 years of experience — from writing static HTML pages as someone who just needed a website, to building fully functional CMS systems when needed.
What I always needed was JavaScript. And for a while, jQuery did the trick, but I was looking for something that handled event delegation without me even knowing the concept — I simply knew what I needed: no add- & remove Listener chaos, just because i needed some interactive buttons or input elements.
jQuery couldn't quite deliver that. Or rather, it technically could, but I couldn't figure out how to do event delegation properly.
Then, over 10 years ago, I discovered the pretty unspectacular handleEvent interface. My entire JavaScript approach instinctively shifted towards event delegation (still without knowing its formal name).
The first thing I did on new projects since: I created a minimalistic version of what YEH does today — though not even close to what YEH can do now.
At the end, it does event delegation — a concept older than JavaScript itself, presumably even older than me.
BTW, now I know, and I admit it, in the first few years I didn't even implement it properly because i didn't knew how and there were no tutorials at all. Or maybe there were a few, but a few was as good as none back in the days. And with that out of the way:
Advanced web components with YEH (Yai Event Hub) - Enterprise-grade tabs with efficient event delegation
Build deeply nested, event-heavy interfaces with constant-time listener delegation and zero manual lifecycle handling. Everything you need in one package.
- Event Delegation – One listener per event type per container, even across X nested components
- YEH Integrated – Event hub included directly in
@yaijs/corepackage - Enterprise Tabs – Feature-complete with accessibility, dynamic loading, routing, animations
- Pure ESM – Works from
file://, CDN, or bundler with zero build required - Event Hub Pattern – Turn any tab into a complete application event system
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@yaijs/core@latest/tabs/yai-tabs.css">
</head>
<body>
<div data-yai-tabs data-theme="default">
<nav data-controller>
<button data-tab-action="open" data-open="1">Tab 1</button>
<button data-tab-action="open" data-open="2">Tab 2</button>
</nav>
<div data-content>
<div data-tab="1">Content 1</div>
<div data-tab="2">Content 2</div>
</div>
</div>
<script type="module">
import { YaiTabs } from 'https://cdn.jsdelivr.net/npm/@yaijs/core@latest/dist/yai-bundle.js';
new YaiTabs();
</script>
</body>
</html>npm install @yaijs/coreimport { YaiTabs, YEH } from '@yaijs/core';
const tabs = new YaiTabs({
defaultBehavior: 'fade',
autoFocus: true
});
// Or extend YEH directly for custom event orchestration
class AppBus extends YEH {
constructor() {
super({ '#app': ['click', 'input', 'change'] });
}
}- Scope-aware event delegation
- Automatic target resolution for nested elements
- Built-in throttle/debounce helpers
- Chainable API (
.on().emit()) - Multi-handler resolution
- Performance metrics and stats
Complete YaiTabs Documentation → | Live Demo →
- 9 animation behaviors (fade, slide, zoom, flip, blur, etc.) + instant mode
- 4 navigation positions (top, right, bottom, left)
- WCAG 2.1 AA compliance with full ARIA support
- Hash-based routing with state preservation
- Dynamic content loading via
data-urlwith abort controllers - Touch/swipe navigation (YaiTabsSwipe)
- Built-in hooks:
tabOpened,tabReady,eventClick,eventInput, etc.
- YaiInputUtils – Headless form utilities with validation, counters, and keyboard shortcuts (Demo →)
- YaiTabsSwipe – Circular navigation, nested ascend/descend, axis locking
- YaiViewport – Observer-free visibility tracking with throttled events
- YaiAutoSwitch – Automated tab cycling for demos (bundle-full only)
YaiTabs doubles as an application event hub. Add any event type and get automatic hooks:
const tabs = new YaiTabs({
events: {
setListener: {
'[data-yai-tabs]': ['click', 'keydown', 'input', 'change', 'submit']
}
}
});
// All events are automatically available as hooks
tabs.hook('eventClick', ({ event, target, container, action }) => {
console.log('Click action:', action); // Extracted from data-click
});
tabs.hook('eventInput', ({ event, target, container, action }) => {
console.log('Input action:', action); // Extracted from data-input
});
tabs.hook('tabOpened', ({ detail }) => {
console.log('Tab opened:', detail.id);
});Multiple hooks per event:
tabs
.hook('tabOpened', (ctx) => trackAnalytics(ctx))
.hook('tabOpened', (ctx) => updateUI(ctx))
.hook('tabOpened', (ctx) => loadContent(ctx));- Documentation Hub – Complete framework documentation
- YaiTabs Guide – Component reference with examples
- Utilities Overview – YaiTabsSwipe, YaiViewport utilities
- YEH Event Hub – Event system foundation
- Interactive Demo – 50+ nested components with all features
- Performance Benchmark – Stress test with 400+ nesting levels
- YaiInputUtils Demo – Headless input tools
- JSFiddle
– Quick start playground, Challenge: Copy the component and paste it into
data-tab="1"ordata-tab="2". And repeat the step in each pasted component. But set your expectations first, what's your first thought? And share your final conclusion.
- Modern ES Modules: Opera 48+, Chrome 61+, Firefox 60+, Safari 11+, Edge 16+
- Tested: Safari 15.6 (macOS 2015), Chrome 106 (Android), Opera/Chrome/Brave/Firefox (Ubuntu 24.04)
- Legacy: Use bundler with polyfills for older browsers
- GitHub Repository – Source code and issues
- NPM Package – Install via npm
- Report Issues – Bug reports and feature requests
- GitHub Pages – Live documentation site
- Engin Ypsilon
License: MIT