feat: final production polish — light mode rebuild, lt.init(), cross-tab theme

Light mode — complete rebuild (section 51):
- Full token override for every surface, component, and state
- Desaturated accents: orange #c44e00, cyan #0062b8, green #006d35 etc.
- Glows replaced with subtle drop-shadow rings (no neon on white)
- Covers: toasts, modals, dropdowns, notification panel, context menu,
  right drawer, combobox, typeahead, wizard, timeline, pagination, tabs,
  badges, tables, code blocks, skeleton, avatar, sortable, markdown,
  scrollbars, buttons, nav drawer, WS status — nothing missed
- Dot-grid: neutral gray (was incorrect blue tint)
- Toast background uses var(--bg-overlay) instead of hardcoded dark rgba

Theme system improvements:
- _applyTheme now sets document.documentElement.style.colorScheme
- theme-color meta tag syncs on toggle (browser chrome follows theme)
- Cross-tab sync via storage event (toggle in one tab updates others)

lt.init() master initializer:
- Single call wires accordion, tooltip, alerts, clipboard, sidebar,
  submenus, and boot sequence
- Replaces 6+ individual .init() calls in user code
- demo HTML updated to use lt.init({ bootName: 'MY APP' })

Accessibility:
- Ticket table: add <caption class="lt-sr-only"> for WCAG compliance
- Table gets aria-label attribute

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-26 00:12:04 -04:00
parent 1d8d274fdd
commit d5dc96178f
3 changed files with 406 additions and 51 deletions
+45
View File
@@ -1462,7 +1462,11 @@
const _themeKey = 'lt_theme';
function _applyTheme(t) {
document.documentElement.setAttribute('data-theme', t);
document.documentElement.style.colorScheme = t;
try { localStorage.setItem(_themeKey, t); } catch(_) {}
// Sync theme-color meta for browser chrome
const metaTheme = document.querySelector('meta[name="theme-color"]');
if (metaTheme) metaTheme.setAttribute('content', t === 'light' ? '#edf0f5' : '#030508');
document.querySelectorAll('.lt-theme-btn').forEach(btn => {
btn.textContent = t === 'light' ? '◐' : '☀';
btn.setAttribute('aria-label', t === 'light' ? 'Switch to dark mode' : 'Switch to light mode');
@@ -1480,6 +1484,10 @@
let saved; try { saved = localStorage.getItem(_themeKey); } catch(_) {}
if (!saved) _applyTheme(e.matches ? 'light' : 'dark');
});
// Sync theme across tabs via storage event
window.addEventListener('storage', e => {
if (e.key === _themeKey && e.newValue) _applyTheme(e.newValue);
});
const theme = {
toggle: () => _applyTheme(document.documentElement.getAttribute('data-theme') === 'light' ? 'dark' : 'light'),
set: t => _applyTheme(t),
@@ -2655,10 +2663,47 @@
},
};
/* ================================================================
MASTER INIT
lt.init(opts?)
Call once after DOM ready. Runs all standard auto-init modules.
Opts: { boot: bool, bootName: str, tooltip: bool, accordion: bool,
alerts: bool, clipboard: bool, sidebar: bool, submenus: bool }
Individual modules can still be called manually.
================================================================ */
function ltInit(opts) {
const o = Object.assign({
boot: true,
bootName: null,
tooltip: true,
accordion: true,
alerts: true,
clipboard: true,
sidebar: true,
submenus: true,
}, opts || {});
if (o.accordion) accordion.init();
if (o.tooltip) tooltip.init();
if (o.alerts) alerts.init();
if (o.clipboard) initCopyButtons();
if (o.sidebar) initSidebar();
if (o.submenus) initSidebarSubmenus();
if (o.boot) {
const bootEl = document.getElementById('lt-boot');
if (bootEl) {
const name = o.bootName || bootEl.dataset.appName || document.title.split('—')[0].trim();
boot.run(name);
}
}
}
/* ================================================================
PUBLIC API
---------------------------------------------------------------- */
global.lt = {
/* Master initializer */
init: ltInit,
/* Core */
escHtml,
toast,