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.12.0: newbie panel is two columns with a prompts TABLE; header numbers (edge to edge, 18px mark, 15px name); copy/send/play action icons shipped
6 files changed
+191−125
assets/icons/action-copy.svgadded+8@@ -0,0 +1,8 @@+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"+ fill="none" stroke="currentColor" stroke-width="1.8"+ stroke-linecap="round" stroke-linejoin="round">+ <!-- Adom action icon: COPY. Two offset sheets. Inline this into markup, where+ currentColor inherits; if you load it as a file, swap to #e6edf3. -->+ <rect x="9" y="9" width="12" height="12" rx="2.5"/>+ <path d="M6 15H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v1"/>+</svg>
assets/icons/action-play.svgadded+6@@ -0,0 +1,6 @@+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"+ fill="none" stroke="currentColor" stroke-width="1.8"+ stroke-linecap="round" stroke-linejoin="round">+ <!-- Adom action icon: PLAY (the demo button's glyph). Outline triangle, never filled. -->+ <path d="M7 4.8v14.4a.6.6 0 0 0 .92.5l11.3-7.2a.6.6 0 0 0 0-1l-11.3-7.2a.6.6 0 0 0-.92.5z"/>+</svg>
assets/icons/action-send.svgadded+8@@ -0,0 +1,8 @@+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"+ fill="none" stroke="currentColor" stroke-width="1.8"+ stroke-linecap="round" stroke-linejoin="round">+ <!-- Adom action icon: SEND TO AI. A paper plane leaving. Inline this into markup,+ where currentColor inherits; if you load it as a file, swap to #e6edf3. -->+ <path d="M21.5 2.5 10.5 13.5"/>+ <path d="M21.5 2.5 14.8 21.5l-4.3-8-8-4.3z"/>+</svg>
package.json+5−2@@ -1,6 +1,6 @@ { "slug": "adom-ui-design",- "version": "1.11.1",+ "version": "1.12.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": {},@@ -31,7 +31,10 @@ "skills/status-leds/SKILL.md", "skills/dash-demo/SKILL.md", "skills/icons/SKILL.md",- "skills/newbie-panel/SKILL.md"+ "skills/newbie-panel/SKILL.md",+ "assets/icons/action-copy.svg",+ "assets/icons/action-send.svg",+ "assets/icons/action-play.svg" ], "scripts": { "install": "./install.sh",
skills/dash-header/SKILL.md+50−3@@ -38,13 +38,60 @@ This skill adds the dashboard-specific rulings the 2026-08-24 audit showed being Same spot on every app so a user's eye learns it once. A full app served in-container that cannot learn the box name (ab's cross-origin /status projection does not carry it yet) says `target: this machine` honestly rather than guessing or hiding the chip.-- **The app mark and the tab favicon are the SAME line-drawing SVG**, per the **icons**+- **The app mark and the tab favicon are the SAME line-drawing SVG file**, per the **icons** sub-skill: white or currentColor strokes on transparent, never the wrapped vendor's logo- and never a filled colored badge. This is what the user sees at 16px in ah's tab strip,- so a brand-colored plate there breaks the fleet look faster than anything on the page.+ and never a filled colored badge. Exact sizes and weights are in the numbers below. - **The ? lives left of the gear** and recalls the newbie scaffolding - see **newbie-graduation**. Gear opens settings per **settings-layout**. +## The numbers (John's ruling, 2026-08-24, after pup and adom-lbr diverged)++Every dashboard header was drifting on size, weight, color and inset. These are the values.++**The bar itself**+- Height **44px**, and it runs **EDGE TO EDGE**. No left, top or right margin, no rounded+ corners, no gap above it: the header is the top of the window, not a card floating in it.+ (pup shipped with a margin on three sides; that is the defect this rule names.)+- `background: var(--surface)`, a single `1px solid var(--line)` bottom border, nothing else.+- Horizontal padding **16px** inside the bar. The bar is flush; its CONTENTS are inset.++**The app mark**+- **18x18**, and it is the SAME FILE as your `webview.favicon`, so the tab icon and the+ header icon are visibly one mark. A filled brand tile in the header beside a line icon in+ the tab strip is the inconsistency this rule kills.+- Line drawing per the **icons** skill. Inline it and let it inherit, or paint `#e6edf3`.+- `stroke-width: 1.8` at 24 viewBox units, so it matches the weight of the action icons.+ A mark drawn at 2.4 reads BOLD next to everyone else (adom-lbr shipped this way; pup's+ weight is the reference).++**The app name**+- Familjen Grotesk **600**, **15px**, `color: var(--text)`, `letter-spacing: -.01em`.+- Not teal, not the accent, not uppercase, not monospace. The name is text, not branding.+- The human name only: `Pup`, `Adom LBR`, `Chip Fetcher`. Never the slug.++**The subtitle**+- **13px**, `color: var(--muted)`, `font-weight: 400`, sitting **8px** after the name on the+ same baseline. Two to four plain words: `AI browser control`, `the KiCad bridge`.+- Hides below 720px, per **responsive-ui**.++**Right-hand controls**+- Icon buttons only, **18px** glyphs in **28x28** ghost buttons, `gap: 6px`,+ `margin-left: auto`. `var(--muted)` at rest, `var(--teal)` on hover.+- Order, left to right: the `target:` chip, then **?** (restores the newbie panel), then the+ settings cog. Same order on every app so the eye learns it once.+- The cog is `assets/icons/settings-cog-outline.svg` from this pack, unmodified. Do not+ substitute another gear: the whole point is that every Adom cog is the same cog.++**The target chip**+- Mono **12px**, `var(--muted)` label with the box name in `var(--text)`, an 8px LED dot+ inside, `border: 1px solid var(--line)`, `border-radius: 999px`, `padding: 3px 10px`.+- A full app served in-container that cannot learn the box name says `target: this machine`+ rather than guessing or hiding the chip.++**Ralph-test the header**: screenshot two apps' headers at the same width and overlay them.+The bar height, the icon size and weight, the name's size and color, the control order and+the cog must be indistinguishable. If you can tell which app is which from anything other+than the mark, the name and the subtitle, something is off-spec. ## Subtitle Two to four words that say what the page is, in plain language: "the KiCad bridge",
skills/newbie-panel/SKILL.md+114−120@@ -2,143 +2,137 @@ name: newbie-panel user-invocable: true description: >-- THE newbie panel every dock dashboard renders: one FULL-WIDTH band across the top of the- page (never a narrow column squeezed beside the app's own UI), holding the sample AI- prompts and the demo button. Defines when it shows, the X that hides it, the ? in the- header that brings it back, where the demo button sits and what it looks like, how prompt- rows are laid out, and the two ICON buttons on every prompt (copy, send to AI) with- tooltips and toasts instead of text labels. Read BEFORE building or restyling the- prompts/demo area of any dashboard. Trigger words: newbie panel, sample prompts panel,- prompts area, say it panel, demo button, copy button, send to ai button, prompt row,- dismiss panel, bring back help, onboarding panel, getting started panel.+ THE newbie panel every dock dashboard renders: ONE full-width, edge-to-edge band at the+ top of the page, split into TWO COLUMNS - the demo button on the left, the sample AI+ prompts on the right as a quiet TABLE (never pills, which go ragged when phrases differ in+ length). Prescribes every dimension so seven apps look identical: column widths, row+ height, type sizes and colors, the 16px line icons for copy and send (shipped as assets in+ this pack), tooltips, toasts, the single X that collapses it and the ? that restores it.+ Read BEFORE building or restyling the prompts/demo area of any dashboard. Trigger words:+ newbie panel, sample prompts panel, prompts table, say it panel, demo button, copy button,+ send to ai button, prompt row, dismiss panel, bring back help, onboarding panel. --- -Parent skill: **adom-ui-design** (layout partner to **say-strip**, **dash-demo**,-**newbie-graduation**, **icons**, **toasts**)+Parent skill: **adom-ui-design** (works with **dash-header**, **dash-demo**,+**newbie-graduation**, **icons**, **toasts**, **tooltips**) # The newbie panel -John, 2026-08-24, looking at a dashboard that squeezed the prompts into a narrow left-column beside the app's own two-column UI:+John's ruling, 2026-08-24, reviewing pup and chip-fetcher side by side: -> "this looks not great. it seems to me the right column should not be showing and the-> whole width of the screen should have the newbie panel that has the sample ai prompts-> and the demo button."+> "one panel at the top of the page with 2 columns. the left column is the demo button. the+> right column is the sample ai prompts. the sample prompts should probably just be in a+> table layout since the pills are kinda ugly cuz the prompts are different lengths, so it+> gets too noisy." -The panel is a BAND, not a column. Text wrapping mid-phrase at 200px, six stacked rows-pushing the app off screen, buttons wider than the prompt they belong to: all of that is-the panel being asked to live in a column it was never designed for.+Pills were the mistake. Six phrases of different lengths in rounded chips, each trailed by+two buttons, produce a ragged staircase that reads as noise however good the copy is. A+table has one left edge, one right edge, and one row height, so the eye reads the PHRASES+instead of the boxes around them. -## Layout law--- **Full page width.** The panel spans the dashboard's content width, top of the page,- above everything the app itself renders. It is never placed inside a sidebar, a split- pane, or one column of the app's own grid.-- **While the panel is open, the app's own columns yield.** On a full app (chip-fetcher,- lbr, parts-search) the panel pushes the app's UI DOWN; it does not sit beside it and it- does not overlay it. A user in the fresh state is reading the panel, not the app.-- **Prompts flow, they do not stack.** Chips wrap left-to-right across the full width,- three or four per row at desktop width, one per row only on a phone. A phrase must never- wrap inside itself at desktop width; if it does, the panel is too narrow, which means it- is in the wrong place.-- **Max width for readability:** cap the panel's inner content at about 1100px and center- it on very wide screens, so phrases stay scannable.+## Anatomy ```-┌──────────────────────────────────────────────────────────────────────────┐-│ Say it ✕ │-│ You never need this page's buttons: just tell your AI, using the word cf.│-│ │-│ ▶ Play the 2-minute demo │-│ │-│ "get me the files for the STM32H757 with cf" ⧉ ➤ │-│ "plan a batch for my BOM with cf" ⧉ ➤ │-│ "find a 3.3V LDO in stock at mouser with cf" ⧉ ➤ │-└──────────────────────────────────────────────────────────────────────────┘- the app's own UI starts here, full width, below the panel+┌ panel: full content width, one card ────────────────────────────────────────────┐+│ Say it ✕ │+│ You never need this page's buttons: just tell your AI, using the word pup. │+│ ┌ left col, 220px ─┬ right col, flex ──────────────────────────────────────────┐│+│ │ │ "open your dashboard in pup" ⧉ ➤ ││+│ │ ▶ Play the │ ───────────────────────────────────────────────────────── ││+│ │ demo │ "open my wiki page in pup" ⧉ ➤ ││+│ │ │ ───────────────────────────────────────────────────────── ││+│ │ 2 minutes │ "screenshot this site in pup" ⧉ ➤ ││+│ └──────────────────┴───────────────────────────────────────────────────────────┘│+└─────────────────────────────────────────────────────────────────────────────────┘ ``` -## Two traps that make a full-width panel stay a column--Found the hard way by chip-fetcher, the first app to convert:--1. **The panel must be a SIBLING of the app body, outside the app's grid.** If it lives- inside your `.app-grid` / two-column layout, it inherits a column and stays a column- however wide you style it. `.newbie` and `.app-body` are siblings; the app body's top- should measure equal to the panel's bottom.-2. **The demo button must fold WITH the panel.** It is part of the newbie surface, so a- dismissed panel that leaves a stray demo button behind is half-collapsed and looks like- a bug.--Measure rather than eyeball: at a wide viewport, assert panel width equals the content-width, inner content is capped near 1100, `appBody.top === panel.bottom`, and no chip is-taller than one line. At 390px, one chip per row and the icon buttons still in a 44px-target.--## The demo button--- **One button, inside the panel, directly under the explainer line and ABOVE the prompts.**- The demo is the fastest path to understanding, so it comes before the reading material.-- Label: `Play the demo`, or with the real duration when you know it- (`Play the 2-minute demo`). Never "Tour", "Walkthrough", "Start", or an emoji.-- Look: the panel's only PRIMARY button. Teal fill `--teal`, `--on-accent` text, radius 8,- padding 9px 16px, with a small play glyph (line icon, per **icons**) to its left.- Everything else in the panel is quiet, so the one filled button reads as the invitation.-- While the demo runs the panel stays put and the player toolbar appears per **dash-demo**;- the button becomes a disabled "Demo running" state rather than vanishing.--## Prompt rows+## The numbers (copy them, do not re-derive them)++**Panel**+- Full content width, a SIBLING of the app body (never inside the app's grid, or it stays a+ column however wide you style it). The app's own UI begins below it.+- `background: var(--surface)`, `border: 1px solid var(--line)`,+ `border-left: 3px solid var(--teal)`, `border-radius: 12px`.+- `padding: 18px 20px 20px`. Outer margin `16px 0 20px`.+- Inner content `max-width: 1180px`, centered, so phrases stay scannable on a 32in monitor.++**Panel heading and explainer**+- Heading: the literal `Say it`, Familjen Grotesk 600, **15px**, `var(--text)`.+- Explainer: **13.5px**, `var(--muted)`, one sentence, `max-width: 70ch`, the app's noun in+ `var(--teal)` and bold.+- The `✕` sits top-right of the panel, 28x28 ghost button, `var(--muted)`, teal on hover.++**Columns**+- `display: grid; grid-template-columns: 220px 1fr; gap: 24px; align-items: start;`+- A `1px` vertical hairline (`var(--line)`) between the columns, drawn as a+ `border-left` on the right column, so the split reads without a heavy divider.+- Below **760px**: `grid-template-columns: 1fr`, demo button first, full width, hairline+ becomes a `border-top`.++**Left column: the demo button**+- The panel's ONLY filled button: `background: var(--teal)`, `color: var(--on-accent)`,+ `border-radius: 8px`, `padding: 10px 18px`, Familjen Grotesk 600 **14px**,+ `display: inline-flex; align-items: center; gap: 8px;`.+- Glyph: `action-play.svg` from this pack, **16px**, stroke 1.8, inherits the button color.+- Label `Play the demo`, or with the real duration `Play the 2-minute demo`. Never "Tour",+ "Walkthrough", "Start", never an emoji.+- Optional second line under the button: duration or step count, **12px**, `var(--muted)`.+- While the demo runs it becomes a disabled `Demo running` in the same footprint; it never+ disappears, and it folds WITH the panel when the panel collapses.++**Right column: the prompts table**+- A real table structure (`<table>` or `role="table"` rows), not a chip flow.+- Row: `height: 40px`, `border-bottom: 1px solid var(--line)`, none on the last row.+- Row hover: `background: rgba(255,255,255,.03)`, cursor pointer (the whole row copies).+- Phrase cell: **14px** body face, `var(--text)`, in curly quotes, the noun in `var(--teal)`,+ `white-space: nowrap; overflow: hidden; text-overflow: ellipsis;` so a long phrase+ truncates rather than wrapping and breaking the row rhythm. Full text in its `title`.+- Action cell: fixed **72px**, right-aligned, holding the two icon buttons with `gap: 6px`.+- 3 to 6 rows. More than six is a menu, not an invitation.++**The two icon buttons**+- Files: `assets/icons/action-copy.svg` and `assets/icons/action-send.svg` from THIS pack.+ Inline them (so `currentColor` inherits); do not draw your own.+- Icon **16px**, stroke 1.8, inside a **28x28** ghost button, `border-radius: 6px`,+ `border: 1px solid transparent`.+- Rest `color: var(--muted)`. Hover `color: var(--teal); border-color: var(--line);+ background: rgba(0,184,177,.08)`. Focus-visible: 2px teal outline.+- Touch: keep the 28px button inside a 44px hit area with padding, per **responsive-ui**.+- **Icon + tooltip + toast is one contract, never ship one without the other two:**+ - `action-copy`: tooltip and `aria-label` `Copy this prompt to your clipboard`; on click,+ copy then the success toast `Copied to clipboard. Paste it into any AI thread.`+ - `action-send`: tooltip and `aria-label` `Send this prompt to a new AI thread`; on click,+ open a NEW thread and submit, then `Sent to a new AI thread.` On failure, error toast+ plus the copy fallback (see **say-strip**). Currently PARKED fleet-wide: the backend+ refuses before any control-API call and the button falls back to copy.+- Tooltips follow the **tooltips** skill: 600ms delay, body-appended fixed div, clamped to+ the viewport. -Each row is the phrase, then its two buttons, right-aligned in a fixed column so the-buttons form a clean vertical pair down the panel:--- Phrase in curly quotes, body face, never monospace, with the app's noun in `--teal`- (see **say-strip** for the wording rules).-- Clicking the PHRASE itself copies, same as the copy button. Largest target, safest action.-- The two buttons are **ICONS, not words** (John's ruling): text labels like "Copy" and- "Send to AI" repeated six times eat the width the phrases need. Icons keep the row to one- line and let the panel breathe.--## The two icon buttons--Both are line icons per the **icons** skill: 16px, `fill="none"`,-`stroke="currentColor"` (they are inlined into your markup, so inheritance works),-stroke-width 1.8, in a 28x28 ghost button, `--muted` at rest and `--teal` on hover.--| Button | Glyph | Tooltip | On click |-|---|---|---|---|-| **Copy** | two offset rounded rectangles | `Copy this prompt to your clipboard` | Copy, then the success toast `Copied to clipboard. Paste it into any AI thread.` |-| **Send to AI** | a paper-plane / arrow leaving a line | `Send this prompt to a new AI thread` | Open a NEW thread and submit, then `Sent to a new AI thread.` On failure: error toast plus the copy fallback (see **say-strip**) |+## Showing, hiding, bringing back -Rules that make icon buttons legible rather than cryptic:+- 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. -- **Every icon button carries a tooltip** (600ms, per the **tooltips** skill) AND an- `aria-label` with the same words. An icon with no tooltip is a guessing game.-- **Every click answers with a toast** (see **toasts**), because an icon gives no built-in- confirmation the way a labelled button does. Icon + tooltip + toast is one contract:- never ship the icon without the other two.-- On touch, where hover cannot happen, the tooltip text is reachable by long-press and the- toast does the explaining. Keep the 28px button inside a 44px touch target.+## Two traps that keep a full-width panel a column -## Showing, hiding, bringing back+Found by chip-fetcher, the first app to convert: -- **Shows** on a fresh dashboard, expanded, per **newbie-graduation**'s Fresh state.-- **Hidden** by ONE `✕` at the panel's top-right, which collapses the WHOLE panel (prompts,- demo, explainer) to a single quiet line: `Say it: 6 phrases`, tappable to expand for the- session. One X for the whole panel is the sanctioned shape, not an X per section.-- **Brought back** by the `?` in the app header, left of the settings cog (see- **dash-header**). It restores the Fresh panel for the current session; the user's- dismissal is remembered across reloads until they ask for it again.-- The collapsed one-liner NEVER disappears entirely: it is the user's thread back to- "you can just say it", which is the whole point of the dashboard.-- Auto-graduation (3 green launches, first AI-driven action) folds the panel the same way a- dismissal does. See **newbie-graduation** for the triggers and the localStorage key,- which MUST be namespaced with your app slug.+1. **The panel must be a SIBLING of the app body**, outside the app's grid, or it inherits a+ column however wide you style it. Assert `appBody.top === panel.bottom`.+2. **The demo button must fold WITH the panel.** A dismissed panel that leaves a stray demo+ button behind looks like a bug. ## Ralph-test -Open the dashboard at 1400px and at 390px and LOOK: the panel spans the full width, no-phrase wraps inside itself, the demo button is the only filled button, and the app's own UI-starts below the panel rather than beside it. Hover both icon buttons 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.+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.