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
1.13.0: panel fully closes with a header TOGGLE; demo toolbar lives in the panel and never uses monospace; never ship title plus a custom tooltip
5 files changed
+68−22
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-ui-design",- "version": "1.12.1",+ "version": "1.13.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/dash-demo/SKILL.md+19−4@@ -65,12 +65,26 @@ A demo is a JSON list of steps. Everything else (player, audio, captions) is gen ## The player toolbar -Visible whenever the demo is running, hidden otherwise:+**It lives INSIDE the newbie panel, directly below the "Play the demo" button, in the left+column** (John's ruling, 2026-08-24). Not floating bottom-centre, not docked to the window,+not overlaying the page. The demo is launched from that button, so its transport belongs in+the same block: the user's eye never leaves the place they started.++Visible whenever the demo is running, absent otherwise (the button above it becomes the+disabled `Demo running` state, per **newbie-panel**): ```-[ ⏮ prev ] [ ⏯ play/pause ] [ ⏭ next ] | [ 🔊 mute ] | step 3/8 | [ ✕ exit ]+[ ⏮ ] [ ⏯ ] [ ⏭ ] [ 🔇 ] step 3/8 [ ✕ ] ``` +**Typography, and this is not optional: NEVER a monospace or Courier face anywhere in the+demo UI.** Pup shipped its toolbar and step counter in Courier and it read as a terminal+bolted onto a designed page. The toolbar uses the body face at **12.5px** for the step+counter (`var(--muted)`, `font-variant-numeric: tabular-nums` so `3/8` does not jitter as it+counts), and the controls are 16px line glyphs in 28x28 ghost buttons, the same buttons as+everywhere else. Monospace is reserved for genuine machine text (versions, paths, IDs), and a+step counter is not machine text.+ - **play/pause**: pause freezes the action where safe, pauses audio mid-word, keeps the caption up. Resume continues the same step. - **prev/next**: jump step boundaries. Audio for the old step stops instantly; the new@@ -78,8 +92,9 @@ Visible whenever the demo is running, hidden otherwise: - **exit**: stop everything, clear the ab caption, stop audio, restore whatever the demo moved (windows, tabs, state), return the dashboard to rest. Exit must be safe at ANY step - ralph-test it from the middle of the most destructive step.-- Toolbar style: house tokens, fixed bottom-center of the dashboard, small; it is a- remote control, not a feature. Buttons follow the input-feedback skill.+- Toolbar style: house tokens, in the panel's left column under the demo button, small; it+ is a remote control, not a feature. Buttons follow the input-feedback skill, and every one+ of them carries a tooltip and an aria-label like any other icon button. ## Where the demo lives on the page
skills/newbie-graduation/SKILL.md+8−7@@ -29,11 +29,11 @@ dashboard's newbie job is to hand the user to their AI. 1. **Fresh** (default on first visit): say strip expanded, getting-started panel open, demo buttons prominent. The dashboard teaches.-2. **Graduated**: each scaffold collapses to a single quiet line ("Say it - 6 phrases",- one row, tap to expand once). Getting-started and demo sections fold to their headings.- The app's real content moves up.-3. **Recallable**: the header's **?** (left of the gear, see dash-header) restores Fresh- for the current session, then the page folds back. Nothing is ever unreachable.+2. **Graduated**: the newbie panel CLOSES completely (no one-liner, no stub) and the app's+ real content moves up to fill the space. The header toggle is how it comes back.+3. **Recallable**: the header TOGGLE (left of the gear, see dash-header) brings the panel+ back, and pressing it again closes it. It is a true toggle with a visible pressed state,+ not a one-way restore. Nothing is ever unreachable. ## Graduation triggers (any one graduates that scaffold) @@ -78,8 +78,9 @@ when storage is empty or unreadable - the safe default is teaching. - The status LED row (see status-leds): health is not scaffolding. - The header, the gear, the ?.-- The say strip's collapsed one-liner: even a graduated page keeps one visible thread back- to "you can just say it".+- The header toggle: even a fully-closed panel leaves one visible, labelled way back to+ "you can just say it". That control is the thread back, which is why the panel itself may+ close completely. ## Ralph-test
skills/newbie-panel/SKILL.md+20−10@@ -111,14 +111,23 @@ instead of the boxes around them. ## Showing, hiding, bringing back - Fresh dashboards show the panel expanded (**newbie-graduation** State 1).-- ONE `✕`, top-right of the panel, collapses the WHOLE panel (heading, explainer, demo,- table) to a single quiet line: `Say it: 6 phrases`, tappable to expand for the session.- Never an X per section.-- The `?` in the header, left of the settings cog, restores the Fresh panel for the session.-- The collapsed one-liner never disappears entirely: it is the user's thread back to- "you can just say it".-- Auto-graduation folds it the same way a dismissal does; the localStorage key MUST be- namespaced with your app slug.+- ONE `✕`, top-right of the panel. It **FULLY CLOSES the panel: no residual one-liner, no+ stub, nothing left behind** (John's ruling, 2026-08-24: "when i close the newbie panel, i+ think it should fully close"). The app's own UI moves up to fill the space. An earlier+ version of this skill said it collapsed to a `Say it: 6 phrases` line; that is retired.+- **The header carries a TOGGLE that brings it back, and it behaves like a toggle**, not a+ one-way "show" button (John, same ruling: "if a header is going to have this button, which+ i like, it needs to act as a toggle button"). Requirements:+ - It sits left of the settings cog, 18px line glyph in a 28x28 ghost button.+ - It reflects state in at least TWO ways, per the **input-feedback** skill: `aria-pressed`+ true/false plus a visible difference (teal glyph and a subtle inset background when the+ panel is open, muted when closed). A toggle that looks identical in both states is a lie.+ - Its tooltip and `aria-label` change with state: `Hide the prompts panel` when open,+ `Show the prompts panel` when closed.+ - Pressing it when the panel is open closes it, exactly as the `✕` does. Both controls+ drive the same state; they never drift apart.+- The choice persists across reloads (namespaced localStorage, see **newbie-graduation**),+ and auto-graduation closes it the same way a dismissal does. ## Two traps that keep a full-width panel a column @@ -134,5 +143,6 @@ Found by chip-fetcher, the first app to convert: At 1400px: panel spans the content width, two columns with the hairline between them, every row exactly 40px, phrases truncating rather than wrapping, one filled button on the page. At 390px: one column, demo first, icons still in a 44px target. Hover both icons and read-the tooltips; click each and watch for the toast. Press `✕`, confirm the one-liner, reload,-confirm it stayed collapsed, press `?`, confirm Fresh returns.+the tooltips; click each and watch for the toast. Press `✕`, confirm the panel is GONE with no stub and the app UI moves up, reload, confirm+it stayed closed, press the header toggle, confirm the panel returns AND the toggle's own+appearance changed, press it again, confirm it closes.
skills/tooltips/SKILL.md+20@@ -27,6 +27,26 @@ thing you are trying to read, or shouting in all caps. This skill is the one cor > tiered to the owner HUD) are plausible-sounding ideas that keep getting reinvented and keep > breaking. Use the body-appended fixed-div renderer below and nothing else. +## ⚠ NEVER ship `title` AND a custom tooltip on the same element++Found live on 2026-08-24: hovering a Send-to-AI button produced TWO tooltips, the styled+Adom one and the browser's own native yellow box, overlapping each other.++The cause is always the same: the element carries a `title` attribute AND a custom tooltip+(`data-tooltip`, a JS handler, a component wrapper). The browser renders `title` natively+after its own delay, on top of yours, in its own style, at its own position, and it cannot+be styled or suppressed once it fires.++- **Pick ONE.** In an Adom app that is the custom tooltip, because it obeys the 600ms delay,+ the house styling, the z-index ladder and the viewport clamp.+- **Use `aria-label` for the accessible name**, never `title`, so screen readers get the text+ without the browser painting a second box.+- If a component library adds `title` for you, strip it (`el.removeAttribute('title')` after+ mount, or pass the prop that disables it).+- Audit before shipping: `document.querySelectorAll('[title][data-tooltip]')` must return+ zero, and hover every icon button once and count the boxes. Two is a bug.++ ## 1. Every interactive element gets a descriptive tooltip Buttons, icon-only controls, labels with jargon, and any non-obvious widget MUST carry a