Skip to content

Comments

Create email updates#407

Merged
nizzyabi merged 6 commits intostagingfrom
create-email-updates
Mar 10, 2025
Merged

Create email updates#407
nizzyabi merged 6 commits intostagingfrom
create-email-updates

Conversation

@nizzyabi
Copy link
Collaborator

@nizzyabi nizzyabi commented Mar 9, 2025

This PR includes both an update to creating emails as well as the onboarding page (WIP)

Summary by CodeRabbit

  • New Features

    • Introduced an enhanced rich text editor with a new formatting toolbar and an AI chat option.
    • Launched an animated loading spinner, new OTP input components, and revamped sign-up, login, and early access registration flows.
    • Added a new LoginZero and SignupZero component for a streamlined user experience.
    • Introduced LoginClient for improved authentication provider management.
  • Style

    • Updated visual elements including a refined navbar, animated gradient backgrounds, and improved dialog appearances.
    • Introduced a new keyframe animation for blinking caret effects in input fields.
  • Refactor

    • Removed legacy sidebars and outdated authentication screens.
    • Streamlined component structures and updated dependency configurations for enhanced UI responsiveness.
    • Simplified social provider configurations by utilizing a dedicated function for retrieval.

@vercel
Copy link

vercel bot commented Mar 9, 2025

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

Name Status Preview Comments Updated (UTC)
0 ✅ Ready (Inspect) Visit Preview 💬 Add feedback Mar 10, 2025 7:23am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 9, 2025

Walkthrough

This pull request introduces a series of changes across the Mail application. The updates include the removal of the AISidebar component from several layouts, enhancements to the AddConnectionDialog with a new icon and animated transitions, and modifications to the redirection URL in the authentication callback. Additionally, new components such as a Spinner, OTP input components, and a rich text editor menu are added. The styles have been refreshed with new CSS animations and layout adjustments, and several obsolete authentication and editor files have been removed, while package dependencies have been updated to support the new features.

Changes

Files Change Summary
apps/mail/app/(routes)/mail/layout.tsx
apps/mail/app/(routes)/settings/layout.tsx
Removed the AISidebar component and its import; updated layout padding from md:p-3 to md:py-3 md:pr-3 in MailLayout.
apps/mail/app/(routes)/settings/connections/page.tsx
apps/mail/components/connection/add.tsx
Added a new Plus icon and restructured AddConnectionDialog with an additional onOpenChange prop and animated transitions using Framer Motion.
apps/mail/app/api/v1/mail/auth/[providerId]/callback/route.ts Changed redirection URL after authentication from "/settings/connections?success=true" to "/onboarding".
apps/mail/app/globals.css
apps/mail/tailwind.config.ts
Introduced a new CSS keyframe animation gradient-flow and added a new caret-blink animation in Tailwind; updated background gradient properties and animation settings.
apps/mail/components/create/editor-buttons.tsx
apps/mail/components/create/editor.tsx
apps/mail/components/create/prosemirror.css
apps/mail/components/create/selectors/text-buttons.tsx
Enhanced the editor by adding a new MenuBar component and link management dialog; updated ProseMirror styling (padding, line-height, removal of .drag-handle); repurposed text formatting buttons to provide an AI chat option.
apps/mail/components/create/editor.css
apps/mail/app/(auth)/signup/page.tsx
apps/mail/app/(auth)/signup/verify/page.tsx
Removed obsolete editor CSS and authentication components (SignUp and VerifyEmail pages).
apps/mail/components/ui/spinner.tsx
apps/mail/components/ui/input-otp.tsx
Added a new animated Spinner component and new OTP input components (InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator) for enhanced UI feedback.
apps/mail/components/ui/dialog.tsx Updated class names for DialogOverlay and DialogContent to adjust background, blur effect, and border radius.
apps/mail/components/ui/input.tsx Updated the Input component to include a value prop with internal state management, ensuring consistency between controlled and uncontrolled states.
apps/mail/package.json
package.json
Added new dependencies: framer-motion, react-use-measure, tiptap-markdown, and several Tiptap packages along with input-otp to support new features and UI enhancements.
apps/mail/app/(auth)/login/early-access/page.tsx
apps/mail/app/(auth)/login/page.tsx
apps/mail/app/(auth)/zero/login/page.tsx
apps/mail/app/(auth)/zero/signup/page.tsx
Introduced new authentication components: EarlyAccess, LoginZero, and SignupZero; updated the traditional Login page with a new Navbar and modified email sign-in flow.
apps/mail/components/home/navbar.tsx Adjusted Navbar styling with modified string quoting, reduced logo size, and updated padding for a more compact layout.

Possibly related PRs

  • fix UI #402: Involves modifications to padding properties in MailLayout and SettingsLayoutContent, aligning with the layout adjustments in this PR.

Suggested reviewers

  • ahmetskilinc

Poem

I’m just a bunny, hopping through the code,
Leaving old sidebars behind on the road.
With menus that shine and spinners that spin,
New features now make our app a win!
Carrots and code, together we stride—
Hop in, dear friend, on this joyful ride!
🥕🐇 Happy coding!

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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.
  • @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: 6

🧹 Nitpick comments (9)
apps/mail/components/create/selectors/text-buttons.tsx (1)

4-6: Unused imports detected.

The imported icons (MessageSquare, FileText, Edit) don't appear to be used in the component. These should be removed to avoid unnecessary code bloat.

-import {
-  MessageSquare,
-  FileText,
-  Edit
-} from 'lucide-react'
+import { } from 'lucide-react'

If the Lucide React package is no longer needed at all, you can remove the import completely.

apps/mail/package.json (2)

59-59: Consider pinning dependency version.

Using caret (^) versioning allows minor version updates which could potentially introduce breaking changes, especially with UI libraries like framer-motion.

-"framer-motion": "^12.4.10",
+"framer-motion": "12.4.10",

Pinning the version ensures consistent behavior across different environments and builds.


82-82: Consider pinning dependency version.

Similarly, react-use-measure uses caret versioning which might lead to unexpected behavior if breaking changes are released in minor updates.

-"react-use-measure": "^2.1.7",
+"react-use-measure": "2.1.7",
apps/mail/components/create/editor-buttons.tsx (1)

4-177: MenuBar component is well-structured but could be more modular

The MenuBar implementation provides comprehensive text formatting options, but the repetitive button patterns could be refactored for better maintainability.

Consider extracting the button patterns into a reusable component to reduce repetition:

+ const MenuButton = ({ 
+   onClick, 
+   disabled, 
+   isActive, 
+   children 
+ }: { 
+   onClick: () => void, 
+   disabled?: boolean, 
+   isActive?: boolean, 
+   children: React.ReactNode 
+ }) => (
+   <button
+     onClick={onClick}
+     disabled={disabled}
+     className={isActive ? 'is-active' : ''}
+   >
+     {children}
+   </button>
+ )

This would simplify your formatting buttons and make the code more maintainable.

apps/mail/app/globals.css (1)

204-208: Improved gradient animation with infinite loop

The compose-gradient class now uses an enhanced animation pattern with better background sizing and the new gradient-flow animation.

One suggestion: Consider adding a media query to disable or reduce animations for users who prefer reduced motion:

@media (prefers-reduced-motion) {
  .compose-gradient {
    animation: none;
    background-position: 0% 50%;
  }
}
apps/mail/components/onboarding/oboarding-flow.tsx (3)

