Files
fdbck/docs/plans/ui-redesign.md
mAi 301cec817a docs: minimalist UI redesign proposal
Per-screen audit + 6 design principles + per-screen mockups + commit-by-commit
implementation plan + 7 open questions.

Boldest moves: collapse the 5-button-per-row admin list into a hover-revealed
⋯ menu with clickable status pill; fold the standalone Share section into the
detail-page header as an inline link strip; drop the JSON-questions textarea
from /new behind a <details> disclosure so the common path reads as four
inputs and a button.

No code touched — design only. Awaiting m's go before coder shift.
2026-05-06 12:16:18 +02:00

39 KiB
Raw Blame History

fdbck — minimalist UI redesign

Status: design proposal, not yet approved. Branch: mai/cronus/fdbck-minimalist-ui. Author: cronus, 2026-05-06.

m's brief: "While our app is quite simple, the layout of it seems overly complex and crowded. I want clearer separation (by negative space) between the different elements and smarter control buttons for a smooth UX."

The app is already small (1 stylesheet, 2 reusable components, 5 routes). The problem isn't features — it's that the existing screens fight minimalism with always-visible action rows, redundant copy, inline style="..." patches, and tight vertical rhythm. This doc proposes per-screen edits that hold features constant but trade visible buttons for whitespace and progressive disclosure.


1. Audit

1.1 / (landing)

┌────────────────────────────────────────┐
│  fdbck                                 │  ← 1.75rem h1
│  Private feedback forms and live chat… │
│                                        │
│  This page is only reachable through…  │
│  [ Admin sign-in ]                     │  ← ghost button
└────────────────────────────────────────┘
  • Already close to minimalist — 20 lines of markup, two paragraphs, one ghost button. Mostly fine.
  • The wordmark fdbck is the brand moment but renders at the same size as every other page h1 (1.75rem). It should feel like a logo on the landing page, not a generic heading.
  • Two paragraphs ("Private feedback forms…" / "This page is only reachable…") partly say the same thing. The second one is a near-tautology — the user is already on the page, so "you got here through a private link" is implicit.
  • Vertical rhythm is tight: 1.5rem between subtitle and section, then the button sits right under one short sentence.
  • Tiny: a marketing-blank landing for a tool whose CTA is "sign in" feels hollow. Either lean further into emptiness (just the wordmark + sign-in) or add one line of confidence-building text. We'll lean into emptiness.

1.2 /login

┌────────────────────────────────────────┐
│  Sign in                               │
│  Admin access only.                    │
│                                        │
│  Email      [______________]           │
│  Password   [______________]           │
│  [ Sign in → ]                         │
└────────────────────────────────────────┘
  • "Sign in" + "Admin access only" is mild redundancy — the page is the form.
  • Error banner sits between the password field and the submit button, which pushes the button down on error and feels like a layout glitch. Better position: above the form (page-level error) or beneath the button as an inline string.
  • Two fields, one button, no dark patterns — already minimalist. Just needs more vertical breathing room and a quieter subtitle (or none).

1.3 /admin/feedback (list)

┌──────────────────────────────────────────────────────────────────┐
│  Feedback forms                              [ + New form ]      │
│  Collect feedback through forms or live chat. Share a private…   │
│                                                                  │
│  Your forms (4)                                                  │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │ Title (link)  [Form+chat] [open]                         │   │
│  │ 12 responses · 7 messages · created 2026-05-01           │   │
│  │ /f/long-slug-shown-raw                                   │   │
│  │ [Edit] [Copy link] [Open] [Close] [Delete]   ← 5 buttons │   │
│  └──────────────────────────────────────────────────────────┘   │
│  …                                                               │
└──────────────────────────────────────────────────────────────────┘
  • The biggest offender. Five always-visible buttons per row (Edit, Copy link, Open, Close/Reopen, Delete) wrap onto multiple lines on narrow widths. Even on desktop they read as a noisy strip.
  • Each row has border + shadow + bg + padding + status pill + mode pill + raw slug + meta line + button strip. Nine visual objects per row.
  • Inline style="…" everywhere (+page.svelte:108-156). Should be classes in feedback.css so dark-mode and rhythm tokens stay consistent.
  • The raw /f/<slug> line is shown but has no purpose for the admin — they use Copy link or Open. It's just text noise.
  • Header repeats the page title in the body (<h1>Feedback forms</h1>) and then the section heading (<h2>Your forms (N)</h2>). The H2 mostly duplicates the H1, just with a count.

