Skip to content

Add dark mode #337

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

Merged
merged 2 commits into from
Feb 15, 2025
Merged

Add dark mode #337

merged 2 commits into from
Feb 15, 2025

Conversation

elie222
Copy link
Owner

@elie222 elie222 commented Feb 15, 2025

Summary by CodeRabbit

  • New Features

    • Introduced a dedicated tabs toolbar to streamline the tab interface.
    • Added a theme provider and theme toggle for enhanced dark mode support.
  • Style

    • Refined color schemes, backgrounds, borders, and hover effects across multiple UI components to ensure visual consistency.
    • Updated styling classes to align with the new design system, including changes to text and background colors for improved readability.
  • Chores

    • Upgraded the theme management dependency and standardized import paths for UI components.

Copy link

vercel bot commented Feb 15, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
inbox-zero ✅ Ready (Inspect) Visit Preview Feb 15, 2025 9:05pm

Copy link
Contributor

coderabbitai bot commented Feb 15, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

The changes span multiple areas of the application. Most modifications involve updates to styling class names to replace hard-coded colors (e.g. "bg-white", "text-gray-700") with new theme tokens such as "bg-background", "text-muted-foreground", and "border-border." A handful of components have been refactored to use new imports (e.g. a new TabsToolbar, ThemeProvider, and ThemeToggle) and updated button patterns (using the asChild prop for nested Link components). Global CSS variables and theming infrastructure have been revised, and minor attribute updates (e.g. adding suppressHydrationWarning) have been applied. No logic or control-flow changes are present.

Changes

