Skip to content

Conversation

@thatraghavarora
Copy link

@thatraghavarora thatraghavarora commented Dec 5, 2025

This pull request introduces a fully implemented Dark Mode theme to the project. The new theme improves readability, reduces eye strain, and enhances the overall user experience, especially in low-light environments.

Summary by CodeRabbit

  • New Features
    • Full dark mode across the app with improved typography, components, and transitions.
    • Theme toggle button added to headers for easy switching; preference persists and respects system defaults.
  • Style / UI Improvements
    • Dark-mode-aware styling applied to cards, pagination, footer, markdown content, and forms for better contrast and consistency.
    • Smooth color transitions and refined borders for a cohesive light/dark experience.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 5, 2025

📝 Walkthrough

Walkthrough

Adds a custom ThemeProvider and ThemeToggle, replaces next-themes usage, and applies dark-mode Tailwind variants across pages, components, and the markdown renderer; theme state persists to localStorage and toggles the root dark class.

Changes

Cohort / File(s) Summary
Theme infrastructure
components/theme-provider.tsx, components/theme-toggle.tsx
New custom ThemeProvider with useTheme hook (theme, toggleTheme, setTheme, isReady), localStorage + system-pref resolution, and root dark class handling. New ThemeToggle component consumes hook and renders accessible toggle UI.
App layout
app/layout.tsx
Wraps app children with ThemeProvider and adds suppressHydrationWarning to <html>.
Site pages
app/page.tsx, app/submit/page.tsx, app/a/[slug]/BlogPostClient.tsx
Injected ThemeToggle into headers and added extensive dark-mode Tailwind variants and transition classes across containers, headers, loading/failure states, and content areas.
UI components
components/blog-card.tsx, components/footer.tsx, components/pagination.tsx
Added/updated dark-mode-aware backgrounds, borders, text colors, and transitions; blog-card gains an outer wrapper altering card background/border while preserving inner content.
Markdown rendering
lib/markdown-renderer.tsx
Extended typography, code blocks, blockquotes, lists, and container classes with dark-mode variants and dark:prose-invert to ensure readable markdown styling.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant UI as ThemeToggle (button)
  participant Hook as useTheme
  participant Provider as ThemeProvider (context)
  participant Storage as localStorage
  participant DOM as document.documentElement

  UI->>Hook: onClick toggleTheme()
  Hook->>Provider: call toggleTheme()
  alt theme changes to "dark"
    Provider->>Storage: localStorage.setItem('theme','dark')
    Provider->>DOM: add class "dark"
  else theme changes to "light"
    Provider->>Storage: localStorage.setItem('theme','light')
    Provider->>DOM: remove class "dark"
  end
  Provider-->>Hook: update theme state (isReady true)
  Hook-->>UI: re-render button (icon/aria-label)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • ceilican

Poem

🐇 In burrows bright and burrows dim I play,
I toggle day to night with just one sway,
Tailwind coats my hops in shadowed hue,
LocalStorage remembers what I do,
A rabbit's flip — now dark and light, hooray! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main objective of the pull request: adding dark mode theme support to improve user experience and accessibility.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
app/submit/page.tsx (2)

47-49: Missing dark mode variant for section header.

The text-gray-900 class will cause poor contrast in dark mode. This pattern repeats across multiple section headers.

Apply this diff to add dark mode support:

-              <h2 className="text-3xl font-bold text-gray-900 mb-6 flex items-center gap-3">
+              <h2 className="text-3xl font-bold text-gray-900 dark:text-gray-100 mb-6 flex items-center gap-3">

The same fix should be applied to similar headers at lines 93, 471, 533, and 573.


220-238: Inline <code> elements lack dark mode styling.

The bg-gray-100 background will cause poor readability in dark mode as it appears nearly white against dark backgrounds. This issue affects multiple code snippets throughout the page.

Apply this diff pattern to all inline code elements:

-                      <code className="bg-gray-100 px-1 rounded">public</code>
+                      <code className="bg-gray-100 dark:bg-slate-700 px-1 rounded">public</code>

This affects approximately 20+ inline code elements throughout the file (lines 222, 226, 234-235, 251, 256, 274, 278, 282-283, 322-324, 338, 376, 520-521, 525).

