Skip to content

Phase 2 — Consumer UI redesign (light Calm-Focus, mobile-first, RTL)#12

Merged
tornidomaroc-web merged 14 commits into
mainfrom
feat/phase-2-ui-redesign
Jul 4, 2026
Merged

Phase 2 — Consumer UI redesign (light Calm-Focus, mobile-first, RTL)#12
tornidomaroc-web merged 14 commits into
mainfrom
feat/phase-2-ui-redesign

Conversation

@tornidomaroc-web

@tornidomaroc-web tornidomaroc-web commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Phase 2 — Consumer UI redesign (web, mobile-first)

Migrates the entire product from the legacy dark theme to the light "Calm Focus" palette, mobile-first, with Arabic/RTL as a first-class concern. Visually verified on the Vercel preview in Arabic (/ar) — landing, dashboard, and Ask pages render correctly on light surfaces at desktop and mobile widths; RTL is mirrored (right sidebar, bottom tab bar in correct order); the streak shows the honest ghost , not a misleading 0; and the decided vocabulary (المواد / الملفات / اسأل / اسأل ملفاتك) displays correctly. Nothing broken.

Merging rebuilds the production deployment (tryknowflow.com) with the new design — intended, now that it's verified.

What the redesign delivered

  • P2.0 — Design-token + font foundation: light Calm-Focus tokens + Rubik (renders Arabic well).
  • P2.1 — UI primitives (Button/Card/Input/Badge/Sheet on cn()) + mobile-first dashboard shell / sidebar / bottom nav; RTL via logical properties.
  • P2.2 — Student home (thin wrapper + dumb StudentHome); honest ghost streak placeholder (reads as not measured, not zero).
  • P2.3 — Subjects list + subject detail + upload-zone restyle.
  • P2.4 — Ask/chat (KBSelector/ChatBox/MessageBubble/ConversationSidebar) + Sheet focus trap.
  • P2.5 — New-subject form + settings/plan (dumb SettingsPanel); <a><Link> upgrade CTA verified against Paddle init-on-mount.
  • P2.6 — All public + auth pages migrated to light (landing, pricing, about, contact, privacy, terms, refund, login, signup) — presentation-only, copy/wiring/RTL preserved. Closes the light→dark seam a Pro user hit from Settings → /pricing.
  • P2.7 — Flipped the three shared dark surfaces to light (dashboard <main>, root <body>, globals.css body {}), removed every per-screen light-canvas bridge, and purged the dead legacy tokens (--bg-color/--accent-color/--border-color/--muted-color/--input-bg + --font-playfair/--font-mono/--font-sans). Full sweep: zero legacy tokens/hexes remain in src.

Honesty / correctness fixes made along the way

Explicitly deferred — still tracked in docs/PROGRESS.md §4

Notes

  • Also merges main's in-flight docs: the resolved Supabase blocker (#21) and the new pre-launch backend item (#22), with supabase-migration-runbook.md marked SUPERSEDED. docs/PROGRESS.md PROGRESS conflict was resolved to keep both truths (Phase 2 complete and #21/#22).
  • Merge method: merge commit (no squash) so main retains all individual P2.0–P2.7 commits. Merged without --admin so branch protection / enforce_admins is honored (0 required approvals).

🤖 Generated with Claude Code

Groundwork for the Calm Focus, light-first, emerald-accent redesign. No
screen redesigned yet — the app looks the same except it now renders in
Rubik (which finally styles Arabic instead of an unstyled fallback).

- globals.css: semantic design tokens as CSS variables (background,
  surface, foreground, muted, border, input, ring, primary + variants,
  radius). Architected dark-ready — a future .dark {} overrides values
  with no utility changes. Legacy neon vars kept temporarily (removed
  screen-by-screen in P2.1-P2.7); transitional font aliases map the old
  --font-playfair/-mono/-sans to Rubik so the in-between app is uniformly
  Rubik, never a broken fallback.
- tailwind.config.ts: theme.extend wires the tokens (colors, fontFamily,
  radius, soft/card shadows); darkMode: 'class' for the dark-ready path.
- layout.tsx: swap the three Latin-only Google fonts (Playfair/DM Mono/
  DM Sans) for Rubik (subsets: latin + arabic); delete the duplicated
  inline <style> color block (globals.css is now the single source).
- add lucide-react (MIT) for a consistent icon set.

Presentation-only; no API/auth/i18n/RTL logic touched; no locale strings
changed; no migration. Production build passes (en+ar generated, Rubik
arabic subset resolves); tsc --noEmit passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
knowflow Ready Ready Preview, Comment Jul 4, 2026 2:44pm

