Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions log.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,5 @@ Append-only. Format: `## [YYYY-MM-DD] <ingest|revise|lint|gap|contradiction|drif
## [2026-08-18] ingest | Consolidated review of knowledge PRs #47–#110 (30 open PRs, 2026-08-06→08-17) into one reconciled state on post-#111 main. 53 new pages, 51 amended pages, 12 indexes updated. New categories: backend/common/ml (mape-aligned-point-prediction), backend/python/packaging (data-files-and-install-paths), security/incident-response (verifying-assumed-security-agents, process-identity-by-path-and-hash). Branches merged chronologically; conflicts union-resolved (related-id unions, max last_verified, newer routing framing + branch-new trigger clauses for index rows, edge-table row unions with one duplicate-substance row dropped). Each branch's own log entries spliced into date order above; every branch's added pages verified present in the final tree. The 30 source PRs are closed in favor of this consolidation (same protocol as the #17–#40 and #42–#43 reconciliations).
## [2026-08-18] ingest | knowledge-flush of 8 queued insights → 7 new pages (two candidates on the same mechanism merged into one page; no existing page carried any of these triggers). New: backend/python/language/source-introspection-of-a-dynamically-loaded-module (`inspect.getfile` resolves a CLASS through `sys.modules[cls.__module__]` but a FUNCTION through `__code__.co_filename`, so a path-loaded module that was never registered makes class introspection die with `TypeError: … is a built-in class` before any assert runs — register per the stdlib's own recipe or retarget the check at a method; reproduced on CPython 3.9.6/3.11.13/3.13.11/3.14.6), databases/query-optimization/repeated-sublinks-in-a-pulled-up-derived-table (a derived table with no aggregate/LIMIT/DISTINCT/set-op is flattened, so a correlated SubLink in its select list is substituted into EVERY referencing aggregate and evaluated once per reference per row; `OFFSET 0` / `MATERIALIZED` fence it and `LATERAL` removes the SubPlan entirely — reproduced on PostgreSQL 16.11: 1/2/3 outer references → 1/2/3 SubPlan nodes, and a PLAIN CTE is folded too so it is not a fence), qa/environments/browser-console-capture-gaps (two disjoint blind spots in one page: a buffer attached after navigation loses every load-time record, and extension content-script logs live in an isolated execution context a main-world collector never sees — clear+reload for the first, judge by DOM side effects for the second; reproduced on Aside CLI 1.26.810: `[]` at 0 ms and at 800 ms, both records after `console.clear()`+`reload()`), platforms/tools/unpacked-extension-source-reload (Chrome's own reload table lists content scripts as requiring an extension refresh "plus the host page"; add a page-visible running-build marker rather than a log line, since content-script logs are collected from another context), testing/quality/expectation-sets-with-one-distinct-value (when every case expects the same literal, a hardcoded constant and the wired computation are observationally identical, so more assertions change nothing — add a case with a DIFFERENT expected value, and probe by substituting the value rather than deleting the key, which only proves key presence; reproduced with unittest: 3 identical expectations → constant survives, +1 differing case → killed, delete probe reddens via KeyError), testing/strategy/orm-generated-test-schema (a test profile whose schema is generated from the ORM model cannot hold a model-vs-database drift — check `ddl-auto` before promising a reproduction, and move verification to a migration-built test DB with `validate` or an `information_schema` gate; field-tested), platforms/filesystems/deleted-file-recovery-on-apfs (run the TRIM/snapshot checks before recommending any recovery tool, work copy sources in fidelity order, and read the exact path out of an app's bookmark blob when the remembered name is wrong; field-tested). Corrections made during verification: three citations inherited from the drafted candidates were dropped rather than carried, because the pages could not be opened and confirmed this session (playwright.dev page-class events, two Apple developer/support pages — the macOS page now cites the local man pages and measurements instead); the Stryker and PIT quotes were re-fetched and replaced with their real sentences. Open-PR dedup: `gh pr list --state open` returned zero rows, so all eight candidates were routed as `new`.
## [2026-08-20] ingest | Frontend visual-design knowledge (2 new pages, NEW category frontend/design). frontend/design/anti-slop-visual-design (field-tested — distilled from hallmark skill v1.1.0, which encodes Anthropic's frontend-design skill + Claude cookbook frontend-aesthetics consensus: decision order with structure-before-visuals as the core claim — the AI tell is structural repetition, not color choice; OKLCH token discipline with the one-accent ≤3% rule and no-pure-extremes; roman-headings + display/body pairing typography; transform/opacity-only motion with the 8-state interactive floor; fabricated-metrics honesty rule; a tells table covering gradient heroes, equal 3-column grids, 100vh centered heroes, genre-blind nav/footer fingerprints, redrawn browser/phone chrome, Lottie/Three.js shortcuts, lazy-loaded LCP, and eyebrow-label decoration). frontend/design/html-in-canvas (verified — WICG html-in-canvas draft: layoutsubtree / drawElementImage / texElementImage2D / copyElementImageToTexture / paint-event API surface, the mandatory returned-transform hit-test sync, the dual DOM+pixels model, and a progressive-enhancement-only stance; status live-checked this session against the WICG repo and the blink-dev intent thread — behind chrome://flags/#canvas-draw-element since Chrome 138 (Dec 2025) dev trial, Origin Trial since Chrome 148 (May 2026)). frontend/index.md routing intro extended with visual-design scope and a new design section. Prohibition-lint directive count unchanged at 71; structure checks 244 pages / 13 indexes / 0 findings.
## [2026-08-21] ingest | frontend/design/responsive-layout (verified — 1 new page). Mobile-responsive layout contract for viewport-range UI: exact viewport meta with zoom left enabled (~980px virtual-viewport mechanism; user-scalable=no blocks the ≥2× WCAG zoom and iOS ignores it — MDN Viewport_meta_element), mobile-first min-width layering with content-driven breakpoints (web.dev responsive-web-design-basics), intrinsic grids repeat(auto-fit, minmax()) before media queries (web.dev patterns) and @container with intrinsic fallback (MDN), touch targets 24px AA SC 2.5.8 / 44px AAA SC 2.5.5 with the 24px-circle spacing exception (W3C Understanding docs), clamp() fluid type gated on a 200%-zoom check (1.4.4, web.dev min-max-clamp), srcset/sizes + width/height CLS reservation (MDN img), the min-width:auto→min-content overflow mechanism fixed by minmax(0,1fr) (MDN min-width), and edge cases for 100vh-vs-dvh/svh, hover:none long-tap emulation, and viewport-fit=cover + env(safe-area-inset) (WebKit blog). 320px no-horizontal-scroll final gate = SC 1.4.10. All 14 cited URLs live-fetched and verified this session by a research subagent; Apple HIG 44pt / Material 48dp figures deliberately NOT cited (JS-rendered pages unverifiable — WCAG carries the target-size claims); rem-vs-px media-query sub-claim omitted as unverified. related links added both ways (anti-slop-visual-design, accessibility/interactive-elements, performance/bundle-and-assets). frontend/index.md design section +1 row, routing intro extended with responsive-layout scope.
## [2026-08-21] revise | frontend/design/anti-slop-visual-design +2 sources / +5 directive rows / +1 edge case (theme-defaults reinforcement). Primary source added: Anthropic Engineering "Improving frontend design through Skills" (claude.com/blog, 2025-11-12; live-fetched — the velog.io/@xxziiko post the contributor supplied is its Korean translation, cross-checked as matching). New Anthropic-backed material: named avoid-list of training-data default fonts (Inter/Roboto/Open Sans/Lato/system) with the distributional-convergence mechanism, feel-category font taxonomy (code/editorial/technical), second-order convergence warning (Space Grotesk as "the new Inter" — vary the escape choice per project), quantified extreme-contrast thresholds (weight 100–200 vs 800–900, 3×+ size jumps), dominant-field + sharp-accent palette framing with IDE-theme/cultural-aesthetic inspiration, domain-derived aesthetic direction folded into the tone-extreme step (non-generic direction reframed as the DEFAULT), motion-budget allocation (one staggered page-load orchestration over scattered micro-interactions), and a right-altitude edge case for writing reusable design guidance (axes + decision logic, no hex hardcoding, no "make it look good"). Aurora-blob Instead-of row reconciled with Anthropic's atmospheric-background endorsement: the tell is ungrounded decoration on a neutral page, theme-earned depth passes. Impeccable README (github.com/pbakaus/impeccable, live-fetched) adds gray-text-on-colored-background and bounce/elastic-easing anti-patterns; tistory.com/1624's deeper Impeccable quotes NOT ingested (cited SKILL.md path 404s — repo restructured; command vocabulary unstable 17→23, only README-level rules taken). Also deliberately skipped: 16px body floor and "adapt don't delete" (third-party, no mechanism, unverifiable primary). frontend/index.md load-when extended (theme direction as default, LLM design-guidance authoring). Prohibition directives unchanged at 71; structure 252/13/0; body 85 lines.
2 changes: 1 addition & 1 deletion wiki/frontend/accessibility/interactive-elements.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ sources:
- https://www.w3.org/TR/using-aria/
- https://www.w3.org/WAI/ARIA/apg/patterns/
last_verified: 2026-07-10
related: [frontend-forms-validation-timing, frontend-agent-interfaces-agent-facing-tool-surfaces, frontend-design-anti-slop-visual-design]
related: [frontend-forms-validation-timing, frontend-agent-interfaces-agent-facing-tool-surfaces, frontend-design-anti-slop-visual-design, frontend-design-responsive-layout]
---

# Building Clickable and Keyboard-Operable UI
Expand Down
23 changes: 17 additions & 6 deletions wiki/frontend/design/anti-slop-visual-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ applies_to: [css, general]
confidence: field-tested
sources:
- "hallmark skill v1.1.0 (anti-AI-slop design skill; distills Anthropic's frontend-design skill, the Claude cookbook on frontend aesthetics, and the 2026 tactile-rebellion consensus)"
last_verified: 2026-08-20
related: [frontend-design-html-in-canvas, frontend-accessibility-interactive-elements]
- "https://claude.com/blog/improving-frontend-design-through-skills — Anthropic Engineering, 2025-11-12 (distributional-convergence mechanism, font avoid-list + taxonomy, extreme-contrast thresholds, domain-derived aesthetic direction, second-order convergence warning; Korean translation: velog.io/@xxziiko)"
- "https://github.com/pbakaus/impeccable — README (gray-text-on-colored-background and bounce/elastic-easing anti-patterns; command list unstable across versions, cited for README-level rules only)"
last_verified: 2026-08-21
related: [frontend-design-html-in-canvas, frontend-accessibility-interactive-elements, frontend-design-responsive-layout]
---

# Making Web UI Look Designed, Not Generated
Expand All @@ -26,7 +28,11 @@ Work in this order — structure decisions precede visual ones:
libraries before restyling anything; preserve them unless asked otherwise.
2. Settle three inputs before code: the audience, the single action the page
drives, and a tone extreme (editorial / brutalist / soft / utilitarian /
luxury / playful / technical). "Clean and modern" is not a tone.
luxury / playful / technical). "Clean and modern" is not a tone. Derive the
direction from the app's subject matter (an RPG tool gets dramatic palettes
and ornament; a trading tool gets terminal density) — the default output of
an unsteered generation is the generic theme, so committing to a
domain-derived direction IS the default here, not an upgrade.
3. Pick the page's structure (heading placement, section rhythm, divider
language) before any visual styling, and vary it between pages — two pages
sharing the hero → 3-feature-grid → CTA rhythm read as one template no matter
Expand All @@ -45,18 +51,22 @@ Color:
| Use OKLCH for every color | Perceptually uniform, so lightness is predictable; hsl/rgb lie about brightness |
| One accent (two max), ≤3% of any viewport | Accent is a highlighter: active nav item, focus ring, link-hover underline, CTA border — not section backgrounds or giant button fills |
| No pure `#000`/`#fff` | Tint paper and ink toward the anchor hue: light paper `oklch(96–98% 0.005–0.015 H)`, dark paper `oklch(12–16% 0.008–0.015 H)` |
| Tint the grays toward the anchor hue | A warm accent with cool-gray body copy reads wrong even to viewers who can't name why |
| Tint the grays toward the anchor hue | A warm accent with cool-gray body copy reads wrong even to viewers who can't name why; on colored surfaces, tint the text toward the surface hue too — neutral gray text on a colored background is a recognized generated-design tell |
| One dominant color field, sharp minority accent | "Dominant colors with sharp accents outperform timid, evenly-distributed palettes" (Anthropic); draw palette direction from IDE themes and cultural aesthetics rather than generic web-palette generators |
| Dark mode: elevation is lightness, not shadow | Higher surface ≈ +3% lightness per level; keep the hue fixed across modes; reduce body font-weight by ~50 to offset light-on-dark optical bolding |

