Skip to content

Feature : add dark mode #105

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

mayur1377
Copy link

@mayur1377 mayur1377 commented Jul 31, 2025

#46 : add dark mode , a few snapshots below

Screenshot 2025-08-01 at 12 38 17 AM Screenshot 2025-08-01 at 12 38 41 AM Screenshot 2025-08-01 at 12 40 14 AM

Summary by CodeRabbit

  • New Features

    • Added a theme toggle button for switching between light and dark modes.
    • Application now supports dark mode, with theme adapting to system preferences.
  • Style

    • Updated all components to use theme-based color tokens instead of hardcoded color values for backgrounds, borders, and text.
    • Improved consistency and accessibility of UI elements across light and dark themes.
    • Unified button, link, and badge styling to align with the new design system.
  • Bug Fixes

    • Suppressed hydration warnings for smoother theme transitions.
  • Refactor

    • Centralized theming logic and ensured all UI components respond to theme changes.

Copy link
Contributor

coderabbitai bot commented Jul 31, 2025

Walkthrough

This update standardizes the application's visual styling to use semantic, theme-based color tokens instead of hardcoded color values. It introduces a global theme provider for dark/light mode support, adds a theme toggle component, and updates numerous UI components to use design system tokens for colors, backgrounds, and borders. No logic or control flow is altered.

Changes

Cohort / File(s) Change Summary
Theme Provider & Dark Mode Support
src/app/layout.tsx, src/components/background-wrapper.tsx, src/components/mode-toggle.tsx
Adds a global ThemeProvider for dark/light mode, updates background rendering for theme awareness, and introduces a new ModeToggle component for switching themes.
Header and Navigation Updates
src/components/header.tsx
Integrates the new theme toggle, updates logo and navigation colors to use theme tokens, and unifies link/button styling with semantic classes.
Button and Link Styling
src/app/dashboard/layout.tsx, src/app/i/[id]/page.tsx, src/app/invoices/create/page.tsx
Updates button and link components to use semantic color classes and consistent UI structure.
Dashboard & Invoice Components
src/components/dashboard/blocks/invoice-row.tsx, src/components/dashboard/invoices-received.tsx, src/components/dashboard/invoices-sent.tsx, src/components/dashboard/subscriptions.tsx, src/components/stat-card.tsx, src/components/invoice-form.tsx, src/components/invoice-me-link.tsx, src/components/invoice-me-links.tsx, src/components/invoice-preview.tsx, src/components/payment-route.tsx, src/components/payment-section.tsx, src/components/payment-secured-using-request.tsx, src/components/footer.tsx, src/components/ui/table/empty-state.tsx, src/components/ui/table/pagination.tsx, src/components/ui/table/table-head-cell.tsx
Refactors all color, border, and background classes to use semantic tokens (text-muted-foreground, bg-muted, border-border, etc.) for consistency and theme compatibility.
Batch, Direct, and Recurring Payment Components
src/components/batch-payout.tsx, src/components/direct-payout.tsx, src/components/create-recurring-payment/blocks/create-recurring-payment-form.tsx, src/components/create-recurring-payment/create-recurring-payment.tsx, src/components/view-recurring-payments/blocks/completed-payments.tsx, src/components/view-recurring-payments/blocks/frequency-badge.tsx, src/components/view-recurring-payments/blocks/status-badge.tsx, src/components/view-recurring-payments/view-recurring-payments.tsx
Updates all color and status badges, step indicators, and text to use theme-based tokens. Adapts visual states for dark/light mode.
Compliance & Subscription Plan Components
src/components/compliance-status.tsx, src/components/subscription-plan-preview.tsx, src/components/subscription-plans/blocks/subscription-plan-link.tsx
Replaces explicit color classes with semantic tokens for status, plan, and badge styling.
Utility and Miscellaneous Components
src/components/short-address.tsx, src/components/ui/tooltip.tsx
Updates utility components to use theme-based color and background classes.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant App
    participant ThemeProvider
    participant ModeToggle

    User->>App: Loads application
    App->>ThemeProvider: Wraps UI in ThemeProvider
    ThemeProvider-->>App: Provides theme context (dark/light)
    App->>ModeToggle: Renders theme toggle button
    User->>ModeToggle: Clicks toggle
    ModeToggle->>ThemeProvider: Updates theme (dark/light)
    ThemeProvider-->>App: Updates theme context
    App-->>User: Rerenders UI with new theme tokens
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • MantisClone

Note

🔌 MCP (Model Context Protocol) integration is now available in Early Access!

Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context.


