Redesign: Complete UI overhaul with dark mode#32
Conversation
…ection PowerPoint Online opens the slideshow in a new browser window; the add-in runs in the original editor window and cannot access the slideshow context. Instead of trying (and failing) to detect the presented slide via getSelectedSlides in read mode, we now only slow the poll cadence (500ms → 1000ms) and re-sync immediately when returning to edit mode. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rework entire design system: cleaner colors, sharper typography, proper shadows - Add dark mode with class-based toggle (persisted in localStorage) - Create ThemeToggle component (sun/moon icon, bottom-right) - Redesign landing page: centered hero, interactive mockup, 3-step workflow, feature grid, target audiences, CTA section with footer - Redesign auth pages: split-screen layout (indigo left panel + form right) - Redesign dashboard: compact header, clean stats + tabs - Redesign PowerPoint page: simpler step-based layout - Fix all German umlauts (ue→ü, oe→ö, ae→ä) across all files - Rewrite all UI copy to be more concrete and benefit-oriented Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughRedesign of UI/layout and global theming with CSS variable-driven tokens and class-based dark mode; updated fonts and a ThemeToggle; many pages/components restyled and copy adjusted; PowerPoint bridge polling made adaptive to active view (edit vs read) with view-change handling. Changes
Sequence Diagram(s)sequenceDiagram
participant UI as App UI
participant Bridge as OfficeBridge
participant Office as PowerPoint (Office.js)
UI->>Bridge: initOfficeBridge()
Bridge->>Office: startPolling(intervalMs = POLL_EDIT_MS)
loop polling
Bridge->>Office: requestCurrentSlide()
Office-->>Bridge: currentSlideInfo
Bridge->>UI: syncCurrentSlide(info)
end
Office-->>Bridge: activeViewChanged(activeView)
Bridge->>Bridge: normalize view -> "edit"/"read"
Bridge->>Bridge: startPolling(intervalMs = POLL_READ_MS or POLL_EDIT_MS)
Bridge->>Office: syncCurrentSlide() (on view change)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~65 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Greptile SummaryThis PR delivers a complete UI overhaul for the Key changes:
Confidence Score: 4/5Safe to merge after fixing the undefined CSS variables in Modal.tsx — one targeted fix remains before all modals render correctly. The vast majority of changes are clean UI/styling work with no logic regressions. The dark mode implementation is solid (FOUC-prevention script, localStorage persistence, hydration warning suppressed). The one concrete bug — undefined
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["layout.tsx — RootLayout"] -->|"Inline script (FOUC prevention)"| B["Check localStorage 'theme'"]
B -->|"'dark' or prefers-color-scheme:dark"| C["Add .dark to <html>"]
B -->|"Otherwise"| D["No class (light mode)"]
A --> E["ConvexClientProvider"]
E --> F["{children}"]
E --> G["ThemeToggle (client)"]
G -->|"onClick"| H["Toggle .dark on <html>"]
H --> I["localStorage.setItem('theme', ...)"]
C --> J["globals.css .dark { --paper, --ink, --accent... }"]
D --> K["globals.css :root { --paper, --ink, --accent... }"]
J --> L["All components read CSS vars"]
K --> L
Reviews (1): Last reviewed commit: "redesign: complete UI overhaul with dark..." | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 9
🧹 Nitpick comments (2)
apps/web/src/components/ThemeToggle.tsx (1)
24-28: Expose toggle state witharia-pressed.This is a toggle button; adding
aria-pressedimproves assistive-tech state reporting.♿ Suggested patch
<button onClick={toggle} className="theme-toggle" aria-label={dark ? "Helles Design aktivieren" : "Dunkles Design aktivieren"} + aria-pressed={dark} >🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/components/ThemeToggle.tsx` around lines 24 - 28, The ThemeToggle button currently uses aria-label but doesn't expose its pressed state; update the button in ThemeToggle (the element with onClick={toggle} using the dark state) to include aria-pressed={dark} so assistive tech can detect the toggle state; ensure you reference the existing dark boolean and toggle handler (onClick={toggle}) when adding aria-pressed to the button element.apps/web/src/app/globals.css (1)
263-264: Add a reduced-motion fallback for animation utilities.These utilities currently animate unconditionally. A
prefers-reduced-motionoverride will improve accessibility.Proposed change
`@layer` utilities { .text-balance { text-wrap: balance; } .animate-fade-up { animation: fade-up 600ms ease-out both; } .animate-soft-float { animation: soft-float 6s ease-in-out infinite; } } + +@media (prefers-reduced-motion: reduce) { + .animate-fade-up, + .animate-soft-float { + animation: none !important; + } +}Also applies to: 311-314
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/app/globals.css` around lines 263 - 264, The animation utility classes (.animate-fade-up and .animate-soft-float, plus the other animation utilities around the block at lines ~311-314) currently run unconditionally; add a prefers-reduced-motion media-query override so animations are disabled for users who prefer reduced motion. Concretely, wrap or override these classes inside an `@media` (prefers-reduced-motion: reduce) { ... } block to set animation: none (or animation-duration: 0ms / animation-name: none) for .animate-fade-up, .animate-soft-float and the other animation utility class names to provide an accessible reduced-motion fallback.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/web/src/app/dashboard/handout/`[id]/page.tsx:
- Around line 94-107: The icon-only move buttons that call
onMoveBlock(block._id, "up") and onMoveBlock(block._id, "down") lack accessible
names; add aria-label attributes to both buttons (e.g., aria-label="Move block
up" and aria-label="Move block down") alongside the existing title so screen
readers announce the purpose while leaving disabled logic and onClick handlers
unchanged.
In `@apps/web/src/app/dashboard/page.tsx`:
- Line 211: The external link anchor that renders Handout (the <a> element using
href={`/h/${s.publicToken}`} with target="_blank` and className="btn-secondary")
is missing a rel attribute; update that anchor to include rel="noopener
noreferrer" to prevent the opened page from accessing window.opener and mitigate
reverse tabnabbing.
In `@apps/web/src/app/globals.css`:
- Around line 197-199: Replace the hard-coded rgba in the CSS rule that
currently uses background: var(--warning-soft); border: 1px solid
rgba(217,119,6,0.2); color: var(--warning); with a semantic CSS variable (e.g.
--warning-soft-border or --soft-note-border) so the border adapts in dark mode;
add the new variable to the token definitions alongside --warning-soft and
--warning (with an appropriate dark-mode value) and update the border
declaration to use var(--warning-soft-border, rgba(217,119,6,0.2)) for
backwards-compatible fallback.
- Line 122: The CSS file has stylelint "declaration-empty-line-before"
violations for several property declarations (e.g., the line with "background:
var(--paper-strong);"); update the spacing to match the project's
declaration-empty-line-before rule by adding or removing the single blank line
immediately before each listed declaration so they conform to the configured
style (apply the same change for the other reported lines). Locate occurrences
by searching for the property tokens like "background:" (and similar
declarations on the referenced lines) in globals.css and normalize the
blank-line presence, or run stylelint --fix to automatically apply the correct
spacing.
In `@apps/web/src/components/dashboard/BlockEditor.tsx`:
- Line 233: The error alert in BlockEditor.tsx uses only light-theme classes on
the div (currently "rounded-2xl border border-red-300/40 bg-red-50/90 px-4 py-3
text-sm text-red-700"); update the class string to include dark-mode variants
(e.g., dark:border-red-600/40, dark:bg-red-900/60 or similar darker bg, and
dark:text-red-200) so the border, background and text colors render correctly in
dark mode while preserving the existing light-mode classes.
In `@apps/web/src/components/ui/Modal.tsx`:
- Around line 39-44: The modal container's inline style in the Modal component
uses boxShadow: "var(--shadow-strong)" which may be undefined; update the style
to use a guaranteed token (e.g., replace "var(--shadow-strong)" with
"var(--shadow-lg)") or add a global CSS variable definition for --shadow-strong;
locate the style block in Modal (the object containing borderRadius, border,
background, boxShadow) and either swap the token to --shadow-lg or define
--shadow-strong in your global CSS variables to ensure the modal always has a
shadow.
- Around line 53-57: The close icon button in Modal.tsx (the button with
onClick={onClose}) is missing an accessible name and button type; update that
button element to include type="button" and an appropriate aria-label (e.g.,
aria-label="Close" or a localized string) so screen readers can identify it,
keeping the onClick={onClose} handler intact.
In `@apps/web/src/lib/powerpoint/officeBridge.ts`:
- Around line 108-123: When view becomes "read" preserve the last known slide
and prevent syncCurrentSlide from emitting editor selection by setting a
read-mode guard instead of only slowing polling: in handleActiveViewChanged set
lastReportedSlide = lastReportedSlide ?? (current cached slide) and set a flag
like isReadMode = true, call startPolling(POLL_READ_MS) but do NOT call
syncCurrentSlide; update syncCurrentSlide (and any emission path) to check
isReadMode and skip emitting or updating lastReportedSlide while true; when
leaving read mode (in the else branch) clear isReadMode = false, reset
lastReportedSlide if needed, resume startPolling(POLL_EDIT_MS) and then call
void syncCurrentSlide() as now to re-sync; apply the same change to the other
matching branch around lines 126-133.
- Around line 86-89: The addHandlerAsync call for
Office.EventType.ActiveViewChanged (Office.context.document.addHandlerAsync) is
missing the AsyncResult callback so registration failures are silent; update the
call that registers handleActiveViewChanged to include the completion callback,
inspect the AsyncResult (check status === Office.AsyncResultStatus.Succeeded or
error) and log/handle errors (and trigger the presentation-mode cadence switch
on success), ensuring you reference Office.context.document.addHandlerAsync,
Office.EventType.ActiveViewChanged, and handleActiveViewChanged when locating
the code.
---
Nitpick comments:
In `@apps/web/src/app/globals.css`:
- Around line 263-264: The animation utility classes (.animate-fade-up and
.animate-soft-float, plus the other animation utilities around the block at
lines ~311-314) currently run unconditionally; add a prefers-reduced-motion
media-query override so animations are disabled for users who prefer reduced
motion. Concretely, wrap or override these classes inside an `@media`
(prefers-reduced-motion: reduce) { ... } block to set animation: none (or
animation-duration: 0ms / animation-name: none) for .animate-fade-up,
.animate-soft-float and the other animation utility class names to provide an
accessible reduced-motion fallback.
In `@apps/web/src/components/ThemeToggle.tsx`:
- Around line 24-28: The ThemeToggle button currently uses aria-label but
doesn't expose its pressed state; update the button in ThemeToggle (the element
with onClick={toggle} using the dark state) to include aria-pressed={dark} so
assistive tech can detect the toggle state; ensure you reference the existing
dark boolean and toggle handler (onClick={toggle}) when adding aria-pressed to
the button element.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 25a61180-0360-45c2-bb49-690ecd711ee6
📒 Files selected for processing (18)
apps/web/src/app/auth/login/page.tsxapps/web/src/app/auth/register/page.tsxapps/web/src/app/dashboard/handout/[id]/page.tsxapps/web/src/app/dashboard/handout/[id]/print/page.tsxapps/web/src/app/dashboard/page.tsxapps/web/src/app/dashboard/session/[id]/page.tsxapps/web/src/app/globals.cssapps/web/src/app/h/[token]/page.tsxapps/web/src/app/layout.tsxapps/web/src/app/page.tsxapps/web/src/app/powerpoint/page.tsxapps/web/src/components/ThemeToggle.tsxapps/web/src/components/dashboard/BlockEditor.tsxapps/web/src/components/dashboard/QRCodeDialog.tsxapps/web/src/components/dashboard/SlideControls.tsxapps/web/src/components/ui/Modal.tsxapps/web/src/lib/powerpoint/officeBridge.tsapps/web/tailwind.config.ts
- Modal: replace undefined --radius-card/--shadow-strong with 0.75rem/--shadow-lg - SlideControls: add dark mode variants to syncModeColor badges - tailwind.config: rename accent → emerald to avoid CSS variable conflict - handout/[id]: add aria-label to icon-only move buttons - dashboard: add rel="noopener noreferrer" to target="_blank" link - globals.css: tokenize soft-note border color with --warning-border for dark mode - officeBridge: resolve merge conflict combining poll frequency + view tracking Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
prefers-color-scheme-Erkennungue→ü,oe→ö,ae→äin sämtlichen Dateien repariertGeänderte Dateien (18)
globals.css— Komplettes Design-System mit Light/Dark-Variablenlayout.tsx— Dark-Mode-Script + ThemeToggle-Integrationtailwind.config.ts—darkMode: "class"hinzugefügtThemeToggle.tsx— Neuer Toggle-Button (Sonne/Mond)page.tsx(Landing) — Komplett neue Struktur und TexteTest plan
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Style
Improvements