1.4 /admin/feedback/new

┌──────────────────────────────────────────────────────────────────┐
│  [← All forms]                                                   │
│  Create a new form                                               │
│  Set up a feedback form, a live chat session, or both. You'll…   │
│                                                                  │
│  Title         [______________________________]                  │
│  Description   [______________________________]                  │
│  ☑ Enable live chat                                              │
│  Questions (JSON, optional)            [ + Insert sample ]       │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │ { … 14-row JSON textarea, monospace … }                  │   │
│  └──────────────────────────────────────────────────────────┘   │
│  Leave empty for chat-only feedback. You can edit questions…    │
│                                                                  │
│  [ ✓ Create form ]                                               │
└──────────────────────────────────────────────────────────────────┘
  • The JSON textarea is a power-user escape hatch dropped into the same surface as a beginner-friendly title/description form. It dominates the page (14 rows, monospace font), even though the visual builder on the detail page is the recommended path.
  • "Insert sample" sits to the right of the label, inside the field's header — visually clever but also noise.
  • The chat checkbox is a single inline item floating in its own block. It looks afterthought-y. (It also reuses .fb-option-row styling, which is meant for question options.)
  • Helper text under the JSON is good, but it's the third descriptive paragraph on the page (<p>Set up a feedback form…</p>, placeholder="…", <div class="fb-question__help">).

1.5 /admin/feedback/[id] (detail)

┌────────────────────────────────────────────────────────────────────────┐
│  [← All forms]                                                         │
│  My session feedback                                                   │
│  Some optional description text shown if present.                      │
│  [open] /f/long-slug [Copy link] [Preview] [Close] [CSV] [JSON] [Delete] ← 8 chips/buttons in one row
│                                                                        │
│  ┌── Share ─────────────────────────────────────────────────────────┐ │
│  │  Memorable short link — resolves to /f/long-slug.                │ │
│  │  https://msbls.de/vote   [ Copy ]   [ Open ↗ ]                   │ │
│  │  ▸ Replace with a different short link                           │ │
│  └──────────────────────────────────────────────────────────────────┘ │
│                                                                        │
│  [ Chat (3) ] [ Results (12) ] [ Responses (12) ] [ Edit ]             │
│  …active tab body…                                                     │
└────────────────────────────────────────────────────────────────────────┘
  • Header is the densest surface in the app. Eight clickable controls in a flex-wrap row: status pill, raw slug, Copy link, Preview, Close/Reopen, CSV, JSON, Delete. On a 1024px viewport this wraps onto two lines.
  • "Copy link / Preview" in the header and a separate Share section and the slug shown raw — three different ways to access the same URL.
  • CSV / JSON download buttons sit between Close and Delete — they're not in the same gravitational tier (export is benign, Delete is nuclear), but they look identical (both fb-btn--ghost fb-btn--sm).
  • The Share section (recently added) was bolted onto the layout rather than designed into it. It sits between header and tabs, breaking the "header → tab → tab body" mental model.
  • The Edit tab's form has its own internal mini-toolbar (Visual / JSON toggle), which is correct but visually clashes with the parent tab strip one screen up.
  • Polling setInterval(refresh, 5000) is right; no UX change needed there.

1.6 /f/[slug] (participant)