📜 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 812190e and b229dcd.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (36)
  • src/app/dashboard/layout.tsx (2 hunks)
  • src/app/i/[id]/page.tsx (1 hunks)
  • src/app/invoices/create/page.tsx (1 hunks)
  • src/app/layout.tsx (2 hunks)
  • src/components/background-wrapper.tsx (3 hunks)
  • src/components/batch-payout.tsx (17 hunks)
  • src/components/compliance-status.tsx (1 hunks)
  • src/components/create-recurring-payment/blocks/create-recurring-payment-form.tsx (2 hunks)
  • src/components/create-recurring-payment/create-recurring-payment.tsx (5 hunks)
  • src/components/dashboard/blocks/invoice-row.tsx (5 hunks)
  • src/components/dashboard/invoices-received.tsx (6 hunks)
  • src/components/dashboard/invoices-sent.tsx (2 hunks)
  • src/components/dashboard/subscriptions.tsx (5 hunks)
  • src/components/direct-payout.tsx (10 hunks)
  • src/components/footer.tsx (1 hunks)
  • src/components/header.tsx (4 hunks)
  • src/components/invoice-form.tsx (2 hunks)
  • src/components/invoice-me-link.tsx (1 hunks)
  • src/components/invoice-me-links.tsx (3 hunks)
  • src/components/invoice-preview.tsx (7 hunks)
  • src/components/mode-toggle.tsx (1 hunks)
  • src/components/payment-route.tsx (4 hunks)
  • src/components/payment-section.tsx (10 hunks)
  • src/components/payment-secured-using-request.tsx (1 hunks)
  • src/components/short-address.tsx (1 hunks)
  • src/components/stat-card.tsx (1 hunks)
  • src/components/subscription-plan-preview.tsx (5 hunks)
  • src/components/subscription-plans/blocks/subscription-plan-link.tsx (3 hunks)
  • src/components/ui/table/empty-state.tsx (1 hunks)
  • src/components/ui/table/pagination.tsx (2 hunks)
  • src/components/ui/table/table-head-cell.tsx (1 hunks)
  • src/components/ui/tooltip.tsx (1 hunks)
  • src/components/view-recurring-payments/blocks/completed-payments.tsx (1 hunks)
  • src/components/view-recurring-payments/blocks/frequency-badge.tsx (1 hunks)
  • src/components/view-recurring-payments/blocks/status-badge.tsx (1 hunks)
  • src/components/view-recurring-payments/view-recurring-payments.tsx (8 hunks)
✅ Files skipped from review due to trivial changes (12)
  • src/components/view-recurring-payments/blocks/frequency-badge.tsx
  • src/components/view-recurring-payments/blocks/completed-payments.tsx
  • src/components/ui/table/pagination.tsx
  • src/components/ui/table/table-head-cell.tsx
  • src/components/create-recurring-payment/create-recurring-payment.tsx
  • src/components/payment-secured-using-request.tsx
  • src/components/create-recurring-payment/blocks/create-recurring-payment-form.tsx
  • src/app/invoices/create/page.tsx
  • src/components/ui/table/empty-state.tsx
  • src/components/dashboard/invoices-received.tsx
  • src/components/payment-section.tsx
  • src/components/stat-card.tsx
🚧 Files skipped from review as they are similar to previous changes (24)
  • src/components/footer.tsx
  • src/app/dashboard/layout.tsx
  • src/components/mode-toggle.tsx
  • src/components/invoice-preview.tsx
  • src/components/view-recurring-payments/blocks/status-badge.tsx
  • src/components/header.tsx
  • src/components/background-wrapper.tsx
  • src/components/batch-payout.tsx
  • src/components/subscription-plan-preview.tsx
  • src/components/short-address.tsx
  • src/components/invoice-me-link.tsx
  • src/app/i/[id]/page.tsx
  • src/components/ui/tooltip.tsx
  • src/components/dashboard/subscriptions.tsx
  • src/components/compliance-status.tsx
  • src/app/layout.tsx
  • src/components/dashboard/blocks/invoice-row.tsx
  • src/components/direct-payout.tsx
  • src/components/view-recurring-payments/view-recurring-payments.tsx
  • src/components/invoice-me-links.tsx
  • src/components/invoice-form.tsx
  • src/components/subscription-plans/blocks/subscription-plan-link.tsx
  • src/components/payment-route.tsx
  • src/components/dashboard/invoices-sent.tsx
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • 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
🪧 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.
    • Explain this complex logic.
    • 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 explain this code block.
  • 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 explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @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.

@MantisClone
Copy link
Member

Hello @mayur1377, thank you for submitting your first pull request to the easy-invoice repository. We value your contribution and encourage you to review our contribution guidelines to ensure your submission meets our standards. Please note that every merged PR is automatically enrolled in our Best PR Initiative, offering a chance to win $500 each quarter. Our team is available via GitHub Discussions or Discord if you have any questions. Welcome aboard!

@MantisClone
Copy link
Member

Thank you for your submission! As you prepare for the review process, please ensure that your PR title, description, and any linked issues fully comply with our contribution guidelines. A clear explanation of your changes and their context will help expedite the review process. Every merged PR is automatically entered into our Best PR Initiative, offering a chance to win $500 every quarter. We appreciate your attention to detail and look forward to reviewing your contribution!

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 (7)
src/components/short-address.tsx (1)

25-30: Improve accessibility with an explicit label

Screen-reader users cannot rely on the visual tooltip; add an aria-label so the button’s purpose is announced even without hover/focus.

-        <button
-          type="button"
-          onClick={handleCopy}
-          className={`text-muted-foreground hover:text-foreground transition-colors flex items-center gap-2 ${className}`}
+        <button
+          type="button"
+          aria-label="Copy address to clipboard"
+          onClick={handleCopy}
+          className={`text-muted-foreground hover:text-foreground transition-colors flex items-center gap-2 ${className}`}
src/components/subscription-plans/blocks/create-subscription-plan.tsx (1)

281-289: Minor UX nit – keep disabled state truly muted
When isLoading is true the button is disabled, yet the hover:text-foreground class still applies and can visually “brighten” the label on hover (HTML disables click events, but the hover style still triggers).
Consider guarding the hover style so it does not activate while disabled:

-className="flex items-center text-sm text-muted-foreground hover:text-foreground transition-colors"
+className="flex items-center text-sm text-muted-foreground transition-colors
+            hover:text-foreground disabled:hover:text-muted-foreground"
src/components/view-recurring-payments/blocks/status-badge.tsx (1)

7-11: Inconsistent background opacity for “paused” badge
All other statuses use the color/10 translucent background pattern, but paused falls back to bg-muted (opaque). For visual consistency you might want:

