-
Notifications
You must be signed in to change notification settings - Fork 29
Add Dark Mode Theme to Improve User Experience and Accessibility #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
📝 WalkthroughWalkthroughAdds 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 Changes
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)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this 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-900class 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-100background 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 wrappinglocalStorageaccess in try-catch for robustness.Accessing
localStoragecan 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: WraplocalStorage.setItemin 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
📒 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-labelto describe the action (switching to the opposite mode)- Disables the button until
isReadyto 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, andisReady, enabling consumers to both read and control theme state.app/layout.tsx (1)
79-85: Correct integration of ThemeProvider with hydration warning suppression.The
suppressHydrationWarningon<html>is appropriate since thedarkclass is applied client-side after hydration, which would otherwise cause a mismatch warning. TheThemeProvidercorrectly 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-inverton 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-100variants 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-200for proper dark mode contrast.
thatraghavarora
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
@coderabbitai generate docstrings |
|
@coderabbitai generate docstrings |
✅ Actions performedInitiated docstring generation; will generate only if new commits exist. |
|
Note Docstrings generation - SUCCESS |
|
@coderabbitai generate docstrings |
✅ Actions performedInitiated docstring generation; will generate only if new commits exist. |
1 similar comment
✅ Actions performedInitiated docstring generation; will generate only if new commits exist. |
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`
|
This PR focuses on dark mode functionality. |
There was a problem hiding this 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
📒 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)
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
✏️ Tip: You can customize this high-level summary in your review settings.