Files
novelly/docs/plans/web/frontend-modernization_output.md
T
James Wampler 1423977ed4 Modernize web client: dark phase-driven theme, sidebar shell, global agent panel
Replaces the warm-paper/serif look with a dark palette where the novel's
lifecycle phase drives the accent color app-wide. Sidebar nav replaces the
old header/tab-bar. Dashboard leads with quick actions (new chapter, new
character, continue writing) instead of just showing history. Agent chat
is now a context-aware slide-out panel reachable from any page in a novel,
replacing the buried /agent tab.
2026-08-20 14:21:44 -07:00

4.9 KiB

Frontend Modernization — Output

Implemented per docs/plans/web/frontend-modernization_plan.md, all 5 chunks.

Chunk 1 — Design tokens + primitives

  • src/index.css: full token rewrite. Dark-first palette (--canvas, --surface, --surface-sunken, --ink, --ink-muted, --line), violet --accent default, light-mode override via prefers-color-scheme + data-theme.
  • Five-stage color ramp --stage-1..5 (violet → blue → coral → teal → gold), shared by NovelPhase and DraftStatus via src/api/stage.ts (novelPhaseColor, draftStatusColor) — both are 5-step progressions, one hue system backs both.
  • Fonts self-hosted via @fontsource-variable/* (no CDN dep): Fraunces (display), Inter (UI), Source Serif 4 (prose/markdown), JetBrains Mono (utility). Imported in src/main.tsx.
  • src/components/ui.tsx primitives (.card, .btn, .input, StatusBadge, etc.) rebuilt on the new tokens.

Chunk 2 — Sidebar shell

  • src/pages/NovelLayout.tsx rebuilt: left sidebar (wordmark, novel title, phase pill, icon nav) replaces the old header + horizontal tab bar. Kills the old back-link-next-to-title layout — top bar is now just a breadcrumb.
  • New src/components/icons.tsx — small hand-written inline SVG icon set (no icon library dependency).
  • Signature element: novel's phase sets --accent/--accent-soft for the whole layout, scoped via inline style on the layout root. Nav active state, buttons, focus rings, phase pill all recolor together when phase changes.
  • Bug fixed during build: breadcrumb section-matching used a suffix startsWith check that broke on exact segment matches (chapters vs chapters/) — replaced with explicit segment split/compare.

Chunk 3 — Dashboard rebuild

  • src/pages/DashboardPage.tsx: quick-actions row now leads the page — New chapter (creates + jumps into the editor), New character (reuses the add-character modal, now exported from CharactersPage.tsx), and Continue writing (jumps to the most-recently-updated chapter, or View chapters if nothing's drafted).
  • Brainstorming phase gets its own pair above the notes field: Add a character / Move to outlining.
  • Renamed OutliningDashboardWorkDashboard (it covers Outlining/Writing/Editing/Complete, not just Outlining — old name was misleading).
  • History content (activity graph, recent chapters/characters, tag cloud) unchanged, just repositioned under the new hero row.

Chunk 4 — Global agent panel

  • /agent route and pages/AgentPage.tsx retired.
  • New src/components/AgentPanel.tsx: fixed slide-out drawer mounted in NovelLayout (shell level), reachable from every page in a novel via the sidebar "Agent" toggle or g a. Non-modal — background stays interactive.
  • Context-aware: panel shows "Talking about {X}" — resolves to the specific chapter/character title on detail pages, falls back to section name elsewhere. Each outgoing message gets a Context: {label} line prepended (server has no route awareness, so this is how the agent learns what page you're on); stripped back out and shown as a small "re: …" tag on render rather than raw text in the transcript.
  • Compacted the old two-pane (sidebar list + chat) layout into a single column with a conversation-switcher dropdown — panel width doesn't fit a full list rail.
  • No backend changes — works within the existing SendAgentMessageRequest shape.

Chunk 5 — Polish

  • Global :focus-visible ring via box-shadow (not outline, to avoid clobbering TagColorPicker's outline-based selection indicator or .input's own focus ring). Ring color follows the phase accent.
  • Global prefers-reduced-motion: reduce override (!important on animation-duration/transition-duration/scroll-behavior) — neutralizes the agent panel's slide transition too, since author !important beats a normal-priority inline style in the cascade.
  • Fixed two leftover hardcoded #9a4a2f (old terracotta accent) defaults in TagColorPicker.tsx and TagsPage.tsx → new violet #7c5cff.
  • Audited remaining pages (Settings, Locations, Tags, Characters, Chapters) — all inherit cleanly from the chunk-1 primitives already, no stale styling found.

Verification

Every chunk built clean (npm run build) and was clicked through live in Chrome against a local API + SQLite instance — login/signup, novel creation, phase switching (confirmed accent recolor live: violet → blue → coral), chapter/character creation flows, agent panel open/close/context-swap across navigation, keyboard focus ring.

Deferred / not done

  • Sidebar collapse toggle — mentioned in the original plan's layout description ("persistent, icon+label, collapsible") but never implemented; flagged as deferred in chunk 2 and again in chunk 5. Would need its own pass (collapsed-width icon rail, persisted preference).
  • No backend/API changes anywhere in this arc — all five chunks were frontend-only.