-  paused: "bg-muted text-muted-foreground border-border",
+  paused: "bg-muted/10 text-muted-foreground border-border",

(if your tailwind config exposes a muted/10 token).

src/components/view-recurring-payments/view-recurring-payments.tsx (1)

82-85: Prefer token without embedded opacity for destructive borders

border-destructive/30 mixes semantic token + hard-coded opacity. Consider a pure token (e.g. border-destructive) and control transparency through CSS variables or the design-system’s .opacity-* utilities to stay fully theme-driven.

src/components/dashboard/invoices-sent.tsx (1)

95-98: Use the Button’s variant API instead of hard-coding colors

Manually setting bg-primary, hover:bg-primary/80, and text-primary-foreground bypasses the button component’s variant system and may diverge if the theme palette changes.

-<Button className="bg-primary hover:bg-primary/80 text-primary-foreground">
+<Button variant="default">

Keeps styling consistent and centralised.

src/components/payment-route.tsx (1)

129-133: Replace hard-coded text-purple-600 with a theme token

This is the last hard-coded colour in the component. Using something like text-primary-foreground (or a dedicated “brand” token) keeps dark-mode contrast predictable.

-<span className="text-purple-600">
+<span className="text-primary-foreground">
src/components/background-wrapper.tsx (1)

67-87: Consider dark mode decorative elements.

The decorative gradient elements are completely hidden in dark mode, which might make the dark theme feel visually empty compared to the light theme.

Consider adding subtle dark mode decoratives:

-      {/* Decorative elements - only show in light mode */}
-      {!isDark && (
+      {/* Decorative elements */}
+      {isDark ? (
+        <>
+          <div className="absolute top-0 right-0 w-[600px] h-[600px] -translate-y-1/2 translate-x-1/2">
+            <div
+              className="w-full h-full rounded-full opacity-10 blur-3xl"
+              style={{
+                background: `linear-gradient(to bottom right, ${getTailwindColor("slate-800")}, ${getTailwindColor("slate-900")})`,
+              }}
+            />
+          </div>
+          <div className="absolute bottom-0 left-0 w-[600px] h-[600px] translate-y-1/2 -translate-x-1/2">
+            <div
+              className="w-full h-full rounded-full opacity-10 blur-3xl"
+              style={{
+                background: `linear-gradient(to top right, ${getTailwindColor("zinc-800")}, ${getTailwindColor("zinc-900")})`,
+              }}
+            />
+          </div>
+        </>
+      ) : (
         <>
           <div className="absolute top-0 right-0 w-[600px] h-[600px] -translate-y-1/2 translate-x-1/2">
             <div
               className="w-full h-full rounded-full opacity-30 blur-3xl"
               style={{
                 background: `linear-gradient(to bottom right, ${getTailwindColor(topGradient.from)}, ${getTailwindColor(topGradient.to)})`,
               }}
             />
           </div>
           <div className="absolute bottom-0 left-0 w-[600px] h-[600px] translate-y-1/2 -translate-x-1/2">
             <div
               className="w-full h-full rounded-full opacity-30 blur-3xl"
               style={{
                 background: `linear-gradient(to top right, ${getTailwindColor(bottomGradient.from)}, ${getTailwindColor(bottomGradient.to)})`,
               }}
             />
           </div>
         </>
-      )}
+      )}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c710014 and 812190e.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (38)
  • src/app/dashboard/layout.tsx (2 hunks)
  • src/app/i/[id]/page.tsx (1 hunks)
  • src/app/invoices/create/page.tsx (1 hunks)
  • src/app/layout.tsx (2 hunks)
  • src/components/background-wrapper.tsx (3 hunks)
  • src/components/batch-payout.tsx (17 hunks)
  • src/components/compliance-status.tsx (1 hunks)
  • src/components/create-recurring-payment/blocks/create-recurring-payment-form.tsx (2 hunks)
  • src/components/create-recurring-payment/create-recurring-payment.tsx (5 hunks)
  • src/components/dashboard/blocks/empty-state.tsx (1 hunks)
  • src/components/dashboard/blocks/invoice-row.tsx (5 hunks)
  • src/components/dashboard/blocks/pagination.tsx (2 hunks)
  • src/components/dashboard/blocks/stat-card.tsx (1 hunks)
  • src/components/dashboard/blocks/table-head-cell.tsx (1 hunks)
  • src/components/dashboard/invoices-received.tsx (6 hunks)
  • src/components/dashboard/invoices-sent.tsx (2 hunks)
  • src/components/dashboard/subscriptions.tsx (4 hunks)
  • src/components/direct-payout.tsx (10 hunks)
  • src/components/footer.tsx (1 hunks)
  • src/components/header.tsx (4 hunks)
  • src/components/invoice-form.tsx (2 hunks)
  • src/components/invoice-me-link.tsx (1 hunks)
  • src/components/invoice-me-links.tsx (3 hunks)
  • src/components/invoice-preview.tsx (7 hunks)
  • src/components/mode-toggle.tsx (1 hunks)
  • src/components/payment-route.tsx (4 hunks)
  • src/components/payment-section.tsx (10 hunks)
  • src/components/payment-secured-using-request.tsx (1 hunks)
  • src/components/short-address.tsx (1 hunks)
  • src/components/subscription-plan-preview.tsx (5 hunks)
  • src/components/subscription-plans/blocks/create-subscription-plan.tsx (1 hunks)
  • src/components/subscription-plans/blocks/subscription-plan-link.tsx (3 hunks)
  • src/components/subscription-plans/subscription-plans.tsx (2 hunks)
  • src/components/ui/tooltip.tsx (1 hunks)
  • src/components/view-recurring-payments/blocks/completed-payments.tsx (1 hunks)
  • src/components/view-recurring-payments/blocks/frequency-badge.tsx (1 hunks)
  • src/components/view-recurring-payments/blocks/status-badge.tsx (1 hunks)
  • src/components/view-recurring-payments/view-recurring-payments.tsx (8 hunks)
