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
New sub-skill: input-feedback - the acknowledgment doctrine (hover/press/focus states on every interactive element; John's ruling 2026-08-18)
3 files changed
+146−2
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-ui-design",- "version": "1.5.0",+ "version": "1.5.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). 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.5.0",+ "version": "1.5.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). One install drops the whole set of skill files onto your container.", "dependencies": {},
skills/input-feedback/SKILL.mdadded+144@@ -0,0 +1,144 @@+---+name: input-feedback+user-invocable: true+description: >-+ The acknowledgment doctrine: every interactive element must answer the human's INPUT itself -+ "yes, you just hovered me" (a subtle border/background shift) and "yes, you just pressed me"+ (a real mousedown/:active state), plus a keyboard :focus-visible ring - BEFORE and separate from+ whatever the action later does. Covers the three acknowledgment moments (hover, press, focus),+ copy-paste CSS recipes on the house tokens for buttons, icon buttons, pills, toggles, rows and+ inputs, the timing rules (hover ~150ms, press instant), touch behavior, disabled/busy states,+ the ralph-test checklist, and the anti-patterns (hover-only buttons, color-only shifts,+ outline:none). Read BEFORE shipping ANY clickable UI. Trigger words: input feedback, button+ feedback, press state, pressed state, mousedown state, active state, :active, hover state,+ hover effect, acknowledge click, acknowledge hover, button not responsive, buttons feel dead,+ click feedback, tap feedback, focus ring, focus-visible, tap highlight, button press animation,+ ui acknowledgment, responsive buttons.+---++Parent skill: **adom-ui-design**++# Input feedback - the UI acknowledges the human++**The doctrine (John, 2026-08-18, verbatim):** the UI must "acknowledge the effort of the human+to click something or hover something ... they are getting feedback from the ui that they just+performed an action and the ui is saying back to them with subtlety of 'yes, you just hovered me'+or 'yes, you just pressed me' - i.e. a mousedown state on a button when the user pushes, or a+slight border treatment upon hover."++This is DISTINCT from "every action answers back" (toasts, state changes - see the `toasts`+sub-skill). That is acknowledgment of the OUTCOME. This skill is acknowledgment of the INPUT+itself, which happens EARLIER: the finger goes down, and before any request fires or any state+changes, the element visibly yields. A button with no pressed state feels dead even when the+action behind it works perfectly - the human is left asking "did that register?" for the whole+round-trip. Input feedback is what makes an interface feel like a physical object instead of a+picture of one.++## The three acknowledgment moments++Every interactive element gets all three. No exceptions, no "it's just a small button".++1. **Hover** - "you found me." A SUBTLE shift: border color up one step, background up one+ surface, or text brightening. One or two properties, ~150ms ease. Hover says "I am+ interactive and I noticed you" - it must never shout.+2. **Press (mousedown / touchstart)** - "you pushed me." The element visibly compresses the+ INSTANT the pointer goes down: translateY(1px) + scale(~0.97-0.98) + a darker fill. This is+ the moment users mean when they say a UI feels responsive. It fires on mousedown, NOT on+ click - the acknowledgment must not wait for the release.+3. **Keyboard focus** - "you reached me without a mouse." `:focus-visible` (never bare+ `:focus`) with a 2px accent outline, offset 2px. Removing outlines without a replacement is+ an accessibility bug, full stop.++## Copy-paste recipes (house tokens)++Assumes the standard tokens (`--border #30363d`, `--surface #161b22`, `--elevated #1c2128`,+`--overlay #21262d`, `--accent #00b8b1`). Adapt values, keep the STRUCTURE: hover = one step up,+active = compress + one step down.++```css+/* Standard button */+.btn{transition:background .15s ease,border-color .15s ease,transform .06s ease}+.btn:hover{background:var(--overlay);border-color:#4b5563} /* border treatment on hover */+.btn:active{transform:translateY(1px) scale(.98);background:var(--surface)} /* the press */+.btn.primary:active{background:#009d97;border-color:#009d97;transform:translateY(1px) scale(.98)}++/* Icon-only button: compress harder, it has no label to carry the change */+.iconbtn{transition:background .15s ease,border-color .15s ease,transform .06s ease}+.iconbtn:hover{background:var(--elevated);border-color:var(--border)}+.iconbtn:active{transform:scale(.9);background:var(--overlay)}++/* Pills / chips / segmented choices */+.pill:hover{border-color:#4b5563;background:var(--elevated);color:var(--text)}+.pill:active{transform:translateY(1px) scale(.97)}++/* Toggle: hover ring + iOS-style knob stretch while held */+.toggle:hover{border-color:var(--accent)}+.toggle:active::after{width:22px} /* knob elongates under the finger */+.toggle.is-on:active::after{left:17px} /* stretch inward from the on side */++/* Interactive rows / list items (ONLY if actually clickable) */+.row:hover{border-color:#4b5563}++/* Inputs */+input:focus-visible{outline:none;border-color:var(--accent)}++/* Keyboard reachability - one rule for everything clickable */+.btn:focus-visible,.iconbtn:focus-visible,.pill:focus-visible,.toggle:focus-visible{+ outline:2px solid var(--accent);outline-offset:2px}+```++## Timing rules (these make or break the feel)++- **Hover: ~150ms ease.** Slow enough to feel smooth, fast enough to feel attributed to you.+- **Press: INSTANT - 60ms transform transition or less.** A press that eases in over 150ms reads+ as lag, not acknowledgment. Put `transform .06s ease` in the base transition list so the press+ snaps and the release springs back on the same short curve; colors may keep the 150ms.+- **Never put a long transition on `:active` properties.** The #1 way to build a press state+ that still feels dead.++## Touch++- `:active` fires on touch contact (the historical 300ms tap delay is gone on modern mobile) -+ the same CSS covers tap feedback. Verify it on a phone width anyway.+- Set `-webkit-tap-highlight-color: transparent` ONLY when your own :active state exists -+ removing the platform's acknowledgment without providing yours is how taps go dead on mobile.+- Elaborate hover effects belong behind `@media (hover: hover)` so they cannot stick "on" after+ a tap on touch screens. A simple border/background hover is harmless either way.++## Disabled and in-flight++- **Disabled elements acknowledge NOTHING**: no hover, no press (`pointer-events` intact for the+ tooltip explaining WHY it is disabled, but visual state frozen, opacity ~0.5,+ `cursor:not-allowed`). Acknowledging input on a control that cannot act is a lie.+- **In-flight (pressed, action running)**: hold a working state - label swap ("Starting...") or+ an inline spinner - until the outcome lands (then the toast/state change takes over; see+ `toasts`). The gap between press-acknowledgment and outcome-acknowledgment must never be+ visually empty on slow actions.++## Ralph-testing input feedback++- **The checklist**: for EVERY interactive element - button, icon button, pill, toggle, row,+ link, input - confirm a visible change on (a) hover, (b) mousedown HELD (press and hold it:+ the compressed state must persist while held), (c) keyboard Tab focus. If any of the three+ produces no visible change, it fails.+- **CSS `:active` and `:hover` only respond to TRUSTED input** - a JS+ `dispatchEvent(new MouseEvent('mousedown'))` will NOT trigger them, so you cannot fake the+ verification from page script. Drive real input (CDP Input dispatch / pup move+click verbs) or+ eyeball it by hand. A real-input `move` onto the element + screenshot proves hover; press+ states need held real input or a human eye.+- Static, non-interactive elements (status cards, labels) get NO hover state - a hover shift on+ something unclickable is a fake affordance and will draw dead clicks.++## Anti-patterns (each of these shipped somewhere and got called out)++- **Hover-only buttons** - the exact failure that created this skill: the fusion Dashboard+ shipped with `:hover` and zero `:active` states, and John pressed buttons that never pressed+ back ("why are none of your buttons responsive when i push them down?").+- **Color-only 5% shifts** - too subtle to register as acknowledgment. Pair a color step with a+ border or transform change.+- **`outline: none` without `:focus-visible` replacement** - keyboard users lose the interface.+- **Transition-lagged presses** - see timing rules.+- **Hover states on static content** - fake affordances.++Reference implementation: `dashboard/ui/index.html` on adom/fusion-bridge (v1.9.60) - every+interactive element carries all three moments on the house tokens.