🧹 Nitpick comments (3)
components/theme-provider.tsx (2)

20-26: Consider wrapping localStorage access in try-catch for robustness.

Accessing localStorage can throw exceptions in certain environments (e.g., private browsing mode in some browsers, or if storage is disabled). Wrapping these calls prevents runtime errors.

   useEffect(() => {
-    const storedTheme = localStorage.getItem("sv-theme") as Theme | null
+    let storedTheme: Theme | null = null
+    try {
+      storedTheme = localStorage.getItem("sv-theme") as Theme | null
+    } catch {
+      // localStorage unavailable (e.g., private browsing)
+    }
     const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches
     const initialTheme: Theme = storedTheme ?? (prefersDark ? "dark" : "light")
     setThemeState(initialTheme)
     setIsReady(true)
   }, [])

28-32: Wrap localStorage.setItem in try-catch as well.

For consistency with the read operation, the write should also handle potential exceptions gracefully.

   useEffect(() => {
     if (!isReady) return
     document.documentElement.classList.toggle("dark", theme === "dark")
-    localStorage.setItem("sv-theme", theme)
+    try {
+      localStorage.setItem("sv-theme", theme)
+    } catch {
+      // localStorage unavailable
+    }
   }, [theme, isReady])
app/submit/page.tsx (1)

52-57: Topic cards lack dark mode background styling.