🧰 Additional context used
🧠 Learnings (15)
📓 Common learnings
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#21
File: src/components/background-wrapper.tsx:31-31
Timestamp: 2025-02-20T10:26:33.809Z
Learning: Dynamic Tailwind class interpolation for gradient classes (from-${color} and to-${color}) in the BackgroundWrapper component is intentionally implemented this way and doesn't require a mapping object solution.
📚 Learning: dynamic tailwind class interpolation for gradient classes (from-${color} and to-${color}) in the bac...
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#21
File: src/components/background-wrapper.tsx:31-31
Timestamp: 2025-02-20T10:26:33.809Z
Learning: Dynamic Tailwind class interpolation for gradient classes (from-${color} and to-${color}) in the BackgroundWrapper component is intentionally implemented this way and doesn't require a mapping object solution.

Applied to files:

  • src/app/i/[id]/page.tsx
  • src/components/view-recurring-payments/blocks/status-badge.tsx
  • src/components/background-wrapper.tsx
📚 Learning: the `payrequest` function in the invoice router retrieves payment transactions calldata from the req...
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#2
File: src/server/routers/invoice.ts:0-0
Timestamp: 2025-02-12T13:04:46.135Z
Learning: The `payRequest` function in the invoice router retrieves payment transactions calldata from the Request API and does not process the payment itself. The actual payment status update happens through the webhook handler.

Applied to files:

  • src/components/payment-secured-using-request.tsx
📚 Learning: the handleformsubmit function in src/components/invoice-form.tsx correctly uses data.clientemail fro...
Learnt from: rodrigopavezi
PR: RequestNetwork/easy-invoice#45
File: src/components/invoice-form.tsx:316-319
Timestamp: 2025-05-19T13:00:48.790Z
Learning: The handleFormSubmit function in src/components/invoice-form.tsx correctly uses data.clientEmail from the form submission data to find matching payers, which is the proper implementation.

Applied to files:

  • src/app/dashboard/layout.tsx
  • src/components/create-recurring-payment/blocks/create-recurring-payment-form.tsx
  • src/components/payment-section.tsx
  • src/components/direct-payout.tsx
  • src/components/dashboard/invoices-sent.tsx
  • src/components/invoice-form.tsx
  • src/components/invoice-preview.tsx
  • src/components/dashboard/invoices-received.tsx
  • src/components/dashboard/blocks/invoice-row.tsx
📚 Learning: the appkit wallet module requires initialization time before it's ready for use. a 2-second delay is...
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#23
File: src/components/direct-payment.tsx:63-89
Timestamp: 2025-02-27T13:58:33.590Z
Learning: The AppKit wallet module requires initialization time before it's ready for use. A 2-second delay is intentionally used in the DirectPayment component to ensure the wallet is fully initialized before allowing interactions.

Applied to files:

  • src/components/subscription-plan-preview.tsx
  • src/components/create-recurring-payment/create-recurring-payment.tsx
  • src/components/direct-payout.tsx
  • src/components/batch-payout.tsx
📚 Learning: in src/components/batch-payout.tsx, the user prefers to keep the simple 2-second timeout for appkit ...
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#64
File: src/components/batch-payout.tsx:100-106
Timestamp: 2025-06-04T10:08:40.123Z
Learning: In src/components/batch-payout.tsx, the user prefers to keep the simple 2-second timeout for AppKit initialization over more complex polling mechanisms when the current approach is working adequately. They favor simplicity over potentially more robust but complex solutions.

Applied to files:

  • src/components/subscription-plan-preview.tsx
  • src/components/create-recurring-payment/create-recurring-payment.tsx
  • src/components/direct-payout.tsx
  • src/components/batch-payout.tsx
📚 Learning: the easy-invoice project prefers simpler, direct implementations over abstract utilities. for exampl...
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#21
File: src/app/invoices/[ID]/page.tsx:113-148
Timestamp: 2025-02-20T10:27:02.993Z
Learning: The easy-invoice project prefers simpler, direct implementations over abstract utilities. For example, using `.toFixed(2)` directly instead of creating separate number formatting utilities.

Applied to files:

  • src/components/payment-section.tsx
  • src/components/invoice-preview.tsx
  • src/components/dashboard/blocks/invoice-row.tsx
📚 Learning: in the requestnetwork/easy-invoice codebase, monetary amounts are stored as text in the database sch...
Learnt from: bassgeta
PR: RequestNetwork/easy-invoice#91
File: drizzle/0007_messy_silver_fox.sql:1-12
Timestamp: 2025-07-14T14:17:05.340Z
Learning: In the RequestNetwork/easy-invoice codebase, monetary amounts are stored as text in the database schema rather than numeric types. This is a deliberate architectural decision to maintain consistency across all amount fields in the system.

Applied to files:

  • src/components/payment-section.tsx
📚 Learning: in the paymentsection component of easyinvoice, selectedroute is automatically set to the first rout...
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#42
File: src/components/payment-section.tsx:534-544
Timestamp: 2025-03-25T09:31:47.519Z
Learning: In the PaymentSection component of EasyInvoice, selectedRoute is automatically set to the first route when payment routes are loaded, and users can only switch between routes, not deselect them entirely.