Typography, layout, motion, states:

| Rule | Detail |
|------|--------|
| Pair a distinctive display face with a refined body face | A single-font Inter/Roboto page is a template signal — the exception is a deliberate mono-only aesthetic |
| Reject the training-data default fonts by name | Inter, Roboto, Open Sans, Lato, and system defaults are the distributional center an unsteered model converges on; replace from a feel category — code: JetBrains Mono/Space Grotesk, editorial: Playfair Display/Crimson Pro, technical: IBM Plex/Source Sans 3 — then use the pick decisively |
| Vary the escape choice per project | Escaping one default only to converge on a new one (Space Grotesk as "the new Inter") is the documented second-order failure — treat any font you've reached twice in a row as the next default to reject |
| Contrast by extremes, not moderate steps | Weight pairs from the ends (100–200 against 800–900, not 400 against 600); heading-to-body size jumps of 3×+, not 1.5×; display+mono or serif+geometric-sans pairings — moderate variation still reads generic |
| Headings stay roman (`font-style: normal`) | An italicized emphasis word inside a heading is among the most reliable AI tells; carry emphasis with weight, accent color, or a drawn underline |
| Bias the layout; vary section padding | Wall-to-wall centered columns and identical padding on every section read as template; breaking symmetry once is enough. Use a 4pt spacing scale with semantic tokens |
| `font-variant-numeric: tabular-nums` on number columns | Proportional figures make prices/dates/metrics misalign vertically |
| Animate `transform`/`opacity` only, with named easing tokens | Support `prefers-reduced-motion`; cut motion before adding it — one orchestrated entrance, then content is just there |
| Animate `transform`/`opacity` only, with named easing tokens | Support `prefers-reduced-motion`; cut motion before adding it — spend the whole motion budget on one orchestrated page-load with staggered reveals (`animation-delay`), then content is just there; scattered per-element micro-interactions read as noise. Ease/cubic-bezier tokens only — bounce/elastic easing reads as dated |
| Ship all 8 states per interactive element | default · hover · focus-visible · active · disabled · loading · error · success — see [frontend-accessibility-interactive-elements] for the focus rules; the focus ring appears instantly, ≥3:1 contrast |
| Prefer silent success and optimistic update + Undo | Toasts are for failures and non-visible async effects; confirmation modals are for irreversible actions only. Tooltip delay: hover ~800ms, focus 0ms |