┌──────────────────────────────────────────┐
│  Title                                   │
│  Optional description                    │
│  [⚠ closed banner if closed]             │
│                                          │
│  Dein Name (optional):  [Anonym______]  ← inline label + full-width input collide
│                                          │
│  ┌── Live-Feedback ──────────────────┐  │
│  │ scroll list of posts              │  │
│  │ [textarea]                        │  │
│  │                       [ Senden ]  │  │
│  └───────────────────────────────────┘  │
│                                          │
│  ┌── Fragebogen ─────────────────────┐  │
│  │ q1 [...]                          │  │
│  │ q2 [...]                          │  │
│  │ [ Absenden ]                      │  │
│  └───────────────────────────────────┘  │
│                                          │
│  fdbck.msbls.de                          │
└──────────────────────────────────────────┘
  • Already simple. Needs more breathing room between Chat and Form sections — they read as two equally-weighted siblings, but in practice one of them is what the user came for.
  • The Dein Name (optional): label sits inline left of a full-width input (fb-name-row), while every other label in the participant form is on its own line above the input. The inline-label pattern is the only one of its kind on this page — kill it.
  • Footer fdbck.msbls.de is fine as a quiet trust signal.
  • Closed banner uses --color-warning palette which reads as alert; for a closed-form neutral state, a quieter visual is better.
  • Locale mix: admin pages use English (Sign in, Edit, Delete), but the participant page is German (Senden, Absenden, Fragebogen). Probably intentional (admins are us, participants are German-speaking) — flagging it so we don't accidentally homogenise during the redesign. Not in scope to change.

2. Principles

The following six rules apply to every screen. They are the lens for §3.

  1. Whitespace over dividers. Replace borders/shadows/dividers with generous vertical space. The rule of thumb: if a card is bordered on a page that's already on a coloured --gradient-bg, the card competes with the page background — drop the border, keep the radius+padding, lean on negative space. Spacing scale: 0.5rem (within a row), 1.25rem (between form fields), 2.5rem (between sections), 4rem (above page footer).
  2. One primary action per page. Per screen, exactly one button uses the solid .fb-btn (filled green). Everything else is --secondary or --ghost or icon-only. Today most screens have 28 solid-or-near-solid actions competing for attention.
  3. Smarter controls — collapse rows. Anywhere we currently render 3+ buttons in a strip, the redesign keeps one primary inline (or zero — "the row itself is the button") and tucks the rest behind a menu (<details> summary or a small popover). Status flips become pill toggles instead of buttons. Destructive actions live only inside the menu, never as a top-level visible button.
  4. Visual hierarchy via type weight, not borders. Inter is loaded — use weight 700 for page-h1, 600 for section-h2, 500 for form labels, 400 for body. Tracking -0.02em on headings (already in the CSS for h1) extended to h2. This lets us drop a lot of decorative chrome.
  5. Optimistic UX. Delete a row → row disappears immediately, with an undo toast for ~6s. Toggle status → pill switches instantly, network call in background. Errors revert the optimistic change and show a small inline message. We already have Svelte 5 $state everywhere, so this is plumbing, not architecture.
  6. No inline style="..." for layout. Every inline style currently in the .svelte files moves to a class in feedback.css. Two reasons: dark mode lives in @media (prefers-color-scheme: dark) rules and inline styles bypass it; and inline styles defeat the spacing-scale rule (1).

Optional principle 7 (suggest, but waiting for m): list, not cards. A naked padded list with hover-revealed actions beats card-grids for a small N (≈ <50 forms). Keeps the page feeling like content, not a dashboard.


3. Per-screen redesigns

3.1 / (landing)

┌────────────────────────────────────────┐
│                                        │
│                                        │
│   fdbck                                │  ← 2.5rem, weight 700, tracked -0.03em
│   feedback by link                     │  ← muted, 1rem, weight 400
│                                        │
│                                        │
│   [ Admin sign-in →  ]                 │  ← single ghost button, sized fb-btn--lg
│                                        │
└────────────────────────────────────────┘
                                            ↑ massive vertical centering
  • Centre the page vertically (max-width 480px, min-height: 100vh, display: grid; place-items: center;).
  • Drop the "This page is only reachable through a private link…" sentence — if a participant lands here they're not lost; the wordmark + sign-in is enough.
  • Wordmark grows to 2.5rem, weight 700, tracking -0.03em. Subtitle shrinks to 1rem muted.
  • Single CTA, fb-btn--lg fb-btn--ghost with the existing arrow-right icon (already used on login submit).

3.2 /login