Applied to files:

  • src/components/payment-section.tsx
  • src/components/payment-route.tsx
  • src/components/batch-payout.tsx
📚 Learning: for the directpayment component, amount validation is already handled through zod schema validation ...
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#23
File: src/components/direct-payment.tsx:343-360
Timestamp: 2025-02-27T14:02:35.047Z
Learning: For the DirectPayment component, amount validation is already handled through Zod schema validation in paymentFormSchema, which ensures the amount is greater than zero.

Applied to files:

  • src/components/direct-payout.tsx
📚 Learning: in the easy invoice project, settimeout is required when submitting a form after modal state changes...
Learnt from: rodrigopavezi
PR: RequestNetwork/easy-invoice#45
File: src/components/invoice-form.tsx:451-453
Timestamp: 2025-05-20T12:59:44.665Z
Learning: In the Easy Invoice project, setTimeout is required when submitting a form after modal state changes in the crypto-to-fiat payment flow. Directly calling handleFormSubmit without setTimeout after closing modals and updating state causes issues.

Applied to files:

  • src/components/direct-payout.tsx
  • src/components/invoice-form.tsx
📚 Learning: for webhook handlers in the easy invoice project, unknown or unexpected substatus values in payment ...
Learnt from: MantisClone
PR: RequestNetwork/easy-invoice#59
File: src/app/api/webhook/route.ts:77-95
Timestamp: 2025-05-22T18:19:12.366Z
Learning: For webhook handlers in the Easy Invoice project, unknown or unexpected subStatus values in payment processing should be treated as errors (using console.error) rather than warnings, and should return a 422 Unprocessable Entity status code.

Applied to files:

  • src/components/direct-payout.tsx
📚 Learning: the invoice me links in the easy-invoice project do not have an expiration mechanism. the invoicemet...
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#8
File: src/app/i/[id]/page.tsx:18-22
Timestamp: 2025-02-13T21:57:39.869Z
Learning: The invoice me links in the easy-invoice project do not have an expiration mechanism. The invoiceMeTable schema only includes id, label, userId, and createdAt fields.

Applied to files:

  • src/components/dashboard/invoices-sent.tsx
  • src/components/dashboard/invoices-received.tsx
📚 Learning: in `src/server/routers/payment.ts`, the batchpay input validation already handles empty arrays corre...
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#67
File: src/server/routers/payment.ts:47-49
Timestamp: 2025-06-04T12:02:39.411Z
Learning: In `src/server/routers/payment.ts`, the batchPay input validation already handles empty arrays correctly. The `batchPaymentFormSchema.shape.payouts.optional()` inherits the `.min(1, "At least one payment is required")` validation from the original schema, so empty payouts arrays are automatically rejected even when the field is made optional.

Applied to files:

  • src/components/batch-payout.tsx
📚 Learning: invoice items are validated at creation time through the schema validation in src/lib/schemas/invoic...
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#2
File: src/app/invoices/[ID]/page.tsx:160-175
Timestamp: 2025-02-12T12:42:40.076Z
Learning: Invoice items are validated at creation time through the schema validation in src/lib/schemas/invoice.ts, ensuring that items array is non-empty and each item has required description, quantity, and price fields. Runtime validation in display components is not necessary.

Applied to files:

  • src/components/invoice-preview.tsx
🧬 Code Graph Analysis (9)
src/components/dashboard/blocks/table-head-cell.tsx (2)
src/components/ui/table.tsx (1)
  • TableHead (113-113)
src/lib/utils.ts (1)
  • cn (4-6)
src/components/view-recurring-payments/view-recurring-payments.tsx (2)
src/components/ui/card.tsx (4)
  • Card (79-79)
  • CardContent (79-79)
  • CardHeader (79-79)
  • CardTitle (79-79)
src/components/ui/table.tsx (1)
  • TableCell (115-115)
src/app/layout.tsx (5)
src/components/app-kit.tsx (1)
  • AppKit (40-42)
src/trpc/react.tsx (1)
  • TRPCReactProvider (14-60)
src/components/background-wrapper.tsx (1)
  • BackgroundWrapper (17-104)
src/components/ui/sonner.tsx (1)
  • Toaster (31-31)
src/components/version-badge.tsx (1)
  • VersionDisplay (9-19)
src/components/payment-section.tsx (1)
src/lib/constants/currencies.ts (2)
  • MAINNET_CURRENCIES (2-18)
  • formatCurrencyLabel (94-139)
src/components/header.tsx (1)
src/components/mode-toggle.tsx (1)
  • ModeToggle (6-40)
src/components/mode-toggle.tsx (1)
src/components/ui/button.tsx (1)
  • Button (56-56)
src/components/invoice-preview.tsx (2)
src/components/ui/card.tsx (2)
  • Card (79-79)
  • CardContent (79-79)
src/lib/date-utils.ts (1)
  • formatDate (9-17)
src/components/dashboard/invoices-received.tsx (3)
src/components/dashboard/blocks/table-head-cell.tsx (1)
  • TableHeadCell (9-13)
src/components/dashboard/blocks/stat-card.tsx (1)
  • StatCard (9-21)
src/components/ui/card.tsx (1)
  • Card (79-79)
src/components/subscription-plans/blocks/subscription-plan-link.tsx (2)
src/components/ui/card.tsx (2)
  • Card (79-79)
  • CardContent (79-79)
src/components/ui/button.tsx (1)
  • Button (56-56)
🔇 Additional comments (61)
src/components/view-recurring-payments/blocks/completed-payments.tsx (1)

