From 41dc3dbeea9b624f3995d113f83a08254a3822c2 Mon Sep 17 00:00:00 2001 From: Mischa Date: Sat, 20 Jun 2026 12:08:34 +0200 Subject: [PATCH] docs: add UI/UX alignment implementation plan --- .../plans/2026-06-20-ui-ux-alignment.md | 624 ++++++++++++++++++ 1 file changed, 624 insertions(+) create mode 100644 docs/superpowers/plans/2026-06-20-ui-ux-alignment.md diff --git a/docs/superpowers/plans/2026-06-20-ui-ux-alignment.md b/docs/superpowers/plans/2026-06-20-ui-ux-alignment.md new file mode 100644 index 0000000..db0df16 --- /dev/null +++ b/docs/superpowers/plans/2026-06-20-ui-ux-alignment.md @@ -0,0 +1,624 @@ +# UI/UX Alignment Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Unify three micro-interaction patterns across the site: back navigation pills, card hover lift, and a map-to-card flash highlight. + +**Architecture:** CSS-first — shared `.back-pill` class drives visual consistency; entry card markup is collapsed from a two-level `article > a` to a flat `` to align hover targets across all three card types; map flash is a short CSS keyframe triggered by a JS-added class. + +**Tech Stack:** Twig templates, vanilla CSS custom properties, vanilla JS, Playwright for tests. + +## Global Constraints + +- Dev server: `http://localhost:8081` — must be running (`make start`) before any Playwright run +- Playwright: `npx playwright test --project=chromium tests/ui/.spec.js` — always run the affected spec after changes +- Demo data required for story/map tests: `make demo-load` +- All CSS uses design tokens from `user/themes/intotheeast/css/tokens.css` — never hard-code colours +- `--color-paper: #1A1814`, `--color-canvas: #22201B`, `--color-ink: #EDE8DF` — the site is dark-themed +- `--site-header-height: 60px` — fixed pills must clear the site nav +- Never read `.env` directly + +--- + +## File Map + +| File | What changes | +|---|---| +| `user/themes/intotheeast/css/style.css` | Add `.back-pill` class; remove duplicate `.story-escape` block; migrate `.entry-card-inner` hover rules to `.entry-card`; add uniform card hover lift; add `@keyframes card-highlight` | +| `user/themes/intotheeast/templates/story.html.twig` | Add `class="back-pill"` to story-footer back link (line 61) | +| `user/themes/intotheeast/templates/entry.html.twig` | Add fixed top back pill before `
`; replace footer teal link with `.back-pill`; add `.entry-back-fixed` CSS | +| `user/themes/intotheeast/templates/trip.html.twig` | Collapse `
` to `` for both card variants; update marker click handler with flash delay | +| `tests/ui/dailies.spec.js` | Update T2 selectors from `.entry-card a[href*="..."]` to `.entry-card[href*="..."]`; add T6 (back pills on entry page) | +| `tests/ui/maps.spec.js` | Add M7 (marker click adds `is-highlighted` class) | + +--- + +## Task 1: CSS foundation — `.back-pill`, card hover lift, flash keyframe, story-escape cleanup + +**Files:** +- Modify: `user/themes/intotheeast/css/style.css` + +**Interfaces:** +- Produces: `.back-pill` class (surface pill), `.entry-card.is-highlighted` animation, uniform hover lift on `.trip-card:hover`, `.entry-card:hover`, `.story-card:hover` + +- [ ] **Step 1: Add `.back-pill` surface pill class** + +Find the `/* ── Back to top pill ──` section (around line 1217). Insert the following block immediately **before** it: + +```css +/* ── Back pill (shared navigation pill component) ───────────────────── */ +.back-pill { + display: inline-flex; + align-items: center; + font-family: var(--font-ui); + font-size: var(--text-sm); + font-weight: 500; + color: var(--color-ink); + text-decoration: none; + background: var(--color-canvas); + border: 1px solid var(--color-border); + border-radius: var(--radius-full); + padding: 0.4rem 0.9rem; + transition: border-color 0.15s, color 0.15s; + cursor: pointer; +} +.back-pill:hover { border-color: var(--color-accent); color: var(--color-accent); } +``` + +- [ ] **Step 2: Remove the duplicate `.story-escape` block** + +Around line 958 there is a `/* ── Story page escape link ──` section with a `.story-escape` rule that is overridden later by the story-section block. Remove this entire section: + +```css +/* ── Story page escape link ──────────────────────────────────────────────────── */ + +.story-escape { + position: fixed; + top: var(--space-5); + left: var(--space-5); + z-index: 200; + font-size: var(--text-sm); + font-weight: 500; + color: var(--color-ink); + text-decoration: none; + background: rgba(0,0,0,0.6); + padding: var(--space-2) var(--space-4); + border-radius: var(--radius-full); + backdrop-filter: blur(4px); +} + +.story-escape:hover { color: var(--color-accent); } +``` + +The authoritative `.story-escape` definition remains in the `/* ── Story pages ──` section (~line 1056). + +- [ ] **Step 3: Add uniform card hover lift + fix story-card transition** + +Find the `.trip-card:hover` rule (in `/* ── Past trips archive ──`). After the existing `.trip-card:hover` block, add: + +```css +.trip-card:hover, +.entry-card:hover, +.story-card:hover { + background: var(--color-surface-raised); +} +``` + +Then find `.story-card` in the `/* ── Stories listing ──` section and add `background 0.15s` to its existing transition so the lift animates: + +```css +/* Before: */ +.story-card { + ... + transition: box-shadow 0.2s; +} + +/* After: */ +.story-card { + ... + transition: box-shadow 0.2s, background 0.15s; +} +``` + +- [ ] **Step 4: Add map flash keyframe** + +At the end of the `/* ── Feed ──` section (after `.entry-card` and related rules, around line 210), add: + +```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; +} +``` + +- [ ] **Step 5: Verify no JS errors on the site** + +```bash +npx playwright test --project=chromium tests/ui/maps.spec.js -g "M1:" +``` + +Expected: PASS (map page loads without errors — confirms CSS is valid). + +- [ ] **Step 6: Commit** + +```bash +git add user/themes/intotheeast/css/style.css +git commit -m "feat: add back-pill class, card hover lift, flash keyframe; remove duplicate story-escape" +``` + +--- + +## Task 2: Story template — apply `.back-pill` to body back link + +**Files:** +- Modify: `user/themes/intotheeast/templates/story.html.twig` + +**Interfaces:** +- Consumes: `.back-pill` class from Task 1 + +- [ ] **Step 1: Write the failing test** + +Add to `tests/ui/stories.spec.js`: + +```js +// ── S7: Story body back link is styled as a back-pill ──────────────────────── +test('S7: story body back link has back-pill class', async ({ page }) => { + await page.goto('/trips/italy-2025/stories/val-dorcia-dawn'); + await expect(page.locator('.story-hero__img')).toBeVisible({ timeout: 8000 }); + // Scroll past the hero to reveal the story body + await page.evaluate(() => window.scrollBy(0, window.innerHeight * 1.5)); + await page.waitForTimeout(300); + const bodyBack = page.locator('.story-footer .back-pill'); + await expect(bodyBack).toBeAttached(); + await expect(bodyBack).toHaveText(/← Back/); +}); +``` + +- [ ] **Step 2: Run test to verify it fails** + +```bash +npx playwright test --project=chromium tests/ui/stories.spec.js -g "S7:" +``` + +Expected: FAIL — "locator('.story-footer .back-pill')" found 0 elements. + +- [ ] **Step 3: Apply `.back-pill` to the story footer back link + fix `.story-footer a` conflict** + +In `story.html.twig`, the story footer currently reads: + +```twig +