┌────────────────────────────────────────┐
│                                        │
│   Sign in                              │  ← drop "Admin access only"
│                                        │
│   Email                                │
│   [______________________]             │
│                                        │
│   Password                             │
│   [______________________]             │
│                                        │
│   ⓘ inline error appears here, muted   │
│                                        │
│   [ Sign in → ]                        │
└────────────────────────────────────────┘
  • Drop the "Admin access only." subtitle (the URL says it).
  • Vertical-centre the form (same grid trick as landing).
  • Inline error: render as a small muted line below the submit button rather than an fb-banner--error block above it. Less alarming, no layout shift.
  • Keep the existing primary fb-btn with arrow-right icon.

3.3 /admin/feedback (list) — the biggest change

┌────────────────────────────────────────────────────────────────────┐
│   Forms                                       [ + New ]            │  ← terse h1, primary CTA
│   ─────────                                                        │
│                                                                    │
│   My session feedback                              ●open  ⋯        │  ← row hover-reveals ⋯
│   Form + chat · 12 responses · 7 messages                          │
│                                                                    │
│   ┌── 2.5rem of pure whitespace ──┐                                │
│                                                                    │
│   Sprint 4 retro                                  ○closed  ⋯       │
│   Form · 0 responses                                               │
│                                                                    │
│   ┌── 2.5rem of pure whitespace ──┐                                │
│                                                                    │
│   Quick chat                                       ●open  ⋯        │
│   Chat · 21 messages                                               │
└────────────────────────────────────────────────────────────────────┘

