← Commit history

New sub-skill: scrollbars (the pretty scrollbar, fade-on-scroll, rounded-corner track inset, gutter, no outer-html scroll); settings-layout gains the scrollbar + open-at-top rules

John Lauer ·46b17cfbe7 ·2mo ago ·parent 91b9f0b
5 files changed +161−2
SKILL.md+1
@@ -420,6 +420,7 @@ This whole system ships as **one installable skill**. `adom-wiki pkg install ado  | Skill | Governs | |---|---|+| [**scrollbars**](https://wiki.adom.inc/adom/adom-ui-design/files/skills/scrollbars/SKILL.md) | The pretty scrollbar (thin, translucent, fade-while-scrolling), the rounded-corner track inset, scrollbar-gutter, and the never-scroll-the-outer-html rule | | [**input-feedback**](https://wiki.adom.inc/adom/adom-ui-design/files/skills/input-feedback/SKILL.md) | The acknowledgment doctrine: hover, mousedown/:active, and focus-visible states on EVERY interactive element - the UI answers 'yes, you just hovered me / pressed me' before the action even runs | | [**settings-layout**](https://wiki.adom.inc/adom/adom-ui-design/files/skills/settings-layout/SKILL.md) | The ah settings surface, reusable: sectioned teal-accent cards that EXPLAIN themselves in full sentences, inline live status, Install/Update/Uninstall rows with live consoles, and the portal-modal mechanics - every Adom app's settings dialog mimics this | | [**tooltips**](https://wiki.adom.inc/adom/adom-ui-design/files/skills/tooltips/SKILL.md) | Great desktop tooltips: 600ms reveal, the fixed-div renderer, placement that never covers what you hover, edge-aware flipping, the z-index ladder |
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-ui-design",-  "version": "1.6.0",+  "version": "1.6.1",   "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.",   "dependencies": {},
page.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-ui-design",-  "version": "1.6.0",+  "version": "1.6.1",   "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.",   "dependencies": {},
skills/scrollbars/SKILL.mdadded+132
@@ -0,0 +1,132 @@+---+name: scrollbars+user-invocable: true+description: >-+  The Adom pretty scrollbar: thin, barely-visible, transparent track, pill thumb that only+  brightens on hover, and the fade-in-while-scrolling variant that disappears when you stop.+  Covers the copy-paste recipe (Chromium ::-webkit-scrollbar + Firefox scrollbar-width /+  scrollbar-color), where to scope it, the ROUNDED-CORNER inset problem (a scrollbar running+  the full height of a radius-12 dialog visually slices the curve off), scrollbar-gutter to stop+  layout shift, the never-scroll-the-outer-html rule, overlay/auto-hide behavior, and how to+  ralph-test it. Read BEFORE shipping any scrolling surface - panel, modal, list, console.+  Trigger words: scrollbar, pretty scrollbar, ugly scrollbar, scrollbar styling, custom+  scrollbar, thin scrollbar, hide scrollbar, fade scrollbar, auto-hide scrollbar, overlay+  scrollbar, webkit-scrollbar, scrollbar-width, scrollbar-color, scrollbar-gutter, scroll+  container, modal scroll, rounded corners scrollbar, scrollbar corner overlap.+---++Parent skill: **adom-ui-design**++# Scrollbars - the pretty one, and only the pretty one++**The rule (John, 2026-08-18):** a default OS scrollbar in an Adom app is "hideous". Adom+scrollbars are **barely visible** - a thin translucent pill on a transparent track, ideally one+that **fades in when you start scrolling and disappears when you stop**. The content is the+subject; the scrollbar is a hint, not a piece of furniture.++## The recipe (copy-paste, both engines)++Put this ONCE, globally, in every Adom app's stylesheet. Chromium needs the+`::-webkit-scrollbar` pseudo-elements; Firefox needs the two standard properties.++```css+/* Firefox + the standard */+* { scrollbar-width: thin; scrollbar-color: rgba(139,148,158,.38) transparent; }++/* Chromium / WebKit */+::-webkit-scrollbar { width: 10px; height: 10px; }+::-webkit-scrollbar-track { background: transparent; }+::-webkit-scrollbar-thumb {+  background: rgba(139,148,158,.32);       /* the muted text color, mostly transparent */+  border-radius: 999px;                     /* a pill, never a rectangle */+  border: 2px solid transparent;            /* the trick: inset the pill off the edge */+  background-clip: padding-box;             /* ... makes the border read as padding */+}+::-webkit-scrollbar-thumb:hover { background: rgba(0,184,177,.55); background-clip: padding-box; }+::-webkit-scrollbar-corner { background: transparent; }+```++Why each line matters: the transparent track kills the OS "gutter" look; the+`border + background-clip: padding-box` pair is what makes the pill float inside the track+instead of butting against the edge; the accent (teal) on hover is the only moment the+scrollbar is allowed to assert itself.++## The fade-in variant (preferred for dense surfaces)++Only show the thumb while the user is actually scrolling. Native overlay scrollbars are not+reliably available, so drive it with a class:++```css+.scroller::-webkit-scrollbar-thumb { background: transparent; transition: background .25s ease; }+.scroller.is-scrolling::-webkit-scrollbar-thumb { background: rgba(139,148,158,.38); }+.scroller:hover::-webkit-scrollbar-thumb      { background: rgba(139,148,158,.28); }+```++```js+const el = document.querySelector('.scroller');+let t; el.addEventListener('scroll', () => {+  el.classList.add('is-scrolling');+  clearTimeout(t); t = setTimeout(() => el.classList.remove('is-scrolling'), 900);+}, {passive: true});+```++Keep `scrollbar-width: thin` (not `none`) so the surface still reports as scrollable to+assistive tech and trackpad users, and never hide the scrollbar on a surface whose+scrollability is not otherwise obvious.++## ⚠ ROUNDED CORNERS: inset the track or you slice the curve++**The bug (John caught it on the fusion Dashboard settings modal):** a dialog with+`border-radius: 12px` that scrolls ITSELF paints the scrollbar over the full height of its+padding box, so the bar runs straight through the top and bottom curves - the corners read as+cut off and the whole dialog looks broken. Two fixes, in order of preference:++1. **Move the scroll inside** (best): the radius element does not scroll; an inner wrapper does.+   ```css+   dialog.settings { border-radius: 12px; overflow: hidden; padding: 0; }+   .settings-body  { max-height: 70vh; overflow: auto; padding: 18px; }+   ```+   The scrollbar now lives inside the clipped box and cannot touch the corner curve.+2. **Inset the track** when you cannot restructure: give the track a vertical margin at least+   as large as the radius.+   ```css+   .rounded-scroller::-webkit-scrollbar-track { margin: 12px 0; }   /* >= border-radius */+   ```++The same rule applies to any radius-carrying scroll surface: cards, popovers, code blocks,+consoles, side panels.++## Layout rules that come with scrolling++- **NEVER let the outer `html`/`body` scroll horizontally.** A page-level horizontal scrollbar+  is always a bug (an element overflowing), never a feature. Wide content - tables, diagrams,+  code, timelines - scrolls INSIDE its own `overflow-x: auto` container.+- **`scrollbar-gutter: stable`** on a container whose content grows across the scroll threshold,+  so the layout does not jump sideways the moment a scrollbar appears. Use+  `stable both-edges` when the container is visually centered.+- **One scroller per region.** Nested scrollers steal wheel events and trap users; if you find+  two, one of them should be `overflow: visible`.+- **Scroll the region, not the app.** A full-height app shell (header + body) puts `overflow:+  auto` on the body region so the header stays put - see the `app-shell` sub-skill.+- **Momentum on touch**: `-webkit-overflow-scrolling: touch` for iOS webviews.++## Ralph-test it++- Open the surface, make it overflow FOR REAL (enough content to scroll), screenshot, and LOOK:+  is the bar thin and translucent, or a fat grey OS bar? On a rounded container, are the top and+  bottom curves intact?+- Check the two states: at rest (thumb barely there or absent) and hovered (thumb visible, teal).+- Check both engines when the app can be opened in either (pup Chromium is the default surface;+  Firefox via ffpup for the standard properties).+- Check that the page itself never grew a horizontal scrollbar:+  `document.documentElement.scrollWidth <= innerWidth`.++## Anti-patterns++- Shipping the OS default because "it is only a settings dialog" - the modal is exactly where a+  fat grey bar is most visible.+- `overflow: hidden` to hide an ugly scrollbar: now the content is unreachable.+- `::-webkit-scrollbar { display: none }` with no other affordance: invisible AND unscrollable+  by keyboard/AT users who need the cue.+- Styling the thumb but leaving the track a solid color: the gutter is what makes it look OS-y.+- A radius container that scrolls itself with no track inset (see above).
skills/settings-layout/SKILL.md+26
@@ -95,6 +95,32 @@ The ah Monitored-AIs pattern: `[checkbox + name] [status: version or "not instal   "<Thing> Settings". - Overlay dims the app behind; the modal owns scroll (max-height ~70vh). +## Scrolling the settings surface (do not ship the OS scrollbar)++Both variants scroll: the full page's editor column, and the compact modal at ~70vh. Use the+house scrollbar from the **scrollbars** sub-skill (thin, transparent track, translucent pill,+teal only on hover) - a fat grey OS bar inside a settings dialog is the most visible place to+get this wrong, and it will be the first thing the user mentions.++**The rounded-corner trap, specifically for the modal:** the settings modal has a 10-12px+radius. If the DIALOG itself is the scroll container, its scrollbar paints down the full padding+box and cuts straight through the top and bottom curves. Structure it so the radius element does+not scroll:++```css+dialog.settings      { border-radius: 12px; overflow: hidden; padding: 0; }+.settings-body       { max-height: 70vh; overflow: auto; padding: 18px; }   /* the scroller */+```++If restructuring is not possible, inset the track by at least the radius:+`.settings-scroller::-webkit-scrollbar-track { margin: 12px 0; }`.++**Open at the top.** `showModal()` autofocuses the first focusable child, so a settings modal+whose first input lives in a LATER card opens scrolled to that card (shipped and caught on the+fusion Dashboard). Give the dialog `tabindex="-1"`, focus the dialog itself on open, and set+`scrollTop = 0` (again inside a `requestAnimationFrame`, since the autofocus scroll lands after+your first assignment).+ ## Copy rules  - Full sentences, present tense, second person where natural. No em-dashes ever (Adom rule).