17-19: Adopts semantic token – looks good

Swapping text-zinc-500 for text-muted-foreground aligns the component with the new theme system and keeps contrast appropriate in both light / dark modes.

src/components/footer.tsx (1)

5-7: Consistent theming – no issues

text-muted-foreground provides the right semantic colour for footer copy and matches tokens used elsewhere in the PR.

src/components/dashboard/blocks/pagination.tsx (2)

22-24: Verify design tokens exist in Tailwind config

The new border-border token assumes a corresponding entry in the theme’s colors map; if it’s missing, the border will be transparent. Please confirm the token is defined (light & dark).


32-33: Semantic text colour – looks good

text-muted-foreground is the right choice for the page indicator; contrast remains acceptable in both themes.

src/components/ui/tooltip.tsx (1)

16-22: Theme tokens applied correctly

bg-popover, text-popover-foreground, and fill-popover match the token naming used elsewhere; no functional impact detected.

src/components/create-recurring-payment/blocks/create-recurring-payment-form.tsx (2)

193-193: LGTM! Correct semantic color token usage.

The replacement of text-zinc-500 with text-muted-foreground is appropriate for help text, ensuring proper contrast in both light and dark themes.


279-279: LGTM! Proper theme-aware button styling.

The replacement of text-zinc-500 hover:text-zinc-800 with text-muted-foreground hover:text-foreground correctly implements semantic color tokens for both normal and hover states, ensuring proper theming across light and dark modes.

src/app/i/[id]/page.tsx (1)

40-40: LGTM! Consistent navigation link theming.

The replacement of text-zinc-600 hover:text-black with text-muted-foreground hover:text-foreground properly implements semantic color tokens for the back navigation link, ensuring consistent theming across light and dark modes.

src/components/dashboard/blocks/table-head-cell.tsx (1)

10-10: LGTM! Appropriate semantic token for table headers.

The replacement of text-zinc-500 with text-muted-foreground is ideal for table headers, providing appropriate visual hierarchy while ensuring proper contrast across light and dark themes.

src/app/invoices/create/page.tsx (1)

30-30: LGTM! Consistent with navigation theming pattern.

The color token replacement follows the same pattern as other navigation links in the codebase, ensuring consistent theming for back navigation elements across the application.

src/app/dashboard/layout.tsx (1)

5-5: LGTM! Improved UI consistency with design system.

The replacement of a custom-styled Link with a Button component using asChild improves consistency with the design system while maintaining the same functionality. This approach provides better theme integration and standardized button styling across the application.

Also applies to: 28-33

src/components/dashboard/blocks/empty-state.tsx (1)

17-21: Semantic token migration looks good
bg-muted, text-foreground, and text-muted-foreground correctly replace the previous hard-coded zinc shades and align with the new theme system. No functional impact detected.

src/components/payment-secured-using-request.tsx (1)

3-8: Consistent success palette usage confirmed
Using bg-success/10, border-success, and the corresponding foreground tokens keeps the component aligned with the new design-token palette. No issues found.

src/components/view-recurring-payments/blocks/frequency-badge.tsx (1)

7-10: LGTM – badges now leverage theme tokens
The frequency badge palette mirrors the status-badge approach and cleanly adopts semantic tokens. No functional or visual concerns noted.

src/components/subscription-plans/subscription-plans.tsx (1)

35-35: LGTM! Consistent theming implementation.

The color class replacements correctly follow the semantic theming pattern - using text-muted-foreground for secondary elements and bg-primary with text-primary-foreground for primary actions. The hover states are properly maintained.

Also applies to: 45-45

src/components/dashboard/subscriptions.tsx (1)

39-39: Excellent theming consistency across the component.

All color replacements follow the semantic token pattern correctly:

  • Table hover states use hover:bg-muted/50 for subtle interactions
  • Icons consistently use text-muted-foreground for secondary visual elements
  • Card borders use the semantic border-border token

Also applies to: 85-85, 179-179, 184-184, 189-189, 193-193, 204-206

src/components/subscription-plan-preview.tsx (1)

120-120: Comprehensive theming implementation across all text elements.

The color replacements consistently follow the semantic token pattern:

  • Secondary labels and descriptive text use text-muted-foreground
  • Interactive elements maintain proper hover states with hover:text-foreground
  • Loading states and instructions appropriately use muted styling

Also applies to: 141-143, 151-153, 159-161, 169-171, 179-181, 187-189, 252-252, 283-283, 294-297

src/components/invoice-form.tsx (1)

590-590: Proper theming implementation in modal and form elements.

The color updates correctly use semantic tokens:

  • Spinner border uses border-foreground for primary visual elements
  • Modal text uses text-muted-foreground for secondary content
  • Submit button follows the primary color scheme pattern with proper hover states

Also applies to: 591-591, 595-595, 1039-1039

src/components/dashboard/blocks/stat-card.tsx (1)

10-10: Perfect implementation of card theming pattern.

The semantic token usage is exactly right:

  • bg-card, border-border, and text-card-foreground provide proper theme support for the card container
  • text-muted-foreground appropriately styles the secondary title text

This follows the established theming pattern consistently.

Also applies to: 12-12

src/components/invoice-me-link.tsx (1)

49-76: LGTM! Consistent theming implementation.

The styling updates properly replace hardcoded zinc colors with semantic theme tokens (text-foreground, text-muted-foreground, bg-muted, hover:bg-muted). The destructive delete button correctly maintains its red styling for visual clarity.

src/app/layout.tsx (3)

12-12: LGTM! Proper ThemeProvider import.


