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

707 lines
39 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
`600` → `600` (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).