@tornidomaroc-web

tornidomaroc-web commented Jul 1, 2026

Copy link
Copy Markdown
Owner Author

🛡️ Fixor Security Report

Repository: tornidomaroc-web/knowflow · PR: #12
Commit: 78df8547c638d3ea83c2f9fdb149c64358b796e2

Summary

Workflow status no_action
Findings scanned 1
Vulnerabilities classified 0
Findings reported 0
Duration 36 ms

No findings in this run — no business-logic vulnerabilities detected.

⚠️ 1 pre-existing issue in files this PR touches — not introduced by this PR

Detection-only: these sit on code this PR did not change. Listed for visibility, not as requests to fix them in this PR.

  • src/lib/i18n/locales/en.ts:89 · secrets_exposure_risk · Password assigned to a hardcoded string of length 8+. Possible types: database password (rotate at the DB, update env var, restart services), service-account c…

🔒 Analyzed by Fixor · 2026-07-04T14:52:06.292Z

First consumers of the Calm Focus palette: the dashboard chrome goes
light; content stays on the legacy dark surface until each screen is
migrated (P2.2+), so un-redesigned screens' white text does not vanish.

Primitives (hand-built on the existing cn(), token-only, no framework):
- ui/Button (variants + sizes, 44px default tap target, buttonVariants
  helper for link styling), Card, Input, Badge, Sheet (controlled
  drawer; Escape + overlay close, aria-modal; no focus trap yet).

Shell:
- Desktop Sidebar rewritten in the light palette (surface, tokens, lucide
  icons, active = primary-subtle). Mobile drops the old checkbox-drawer
  hack for a slim top bar (brand + sign-out) plus a bottom tab bar
  (thumb-reachable, >=44px, safe-area padded for the Phase 8 Capacitor
  shell).
- RTL now via Tailwind logical properties (start-0, border-e, ms-60) that
  auto-mirror under dir="rtl" -- cleaner than the prior isRtl branching.
- Shared SignOutButton keeps the exact client-Supabase signOut + redirect
  in one place, used by both sidebar and mobile top bar.

Presentation-only: auth/entitlement/redirect logic in the server layout
preserved verbatim; no locale strings changed; no migration. tsc and a
production build pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restructure the dashboard home into a student home on light surfaces —
the first CONTENT screen to leave the legacy dark panel.

- Split into a thin server wrapper (page.tsx: auth + the 3 count queries +
  activity fetch, all unchanged) and a dumb, prop-driven <StudentHome/>
  presentational component (Phase 8 reuse).
- Sections: welcome header, primary "Ask" entry, an inert streak placeholder
  (renders 0; Phase 5 wires real tracking), subject stats, subjects
  quick-access, and a restyled RecentActivity.
- Root paints its own light canvas so every heading/label/card sits on a
  light surface with dark tokens — nothing inherits the layout's legacy
  text-white, so nothing vanishes. The dark <main> gutter closes when the
  whole layout flips light at the end of Phase 2.
- RTL-safe: logical properties + rtl:-scale-x-100 on directional arrows.
- Locale: home-only reword of talkAgentTitle out of terminal caps; add
  newSubject/streakLabel/streakUnit (en+ar). Shared newKb* keys untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Switch the inert streak placeholder from a muted "0" to a ghost "—". A "0"
asserts a live measurement that happens to read zero (and would read 0 even
for a returning active student until Phase 5) — the same soft over-implication
refused with "Unlimited"/"page citations". "—" reads as "not tracked yet".