36-36: LGTM! Correct hydration warning suppression.

The suppressHydrationWarning attribute prevents React hydration mismatches that occur during theme initialization, which is a standard practice when implementing themes.


41-51: LGTM! Excellent ThemeProvider configuration.

The ThemeProvider is properly configured with:

  • attribute="class" for CSS class-based theming
  • defaultTheme="system" to respect user's system preference
  • enableSystem to detect system theme changes
  • Correct nesting with other providers maintains the component hierarchy
src/components/dashboard/blocks/invoice-row.tsx (1)

52-119: LGTM! Comprehensive and consistent theming updates.

All styling changes properly implement the semantic token approach:

  • Row hover states use bg-muted/50 for subtle interaction feedback
  • Secondary text elements (recurrence, email, dates) consistently use text-muted-foreground
  • Action buttons use semantic tokens (bg-card, border-border, hover:bg-muted)
  • Icons appropriately use text-muted-foreground for consistent visual hierarchy
src/components/dashboard/invoices-received.tsx (4)

38-47: LGTM! Consistent table header styling.

Table header cells properly use text-muted-foreground for secondary text hierarchy.


190-211: LGTM! Well-designed selection summary and CTA.

The selected invoices summary box uses appropriate muted styling (bg-muted, border-border), while the batch pay button correctly uses primary colors to emphasize the call-to-action.


219-229: LGTM! Consistent stat card icon styling.

All stat card icons consistently use text-muted-foreground for proper visual hierarchy.


233-246: LGTM! Proper card and empty state theming.

The table card uses semantic border tokens, and the empty state icon is appropriately styled with muted foreground color.

src/components/invoice-me-links.tsx (3)

60-60: LGTM! Proper navigation link theming.

The back navigation link correctly uses text-muted-foreground to text-foreground transition on hover, maintaining consistent navigation styling.


70-70: LGTM! Appropriate primary button styling.

The "New Link" button properly uses primary color tokens for call-to-action emphasis.


99-99: LGTM! Consistent CTA button styling.

The "Create" button maintains consistency with the primary button styling pattern established throughout the application.

src/components/compliance-status.tsx (1)

29-55: LGTM! Excellent semantic token implementation.

The STATUS_CONFIG object has been consistently updated to use semantic design tokens instead of hardcoded color utilities. The mapping is well-structured:

  • destructive tokens for error states (not_started)
  • warning tokens for in-progress states (initiated, pending)
  • success tokens for completed states (completed, approved)

This change enables proper theme support and maintains visual consistency across light and dark modes.

src/components/mode-toggle.tsx (1)

1-41: Excellent theme toggle implementation!

The ModeToggle component is well-implemented with several notable strengths:

  1. Smooth animations: Uses CSS transforms with cubic-bezier timing for professional feel
  2. Accessibility: Includes proper aria-label for screen readers
  3. Visual feedback: Clear Sun/Moon icons with rotation animation
  4. Theme-aware styling: Uses semantic tokens (bg-muted, text-foreground) that adapt to current theme
  5. Clean API: Simple toggle between light/dark modes

The sliding animation with the calculated translateX and icon rotation creates an intuitive user experience.

src/components/invoice-preview.tsx (3)

32-32: Good semantic token adoption for card container.

The Card component now uses proper theme-aware tokens (bg-card, text-card-foreground, border-border) instead of hardcoded colors, enabling proper dark mode support.


38-242: Consistent text color token updates throughout the component.

All instances of hardcoded text-neutral-500 and text-neutral-600 have been systematically replaced with text-muted-foreground. This creates consistent theming for:

  • Section labels (INVOICE NO, ISSUED, DUE DATE, etc.)
  • Email addresses and contact information
  • Table headers and secondary text
  • Notes and payment details

The semantic token approach ensures proper contrast ratios in both light and dark themes.


128-157: Border styling properly updated for theme consistency.

Table borders and dividers now use border-border instead of border-neutral-200, ensuring they adapt appropriately to the current theme.

src/components/header.tsx (4)

3-3: Good integration of theme toggle component.

The ModeToggle component is properly imported and will be integrated into the header navigation.


24-30: Logo styling updated for theme consistency.

The logo container now uses semantic tokens (bg-primary, text-primary-foreground, text-foreground) ensuring it adapts properly to both light and dark themes while maintaining brand identity.


37-68: Navigation links properly themed.

All navigation links now use consistent semantic tokens:

  • text-foreground for normal state
  • text-muted-foreground for hover state
  • Proper theme-aware styling for the "Book A Demo" link

This ensures good readability and visual hierarchy in both light and dark modes.


93-93: Theme toggle well-positioned in navigation.

The ModeToggle component is appropriately placed at the end of the navigation items, providing easy access to theme switching without cluttering the main navigation flow.

src/components/batch-payout.tsx (6)

262-280: Card styling properly updated for theme support.

The main Card container and header now use semantic tokens (bg-card, text-card-foreground, border-border, bg-muted) ensuring consistent theming across light and dark modes while maintaining the visual hierarchy.


285-289: Loading state styling theme-aware.

The loading spinner and text now use text-muted-foreground for consistent secondary text styling that adapts to the current theme.


298-330: Step indicators properly themed.

The wallet connection and payment steps now use semantic tokens for:

  • Active/inactive state colors (text-foreground vs text-muted-foreground)
  • Step backgrounds (bg-muted for active, border-border for inactive)
  • Progress bar styling

This maintains clear visual progression while supporting both themes.


350-498: Table styling comprehensively updated.

