docs(webui): implementation plan for welcome screen polish

This commit is contained in:
m4
2026-08-10 22:26:11 +08:00
parent 37f9944ca1
commit 92acc7802e
@@ -0,0 +1,192 @@
# Welcome Screen Polish 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:** Add a gradient brand mark + larger title and pastel-tinted stat cards to the chat welcome screen, per the approved spec.
**Architecture:** Two-file, class-string-only change: the welcome block in `ChatInterface.tsx` and the stats grid in `ResearchDashboard.tsx`. No logic changes.
**Tech Stack:** Tailwind CSS 3 (`darkMode: "class"`), lucide-react icons, Vitest.
**Spec:** `docs/superpowers/specs/2026-08-10-welcome-screen-polish-design.md`
## Global Constraints
- Purely visual: `npx tsc --noEmit`, `npx eslint` on the two files, `npm test` must stay green.
- `src/app/components/ChatInterface.tsx` contains unrelated uncommitted user changes — the implementer edits but does NOT stage or commit it; the controller stages only the task's hunk via filtered `git apply --cached`. `src/app/components/ResearchDashboard.tsx` is clean.
- NEVER use `git add -A` / `git add .`. Do not touch `src/app/components/ContextUsageIndicator.tsx` (untracked user WIP).
- Known pre-existing lint noise: `src/app/components/MarkdownContent.tsx` has an eslint error from user WIP — ignore it.
- All tinted classes are full static strings per stat — no dynamic Tailwind class construction (JIT must see them).
- Commit style: `style(webui): …`.
---
### Task 1: Gradient brand mark + pastel stat cards
**Files:**
- Modify: `src/app/components/ChatInterface.tsx` (~line 1744 welcome block; NOT committed by implementer)
- Modify: `src/app/components/ResearchDashboard.tsx` (stats grid; clean, committed normally)
**Interfaces:**
- Consumes: existing tokens (`--ring` for focus rings). Produces nothing — leaf change.
- [ ] **Step 1: Brand tile + larger title in the welcome block**
In `src/app/components/ChatInterface.tsx`, add `Sparkles` to the existing `lucide-react` import (alphabetical position among the existing named imports; there is a multi-import from `lucide-react` near the top of the file).
Find (lines 1744-1747):
```tsx
<div className="flex min-h-[42vh] flex-col items-center justify-center px-3 pt-12 text-center sm:pt-16">
<h2 className="text-pretty text-lg font-semibold sm:text-xl">
Where research evolves
</h2>
```
Replace with:
```tsx
<div className="flex min-h-[42vh] flex-col items-center justify-center px-3 pt-12 text-center sm:pt-16">
<div className="mb-4 grid size-14 place-items-center rounded-2xl bg-gradient-to-br from-cyan-400 to-cyan-600 shadow-lg shadow-cyan-500/30">
<Sparkles
className="size-7 text-white"
aria-hidden="true"
/>
</div>
<h2 className="text-pretty text-2xl font-semibold tracking-tight sm:text-3xl">
Where research evolves
</h2>
```
- [ ] **Step 2: Per-stat tint fields in `ResearchDashboard.tsx`**
In the `stats` array type (lines 172-179), add two fields to the inline type:
```ts
const stats: Array<{
value: string | number;
unit?: string;
label: string;
hint: string;
Icon: typeof Network;
cardClass: string;
tileClass: string;
target: NavTarget;
}> = [
```
Add to each stat entry, respectively:
Knowledge:
```ts
cardClass:
"border-cyan-100 bg-cyan-50 dark:border-cyan-900/50 dark:bg-cyan-950/40",
tileClass:
"bg-cyan-100 text-cyan-700 dark:bg-cyan-900/60 dark:text-cyan-300",
```
Timeline:
```ts
cardClass:
"border-violet-100 bg-violet-50 dark:border-violet-900/50 dark:bg-violet-950/40",
tileClass:
"bg-violet-100 text-violet-700 dark:bg-violet-900/60 dark:text-violet-300",
```
Workspace:
```ts
cardClass:
"border-amber-100 bg-amber-50 dark:border-amber-900/50 dark:bg-amber-950/40",
tileClass:
"bg-amber-100 text-amber-700 dark:bg-amber-900/60 dark:text-amber-300",
```
Scheduled:
```ts
cardClass:
"border-emerald-100 bg-emerald-50 dark:border-emerald-900/50 dark:bg-emerald-950/40",
tileClass:
"bg-emerald-100 text-emerald-700 dark:bg-emerald-900/60 dark:text-emerald-300",
```
- [ ] **Step 3: Card + icon-tile markup**
In the stats map (line 215), change the destructure from:
```ts
{stats.map(({ value, unit, label, hint, Icon, target }) => (
```
to:
```ts
{stats.map(
({ value, unit, label, hint, Icon, cardClass, tileClass, target }) => (
```
Replace the button's className (line 224):
```ts
className="hover:border-[var(--brand)]/40 flex min-h-[82px] flex-col items-center justify-center gap-1 rounded-md border border-border bg-[var(--color-surface)] px-2 py-2.5 transition-colors hover:bg-accent/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
```
with (template literal, static parts first):
```ts
className={`flex min-h-[82px] flex-col items-center justify-center gap-1 rounded-xl border px-2 py-2.5 transition-all hover:-translate-y-0.5 hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${cardClass}`}
```
Replace the icon (lines 226-229):
```tsx
<Icon
className="size-4 text-[var(--brand)]"
aria-hidden="true"
/>
```
with:
```tsx
<span
className={`grid size-8 place-items-center rounded-lg ${tileClass}`}
>
<Icon
className="size-4"
aria-hidden="true"
/>
</span>
```
(The existing prettier setup will reformat the map callback's closing parens; run `npx prettier --write src/app/components/ResearchDashboard.tsx` after edits to normalize.)
- [ ] **Step 4: Verify**
Run: `npx tsc --noEmit && npx eslint src/app/components/ChatInterface.tsx src/app/components/ResearchDashboard.tsx && npm test`
Expected: clean, all tests pass (310 passed / 1 skipped).
- [ ] **Step 5: Commit**
Implementer commits ONLY ResearchDashboard.tsx:
```bash
git add src/app/components/ResearchDashboard.tsx
git commit -m "style(webui): pastel-tinted stat cards on welcome screen"
```
The controller then stages the ChatInterface.tsx welcome-block hunk (filtered `git apply --cached`) and commits:
```bash
git commit -m "style(webui): gradient brand mark and larger welcome title"
```
- [ ] **Step 6 (controller, not implementer):** Hand to the user for the visual gate (welcome screen, light + dark).
---
## Self-Review Notes (already applied)
- **Spec coverage:** A → Step 1; B (tint table, icon tile, hover lift, dark mode) → Steps 2-3. Focus rings kept (`ring-ring`) per spec.
- **Placeholder scan:** every edit has exact old/new strings with line anchors (lines may drift ±5 due to user WIP — search, don't trust numbers).
- **Type consistency:** `cardClass`/`tileClass` names used in Steps 2 and 3 match.
- **Risk:** the stats-map destructure line is long after adding two fields; Step 3 mandates prettier to keep formatting consistent with repo style.