skill
Adom UI Design System
Public Made by Adomby adom
How the AI builds and tests interfaces people love to use in Adom. Ships as one installable skill that bundles focused skills (tooltips, floating-windows, toasts, responsive-ui, app-shell, ai-driven-apps, clickable-paths).
← Commit history
newbie-panel 2.25.0: one live send toast narrated by Hydrogen's run-prompt status (human line + progress bar), terminal succeeded/failed honoured, delivered = sent, the AI named
1 file changed
+36−8
assets/module/newbie-panel.js+36−8@@ -101,7 +101,10 @@ .anp-toast.err{border-left:3px solid #f85149;} .anp-toast.info{border-left:3px solid #00b8b1;} @keyframes anp-in{from{opacity:0;transform:translateY(6px);}to{opacity:1;transform:none;}}-@media (prefers-reduced-motion:reduce){.anp-toast{animation:none;}}+.anp-toast{position:relative; overflow:hidden;}+.anp-toast-bar{position:absolute; left:0; right:0; bottom:0; height:3px; background:rgba(255,255,255,.08);}+.anp-toast-bar i{display:block; height:100%; width:0; background:#00b8b1; transition:width .4s ease;}+@media (prefers-reduced-motion:reduce){.anp-toast{animation:none;} .anp-toast-bar i{transition:none;}} .anp-tip{position:fixed; z-index:99999; pointer-events:none; padding:6px 9px; border-radius:6px; background:#0d1117; border:1px solid #30363d; color:#e6edf3; text-transform:none;@@ -206,7 +209,17 @@ toastHost.appendChild(t); /* retextable, so a long send can narrate its phases in ONE toast instead of * stacking six of them on top of each other. */- t.setText = function (next) { t.innerHTML = esc(next); return t; };+ t.setText = function (next) { t.innerHTML = esc(next); if (t._bar) t.appendChild(t._bar); return t; };+ /* A live send narrates ONE toast: the text comes from Hydrogen's status route (`human`)+ * and the thin bar from its `progress` (John 2026-09-07: "better state and progress+ * information back to the caller"). */+ t.setProgress = function (p) {+ if (typeof p !== 'number') return t;+ if (!t._bar) { t._bar = el('div', 'anp-toast-bar'); t._bar.appendChild(el('i')); t.appendChild(t._bar); }+ t._bar.firstChild.style.width = Math.round(Math.max(0, Math.min(1, p)) * 100) + '%';+ return t;+ };+ t.setKind = function (k) { t.className = 'anp-toast ' + (k || 'info'); return t; }; setTimeout(function () { t.remove(); }, ms || (kind === 'err' ? 7000 : 4000)); return t; }@@ -310,7 +323,15 @@ hint: 'Your AI chat opened. This app does not proxy GET ' + '/ai-threads/run-prompt/status yet, so progress cannot be shown.' }); var state = (st.job && st.job.state) || '';- if (typeof onProgress === 'function') { try { onProgress(state, st.job); } catch (e) {} }+ if (typeof onProgress === 'function') { try { onProgress(state, st.job, st); } catch (e) {} }+ /* Hydrogen 1.0.240+ says it outright: terminal + succeeded/failed, with a+ * ready `human` line. Codex, Kimi and Antigravity end in `delivered`. */+ if (st.terminal === true) {+ if (st.succeeded === true || state === 'delivered') return resolve({ state: 'delivered', phase: state, ai: st.ai, surface: st.surface });+ if (st.failed === true) return resolve({ state: 'failed', phase: state, ai: st.ai,+ hint: st.human || (st.error && (st.error.error || st.error)) || state });+ }+ if (state === 'delivered') return resolve({ state: 'delivered', phase: state, ai: st.ai }); /* working or later IS sent, for the user-facing toast. */ if (state === 'working' || state === 'done' || state === 'needs_you' || state === 'still_working') return resolve({ state: 'delivered', phase: state });@@ -406,12 +427,19 @@ if (sd.disabled) return; sd.disabled = true; var pending = toast('Opening a new AI thread…', 'info', 120000);- send(base, phrase, appName, slug, function (state, job) {- if (PHASE[state]) pending.setText(PHASE[state]);- if (typeof cfg.onProgress === 'function') { try { cfg.onProgress(state, job); } catch (e) {} }+ pending.setProgress(0.02);+ send(base, phrase, appName, slug, function (state, job, st) {+ /* Prefer Hydrogen's own words (they name the AI: "opening a Codex thread",+ * "delivered to Antigravity"); the PHASE table is the pre-1.0.240 fallback. */+ var line = (st && st.human) ? (st.human.charAt(0).toUpperCase() + st.human.slice(1) + '…') : PHASE[state];+ if (line) pending.setText(line);+ if (st && typeof st.progress === 'number') pending.setProgress(st.progress);+ if (typeof cfg.onProgress === 'function') { try { cfg.onProgress(state, job, st); } catch (e) {} } }, cfg.ai).then(function (r) { pending.remove();- if (r.state === 'delivered') toast('Sent. Your AI thread has the prompt.', 'ok');+ var who = r.ai ? r.ai : 'your AI';+ if (r.state === 'delivered') toast('Sent to ' + who + '. The thread has your prompt' + (r.surface === 'tab' ? ', in an editor tab.' : '.'), 'ok', 5000);+ else if (r.state === 'failed') toast((r.hint || 'The send failed.') + ' Check your AI threads before sending again.', 'err', 9000); else toast('Thread opened, delivery not confirmed. Check your AI threads before sending again.', 'info', 8000); }).catch(function (err) { pending.remove();@@ -733,6 +761,6 @@ } root.AdomNewbiePanel = { mount: mount, toast: toast, selfCheck: selfCheck, copyText: copyText,- checkSend: checkSend, version: '2.24.0',+ checkSend: checkSend, version: '2.25.0', TWO_COL_MIN: TWO_COL_MIN, PHRASE_BUDGET: PHRASE_BUDGET }; })(typeof window !== 'undefined' ? window : this);