The payments table now uses consistent semantic tokens throughout:

  • Table borders (border-border)
  • Row hover states (hover:bg-muted/50)
  • Input focus rings (focus-visible:ring-border)
  • Action button styling with proper destructive colors
  • Cell text hierarchy with text-muted-foreground for row numbers

All interactive elements maintain proper accessibility while supporting theme switching.


509-572: Summary and action sections well-themed.

The batch summary card and action buttons use appropriate semantic tokens:

  • Summary card background (bg-muted)
  • Text hierarchy for labels and values
  • Add payment button with dashed border styling
  • Consistent use of text-muted-foreground for secondary information

The theming maintains the component's functional clarity while enabling dark mode support.


578-585: Footer wallet address styling updated.

The connected wallet address display now uses theme-aware colors (text-muted-foreground, hover:text-foreground) ensuring good readability in both light and dark modes.

src/components/view-recurring-payments/view-recurring-payments.tsx (1)

150-152: LGTM – token migration looks solid

The switch to bg-muted, border-border, and text-card-foreground is consistent with the rest of the PR. No functional impact detected.

src/components/create-recurring-payment/create-recurring-payment.tsx (1)

49-53: LGTM – loader adopts semantic colour

Replacing the hard-coded zinc tint with text-muted-foreground aligns the spinner with both light and dark themes.

src/components/direct-payout.tsx (1)

216-227: No changes needed: border-foreground is valid
The Tailwind config defines a top-level foreground color token, and Tailwind generates border-<color> utilities for every theme color. Therefore border-foreground does exist and will correctly apply the foreground border color.

src/components/payment-section.tsx (4)

404-410: LGTM! Proper semantic token usage for success styling.

The secure payment section correctly uses semantic success tokens (bg-success/10, border-success, text-success, text-success-foreground) which will adapt properly to both light and dark themes.


413-428: LGTM! Consistent warning styling with semantic tokens.

The cryptocurrency warning section properly implements semantic warning tokens (bg-warning/10, border-warning, text-warning, text-warning-foreground) for theme-aware styling.


439-448: LGTM! Proper muted styling implementation.

The currency conversion display and recipient address sections correctly use semantic muted tokens (text-muted-foreground, bg-muted, border-border) for consistent theming.

Also applies to: 455-463


472-516: LGTM! Consistent step indicators and loading states styling.

The payment steps, wallet connection UI, and loading states properly implement semantic tokens (text-foreground, text-muted-foreground, bg-muted, border-foreground, border-muted) for theme consistency.

Also applies to: 522-567, 584-648

src/components/background-wrapper.tsx (4)

1-2: LGTM! Proper theme integration.

The component correctly integrates the useTheme hook from next-themes to enable theme-aware styling. The implementation follows React best practices for theme detection.

Also applies to: 28-29, 61-61


49-54: LGTM! Dark mode color additions.

The dark mode color hex codes are properly added to the color mapping. The zinc and slate variations provide good options for dark theme styling.


64-66: LGTM! Theme-aware background implementation.

The dynamic background color switching between light (#FAFAFA) and dark (#0A0A0A) themes is properly implemented using conditional rendering.


93-95: LGTM! Theme-aware dot pattern implementation.

The dot pattern background correctly adapts its color based on the theme (#1f1f1f for dark, #e5e5e5 for light), providing consistent visual texture across themes.

src/components/subscription-plans/blocks/subscription-plan-link.tsx (4)

79-79: LGTM! Proper Card styling with semantic tokens.

The Card component correctly uses semantic design tokens (bg-card, border-border, text-card-foreground) for consistent theming across light and dark modes.


84-85: LGTM! Consistent text styling with semantic tokens.

The text elements properly use semantic tokens (text-foreground for primary text, text-muted-foreground for secondary text) ensuring proper contrast and readability in both themes.

Also applies to: 101-101, 105-105


114-114: LGTM! Proper button and icon styling.

The action buttons correctly use hover:bg-muted for hover states and text-muted-foreground for icons, providing consistent interactive feedback across themes.

Also applies to: 117-117, 123-123, 127-127


135-139: LGTM! Appropriate preservation of destructive styling.

The delete button intentionally maintains its red styling (hover:bg-red-50, text-red-500) which is correct UX practice - destructive actions should maintain their warning appearance regardless of theme to prevent accidental deletions.

Copy link
Contributor

@bassgeta bassgeta left a comment

Choose a reason for hiding this comment

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

Thank you for your contribution to Easy Invoice <3
Really good work, thanks for switching our tailwind variable names to something semantic instead of just using the colour names...

On top of the 3 things I commented on, I've noticed a pretty weird bug which happens only when loading the app the very first time:
image
Something gets mixed up and some components end up in their dark theme variant, while others do not.
Tried this out on multiple Chromium browsers and I can reproduce it constantly.

The error goes away after toggling the theme at least once.

Not sure what the solution could be, but maybe the theme switcher should check if theme isn't yet set, to just default to the light theme.

Other than that loving the dark mode look 😎
image

Some more issues with dark mode:

  1. Invoice me links
image 2. The alert modal's delete text is dark, should probably be white image 3. The user popup is still white in dark mode image 4. The `/invoices/:id` page is borked image

And sadly, mandatory merge conflicts due to one of our huge PRs coming in, sorry about that 😅
After merging, do check the /subscription-plans route, there's a ton of added things there now.

After the UI issues and review comments are taken care of, I'll gladly drop an approval 💯

? "border-black bg-zinc-50"
: "border-zinc-300"
? "border-foreground bg-muted"
: "border-border"
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it possible to rename border-border into border-primary or something? border-border is a bit funny :D

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.

3 participants