The gradient backgrounds use light colors (from-[#228B22]/5) that won't provide sufficient contrast in dark mode. Consider adding dark mode variants for the card backgrounds.

Example fix for consistency:

-                <div className="bg-gradient-to-r from-[#228B22]/5 to-[#91A511]/5 p-4 rounded-lg border border-[#228B22]/10">
+                <div className="bg-gradient-to-r from-[#228B22]/5 to-[#91A511]/5 dark:from-[#228B22]/10 dark:to-[#91A511]/10 p-4 rounded-lg border border-[#228B22]/10 dark:border-[#228B22]/20">

Apply similar changes to all topic cards in lines 52-88.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 55a58fc and 856152a.

📒 Files selected for processing (10)
  • app/a/[slug]/BlogPostClient.tsx (3 hunks)
  • app/layout.tsx (2 hunks)
  • app/page.tsx (3 hunks)
  • app/submit/page.tsx (22 hunks)
  • components/blog-card.tsx (2 hunks)
  • components/footer.tsx (1 hunks)
  • components/pagination.tsx (6 hunks)
  • components/theme-provider.tsx (1 hunks)
  • components/theme-toggle.tsx (1 hunks)
  • lib/markdown-renderer.tsx (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
app/submit/page.tsx (1)
components/theme-toggle.tsx (1)
  • ThemeToggle (6-21)
app/page.tsx (1)
components/theme-toggle.tsx (1)
  • ThemeToggle (6-21)
app/a/[slug]/BlogPostClient.tsx (3)
lib/blog.ts (1)
  • BlogPost (3-12)
components/theme-toggle.tsx (1)
  • ThemeToggle (6-21)
lib/markdown-renderer.tsx (1)
  • MarkdownRenderer (8-145)
components/theme-toggle.tsx (1)
components/theme-provider.tsx (1)
  • useTheme (51-57)
🪛 ast-grep (0.40.0)
lib/markdown-renderer.tsx

[warning] 141-141: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html

(react-unsafe-html-injection)

🪛 Biome (2.1.2)
lib/markdown-renderer.tsx

[error] 142-142: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

🔇 Additional comments (16)
components/theme-toggle.tsx (1)

6-21: Well-implemented theme toggle with good accessibility.

The component correctly:

  • Uses aria-label to describe the action (switching to the opposite mode)
  • Disables the button until isReady to prevent hydration mismatch interactions
  • Applies aria-hidden="true" on decorative icons
  • Shows contextually appropriate icons (Sun when dark → switch to light, Moon when light → switch to dark)
components/theme-provider.tsx (1)

37-48: Provider context value and structure look good.

The context correctly exposes theme, toggleTheme, setTheme, and isReady, enabling consumers to both read and control theme state.

app/layout.tsx (1)

79-85: Correct integration of ThemeProvider with hydration warning suppression.

The suppressHydrationWarning on <html> is appropriate since the dark class is applied client-side after hydration, which would otherwise cause a mismatch warning. The ThemeProvider correctly wraps children inside the body.

components/pagination.tsx (1)

50-54: Dark mode styling correctly applied to pagination controls.

The dark variants are consistently applied across enabled, disabled, and active states for both client-side (onPageChange) and server-side (Link) navigation patterns.

components/footer.tsx (1)

27-38: Dark mode styling correctly applied to footer.

The gradient background transitions smoothly between light and dark modes, and text colors are properly adjusted for readability in both themes.

app/a/[slug]/BlogPostClient.tsx (2)

8-24: ThemeToggle integration and dark mode styling look good.

The toggle is correctly placed in the header alongside the back navigation, and all header elements have appropriate dark mode variants for a cohesive experience.


29-82: Dark mode styling consistently applied across article content.

The content container, metadata section, prose wrapper, and copyright footer all have appropriate dark mode variants. The use of dark:prose-invert on line 72 works well with the custom MarkdownRenderer styling.

components/blog-card.tsx (1)

21-58: Dark mode styling correctly applied to blog card.

The card properly transitions between themes with appropriate background, border, and text color variants. The group-hover dark mode variant on line 54 ensures consistent interactive feedback in both themes.

lib/markdown-renderer.tsx (1)

14-21: Dark mode styling correctly applied to markdown headers (h2, h3).

The dark:text-gray-100 variants provide good contrast for rendered markdown content in dark mode.

app/page.tsx (3)

10-10: LGTM!

ThemeToggle import is correctly added.


78-97: LGTM!

Dark mode styling for loading and error states is well implemented with appropriate color transitions and contrasting text colors.


102-122: LGTM!

The header restructuring with ThemeToggle integration is clean. The dark mode classes for the header background (dark:bg-slate-900/80), border (dark:border-white/10), and subtitle text (dark:text-gray-300) provide good visual hierarchy and contrast.

app/submit/page.tsx (4)

4-4: LGTM!

ThemeToggle import is correctly added.


14-26: LGTM!

Container and header dark mode styling is consistent with the homepage implementation.


181-210: LGTM!

Sub-step containers correctly include dark mode backgrounds (dark:bg-slate-900/40).


38-43: LGTM!

Introductory paragraph correctly includes dark:text-gray-200 for proper dark mode contrast.

Copy link
Author

@thatraghavarora thatraghavarora left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@thatraghavarora
Copy link
Author

@coderabbitai generate docstrings

@thatraghavarora
Copy link
Author

@coderabbitai generate docstrings

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 13, 2025

✅ Actions performed

Initiated docstring generation; will generate only if new commits exist.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 13, 2025

Note

Docstrings generation - SUCCESS
Generated docstrings for this pull request at #48

@thatraghavarora
Copy link
Author

@coderabbitai generate docstrings

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 13, 2025

✅ Actions performed

Initiated docstring generation; will generate only if new commits exist.

1 similar comment
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 13, 2025

✅ Actions performed

Initiated docstring generation; will generate only if new commits exist.

coderabbitai bot added a commit that referenced this pull request Dec 13, 2025
Docstrings generation was requested by @thatraghavarora.

* #38 (comment)

The following files were modified:

* `app/a/[slug]/BlogPostClient.tsx`
* `app/layout.tsx`
* `app/page.tsx`
* `app/submit/page.tsx`
* `components/blog-card.tsx`
* `components/footer.tsx`
* `components/pagination.tsx`
* `components/theme-provider.tsx`
* `components/theme-toggle.tsx`
* `lib/markdown-renderer.tsx`
@thatraghavarora
Copy link
Author

This PR focuses on dark mode functionality.
The docstring coverage warning is pre-existing and unrelated to this change.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 856152a and 4fdf2cf.

📒 Files selected for processing (1)
  • components/blog-card.tsx
🧰 Additional context used
🪛 Biome (2.1.2)
components/blog-card.tsx

[error] 22-22: Expected corresponding JSX closing tag for 'article'.

Opening tag

closing tag

(parse)

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