File(s) Change Summary
apps/web/app/(app)/automation/*, apps/web/app/(app)/cold-email-blocker/page.tsx, apps/web/app/(app)/compose/ComposeEmailForm.tsx, apps/web/app/(app)/new-senders/page.tsx, apps/web/app/(app)/no-reply/page.tsx, apps/web/app/(app)/onboarding/*, apps/web/app/(app)/premium/*, apps/web/app/blog/components/Prose.tsx, apps/web/app/layout.tsx Updated page and feature components to adopt new design tokens. Class names for text, backgrounds, and borders have been replaced (e.g. from "bg-white" to "bg-background"). The TabsToolbar component is now used to encapsulate tab elements, and minor HTML attribute adjustments have been made.
apps/web/components/* (e.g. ActionButtons, ActionButtonsBulk, Badge, ButtonGroup, EmailCell, EmailMessageCell, Input, NavBottom, RadioGroup, Select, Toggle, TopBar, TopNav, Typography, Tiptap, email-list components) Revised UI components to consistently use updated design tokens and responsive dark mode classes. Icon sizes and color classes have been modified, and new props (e.g. optional className) introduced to support flexible theming without impacting functionality.
apps/web/components/ui/* (e.g. alert, button, calendar, card, command, dialog, dropdown-menu, hover-card, popover, select, sheet, sidebar, table, tabs, tooltip) UI library components now reference theme-based tokens. New variants (such as primaryBlue) and refined dark mode styles have been introduced. The overall styling has been standardized by replacing fixed color classes with theme tokens.
apps/web/{components/{theme-provider,theme-toggle}, providers/AppProviders.tsx, package.json, styles/globals.css} Introduced a new theming infrastructure with ThemeProvider and ThemeToggle components. A new dependency (next-themes) was added, global CSS custom properties were updated, and the provider hierarchy was modified to integrate theme management throughout the app.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant TT as ThemeToggle
    participant UH as useTheme Hook
    participant TP as ThemeProvider
    participant G as Global CSS

    U->>TT: Click theme toggle button
    TT->>UH: Invoke toggleTheme()
    UH->>TP: Update theme state (light/dark)
    TP->>G: Pass updated theme variables
    G->>U: Render UI with new styles
Loading
sequenceDiagram
    participant U as User
    participant TT as TabsToolbar
    participant TL as TabsList
    participant CP as Content Panel

    U->>TT: Click on a tab
    TT->>TL: Highlight selected tab
    TL->>CP: Switch active content panel
    CP->>U: Display updated tab content
Loading

Possibly related PRs

Poem

I’m a bunny in the code, hopping through changes so bright,
Switching grays to muted tones, making every style just right.
Tabs now dance in toolbars new, themes twinkle in the night,
With each line and subtle tweak, the design takes flight.
My whiskers twitch at every update – oh, what a joyful sight!

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

apps/web/components/ui/dialog.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

Error: Failed to load parser '@typescript-eslint/parser' declared in 'apps/web/.eslintrc.json': Cannot find module '@typescript-eslint/parser'
Require stack:

  • /apps/web/.eslintrc.json
    at Module._resolveFilename (node:internal/modules/cjs/loader:1248:15)
    at Function.resolve (node:internal/modules/helpers:145:19)
    at Object.resolve (/node_modules/.pnpm/@eslint[email protected]/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2346:46)
    at ConfigArrayFactory._loadParser (/node_modules/.pnpm/@eslint[email protected]/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3325:39)
    at ConfigArrayFactory._normalizeObjectConfigDataBody (/node_modules/.pnpm/@eslint[email protected]/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3099:43)
    at _normalizeObjectConfigDataBody.next ()
    at ConfigArrayFactory._normalizeObjectConfigData (/node_modules/.pnpm/@eslint[email protected]/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3040:20)
    at _normalizeObjectConfigData.next ()
    at ConfigArrayFactory.loadInDirectory (/node_modules/.pnpm/@eslint[email protected]/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2886:28)
    at CascadingConfigArrayFactory._loadConfigInAncestors (/node_modules/.pnpm/@eslint[email protected]/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3871:46)
apps/web/components/ui/card.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

Error: Failed to load parser '@typescript-eslint/parser' declared in 'apps/web/.eslintrc.json': Cannot find module '@typescript-eslint/parser'
Require stack:

  • /apps/web/.eslintrc.json
    at Module._resolveFilename (node:internal/modules/cjs/loader:1248:15)
    at Function.resolve (node:internal/modules/helpers:145:19)
    at Object.resolve (/node_modules/.pnpm/@eslint[email protected]/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2346:46)
    at ConfigArrayFactory._loadParser (/node_modules/.pnpm/@eslint[email protected]/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3325:39)
    at ConfigArrayFactory._normalizeObjectConfigDataBody (/node_modules/.pnpm/@eslint[email protected]/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3099:43)
    at _normalizeObjectConfigDataBody.next ()
    at ConfigArrayFactory._normalizeObjectConfigData (/node_modules/.pnpm/@eslint[email protected]/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3040:20)
    at _normalizeObjectConfigData.next ()
    at ConfigArrayFactory.loadInDirectory (/node_modules/.pnpm/@eslint[email protected]/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2886:28)
    at CascadingConfigArrayFactory._loadConfigInAncestors (/node_modules/.pnpm/@eslint[email protected]/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3871:46)
apps/web/components/ui/table.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

Error: Failed to load parser '@typescript-eslint/parser' declared in 'apps/web/.eslintrc.json': Cannot find module '@typescript-eslint/parser'
Require stack:

  • /apps/web/.eslintrc.json
    at Module._resolveFilename (node:internal/modules/cjs/loader:1248:15)
    at Function.resolve (node:internal/modules/helpers:145:19)
    at Object.resolve (/node_modules/.pnpm/@eslint[email protected]/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2346:46)
    at ConfigArrayFactory._loadParser (/node_modules/.pnpm/@eslint[email protected]/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3325:39)
    at ConfigArrayFactory._normalizeObjectConfigDataBody (/node_modules/.pnpm/@eslint[email protected]/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3099:43)
    at _normalizeObjectConfigDataBody.next ()
    at ConfigArrayFactory._normalizeObjectConfigData (/node_modules/.pnpm/@eslint[email protected]/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3040:20)
    at _normalizeObjectConfigData.next ()
    at ConfigArrayFactory.loadInDirectory (/node_modules/.pnpm/@eslint[email protected]/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2886:28)
    at CascadingConfigArrayFactory._loadConfigInAncestors (/node_modules/.pnpm/@eslint[email protected]/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3871:46)
  • 1 others

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 94244df and 64d3824.

📒 Files selected for processing (4)
  • apps/web/components/ui/card.tsx (2 hunks)
  • apps/web/components/ui/dialog.tsx (3 hunks)
  • apps/web/components/ui/sheet.tsx (3 hunks)
  • apps/web/components/ui/table.tsx (3 hunks)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

🔭 Outside diff range comments (1)
apps/web/app/(app)/settings/EmailUpdatesSection.tsx (1)

43-45: ⚠️ Potential issue

Fix inconsistency in form default values.

The form's defaultValues still references statsEmailFrequency, but the form field now uses summaryEmailFrequency. This mismatch could lead to initialization issues.

Apply this diff to update the default values:

    defaultValues: {
-     statsEmailFrequency: props.statsEmailFrequency,
+     summaryEmailFrequency: props.statsEmailFrequency,
    },
🧹 Nitpick comments (27)
apps/web/components/ui/table.tsx (1)

46-46: Consider updating TableFooter background colors to use theme tokens.

For consistency with the other theme changes, consider replacing the hard-coded slate colors with theme tokens:

  • bg-slate-100/50 could use a theme token
  • dark:bg-slate-800/50 could use a dark theme token
apps/web/components/Input.tsx (1)

139-141: Consider using semantic color token for error text.

The error message uses a hardcoded text-red-400 color. Consider using a semantic color token for better theme consistency.

-    <div className="mt-0.5 text-sm font-semibold leading-snug text-red-400">
+    <div className="mt-0.5 text-sm font-semibold leading-snug text-destructive">
apps/web/components/ui/sheet.tsx (3)

40-40: Consider updating close button styles for dark mode consistency.

While the main sheet background now uses the theme-aware bg-background token, the close button still uses hard-coded colors:

  • ring-offset-white
  • ring-slate-950
  • bg-slate-100

Consider updating these to use theme tokens for consistent dark mode support.

- className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-slate-950 focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-slate-100 dark:ring-offset-slate-950 dark:focus:ring-slate-300 dark:data-[state=open]:bg-slate-800"
+ className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-foreground focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-muted"

Also applies to: 90-93


149-152: Consider using theme token for dark mode text color.

While the light mode now uses the theme-aware text-muted-foreground token, the dark mode still uses a hard-coded dark:text-slate-400. For consistency, consider using the same token for both modes.

- "text-sm text-muted-foreground dark:text-slate-400"
+ "text-sm text-muted-foreground"

1-169: Consider completing the dark mode implementation.

While some parts of the component have been updated to use theme tokens, there are still several instances of hard-coded colors throughout the file (e.g., in SheetTitle). For a more maintainable dark mode implementation, consider:

  1. Auditing all color-related classes in the file
  2. Converting remaining hard-coded colors to theme tokens
  3. Ensuring consistent usage of tokens across all subcomponents

This will make the theming system more robust and easier to maintain.

apps/web/components/Typography.tsx (5)

12-12: Consider using semantic color tokens for light mode.

While dark mode is correctly using the semantic token dark:text-foreground, consider using text-foreground instead of text-slate-900 for light mode to maintain consistency with the design system.

-      "font-cal text-2xl leading-7 text-slate-900 dark:text-foreground sm:truncate sm:text-3xl",
+      "font-cal text-2xl leading-7 text-foreground sm:truncate sm:text-3xl",

26-29: Add light mode text color token.

The component has dark mode color specified but lacks an explicit light mode color. Consider adding text-foreground for consistency.

-      "font-cal text-base leading-7 dark:text-foreground",
+      "font-cal text-base leading-7 text-foreground",

41-44: Use semantic color token for description text.

For better theme consistency, consider using text-muted-foreground instead of text-slate-700.

-      "mt-1 text-sm leading-6 text-slate-700 dark:text-foreground",
+      "mt-1 text-sm leading-6 text-muted-foreground",

54-58: Use semantic color token for message text.

For better theme consistency, consider using text-muted-foreground instead of text-slate-700.

-    className={cn("text-sm text-slate-700 dark:text-foreground", className)}
+    className={cn("text-sm text-muted-foreground", className)}

100-103: Use semantic color token for link text.

For better theme consistency, consider using text-primary for both light and dark modes.

-          "font-semibold text-blue-600 hover:underline dark:text-primary",
+          "font-semibold text-primary hover:underline",
apps/web/components/ui/dialog.tsx (3)

41-41: Consider using theme tokens for border colors.

While the background color now uses the theme token, the border colors (border-slate-200 and dark:border-slate-800) are still hard-coded. Consider using the theme token border-border for consistency with the new theming system.

-"fixed left-[50%] top-[50%] z-50 grid max-h-screen w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 overflow-y-auto border border-slate-200 bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] dark:border-slate-800 sm:rounded-lg md:w-full"
+"fixed left-[50%] top-[50%] z-50 grid max-h-screen w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 overflow-y-auto border border-border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full"

47-47: Consider using theme tokens for all color values.

While the text color now uses the theme token text-muted-foreground, there are still several hard-coded slate colors. Consider using appropriate theme tokens for consistency:

-"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-slate-950 focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-slate-100 data-[state=open]:text-muted-foreground dark:ring-offset-slate-950 dark:focus:ring-slate-300 dark:data-[state=open]:bg-slate-800 dark:data-[state=open]:text-slate-400"
+"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-muted data-[state=open]:text-muted-foreground"

105-108: Consider using theme tokens for dark mode text color.

While the light mode text color uses the theme token text-muted-foreground, the dark mode still uses a hard-coded color. Consider using the same token for both modes for consistency.

-      "text-sm text-muted-foreground dark:text-slate-400",
+      "text-sm text-muted-foreground",
apps/web/components/ui/command.tsx (5)

18-18: Use theme tokens consistently for text colors.

While the background now uses the theme token bg-background, the text colors are still using hard-coded values (text-slate-950, dark:text-slate-50). For consistency with the dark mode implementation, consider using theme tokens.

-      "flex h-full w-full flex-col overflow-hidden rounded-md bg-background text-slate-950 dark:text-slate-50",
+      "flex h-full w-full flex-col overflow-hidden rounded-md bg-background text-foreground",

39-39: Remove hard-coded dark mode color override.

The component uses the theme token text-muted-foreground but overrides it with dark:text-slate-400. For consistency, remove the dark mode override since text-muted-foreground should handle both light and dark modes.

-          className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground dark:[&_[cmdk-group-heading]]:text-slate-400 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5"
+          className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5"

58-58: Remove redundant dark mode placeholder color.

The component uses the theme token placeholder:text-muted-foreground but includes a redundant dark mode override with dark:placeholder:text-slate-400. The theme token should handle both modes.

-        "flex h-11 w-full rounded-md border-transparent bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground focus:border-transparent focus-visible:ring-transparent disabled:cursor-not-allowed disabled:opacity-50 dark:placeholder:text-slate-400",
+        "flex h-11 w-full rounded-md border-transparent bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground focus:border-transparent focus-visible:ring-transparent disabled:cursor-not-allowed disabled:opacity-50",

101-101: Use theme tokens consistently and remove dark mode overrides.

The component mixes theme tokens with hard-coded colors:

  • Uses hard-coded text-slate-950/dark:text-slate-50 for text
  • Uses text-muted-foreground with redundant dark:text-slate-400 override

For consistency, use theme tokens throughout and remove dark mode overrides.

-      "overflow-hidden p-1 text-slate-950 dark:text-slate-50 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground dark:[&_[cmdk-group-heading]]:text-slate-400",
+      "overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",

129-129: Consider updating all component colors to use theme tokens.

While reviewing the dark mode changes, I noticed that some components still use hard-coded colors:

  • CommandItem uses aria-selected:bg-slate-100/dark:aria-selected:bg-slate-800
  • CommandShortcut uses bg-slate-200/dark:bg-slate-800 and text-slate-800/dark:text-slate-400

Consider updating these components to use theme tokens for consistency with the rest of the changes.

Also applies to: 145-145

apps/web/components/TabsToolbar.tsx (1)

7-23: Consider adding aria-label for better accessibility.

The implementation looks good and correctly uses theme tokens. Consider adding an aria-label to improve accessibility for screen readers.

 export function TabsToolbar({
   className,
   children,
   ...props
 }: TabsToolbarProps) {
   return (
     <div
+      aria-label="Tabs toolbar"
       className={cn(
         "content-container flex shrink-0 flex-col justify-between gap-x-4 space-y-2 border-b border-border bg-background py-2 shadow-sm md:flex-row md:gap-x-6 md:space-y-0",
         className,
       )}
       {...props}
     >
       {children}
     </div>
   );
 }
apps/web/providers/AppProviders.tsx (1)

12-18: Consider making theme configuration more flexible.

The implementation works but has hardcoded theme settings. Consider making these configurable through environment variables for better flexibility across different environments.

+// In your environment.d.ts
+interface ProcessEnv {
+  NEXT_PUBLIC_DEFAULT_THEME?: 'light' | 'dark';
+  NEXT_PUBLIC_ENABLE_SYSTEM_THEME?: string;
+}

 <ThemeProvider 
   attribute="class" 
-  defaultTheme="light"
-  enableSystem={false}
+  defaultTheme={process.env.NEXT_PUBLIC_DEFAULT_THEME || 'light'}
+  enableSystem={process.env.NEXT_PUBLIC_ENABLE_SYSTEM_THEME === 'true'}
 >
apps/web/components/theme-toggle.tsx (1)

8-36: Enhance accessibility and user experience of theme toggle.

While the implementation is functional, there are several improvements that could enhance accessibility and user experience:

  1. Add aria-label for screen readers
  2. Handle theme loading state
  3. Add tooltip for better UX
  4. Use consistent button styling
+import { Button } from "@/components/ui/button";
+import { Tooltip } from "@/components/ui/tooltip";

 export function ThemeToggle({ focus }: { focus?: boolean }) {
-  const { setTheme, theme } = useTheme();
+  const { setTheme, theme, systemTheme } = useTheme();
+  const [mounted, setMounted] = React.useState(false);
+
+  React.useEffect(() => {
+    setMounted(true);
+  }, []);
+
+  // Avoid hydration mismatch
+  if (!mounted) return null;

   const toggleTheme = () => setTheme(theme === "light" ? "dark" : "light");

   return (
-    <button
-      type="button"
-      className={cn(
-        "flex w-full items-center px-3 py-1 text-sm leading-6 text-foreground",
-        focus && "bg-accent",
-      )}
-      onClick={toggleTheme}
-      onKeyDown={(e) => {
-        if (e.key === "Enter" || e.key === " ") {
-          e.preventDefault();
-          toggleTheme();
-        }
-      }}
-    >
-      {theme === "light" ? (
-        <MoonIcon className="mr-2 h-4 w-4" />
-      ) : (
-        <SunIcon className="mr-2 h-4 w-4" />
-      )}
-      {theme === "light" ? "Dark" : "Light"} mode
-    </button>
+    <Tooltip content={`Switch to ${theme === 'light' ? 'dark' : 'light'} mode`}>
+      <Button
+        type="button"
+        variant="ghost"
+        className={cn("w-full", focus && "bg-accent")}
+        onClick={toggleTheme}
+        aria-label={`Switch to ${theme === 'light' ? 'dark' : 'light'} mode`}
+      >
+        {theme === "light" ? (
+          <MoonIcon className="mr-2 h-4 w-4" />
+        ) : (
+          <SunIcon className="mr-2 h-4 w-4" />
+        )}
+        {theme === "light" ? "Dark" : "Light"} mode
+      </Button>
+    </Tooltip>
   );
 }
apps/web/components/ui/alert.tsx (1)

12-15: Consider using theme tokens for destructive and success variants.

For consistency with the default and blue variants, consider replacing hardcoded dark mode colors with theme tokens.

-        destructive:
-          "border-red-500/50 text-red-500 dark:border-red-500 [&>svg]:text-red-500 dark:border-red-900/50 dark:text-red-900 dark:dark:border-red-900 dark:[&>svg]:text-red-900",
-        success:
-          "border-green-500/50 text-green-500 dark:border-green-500 [&>svg]:text-green-500 dark:border-green-900/50 dark:text-green-900 dark:dark:border-green-900 dark:[&>svg]:text-green-900",
+        destructive:
+          "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive dark:text-destructive-foreground",
+        success:
+          "border-success/50 text-success dark:border-success [&>svg]:text-success dark:text-success-foreground",
apps/web/components/Toggle.tsx (1)

26-26: LGTM! Comprehensive dark mode implementation for Toggle component.

The changes properly implement dark mode support with appropriate color tokens and transitions.

Consider extracting the complex className string into a constant or using a CSS module to improve readability:

+const switchClassName = "relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2 dark:focus:ring-white dark:focus:ring-offset-gray-900";

 <Switch
   checked={enabled}
   onChange={onChange}
   className={clsx(
     enabled ? bgClass : "bg-gray-200 dark:bg-input",
-    "relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2 dark:focus:ring-white dark:focus:ring-offset-gray-900",
+    switchClassName,
   )}
 >

Also applies to: 42-43, 51-51

apps/web/app/(app)/settings/EmailUpdatesSection.tsx (1)

82-87: Remove commented-out code.

The commented-out Select component for "Stats Update Email" should be removed if it's no longer needed.

apps/web/components/ui/button.tsx (1)

26-27: Consider using theme tokens for primaryBlue variant.

While other variants use theme tokens for colors, the primaryBlue variant uses direct color values (bg-blue-600, text-white). For consistency with the dark mode implementation, consider using theme tokens instead.

Apply this diff to use theme tokens:

        primaryBlue:
-         "bg-blue-600 text-white hover:bg-blue-700 dark:bg-blue-700 dark:hover:bg-blue-800",
+         "bg-primary-blue text-primary-blue-foreground hover:bg-primary-blue/90",
apps/web/components/email-list/EmailContents.tsx (1)

8-8: Consider handling theme changes more robustly.

The current implementation only adds the dark class on initial load. If the user changes the theme while viewing an email, the iframe content won't update.

Consider updating the implementation to handle theme changes:

 if (event.currentTarget.contentWindow) {
   // sometimes we see minimal scrollbar, so add a buffer
   const BUFFER = 5;

   const height = `${
     event.currentTarget.contentWindow.document.documentElement
       .scrollHeight + BUFFER
   }px`;

   event.currentTarget.style.height = height;
   setIsLoading(false);

-  // Add dark mode class based on theme
-  if (theme === "dark") {
-    event.currentTarget.contentWindow.document.documentElement.classList.add(
-      "dark",
-    );
-  }
+  // Update dark mode class based on theme
+  event.currentTarget.contentWindow.document.documentElement.classList.toggle(
+    "dark",
+    theme === "dark"
+  );
 }

Also applies to: 34-39

apps/web/components/ui/select.tsx (1)

43-43: Maintain consistency in border color tokens.

The SelectContent component uses a hardcoded border-slate-200 while other components use the border-input token. Consider updating for consistency.

-"relative z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-200 bg-background text-slate-950 shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-slate-800 dark:text-slate-50"
+"relative z-50 min-w-[8rem] overflow-hidden rounded-md border border-input bg-background text-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 23a3d55 and 94244df.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (71)
  • apps/web/app/(app)/automation/ExecutedRulesTable.tsx (1 hunks)
  • apps/web/app/(app)/automation/ProcessResultDisplay.tsx (4 hunks)
  • apps/web/app/(app)/automation/ProcessRules.tsx (2 hunks)
  • apps/web/app/(app)/automation/ReportMistake.tsx (1 hunks)
  • apps/web/app/(app)/automation/group/LearnedPatterns.tsx (1 hunks)
  • apps/web/app/(app)/automation/page.tsx (3 hunks)
  • apps/web/app/(app)/cold-email-blocker/page.tsx (2 hunks)
  • apps/web/app/(app)/compose/ComposeEmailForm.tsx (6 hunks)
  • apps/web/app/(app)/new-senders/page.tsx (1 hunks)
  • apps/web/app/(app)/no-reply/page.tsx (1 hunks)
  • apps/web/app/(app)/onboarding/OnboardingEmailAssistant.tsx (3 hunks)
  • apps/web/app/(app)/onboarding/Steps.tsx (1 hunks)
  • apps/web/app/(app)/premium/Pricing.tsx (3 hunks)
  • apps/web/app/(app)/premium/page.tsx (1 hunks)
  • apps/web/app/(app)/reply-zero/ReplyTrackerEmails.tsx (3 hunks)
  • apps/web/app/(app)/reply-zero/page.tsx (3 hunks)
  • apps/web/app/(app)/settings/AboutSectionForm.tsx (2 hunks)
  • apps/web/app/(app)/settings/ApiKeysCreateForm.tsx (3 hunks)
  • apps/web/app/(app)/settings/DeleteSection.tsx (3 hunks)
  • apps/web/app/(app)/settings/EmailUpdatesSection.tsx (1 hunks)
  • apps/web/app/(app)/settings/LabelsSection.tsx (1 hunks)
  • apps/web/app/(app)/settings/ModelSection.tsx (1 hunks)
  • apps/web/app/(app)/settings/MultiAccountSection.tsx (2 hunks)
  • apps/web/app/(app)/simple/SimpleList.tsx (2 hunks)
  • apps/web/app/(app)/stats/Stats.tsx (3 hunks)
  • apps/web/app/blog/components/Prose.tsx (1 hunks)
  • apps/web/app/layout.tsx (1 hunks)
  • apps/web/components/ActionButtons.tsx (3 hunks)
  • apps/web/components/ActionButtonsBulk.tsx (6 hunks)
  • apps/web/components/Badge.tsx (1 hunks)
  • apps/web/components/ButtonGroup.tsx (1 hunks)
  • apps/web/components/EmailCell.tsx (1 hunks)
  • apps/web/components/EmailMessageCell.tsx (1 hunks)
  • apps/web/components/Input.tsx (7 hunks)
  • apps/web/components/NavBottom.tsx (2 hunks)
  • apps/web/components/RadioGroup.tsx (2 hunks)
  • apps/web/components/Select.tsx (2 hunks)
  • apps/web/components/TabsToolbar.tsx (1 hunks)
  • apps/web/components/Toggle.tsx (2 hunks)
  • apps/web/components/TopBar.tsx (1 hunks)
  • apps/web/components/TopNav.tsx (4 hunks)
  • apps/web/components/Typography.tsx (6 hunks)
  • apps/web/components/editor/Tiptap.tsx (1 hunks)
  • apps/web/components/email-list/EmailAttachments.tsx (1 hunks)
  • apps/web/components/email-list/EmailContents.tsx (4 hunks)
  • apps/web/components/email-list/EmailDetails.tsx (1 hunks)
  • apps/web/components/email-list/EmailList.tsx (2 hunks)
  • apps/web/components/email-list/EmailListItem.tsx (4 hunks)
  • apps/web/components/email-list/EmailMessage.tsx (3 hunks)
  • apps/web/components/email-list/EmailPanel.tsx (1 hunks)
  • apps/web/components/email-list/EmailThread.tsx (1 hunks)
  • apps/web/components/theme-provider.tsx (1 hunks)
  • apps/web/components/theme-toggle.tsx (1 hunks)
  • apps/web/components/ui/alert.tsx (1 hunks)
  • apps/web/components/ui/button.tsx (1 hunks)
  • apps/web/components/ui/calendar.tsx (2 hunks)
  • apps/web/components/ui/card.tsx (2 hunks)
  • apps/web/components/ui/command.tsx (4 hunks)
  • apps/web/components/ui/dialog.tsx (3 hunks)
  • apps/web/components/ui/dropdown-menu.tsx (2 hunks)
  • apps/web/components/ui/hover-card.tsx (1 hunks)
  • apps/web/components/ui/popover.tsx (1 hunks)
  • apps/web/components/ui/select.tsx (2 hunks)
  • apps/web/components/ui/sheet.tsx (3 hunks)
  • apps/web/components/ui/sidebar.tsx (4 hunks)
  • apps/web/components/ui/table.tsx (3 hunks)
  • apps/web/components/ui/tabs.tsx (3 hunks)
  • apps/web/components/ui/tooltip.tsx (1 hunks)
  • apps/web/package.json (1 hunks)
  • apps/web/providers/AppProviders.tsx (1 hunks)
  • apps/web/styles/globals.css (2 hunks)
✅ Files skipped from review due to trivial changes (33)
  • apps/web/components/EmailCell.tsx
  • apps/web/app/(app)/new-senders/page.tsx
  • apps/web/app/(app)/automation/ExecutedRulesTable.tsx
  • apps/web/app/(app)/premium/page.tsx
  • apps/web/components/email-list/EmailThread.tsx
  • apps/web/app/(app)/settings/ModelSection.tsx
  • apps/web/components/ui/hover-card.tsx
  • apps/web/components/ButtonGroup.tsx
  • apps/web/components/email-list/EmailDetails.tsx
  • apps/web/app/(app)/automation/ProcessRules.tsx
  • apps/web/app/(app)/onboarding/OnboardingEmailAssistant.tsx
  • apps/web/components/ActionButtonsBulk.tsx
  • apps/web/components/email-list/EmailAttachments.tsx
  • apps/web/components/ui/dropdown-menu.tsx
  • apps/web/app/(app)/no-reply/page.tsx
  • apps/web/components/EmailMessageCell.tsx
  • apps/web/components/ui/popover.tsx
  • apps/web/app/blog/components/Prose.tsx
  • apps/web/components/ui/tooltip.tsx
  • apps/web/components/ActionButtons.tsx
  • apps/web/components/editor/Tiptap.tsx
  • apps/web/app/(app)/settings/LabelsSection.tsx
  • apps/web/app/(app)/settings/ApiKeysCreateForm.tsx
  • apps/web/app/(app)/onboarding/Steps.tsx
  • apps/web/components/email-list/EmailPanel.tsx
  • apps/web/components/email-list/EmailList.tsx
  • apps/web/components/email-list/EmailMessage.tsx
  • apps/web/app/(app)/automation/ProcessResultDisplay.tsx
  • apps/web/app/(app)/reply-zero/ReplyTrackerEmails.tsx
  • apps/web/app/(app)/automation/ReportMistake.tsx
  • apps/web/components/email-list/EmailListItem.tsx
  • apps/web/app/(app)/compose/ComposeEmailForm.tsx
  • apps/web/app/(app)/simple/SimpleList.tsx
🔇 Additional comments (51)
apps/web/app/(app)/automation/group/LearnedPatterns.tsx (2)

21-21: LGTM! Good use of theme tokens.

The background and hover states now properly respond to theme changes by using theme tokens (bg-background, hover:bg-muted) instead of hard-coded colors.


23-23: LGTM! Good use of theme tokens.

The icon color now properly responds to theme changes by using the theme token (text-muted-foreground) instead of a hard-coded color.

apps/web/components/RadioGroup.tsx (5)

41-41: LGTM! Good use of theme tokens.

The change from hard-coded colors to theme tokens (bg-background) improves theme consistency.


55-55: LGTM! Good dark mode implementation.

The dark mode classes are well-structured with appropriate color values and state handling.


60-60: LGTM! Excellent accessibility consideration.

The dark mode implementation maintains proper focus indicators and contrast ratios, ensuring good accessibility.


62-62: LGTM! Consistent theme token usage.

The change maintains visual consistency by using the theme token.


65-65: LGTM! Well-structured text color implementation.

The text colors are properly implemented with good contrast ratios in both light and dark modes, including proper handling of checked states.

Also applies to: 68-68

apps/web/components/ui/table.tsx (3)

61-61: LGTM! Border styling updated for theme support.

The addition of the border-border class aligns with the dark mode implementation by using theme tokens instead of hard-coded colors.


76-76: LGTM! Text color updated to use theme token.

The replacement of text-slate-500 with text-muted-foreground improves theme consistency by using semantic color tokens.


102-105: LGTM! Text color updated and formatting improved.

The replacement of text-slate-500 with text-muted-foreground maintains theme consistency, and the reformatting improves code readability.

apps/web/components/Input.tsx (3)

75-75: LGTM: Improved component flexibility with className prop.

The addition of the optional className prop to InputWithLeftFixedText and InputWithRightFixedText components enhances their reusability and customization options.

Also applies to: 82-82, 148-148, 169-169


88-88: LGTM: Consistent dark mode implementation.

The dark mode styling implementation follows a consistent pattern using semantic color tokens and maintains proper contrast ratios.

Also applies to: 115-115, 131-131, 152-152, 158-158, 176-176, 180-180, 198-198, 207-207


198-198: LGTM: Enhanced interactive states.

The addition of transition effects and improved hover states for the add/remove buttons enhances the user experience while maintaining accessibility.

Also applies to: 207-207

apps/web/components/TopBar.tsx (3)

3-7: LGTM!

The TopBarProps interface is well-defined with appropriate types and follows TypeScript best practices.


9-9: LGTM!

The function signature is well-structured, using the new interface and providing appropriate default values.


13-13: LGTM!

The styling changes appropriately replace hard-coded colors with theme tokens (bg-background) to support dark mode while maintaining the existing layout.

apps/web/app/(app)/stats/Stats.tsx (2)

19-19: LGTM!

The import statement follows the project's import pattern consistently.


70-85: LGTM!

The TopBar component is correctly integrated, maintaining existing functionality while supporting dark mode through the new theming system.

apps/web/components/ui/sheet.tsx (1)

30-30: LGTM! Good use of theme token.

The change from hard-coded bg-white/80 to theme-aware bg-background/80 is appropriate for dark mode support while maintaining the same visual effects.

apps/web/components/Typography.tsx (1)

86-90: Great use of semantic color tokens!

The component correctly uses the text-muted-foreground token for consistent theming.

apps/web/components/ui/dialog.tsx (1)

24-24: LGTM! Good use of theme tokens.

The change from hard-coded bg-white to theme-aware bg-background token is appropriate for dark mode support.

apps/web/components/ui/card.tsx (1)

12-12: Well-structured theme token implementation!

The replacement of hard-coded colors with semantic theme tokens (border-border, bg-background, text-foreground) ensures consistent theming and proper dark mode support.

apps/web/components/NavBottom.tsx (2)

25-25: LGTM! Good use of theme tokens.

The change from hard-coded bg-white to theme-aware bg-background properly supports dark mode by using the new design system's color tokens.


36-37:

❓ Verification inconclusive

LGTM! Good use of semantic color tokens.

The changes properly implement dark mode support by:

  • Using text-foreground for selected state
  • Using text-muted-foreground for unselected state
  • Maintaining visual hierarchy through proper contrast

Please verify that the contrast ratios between foreground/background and muted-foreground/background meet WCAG accessibility guidelines in both light and dark modes.


🌐 Web query:

What are the minimum contrast ratios required for WCAG 2.1 Level AA compliance?

💡 Result:

WCAG 2.1 Level AA compliance requires specific contrast ratios to ensure content accessibility:

Text Contrast Requirements

  • Normal text: Minimum 4.5:1 contrast ratio between text/background (e.g., #767676 gray on white)[1][6][7].
  • Large text: Reduced requirement of 3:1 for:
    • Text ≥18pt (≈24px)
    • Bold text ≥14pt (≈18.67px)[1][4][9].
      Exceptions: Logos, purely decorative text, or inactive UI elements have no requirements[1][7].

Non-Text Contrast Requirements

  • UI components (buttons, form borders) and graphical objects (charts, icons): Minimum 3:1 contrast against adjacent colors[1][10].
  • Applies to visual states like focus indicators but excludes inactive elements[1].

Key Implementation Notes

  • Ratios are strict thresholds (e.g., #777777 gray fails at 4.47:1)[1].
  • These rules apply to both web text and images containing text[6][7].
  • Enhanced AAA requirements exist (7:1 for normal text), but Level AA is legally mandated in most contexts[4][9].

For context, these ratios compensate for common vision challenges like age-related contrast sensitivity loss or 20/40 visual acuity[3][7]. Tools like color contrast checkers can validate compliance during design[4][10].

Citations:


LGTM! Semantic token usage is spot on.

The changes correctly implement dark mode support by:

  • Using text-foreground for the selected state.
  • Using text-muted-foreground for the unselected state.
  • Properly maintaining visual hierarchy with thematic tokens.

Please ensure that the contrast ratios for both tokens meet WCAG 2.1 Level AA guidelines—that is, a minimum contrast ratio of 4.5:1 for normal text (or 3:1 for large/bold text) in both light and dark modes.

apps/web/components/Badge.tsx (2)

12-23: LGTM! Well-implemented dark mode support.

The dark mode implementation follows best practices:

  • Consistent pattern across all color variants
  • Appropriate use of opacity modifiers for subtle backgrounds (/10) and borders (/20)
  • Maintains good contrast ratios in both light and dark modes

12-23:

❓ Verification inconclusive

Verify color scheme matches design system.

Please ensure these color combinations align with your design system's accessibility guidelines for both light and dark modes.


🌐 Web query:

What are the recommended contrast ratios for text and background colors in dark mode according to WCAG guidelines?

💡 Result:

The Web Content Accessibility Guidelines (WCAG) specify contrast ratio requirements for text and background colors that apply universally across both light and dark modes. Here are the key standards:

Core Contrast Requirements

  • Normal text: Minimum 4.5:1 contrast ratio
    Applies to text smaller than 18pt (24px) in regular weight or 14pt (19px) in bold[1][3][6][10].

  • Large text: Minimum 3:1 contrast ratio
    For text ≥18pt (24px) in regular weight or ≥14pt (19px) in bold[1][3][6][10].

  • User interface components: Minimum 3:1 contrast
    Applies to buttons, form fields, icons, and other interactive elements against adjacent colors[1][4].

Dark Mode Implementation Notes

  • Avoid pure black (#000000) backgrounds
    Use dark grays instead to reduce eye strain from excessive contrast[1].

  • Test saturated colors carefully
    Bright colors often fail WCAG ratios - e.g., pure red (#FF0000) only achieves 4:1 on white[4].

  • Hyperlinks require special attention
    Common dark mode implementations like blue links on dark backgrounds often fail contrast checks[7].

Key Exceptions

  • Logos/branding: No minimum requirement[10]
  • Decorative/inactive elements: No requirement[10]

While dark modes can improve readability for some users in low-light conditions[2], they must still meet these same WCAG standards. A common misconception is that dark themes inherently provide sufficient contrast - testing tools like WebAIM's Contrast Checker[6] should always be used to verify compliance[7].

Citations:


Action: Verify Color Scheme Accessibility Compliance

  • File: apps/web/components/Badge.tsx (Lines 12–23)
  • Ensure that each color pairing meets WCAG requirements:
    • Normal text: Minimum contrast ratio of 4.5:1.
    • Large text: Minimum contrast ratio of 3:1.
  • In particular, verify that both the light mode classes (e.g., bg-gray-50/text-gray-600) and the dark mode classes (e.g., dark:bg-gray-400/10/dark:text-gray-400) provide sufficient contrast. Consider using a contrast-checking tool such as the WebAIM Contrast Checker to confirm compliance.
apps/web/components/theme-provider.tsx (1)

1-9: Clean implementation of theme provider!

The implementation is concise and follows React best practices by properly forwarding props to the underlying NextThemesProvider.

apps/web/components/Select.tsx (1)

28-30: LGTM! Well-implemented dark mode support.

The className updates properly implement dark mode support by:

  • Using theme tokens (border-input, bg-background) instead of hard-coded colors
  • Maintaining accessibility with proper focus states
  • Preserving disabled state styling
apps/web/app/(app)/cold-email-blocker/page.tsx (1)

20-28: LGTM! Clean UI restructuring.

The TabsToolbar implementation provides a more organized structure while maintaining theme consistency.

apps/web/app/(app)/settings/AboutSectionForm.tsx (1)

4-4: LGTM! Consistent component structure.

The Button component updates align with the new theming system, using centralized UI components.

Also applies to: 54-56

apps/web/components/ui/alert.tsx (1)

11-11: LGTM! Improved dark mode contrast.

The alert variants now properly support dark mode with better color contrast, especially in the blue variant.

Also applies to: 16-16

apps/web/app/(app)/settings/DeleteSection.tsx (1)

4-4: LGTM! Button component updates align with theming system.

The changes appropriately migrate to the new button component and use theme-aware variants instead of hardcoded colors.

Also applies to: 26-26, 43-43

apps/web/app/(app)/automation/page.tsx (1)

13-13: LGTM! TabsToolbar integration improves UI consistency.

The TabsToolbar component provides a consistent container for tabs navigation, likely supporting dark mode and maintaining visual hierarchy.

Also applies to: 26-48

apps/web/app/layout.tsx (1)

82-82: LGTM! Added necessary hydration warning suppression.

The suppressHydrationWarning attribute is required to prevent React hydration mismatches that occur during theme changes, as the initial server-rendered HTML might not match the client-side state when dark mode is enabled.

apps/web/components/ui/calendar.tsx (1)

37-37: LGTM! Consistent use of theme tokens.

The changes correctly replace hardcoded slate colors with theme tokens (text-muted-foreground), ensuring proper dark mode support while maintaining visual consistency.

Also applies to: 50-51

apps/web/components/ui/tabs.tsx (1)

79-80: LGTM! Consistent theming with preserved accessibility.

The changes correctly implement theme tokens while maintaining important accessibility features like focus states and ring offsets.

Also applies to: 97-98, 123-124

apps/web/app/(app)/reply-zero/page.tsx (1)

20-20: LGTM! Clean implementation of TabsToolbar.

The replacement of the div wrapper with TabsToolbar component maintains the existing functionality while supporting the new theming system.

Also applies to: 51-96

apps/web/components/email-list/EmailContents.tsx (1)

95-107: LGTM! Well-structured CSS variables for theming.

The CSS variables implementation provides a clean separation between light and dark themes while maintaining consistency with the application's color scheme.

apps/web/components/TopNav.tsx (1)

24-25: LGTM! Clean integration of theme toggle.

The ThemeToggle component is well-placed in the user menu, and all color classes have been properly updated to use theme tokens.

Also applies to: 119-119

apps/web/app/(app)/settings/MultiAccountSection.tsx (2)

4-4: LGTM! Import changes look good.

The updated imports improve component organization by using the new UI component structure.

Also applies to: 12-12


199-207: Well-structured button implementation.

The refactoring to use asChild with nested Link improves semantic HTML while maintaining button styling and behavior.

apps/web/app/(app)/premium/Pricing.tsx (2)

107-115: Consistent button implementation.

Good use of the asChild pattern for both navigation buttons, maintaining proper semantics while sharing button styles.

Also applies to: 117-122


127-127: Theme-aware background styling.

The update to use bg-background aligns with the new theming system, ensuring proper dark mode support.

Also applies to: 137-141

apps/web/components/ui/sidebar.tsx (4)

254-254: Theme-aware border styling.

Good update to use the border-border token for consistent theming.


339-340: Dark mode background update.

The background color update properly handles both light and dark modes.


535-535: Theme-aware button styling.

Good update to use bg-background for consistent button theming.


349-365:

✅ Verification successful

Verify if SidebarInput is needed.

The SidebarInput component is commented out. Consider removing it if it's no longer needed.


🏁 Script executed:

#!/bin/bash
# Check if SidebarInput is used anywhere in the codebase
rg "SidebarInput" --type tsx --type ts

Length of output: 66


SidebarInput Unused: Verify and Remove Commented Code

It appears that the SidebarInput component isn’t referenced anywhere in the codebase when searching with explicit file globs for .tsx and .ts files. Please run the above script to manually verify this result. If no usage is detected, you can safely remove the commented SidebarInput code in apps/web/components/ui/sidebar.tsx.


🏁 Script executed:

[run_scripts]
#!/bin/bash
# Re-run the usage search for SidebarInput with explicit file globs for .tsx and .ts files.
rg "SidebarInput" -g "*.tsx" -g "*.ts"

Length of output: 372


SidebarInput Unused - Approved for Removal

After re-running the search, we found that references to SidebarInput exist only within commented code in apps/web/components/ui/sidebar.tsx (lines 349-365). Since there are no active usages of the component in the codebase, it's safe to remove this commented-out code to clean up the file.

apps/web/styles/globals.css (3)

7-35: Well-documented color system.

Excellent use of CSS custom properties with helpful comments indicating the corresponding color names. This makes the theming system more maintainable.


49-80: Comprehensive dark theme implementation.

Good coverage of all necessary color tokens for dark mode, including chart colors. The values provide good contrast while maintaining visual hierarchy.


88-95: Proper base styling setup.

The new base layer ensures consistent border and background colors across all elements.

apps/web/package.json (1)

106-106: Dependency Addition for Dark Mode Support

The inclusion of "next-themes": "0.4.4" is well-aligned with the PR’s objective to add dark mode support. Ensure that this version is fully compatible with your current Next.js version (14.2.15) and that any required configuration in your theme provider or global CSS is updated accordingly.

Comment on lines 53 to 56
className={cn(
"text-sm text-muted-foreground dark:text-slate-400",
className,
)}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Update dark mode color to use theme token.

While the light mode correctly uses text-muted-foreground, the dark mode still uses a hard-coded color dark:text-slate-400. For consistency and maintainability, consider using the theme token for dark mode as well.

-      "text-sm text-muted-foreground dark:text-slate-400",
+      "text-sm text-muted-foreground",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
className={cn(
"text-sm text-muted-foreground dark:text-slate-400",
className,
)}
className={cn(
"text-sm text-muted-foreground",
className,
)}

@elie222 elie222 merged commit 877dd99 into main Feb 15, 2025
1 of 3 checks passed
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