Skip to content

Add system setting to switcher#661

Merged
yamcodes merged 3 commits intomainfrom
608-darklight-mode-switcher-doesnt-sync-reliably-with-system-setting
Dec 27, 2025
Merged

Add system setting to switcher#661
yamcodes merged 3 commits intomainfrom
608-darklight-mode-switcher-doesnt-sync-reliably-with-system-setting

Conversation

@yamcodes
Copy link
Owner

@yamcodes yamcodes commented Dec 27, 2025

Closes #608

Summary by CodeRabbit

  • New Features
    • Added theme switching allowing users to choose light, dark, or system themes.
    • Added a theme toggle control in the app layout with clear visual indicators for each mode.
    • Toggle includes accessibility improvements (ARIA support and clear active state) for better keyboard and assistive tech use.

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

@yamcodes yamcodes linked an issue Dec 27, 2025 that may be closed by this pull request
@vercel
Copy link

vercel bot commented Dec 27, 2025

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

Project Deployment Review Updated (UTC)
arkenv Ready Ready Preview, Comment Dec 27, 2025 9:29pm

@changeset-bot
Copy link

changeset-bot bot commented Dec 27, 2025

⚠️ No Changeset found

Latest commit: 3394326

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions github-actions bot added the www Improvements or additions to arkenv.js.org label Dec 27, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 27, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Adds a new client-side ThemeToggle component, wires it into the layout configuration as themeSwitch, and updates the RootProvider to explicitly support the "system", "light", and "dark" themes to enable user theme selection and system-sync behavior.

Changes

Cohort / File(s) Summary
Layout configuration
apps/www/app/layout.config.tsx, apps/www/app/layout.tsx
Import and register ThemeToggle as themeSwitch in baseOptions; update RootProvider themes to include "system", "light", and "dark".
Theme toggle component
apps/www/components/ui/theme-toggle.tsx
New client component implementing an accessible 3-way theme selector (light/system/dark) using next-themes, Lucide icons, mounted-state guard to avoid SSR hydration issues, and conditional styling via cn.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant User
  participant ThemeToggle as ThemeToggle UI
  participant RootProvider as Theme Provider (next-themes)
  participant OS as System Preference

  User->>ThemeToggle: Clicks theme button (light/system/dark)
  alt option != "system"
    ThemeToggle->>RootProvider: setTheme("light"|"dark")
    RootProvider-->>User: Apply selected theme classes/styles
  else option == "system"
    ThemeToggle->>RootProvider: setTheme("system")
    RootProvider->>OS: query prefers-color-scheme
    OS-->>RootProvider: returns light/dark
    RootProvider-->>User: Apply system theme classes/styles
  end
  note right of ThemeToggle: Mounted-state guard prevents SSR mismatch\nARIA attributes updated for active button
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰
Three buttons, round and bright, I cheer—
light, system, dark, all near,
I hop and toggle without fright,
the site now matches day or night,
nibble a twig, and click to delight.

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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add system setting to switcher' directly and clearly describes the main change: adding a system theme setting option to the theme switcher component.
Linked Issues check ✅ Passed The PR implements both primary requirements from issue #608: adds a 'system' setting mode that follows OS appearance, and integrates a theme toggle component for switching between light, dark, and system themes.
Out of Scope Changes check ✅ Passed All changes are directly related to issue #608: adding system theme support, creating the theme toggle component, and integrating it into the layout configuration. No unrelated modifications detected.

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4aa2abd and 3394326.

📒 Files selected for processing (1)
  • apps/www/components/ui/theme-toggle.tsx

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: 1

🧹 Nitpick comments (1)
apps/www/components/ui/theme-toggle.tsx (1)

42-43: Simplify redundant ternary expression.

The current logic (theme === "system" ? "system" : theme) === option.value is redundant and can be simplified to just theme === option.value, as the ternary always returns theme.

🔎 Simplified logic
-			const isActive =
-				(theme === "system" ? "system" : theme) === option.value;
+			const isActive = theme === option.value;
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 69ec168 and 4aa2abd.

📒 Files selected for processing (3)
  • apps/www/app/layout.config.tsx
  • apps/www/app/layout.tsx
  • apps/www/components/ui/theme-toggle.tsx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