- streak prop is now number | null: null → ghost "—" (unit suppressed so it
  doesn't re-imply a days measurement); a real number renders normally, so
  Phase 5 just passes a value with no component change.

Presentation-only; locale untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restyle the subjects screens and the upload zone to the light Calm-Focus
palette. Presentation-only; data/upload wiring untouched.

- knowledge/page.tsx → thin server wrapper (list fetch + ordering verbatim)
  feeding a new dumb <SubjectsList/> (prop-driven hrefs/labels, Phase 8 reuse).
- knowledge/[id]/page.tsx is a client component, so it's restyled in place:
  the load effect, docs state, DropZone optimistic onSuccess, and statusColor
  mapping are preserved (status hexes swapped for AA-safe light tokens).
- DropZone: restyle only. accept=".pdf,.docx,.pptx,.xlsx,.txt,.md" kept EXACTLY
  (still matches the "Supported" hint and the server ALLOWED_TYPES); handleFile,
  onDrop, the /api/ingest fetch, the state machine, and onSuccess are unchanged.
  Added an Upload affordance icon (idle state only) — no format implications.
- Each screen paints its own light canvas so headings/cards/labels use dark
  tokens and nothing inherits the layout's legacy text-white. Directional
  arrows flip under RTL (rtl:-scale-x-100); language badge preserved.

Locale untouched (diff-clean); shared newKb* keys intact for the agent screen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restyle the highest-logic screen to the light Calm-Focus palette. All engine
logic is preserved verbatim — restyle only.

- Sheet: ADD a focus trap (P2.4 commitment). Focus moves into the panel on
  open, Tab/Shift+Tab cycle within it, focus restores to the trigger on close;
  existing Escape + overlay-close + aria-modal kept. First real Sheet use.
- KBSelector: modern chat layout — desktop keeps the persistent history column;
  mobile moves it into a Sheet drawer (start-side, RTL-aware) opened by a Menu
  button. Subject pills stay single-select (switch active subject + reset
  conversation) — never a cross-subject/multi-select search. Selection/mount/
  fetch logic unchanged; the only additions are drawer open/close state.
- ChatBox: restyle only — handleSend, the SSE reader loop, decodeCitations, the
  X-Conversation-Id / X-Citations header reads, scroll, and Cmd+Enter are
  byte-for-byte unchanged.
- MessageBubble: light bubbles (emerald user / bordered assistant); markdown
  marks inherit the bubble color so they read on both. Citations still render
  [n] filename + a "filename · NN% match" tooltip — no page numbers.
- agent/page.tsx → thin server wrapper; no-subjects case is the dumb
  <AgentEmptyState/> (Phase 8 reuse).
- Each screen paints its own light canvas so nothing inherits the layout's
  legacy text-white. Locale: add agent.history (en+ar) for the drawer label;
  shared newKb* keys untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ror (P2.4)

Honesty fix (scoped exception to P2.4's presentation-only rule). The rate-limit
429 is sent as text/plain, but handleSend did `if (!res.ok) throw` → the catch
rendered the generic "Connection error." — hiding the real reason AND implying a
technical failure. A limited student would think the app is broken.

Now the !res.ok branch reads the response body and renders THAT as the assistant
message (falling back to the generic string only when the body is empty), then
returns before the streaming path. Confined to that branch: the SSE stream loop,
decodeCitations, and the X-Conversation-Id/X-Citations reads are untouched, and
genuine network/stream failures still land in catch with the friendly fallback.

Locale diff-clean: the message comes from the server; only the empty-body
fallback reuses the existing connectionError string.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restyle the new-subject form and the settings/plan screen to the light
Calm-Focus palette. Presentation-only; wiring preserved verbatim.

- new/page.tsx is a client component → restyled in place. handleSubmit is
  untouched: the auth check, /api/check-limit fetch, and the tier-correct,
  interpolated limit message (template = pro ? errorLimitPro : errorLimitFree;
  replace('{limit}', limit)) are byte-for-byte preserved — no hardcoded number,
  no free-plan wording leaking to Pro. Inputs use the light Input primitive /
  field styling; native select arrow kept for a clear (RTL-correct) affordance.
- settings/page.tsx → thin server wrapper feeding a new dumb <SettingsPanel/>
  (Phase 8 reuse). getEntitlement stays the sole tier source (never a raw
  subscriptions read); isPro, the locale-aware renewal date, the /pricing
  upgrade path, and the active-subscription text are all preserved. The user
  email is present in the Account card (its intended home after being dropped
  from mobile chrome and the home header).
- Each screen paints its own light canvas so nothing inherits the layout's
  legacy text-white. Locale untouched (diff-clean); shared keys intact.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tornidomaroc-web and others added 2 commits July 3, 2026 02:33
First of three P2.6 commits. Migrate the auth pages to the light Calm-Focus
palette; presentation-only, all wiring preserved verbatim.

- login: `signInWithPassword` + `router.push`, form state, and the
  show/hide-password toggle are unchanged — only classNames/structure flipped
  to light (brand panel now emerald `bg-primary`, form on `bg-surface`, light
  inputs). RTL upgraded to logical properties (`border-e`, `end-3`, `text-start`).
- signup: `signUp` + the `profiles` upsert (incl. `plan: 'free'`, `full_name`,
  `email`) + `router.push` unchanged; same light restyle.
- Each page paints its OWN light canvas (`bg-background`) — the root `<body>` /
  `globals.css` dark surfaces are deliberately NOT touched (that's P2.7).
- Locale `t.*` untouched (diff-clean); no migration.

Also lands PROGRESS.md: register #17–19 (legal pages English-only; stale
vocab/domains; non-functional contact form) + P2.6 split (a done, b/c remaining).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Second of three P2.6 commits. Migrate the two converting pages to the light
Calm-Focus palette; presentation-only, all wiring preserved verbatim.

- landing: every href unchanged — the three `/signup` CTAs (nav, hero cta1,
  bottom CTA), the nav `/pricing`+`/about`, `#how-it-works` (×2), and the footer
  privacy/terms/refund/Support(contact)/GitHub links. All `t.*` copy untouched.
  Hero terminal mock restyled to a light code card (traffic-light chrome kept).
- pricing: the `initializePaddle` mount effect, the checkout `onClick`
  (getUser → login redirect → `/api/paddle/checkout` → `paddle?.Checkout.open`),
  and the free-plan `<Link href=/signup>` are byte-for-byte unchanged — only
  classNames flipped to light (Pro card `border-primary`, error → red-700).
- Each page paints its OWN light canvas (`bg-background`); root `<body>` /
  `globals.css` NOT touched (P2.7). Locale `t.*` diff-clean; no migration.

PROGRESS.md: register #20 (landing "Ready in 0.4s" is a hardcoded speed
over-promise the real ingestion doesn't meet) + P2.6b marked done. #17/#18
extended to name the auth "Unlock your knowledge" tagline (i18n + stale-vocab).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Third of three P2.6 commits. Migrate the low-wiring content pages to light;
presentation-only, content and wiring preserved verbatim.

- about: restyle only; the `/signup` CTA + all `t.about.*` copy unchanged.
- contact: mailto (`hello@tryknowflow.com`) + GitHub link preserved; the form is
  left HONESTLY INERT — `type="button"`, no onSubmit/handler added (register #19
  wire-or-mailto-only is a later decision, not this restyle). Inputs restyled.
- privacy / terms / refund: prose text is byte-identical to main (md5-verified);
  only the wrapper/headings flipped to light and the dead `prose prose-invert`
  classes dropped (no typography plugin installed). Content stays English under
  /ar by design — pre-existing, tracked as #17/#18, NOT a regression here.
- Each page paints its own `bg-background` bridge; root `<body>` / `globals.css`
  NOT touched (P2.7). Locale `t.*` diff-clean; no migration.

PROGRESS.md: P2.6c done → P2.6 COMPLETE (only P2.7 remains). #20 reclassified
into the honesty/over-promise bucket (false speed claim, not i18n).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…7) — Phase 2 complete

The final flip + audit. Presentation-only in effect; no wiring/copy/locale change.

FLIP the three shared dark surfaces to the semantic light palette:
- dashboard `<main>` (dashboard/layout.tsx): bg-[var(--bg-color)]/text-white → bg-background/text-foreground.
- root `<body>` ([locale]/layout.tsx): same.
- globals.css `body {}`: var(--bg-color)/white → var(--background)/var(--foreground).

REMOVE every per-screen/per-page light-canvas bridge that compensated for the
dark root, now redundant:
- 6 dashboard screens (StudentHome, SubjectsList, SettingsPanel, AgentEmptyState,
  knowledge/new, knowledge/[id]): drop the `rounded-2xl bg-background p-4 md:p-6`
  self-canvas wrapper (was double-padding on the now-light main); the `<main>`
  owns the canvas + padding. Stale "paints its own canvas" comments corrected.
- 9 public/auth pages: drop the redundant root `bg-background text-foreground`
  (body provides it). Only the root className changed — all auth/Paddle/CTA
  wiring untouched (verified: signInWithPassword, signUp + profiles upsert +
  plan:'free', initializePaddle + checkout all intact).

PURGE the dead legacy tokens (confirmed zero references repo-wide first):
- --bg-color/--accent-color/--border-color/--muted-color/--input-bg
- transitional font aliases --font-playfair/--font-mono/--font-sans.

Audit: full sweep shows zero legacy tokens/hexes/`text-white` remain in src;
tsc clean; locale files not in the diff. PROGRESS.md: P2.7 done, #13 resolved,
Phase 2 code-complete (pending PR #12 merge).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tornidomaroc-web tornidomaroc-web changed the title Phase 2: modern mobile-first UI redesign Phase 2 — Consumer UI redesign (light Calm-Focus, mobile-first, RTL) Jul 4, 2026
@tornidomaroc-web tornidomaroc-web marked this pull request as ready for review July 4, 2026 14:43
@tornidomaroc-web tornidomaroc-web merged commit 7722373 into main Jul 4, 2026
2 checks passed
@tornidomaroc-web tornidomaroc-web deleted the feat/phase-2-ui-redesign branch July 4, 2026 14:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant