-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Update shadcn/ui components to latest version and fix dialog backdrop blur #2014
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: staging
Are you sure you want to change the base?
Update shadcn/ui components to latest version and fix dialog backdrop blur #2014
Conversation
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughRefactors UI to migrate from the monolithic radix-ui import to scoped @radix-ui/* packages, overhauls Dialog and Sheet APIs, simplifies Button/Input/Separator/Skeleton, updates ScrollArea signature, tweaks Command components, removes DialogContent’s showOverlay usage across call sites, adjusts global CSS variables/base, and updates dependencies including Radix packages and zod pin. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant App
participant Dialog as Dialog (Radix)
participant Overlay as Overlay (always-on)
participant Content as DialogContent
User->>App: Click DialogTrigger
App->>Dialog: open=true
Dialog->>Overlay: Render fixed overlay
Dialog->>Content: Render content (showCloseButton?)
alt Close via button
User->>Content: Click Close (X)
Content->>Dialog: onClose()
Dialog-->>Overlay: Unmount
Dialog-->>Content: Unmount
else Click outside / Esc
User->>Dialog: Dismiss
Dialog-->>Overlay: Unmount
Dialog-->>Content: Unmount
end
sequenceDiagram
autonumber
actor User
participant App
participant Sheet as Sheet Root
participant SOverlay as SheetOverlay
participant SContent as SheetContent (side=top|right|bottom|left)
User->>App: Click SheetTrigger
App->>Sheet: open=true
Sheet->>SOverlay: Render backdrop
Sheet->>SContent: Slide-in from side
User->>SContent: Interact
User->>SContent: Click Close (X) / overlay / Esc
SContent->>Sheet: onClose()
Sheet-->>SOverlay: Unmount
Sheet-->>SContent: Slide-out & unmount
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
✨ Finishing Touches🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
…nts and update dialog component
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 46
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (42)
apps/mail/components/ui/alert.tsx (4)
30-38: Fix DOM type mismatch for AlertTitle.Ref says paragraph, element is h5. In strict mode, this will bite. Make the ref an HTMLHeadingElement.
Apply this diff:
-const AlertTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>( +const AlertTitle = React.forwardRef<HTMLHeadingElement, React.HTMLAttributes<HTMLHeadingElement>>(
41-46: Fix DOM type mismatch for AlertDescription.Ref/props typed as paragraph, but you render a div. Correct the element types.
Apply this diff:
-const AlertDescription = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes<HTMLParagraphElement> ->(({ className, ...props }, ref) => ( - <div ref={ref} className={cn('text-sm [&_p]:leading-relaxed', className)} {...props} /> +const AlertDescription = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes<HTMLDivElement> +>(({ className, ...props }, ref) => ( + <div ref={ref} className={cn('text-sm [&_p]:leading-relaxed', className)} {...props} />
45-45: Optional: adopt modern descendant variant
Let’s future-proof this component by swapping[&_p]:leading-relaxedfor**:p:leading-relaxedin apps/mail/components/ui/alert.tsx:45. We’ve spotted numerous other[&_*]selectors acrossapps/mail—consider a global migration once you enable the new Tailwind variants.
30-46: Align forwardRef generics with rendered tags.
- apps/mail/components/ui/alert.tsx
- AlertTitle: change the ref generic from HTMLParagraphElement to HTMLHeadingElement.
- AlertDescription: change the ref generic from HTMLParagraphElement to HTMLDivElement and update props to React.HTMLAttributes (or swap the
<div>for a<p>).- Add a repo-wide AST-based check (e.g. ast-grep or lint rule) to enforce that
forwardRef<T, …>matches the actual JSX tag and prevent future mismatches.apps/mail/components/ui/resizable.tsx (4)
3-7: Use type-only React imports; don’t rely on the globalReactnamespaceStrict TS setups can choke on
React.ComponentPropswithout an explicit import. Import the type and simplify references.'use client'; +import type { ComponentProps } from 'react'; import * as ResizablePrimitive from 'react-resizable-panels'; import { GripVertical } from 'lucide-react'; import { cn } from '@/lib/utils'; -}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => ( +}: ComponentProps<typeof ResizablePrimitive.PanelGroup>) => ( -}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & { +}: ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & { withHandle?: boolean; }) => (Also applies to: 8-12, 24-26
12-15: Wrap long Tailwind strings to meet 100-char limitBreak the long class into multiple cn segments for readability and to honor repo limits.
<ResizablePrimitive.PanelGroup - className={cn('flex h-full w-full data-[panel-group-direction=vertical]:flex-col', className)} + className={cn( + 'flex h-full w-full', + 'data-[panel-group-direction=vertical]:flex-col', + className, + )} {...props} />
28-31: Tailwind rename + readability: outline-none → outline-hidden; split the mega stringUpdate deprecated utility per guidelines and split to keep lines sane.
<ResizablePrimitive.PanelResizeHandle - className={cn( - 'bg-border focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90', - className, - )} + className={cn( + 'bg-border relative flex w-px items-center justify-center', + 'focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1', + 'after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2', + 'data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full', + 'data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full', + 'data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0', + '[&[data-panel-group-direction=vertical]>div]:rotate-90', + className, + )} {...props} >
35-37: Tailwind rename: rounded-sm → rounded-xsMatches the repo’s utility renames.
- <div className="bg-border z-10 flex h-4 w-3 items-center justify-center rounded-sm border"> + <div className="bg-border z-10 flex h-4 w-3 items-center justify-center rounded-xs border"> <GripVertical className="h-2.5 w-2.5" /> </div>apps/mail/components/responsive-modal.tsx (2)
29-35: Fix VisuallyHidden usage — named import shouldn’t be dot-chained.You imported
{ VisuallyHidden }, but you’re renderingVisuallyHidden.VisuallyHidden. That will explode at runtime. Render the component directly (or switch to namespace import and use.Root). Let’s keep it simple.- <VisuallyHidden.VisuallyHidden> + <VisuallyHidden> <DialogHeader> <DialogTitle>Title</DialogTitle> <DialogDescription>Modal content</DialogDescription> </DialogHeader> - </VisuallyHidden.VisuallyHidden> + </VisuallyHidden> ... - <VisuallyHidden.VisuallyHidden> + <VisuallyHidden> <DrawerHeader> <DrawerTitle>Title</DrawerTitle> </DrawerHeader> - </VisuallyHidden.VisuallyHidden> + </VisuallyHidden>Also applies to: 45-50
28-38: Move hidden DialogHeader into DialogContent
Aligns with Radix UI’s requirement thatDialogTitle/DialogDescriptionbe descendants ofDialogContentfor proper context-based a11y wiring. (radix-ui.com)apps/mail/components/ui/tooltip.tsx (3)
21-21: Outline variant currently renders no border width.
border-bordersets color only. Add a width so the outline actually appears.Apply:
- outline: 'border-border', + outline: 'border border-border',
49-69: Wrap Content in a Portal to avoid clipping and stacking-context gotchas.Without a Portal, tooltips can be cut off inside overflow/transform containers. Radix ships a Portal for this—use it.
Apply:
- <TooltipPrimitive.Content - ref={ref} - sideOffset={sideOffset} - className={cn(tooltipVariants({ variant }), className)} - {...props} - > + <TooltipPrimitive.Portal> + <TooltipPrimitive.Content + ref={ref} + sideOffset={sideOffset} + className={cn(tooltipVariants({ variant }), className)} + {...props} + > {variant === 'sidebar' && ( <svg width="6" height="10" viewBox="0 0 6 10" fill="none" xmlns="http://www.w3.org/2000/svg" className="absolute left-[-6px] top-1/2 -translate-y-1/2" > <path d="M6 0L0 5L6 10V0Z" className="fill-white/80 dark:fill-[#413F3E]" /> </svg> )} {props.children} - </TooltipPrimitive.Content> + </TooltipPrimitive.Content> + </TooltipPrimitive.Portal>
55-66: Make the arrow non-interactive to prevent hover flicker.The SVG can steal pointer events at the edge. Nuke them.
Apply:
- className="absolute left-[-6px] top-1/2 -translate-y-1/2" + className="pointer-events-none absolute left-[-6px] top-1/2 -translate-y-1/2"apps/mail/components/ui/toggle.tsx (1)
36-36: Minor robustness: don’t rely on cva merging className.Safer to pass
classNameviacnto avoid depending on cva’sclassNamepassthrough semantics.- className={cn(toggleVariants({ variant, size, className }))} + className={cn(toggleVariants({ variant, size }), className)}apps/mail/app/globals.css (1)
19-19: Switch to native @variant dark directive (apps/mail/app/globals.css:19)
Tailwind v4 natively supports dark mode via@variant dark, so replace the custom hack:-/* Custom variant for dark mode */ -@custom-variant dark (&:where(.dark, .dark *)); +/* Use Tailwind v4 dark mode variant */ +@variant dark;Then wrap your dark-mode rules in
@variant dark { … }as needed.apps/mail/components/ui/progress.tsx (1)
12-21: Forwardvalueto Root (a11y), clamp it, and prefertransition-transform.Right now
valueis stripped fromRoot, so ARIA reads it as indeterminate—bad UX. Also, clamp to [0,100] to avoid overshoot.transition-allis overkill; animate only transforms for perf.Apply:
<ProgressPrimitive.Root ref={ref} className={cn('bg-secondary relative h-4 w-full overflow-hidden rounded-full', className)} + value={value} {...props} > <ProgressPrimitive.Indicator - className="bg-primary h-full w-full flex-1 transition-all" - style={{ transform: `translateX(-${100 - (value || 0)}%)` }} + className="bg-primary h-full w-full flex-1 transition-transform" + style={{ + transform: `translateX(-${ + 100 - Math.max(0, Math.min(100, value ?? 0)) + }%)`, + }} />apps/mail/components/ui/radio-group.tsx (1)
25-27: Replace deprecated Tailwind utility and align base border token.Use
outline-hiddenper guidelines and avoid primary border for the unchecked state.- 'border-primary text-primary ring-offset-background focus-visible:ring-ring aspect-square h-4 w-4 rounded-full border focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50', + 'border-input data-[state=checked]:border-primary text-primary ring-offset-background focus-visible:ring-ring aspect-square h-4 w-4 rounded-full border focus:outline-hidden focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',apps/mail/components/connection/add.tsx (1)
119-119: Tailwind class likely invalid: 'size-6!'Tailwind’s important modifier is prefix ‘!’, not suffix. Use '!size-6' (or plain 'size-6') to avoid no-op class.
Apply this diff:
- <Icon className="size-6!" /> + <Icon className="!size-6" />apps/mail/components/ui/label.tsx (1)
15-18: Drop unused VariantProps to avoid API noise.labelVariants defines no variants, yet props expose VariantProps — dead weight.
Apply:
- React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & VariantProps<typeof labelVariants> + React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> >(({ className, ...props }, ref) => ( - <LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} /> + <LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} />If you intend to add variants, wire them through instead of removing.
apps/mail/components/ui/checkbox.tsx (1)
13-24: Tailwind v4 rename fixes: outline + rounding.Align with the renamed utilities to avoid subtle styling drift.
Apply:
<CheckboxPrimitive.Root ref={ref} className={cn( - 'border-primary ring-offset-background focus-visible:ring-ring data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground peer h-4 w-4 shrink-0 rounded-sm border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50', + 'border-primary ring-offset-background focus-visible:ring-ring data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground peer h-4 w-4 shrink-0 rounded-xs border focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50', className, )}apps/mail/components/ui/sidebar.tsx (6)
131-145: Icon size mismatch blows up the trigger button.Button is 28px; icon is h-12. That’s… suboptimal UI.
Apply:
- <Menu className="h-12" /> + <Menu className="size-4" />
291-305: Use outline-hidden (Tailwind v4 rename).Keep consistency with new utilities.
Apply:
- <Comp + <Comp ref={ref} data-sidebar="group-label" className={cn( - 'text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-none transition-[margin,opacity] duration-200 ease-in-out focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0', + 'text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-in-out focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0', 'group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0', className, )}
312-329: Same rename here: outline-hidden.Apply:
- className={cn( + className={cn( 'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-none transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0', + // outline-none -> outline-hidden + // (Tailwind v4)Better as a direct change:
- 'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-none transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0', + 'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
569-589: One more outline rename on sub-button.Apply:
- className={cn( + className={cn( 'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0', + // outline-none -> outline-hiddenDirect fix:
- '... rounded-md px-2 outline-none focus-visible:ring-2 ...', + '... rounded-md px-2 outline-hidden focus-visible:ring-2 ...',
111-116: shadow → shadow-sm (Tailwind v4 rename).Prevents silent style drift across themes.
Apply:
- className="group-data-[variant=floating]:border-sidebar-border bg-sidebar dark:bg-sidebar flex h-full w-full flex-col overflow-hidden duration-300 ease-in-out group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow" + className="group-data-[variant=floating]:border-sidebar-border bg-sidebar dark:bg-sidebar flex h-full w-full flex-col overflow-hidden duration-300 ease-in-out group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm"
1-617: Replace all remainingoutline-nonewithoutline-hidden
No legacySlot.Slotusages detected. However, numerousoutline-noneinstances remain across UI components (e.g., in calendar.tsx, dropdown-menu.tsx, textarea.tsx, sidebar.tsx, navigation-menu.tsx, etc.). Update them tofocus-visible:outline-hidden(or equivalent) to complete the migration.apps/mail/components/ui/toggle-group.tsx (1)
42-45: Prop precedence is inverted; item-level props should override context.Right now context wins, making per-item overrides impossible.
Apply:
- toggleVariants({ - variant: context.variant || variant, - size: context.size || size, - }), + toggleVariants({ + variant: variant ?? context.variant, + size: size ?? context.size, + }),apps/mail/components/ui/collapsible.tsx (1)
7-9: Bug: wrong Radix members (will break at runtime).In @radix-ui/react-collapsible the members are Trigger and Content, not CollapsibleTrigger/CollapsibleContent.
Apply:
-const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger; - -const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent; +const CollapsibleTrigger = CollapsiblePrimitive.Trigger; + +const CollapsibleContent = CollapsiblePrimitive.Content;Optional simplification (clearer and tree-shakeable):
export { Root as Collapsible, Trigger as CollapsibleTrigger, Content as CollapsibleContent, } from '@radix-ui/react-collapsible';apps/mail/components/ui/form.tsx (2)
108-114: Add aria-errormessage for robust a11y.
Makes error association explicit for AT. Minimal change, maximal clarity.<Slot ref={ref} id={formItemId} aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`} aria-invalid={!!error} + aria-errormessage={error ? formMessageId : undefined} {...props} />
141-156: Announce errors: add role/aria-live on message.
Make it obvious to screen readers. Accessibility at ludicrous speed.return ( <p ref={ref} id={formMessageId} - className={cn('text-destructive text-sm font-medium', className)} + className={cn('text-destructive text-sm font-medium', className)} + role={error ? 'alert' : undefined} + aria-live={error ? 'polite' : undefined} {...props} > {body} </p> );apps/mail/components/ui/accordion.tsx (2)
27-35: Drop transition-all on the trigger to avoid layout/paint churn.Only color and the child svg rotate. Prefer targeted transitions.
Apply:
- 'flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180', + 'flex flex-1 items-center justify-between py-4 font-medium hover:underline transition-colors [&[data-state=open]>svg]:rotate-180',
45-49: Avoid transition-all on content; honor reduced motion.You already have explicit keyframe animations; transition-all is redundant and can jank.
Apply:
- className="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm transition-all" + className="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down motion-reduce:!animate-none overflow-hidden text-sm"apps/mail/components/ui/scroll-area.tsx (1)
30-42: Add data-slot for consistency with the new slot-based systemSmall but useful for styling hooks.
- <ScrollAreaPrimitive.ScrollAreaScrollbar + <ScrollAreaPrimitive.ScrollAreaScrollbar + data-slot="scrollbar" @@ - <ScrollAreaPrimitive.ScrollAreaThumb className="bg-border relative flex-1 rounded-full" /> + <ScrollAreaPrimitive.ScrollAreaThumb + data-slot="scrollbar-thumb" + className="bg-border relative flex-1 rounded-full" + />apps/mail/components/context/label-sidebar-context.tsx (1)
56-60: Use onSelect instead of onClick on ContextMenuItem for reliable close semantics.Radix ContextMenu items fire
onSelectand close by default;onClickcan be less consistent whenasChildis used.- <ContextMenuItem - asChild - onClick={() => setDeleteDialogOpen(true)} + <ContextMenuItem + asChild + onSelect={() => setDeleteDialogOpen(true)} disabled={false} className="gap-2 text-sm" >apps/mail/components/create/template-button.tsx (1)
203-204: Tailwind class: use arbitrary value syntax for z-index.
z-99999isn’t a standard scale value. Preferz-[99999]to guarantee it compiles under the Tailwind plugin stack.- <DropdownMenuContent className="z-99999 w-60" align="start" sideOffset={6}> + <DropdownMenuContent className="z-[99999] w-60" align="start" sideOffset={6}> @@ - <DropdownMenuSubContent className="z-99999 w-60"> + <DropdownMenuSubContent className="z-[99999] w-60">Also applies to: 218-218
apps/mail/components/create/email-composer.tsx (3)
1008-1025: Fix invalid Tailwind class: use z-[99999], not z-99999.z-99999 isn’t a default utility; JIT won’t emit it. This can break layering with the new overlay.
- <DialogContent className="z-99999 sm:max-w-[425px]"> + <DialogContent className="z-[99999] sm:max-w-[425px]">
1028-1056: Same z-index issue here—apply the bracketed arbitrary value.Keep stacking consistent across both dialogs.
- <DialogContent className="z-99999 sm:max-w-[425px]"> + <DialogContent className="z-[99999] sm:max-w-[425px]">
1008-1056: Consider replacing giant z-index with a tokenized layer.Hardcoding 99999 is… suboptimal. Define a design-token or Tailwind theme layer (e.g., z-modal) so overlays stay deterministic across portals.
I can draft a Tailwind theme extension and refactor call-sites if you want.
apps/mail/components/ui/context-menu.tsx (1)
83-87: Replace outline-none with outline-hidden.Consistency matters.
- 'focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50', + 'focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden data-[disabled]:pointer-events-none data-[disabled]:opacity-50',apps/mail/components/ui/dropdown-menu.tsx (1)
158-158: Unify separator color with ContextMenu (bg-border).Minor consistency polish across menus.
- className={cn('bg-muted -mx-1 my-1 h-px', className)} + className={cn('bg-border -mx-1 my-1 h-px', className)}apps/mail/components/ui/command.tsx (2)
42-51: Rename outline-none to outline-hidden per guidelines.Aligns with the repo’s Tailwind rename policy.
- 'placeholder:text-muted-foreground flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none disabled:cursor-not-allowed disabled:opacity-50', + 'placeholder:text-muted-foreground flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50',
111-118: Unify selected-state selector.You’re mixing quoted and unquoted data-attr variants; pick one for consistency and to avoid accidental specificity quirks.
- "data-[selected='true']:bg-accent data-[selected=true]:text-accent-foreground relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + 'data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (51)
apps/mail/app/(routes)/settings/connections/page.tsx(1 hunks)apps/mail/app/(routes)/settings/danger-zone/page.tsx(1 hunks)apps/mail/app/globals.css(6 hunks)apps/mail/components/connection/add.tsx(1 hunks)apps/mail/components/context/command-palette-context.tsx(5 hunks)apps/mail/components/context/label-sidebar-context.tsx(1 hunks)apps/mail/components/create/email-composer.tsx(2 hunks)apps/mail/components/create/template-button.tsx(1 hunks)apps/mail/components/labels/label-dialog.tsx(1 hunks)apps/mail/components/magicui/file-tree.tsx(1 hunks)apps/mail/components/mail/mail-display.tsx(2 hunks)apps/mail/components/onboarding.tsx(1 hunks)apps/mail/components/responsive-modal.tsx(1 hunks)apps/mail/components/setup-phone.tsx(1 hunks)apps/mail/components/ui/accordion.tsx(3 hunks)apps/mail/components/ui/alert.tsx(1 hunks)apps/mail/components/ui/avatar.tsx(2 hunks)apps/mail/components/ui/badge.tsx(1 hunks)apps/mail/components/ui/button.tsx(2 hunks)apps/mail/components/ui/checkbox.tsx(1 hunks)apps/mail/components/ui/collapsible.tsx(1 hunks)apps/mail/components/ui/command.tsx(8 hunks)apps/mail/components/ui/context-menu.tsx(7 hunks)apps/mail/components/ui/dialog.tsx(1 hunks)apps/mail/components/ui/drawer.tsx(3 hunks)apps/mail/components/ui/dropdown-menu.tsx(7 hunks)apps/mail/components/ui/form.tsx(3 hunks)apps/mail/components/ui/input.tsx(1 hunks)apps/mail/components/ui/label.tsx(1 hunks)apps/mail/components/ui/navigation-menu.tsx(5 hunks)apps/mail/components/ui/popover.tsx(2 hunks)apps/mail/components/ui/pricing-dialog.tsx(1 hunks)apps/mail/components/ui/pricing-switch.tsx(2 hunks)apps/mail/components/ui/progress.tsx(2 hunks)apps/mail/components/ui/prompts-dialog.tsx(1 hunks)apps/mail/components/ui/radio-group.tsx(1 hunks)apps/mail/components/ui/resizable.tsx(1 hunks)apps/mail/components/ui/scroll-area.tsx(1 hunks)apps/mail/components/ui/select.tsx(8 hunks)apps/mail/components/ui/separator.tsx(1 hunks)apps/mail/components/ui/sheet.tsx(1 hunks)apps/mail/components/ui/sidebar.tsx(6 hunks)apps/mail/components/ui/skeleton.tsx(1 hunks)apps/mail/components/ui/switch.tsx(2 hunks)apps/mail/components/ui/tabs.tsx(3 hunks)apps/mail/components/ui/textarea.tsx(1 hunks)apps/mail/components/ui/toggle-group.tsx(1 hunks)apps/mail/components/ui/toggle.tsx(1 hunks)apps/mail/components/ui/tooltip.tsx(1 hunks)apps/mail/package.json(2 hunks)pnpm-workspace.yaml(1 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{css,js,ts,jsx,tsx,mdx}
📄 CodeRabbit inference engine (.cursor/rules/tailwind-css-v4.mdc)
**/*.{css,js,ts,jsx,tsx,mdx}: Chain variants together for composable variants (e.g.,group-has-data-potato:opacity-100).
Use new variants such asstarting,not-*,inert,nth-*,in-*,open(for:popover-open), and**for all descendants.
Do not use deprecated utilities likebg-opacity-*,text-opacity-*,border-opacity-*, anddivide-opacity-*; use the new syntax (e.g.,bg-black/50).
Use renamed utilities:shadow-smis nowshadow-xs,shadowis nowshadow-sm,drop-shadow-smis nowdrop-shadow-xs,drop-shadowis nowdrop-shadow-sm,blur-smis nowblur-xs,bluris nowblur-sm,rounded-smis nowrounded-xs,roundedis nowrounded-sm,outline-noneis nowoutline-hidden.
Usebg-(--brand-color)syntax for CSS variables in arbitrary values instead ofbg-[--brand-color].
Stacked variants now apply left-to-right instead of right-to-left.
Files:
apps/mail/components/mail/mail-display.tsxapps/mail/app/(routes)/settings/connections/page.tsxapps/mail/components/context/label-sidebar-context.tsxapps/mail/app/(routes)/settings/danger-zone/page.tsxapps/mail/components/connection/add.tsxapps/mail/components/ui/resizable.tsxapps/mail/components/ui/prompts-dialog.tsxapps/mail/components/ui/alert.tsxapps/mail/components/responsive-modal.tsxapps/mail/components/ui/pricing-dialog.tsxapps/mail/components/labels/label-dialog.tsxapps/mail/components/ui/textarea.tsxapps/mail/components/ui/tooltip.tsxapps/mail/components/magicui/file-tree.tsxapps/mail/components/setup-phone.tsxapps/mail/components/ui/toggle-group.tsxapps/mail/components/ui/checkbox.tsxapps/mail/components/onboarding.tsxapps/mail/components/create/template-button.tsxapps/mail/components/ui/progress.tsxapps/mail/components/create/email-composer.tsxapps/mail/components/ui/drawer.tsxapps/mail/components/ui/label.tsxapps/mail/components/ui/input.tsxapps/mail/components/ui/command.tsxapps/mail/components/ui/tabs.tsxapps/mail/components/ui/sidebar.tsxapps/mail/components/ui/context-menu.tsxapps/mail/components/ui/select.tsxapps/mail/components/ui/skeleton.tsxapps/mail/app/globals.cssapps/mail/components/ui/scroll-area.tsxapps/mail/components/ui/separator.tsxapps/mail/components/ui/toggle.tsxapps/mail/components/ui/collapsible.tsxapps/mail/components/ui/radio-group.tsxapps/mail/components/ui/navigation-menu.tsxapps/mail/components/context/command-palette-context.tsxapps/mail/components/ui/dropdown-menu.tsxapps/mail/components/ui/avatar.tsxapps/mail/components/ui/form.tsxapps/mail/components/ui/pricing-switch.tsxapps/mail/components/ui/accordion.tsxapps/mail/components/ui/switch.tsxapps/mail/components/ui/popover.tsxapps/mail/components/ui/button.tsxapps/mail/components/ui/sheet.tsxapps/mail/components/ui/badge.tsxapps/mail/components/ui/dialog.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (AGENT.md)
**/*.{js,jsx,ts,tsx}: Use 2-space indentation
Use single quotes
Limit lines to 100 characters
Semicolons are required
Files:
apps/mail/components/mail/mail-display.tsxapps/mail/app/(routes)/settings/connections/page.tsxapps/mail/components/context/label-sidebar-context.tsxapps/mail/app/(routes)/settings/danger-zone/page.tsxapps/mail/components/connection/add.tsxapps/mail/components/ui/resizable.tsxapps/mail/components/ui/prompts-dialog.tsxapps/mail/components/ui/alert.tsxapps/mail/components/responsive-modal.tsxapps/mail/components/ui/pricing-dialog.tsxapps/mail/components/labels/label-dialog.tsxapps/mail/components/ui/textarea.tsxapps/mail/components/ui/tooltip.tsxapps/mail/components/magicui/file-tree.tsxapps/mail/components/setup-phone.tsxapps/mail/components/ui/toggle-group.tsxapps/mail/components/ui/checkbox.tsxapps/mail/components/onboarding.tsxapps/mail/components/create/template-button.tsxapps/mail/components/ui/progress.tsxapps/mail/components/create/email-composer.tsxapps/mail/components/ui/drawer.tsxapps/mail/components/ui/label.tsxapps/mail/components/ui/input.tsxapps/mail/components/ui/command.tsxapps/mail/components/ui/tabs.tsxapps/mail/components/ui/sidebar.tsxapps/mail/components/ui/context-menu.tsxapps/mail/components/ui/select.tsxapps/mail/components/ui/skeleton.tsxapps/mail/components/ui/scroll-area.tsxapps/mail/components/ui/separator.tsxapps/mail/components/ui/toggle.tsxapps/mail/components/ui/collapsible.tsxapps/mail/components/ui/radio-group.tsxapps/mail/components/ui/navigation-menu.tsxapps/mail/components/context/command-palette-context.tsxapps/mail/components/ui/dropdown-menu.tsxapps/mail/components/ui/avatar.tsxapps/mail/components/ui/form.tsxapps/mail/components/ui/pricing-switch.tsxapps/mail/components/ui/accordion.tsxapps/mail/components/ui/switch.tsxapps/mail/components/ui/popover.tsxapps/mail/components/ui/button.tsxapps/mail/components/ui/sheet.tsxapps/mail/components/ui/badge.tsxapps/mail/components/ui/dialog.tsx
**/*.{js,jsx,ts,tsx,css}
📄 CodeRabbit inference engine (AGENT.md)
Use Prettier with sort-imports and Tailwind plugins
Files:
apps/mail/components/mail/mail-display.tsxapps/mail/app/(routes)/settings/connections/page.tsxapps/mail/components/context/label-sidebar-context.tsxapps/mail/app/(routes)/settings/danger-zone/page.tsxapps/mail/components/connection/add.tsxapps/mail/components/ui/resizable.tsxapps/mail/components/ui/prompts-dialog.tsxapps/mail/components/ui/alert.tsxapps/mail/components/responsive-modal.tsxapps/mail/components/ui/pricing-dialog.tsxapps/mail/components/labels/label-dialog.tsxapps/mail/components/ui/textarea.tsxapps/mail/components/ui/tooltip.tsxapps/mail/components/magicui/file-tree.tsxapps/mail/components/setup-phone.tsxapps/mail/components/ui/toggle-group.tsxapps/mail/components/ui/checkbox.tsxapps/mail/components/onboarding.tsxapps/mail/components/create/template-button.tsxapps/mail/components/ui/progress.tsxapps/mail/components/create/email-composer.tsxapps/mail/components/ui/drawer.tsxapps/mail/components/ui/label.tsxapps/mail/components/ui/input.tsxapps/mail/components/ui/command.tsxapps/mail/components/ui/tabs.tsxapps/mail/components/ui/sidebar.tsxapps/mail/components/ui/context-menu.tsxapps/mail/components/ui/select.tsxapps/mail/components/ui/skeleton.tsxapps/mail/app/globals.cssapps/mail/components/ui/scroll-area.tsxapps/mail/components/ui/separator.tsxapps/mail/components/ui/toggle.tsxapps/mail/components/ui/collapsible.tsxapps/mail/components/ui/radio-group.tsxapps/mail/components/ui/navigation-menu.tsxapps/mail/components/context/command-palette-context.tsxapps/mail/components/ui/dropdown-menu.tsxapps/mail/components/ui/avatar.tsxapps/mail/components/ui/form.tsxapps/mail/components/ui/pricing-switch.tsxapps/mail/components/ui/accordion.tsxapps/mail/components/ui/switch.tsxapps/mail/components/ui/popover.tsxapps/mail/components/ui/button.tsxapps/mail/components/ui/sheet.tsxapps/mail/components/ui/badge.tsxapps/mail/components/ui/dialog.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENT.md)
Enable TypeScript strict mode
Files:
apps/mail/components/mail/mail-display.tsxapps/mail/app/(routes)/settings/connections/page.tsxapps/mail/components/context/label-sidebar-context.tsxapps/mail/app/(routes)/settings/danger-zone/page.tsxapps/mail/components/connection/add.tsxapps/mail/components/ui/resizable.tsxapps/mail/components/ui/prompts-dialog.tsxapps/mail/components/ui/alert.tsxapps/mail/components/responsive-modal.tsxapps/mail/components/ui/pricing-dialog.tsxapps/mail/components/labels/label-dialog.tsxapps/mail/components/ui/textarea.tsxapps/mail/components/ui/tooltip.tsxapps/mail/components/magicui/file-tree.tsxapps/mail/components/setup-phone.tsxapps/mail/components/ui/toggle-group.tsxapps/mail/components/ui/checkbox.tsxapps/mail/components/onboarding.tsxapps/mail/components/create/template-button.tsxapps/mail/components/ui/progress.tsxapps/mail/components/create/email-composer.tsxapps/mail/components/ui/drawer.tsxapps/mail/components/ui/label.tsxapps/mail/components/ui/input.tsxapps/mail/components/ui/command.tsxapps/mail/components/ui/tabs.tsxapps/mail/components/ui/sidebar.tsxapps/mail/components/ui/context-menu.tsxapps/mail/components/ui/select.tsxapps/mail/components/ui/skeleton.tsxapps/mail/components/ui/scroll-area.tsxapps/mail/components/ui/separator.tsxapps/mail/components/ui/toggle.tsxapps/mail/components/ui/collapsible.tsxapps/mail/components/ui/radio-group.tsxapps/mail/components/ui/navigation-menu.tsxapps/mail/components/context/command-palette-context.tsxapps/mail/components/ui/dropdown-menu.tsxapps/mail/components/ui/avatar.tsxapps/mail/components/ui/form.tsxapps/mail/components/ui/pricing-switch.tsxapps/mail/components/ui/accordion.tsxapps/mail/components/ui/switch.tsxapps/mail/components/ui/popover.tsxapps/mail/components/ui/button.tsxapps/mail/components/ui/sheet.tsxapps/mail/components/ui/badge.tsxapps/mail/components/ui/dialog.tsx
pnpm-workspace.yaml
📄 CodeRabbit inference engine (AGENT.md)
Monorepo managed with pnpm workspaces
Files:
pnpm-workspace.yaml
**/package.json
📄 CodeRabbit inference engine (AGENT.md)
Workspace packages use catalog versioning for shared dependencies
Files:
apps/mail/package.json
**/*.css
📄 CodeRabbit inference engine (.cursor/rules/tailwind-css-v4.mdc)
**/*.css: Use the@themedirective in CSS for Tailwind v4 configuration instead oftailwind.config.js.
Use@import "tailwindcss";in CSS instead of@tailwinddirectives.
Legacytailwind.config.jsfiles can be imported in CSS using the@configdirective.
Use native CSS@layerinstead of Tailwind's custom implementation.
Access all Tailwind design tokens as CSS variables using the namespace format (e.g.,--color-blue-500).
Override entire theme namespaces in CSS using--font-*: initial;or--*: initial;.
Use container query utilities (@container,@sm:,@max-md:, etc.) directly in CSS for responsive design.
Use 3D transform utilities such astransform-3d,rotate-x-*,scale-z-*, andperspective-*in CSS.
Use new gradient utilities likebg-linear-45,bg-conic, andbg-radial-[at_25%_25%]in CSS.
Use new shadow utilities such asinset-shadow-*andinset-ring-*in CSS.
Use new CSS property utilities likefield-sizing-content,scheme-light,scheme-dark, andfont-stretch-*in CSS.
Define custom utilities using the@utilitydirective in CSS.
Define custom variants using the@variantdirective in CSS.
Use the@plugindirective in CSS to include Tailwind plugins.
Use new default styles: border color iscurrentColor, ring width is 1px, placeholder text uses current color at 50% opacity, and hover styles only apply on devices that support hover.
Use CSS variables instead of thetheme()function.
Use the@import "tailwindcss" prefix(tw);syntax in CSS to add a prefix to all Tailwind classes.
Add sources for Tailwind using the@sourcedirective in CSS.
Disable automatic source detection in Tailwind using@import "tailwindcss" source(none);in CSS.
Import legacy config files in CSS using@config.
Configure dark mode in CSS using the@variant darkdirective.
Extend container customization in CSS using the@utilitydirective.
Files:
apps/mail/app/globals.css
🧠 Learnings (8)
📚 Learning: 2025-08-10T08:25:22.063Z
Learnt from: CR
PR: Mail-0/Zero#0
File: AGENT.md:0-0
Timestamp: 2025-08-10T08:25:22.063Z
Learning: Applies to **/package.json : Workspace packages use catalog versioning for shared dependencies
Applied to files:
pnpm-workspace.yaml
📚 Learning: 2025-08-10T08:25:22.063Z
Learnt from: CR
PR: Mail-0/Zero#0
File: AGENT.md:0-0
Timestamp: 2025-08-10T08:25:22.063Z
Learning: Applies to pnpm-workspace.yaml : Monorepo managed with pnpm workspaces
Applied to files:
pnpm-workspace.yaml
📚 Learning: 2025-08-03T20:42:04.207Z
Learnt from: CR
PR: Mail-0/Zero#0
File: .cursor/rules/tailwind-css-v4.mdc:0-0
Timestamp: 2025-08-03T20:42:04.207Z
Learning: Applies to **/*.{css,js,ts,jsx,tsx,mdx} : Use `bg-(--brand-color)` syntax for CSS variables in arbitrary values instead of `bg-[--brand-color]`.
Applied to files:
apps/mail/app/globals.css
📚 Learning: 2025-08-03T20:42:04.207Z
Learnt from: CR
PR: Mail-0/Zero#0
File: .cursor/rules/tailwind-css-v4.mdc:0-0
Timestamp: 2025-08-03T20:42:04.207Z
Learning: Applies to **/*.css : Use new default styles: border color is `currentColor`, ring width is 1px, placeholder text uses current color at 50% opacity, and hover styles only apply on devices that support hover.
Applied to files:
apps/mail/app/globals.css
📚 Learning: 2025-08-03T20:42:04.207Z
Learnt from: CR
PR: Mail-0/Zero#0
File: .cursor/rules/tailwind-css-v4.mdc:0-0
Timestamp: 2025-08-03T20:42:04.207Z
Learning: Applies to **/*.css : Use new CSS property utilities like `field-sizing-content`, `scheme-light`, `scheme-dark`, and `font-stretch-*` in CSS.
Applied to files:
apps/mail/app/globals.css
📚 Learning: 2025-08-03T20:42:04.207Z
Learnt from: CR
PR: Mail-0/Zero#0
File: .cursor/rules/tailwind-css-v4.mdc:0-0
Timestamp: 2025-08-03T20:42:04.207Z
Learning: Applies to **/*.css : Configure dark mode in CSS using the `variant dark` directive.
Applied to files:
apps/mail/app/globals.css
📚 Learning: 2025-08-03T20:42:04.207Z
Learnt from: CR
PR: Mail-0/Zero#0
File: .cursor/rules/tailwind-css-v4.mdc:0-0
Timestamp: 2025-08-03T20:42:04.207Z
Learning: Applies to **/*.{css,js,ts,jsx,tsx,mdx} : Use renamed utilities: `shadow-sm` is now `shadow-xs`, `shadow` is now `shadow-sm`, `drop-shadow-sm` is now `drop-shadow-xs`, `drop-shadow` is now `drop-shadow-sm`, `blur-sm` is now `blur-xs`, `blur` is now `blur-sm`, `rounded-sm` is now `rounded-xs`, `rounded` is now `rounded-sm`, `outline-none` is now `outline-hidden`.
Applied to files:
apps/mail/app/globals.cssapps/mail/components/ui/toggle.tsx
📚 Learning: 2025-08-03T20:42:04.207Z
Learnt from: CR
PR: Mail-0/Zero#0
File: .cursor/rules/tailwind-css-v4.mdc:0-0
Timestamp: 2025-08-03T20:42:04.207Z
Learning: Applies to **/*.css : Use native CSS `layer` instead of Tailwind's custom implementation.
Applied to files:
apps/mail/app/globals.css
🧬 Code graph analysis (21)
apps/mail/components/mail/mail-display.tsx (1)
apps/mail/components/ui/dialog.tsx (1)
DialogContent(121-121)
apps/mail/components/connection/add.tsx (1)
apps/mail/components/ui/dialog.tsx (1)
DialogContent(121-121)
apps/mail/components/labels/label-dialog.tsx (1)
apps/mail/components/ui/dialog.tsx (1)
DialogContent(121-121)
apps/mail/components/setup-phone.tsx (1)
apps/mail/components/ui/dialog.tsx (1)
DialogContent(121-121)
apps/mail/components/onboarding.tsx (1)
apps/mail/components/ui/dialog.tsx (1)
DialogContent(121-121)
apps/mail/components/create/template-button.tsx (1)
apps/mail/components/ui/dialog.tsx (1)
DialogContent(121-121)
apps/mail/components/create/email-composer.tsx (1)
apps/mail/components/ui/dialog.tsx (1)
DialogContent(121-121)
apps/mail/components/ui/drawer.tsx (1)
apps/mail/lib/utils.ts (1)
cn(56-56)
apps/mail/components/ui/input.tsx (1)
apps/mail/lib/utils.ts (1)
cn(56-56)
apps/mail/components/ui/command.tsx (2)
apps/mail/lib/utils.ts (1)
cn(56-56)apps/mail/components/icons/icons.tsx (1)
Search(1651-1666)
apps/mail/components/ui/select.tsx (2)
apps/mail/components/icons/icons.tsx (2)
ChevronDown(1200-1216)Check(1634-1649)apps/mail/lib/utils.ts (1)
cn(56-56)
apps/mail/components/ui/skeleton.tsx (1)
apps/mail/lib/utils.ts (1)
cn(56-56)
apps/mail/components/ui/scroll-area.tsx (1)
apps/mail/lib/utils.ts (1)
cn(56-56)
apps/mail/components/ui/separator.tsx (1)
apps/mail/lib/utils.ts (1)
cn(56-56)
apps/mail/components/context/command-palette-context.tsx (1)
apps/mail/components/ui/dialog.tsx (2)
DialogTitle(127-127)DialogDescription(122-122)
apps/mail/components/ui/dropdown-menu.tsx (1)
apps/mail/components/icons/icons.tsx (1)
ChevronRight(835-850)
apps/mail/components/ui/avatar.tsx (1)
apps/mail/lib/utils.ts (1)
cn(56-56)
apps/mail/components/ui/switch.tsx (1)
apps/mail/lib/utils.ts (1)
cn(56-56)
apps/mail/components/ui/button.tsx (1)
apps/mail/lib/utils.ts (1)
cn(56-56)
apps/mail/components/ui/sheet.tsx (1)
apps/mail/lib/utils.ts (1)
cn(56-56)
apps/mail/components/ui/dialog.tsx (1)
apps/mail/lib/utils.ts (1)
cn(56-56)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: cubic · AI code reviewer
| --subtleBlack: #1F1F1F; | ||
| --skyBlue: #0066FF; | ||
| --shinyGray: #A1A1A1; | ||
| --sidebar: hsl(0 0% 98%); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Unify the sidebar token — single source of truth.
You introduced --sidebar but the theme still maps to --sidebar-background. Wire it up or delete the new var to avoid dead config.
Apply this diff to use the new token across the theme:
@@
- --sidebar: hsl(0 0% 98%);
+ --sidebar: hsl(0 0% 98%);
@@
- --sidebar: hsl(240 5.9% 10%);
+ --sidebar: hsl(240 5.9% 10%);
@@
- --color-sidebar: var(--sidebar-background);
+ --color-sidebar: var(--sidebar);If other files still consume --sidebar-background, keep both and plan a follow-up sweep.
Also applies to: 118-118, 166-174
🤖 Prompt for AI Agents
In apps/mail/app/globals.css around lines 80 (and also check 118 and 166-174),
you added a new CSS variable --sidebar but the rest of the theme still uses
--sidebar-background, creating a dead/duplicate token; either wire the theme to
use --sidebar everywhere or remove --sidebar. Fix by updating all occurrences of
--sidebar-background in this file (and any other project files) to reference
--sidebar (or add --sidebar-background as an alias that references --sidebar) so
there is a single source of truth, and if you choose to keep both add a TODO to
sweep other files later.
| @layer base { | ||
| * { | ||
| @apply border-border outline-ring/50; | ||
| } | ||
| body { | ||
| @apply bg-background text-foreground; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Kill the duplication: two base layers fight; last one wins.
You now have two @layer base blocks for * and body. This creates conflicting cascade. Pick one baseline and delete the other. If the intent is the simplified body, remove the earlier block.
Apply this diff to consolidate:
@@
-@layer base {
- * {
- @apply border-border;
- }
- body {
- @apply bg-background text-foreground font-sans overscroll-none style-scrollbar;
- }
-}Optionally, if you still want the scrollbar styling and font family, fold them into the final block instead:
@layer base {
* {
- @apply border-border outline-ring/50;
+ @apply border-border outline-ring/50;
}
body {
- @apply bg-background text-foreground;
+ @apply bg-background text-foreground font-sans style-scrollbar;
+ /* If you intended to drop overscroll-none, omit it; else add it back explicitly */
+ /* @apply overscroll-none; */
}
}Also sanity-check outline-ring/50 on * — global outline color is fine, but unnecessary work. Consider scoping to focusable elements if perf or specificity becomes noisy.
🏁 Script executed:
#!/bin/bash
echo "Occurrences of '@layer base' in apps/mail/app/globals.css:"
rg -n '@layer base' apps/mail/app/globals.css
echo ""
echo "Snippets around each occurrence:"
for L in $(rg -n '@layer base' apps/mail/app/globals.css | cut -d: -f1); do
echo "=== Snippet around line $L ==="
sed -n "$((L-5)),$((L+10))p" apps/mail/app/globals.css
echo ""
doneLength of output: 1199
Consolidate duplicate @layer base blocks (lines 278 & 480). Only the last block wins, so remove the one at 278 or merge its unique body styles (font-sans overscroll-none style-scrollbar) into the block at 480. Consider scoping outline-ring/50 to focusable elements for better performance.
🤖 Prompt for AI Agents
In apps/mail/app/globals.css around lines 480 (and duplicate at 278), there are
two @layer base blocks where only the last one wins; remove the earlier block at
line 278 or merge its unique declarations (font-sans, overscroll-none,
style-scrollbar) into the block at 480 so all base styles are consolidated; also
scope the universal outline-rule (outline-ring/50) to focusable elements (e.g.,
links, buttons, inputs, textareas, selects, and elements using tabindex) instead
of applying to * to reduce styling cost and avoid unintended outlines.
| <DialogContent className="bg-panelLight mx-auto w-full max-w-[90%] rounded-xl border p-0 sm:max-w-[690px] dark:bg-[#111111]"> | ||
| <div className="flex flex-col gap-4 p-4"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Place DialogTitle inside DialogContent (or add a header) for proper a11y semantics.
Right now DialogTitle sits outside Content. Move it inside so aria attributes resolve correctly.
- <Dialog open={open} onOpenChange={onOpenChange}>
- <DialogTitle></DialogTitle>
- <DialogContent className="bg-panelLight mx-auto w-full max-w-[90%] rounded-xl border p-0 sm:max-w-[690px] dark:bg-[#111111]">
+ <Dialog open={open} onOpenChange={onOpenChange}>
+ <DialogContent className="bg-panelLight mx-auto w-full max-w-[90%] rounded-xl border p-0 sm:max-w-[690px] dark:bg-[#111111]">
+ {/* Optional header for a11y */}
+ {/* <DialogHeader><DialogTitle>Welcome to Zero Email</DialogTitle></DialogHeader> */}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <DialogContent className="bg-panelLight mx-auto w-full max-w-[90%] rounded-xl border p-0 sm:max-w-[690px] dark:bg-[#111111]"> | |
| <div className="flex flex-col gap-4 p-4"> | |
| <Dialog open={open} onOpenChange={onOpenChange}> | |
| {/* Removed the standalone <DialogTitle> so that it lives inside the content for proper aria semantics */} | |
| <DialogContent className="bg-panelLight mx-auto w-full max-w-[90%] rounded-xl border p-0 sm:max-w-[690px] dark:bg-[#111111]"> | |
| {/* Optional header for a11y */} | |
| {/* <DialogHeader> | |
| <DialogTitle>Welcome to Zero Email</DialogTitle> | |
| </DialogHeader> */} | |
| <div className="flex flex-col gap-4 p-4"> | |
| {/* …the rest of your onboarding UI… */} | |
| </div> | |
| </DialogContent> | |
| </Dialog> |
🤖 Prompt for AI Agents
In apps/mail/components/onboarding.tsx around lines 75-76, DialogTitle is
currently placed outside of DialogContent which breaks accessibility semantics;
move the existing DialogTitle element so it is nested directly inside the
DialogContent (or add a header wrapper inside DialogContent and place
DialogTitle there) ensuring the title is rendered before the main content and
that aria-labelledby/aria-describedby references resolve correctly; update any
classNames/layout as needed so visual layout is unchanged after moving the
title.
| import { Drawer, DrawerContent, DrawerHeader, DrawerTitle } from '@/components/ui/drawer'; | ||
| import { VisuallyHidden } from 'radix-ui'; | ||
| import { VisuallyHidden } from '@radix-ui/react-visually-hidden'; | ||
| import { type ReactElement } from 'react'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Type import nit — import ReactNode directly.
Cleaner and consistent with TS strict prefs.
-import { type ReactElement } from 'react';
+import type { ReactElement, ReactNode } from 'react';
...
type ResponsiveModalProps = {
- children: React.ReactNode;
+ children: ReactNode;
open: boolean;
onOpenChange: (open: boolean) => void;
};Also applies to: 13-17
🤖 Prompt for AI Agents
In apps/mail/components/responsive-modal.tsx around line 10 (and similarly lines
13–17), the import uses "type ReactElement"; change the import to pull ReactNode
instead (e.g. import { type ReactNode } from 'react') and update any related
prop/type annotations that currently reference ReactElement to use ReactNode for
consistency with TS strict preferences.
| import { VisuallyHidden } from 'radix-ui'; | ||
| import { VisuallyHidden } from '@radix-ui/react-visually-hidden'; | ||
| import { type ReactElement } from 'react'; | ||
| // import { useMedia } from 'react-use'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
isDesktop hardcoded to true — mobile Drawer path is dead. Intended?
If not deliberate, re-enable a media query so this actually responds. Speed is key; correctness too.
-// import { useMedia } from 'react-use';
+import { useMedia } from 'react-use';
...
- const isDesktop = true;
+ const isDesktop = useMedia('(min-width: 768px)', true);Verify no hydration warnings and that Drawer renders below 768px.
Also applies to: 24-27
🤖 Prompt for AI Agents
In apps/mail/components/responsive-modal.tsx around line 11 (and also affecting
lines 24–27) you hardcoded isDesktop = true which disables the mobile Drawer —
re-enable a media query (e.g., import useMedia from 'react-use' and call
useMedia('(min-width: 768px)')) to derive isDesktop; to avoid hydration
warnings, compute isDesktop only on the client (use a mounted flag with
useEffect or useMedia's initialValue tied to typeof window check) or render a
placeholder until mounted so server vs client markup matches; finally ensure the
Drawer branch is returned when isDesktop is false (width < 768px) so the Drawer
renders on mobile.
| className={cn( | ||
| 'bg-background pointer-events-none relative block h-3 w-3 rounded-full shadow-lg ring-0 transition-transform data-[state=checked]:right-1 data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0 dark:bg-white', | ||
| 'bg-background pointer-events-none block h-5 w-5 rounded-full shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0', | ||
| )} | ||
| /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Split long Thumb class for ≤100 chars.
Tiny readability win; zero functional change.
- 'bg-background pointer-events-none block h-5 w-5 rounded-full shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0',
+ 'bg-background pointer-events-none block h-5 w-5 rounded-full shadow-lg ring-0',
+ 'transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0',📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| className={cn( | |
| 'bg-background pointer-events-none relative block h-3 w-3 rounded-full shadow-lg ring-0 transition-transform data-[state=checked]:right-1 data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0 dark:bg-white', | |
| 'bg-background pointer-events-none block h-5 w-5 rounded-full shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0', | |
| )} | |
| className={cn( | |
| 'bg-background pointer-events-none block h-5 w-5 rounded-full shadow-lg ring-0', | |
| 'transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0', | |
| )} |
🤖 Prompt for AI Agents
In apps/mail/components/ui/switch.tsx around lines 21 to 23, the long single
string of classes passed to cn for the thumb exceeds 100 chars and should be
split for readability; break the long class string into multiple shorter strings
(either as multiple arguments to cn or an array of strings) so each line is ≤100
chars, keep the exact class tokens and their order unchanged, and ensure the
data-[state=checked] and data-[state=unchecked] utilities remain attached to the
correct token so behavior is preserved.
| className={cn( | ||
| 'ring-offset-background focus-visible:ring-ring data-[state=active]:bg-background data-[state=active]:text-foreground inline-flex items-center justify-center whitespace-nowrap rounded-sm px-2 py-px text-sm font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm', | ||
| 'ring-offset-background focus-visible:ring-ring data-[state=active]:bg-background data-[state=active]:text-foreground inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm', | ||
| className, | ||
| )} | ||
| {...props} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
🛠️ Refactor suggestion
Adopt Tailwind’s renamed utilities and keep lines ≤100 chars.
Use new tokens: rounded-sm → rounded-xs, outline-none → outline-hidden, shadow-sm → shadow-xs. Also split the long class string and avoid transition-all (scope transitions explicitly).
- className={cn(
- 'ring-offset-background focus-visible:ring-ring data-[state=active]:bg-background data-[state=active]:text-foreground inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm',
- className,
- )}
+ className={cn(
+ 'ring-offset-background focus-visible:ring-ring',
+ 'inline-flex items-center justify-center whitespace-nowrap rounded-xs px-3 py-1.5 text-sm font-medium',
+ 'transition-[color,box-shadow] focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-offset-2',
+ 'disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-xs',
+ className,
+ )}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| className={cn( | |
| 'ring-offset-background focus-visible:ring-ring data-[state=active]:bg-background data-[state=active]:text-foreground inline-flex items-center justify-center whitespace-nowrap rounded-sm px-2 py-px text-sm font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm', | |
| 'ring-offset-background focus-visible:ring-ring data-[state=active]:bg-background data-[state=active]:text-foreground inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm', | |
| className, | |
| )} | |
| {...props} | |
| className={cn( | |
| 'ring-offset-background focus-visible:ring-ring', | |
| 'inline-flex items-center justify-center whitespace-nowrap rounded-xs px-3 py-1.5 text-sm font-medium', | |
| 'transition-[color,box-shadow] focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-offset-2', | |
| 'disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-xs', | |
| className, | |
| )} | |
| {...props} |
🤖 Prompt for AI Agents
In apps/mail/components/ui/tabs.tsx around lines 31 to 35, update the long
className string to use Tailwind’s renamed utilities and keep lines under 100
chars: replace rounded-sm with rounded-xs, focus-visible:outline-none with
focus-visible:outline-hidden, and data-[state=active]:shadow-sm with
data-[state=active]:shadow-xs; remove transition-all and instead add explicit
transition classes (e.g., transition-colors transition-shadow duration-150) to
scope transitions; and split the class string into multiple concatenated strings
or array entries passed to cn so no line exceeds 100 characters.
| <textarea | ||
| className={cn( | ||
| 'border-input bg-background ring-offset-background placeholder:text-muted-foreground flex min-h-[80px] w-full rounded-md border px-3 py-2 text-base focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm', | ||
| 'border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex min-h-[80px] w-full rounded-md border px-3 py-2 text-base focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Rename deprecated utility: outline-none → outline-hidden.
Aligns with the new utilities in the guidelines.
Apply this diff:
- 'border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex min-h-[80px] w-full rounded-md border px-3 py-2 text-base focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
+ 'border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex min-h-[80px] w-full rounded-md border px-3 py-2 text-base focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 'border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex min-h-[80px] w-full rounded-md border px-3 py-2 text-base focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm', | |
| 'border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex min-h-[80px] w-full rounded-md border px-3 py-2 text-base focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm', |
🤖 Prompt for AI Agents
In apps/mail/components/ui/textarea.tsx around line 10, replace the deprecated
utility "outline-none" with the new "outline-hidden" inside the Tailwind class
string; update the class list to use "focus-visible:outline-hidden" (preserving
all other classes and spacing) so the component aligns with the new utility
naming.
|
|
||
| const toggleVariants = cva( | ||
| 'inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0', | ||
| 'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 gap-2', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Tailwind v4 rename: use outline-hidden, not outline-none.
Per repo guidelines, outline-none → outline-hidden. Also, this line likely exceeds the 100-char limit—consider factoring base classes to keep lint green.
Apply:
- 'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 gap-2',
+ 'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 gap-2',Nit: if the linter complains about line length, split the base classes into a const base = '...' and pass base to cva, or move some stable pieces into cn() alongside toggleVariants(...).
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 gap-2', | |
| 'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 gap-2', |
🤖 Prompt for AI Agents
In apps/mail/components/ui/toggle.tsx around line 10, the Tailwind class list
uses the deprecated outline-none and the string exceeds the 100‑char lint limit;
replace outline-none with outline-hidden and refactor the long class string by
extracting stable base classes into a const (e.g. const base = '...') and pass
that base into cva or combine via cn(toggleVariants(...), base) so the file
stays under the line-length limit and follows repo guidelines.
| outline: 'border border-input bg-transparent hover:bg-accent hover:text-accent-foreground', | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Outline variant: drop the border when active for cleaner “on” state.
Prevents the outline border from clashing with the bg-accent on toggle.
- outline: 'border border-input bg-transparent hover:bg-accent hover:text-accent-foreground',
+ outline: 'border border-input bg-transparent hover:bg-accent hover:text-accent-foreground data-[state=on]:border-transparent',📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| outline: 'border border-input bg-transparent hover:bg-accent hover:text-accent-foreground', | |
| }, | |
| outline: 'border border-input bg-transparent hover:bg-accent hover:text-accent-foreground data-[state=on]:border-transparent', | |
| }, |
🤖 Prompt for AI Agents
In apps/mail/components/ui/toggle.tsx around lines 15 to 16, the "outline"
variant currently applies a visible border even when the toggle is active;
update the variant so the border is removed in the active/on state (e.g. replace
the active state classes that include 'border' with 'border-0' or
'border-transparent' and keep bg-accent and hover styles), ensuring the toggle
shows a clean filled "on" appearance while hover behavior remains unchanged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review continued from previous batch...
| } from '@/components/ui/dialog'; | ||
| 'use client'; | ||
|
|
||
| import { type DialogProps } from '@radix-ui/react-dialog'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Decouple from Radix types; derive from local Dialog instead.
Prevents tight coupling and future Radix changes from leaking through.
-import { type DialogProps } from '@radix-ui/react-dialog';
+// (type-only) derive from local Dialog to avoid coupling to Radix types
-const CommandDialog = ({ children, ...props }: DialogProps) => {
+const CommandDialog = (
+ { children, ...props }: React.ComponentProps<typeof Dialog>,
+) => {Also applies to: 26-26
🤖 Prompt for AI Agents
In apps/mail/components/ui/command.tsx around lines 3 and 26, remove the import
of DialogProps from '@radix-ui/react-dialog' and instead derive the dialog prop
type from our local Dialog component to avoid coupling to Radix; either import a
DialogProps type exported by the local Dialog module or define the type as
React.ComponentPropsWithoutRef<typeof Dialog> (or the appropriate ComponentProps
helper) and update the function/component signatures to use that local-derived
type.
| @@ -46,12 +39,12 @@ const CommandInput = React.forwardRef< | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
❓ Verification inconclusive
Hide the close button inside CommandDialog.
The new DialogContent renders a close button by default; it overlaps the command UI. Turn it off here.
- <DialogContent className="overflow-hidden p-0 shadow-lg">
+ <DialogContent showCloseButton={false} className="overflow-hidden p-0 shadow-lg">Hide default close button in CommandDialog via CSS utility. The built-in close button in DialogContent overlaps the command UI—hide it with a Tailwind selector:
- <DialogContent className="overflow-hidden p-0 shadow-lg">
+ <DialogContent className="overflow-hidden p-0 shadow-lg [&_[data-radix-dialog-close]]:hidden">📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <DialogContent className="overflow-hidden p-0 shadow-lg"> | |
| <Command className="[&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5"> | |
| {children} | |
| </Command> | |
| </DialogContent> | |
| <DialogContent className="overflow-hidden p-0 shadow-lg [&_[data-radix-dialog-close]]:hidden"> | |
| <Command className="[&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5"> | |
| {children} | |
| </Command> | |
| </DialogContent> |
🤖 Prompt for AI Agents
apps/mail/components/ui/command.tsx around lines 29-33: the DialogContent
contains the built-in close button which overlaps the command UI; update the
DialogContent className to include a Tailwind selector that hides the default
close button element inside it (e.g. add a utility targeting the close button
selector and set it hidden) and ensure other dialog close mechanisms
(ESC/overlay) remain enabled.
| 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-[--radix-dropdown-menu-content-transform-origin] overflow-hidden rounded-md border p-1 shadow-lg', | ||
| className, | ||
| )} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix transform-origin CSS var syntax.
Use var(...); current value is invalid.
- 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-[--radix-dropdown-menu-content-transform-origin] overflow-hidden rounded-md border p-1 shadow-lg',
+ 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-[var(--radix-dropdown-menu-content-transform-origin)] overflow-hidden rounded-md border p-1 shadow-lg',📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-[--radix-dropdown-menu-content-transform-origin] overflow-hidden rounded-md border p-1 shadow-lg', | |
| className, | |
| )} | |
| 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-[var(--radix-dropdown-menu-content-transform-origin)] overflow-hidden rounded-md border p-1 shadow-lg', | |
| className, | |
| )} |
🤖 Prompt for AI Agents
In apps/mail/components/ui/dropdown-menu.tsx around lines 49 to 51, the Tailwind
utility used for transform-origin is currently using the raw CSS variable name
"origin-[--radix-dropdown-menu-content-transform-origin]" which is invalid;
update it to use the CSS var() syntax by replacing that token with
"origin-[var(--radix-dropdown-menu-content-transform-origin)]" so Tailwind emits
a valid transform-origin value.
| className, | ||
| )} | ||
| {...props} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also fix transform-origin var on Content.
Align with SubContent and Radix docs.
- 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] origin-[--radix-dropdown-menu-content-transform-origin] overflow-y-auto overflow-x-hidden rounded-md border p-1 shadow-md',
+ 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] origin-[var(--radix-dropdown-menu-content-transform-origin)] overflow-y-auto overflow-x-hidden rounded-md border p-1 shadow-md',📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] origin-[--radix-dropdown-menu-content-transform-origin] overflow-y-auto overflow-x-hidden rounded-md border p-1 shadow-md', | |
| className, | |
| )} | |
| 'bg-popover text-popover-foreground \ | |
| data-[state=open]:animate-in data-[state=closed]:animate-out \ | |
| data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 \ | |
| data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 \ | |
| data-[side=bottom]:slide-in-from-top-2 \ | |
| data-[side=left]:slide-in-from-right-2 \ | |
| data-[side=right]:slide-in-from-left-2 \ | |
| data-[side=top]:slide-in-from-bottom-2 \ | |
| z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] \ | |
| min-w-[8rem] \ | |
| origin-[var(--radix-dropdown-menu-content-transform-origin)] \ | |
| overflow-y-auto overflow-x-hidden rounded-md border p-1 shadow-md', | |
| className, | |
| )} |
🤖 Prompt for AI Agents
In apps/mail/components/ui/dropdown-menu.tsx around lines 66 to 68, the Content
class uses origin-[--radix-dropdown-menu-content-transform-origin] which is
incorrect; change it to use the CSS var() form
origin-[var(--radix-dropdown-menu-content-transform-origin)] so the
transform-origin matches SubContent and Radix docs, and ensure the className
concatenation remains unchanged.
| @@ -94,7 +97,7 @@ const DropdownMenuCheckboxItem = React.forwardRef< | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Replace outline-none with outline-hidden (item).
- 'focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
+ 'focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 'focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0', | |
| inset && 'pl-8', | |
| className, | |
| )} | |
| 'focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0', | |
| inset && 'pl-8', | |
| className, | |
| )} |
🤖 Prompt for AI Agents
In apps/mail/components/ui/dropdown-menu.tsx around lines 84 to 87, the class
string currently includes "outline-none" but the review requests using
"outline-hidden (item)"; replace the "outline-none" token with "outline-hidden"
(and annotate or mark it as the item variant if your style system expects the
literal "(item)" marker), ensuring the resulting class list contains
"outline-hidden" in place of "outline-none" so the component uses the correct
outline utility.
| className, | ||
| )} | ||
| {...props} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Replace outline-none with outline-hidden (radio item).
- 'focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
+ 'focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50',📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 'focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50', | |
| className, | |
| )} | |
| 'focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50', | |
| className, | |
| )} |
🤖 Prompt for AI Agents
In apps/mail/components/ui/dropdown-menu.tsx around lines 123 to 125, the radio
item classes include 'outline-none' but the design system expects
'outline-hidden'; update the class string to replace 'outline-none' with
'outline-hidden' so the radio item uses the correct utility, keeping the rest of
the className merge intact and preserving surrounding spacing and commas.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
10 issues found across 52 files
React with 👍 or 👎 to teach cubic. You can also tag @cubic-dev-ai to give feedback, ask questions, or re-run the review.
| isLoading?: boolean; | ||
| loadingText?: string; | ||
| } | ||
| function Button({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Button no longer forwards its ref, which can break focus management and integrations expecting a ref (common in shadcn/radix patterns). Reintroduce React.forwardRef for parity and accessibility.
(Based on your team's feedback about keeping component APIs consistent while migrating to modern imports.)
Prompt for AI agents
Address the following comment on apps/mail/components/ui/button.tsx at line 40:
<comment>Button no longer forwards its ref, which can break focus management and integrations expecting a ref (common in shadcn/radix patterns). Reintroduce React.forwardRef for parity and accessibility.
(Based on your team's feedback about keeping component APIs consistent while migrating to modern imports.)</comment>
<file context>
@@ -36,50 +37,25 @@ const buttonVariants = cva(
- isLoading?: boolean;
- loadingText?: string;
-}
+function Button({
+ className,
+ variant,
</file context>
| "@fontsource-variable/geist-mono": "5.2.6", | ||
| "@hookform/resolvers": "4.1.2", | ||
| "@intercom/messenger-js-sdk": "0.0.14", | ||
| "@radix-ui/react-accordion": "1.2.12", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Multiple @radix-ui/react-* dependencies were added but no code references to "@radix-ui" exist in the repo, indicating these are currently unused and add install size and maintenance surface. Consider removing unused deps or include the related code changes that use them.
(Based on your PR’s goal of migrating to modern @radix-ui imports and removing the legacy package, I verified actual usage across the codebase.)
Prompt for AI agents
Address the following comment on apps/mail/package.json at line 28:
<comment>Multiple @radix-ui/react-* dependencies were added but no code references to "@radix-ui" exist in the repo, indicating these are currently unused and add install size and maintenance surface. Consider removing unused deps or include the related code changes that use them.
(Based on your PR’s goal of migrating to modern @radix-ui imports and removing the legacy package, I verified actual usage across the codebase.)</comment>
<file context>
@@ -25,6 +25,28 @@
"@fontsource-variable/geist-mono": "5.2.6",
"@hookform/resolvers": "4.1.2",
"@intercom/messenger-js-sdk": "0.0.14",
+ "@radix-ui/react-accordion": "1.2.12",
+ "@radix-ui/react-avatar": "1.1.10",
+ "@radix-ui/react-checkbox": "1.3.3",
</file context>
| className={cn( | ||
| 'file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input shadow-xs flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base outline-none transition-[color,box-shadow] file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm', | ||
| 'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]', | ||
| 'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aria-invalid sets a ring color without a ring width, so the error ring won’t be visible. Add a ring size (e.g., aria-invalid:ring-[3px]) so the invalid state is apparent.
(Based on your team's feedback about ensuring consistent focus rings and a11y across components.)
Prompt for AI agents
Address the following comment on apps/mail/components/ui/input.tsx at line 13:
<comment>aria-invalid sets a ring color without a ring width, so the error ring won’t be visible. Add a ring size (e.g., aria-invalid:ring-[3px]) so the invalid state is apparent.
(Based on your team's feedback about ensuring consistent focus rings and a11y across components.)</comment>
<file context>
@@ -2,21 +2,20 @@ import * as React from 'react';
+ className={cn(
+ 'file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input shadow-xs flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base outline-none transition-[color,box-shadow] file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
+ 'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
+ 'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
+ className,
+ )}
</file context>
| 'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive', | |
| 'aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive', |
| }, | ||
| ); | ||
| Input.displayName = 'Input'; | ||
| function Input({ className, type, ...props }: React.ComponentProps<'input'>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ref is no longer forwarded to the underlying input, which will break react-hook-form registration and any ref-based focus/validation. Restore React.forwardRef and pass ref to the native to maintain behavior.
(Based on your team's goal of keeping all existing functionality intact during the migration.)
Prompt for AI agents
Address the following comment on apps/mail/components/ui/input.tsx at line 5:
<comment>Ref is no longer forwarded to the underlying input, which will break react-hook-form registration and any ref-based focus/validation. Restore React.forwardRef and pass ref to the native <input> to maintain behavior.
(Based on your team's goal of keeping all existing functionality intact during the migration.)</comment>
<file context>
@@ -2,21 +2,20 @@ import * as React from 'react';
- },
-);
-Input.displayName = 'Input';
+function Input({ className, type, ...props }: React.ComponentProps<'input'>) {
+ return (
+ <input
</file context>
| }, | ||
| }, | ||
| ); | ||
| function SheetContent({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ref is not forwarded for SheetContent; use React.forwardRef to preserve ref support and match Radix/shadcn conventions.
Prompt for AI agents
Address the following comment on apps/mail/components/ui/sheet.tsx at line 41:
<comment>Ref is not forwarded for SheetContent; use React.forwardRef to preserve ref support and match Radix/shadcn conventions.</comment>
<file context>
@@ -1,110 +1,125 @@
- },
- },
-);
+function SheetContent({
+ className,
+ children,
</file context>
| <NavigationMenuPrimitive.Viewport | ||
| className={cn( | ||
| 'origin-top-center bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 relative mt-1.5 h-(--radix-navigation-menu-viewport-height) w-full overflow-hidden rounded-md border shadow md:w-(--radix-navigation-menu-viewport-width)', | ||
| 'origin-top-center bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border shadow-lg md:w-[var(--radix-navigation-menu-viewport-width)]', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
origin-top-center is not a valid Tailwind utility by default; the transform-origin will be ignored. Use origin-top (equivalent to top center) or define a custom transformOrigin in Tailwind config.
Prompt for AI agents
Address the following comment on apps/mail/components/ui/navigation-menu.tsx at line 84:
<comment>origin-top-center is not a valid Tailwind utility by default; the transform-origin will be ignored. Use origin-top (equivalent to top center) or define a custom transformOrigin in Tailwind config.</comment>
<file context>
@@ -80,7 +81,7 @@ const NavigationMenuViewport = React.forwardRef<
<NavigationMenuPrimitive.Viewport
className={cn(
- 'origin-top-center bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 relative mt-1.5 h-(--radix-navigation-menu-viewport-height) w-full overflow-hidden rounded-md border shadow md:w-(--radix-navigation-menu-viewport-width)',
+ 'origin-top-center bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border shadow-lg md:w-[var(--radix-navigation-menu-viewport-width)]',
className,
)}
</file context>
| 'origin-top-center bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border shadow-lg md:w-[var(--radix-navigation-menu-viewport-width)]', | |
| 'origin-top bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border shadow-lg md:w-[var(--radix-navigation-menu-viewport-width)]', |
| <TooltipContent>Prompts</TooltipContent> | ||
| </Tooltip> | ||
| <DialogContent className="max-w-(--breakpoint-lg)" showOverlay={true}> | ||
| <DialogContent className="max-w-(--breakpoint-lg)"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invalid Tailwind class syntax for arbitrary value; use square brackets with var() so the max-width is applied.
Prompt for AI agents
Address the following comment on apps/mail/components/ui/prompts-dialog.tsx at line 135:
<comment>Invalid Tailwind class syntax for arbitrary value; use square brackets with var() so the max-width is applied.</comment>
<file context>
@@ -132,7 +132,7 @@ export function PromptsDialog() {
<TooltipContent>Prompts</TooltipContent>
</Tooltip>
- <DialogContent className="max-w-(--breakpoint-lg)" showOverlay={true}>
+ <DialogContent className="max-w-(--breakpoint-lg)">
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
</file context>
| <DialogContent className="max-w-(--breakpoint-lg)"> | |
| <DialogContent className="max-w-[var(--breakpoint-lg)]"> |
| ref={ref} | ||
| className={cn( | ||
| 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-32 origin-(--radix-select-content-transform-origin) overflow-y-auto overflow-x-hidden rounded-md border shadow-md', | ||
| 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-[--radix-select-content-available-height] min-w-[8rem] origin-[--radix-select-content-transform-origin] overflow-y-auto overflow-x-hidden rounded-md border shadow-md', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tailwind arbitrary values using CSS variables should be wrapped in var(...); use max-h-[var(--radix-select-content-available-height)] and origin-[var(--radix-select-content-transform-origin)] to ensure valid CSS.
Prompt for AI agents
Address the following comment on apps/mail/components/ui/select.tsx at line 71:
<comment>Tailwind arbitrary values using CSS variables should be wrapped in var(...); use max-h-[var(--radix-select-content-available-height)] and origin-[var(--radix-select-content-transform-origin)] to ensure valid CSS.</comment>
<file context>
@@ -63,7 +68,7 @@ const SelectContent = React.forwardRef<
ref={ref}
className={cn(
- 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-32 origin-(--radix-select-content-transform-origin) overflow-y-auto overflow-x-hidden rounded-md border shadow-md',
+ 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-[--radix-select-content-available-height] min-w-[8rem] origin-[--radix-select-content-transform-origin] overflow-y-auto overflow-x-hidden rounded-md border shadow-md',
position === 'popper' &&
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
</file context>
| 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-[--radix-select-content-available-height] min-w-[8rem] origin-[--radix-select-content-transform-origin] overflow-y-auto overflow-x-hidden rounded-md border shadow-md', | |
| 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-[var(--radix-select-content-available-height)] min-w-[8rem] origin-[var(--radix-select-content-transform-origin)] overflow-y-auto overflow-x-hidden rounded-md border shadow-md', |
| orientation = 'horizontal', | ||
| decorative = true, | ||
| ...props | ||
| }: React.ComponentProps<typeof SeparatorPrimitive.Root>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Props type includes ref even though this component does not support refs; use ComponentPropsWithoutRef to align types and avoid confusion.
Prompt for AI agents
Address the following comment on apps/mail/components/ui/separator.tsx at line 13:
<comment>Props type includes ref even though this component does not support refs; use ComponentPropsWithoutRef to align types and avoid confusion.</comment>
<file context>
@@ -1,24 +1,28 @@
+ orientation = 'horizontal',
+ decorative = true,
+ ...props
+}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
+ return (
+ <SeparatorPrimitive.Root
</file context>
| }: React.ComponentProps<typeof SeparatorPrimitive.Root>) { | |
| }: React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>) { |
| orientation={orientation} | ||
| className={cn( | ||
| 'bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=vertical]:h-full data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px', | ||
| className, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
data-[orientation] size classes have higher specificity than consumer classes (e.g., h-6), blocking overrides; vertical separators will ignore custom heights like in create/toolbar.
Prompt for AI agents
Address the following comment on apps/mail/components/ui/separator.tsx at line 20:
<comment>data-[orientation] size classes have higher specificity than consumer classes (e.g., h-6), blocking overrides; vertical separators will ignore custom heights like in create/toolbar.</comment>
<file context>
@@ -1,24 +1,28 @@
+ decorative={decorative}
+ orientation={orientation}
+ className={cn(
+ 'bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=vertical]:h-full data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px',
+ className,
+ )}
</file context>
fixes #1891
Description
Updated shadcn/ui components to the latest version with modern import patterns and fixed several UI issues. Changed from legacy
import { Component as ComponentPrimitive } from 'radix-ui'toimport * as ComponentPrimitive from "@radix-ui/react-component"across all UI components. Fixed the create email component backdrop blur functionality and added tooltip support for keyboard shortcuts. Preserved custom modifications in complex components like the calendar while updating the core component structure.Type of Change
Areas Affected
Testing Done
Security Considerations
Checklist
Additional Notes
This migration addresses the outdated shadcn components throughout the codebase. Key improvements include fixing the dialogue backdrop blur issue in the create email component and adding proper tooltip functionality for keyboard shortcuts. Components with extensive customisations (like the calendar) were carefully preserved while updating the underlying primitives. The new import pattern offers improved tree-shaking and enhanced TypeScript support.
Screenshots/Recordings
By submitting this pull request, I confirm that my contribution is made under the terms of the project's license.
Summary by cubic
Migrated all shadcn/ui components to the latest version with modern Radix imports for better a11y, focus states, and consistency. Removed the legacy radix-ui package and fixed overlay/backdrop issues (e.g., Dialog, Drawer).
Refactors
Migration
Summary by CodeRabbit
Style
Refactor
Chores