**/*.{ts,tsx}: Prefer type over interface for type definitions in TypeScript
Use TypeScript 5.1+ features when appropriate
Leverage const type parameters for better inference in TypeScript
Use JSDoc comments for public APIs
Use tabs for indentation (configured in Biome)
Use double quotes for strings (configured in Biome)
Organize imports automatically (Biome handles this)
Avoid explicit types when TypeScript can infer them (noInferrableTypes error)
Use as const where appropriate for immutable values (useAsConstAssertion error)
Don't reassign function parameters (noParameterAssign error)
Place default parameters last in function signatures (useDefaultParameterLast error)
Always initialize enum values (useEnumInitializers error)
Declare one variable per statement (useSingleVarDeclarator error)
Avoid unnecessary template literals (noUnusedTemplateLiteral error)
Prefer Number.parseInt over global parseInt (useNumberNamespace error)
Use kebab-case for TypeScript filenames (e.g., create-env.ts)
Use camelCase for function names (e.g., createEnv)
Use PascalCase for type names (e.g., ArkEnvError)
Use UPPER_SNAKE_CASE for environment variables and constants
Include examples in JSDoc comments when helpful for public APIs
Document complex type logic with JSDoc comments
Use ArkEnvError for environment variable validation errors
Provide clear, actionable error messages that include the variable name and expected type

**/*.{ts,tsx}: Use createEnv(schema) function (or default import as arkenv) to create validated environment objects in TypeScript
Use built-in validators (host, port, url, email) from ArkEnv when available instead of custom ArkType schemas
Provide default values for optional environment variables using ArkType syntax (e.g., 'boolean = false')
Use ArkEnvError for environment variable errors instead of generic Error types
For environment schema definition, use ArkType string literal syntax for enumerated values (e.g., "'deve...

Files:

  • apps/www/components/ui/theme-toggle.tsx
  • apps/www/app/layout.tsx
  • apps/www/app/layout.config.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

Use self-closing JSX elements (useSelfClosingElements error)

Files:

  • apps/www/components/ui/theme-toggle.tsx
  • apps/www/app/layout.tsx
  • apps/www/app/layout.config.tsx
apps/www/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (apps/www/.cursor/rules/posthog-integration.mdc)

apps/www/**/*.{ts,tsx,js,jsx}: If using TypeScript, use an enum to store feature flag names. If using JavaScript, store feature flag names as strings to an object declared as a constant to simulate an enum. Use UPPERCASE_WITH_UNDERSCORE naming convention for enum/const object members.
If a custom property for a person or event is referenced in two or more files or two or more callsites in the same file, use an enum or const object with UPPERCASE_WITH_UNDERSCORE naming convention, similar to feature flags.

Files:

  • apps/www/components/ui/theme-toggle.tsx
  • apps/www/app/layout.tsx
  • apps/www/app/layout.config.tsx
🧠 Learnings (1)
📚 Learning: 2025-12-25T21:14:25.628Z
Learnt from: yamcodes
Repo: yamcodes/arkenv PR: 616
File: apps/www/app/(home)/page.tsx:18-18
Timestamp: 2025-12-25T21:14:25.628Z
Learning: In projects using fumadocs-ui's HomeLayout component, the HomeLayout itself renders a top-level <main> element with id="nd-home-layout", so page components should not include their own <main> wrapper to avoid duplicate main landmarks.

Applied to files:

  • apps/www/app/layout.config.tsx
🧬 Code graph analysis (3)
apps/www/components/ui/theme-toggle.tsx (1)
apps/www/lib/utils/cn.ts (1)
  • cn (4-6)
apps/www/app/layout.tsx (1)
tooling/playwright-www/tests/theme-switching.test.ts (3)
  • test (3-87)
  • page (4-64)
  • window (39-44)
apps/www/app/layout.config.tsx (1)
apps/www/components/ui/theme-toggle.tsx (1)
  • ThemeToggle (14-64)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: test-e2e (a11y)
  • GitHub Check: test-e2e (e2e)
🔇 Additional comments (6)
apps/www/app/layout.tsx (1)

48-48: LGTM! System theme support successfully added.

The explicit themes array properly enables the three-option theme switcher (system, light, dark) that resolves the sync issue described in #608. This works correctly with the existing enableSystem: true configuration.

apps/www/app/layout.config.tsx (1)

3-3: LGTM! Theme toggle properly integrated.

The ThemeToggle component is correctly imported and configured as the layout's theme switch control, completing the integration with fumadocs-ui's BaseLayoutProps.

Also applies to: 16-18

apps/www/components/ui/theme-toggle.tsx (4)

1-6: LGTM! Proper client component setup.

The "use client" directive is correctly placed for this interactive component, and all imports are appropriate for the theme toggle functionality.


8-12: LGTM! Type definition follows coding guidelines.

The Option type correctly uses type instead of interface as per the project's coding guidelines, and the structure is well-suited for the theme options.


26-30: LGTM! Well-typed options array.

The as const satisfies Option[] syntax leverages TypeScript 5.1+ features for strong type inference while maintaining const assertions, and the icon-to-theme mappings are semantically clear.


32-63: LGTM! Excellent accessibility implementation.

The component render demonstrates strong accessibility practices:

  • Semantic <fieldset> grouping
  • Proper ARIA attributes (aria-label, aria-pressed)
  • Clear visual state indicators with keyboard-friendly styling
  • Explicit type="button" to prevent unintended form submissions

The integration with next-themes via setTheme is correct and will properly update the theme across the application.

…, update dependencies, and refine Bun React env type.
@yamcodes yamcodes merged commit 3a1ddd0 into main Dec 27, 2025
11 of 13 checks passed
@yamcodes yamcodes deleted the 608-darklight-mode-switcher-doesnt-sync-reliably-with-system-setting branch December 27, 2025 21:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

www Improvements or additions to arkenv.js.org

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dark/light mode switcher doesn't sync reliably with system setting

1 participant