geUI + geIcon Showcase
All APIs Demonstrated

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.

Icon Library — 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.

Declarative (data-icon):
Buttons
Icon-only:
Badges
primary success danger warning muted
Toast — geUIHelper.toast(msg, type, duration)

Toasts are appended to a .toast-container (auto-created) and auto-dismiss. Duration defaults to 3000 ms.

Tabs — geUIHelper.tabs('.tabmenu')

Full ARIA support. Navigate with ← → arrow keys, Home, End.

  • Overview
  • Usage
  • API
  • Icons

geUI Overview

A lightweight, opinionated UI helper for modern vanilla JS. No dependencies, tree-shakeable, full ARIA keyboard navigation built-in.

Zero deps ES Modules ARIA ready
Accordion — geUIHelper.accordion('.accordion')

data-single on .accordion collapses siblings on open. Navigate with ↑ ↓ arrow keys, Escape closes.

What is geUIHelper?
A static class with zero dependencies providing DOM helpers, theming, toast notifications, modal management, ARIA-compliant tabs and accordions, form validation wiring, and keyboard shortcut binding — all in a single file.
How does theme init work?
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>.
Can I extend geUIHelper?
Yes. Because it's a static class, extending it is just class geMenu extends geUIHelper { ... }. Your subclass inherits all base methods while you add domain-specific helpers. See the geDropdown section below.
How do I add icons?
Open 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.
Modal — 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.

Form — 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.

Copy — 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 });
DOM Utilities — show / hide / toggle / class

All six methods operate on the target paragraph below. Watch it respond.

I am the util target. Manipulate me with the buttons below.

Keyboard Shortcuts — geUIHelper.onKey(combo, fn)

Supports single keys, modifier combos, and Ctrl+Shift combinations. Registered globally. Escape is wired automatically to close any active modal.

Save document (demo)
Ctrl + S
Open search palette
Ctrl + K
Toggle dark / light theme
Ctrl + Shift + D
Fire a test toast
T
Close active modal (built-in)
Escape
Theme — 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.

Extension: geDropdown — extending geUIHelper
Per README-js.md: 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'));
    });
  }
}
Full API Reference
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