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
2.8.0: copy falls back to execCommand - navigator.clipboard rejects with NotAllowedError in ah's webview, so the only path the panel had was failing
3 files changed
+57−3
assets/module/newbie-panel.js+31−2@@ -139,6 +139,35 @@ return safe.replace(re, '<b>$1</b>'); } + /* ---- copy, with a fallback that does not need the async clipboard ------+ * navigator.clipboard.writeText needs a secure context AND, in several embedded webviews,+ * transient user activation plus a clipboard-write permission that is simply absent. In+ * ah's webview it rejects with NotAllowedError, so the ONLY path the panel had would fail+ * and the user got "Could not reach the clipboard" on a button that looks like it works.+ * The execCommand path is deprecated but synchronous, needs no permission, and works in+ * exactly the contexts the async API refuses. Try the modern one, fall back, and only then+ * report failure. */+ function copyText(text) {+ return new Promise(function (resolve, reject) {+ function legacy() {+ try {+ var ta = document.createElement('textarea');+ ta.value = text;+ ta.setAttribute('readonly', '');+ ta.style.cssText = 'position:fixed;top:0;left:-9999px;opacity:0';+ document.body.appendChild(ta);+ ta.select(); ta.setSelectionRange(0, ta.value.length);+ var ok = document.execCommand && document.execCommand('copy');+ ta.remove();+ ok ? resolve('legacy') : reject(new Error('execCommand refused'));+ } catch (e) { reject(e); }+ }+ if (navigator.clipboard && navigator.clipboard.writeText) {+ navigator.clipboard.writeText(text).then(function () { resolve('async'); }, legacy);+ } else legacy();+ });+ }+ /* ---- toasts ---------------------------------------------------------- */ var toastHost = null; function toast(msg, kind, ms) {@@ -275,7 +304,7 @@ tipFor(cp, 'Copy this phrase'); cp.addEventListener('click', function (e) { e.stopPropagation();- (navigator.clipboard ? navigator.clipboard.writeText(phrase) : Promise.reject())+ copyText(phrase) .then(function () { toast('Copied. Paste it to your AI.', 'ok'); }) .catch(function () { toast('Could not reach the clipboard. Select the phrase and copy it.', 'err'); }); });@@ -485,6 +514,6 @@ return { ok: ok, rows: rows }; } - root.AdomNewbiePanel = { mount: mount, toast: toast, selfCheck: selfCheck, version: '2.6.0',+ root.AdomNewbiePanel = { mount: mount, toast: toast, selfCheck: selfCheck, copyText: copyText, version: '2.8.0', TWO_COL_MIN: TWO_COL_MIN, PHRASE_BUDGET: PHRASE_BUDGET }; })(typeof window !== 'undefined' ? window : this);
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-ui-design",- "version": "2.7.0",+ "version": "2.8.0", "type": "skill", "description": "The Adom UI Design System plus a bundle of focused UI skills (tooltips, floating-windows, toasts, responsive-ui, app-shell, ai-driven-apps, clickable-paths, dark-default, input-feedback, settings-layout). One install drops the whole set of skill files onto your container, plus shared icon assets (the settings cog) so every Adom app draws the same glyph.", "dependencies": {},
skills/newbie-panel/SKILL.md+25@@ -952,6 +952,31 @@ the page. Check it by toggling: screenshot with the panel open and closed and compare the distance from the header to the first content row. It should be identical. +## ⛔ navigator.clipboard REJECTS IN AH'S WEBVIEW. THE COPY BUTTON NEEDS A FALLBACK.++Ralph-testing the copy button on two live dashboards in John's dock returned, on both:++```+toast: "Could not reach the clipboard. Select the phrase and copy it."+readText(): READ_BLOCKED:NotAllowedError+```++`navigator.clipboard.writeText` needs a secure context AND, in several embedded webviews,+transient user activation plus a clipboard-write permission that is simply absent. The module+had only that path, so the button looked like it worked and told the user it had failed.++**2.8.0 adds a `execCommand('copy')` fallback**: a hidden readonly textarea, select, copy,+remove. Deprecated but synchronous, needs no permission, and works in exactly the contexts the+async API refuses. Try the modern API, fall back, and only then report failure. `copyText` is+exported so a test can exercise the same path the button uses.++**Honest caveat on how this was found:** the click was synthetic (`btn.click()` from an eval),+and the async clipboard API can reject for a synthetic click that would succeed for a real+one. So the observed failure may overstate what a user hits. The fallback is correct+regardless: a copy button whose only path requires a permission the host may not grant is a+button that fails silently for some users, and there is no downside to the second path.+**Verify with a real click before claiming the user-facing bug is fixed.**+ ## ⛔ THE DOCK INSTALLS A PACKAGE. IT DOES NOT RESTART THE RUNNING PROCESS. **Publishing is not deploying, and installing is not running.** lbr found John's box serving