From f0c8ce313730a09bfaf73f4f1883737170f09a26 Mon Sep 17 00:00:00 2001 From: Mischa Date: Sat, 20 Jun 2026 11:53:51 +0200 Subject: [PATCH] docs: add UI/UX alignment design spec (back pills, card hover, map flash) --- .../2026-06-20-ui-ux-alignment-design.md | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 docs/superpowers/specs/2026-06-20-ui-ux-alignment-design.md diff --git a/docs/superpowers/specs/2026-06-20-ui-ux-alignment-design.md b/docs/superpowers/specs/2026-06-20-ui-ux-alignment-design.md new file mode 100644 index 0000000..5bb9745 --- /dev/null +++ b/docs/superpowers/specs/2026-06-20-ui-ux-alignment-design.md @@ -0,0 +1,166 @@ +# UI/UX Alignment — Design Spec + +*2026-06-20* + +--- + +## Goal + +Unify three disconnected micro-interaction patterns across the site: + +1. **Back navigation** — inconsistent style and position across story and entry pages +2. **Card hover** — inconsistent lift behaviour and structural divergence across the three card types +3. **Map flash** — no visual feedback after the feed scrolls to a marker-targeted card + +--- + +## 1. Back pill system + +### Canonical pill component + +The site is dark-themed (`--color-paper: #1A1814`, `--color-ink: #EDE8DF` cream). Two visual variants of a single pill component, chosen by what is behind it: + +**Surface pill** (sits on the dark paper/canvas background): +```css +background: var(--color-canvas); +border: 1px solid var(--color-border); +color: var(--color-ink); +border-radius: 9999px; +padding: 0.4rem 0.9rem; +font-size: var(--text-sm); +font-weight: 500; +text-decoration: none; +transition: border-color 0.15s, color 0.15s; +``` +Hover: `border-color: var(--color-accent); color: var(--color-accent)` + +**Overlay pill** (sits on top of a hero photo): +```css +background: rgba(0,0,0,0.6); +backdrop-filter: blur(4px); +color: var(--color-ink); +border-radius: 9999px; +padding: var(--space-2) var(--space-4); +font-size: var(--text-sm); +font-weight: 500; +text-decoration: none; +``` +Hover: `color: var(--color-accent)` + +The `.story-totop` button already matches the surface pill tokens (`--color-canvas` bg, `--color-border` border, `--color-ink` text) — it becomes part of this system without visual changes. + +### Pill inventory + +| Element | Page | Variant | Position | Notes | +|---|---|---|---|---| +| `.story-escape` | story | overlay | `fixed`, top-left | Overlays hero; keep as-is | +| `← Back` in story body | story | surface | `static`, below-hero body section | Apply surface pill class | +| Entry top back | entry | surface | `fixed`, `top: calc(var(--site-header-height) + var(--space-3))`, left | New element | +| Entry footer back | entry | surface | `static`, in `.entry-footer` | Replaces current teal text link | +| `.story-totop` | story | surface | `fixed`, bottom-right | Existing; bring into token system | + +### Shared behaviour + +All back pills use the same `onclick` pattern already present on `.story-escape`: +```js +onclick="if(history.length > 1){ history.back(); return false; }" +``` +Fallback `href` is always `page.parent().url`. + +--- + +## 2. Card hover unification + +### Structural fix — entry card markup + +Entry cards currently use a two-level structure (`
` wrapping ``), which causes the hover target to differ from trip and story cards. This diverges for no functional reason — `id` and `data-*` attributes are valid on `` elements. + +**Before:** +```html + +``` + +**After:** +```html + + ... + +``` + +The class `.entry-card-inner` is eliminated. All CSS rules previously on `.entry-card-inner` move to `.entry-card`. The map's `document.getElementById('entry-' + slug)` continues to work unchanged. + +The story variant card in the trip feed (`entry-card--story`) follows the same structural change. + +### Hover pattern + +All three card root elements get a uniform background lift: + +```css +.trip-card:hover, +.entry-card:hover, +.story-card:hover { + background: var(--color-surface-raised); +} +``` + +Existing per-card effects are additive on top of the lift: +- **Entry card**: photo zoom (`transform: scale(1.04)`) + title tint (`color: var(--color-accent)`) — keep +- **Story card**: shadow (`box-shadow: var(--shadow-md)`) — keep +- **Trip card**: border accent (`border-color: var(--color-accent)`) — keep + +Transition values align across all three cards: `transition: background 0.15s, border-color 0.15s`. + +--- + +## 3. Map flash + +### Problem + +After clicking a marker on the trip page mini-map, `scrollIntoView({ behavior: 'smooth', block: 'center' })` scrolls the feed but provides no visual confirmation of which card arrived. + +### Solution + +A 700ms keyframe animation adds a faint teal wash to the targeted card, delayed 350ms after the click to let the scroll complete first. + +**CSS:** +```css +@keyframes card-highlight { + 0% { background-color: color-mix(in srgb, var(--color-accent) 12%, transparent); } + 100% { background-color: transparent; } +} + +.entry-card.is-highlighted { + animation: card-highlight 0.7s ease-out forwards; +} +``` + +**JS (in `trip.html.twig`, marker click handler):** +```js +el.addEventListener('click', function () { + var card = document.getElementById('entry-' + entry.slug); + if (!card) return; + card.scrollIntoView({ behavior: 'smooth', block: 'center' }); + setTimeout(function () { + card.classList.add('is-highlighted'); + setTimeout(function () { card.classList.remove('is-highlighted'); }, 700); + }, 350); +}); +``` + +The `is-highlighted` class is removed after the animation so it can re-trigger on repeated clicks of the same marker. + +--- + +## Out of scope + +- Semantics/accessibility audit of feed list containers and landmark roles (logged as backlog) +- `
` element on full entry/story pages (logged as backlog) +- `.story-totop` behaviour changes — visual tokens only +- Dark mode variants of the new light pills