Row anatomy:

  • The whole row title is a link → goes to detail (today's "Edit" button becomes implicit).
  • Subtitle: mode + counts only. Drop the raw /f/<slug> line, the created DATE ("created" word), and the mode pill — fold mode into the subtitle text ("Form + chat · 12 responses").
  • Right side: a status dot+label (●open / ○closed) that is the toggle — click flips it (optimistic). One control replaces today's pill-+-Close-button pair.
  • Trailing menu (<details> summary or popover) opens:
    • Copy link
    • Open ↗
    • Edit (explicit jump, even though row is also a link)
    • ──────
    • Delete (red)
  • Drop border + shadow + bg on the row container. Rely on row-padding
    • 2.5rem gap between rows. Hover state: faint --color-bg-tertiary background, no border.
  • Mobile (< 640px): keep the always visible; on desktop reveal on hover for a calmer default state.

Header:

  • Drop the descriptive paragraph ("Collect feedback through forms…"). The user already knows what fdbck is.
  • H1 reads "Forms" (terser than "Feedback forms", since we're already at /admin/feedback).
  • Drop the H2 "Your forms (N)" — the count moves into the H1 area as a small muted number, or drops entirely (the rows themselves are the count).
  • Keep one solid + New button on the right.

Empty state: generous whitespace + "No forms yet — create your first one." + the same + New button as primary CTA.

Optimistic delete: after confirming, row disappears immediately; toast at the bottom: "Form deleted. [Undo]" for 6s.

3.4 /admin/feedback/new

┌────────────────────────────────────────────────────────────────────┐
│   ← Forms                                                          │  ← terse back-link, no chip
│                                                                    │
│   New form                                                         │
│                                                                    │
│   Title                                                            │
│   [______________________________________________]                 │
│                                                                    │
│   Description (optional)                                           │
│   [______________________________________________]                 │
│                                                                    │
│   ☐ Enable live chat                                               │
│                                                                    │
│   ▸ Add questions now (advanced)                                   │  ← collapsed by default
│                                                                    │
│   [ ✓ Create form ]                                                │
└────────────────────────────────────────────────────────────────────┘
  • Title + Description + chat checkbox are the common path. They occupy the full page width without any JSON noise.
  • The JSON textarea moves behind a <details> disclosure labelled "Add questions now (advanced)". Inside the disclosure we keep:
    • the Insert sample button (now sits inside the disclosure, where it belongs)
    • the textarea
    • the helper paragraph
  • Rationale: the visual builder on the detail page is the canonical path for adding questions; offering JSON paste at creation is power-user speed-up, not the default. By collapsing it, the new-form page reads like 4 inputs and a button.
  • Replace the back-link button with a plain ← Forms text-link in muted weight 500, no chip styling.
  • Drop the page subtitle ("Set up a feedback form…"). The label "New form"
    • the form below carry the meaning.
  • Move the chat toggle from a faux-fb-option-row checkbox to a proper .fb-toggle with a clean label-on-the-left layout (new class — small CSS addition).

3.5 /admin/feedback/[id] (detail) — the second-biggest change

┌────────────────────────────────────────────────────────────────────────┐
│   ← Forms                                                              │
│                                                                        │
│   My session feedback                                  ●open   ⋯       │  ← title + clickable status pill + ⋯
│   Some optional description shown if present.                          │
│                                                                        │
│   msbls.de/vote        [ Copy ]  [ Open ↗ ]  [ Replace ]               │  ← share-link strip, INLINE in header
│                                                                        │
│   ─────────────────────────────────────────────────────────────────    │  ← whitespace, no border
│                                                                        │
│   [ Chat (3) ] [ Results (12) ] [ Responses (12) ] [ Edit ]            │
│                                                                        │
│   …active tab body, with 2.5rem top-padding…                           │
└────────────────────────────────────────────────────────────────────────┘

Header collapse — 8 controls → 3 visible:

today's control redesign
status pill (display only) status pill, clickable to toggle (optimistic)
/f/slug raw text dropped (the share strip below has the link)
Copy link button inside share strip
Preview button inside share strip ("Open ↗")
Close / Reopen button merged into status pill
CSV button inside menu
JSON button inside menu
Delete button inside menu (red, last)

menu contents (in order, with separators):

  1. Copy link (when the share strip is hidden on mobile)
  2. Export CSV
  3. Export JSON
  4. ──────
  5. Delete (red)

Share section disappears as a separate block. The short URL is shown inline in the header as one strip:

  • If inst.short_url exists: show it + Copy + Open ↗ + Replace (Replace opens a small inline form under the strip — same <details> pattern as today, but compact).
  • If it doesn't: show "No short link · [ Create one ]" → click reveals the slug input + create button.

This kills today's awkward "section between header and tabs" structure and folds share into the place where the user expects "where do I share this".

Tabs unchanged in count and labels. They stay: Chat / Results / Responses / Edit. Selection style stays the segmented-pill (fb-tabs / fb-tab--active). Whitespace between tab strip and tab body grows from 1.25rem to 2.5rem so the tab body breathes.

Edit tab inline polish:

  • Drop the duplicate <h2>Edit · v3</h2> heading inside the tab — the active tab pill already says "Edit". Save the version pill for a quiet spot next to the Save button.
  • The Visual / JSON toggle becomes a small segmented control in the same shape as the tab pills (consistency).
  • Save button is the page's primary action while this tab is active. No other solid button on the page in that state.

Banner about responses-already-received ({submissions.length} responses already received…) becomes a single muted line above the form, not a banner box.

3.6 /f/[slug] (participant)

┌──────────────────────────────────────────┐
│                                          │
│   Title                                  │  ← h1, room above
│   Optional description                   │
│                                          │
│   ⓘ closed   (only if closed, neutral)   │  ← muted not yellow when closed
│                                          │
│   ─────────────────────────────────────  │  ← 3rem gap
│                                          │
│   Live-Feedback                          │
│   ┌── chat list ──────────────────────┐ │
│   │  …                                │ │
│   └───────────────────────────────────┘ │
│   [ textarea (full width)            ]  │
│                                  [Senden]│
│                                          │
│   ─────────────────────────────────────  │  ← 3rem gap (same as above)
│                                          │
│   Fragebogen                             │
│   q1                                     │
│   q2                                     │
│                                          │
│   [ Absenden ]                           │
│                                          │
│                                          │
│           fdbck.msbls.de                 │
└──────────────────────────────────────────┘
  • Drop the inline-label name row. Replace with a normal labelled field matching the rest of the form:

    Dein Name (optional)
    [Anonym__________________________]
    

    Or move it below the chat/form sections as a footer-style "Du schreibst als: Anonym ✎" with click-to-edit. (Suggested — see open question #5.) For v1 keep it at top but normalise its layout.

  • Increase section gap from 1.75rem to 3rem between the chat block and the form block, so they read as two distinct activities.

  • Closed banner: switch from amber --color-warning palette to a quiet neutral muted style (1px top border + small italic line) — closed is a state, not an alert.

  • Drop the border-color: var(--color-primary) on .fb-chat__post--mine in favour of a subtle left-border-only accent (3px, --color-primary). The current full pill-with-coloured-border treatment is loud.

  • Footer fdbck.msbls.de → wrap as a permalink to /, very muted.


4. Implementation plan

The redesign is only CSS + small .svelte markup edits. No new components, no new dependencies, no schema changes. Suggested commit order (each commit is independently mergeable and testable):

Commit 1 — CSS foundation: spacing scale + typography rhythm

  • src/lib/styles/feedback.css:
    • Add a spacing scale as CSS custom properties (--space-1 through --space-7, or named --gap-row / --gap-field / --gap-section / --gap-foot).
    • Bump .fb-section margin-bottom from 1.75rem--gap-section (≈ 2.5rem).
    • .fb-header h1 weight stays 700; .fb-section h2 weight bumps from 600600 (no change) but tracking -0.01em already there.
    • Add .fb-page-narrow (max-width 480px) and .fb-page-center (vertical grid centre) modifiers for landing/login.
    • Add .fb-toggle for label-left+switch-right boolean fields.
    • Add .fb-row for spacious list rows (no border, no shadow, hover bg) plus .fb-row__title, .fb-row__meta, .fb-row__actions.
    • Add .fb-status-pill (clickable open/closed pill).
    • Add .fb-menu (the dropdown — implemented as <details> + <summary> + a positioned panel).
    • Add .fb-share-strip (the inline header share row in 3.5).
  • No structural Svelte changes in this commit — verify in the browser that the existing pages still render fine since added classes are unused additions.

Commit 2 — landing + login (cheap wins)

  • src/routes/+page.svelte: drop the second paragraph; wrap shell in fb-page-center fb-page-narrow; bump wordmark size.
  • src/routes/login/+page.svelte: drop the "Admin access only." subtitle; wrap in fb-page-center fb-page-narrow; move error from fb-banner--error block to a small inline muted line.
  • Verify both routes in the browser at 375px / 1024px / 1440px.

Commit 3 — /admin/feedback/new

  • src/routes/admin/feedback/new/+page.svelte:
    • Drop the page subtitle.
    • Replace the chat-checkbox block with .fb-toggle.
    • Wrap "Questions (JSON, optional)" + sample button + textarea + helper inside a <details> with summary "Add questions now (advanced)".
    • Remove inline style="..." on the back-link block; replace with a .fb-back-link class (text-only, muted).

Commit 4 — /admin/feedback (list) — biggest change, isolated commit

  • src/routes/admin/feedback/+page.svelte:
    • Drop the H1 paragraph.
    • Drop the H2 "Your forms (N)".
    • Replace each row (today's bordered card with 5 buttons) with the .fb-row pattern from commit 1: title is a link to detail, subtitle merges mode + counts, right side is .fb-status-pill (toggle) + .fb-menu trigger.
    • Move all inline style="..." to classes (no new feature).
    • Add the menu component inline using <details> — no JS framework needed; click-outside-to-close via a small addEventListener in onMount.
  • Add optimistic delete with undo toast (small <aside> element fixed to bottom-centre, setTimeout 6s, calls DELETE only after timeout expires).
  • Verify the live deployed list still looks right after deploy.

Commit 5 — /admin/feedback/[id] (detail) — second-biggest change

  • src/routes/admin/feedback/[id]/+page.svelte:
    • Header collapse per 3.5: status becomes .fb-status-pill, drop raw /f/slug text, drop inline Copy/Preview/Close/Reopen/CSV/ JSON/Delete buttons.
    • Add .fb-share-strip directly under the title/description in the header (replaces the standalone Share section below).
    • Add .fb-menu with Copy link / Export CSV / Export JSON / ────── / Delete.
    • Delete the standalone <section data-fb-share> block — its contents are now in the header strip + a "Replace" inline form.
    • Inside Edit tab: drop the <h2>Edit · v3</h2>, move version pill next to Save; turn Visual/JSON into a segmented pill control matching .fb-tabs.
    • Move submissions.length warning from .fb-banner to muted line.
    • Replace inline style="..." with classes throughout.

Commit 6 — /f/[slug] participant polish

  • src/routes/f/[slug]/+page.svelte:
    • Replace the inline-label name row with a stacked-label field.
    • Increase gap between Chat and Form sections (use --gap-section).
    • Switch "(closed)" banner to neutral muted style (a new .fb-status-line--muted modifier on .fb-banner or a dedicated .fb-closed-line class).
    • Adjust .fb-chat__post--mine styling: drop full coloured border, add border-left: 3px solid var(--color-primary) only.
    • Wrap footer text in an <a href="/"> with aria-label="fdbck home".

Commit 7 — sweep: optimistic toggles, hover-reveal actions

  • Add the optimistic-update + undo-toast pattern to setStatus on the detail page (status pill instant flip, server call after).
  • Apply the same to per-row toggleStatus on the list page.
  • Verify dark-mode pass: walk all five routes in dark mode (browser emulator) since multiple inline style="..." strings were converted to classes that inherit from :root / prefers-color-scheme.

5. Open questions for m

These are decisions m should weigh in on before implementation. Each has my recommendation, but they're all reversible.

  1. Cards vs spacious list for /admin/feedback. I'm proposing a spacious list (no border, lots of whitespace, hover-revealed ). The brief mentions cards as an option. My recommendation: list. Cards add visual chrome (border + shadow) which is the opposite of "negative space". Cards earn their keep when each item has rich content (image, multi-line preview); fdbck rows have title + 2 meta lines.
  2. Optimistic delete with 6s undo, or keep the confirm() modal? Today both list and detail use confirm("…cannot be undone"). The undo toast is smoother but trades safety for fluency. My recommendation: undo toast — the row reappears identically if undone, the destructive call only fires after timeout, no data is actually at risk during the 6s window. Keep confirm() only on detail-page Delete (deleting from the detail page is a more deliberate action and merits an extra step).
  3. Share-link strip in the detail header — does it belong there? I'm folding the standalone Share section into the header (3.5). Alternative: keep Share as a section but move it below the tabs, so the header stays minimal. My recommendation: in the header. Sharing the link is the second-most-common action after viewing results; it belongs near the title.
  4. Drop the Edit tab body's inner H2? Today every tab body has an <h2> echoing the tab name (<h2>Live chat</h2>, <h2>Results</h2>, etc.). I want to drop these — the tab strip already labels the active section. But this is a stylistic call. My recommendation: drop the inner H2s, add 2rem of top padding to the tab body so the active tab pill alone titles the section.
  5. Participant name field — top, bottom-as-footer, or bottom-as- "edit"? Today it's at the top with an inline label. I'm proposing stacking it the same as other fields. A bolder alternative: move it to a footer-style "Du schreibst als: Anonym ✎" below all sections. My recommendation for v1: stacked label, top. Bolder move waits for v2.
  6. Locale homogenisation. Admin pages are English, participant page is German. Out of scope for this redesign — flagging only so we don't accidentally translate one of them while doing the markup pass. Confirm this stays as-is.
  7. Accent on --color-primary. Same green stays per brief. But today some screens have box-shadow: 0 0 0 3px rgb(22 163 74 / 0.15) on focus and others have 0.25 opacity — minor inconsistency. Worth normalising during commit 1? My recommendation: yes, normalise to one focus-ring rule (0.2 opacity, 3px).

6. Anti-scope (explicitly NOT in this redesign)

  • Palette: no new colours, no new accent.
  • Stack: still SvelteKit + vanilla CSS + Inter. No new deps.
  • Routes: unchanged URL structure.
  • Data model: unchanged.
  • Locale: no homogenisation (see Q6).
  • Polling intervals (5s admin, 3s chat): unchanged.
  • Auth flow / share-link backend: unchanged (only the display of the share link in the detail header changes).