Expand All @@ -68,6 +78,7 @@ Typography, layout, motion, states:
| Restyling an existing app | Replace only the visual layer inside existing boundaries — keep routes, component ownership, copy intent, and information architecture; deleting production files needs explicit approval |
| The brief genuinely needs icons | One icon library per project; emoji (✨ 🚀 ⚡) standing in for feature icons is the recognized AI default |
| The base design passes and an effect layer is wanted | Canvas/shader effects go on top of a passing base, not instead of one — see [frontend-design-html-in-canvas] |
| Writing reusable design guidance (a prompt, skill, or wiki page) rather than styling directly | Pitch it at the "right altitude": name the design axes and their decision logic (pairing categories, contrast thresholds), never exact hex/pixel values (over-constrains) and never "make it look good" (assumes context the model lacks) |
| Narrow viewports (verify 320/375/414/768px) | Root `overflow-x: clip` on both `html` and `body`; clickable text stays on one line (shorten the label, then `white-space: nowrap`, then drop the item); image-bearing grid tracks use `minmax(0, 1fr)` |

## Instead of
Expand All @@ -78,7 +89,7 @@ Typography, layout, motion, states:
| Three equal columns of icon-above-heading-above-body feature cards | Vary column widths and card heights, pull icons inline, or use typographic rhythm with no cards | Every LLM emits this grid |
| `min-height: 100vh` centered hero with one sentence and a big CTA | Content-height hero, biased left or right, with more than a sentence | The default LLM landing page |
| Wordmark-left + inline links + CTA-right sticky nav, and a 4-column link footer | Shape nav and footer to the site's genre; the footer closes the page rather than cataloguing a sitemap | Both shapes are genre-blind template fingerprints |
| Aurora blobs, floating 3D orbs, or decorative glassmorphism behind the hero | Solid surface, or a subtle two-stop gradient with faint grain | 2022-era generated-design defaults; audiences pattern-match them in milliseconds |
| Aurora blobs, floating 3D orbs, or decorative glassmorphism behind the hero | Solid surface, a subtle two-stop gradient with faint grain, or a layered atmospheric background (gradients/geometry/texture) that belongs to the committed aesthetic | The tell is the ungrounded decoration pasted on a neutral page, not depth itself — atmosphere earned by the theme passes, the 2022 default doesn't |
| `transition-all`, `hover:scale-105` on every card, scroll-triggered fade-up on every section | Specify transitioned properties; one hover signal per element; one entrance for the page | The page never settles; motion reads as templated |
| Hand-building fake browser bars, phone frames, or IDE chrome around screenshots | A real screenshot in a `<figure>` with at most a hairline border | Redrawn chrome is always wrong in detail and reads as invented UI |
| Lottie or Three.js for a simple or non-interactive visual | Hand-built CSS/SVG; 3D must be user-manipulable to earn its bundle | Runtime plus hundreds of KB for what CSS does in zero bytes |
Expand Down
Loading
Loading