geUI Showcase
Every method in geUIHelper and icx is exercised here — tabs, accordion, modal, form, toast, keyboard shortcuts, theme, DOM helpers, and the geDropdown extension pattern from the README.
icx.icon(name) + [data-icon]
Icons are used two ways. Declarative: <svg data-icon="name"> in HTML, hydrated by icx.replace() on boot. Programmatic: icx.icon('name') returns an SVG string for injection — the grid below is built entirely via JS.
geUIHelper.toast(msg, type, duration)
Toasts are appended to a .toast-container (auto-created) and auto-dismiss. Duration defaults to 3000 ms.
geUIHelper.tabs('.tabmenu')
Full ARIA support. Navigate with ← → arrow keys, Home, End.
geUI Overview
A lightweight, opinionated UI helper for modern vanilla JS. No dependencies, tree-shakeable, full ARIA keyboard navigation built-in.
Quick Start
import geUIHelper from './geui.js';
import icx from './ge-icon.js';
document.addEventListener('DOMContentLoaded', () => {
icx.replace(); // hydrate [data-icon]
geUIHelper.tabs('.tabmenu'); // init tabs
geUIHelper.accordion('.accordion'); // init accordion
});
Key APIs
geUIHelper.el()
geUIHelper.toast()
geUIHelper.modal()
geUIHelper.tabs()
geUIHelper.onKey()
icx.icon()
icx.replace()
Icon Usage
Two approaches:
// Declarative — [data-icon] in HTML, replace() on boot
<svg data-icon="check"></svg>
// Programmatic — inject SVG string from JS
el.innerHTML = icx.icon('trash', 'my-class');
geUIHelper.accordion('.accordion')
data-single on .accordion collapses siblings on open. Navigate with ↑ ↓ arrow keys, Escape closes.
geUIHelper auto-initialises on import via a static class block. It reads localStorage first, then falls back to prefers-color-scheme. The result is applied as data-theme on <html>.
class geMenu extends geUIHelper { ... }. Your subclass inherits all base methods while you add domain-specific helpers. See the geDropdown section below.
icons.html in a browser — it's a visual SVG editor. Add, rename, or delete icons there, then click Export icons.js and replace the file. Never hand-edit icons.js directly.
geUIHelper.modal('open' | 'close' | 'destroy', id)
Uses .overlay + .modal from base.css. Focus is trapped while open (Tab / Shift+Tab cycle). Escape closes. Click the backdrop to dismiss.
geUIHelper.handleForm(formEl, async (data) => ...)
handleForm wires HTML5 validation, calls your async handler on valid submit, shows a success toast and resets the form on { ok: true }. prepareForm auto-assigns IDs to un-labelled fields.
geUIHelper.copy(btn, target, options?)
Wires a button to copy the contents of a textarea or pre using execCommand('copy') — no clipboard permission required. The button label swaps briefly to confirm, then restores.
geUIHelper.copy(btn, target);
geUIHelper.copy(btn, target, { success: '✓ Done', duration: 2000 });
All six methods operate on the target paragraph below. Watch it respond.
I am the util target. Manipulate me with the buttons below.
geUIHelper.onKey(combo, fn)
Supports single keys, modifier combos, and Ctrl+Shift combinations. Registered globally. Escape is wired automatically to close any active modal.
geUIHelper.setTheme() / getCurrentTheme()
Theme is stored in localStorage and applied via data-theme on <html>. Auto-initialises from user preference on first load. Click the sun/moon button in the header, or use Ctrl+Shift+D.
class geDropdown extends geUIHelper { ... } — your subclass inherits all base methods. Add static initDropdown() as a domain-specific helper. Then call geDropdown.initDropdown('.ken-dropdown-trigger') in your entry point.
// ken.js — extension pattern from README-js.md
class geDropdown extends geUIHelper {
static initDropdown(triggerSelector) {
geUIHelper.els(triggerSelector).forEach(trigger => {
const menu = trigger.nextElementSibling;
geUIHelper.on(trigger, 'click', e => {
e.stopPropagation();
geUIHelper.toggleClass(menu, 'active');
});
});
document.addEventListener('click', () => {
geUIHelper.els('.ken-dropdown-menu.active')
.forEach(m => geUIHelper.removeClass(m, 'active'));
});
}
}
| Method | Returns | Notes |
|---|---|---|
geUIHelper.el(sel) |
Element | null | querySelector shorthand |
geUIHelper.els(sel) |
Element[] | querySelectorAll → spread array |
geUIHelper.show(el) |
void | Removes inline display:none |
geUIHelper.hide(el) |
void | Sets style.display = 'none' |
geUIHelper.toggle(el) |
void | Flips between show / hide |
geUIHelper.addClass(el, cls) |
void | classList.add with null guard |
geUIHelper.removeClass(el, cls) |
void | classList.remove with null guard |
geUIHelper.toggleClass(el, cls) |
void | classList.toggle with null guard |
geUIHelper.on(el, ev, fn) |
void | addEventListener with null guard |
geUIHelper.onKey(combo, fn) |
handler fn | 'Ctrl+S', 'Escape', 't', etc. |
geUIHelper.setTheme(t) |
void | 'dark' | 'light' → persisted |
geUIHelper.getCurrentTheme() |
'dark' | 'light' | Reads data-theme attribute |
geUIHelper.toast(msg, type, ms) |
void | type: success | error | info | warning |
geUIHelper.modal(action, id) |
void | action: open | close | destroy |
geUIHelper.tabs(sel) |
void | ARIA tablist + keyboard nav |
geUIHelper.accordion(sel) |
void | data-single for exclusive mode |
geUIHelper.handleForm(form, fn) |
void | HTML5 validation + async submit |
geUIHelper.prepareForm(form) |
void | Auto-assign ids to un-labelled fields |
geUIHelper.copy(btn, target, opts?) |
void | execCommand copy — no clipboard permission needed |
geUIHelper.error(msg, err) |
void | console.error + error toast |
icx.icon(name, classes?) |
string | SVG HTML string for innerHTML |
icx.replace() |
void | Hydrate all [data-icon] in DOM |
icx.delayreplace(sel) |
void | Hydrate [data-icon] in a subtree |