36-40: Enhance URL parameter handling with better validation.

The code correctly retrieves the step parameter from the URL, but consider adding more robust error handling for invalid or malformed URLs, especially since this is used to determine the onboarding flow state.

  const searchParams = new URLSearchParams(
    typeof window !== "undefined" ? window.location.search : "",
  );
  const stepParam = searchParams.get("step");
+  // Log or handle malformed URLs
+  if (typeof window !== "undefined" && window.location.search && !stepParam) {
+    console.warn("Invalid step parameter in URL");
+  }

211-257: Use optional chaining for better code conciseness.

The static analysis tool suggests using optional chaining here for better readability.

-  {connections && connections.map((connection) => (
+  {connections?.map((connection) => (
     <div key={connection.id} className="flex items-center justify-between">
       {/* rest of the code */}
     </div>
   ))}
🧰 Tools
🪛 Biome (1.9.4)

[error] 211-257: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


103-374: Consider breaking down the large renderStep function into smaller components.

The renderStep function is quite large and handles multiple different steps. Consider breaking it down into separate components for each step to improve readability and maintainability.

For example:

// Create separate components
const LoginStep = ({ isAuthenticating, setIsAuthenticating }) => (
  <motion.div key="login-step" /* animations... */ >
    {/* Login step content */}
  </motion.div>
);

const ConnectStep = ({ connections, isDialogOpen, setIsDialogOpen, router }) => (
  <motion.div key="connect-step" /* animations... */ >
    {/* Connect step content */}
  </motion.div>
);

// Then in renderStep
const renderStep = (step: number) => {
  switch (step) {
    case 0:
      return (
        <div className="flex flex-col items-center justify-center">
          <LoginStep 
            isAuthenticating={isAuthenticating} 
            setIsAuthenticating={setIsAuthenticating} 
          />
          {renderNavigation()}
        </div>
      );
    // other cases...
  }
};
🧰 Tools
🪛 Biome (1.9.4)

[error] 211-257: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

apps/mail/components/create/editor.tsx (1)

95-135: Remove unnecessary comments in the MenuBar component.

There are leftover development comments that don't add value to the code and should be removed for clarity.

- // Replace the old setLink function with this new implementation
  const handleLinkDialogOpen = () => {
    // If a link is already active, pre-fill the input with the current URL
    if (editor.isActive("link")) {
      const attrs = editor.getAttributes("link");
      setLinkUrl(attrs.href || "");
    } else {
      setLinkUrl("");
    }
    setLinkDialogOpen(true);
  };

  const handleSaveLink = () => {
-   // empty
    if (linkUrl === "") {
      editor.chain().focus().unsetLink().run();
    } else {
      // Format the URL with proper protocol if missing
      let formattedUrl = linkUrl;
      if (formattedUrl && !/^https?:\/\//i.test(formattedUrl)) {
        formattedUrl = `https://${formattedUrl}`;
      }
      // set link
      editor.chain().focus().setLink({ href: formattedUrl }).run();
    }
    setLinkDialogOpen(false);
  };
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 09674a0 and 93a3d23.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (17)
  • apps/mail/app/(routes)/mail/layout.tsx (1 hunks)
  • apps/mail/app/(routes)/settings/connections/page.tsx (2 hunks)
  • apps/mail/app/(routes)/settings/layout.tsx (0 hunks)
  • apps/mail/app/api/v1/mail/auth/[providerId]/callback/route.ts (1 hunks)
  • apps/mail/app/globals.css (1 hunks)
  • apps/mail/app/onboarding/page.tsx (1 hunks)
  • apps/mail/components/connection/add.tsx (2 hunks)
  • apps/mail/components/create/editor-buttons.tsx (1 hunks)
  • apps/mail/components/create/editor.css (0 hunks)
  • apps/mail/components/create/editor.tsx (5 hunks)
  • apps/mail/components/create/prosemirror.css (2 hunks)
  • apps/mail/components/create/selectors/text-buttons.tsx (1 hunks)
  • apps/mail/components/onboarding/oboarding-flow.tsx (1 hunks)
  • apps/mail/components/ui/dialog.tsx (2 hunks)
  • apps/mail/components/ui/spinner.tsx (1 hunks)
  • apps/mail/package.json (2 hunks)
  • package.json (1 hunks)
💤 Files with no reviewable changes (2)
  • apps/mail/components/create/editor.css
  • apps/mail/app/(routes)/settings/layout.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
apps/mail/components/onboarding/oboarding-flow.tsx

[error] 211-257: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (21)
apps/mail/components/create/selectors/text-buttons.tsx (1)

17-26: AI functionality implementation is incomplete.

The handleChatWithAI function currently only logs the selected text without implementing the actual AI functionality. Since this is a core feature being introduced, it should either be fully implemented or have a more descriptive TODO comment indicating next steps.

Consider enhancing this implementation with actual API calls to your AI service or adding more detailed TODOs about how this will be connected.

apps/mail/app/onboarding/page.tsx (1)

5-7: Component implementation is minimal but correct.

The component structure is simple and follows React best practices. It properly exports a default function that returns the OnboardingFlow component.

apps/mail/package.json (1)

59-82:

Details

✅ Verification successful

Verify that the new dependencies are being used in the codebase.

Two new dependencies (framer-motion, react-use-measure) have been added to package.json. Ensure they're being used in the codebase to avoid unnecessary dependencies.


🏁 Script executed:

#!/bin/bash
# Search for usage of framer-motion and react-use-measure in the codebase
echo "=== Searching for framer-motion usage ==="
rg -l "from ['\"]framer-motion['\"]" --type tsx --type ts

echo "=== Searching for react-use-measure usage ==="
rg -l "from ['\"]react-use-measure['\"]" --type tsx --type ts

Length of output: 381


Below is an updated script to verify the dependency usage. The previous search failed due to file-type issues with ripgrep; this new script uses the Unix find command to look through all TypeScript files (both *.ts and *.tsx):

Next Steps:
Please re-run this script manually to confirm whether these dependencies are actually imported anywhere in the TypeScript code. Once you confirm the output, we can update or resolve the review comment accordingly.


🏁 Script executed:

#!/bin/bash
echo "=== Searching for framer-motion usage in .ts/.tsx files ==="
find . -type f \( -iname "*.ts" -o -iname "*.tsx" \) -exec grep -H "from ['\"]framer-motion['\"]" {} \;

echo "=== Searching for react-use-measure usage in .ts/.tsx files ==="
find . -type f \( -iname "*.ts" -o -iname "*.tsx" \) -exec grep -H "from ['\"]react-use-measure['\"]" {} \;

Length of output: 987


Dependency usage verified: The search confirms that the new dependencies are actively used in the codebase:

  • framer-motion is imported in:

    • apps/mail/components/connection/add.tsx
    • apps/mail/components/onboarding/oboarding-flow.tsx
    • apps/mail/components/ui/spinner.tsx
  • react-use-measure is imported in:

    • apps/mail/components/onboarding/oboarding-flow.tsx

No further action is needed for these dependency changes.

apps/mail/app/api/v1/mail/auth/[providerId]/callback/route.ts (1)

62-62: Redirect flow changed from settings to onboarding.

The redirect URL has been changed from a settings page with success feedback to an onboarding page. This changes the user flow after authentication.

Ensure that:

  1. The onboarding page is prepared to handle users coming from an authentication flow
  2. Any functionality previously available on the settings page post-authentication is now available in the onboarding flow
  3. Users have a clear path to navigate back to settings if needed

You might want to consider adding a query parameter like ?auth_success=true to inform the onboarding page about the successful authentication.

apps/mail/app/(routes)/mail/layout.tsx (1)

9-9: Padding adjustments in the layout wrapper

The padding has been changed from having uniform padding on all sides (md:p-3) to only having padding on the top, bottom, and right sides (md:py-3 md:pr-3). This removes the left padding, which could affect how content aligns with the sidebar in medium and larger screens.

apps/mail/app/(routes)/settings/connections/page.tsx (2)

21-21: New icon import added

The Plus icon has been imported from lucide-react to support the new Add Connection button design.


153-165: Great UI enhancement for Add Connection button

The new button design with expand-on-hover effect creates a cleaner interface by default while still providing clear labeling when users interact with it. The implementation using group hover states and transitions is well-crafted.

The transition animation is smooth and intuitive. The overflow handling and absolute positioning ensure the layout doesn't shift during the animation.

apps/mail/components/ui/dialog.tsx (2)

23-23: Enhanced dialog overlay with blur effect

Adding backdrop-blur-sm to the dialog overlay creates a more modern, depth-enhancing visual effect that helps focus attention on the dialog content.


40-40: Updated dialog styling for better theming and rounded corners

The changes to the dialog content include:

  1. Replacing bg-background with bg-offsetLight dark:bg-offsetDark for better theme support
  2. Changing from sm:rounded-2xl to rounded-lg for a more consistent border radius

These updates improve the dialog's appearance across different themes and screen sizes.

package.json (2)

45-45:

Details

❌ Incorrect review comment

Missing animation dependencies in package.json

According to the AI summary, the PR should also include framer-motion and react-use-measure dependencies, but they don't appear in this diff section. Make sure these dependencies are properly added since they appear to be needed for animations implemented in the code.


🏁 Script executed:

#!/bin/bash
# Check if the dependencies are defined elsewhere or in another package.json
grep -r "framer-motion\|react-use-measure" --include="package.json" .

Length of output: 187


Animation dependencies already integrated

The framer-motion and react-use-measure dependencies are correctly added in the apps/mail/package.json file. The diff in the root package.json only showing the update for "@vercel/analytics": "1.5.0" is expected, as these animation libraries are intentionally managed in the mail app’s package configuration. Please disregard the request for adding these dependencies to the root package.json.

Likely an incorrect or invalid review comment.


41-44:

Details

❓ Verification inconclusive

Added Tiptap rich text editor dependencies

The addition of Tiptap packages suggests implementation of rich text editing features. The chosen versions are aligned, which is good practice.


🌐 Web query:

Are there any known issues with Tiptap 2.11.5 that should be considered?

💡 Result:

Tiptap 2.11.5 has several known issues that developers should consider, particularly around specific extensions and behavioral inconsistencies. While generally stable, these issues may impact implementation decisions:

1. Table Extension Validator Conflicts
Recent reports indicate problems with table rendering in strict validation environments, where basic tables get rejected by the validator despite correct syntax[3]. This appears environment-specific but could affect projects using strict content validation rules.

2. toggleMark Whitespace Behavior
The core package diverges from ProseMirror's expected behavior by applying marks to leading/trailing whitespace in text selections. This causes inconsistencies when toggling formatting (bold/italic/etc.) compared to native ProseMirror implementations[11].

3. Dependency Management Challenges
The React implementation (@tiptap/react 2.11.5) shows:

  • 2 outdated dependencies
  • 11 total dependencies
    While no critical vulnerabilities are reported[12][13], outdated dependencies could lead to compatibility issues in complex projects[1][6].

4. Frequent Versioning Considerations
Though not exclusive to 2.11.5, historical patterns show rapid updates sometimes cause peer dependency warnings during upgrades[6]. Developers should implement strict version pinning for critical production environments.

For most implementations, these issues are manageable through workarounds like custom validation rules or mark handling logic. The active development status (28k+ GitHub stars, recent issues) suggests ongoing maintenance and responsiveness to reported problems[1][4].

Citations:


Attention: Tiptap 2.11.5 Known Issues & Testing Advisory

The addition of Tiptap rich text editor dependencies in package.json (lines 41–44) is noted, and aligning the versions is good practice. However, please be aware of a few known concerns with version 2.11.5:

  • Table Extension Validator: In environments with strict validation, there have been reports of valid tables being rejected.
  • toggleMark Whitespace Behavior: The handling of leading/trailing whitespace when toggling marks (e.g., bold/italic) may behave unexpectedly compared to ProseMirror’s native behavior.
  • Dependency Management: The @tiptap/react package includes a few outdated dependencies that might result in versioning warnings, even though no critical vulnerabilities are reported at this time.

It would be prudent to test these cases in your implementation and consider any necessary workarounds (such as custom table validators or mark handling adjustments) if your project relies on strict content validation or precise text formatting behavior.

apps/mail/components/ui/spinner.tsx (1)

1-41: Well-implemented spinner component with framer-motion animations!

The Spinner component is cleanly implemented with proper TypeScript types and default values for props. The animation configuration creates a smooth loading indicator with continuous rotation and path length/opacity transitions.

apps/mail/components/connection/add.tsx (2)

8-16: Good addition of onOpenChange prop for better dialog control

The onOpenChange prop enables parent components to control the dialog state, enhancing component reusability.


33-75: Excellent use of framer-motion for enhanced UI feedback

The implementation of animated transitions using framer-motion improves the user experience with smooth, staggered animations. The delay calculation based on index creates a pleasing visual effect.

apps/mail/app/globals.css (1)

192-202: Well-defined gradient animation keyframes

The gradient-flow keyframes create a smooth background animation effect with proper timing.

apps/mail/components/create/editor.tsx (3)

280-284: Good implementation of focusEditor function.

The focusEditor function is well-implemented, providing a clean way to focus the editor when needed.


286-296: Clarify the purpose of preventing Enter key propagation.

The event handler prevents Enter key propagation even without Shift key. Consider adding a comment explaining why this behavior is needed, or modify it to only prevent default for specific scenarios.

  onKeyDown={(e) => {
    // Prevent form submission on Enter key
    if (e.key === "Enter" && !e.shiftKey) {
      e.stopPropagation();
+     // Note: This prevents form submission but allows the editor to handle the Enter key
    }
  }}

Could you verify if this approach correctly prevents form submission while still allowing the editor to create new lines with Enter?


323-324: Good integration of MenuBar component.

The MenuBar component is well-integrated into the Editor through the slotBefore prop, providing a clean separation of concerns.

apps/mail/components/create/prosemirror.css (3)

2-6: Consistent styling updates to ProseMirror.

The padding and line-height changes help maintain a consistent appearance throughout the editor.


188-207: Good fix for list placeholder issues.

The newly added CSS rules effectively address the placeholder display issues in list items, ensuring a better user experience.


209-229: Well-considered spacing adjustments.

The spacing and line-height adjustments for list items and paragraphs create a more compact and readable layout while maintaining consistent indentation.

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

🧹 Nitpick comments (2)
apps/mail/components/create/editor.tsx (2)

93-134: Well-implemented MenuBar with link handling functionality.

The MenuBar component properly uses the Tiptap editor context and implements link management functionality. The pre-filling of URLs and URL formatting logic are well thought out.

However, the handleSaveLink function has an empty comment that could be removed.

  const handleSaveLink = () => {
-    // empty
    if (linkUrl === "") {
      editor.chain().focus().unsetLink().run();
    } else {

224-256: Well-implemented link dialog with good UX.

The link dialog provides a clear interface for adding and managing links. The dialog includes a descriptive header, input field with proper labeling, and action buttons.

Consider adding keyboard handling to allow users to submit the form by pressing Enter.

              <Input
                id="url"
                value={linkUrl}
                onChange={(e) => setLinkUrl(e.target.value)}
                placeholder="https://example.com"
+               onKeyDown={(e) => {
+                 if (e.key === 'Enter') {
+                   e.preventDefault();
+                   handleSaveLink();
+                 }
+               }}
              />
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 93a3d23 and 697d669.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (2)
  • apps/mail/components/create/editor.tsx (5 hunks)
  • apps/mail/package.json (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/mail/package.json
🔇 Additional comments (16)
apps/mail/components/create/editor.tsx (16)

3-15: Good addition of relevant icons for the editor toolbar.

The import of various icons from lucide-react provides necessary UI elements for the rich text editing features. The chosen icons appropriately represent their respective formatting actions.


25-32: Appropriate use of dialog components for the link functionality.

The import of Dialog components from the UI library provides a solid foundation for implementing the link addition feature.


36-36: Good update to the Tiptap import.

Adding the useCurrentEditor import from @tiptap/react is essential for accessing the editor instance within the MenuBar component.


41-43: Appropriate imports for the enhanced UI components.

The Button and Input components are correctly imported for use in the link dialog, and the Markdown import enables proper markdown support.


45-45: Required useState import added.

Adding the useState import is necessary for managing local state in the new MenuBar component.


47-47: Good setup of extensions with Markdown support.

The extensions array includes Markdown support, enhancing the editor's capabilities.


136-222: Well-structured formatting toolbar with appropriate UI feedback.

The toolbar is well-organized into logical groups (headings, text formatting, lists) with appropriate spacing and visual feedback for active states. The implementation correctly uses the editor API to apply formatting.


259-263: Clean function signature with proper defaults.

The Editor component has a clean function signature with appropriate defaults for the placeholder text.


274-274: Good addition of editor reference.

Adding a reference to the editor instance allows for programmatic control of the editor outside of Tiptap's internal mechanisms.


278-284: Well-implemented focus handling.

The focusEditor function properly checks for the existence of the editor reference before attempting to focus, preventing potential errors.


286-289: Good UX improvement with click-to-focus behavior.

Adding the click handler to focus the editor improves user experience by allowing clicks anywhere in the editor container to focus the editor.


291-291: Improved key handling for form submission prevention.

The updated condition properly prevents form submission only when Enter is pressed without the Shift key, allowing for line breaks with Shift+Enter.


318-320: Good editor instance storage for external access.

Storing the editor instance in the ref allows the focusEditor function and potentially other external functions to access and control the editor.


322-322: Appropriate placement of the MenuBar component.

Using the slotBefore prop to insert the MenuBar ensures it appears in the correct position above the editor content.


326-334: Improved key handling in EditorCommand.

The updated key handling prevents form submission when pressing Enter, Space, or Spacebar, ensuring that these keys work properly within the command context.


364-365: Good comment update reflecting the UI changes.

The comment accurately reflects that only the TextButtons component is being used, which clarifies the intention of the EditorMenu.

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

🧹 Nitpick comments (13)
apps/mail/components/ui/input.tsx (1)

6-9: Fix for controlled/uncontrolled input warning

Good improvement to prevent the React warning about switching between controlled and uncontrolled inputs. Consider also handling null values to make the solution more robust.

-    const inputValue = value === undefined ? "" : value;
+    const inputValue = value === undefined || value === null ? "" : value;

Also applies to: 17-17

apps/mail/app/(auth)/zero/signup/page.tsx (3)

12-16: Schema validation mismatch with UI labels

The validation schema refers to the email field as "Username" in the error message, but the UI labels it as "Email". This inconsistency could confuse users.

-  email: z.string().min(1, { message: "Username must be at least 1 character" }),
+  email: z.string().min(1, { message: "Email username must be at least 1 character" }),

112-116: Incorrect login prompt text

Since this is a signup page, the text should say "Already have an account?" instead of "Don't have an account?".

-                Don't have an account?{" "}
+                Already have an account?{" "}

91-94: Empty container in password field section

There's an empty div with flex layout that doesn't contain any content. This was likely intended for a "Forgot password" link or similar UI element.

Either remove the empty container or add the intended content:

-                  <div className="flex items-center justify-between">
-                    <FormLabel className="text-muted-foreground">Password</FormLabel>
-                   
-                  </div>
+                  <FormLabel className="text-muted-foreground">Password</FormLabel>
apps/mail/app/(auth)/zero/login/page.tsx (1)

62-86: Add password strength requirements and visual feedback.

The password field could benefit from additional feedback to users about password requirements.

Consider adding:

  1. Visual password strength indicator
  2. Clear requirements text
  3. Show/hide password toggle
<FormItem>
  <div className="flex items-center justify-between">
    <FormLabel className="text-muted-foreground">Password</FormLabel>
    <Link
      href="/forgot-password"
      className="text-muted-foreground text-xs hover:text-white"
    >
      Forgot your password?
    </Link>
  </div>
  <FormControl>
    <div className="relative">
      <Input
        type="password"
        placeholder="••••••••"
        {...field}
        className="bg-black text-white"
      />
+     <button
+       type="button"
+       onClick={() => {
+         const input = document.querySelector('input[name="password"]');
+         if (input) {
+           const newType = input.type === 'password' ? 'text' : 'password';
+           input.type = newType;
+         }
+       }}
+       className="absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground"
+     >
+       {field.value ? "Show" : "Hide"}
+     </button>
    </div>
  </FormControl>
+  <p className="text-xs text-muted-foreground mt-1">
+    Password must be at least 6 characters
+  </p>
</FormItem>
apps/mail/app/(auth)/login/early-access/page.tsx (4)

19-24: Enhance form validation.

The current schema validation is minimal. Consider enhancing it to improve user experience and security.

const formSchema = z.object({
-  name: z.string().min(1, { message: "Name must be at least 1 character" }),
-  email: z.string().min(1, { message: "Invalid email address" }),
-  earlyAccessEmail: z.string().min(1, { message: "Invalid early access email address" }),
-  password: z.string().min(6, { message: "Password must be at least 6 characters" }),
+  name: z.string().min(1, { message: "Name must be at least 1 character" })
+    .max(50, { message: "Name cannot exceed 50 characters" }),
+  email: z.string()
+    .min(1, { message: "Email cannot be empty" })
+    .max(30, { message: "Email cannot exceed 30 characters" })
+    .regex(/^[a-zA-Z0-9_.-]+$/, { message: "Email can only contain letters, numbers, periods, underscores, and hyphens" }),
+  earlyAccessEmail: z.string()
+    .email({ message: "Please enter a valid email address" }),
+  password: z.string()
+    .min(6, { message: "Password must be at least 6 characters" })
+    .regex(/[A-Z]/, { message: "Password must contain at least one uppercase letter" })
+    .regex(/[0-9]/, { message: "Password must contain at least one number" }),
});

149-161: Add explanation for "Early access email".

It's not immediately clear what the "Early access email" field is for. Add a description or tooltip to explain this field to users.

<FormItem>
  <FormLabel className="text-muted-foreground">Early access email</FormLabel>
+  <p className="text-xs text-muted-foreground mb-1">
+    The email address where you received your early access invitation.
+  </p>
  <FormControl>
    <Input
      placeholder="luke@example.com"
      {...field}
      className="bg-black text-sm text-white placeholder:text-sm"
    />
  </FormControl>
</FormItem>

238-246: Add email copying functionality.

In the success screen, it would be helpful to add a "Copy email" button to allow users to easily copy their new email address.

<div className="mb-8">
  <h1 className="mb-4 text-4xl font-bold text-white">
    Congratulations 🎉 Your email is now:
  </h1>

-  <p className="text-primary mb-2 text-2xl font-bold">{userEmail}</p>
+  <div className="flex items-center justify-center gap-2 mb-2">
+    <p className="text-primary text-2xl font-bold">{userEmail}</p>
+    <button
+      onClick={() => {
+        navigator.clipboard.writeText(userEmail);
+        toast.success("Email copied to clipboard!");
+      }}
+      className="text-muted-foreground hover:text-white"
+    >
+      <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+        <rect width="14" height="14" x="8" y="8" rx="2" ry="2" />
+        <path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" />
+      </svg>
+    </button>
+  </div>
  <p className="text-muted-foreground text-sm">Stay tuned for our beta release!</p>
</div>

63-95: Consider limiting confetti animation.

The current confetti animation implementation could potentially cause performance issues on low-end devices. Consider adding a check to limit or disable animations based on device performance.

// Trigger confetti when verified changes to true
useEffect(() => {
  if (verified) {
+    // Check if the device is potentially low-end
+    const isLowEndDevice = () => {
+      // Check if device is mobile
+      const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
+      // Check if browser supports the hardwareConcurrency API
+      const lowCPUCount = navigator.hardwareConcurrency && navigator.hardwareConcurrency < 4;
+      return isMobile || lowCPUCount;
+    };
+    
+    // Reduce particles or skip animation for low-end devices
+    if (isLowEndDevice()) {
+      toast.success("Email verified successfully!");
+      return;
+    }
+    
    const duration = 3 * 1000;
    const animationEnd = Date.now() + duration;

    const randomInRange = (min: number, max: number) => {
      return Math.random() * (max - min) + min;
    };

    const interval = setInterval(() => {
      const timeLeft = animationEnd - Date.now();

      if (timeLeft <= 0) {
        return clearInterval(interval);
      }

      const particleCount = 50 * (timeLeft / duration);

      // since particles fall down, start a bit higher than random
      confetti({
        particleCount,
        startVelocity: 30,
        spread: 360,
        origin: {
          x: randomInRange(0.1, 0.9),
          y: randomInRange(0, 0.2),
        },
      });
    }, 250);

    return () => clearInterval(interval);
  }
}, [verified]);
apps/mail/components/ui/input-otp.tsx (4)

33-59: Consider adding error state handling to InputOTPSlot.

The current implementation handles active state, but it might be beneficial to also support error states for validation feedback. This would make the component more robust for form validation scenarios.

 const InputOTPSlot = React.forwardRef<
   React.ElementRef<"div">,
-  React.ComponentPropsWithoutRef<"div"> & { index: number }
+  React.ComponentPropsWithoutRef<"div"> & { index: number; hasError?: boolean }
 >(({ index, className, ...props }, ref) => {
   const inputOTPContext = React.useContext(OTPInputContext)
   const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index]
+  const { hasError } = props;

   return (
     <div
       ref={ref}
       className={cn(
         "relative flex h-9 w-9 items-center justify-center border-y border-r border-input text-sm shadow-sm transition-all first:rounded-l-md first:border-l last:rounded-r-md",
         isActive && "z-10 ring-1 ring-ring",
+        hasError && "border-destructive ring-1 ring-destructive",
         className
       )}
       {...props}
     >

37-38: Add a safety check for OTPInputContext.

It's a good practice to add a safety check when using React context to handle cases where the component might be used outside of its intended context provider.

 const InputOTPSlot = React.forwardRef<
   React.ElementRef<"div">,
   React.ComponentPropsWithoutRef<"div"> & { index: number }
 >(({ index, className, ...props }, ref) => {
   const inputOTPContext = React.useContext(OTPInputContext)
+  if (!inputOTPContext) {
+    throw new Error("InputOTPSlot must be used within an InputOTP component")
+  }
   const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index]

61-68: Enhance accessibility for InputOTPSeparator.

Adding more detailed ARIA attributes would improve the accessibility of the separator for screen readers.

 const InputOTPSeparator = React.forwardRef<
   React.ElementRef<"div">,
   React.ComponentPropsWithoutRef<"div">
 >(({ ...props }, ref) => (
-  <div ref={ref} role="separator" {...props}>
+  <div ref={ref} role="separator" aria-hidden="true" {...props}>
     <Minus />
   </div>
 ))

9-23: Add an example JSDoc comment for component usage.

Documentation would help other developers understand how to use this component correctly.

+/**
+ * InputOTP - A component for One-Time Password input fields
+ * 
+ * @example
+ * <InputOTP maxLength={6}>
+ *   <InputOTPGroup>
+ *     <InputOTPSlot index={0} />
+ *     <InputOTPSlot index={1} />
+ *     <InputOTPSeparator />
+ *     <InputOTPSlot index={2} />
+ *     <InputOTPSlot index={3} />
+ *   </InputOTPGroup>
+ * </InputOTP>
+ */
 const InputOTP = React.forwardRef<
   React.ElementRef<typeof OTPInput>,
   React.ComponentPropsWithoutRef<typeof OTPInput>
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 697d669 and fa1c24e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • apps/mail/app/(auth)/login/early-access/page.tsx (1 hunks)
  • apps/mail/app/(auth)/login/page.tsx (2 hunks)
  • apps/mail/app/(auth)/signup/page.tsx (0 hunks)
  • apps/mail/app/(auth)/signup/verify/page.tsx (0 hunks)
  • apps/mail/app/(auth)/zero/login/page.tsx (1 hunks)
  • apps/mail/app/(auth)/zero/signup/page.tsx (1 hunks)
  • apps/mail/components/home/navbar.tsx (4 hunks)
  • apps/mail/components/ui/input-otp.tsx (1 hunks)
  • apps/mail/components/ui/input.tsx (1 hunks)
  • apps/mail/tailwind.config.ts (2 hunks)
  • package.json (1 hunks)
💤 Files with no reviewable changes (2)
  • apps/mail/app/(auth)/signup/page.tsx
  • apps/mail/app/(auth)/signup/verify/page.tsx
🔇 Additional comments (11)
apps/mail/components/home/navbar.tsx (3)

25-34: UI adjustments look good - more compact layout

The navbar layout has been updated with reduced padding (from px-7/lg:px-20 to px-3/lg:px-4) and smaller logo size (from h-9/w-9 to h-6/w-6), creating a more compact and modern design.


39-44: Class reorganization preserves functionality

The reorganization of classes in both the Menu component and SheetContent maintain the same behavior while improving code readability.


64-69: Improved Button formatting

The Button component has been formatted with better readability by putting the asChild prop on a separate line, which is a good practice for maintaining clean code.

apps/mail/tailwind.config.ts (1)

94-97: Well-implemented caret blinking animation

The new "caret-blink" animation is properly defined with appropriate opacity transitions and timing. This will create a natural blinking effect that improves user experience when used with input elements.

Also applies to: 131-131

apps/mail/components/ui/input.tsx (1)

14-14: Smooth transition effect added

Adding transition-shadow with duration and easing improves the user experience by making focus state changes appear smoother.

apps/mail/app/(auth)/zero/signup/page.tsx (1)

73-80: Well-implemented email input with domain suffix

The input field with the "@0.email" suffix is well-implemented, providing clear visual feedback to users about the domain they're signing up with.

package.json (1)

41-46:

Details

✅ Verification successful

Ensure Tiptap and OTP dependencies are compatible with your project.

The added dependencies suggest the implementation of rich text editing (Tiptap) and OTP input functionality in the application. The version constraints are mixed between exact versions (2.11.5) and compatible versions (^).


🏁 Script executed:

#!/bin/bash
# Check npm for compatibility issues and recent vulnerabilities in the added packages

echo "Checking for latest versions of added packages:"
npm view @tiptap/extension-link version
npm view @tiptap/pm version
npm view @tiptap/react version
npm view @tiptap/starter-kit version
npm view input-otp version

echo -e "\nChecking for any known vulnerabilities:"
npm audit --json @tiptap/extension-link@^2.11.5 @tiptap/pm@2.11.5 @tiptap/react@2.11.5 @tiptap/starter-kit@^2.11.5 input-otp@^1.4.2 2>/dev/null | jq '.vulnerabilities'

Length of output: 573


Dependencies and Vulnerability Check Confirmed

The executed verification confirms that the Tiptap and OTP dependencies are correctly set to version 2.11.5 and 1.4.2 respectively, with no reported vulnerabilities. The mix of exact and caret version specifiers does not cause any compatibility issues as the resolved versions are consistent.

apps/mail/app/(auth)/zero/login/page.tsx (2)

43-60: LGTM: Form structure and validation well implemented.

The form structure is well implemented with proper validation and field control using react-hook-form and zod. The form layout is clean and accessible with appropriate labels and controls.


92-98: LGTM: Clean signup link implementation.

The signup navigation link is well-implemented and properly styled.

apps/mail/app/(auth)/login/page.tsx (1)

6-6:

Details

✅ Verification successful

Ensure Navbar component is properly exported from its module.

You've added the Navbar import, but make sure the component is being exported correctly from its module.


🏁 Script executed:

#!/bin/bash
# Check if Navbar is properly exported from the module
echo "Checking Navbar component exports:"
cat $(fd --type file --full-path "components/home/navbar.tsx")

Length of output: 4192


Navbar export verified – no changes necessary.

The verification confirms that the Navbar component is correctly exported as a default export from apps/mail/components/home/navbar.tsx, matching its import in the login page.

apps/mail/components/ui/input-otp.tsx (1)

1-71: Well-structured OTP input components with good TypeScript type definitions.

This looks like a well-implemented set of OTP input components that follow React best practices. The components are properly typed and use ref forwarding correctly. Good job on using Context from the input-otp package and adding proper displayNames for better debugging.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (7)
apps/mail/app/(auth)/zero/signup/page.tsx (2)

12-16: Mismatch between field name and validation message.
Your form schema uses email: z.string().min(1, ...) but the error message states "Username must be at least 1 character." Consider updating the label or leveraging a more precise email validation approach if you truly want an email field.

-  email: z.string().min(1, { message: "Username must be at least 1 character" }),
+  email: z.string().min(1, { message: "Email must be at least 1 character" }),

123-139: Review absolute footer positioning.
Using position: absolute may cause overlap issues on smaller viewports and cause the footer to appear above the bottom of the screen. Consider a relative or sticky footer approach instead.

apps/mail/app/(auth)/login/login-client.tsx (3)

59-98: Use optional chaining to improve code readability

The session check on line 99 could be simplified using optional chaining.

-  if (isPending || (session && session.connectionId)) return null;
+  if (isPending || session?.connectionId) return null;

111-127: Consider using a more specific type than any

In the handleProviderClick function, you're using provider.id as any when calling signIn.social(). Consider defining a proper type for this instead of using any to maintain type safety.


315-330: Consider adding version information to the footer

The footer currently includes links to Terms of Service and Privacy Policy. Consider adding version information or a link to the project repository to help with support and transparency.

apps/mail/lib/auth-providers.ts (2)

1-16: Consider using a more specific type for the config property

The config property in the ProviderConfig interface is typed as any. Consider defining a more specific interface for each provider's configuration to improve type safety.

export interface ProviderConfig {
  id: string;
  name: string;
  requiredEnvVars: string[];
  envVarInfo?: EnvVarInfo[];
-  config: any;
+  config: {
+    clientId?: string;
+    clientSecret?: string;
+    prompt?: string;
+    accessType?: string;
+    scope?: string[];
+    [key: string]: any;
+  };
  required?: boolean;
  isCustom?: boolean;
  customRedirectPath?: string;
}

75-77: Inconsistent null handling between providers

The GitHub configuration doesn't use non-null assertions, unlike the Google configuration. Consider standardizing the approach for all providers.

  config: {
-    clientId: process.env.GITHUB_CLIENT_ID,
-    clientSecret: process.env.GITHUB_CLIENT_SECRET,
+    clientId: process.env.GITHUB_CLIENT_ID || '',
+    clientSecret: process.env.GITHUB_CLIENT_SECRET || '',
  },
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between fa1c24e and 98a78c5.

📒 Files selected for processing (6)
  • apps/mail/app/(auth)/login/login-client.tsx (1 hunks)
  • apps/mail/app/(auth)/login/page.tsx (1 hunks)
  • apps/mail/app/(auth)/zero/login/page.tsx (1 hunks)
  • apps/mail/app/(auth)/zero/signup/page.tsx (1 hunks)
  • apps/mail/lib/auth-providers.ts (1 hunks)
  • apps/mail/lib/auth.ts (2 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
apps/mail/app/(auth)/login/login-client.tsx

[error] 99-99: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (17)
apps/mail/app/(auth)/zero/signup/page.tsx (3)

1-2: Good usage of client directive.
No issues found; everything looks standard for a Next.js Client Component.


27-37: No actual signup logic implemented.
The onSubmit function only displays a toast message and doesn't perform real account creation or authentication. This is a known issue from previous reviews.


39-120: Form structure looks solid.
The usage of react-hook-form and zod is consistent and well-structured. Labeling and placeholders are intuitive. Good job on providing descriptive placeholders.

apps/mail/lib/auth.ts (1)

9-9: Modular approach for social providers.
Extracting social provider configurations into getSocialProviders() improves maintainability and reduces clutter in this file. Ensure that getSocialProviders() gracefully handles missing or invalid provider configurations.

Also applies to: 30-30

apps/mail/app/(auth)/zero/login/page.tsx (3)

1-16: Well-structured imports and schema definition.
Everything looks neat and consistent with the usage of react-hook-form and zod.


26-33: Authentication logic is missing.
Similar to SignupZero, the code only shows a toast message instead of actually performing the login. Please integrate the real authentication flow or clarify if it's still a work in progress.


35-121: UI design is clear.
The form fields, placeholders, and styling are coherent with the rest of the app. Good use of Link for password resets and sign-up navigation.

apps/mail/app/(auth)/login/page.tsx (1)

1-46: Dynamic provider setup is well-structured.
Combining built-in providers and custom providers into allProviders yields a flexible approach. The environment variable checks are thorough.

apps/mail/app/(auth)/login/login-client.tsx (5)

36-57: Good implementation of the provider icon mapping function

The getProviderIcon function is well-structured with a clear switch statement and proper fallback handling for unknown providers.


129-136: Well-implemented sorting logic for providers

The sorting logic effectively prioritizes the "Zero" provider first, followed by required providers before non-required ones. This provides a good user experience by highlighting the most important options.


156-270: Good user experience for configuration assistance

The detailed configuration UI for development environments is well-implemented, with:

  • Clear visual indicators for missing configuration
  • Collapsible sections for each provider
  • Animated transitions for better UX
  • Sample environment variable values
  • Link to documentation

This will significantly help developers during setup.


272-294: Clear error handling for production environments

The simplified error message for production environments appropriately hides implementation details while still informing users about the authentication service unavailability.


296-311:

Details

✅ Verification successful

Verify the callbackURL for authentication

The callbackURL is hardcoded to "/mail" in the handleProviderClick function. Ensure this is the correct redirect path after authentication for all providers.


🏁 Script executed:

#!/bin/bash
# Search for other callbackURL references in the codebase
rg "callbackURL" --type ts --type tsx

Length of output: 65


Attention: Verify Hardcoded callbackURL Usage
The previous search failed due to the TSX file type not being recognized. Please re-run the above script to ensure that the hardcoded callbackURL (set to "/mail" in the handleProviderClick function) is the intended redirect path across all providers.


🏁 Script executed:

#!/bin/bash
# Re-run the search for "callbackURL" in TS and TSX files 
rg --type-add 'tsx:*.tsx' --type tsx "callbackURL"

Length of output: 126


Callback URL Verification
The search confirmed that the only usage of callbackURL is in apps/mail/app/(auth)/login/login-client.tsx, where it is hardcoded to "/mail". If this is indeed the intended redirect path for all providers post-authentication, then the implementation is consistent. However, if different providers require unique callback paths, consider parameterizing this value.

apps/mail/lib/auth-providers.ts (4)

18-27: Good implementation of custom provider for Zero

The custom provider for Zero is well-structured with appropriate properties. The empty arrays and objects for requiredEnvVars and config make sense as this is handled by a custom redirect.


81-92: Well-implemented provider validation logic

The isProviderEnabled function correctly checks for required environment variables and logs appropriate error messages. The special handling for custom providers is also a good addition.


94-106: Good error handling for required providers

The getSocialProviders function properly throws an error when required providers are not configured, which will help catch configuration issues early.


69-72:

Details

❓ Verification inconclusive

Inconsistent redirect URI paths between providers

The default redirect URI for GitHub points to /api/auth/callback/github, while Google uses /api/v1/mail/auth/google/callback. Ensure this inconsistency is intentional and properly documented.


🏁 Script executed:

#!/bin/bash
# Check for callback URI patterns in the codebase
rg "callback" --type ts --type tsx | grep -i "uri\|url"

Length of output: 83


Verify Inconsistent Redirect URI Paths for Providers

The GitHub provider’s default redirect URI in apps/mail/lib/auth-providers.ts (line 69-72) is set to
http://localhost:3000/api/auth/callback/github, while the Google provider (configured elsewhere) appears to use
/api/v1/mail/auth/google/callback. Please confirm whether this discrepancy is intentional. If it is, ensure the rationale is clearly documented.

Note: The initial automated search using

rg "callback" --type ts --type tsx | grep -i "uri\|url"

resulted in an error regarding an unrecognized file type ("tsx"). Consider re-running the search with a corrected command such as:

#!/bin/bash
# Search for callback URI patterns in both .ts and .tsx files using glob filters
rg "callback" -g "*.ts" -g "*.tsx" | grep -i "uri\|url"

or perform a manual verification to ensure no unintended mismatches exist.

  • Confirm specifically whether the different callback URI paths are by design.
  • Update documentation or code comments accordingly if the divergence is intentional.

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

♻️ Duplicate comments (3)
apps/mail/app/(auth)/login/early-access/page.tsx (3)

111-122: ⚠️ Potential issue

Implement actual registration logic.

The onSubmit function currently only shows a toast and updates the UI state without actually registering the user. Implement the actual API call to register the user.

function onSubmit(values: z.infer<typeof formSchema>) {
  // Append the @0.email suffix to the username
  const fullEmail = `${values.email}@0.email`;
  setUserEmail(fullEmail);

+  // Show loading toast
+  const toastId = toast.loading("Creating your account...");
+  
+  // Implement actual registration API call
+  try {
+    // Replace with actual API call
+    // await registerUser({
+    //   name: values.name,
+    //   email: fullEmail,
+    //   earlyAccessEmail: values.earlyAccessEmail,
+    //   password: values.password
+    // });
+    
+    toast.success("Signup successful, please verify your email", { id: toastId });
+    
+    // Show verification screen
+    setShowVerification(true);
+  } catch (error) {
+    toast.error("Signup failed", { 
+      id: toastId,
+      description: error instanceof Error ? error.message : "Please try again"
+    });
+  }
-  // Use the correct sonner toast API
-  toast.success("Signup successful, please verify your email");
-
-  // Show verification screen
-  setShowVerification(true);
  // URL will be updated in the useEffect
}

399-404: ⚠️ Potential issue

Implement actual "Resend" functionality.

The "Resend" button currently only shows a toast message but doesn't actually resend the verification code. Implement the actual resend functionality.

<button
-  onClick={() => toast.info("New code sent!")}
+  onClick={() => {
+    const toastId = toast.loading("Sending new code...");
+    
+    // Implement actual resend API call
+    try {
+      // Replace with actual API call
+      // await resendVerificationCode({
+      //   email: userEmail
+      // });
+      
+      toast.success("New verification code sent!", { id: toastId });
+    } catch (error) {
+      toast.error("Failed to send new code", { 
+        id: toastId,
+        description: error instanceof Error ? error.message : "Please try again"
+      });
+    }
+  }}
  className="text-primary hover:underline"
>
  Resend
</button>

193-205: ⚠️ Potential issue

Implement actual verification logic and handle the redirect properly.

The handleVerify function currently doesn't actually verify the code against any backend. Also, the immediate redirect to /mail might prevent users from seeing the success message and confetti animation.

function handleVerify() {
  if (verificationCode.length === 6) {
-    setVerified(true);
-    setVerificationError(false);
-    toast.success("Email verified successfully!");
-    // Redirect to /mail after verification
-    router.push("/mail");
+    // Show loading toast
+    const toastId = toast.loading("Verifying email...");
+
+    // Implement actual verification API call
+    try {
+      // Replace with actual API call
+      // await verifyEmail({
+      //   email: userEmail,
+      //   code: verificationCode
+      // });
+      
+      toast.success("Email verified successfully!", { id: toastId });
+      setVerified(true);
+      setVerificationError(false);
+      
+      // Redirect after a delay to show the success animation
+      setTimeout(() => {
+        router.push("/mail");
+      }, 3000); // 3 seconds should be enough to see the confetti
+    } catch (error) {
+      setVerificationError(true);
+      toast.error("Verification failed", { 
+        id: toastId,
+        description: error instanceof Error ? error.message : "Please try again"
+      });
+    }
    // URL will be updated in the useEffect
  } else {
    setVerificationError(true);
    toast.error("Please enter a valid 6-digit code");
  }
}
🧹 Nitpick comments (6)
apps/mail/components/ui/input.tsx (1)

17-19: Consider adding accessibility attributes for error states.

The visual error state with transition effects is a good UX improvement, but it would be even better with proper accessibility support.

Consider adding the aria-invalid attribute when in error state to improve screen reader support:

 <input
   type={type}
   className={cn(
     "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-[#454545] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm transition-shadow duration-300 ease-in-out",
     error && "ring-2 ring-red-500 ring-offset-1",
     className,
   )}
   value={inputValue}
+  aria-invalid={error}
   ref={ref}
   {...props}
 />
apps/mail/app/(auth)/login/early-access/page.tsx (5)

20-28: Good validation schema, but password requirements should be stronger.

The form validation schema is well-structured with clear error messages. However, the password validation only requires 6 characters minimum, which is relatively weak by modern security standards.

Consider strengthening password requirements:

 password: z.string().min(6, { message: "Password must be at least 6 characters" }),
+  // Add more password requirements
+  password: z
+    .string()
+    .min(8, { message: "Password must be at least 8 characters" })
+    .refine(
+      (password) => /[A-Z]/.test(password) && /[a-z]/.test(password) && /[0-9]/.test(password),
+      { message: "Password must include uppercase, lowercase, and numbers" }
+    ),

125-191: Refactor error handling for better maintainability.

The current error handling approach with a large error message mapping array is verbose and could be difficult to maintain. Consider refactoring to a more concise approach.

- // Handle form errors with toast notifications
- const onError = (errors: any) => {
-   // Define error messages mapping
-   const errorMessageMap = [
-     // Email errors
-     {
-       field: "email",
-       pattern: "@ symbol",
-       message: "Zero email has to have only letters (a-z), numbers (0-9), and periods (.).",
-     },
-     {
-       field: "email",
-       pattern: "required",
-       message: "Username is required",
-     },
-     // ... many more mappings
-   ];
-
-   // Find the first matching error and show toast
-   for (const [field, fieldError] of Object.entries(errors)) {
-     const errorMessage = (fieldError as { message?: string })?.message || "";
-
-     // Find matching error pattern
-     const matchedError = errorMessageMap.find(
-       (mapping) =>
-         mapping.field === field &&
-         (mapping.pattern === "" || errorMessage.includes(mapping.pattern)),
-     );
-
-     if (matchedError) {
-       toast.error(matchedError.message);
-       return;
-     }
-   }
-
-   // Fallback for any other errors
-   toast.error("Please fix the form errors");
- };

+ // Handle form errors with toast notifications
+ const onError = (errors: any) => {
+   // Get the first error message and display it
+   const firstError = Object.values(errors)[0] as { message?: string } | undefined;
+   if (firstError?.message) {
+     toast.error(firstError.message);
+   } else {
+     toast.error("Please fix the form errors");
+   }
+ };

330-387: Improve code modularity and reduce duplication in OTP input slots.

The OTP input section has a lot of repeated code for the InputOTPSlot components. Consider extracting this to a helper function or component to reduce duplication.

+ // Create a helper component for OTP slots
+ const OTPSlot = ({ index, hasError }: { index: number; hasError: boolean }) => (
+   <InputOTPSlot
+     index={index}
+     className={cn(
+       "border-input h-12 w-12 bg-black text-lg text-white",
+       hasError && "ring-2 ring-red-500 ring-offset-1",
+     )}
+   />
+ );

<InputOTP
  maxLength={6}
  value={verificationCode}
  onChange={(value) => {
    setVerificationCode(value);
    // Clear error when user starts typing again
    if (verificationError) {
      setVerificationError(false);
    }
  }}
  className="justify-center gap-2"
>
  <InputOTPGroup>
-   <InputOTPSlot
-     index={0}
-     className={cn(
-       "border-input h-12 w-12 bg-black text-lg text-white",
-       verificationError && "ring-2 ring-red-500 ring-offset-1",
-     )}
-   />
-   <InputOTPSlot
-     index={1}
-     className={cn(
-       "border-input h-12 w-12 bg-black text-lg text-white",
-       verificationError && "ring-2 ring-red-500 ring-offset-1",
-     )}
-   />
-   ... repeat for other slots
+   {[0, 1, 2, 3, 4, 5].map((index) => (
+     <OTPSlot key={index} index={index} hasError={verificationError} />
+   ))}
  </InputOTPGroup>
</InputOTP>

273-276: Improve field change handling to include validation.

The current field change handler for email bypasses validation. Consider updating it to properly validate input while typing.

onChange={(e) => {
  // Just update the field value without showing toast errors
  const value = e.target.value;
-  field.onChange(value);
+  // Prevent @ symbol in username
+  if (!value.includes('@')) {
+    field.onChange(value);
+  }
}}

416-426: Improve loading state feedback.

The current loading fallback only shows "Loading..." text. Consider implementing a more user-friendly loading state with a spinner or progress indicator.

<Suspense
  fallback={
    <div className="flex h-full min-h-screen w-full items-center justify-center bg-black">
-     <div className="text-white">Loading...</div>
+     <div className="flex flex-col items-center gap-4">
+       <div className="h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent"></div>
+       <div className="text-white">Loading...</div>
+     </div>
    </div>
  }
>
  <EarlyAccessContent />
</Suspense>
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 98a78c5 and 69b9c31.

📒 Files selected for processing (2)
  • apps/mail/app/(auth)/login/early-access/page.tsx (1 hunks)
  • apps/mail/components/ui/input.tsx (1 hunks)
🔇 Additional comments (5)
apps/mail/components/ui/input.tsx (3)

5-7: Well-structured type definition with error handling support.

Adding a dedicated interface for input props with error handling capability is a good TypeScript practice. This makes the component API more explicit and enables proper type checking.


9-13: Good solution for controlled component consistency.

The implementation to prevent switching between controlled and uncontrolled states is excellent. By ensuring the value is always defined, you avoid the common React warning about components switching between these states.


22-22: Properly implemented controlled component pattern.

Using the derived inputValue instead of directly using value ensures the component remains consistently controlled, which is the recommended React pattern.

apps/mail/app/(auth)/login/early-access/page.tsx (2)

69-101: Good use of useEffect for confetti animation and cleanup.

The confetti animation implementation with proper interval cleanup in the effect return function is well done. This prevents memory leaks when the component unmounts.


47-66: Good URL management through URL parameters.

The use of URLSearchParams to manage application state in the URL is excellent. It provides a shareable URL and maintains state across page reloads.

@nizzyabi nizzyabi merged commit 3a8739d into staging Mar 10, 2025
4 checks passed
@nizzyabi nizzyabi deleted the create-email-updates branch March 10, 2025 21:56
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