-
Notifications
You must be signed in to change notification settings - Fork 1
Feature/tailwind update v4 #100
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
Conversation
- 在jest.setup.js中,增加对登录和注册错误的处理,以便更好地抑制预期的错误信息。 - 在register.test.ts中,修改密码测试用例,使用一个实际过短的密码进行验证。 - 在ProfileForm.test.tsx中,优化MockNiceAvatar组件,确保不将不必要的属性传递给DOM元素。 -->跑通所有test
- 在package.json中添加了@tailwindcss/postcss依赖,并更新了tailwindcss版本至4.1.7。 - 修改postcss.config.js以使用@tailwindcss/postcss插件替代原有的tailwindcss和autoprefixer配置。 - 更新globals.css以引入tailwindcss,并定义了一系列CSS变量以便于主题管理。 - 在tailwind.config.js中移除了冗余的主题扩展配置,简化了配置文件。
- 在frontend.mdc中更新了Tailwind CSS版本为v4,并修正了相关描述。 - 在ui.mdc中调整了CSS变量的定义,确保所有token仅在globals.css中定义。 - 在package.json中添加了多个@radix-ui组件库的依赖,增强了UI组件的功能。 - 新增了多个UI组件,包括日历、复选框、可折叠面板等,丰富了前端功能。 - 更新了多个现有组件的实现,提升了代码的可读性和一致性。 - 在utils.ts中优化了错误处理逻辑,增强了代码的健壮性。
WalkthroughThis update introduces a comprehensive overhaul of the frontend UI system. It replaces most React.forwardRef components with plain function components, adds new UI primitives (calendar, checkbox, collapsible, etc.), and restructures global CSS for Tailwind v4 compatibility. The Tailwind config is simplified, new dependencies are added, and documentation is updated for clarity and accuracy. Changes
Sequence Diagram(s)sequenceDiagram
participant App
participant UIComponent
participant Primitive
participant DOM
App->>UIComponent: Render with props
UIComponent->>Primitive: Pass props, add data-slot, merge className
Primitive->>DOM: Render styled element
sequenceDiagram
participant App
participant useIsMobile
participant Window
App->>useIsMobile: Call hook
useIsMobile->>Window: Add media query listener
Window-->>useIsMobile: On resize, update isMobile state
useIsMobile-->>App: Return isMobile boolean
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Qodo Merge was enabled for this repository. To continue using it, please link your Git account with your Qodo account here. PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
PR Review 🔍
|
Qodo Merge was enabled for this repository. To continue using it, please link your Git account with your Qodo account here. PR Code Suggestions ✨Explore these optional code suggestions:
|
PR Code Suggestions ✨
|
CI Feedback 🧐(Feedback updated until commit ff070a6)A test triggered by this PR failed. Here is an AI-generated analysis of the failure:
|
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: 19
♻️ Duplicate comments (3)
frontend/components/ui/dialog.tsx (1)
27-31
: Same ref-forwarding concern
DialogClose
,DialogTrigger
, etc. expose a prop type that includesref
but don’t forward it. Apply the same fix suggested fordrawer.tsx
.frontend/components/ui/sheet.tsx (1)
47-56
: Missingref
forwarding (again)
SheetContent
often needs a ref (e.g. to trap focus). ApplyforwardRef
as noted for other components.frontend/components/ui/dropdown-menu.tsx (1)
233-235
: Repeat of invalid CSS-var syntax in SubContentThe same
origin-(--radix-dropdown-menu-content-transform-origin)
issue appears here; please apply the fix globally.
🧹 Nitpick comments (18)
frontend/hooks/use-mobile.ts (3)
6-8
: Consider initializing state usingwindow.matchMedia
to prevent hydration mismatches
InitializingisMobile
asundefined
then coercing tofalse
(!!isMobile
) may cause a flash of incorrect layout on the client or SSR hydration warnings. You can derive the initial state directly fromwindow.matchMedia
when available, falling back tofalse
on the server:- const [isMobile, setIsMobile] = React.useState<boolean | undefined>( - undefined, - ); + const [isMobile, setIsMobile] = React.useState<boolean>(() => + typeof window !== "undefined" + ? window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`).matches + : false + );
12-14
: Use the event’smatches
property instead ofwindow.innerWidth
Inside your change handler, prefer readingevent.matches
for consistency with the media query:- const onChange = () => { - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); - }; + const onChange = (e: MediaQueryListEvent) => { + setIsMobile(e.matches); + };
20-21
: Remove unnecessary double negation in return
SinceisMobile
is now always a boolean, you can return it directly instead of coercing again:- return !!isMobile; + return isMobile;frontend/components/ui/toggle-group.tsx (1)
58-65
: Consider breaking down the complex className string for readability.The className composition is functionally correct but the inline string is quite long and hard to read. Consider extracting the base classes to improve maintainability.
+const toggleGroupItemClasses = [ + "min-w-0 flex-1 shrink-0 rounded-none shadow-none", + "first:rounded-l-md last:rounded-r-md", + "focus:z-10 focus-visible:z-10", + "data-[variant=outline]:border-l-0 data-[variant=outline]:first:border-l" +].join(" "); className={cn( toggleVariants({ variant: context.variant || variant, size: context.size || size, }), - "min-w-0 flex-1 shrink-0 rounded-none shadow-none first:rounded-l-md last:rounded-r-md focus:z-10 focus-visible:z-10 data-[variant=outline]:border-l-0 data-[variant=outline]:first:border-l", + toggleGroupItemClasses, className, )}frontend/components/ui/toggle.tsx (1)
10-10
: Consider breaking down the long base classes string for maintainability.The base classes string is comprehensive but quite long (300+ characters), making it harder to read and maintain. Consider splitting it into logical groups.
const toggleVariants = cva( - "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap", + [ + // Base layout and typography + "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap", + // Interactive states + "hover:bg-muted hover:text-muted-foreground", + "disabled:pointer-events-none disabled:opacity-50", + "data-[state=on]:bg-accent data-[state=on]:text-accent-foreground", + // Focus and validation states + "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none", + "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + // SVG styling and transitions + "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0", + "transition-[color,box-shadow]" + ].join(" "),frontend/components/ui/label.tsx (1)
15-18
: Consider the flex layout implicationsThe new styling applies
flex items-center gap-2
which changes the label from inline to flex layout. This could affect existing layouts where labels are expected to behave as inline elements.Consider making the flex layout conditional or providing a variant prop:
- "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", + "text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",Or add a variant system for different layout modes.
frontend/components/ui/input.tsx (1)
11-15
: Comprehensive but potentially conflicting CSS classesThe styling is very comprehensive with file input styles, selection colors, and various states. However, having multiple
focus-visible
declarations and complex class combinations might lead to specificity issues.Consider organizing the classes for better maintainability:
className={cn( - "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none 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", + // Base styles + "flex h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs outline-none transition-[color,box-shadow] md:text-sm", + // Dark mode + "dark:bg-input/30", + // Placeholder and selection + "placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground", + // File input specific + "file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground", + // Focus states + "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", + // Invalid states + "aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40", + // Disabled states + "disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50", className, )}frontend/components/ui/resizable.tsx (1)
31-54
: Consider improving readability of complex class string.The ResizableHandle component is well-implemented with proper orientation handling and accessibility features. However, the class string on lines 41-43 is quite complex and could benefit from being broken down for better maintainability.
Consider extracting the orientation-specific classes into separate variables:
+const baseHandleClasses = "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:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden"; +const verticalHandleClasses = "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={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:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden 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", + baseHandleClasses, + verticalHandleClasses, className, )}frontend/components/ui/tabs.tsx (1)
37-51
: Consider improving readability of complex TabsTrigger styling.The TabsTrigger component is well-implemented with comprehensive state handling, but the class string on lines 44-46 is quite complex and could benefit from being broken down for better maintainability.
Consider extracting state-specific classes into separate variables:
+const baseTriggerClasses = "inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"; +const activeTriggerClasses = "data-[state=active]:bg-background dark:data-[state=active]:text-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 data-[state=active]:shadow-sm"; +const focusTriggerClasses = "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring focus-visible:ring-[3px] focus-visible:outline-1"; +const colorClasses = "text-foreground dark:text-muted-foreground"; className={cn( - "data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + baseTriggerClasses, + activeTriggerClasses, + focusTriggerClasses, + colorClasses, className, )}frontend/components/ui/card.tsx (1)
84-92
: Consider export order consistency.The CardAction component is exported in the middle of the list rather than with other layout components (CardHeader, CardFooter). Consider grouping related components together.
export { Card, CardHeader, + CardAction, CardFooter, CardTitle, - CardAction, CardDescription, CardContent, };frontend/components/ui/command.tsx (1)
56-76
: Decorative icon should be hidden from assistive tech
SearchIcon
is purely visual. Addaria-hidden
andfocusable="false"
so it is ignored by screen-readers and not tabbable in Safari.-<SearchIcon className="size-4 shrink-0 opacity-50" /> +<SearchIcon + className="size-4 shrink-0 opacity-50" + aria-hidden="true" + focusable="false" />frontend/app/globals.css (1)
399-406
: Duplicate@layer base
block – unnecessary bloatLines 280-305 already define identical body/element styles; this second
@layer base
block duplicates them. Apart from extra bytes, double
rules may confuse future maintainers.Consider deleting the block starting at line 399.
frontend/components/ui/drawer.tsx (2)
58-66
: Hard-coded spacing & duplicate responsive rulesThe composite class list is huge and mixes behaviour (animation), layout and design tokens.
Consider extracting the directional sizing rules into a small helper (variantClasses[direction]
) to keep the JSX readable and avoid accidental duplication (max-h-[80vh]
appears twice).Refactoring pays off quickly when the design system evolves.
68-70
: Potential a11y issue – handle bar lacksrole
The decorative handle for bottom drawers could be announced by screen readers as “group” with no purpose. Add
aria-hidden="true"
to ensure it’s ignored.-<div className="bg-muted … group-data-[vaul-drawer-direction=bottom]/drawer-content:block" /> +<div + aria-hidden="true" + className="bg-muted … group-data-[vaul-drawer-direction=bottom]/drawer-content:block" />frontend/components/ui/select.tsx (1)
108-113
: Over-engineered selector syntax
*:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex …
is very hard to read and maintain.
Consider extracting these rules into a scoped CSS layer (e.g. using@layer components
) or at least grouping them withclsx
helpers.This will reduce the chance of class name typos and improve diff readability.
frontend/components/ui/dialog.tsx (1)
65-70
: Close button isn’t keyboard-focus visibleThe
<DialogPrimitive.Close>
element hasopacity-70
and changes opacity only on hover. Users navigating with keyboard might not realise it’s focused.Add a distinct focus style, e.g.:
- className="ring-offset-background … opacity-70 transition-opacity hover:opacity-100 focus:ring-2 … + className="ring-offset-background … opacity-70 transition-opacity hover:opacity-100 focus:opacity-100 focus:ring-2 …frontend/components/ui/sheet.tsx (1)
61-71
: Animation utility duplication & readabilityThe
className
block duplicates state/side animation utilities already provided by Radix (data-motion
). Extracting to a helper or mapping object would:
- Remove the long ternaries inside JSX.
- Prevent mismatched variants (e.g. someone edits right/left but forgets top/bottom).
Example:
const sideClasses = { right: "data-[state=closed]:slide-out-to-right …", left: "data-[state=closed]:slide-out-to-left …", top: "data-[state=closed]:slide-out-to-top …", bottom:"data-[state=closed]:slide-out-to-bottom …", }; … className={cn(base, sideClasses[side], className)}frontend/components/ui/sidebar.tsx (1)
86-87
: Cookie is written but never read
SidebarProvider
persists the sidebar state in a cookie (sidebar_state
) but the initial state on page load is alwaysdefaultOpen
. Consider reading the cookie on mount to honour the user’s previous choice:-const [_open, _setOpen] = React.useState(defaultOpen); +const [_open, _setOpen] = React.useState(() => { + const match = document.cookie.match(/(?:^|; )sidebar_state=(true|false)/); + return match ? match[1] === "true" : defaultOpen; +});This keeps UX consistent across sessions.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
frontend/pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (48)
.cursor/rules/frontend.mdc
(1 hunks).cursor/rules/ui.mdc
(2 hunks)frontend/__tests__/components/ProfileForm.test.tsx
(1 hunks)frontend/__tests__/register.test.ts
(1 hunks)frontend/app/customers/page.tsx
(2 hunks)frontend/app/globals.css
(1 hunks)frontend/components.json
(1 hunks)frontend/components/ui/alert.tsx
(2 hunks)frontend/components/ui/badge.tsx
(2 hunks)frontend/components/ui/breadcrumb.tsx
(1 hunks)frontend/components/ui/button.tsx
(2 hunks)frontend/components/ui/calendar.tsx
(1 hunks)frontend/components/ui/card.tsx
(1 hunks)frontend/components/ui/checkbox.tsx
(1 hunks)frontend/components/ui/collapsible.tsx
(1 hunks)frontend/components/ui/command.tsx
(1 hunks)frontend/components/ui/dialog.tsx
(1 hunks)frontend/components/ui/drawer.tsx
(1 hunks)frontend/components/ui/dropdown-menu.tsx
(1 hunks)frontend/components/ui/hover-card.tsx
(1 hunks)frontend/components/ui/input.tsx
(1 hunks)frontend/components/ui/label.tsx
(1 hunks)frontend/components/ui/menubar.tsx
(1 hunks)frontend/components/ui/navigation-menu.tsx
(2 hunks)frontend/components/ui/pagination.tsx
(1 hunks)frontend/components/ui/popover.tsx
(1 hunks)frontend/components/ui/progress.tsx
(1 hunks)frontend/components/ui/resizable.tsx
(1 hunks)frontend/components/ui/scroll-area.tsx
(1 hunks)frontend/components/ui/select.tsx
(1 hunks)frontend/components/ui/separator.tsx
(1 hunks)frontend/components/ui/sheet.tsx
(1 hunks)frontend/components/ui/sidebar.tsx
(8 hunks)frontend/components/ui/skeleton.tsx
(1 hunks)frontend/components/ui/sonner.tsx
(2 hunks)frontend/components/ui/switch.tsx
(1 hunks)frontend/components/ui/table.tsx
(1 hunks)frontend/components/ui/tabs.tsx
(1 hunks)frontend/components/ui/textarea.tsx
(1 hunks)frontend/components/ui/toggle-group.tsx
(1 hunks)frontend/components/ui/toggle.tsx
(1 hunks)frontend/components/ui/tooltip.tsx
(1 hunks)frontend/hooks/use-mobile.ts
(1 hunks)frontend/jest.setup.js
(2 hunks)frontend/lib/utils.ts
(1 hunks)frontend/package.json
(5 hunks)frontend/postcss.config.js
(1 hunks)frontend/tailwind.config.js
(0 hunks)
💤 Files with no reviewable changes (1)
- frontend/tailwind.config.js
🧰 Additional context used
🧬 Code Graph Analysis (31)
frontend/components/ui/skeleton.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/switch.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/label.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/toggle.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/scroll-area.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/resizable.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/button.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/textarea.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/input.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/badge.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/popover.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/tooltip.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/separator.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/checkbox.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/drawer.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/select.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/dialog.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/hover-card.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/toggle-group.tsx (2)
frontend/components/ui/toggle.tsx (1)
toggleVariants
(47-47)frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/progress.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/table.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/calendar.tsx (2)
frontend/lib/utils.ts (1)
cn
(4-6)frontend/components/ui/button.tsx (1)
buttonVariants
(59-59)
frontend/components/ui/tabs.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/menubar.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/alert.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/navigation-menu.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/breadcrumb.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/card.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/pagination.tsx (2)
frontend/lib/utils.ts (1)
cn
(4-6)frontend/components/ui/button.tsx (2)
Button
(59-59)buttonVariants
(59-59)
frontend/components/ui/sheet.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
frontend/components/ui/dropdown-menu.tsx (1)
frontend/lib/utils.ts (1)
cn
(4-6)
🪛 Biome (1.9.4)
frontend/app/globals.css
[error] 162-162: expected ,
but instead found .5
Remove .5
(parse)
[error] 162-162: expected ,
but instead found :
Remove :
(parse)
[error] 162-162: Unexpected value or character.
Expected one of:
(parse)
[error] 162-162: expected ,
but instead found rem
Remove rem
(parse)
[error] 162-162: expected ,
but instead found ;
Remove ;
(parse)
[error] 162-163: expected ,
but instead found --spacing-1
Remove --spacing-1
(parse)
[error] 163-163: Unexpected value or character.
Expected one of:
(parse)
[error] 163-163: expected ,
but instead found rem
Remove rem
(parse)
[error] 163-163: expected ,
but instead found ;
Remove ;
(parse)
[error] 163-164: expected ,
but instead found --spacing-1
Remove --spacing-1
(parse)
[error] 164-164: expected ,
but instead found .5
Remove .5
(parse)
[error] 164-164: expected ,
but instead found :
Remove :
(parse)
[error] 164-164: Unexpected value or character.
Expected one of:
(parse)
[error] 164-164: expected ,
but instead found rem
Remove rem
(parse)
[error] 164-164: expected ,
but instead found ;
Remove ;
(parse)
[error] 164-165: expected ,
but instead found --spacing-2
Remove --spacing-2
(parse)
[error] 165-165: Unexpected value or character.
Expected one of:
(parse)
[error] 165-165: expected ,
but instead found rem
Remove rem
(parse)
[error] 165-165: expected ,
but instead found ;
Remove ;
(parse)
[error] 165-166: expected ,
but instead found --spacing-2
Remove --spacing-2
(parse)
[error] 166-166: expected ,
but instead found .5
Remove .5
(parse)
[error] 166-166: expected ,
but instead found :
Remove :
(parse)
[error] 166-166: Unexpected value or character.
Expected one of:
(parse)
[error] 166-166: expected ,
but instead found rem
Remove rem
(parse)
[error] 166-166: expected ,
but instead found ;
Remove ;
(parse)
[error] 166-167: expected ,
but instead found --spacing-3
Remove --spacing-3
(parse)
[error] 167-167: Unexpected value or character.
Expected one of:
(parse)
[error] 167-167: expected ,
but instead found rem
Remove rem
(parse)
[error] 167-167: expected ,
but instead found ;
Remove ;
(parse)
[error] 167-168: expected ,
but instead found --spacing-3
Remove --spacing-3
(parse)
[error] 168-168: expected ,
but instead found .5
Remove .5
(parse)
[error] 168-168: expected ,
but instead found :
Remove :
(parse)
[error] 168-168: Unexpected value or character.
Expected one of:
(parse)
[error] 168-168: expected ,
but instead found rem
Remove rem
(parse)
[error] 168-168: expected ,
but instead found ;
Remove ;
(parse)
[error] 169-169: expected ,
but instead found --spacing-4
Remove --spacing-4
(parse)
[error] 169-169: Unexpected value or character.
Expected one of:
(parse)
[error] 169-169: expected ,
but instead found rem
Remove rem
(parse)
[error] 169-169: expected ,
but instead found ;
Remove ;
(parse)
[error] 170-170: expected ,
but instead found --spacing-5
Remove --spacing-5
(parse)
[error] 170-170: Unexpected value or character.
Expected one of:
(parse)
[error] 170-170: expected ,
but instead found rem
Remove rem
(parse)
[error] 170-170: expected ,
but instead found ;
Remove ;
(parse)
[error] 171-171: expected ,
but instead found --spacing-6
Remove --spacing-6
(parse)
[error] 171-171: Unexpected value or character.
Expected one of:
(parse)
[error] 171-171: expected ,
but instead found rem
Remove rem
(parse)
[error] 171-171: expected ,
but instead found ;
Remove ;
(parse)
[error] 172-172: expected ,
but instead found --spacing-7
Remove --spacing-7
(parse)
[error] 172-172: Unexpected value or character.
Expected one of:
(parse)
[error] 172-172: expected ,
but instead found rem
Remove rem
(parse)
[error] 172-172: expected ,
but instead found ;
Remove ;
(parse)
[error] 172-173: expected ,
but instead found --spacing-8
Remove --spacing-8
(parse)
[error] 173-173: Unexpected value or character.
Expected one of:
(parse)
[error] 173-173: expected ,
but instead found rem
Remove rem
(parse)
[error] 173-173: expected ,
but instead found ;
Remove ;
(parse)
[error] 173-174: expected ,
but instead found --spacing-9
Remove --spacing-9
(parse)
[error] 174-174: Unexpected value or character.
Expected one of:
(parse)
[error] 174-174: expected ,
but instead found rem
Remove rem
(parse)
[error] 174-174: expected ,
but instead found ;
Remove ;
(parse)
[error] 174-175: expected ,
but instead found --spacing-10
Remove --spacing-10
(parse)
[error] 175-175: Unexpected value or character.
Expected one of:
(parse)
[error] 175-175: expected ,
but instead found rem
Remove rem
(parse)
[error] 175-175: expected ,
but instead found ;
Remove ;
(parse)
[error] 176-176: expected ,
but instead found --spacing-11
Remove --spacing-11
(parse)
[error] 176-176: Unexpected value or character.
Expected one of:
(parse)
[error] 176-176: expected ,
but instead found rem
Remove rem
(parse)
[error] 176-177: expected ,
but instead found ;
Remove ;
(parse)
[error] 177-177: expected ,
but instead found --spacing-12
Remove --spacing-12
(parse)
[error] 177-177: Unexpected value or character.
Expected one of:
(parse)
[error] 177-177: expected ,
but instead found rem
Remove rem
(parse)
[error] 177-178: expected ,
but instead found ;
Remove ;
(parse)
[error] 178-178: expected ,
but instead found --spacing-14
Remove --spacing-14
(parse)
[error] 178-178: Unexpected value or character.
Expected one of:
(parse)
[error] 178-179: expected ,
but instead found rem
Remove rem
(parse)
[error] 179-179: expected ,
but instead found ;
Remove ;
(parse)
[error] 179-179: expected ,
but instead found --spacing-16
Remove --spacing-16
(parse)
[error] 179-179: Unexpected value or character.
Expected one of:
(parse)
[error] 179-180: expected ,
but instead found rem
Remove rem
(parse)
[error] 180-180: expected ,
but instead found ;
Remove ;
(parse)
[error] 180-180: expected ,
but instead found --spacing-20
Remove --spacing-20
(parse)
[error] 180-180: Unexpected value or character.
Expected one of:
(parse)
[error] 180-181: expected ,
but instead found rem
Remove rem
(parse)
[error] 181-181: expected ,
but instead found ;
Remove ;
(parse)
[error] 181-181: expected ,
but instead found --spacing-24
Remove --spacing-24
(parse)
[error] 181-181: Unexpected value or character.
Expected one of:
(parse)
[error] 181-182: expected ,
but instead found rem
Remove rem
(parse)
[error] 182-182: expected ,
but instead found ;
Remove ;
(parse)
[error] 182-182: expected ,
but instead found --spacing-28
Remove --spacing-28
(parse)
[error] 182-182: Unexpected value or character.
Expected one of:
(parse)
[error] 182-182: expected ,
but instead found rem
Remove rem
(parse)
[error] 182-183: expected ,
but instead found ;
Remove ;
(parse)
[error] 183-183: expected ,
but instead found --spacing-32
Remove --spacing-32
(parse)
[error] 183-183: Unexpected value or character.
Expected one of:
(parse)
[error] 183-183: expected ,
but instead found rem
Remove rem
(parse)
[error] 183-183: expected ,
but instead found ;
Remove ;
(parse)
[error] 184-184: expected ,
but instead found --spacing-36
Remove --spacing-36
(parse)
[error] 184-184: Unexpected value or character.
Expected one of:
(parse)
[error] 184-184: expected ,
but instead found rem
Remove rem
(parse)
[error] 184-184: expected ,
but instead found ;
Remove ;
(parse)
[error] 185-185: expected ,
but instead found --spacing-40
Remove --spacing-40
(parse)
[error] 185-185: Unexpected value or character.
Expected one of:
(parse)
[error] 185-185: expected ,
but instead found rem
Remove rem
(parse)
[error] 185-185: expected ,
but instead found ;
Remove ;
(parse)
[error] 186-186: expected ,
but instead found --spacing-44
Remove --spacing-44
(parse)
[error] 186-186: Unexpected value or character.
Expected one of:
(parse)
[error] 186-186: expected ,
but instead found rem
Remove rem
(parse)
[error] 186-186: expected ,
but instead found ;
Remove ;
(parse)
[error] 187-187: expected ,
but instead found --spacing-48
Remove --spacing-48
(parse)
[error] 187-187: Unexpected value or character.
Expected one of:
(parse)
[error] 187-187: expected ,
but instead found rem
Remove rem
(parse)
[error] 187-187: expected ,
but instead found ;
Remove ;
(parse)
[error] 188-188: expected ,
but instead found --spacing-52
Remove --spacing-52
(parse)
[error] 188-188: Unexpected value or character.
Expected one of:
(parse)
[error] 188-188: expected ,
but instead found rem
Remove rem
(parse)
[error] 188-188: expected ,
but instead found ;
Remove ;
(parse)
[error] 189-189: expected ,
but instead found --spacing-56
Remove --spacing-56
(parse)
[error] 189-189: Unexpected value or character.
Expected one of:
(parse)
[error] 189-189: expected ,
but instead found rem
Remove rem
(parse)
[error] 189-189: expected ,
but instead found ;
Remove ;
(parse)
[error] 190-190: expected ,
but instead found --spacing-60
Remove --spacing-60
(parse)
[error] 190-190: Unexpected value or character.
Expected one of:
(parse)
[error] 190-190: expected ,
but instead found rem
Remove rem
(parse)
[error] 190-190: expected ,
but instead found ;
Remove ;
(parse)
[error] 192-192: expected ,
but instead found --spacing-64
Remove --spacing-64
(parse)
[error] 192-192: Unexpected value or character.
Expected one of:
(parse)
[error] 192-192: expected ,
but instead found rem
Remove rem
(parse)
[error] 192-192: expected ,
but instead found ;
Remove ;
(parse)
[error] 192-193: expected ,
but instead found --spacing-72
Remove --spacing-72
(parse)
[error] 193-193: Unexpected value or character.
Expected one of:
(parse)
[error] 193-193: expected ,
but instead found rem
Remove rem
(parse)
[error] 193-193: expected ,
but instead found ;
Remove ;
(parse)
[error] 193-193: expected ,
but instead found --spacing-80
Remove --spacing-80
(parse)
[error] 193-193: Unexpected value or character.
Expected one of:
(parse)
[error] 193-193: expected ,
but instead found rem
Remove rem
(parse)
[error] 193-193: expected ,
but instead found ;
Remove ;
(parse)
[error] 193-194: expected ,
but instead found --spacing-96
Remove --spacing-96
(parse)
[error] 194-194: Unexpected value or character.
Expected one of:
(parse)
[error] 194-194: expected ,
but instead found rem
Remove rem
(parse)
[error] 194-194: expected ,
but instead found ;
Remove ;
(parse)
[error] 195-196: expected ,
but instead found --radius-sm
Remove --radius-sm
(parse)
[error] 196-196: expected ,
but instead found (
Remove (
(parse)
[error] 196-196: expected ,
but instead found var
Remove var
(parse)
[error] 196-196: expected ,
but instead found (
Remove (
(parse)
[error] 196-196: expected ,
but instead found --radius
Remove --radius
(parse)
[error] 196-196: expected ,
but instead found )
Remove )
(parse)
[error] 196-196: expected ,
but instead found px
Remove px
(parse)
[error] 196-196: expected ,
but instead found )
Remove )
(parse)
[error] 196-197: expected ,
but instead found --radius-md
Remove --radius-md
(parse)
[error] 197-197: expected ,
but instead found (
Remove (
(parse)
[error] 197-197: expected ,
but instead found var
Remove var
(parse)
[error] 197-197: expected ,
but instead found (
Remove (
(parse)
[error] 197-197: expected ,
but instead found --radius
Remove --radius
(parse)
[error] 197-197: expected ,
but instead found )
Remove )
(parse)
[error] 199-199: expected ,
but instead found px
Remove px
(parse)
[error] 199-199: expected ,
but instead found )
Remove )
(parse)
[error] 199-200: expected ,
but instead found --radius-lg
Remove --radius-lg
(parse)
[error] 200-200: expected ,
but instead found (
Remove (
(parse)
[error] 200-200: expected ,
but instead found --radius
Remove --radius
(parse)
[error] 200-200: expected ,
but instead found )
Remove )
(parse)
[error] 200-200: expected ,
but instead found --radius-xl
Remove --radius-xl
(parse)
[error] 200-200: expected ,
but instead found (
Remove (
(parse)
[error] 200-200: expected ,
but instead found var
Remove var
(parse)
[error] 200-200: expected ,
but instead found (
Remove (
(parse)
[error] 200-201: expected ,
but instead found --radius
Remove --radius
(parse)
[error] 201-201: expected ,
but instead found )
Remove )
(parse)
[error] 201-201: expected ,
but instead found +
Remove +
(parse)
[error] 201-201: Expected a relative selector but instead found '4'.
Expected a relative selector here.
(parse)
[error] 201-201: expected ,
but instead found px
Remove px
(parse)
[error] 201-201: expected ,
but instead found )
Remove )
(parse)
[error] 201-201: expected ,
but instead found --radius-full
Remove --radius-full
(parse)
[error] 201-201: Unexpected value or character.
Expected one of:
(parse)
[error] 201-201: expected ,
but instead found px
Remove px
(parse)
[error] 201-201: expected ,
but instead found ;
Remove ;
(parse)
[error] 201-201: expected ,
but instead found --shadow-sm
Remove --shadow-sm
(parse)
[error] 201-201: Unexpected value or character.
Expected one of:
(parse)
[error] 202-202: expected ,
but instead found px
Remove px
(parse)
[error] 202-202: Expected a compound selector but instead found '2'.
Expected a compound selector here.
(parse)
[error] 202-202: expected ,
but instead found px
Remove px
(parse)
[error] 202-202: Expected a compound selector but instead found '0'.
Expected a compound selector here.
(parse)
[error] 202-202: expected ,
but instead found rgb
Remove rgb
(parse)
[error] 202-202: expected ,
but instead found (
Remove (
(parse)
[error] 202-202: expected ,
but instead found --shadow
Remove --shadow
(parse)
[error] 202-202: Unexpected value or character.
Expected one of:
(parse)
[error] 202-202: expected ,
but instead found px
Remove px
(parse)
[error] 202-202: Expected a compound selector but instead found '3'.
Expected a compound selector here.
(parse)
[error] 202-202: expected ,
but instead found px
Remove px
(parse)
[error] 202-202: Expected a compound selector but instead found '0'.
Expected a compound selector here.
(parse)
[error] 202-202: expected ,
but instead found rgb
Remove rgb
(parse)
[error] 202-202: expected ,
but instead found (
Remove (
(parse)
[error] 202-202: Expected a relative selector but instead found '0 1'.
Expected a relative selector here.
(parse)
[error] 202-202: expected ,
but instead found px
Remove px
(parse)
[error] 202-202: Expected a compound selector but instead found '2'.
Expected a compound selector here.
(parse)
[error] 202-202: expected ,
but instead found px
Remove px
(parse)
[error] 202-203: Expected a compound selector but instead found '-1'.
Expected a compound selector here.
(parse)
[error] 203-203: expected ,
but instead found px
Remove px
(parse)
[error] 203-203: expected ,
but instead found (
Remove (
(parse)
[error] 203-203: expected ,
but instead found --shadow-md
Remove --shadow-md
(parse)
[error] 203-203: Unexpected value or character.
Expected one of:
(parse)
[error] 203-203: expected ,
but instead found px
Remove px
(parse)
[error] 203-203: Expected a compound selector but instead found '6'.
Expected a compound selector here.
(parse)
[error] 203-203: expected ,
but instead found px
Remove px
(parse)
[error] 203-203: Expected a compound selector but instead found '-1'.
Expected a compound selector here.
(parse)
[error] 203-203: expected ,
but instead found px
Remove px
(parse)
[error] 203-203: expected ,
but instead found (
Remove (
(parse)
[error] 203-203: Expected a relative selector but instead found '0 2'.
Expected a relative selector here.
(parse)
[error] 203-203: expected ,
but instead found px
Remove px
(parse)
[error] 203-203: Expected a compound selector but instead found '4'.
Expected a compound selector here.
(parse)
[error] 203-203: expected ,
but instead found px
Remove px
(parse)
[error] 203-203: Expected a compound selector but instead found '-2'.
Expected a compound selector here.
(parse)
[error] 203-204: expected ,
but instead found px
Remove px
(parse)
[error] 204-204: expected ,
but instead found (
Remove (
(parse)
[error] 204-204: expected ,
but instead found --shadow-lg
Remove --shadow-lg
(parse)
[error] 204-204: Unexpected value or character.
Expected one of:
(parse)
[error] 204-204: expected ,
but instead found px
Remove px
(parse)
[error] 204-204: Expected a compound selector but instead found '15'.
Expected a compound selector here.
(parse)
[error] 204-204: expected ,
but instead found px
Remove px
(parse)
[error] 204-204: Expected a compound selector but instead found '-3'.
Expected a compound selector here.
(parse)
[error] 204-204: expected ,
but instead found px
Remove px
(parse)
[error] 204-204: expected ,
but instead found (
Remove (
(parse)
[error] 204-204: Expected a relative selector but instead found '0 4'.
Expected a relative selector here.
(parse)
[error] 204-204: expected ,
but instead found px
Remove px
(parse)
[error] 204-204: Expected a compound selector but instead found '6'.
Expected a compound selector here.
(parse)
[error] 204-204: expected ,
but instead found px
Remove px
(parse)
[error] 204-204: Expected a compound selector but instead found '-4'.
Expected a compound selector here.
(parse)
[error] 204-205: expected ,
but instead found px
Remove px
(parse)
[error] 205-205: expected ,
but instead found (
Remove (
(parse)
[error] 205-205: expected ,
but instead found --shadow-xl
Remove --shadow-xl
(parse)
[error] 205-205: Unexpected value or character.
Expected one of:
(parse)
[error] 205-205: expected ,
but instead found px
Remove px
(parse)
[error] 205-205: Expected a compound selector but instead found '25'.
Expected a compound selector here.
(parse)
[error] 205-205: expected ,
but instead found px
Remove px
(parse)
[error] 205-205: Expected a compound selector but instead found '-5'.
Expected a compound selector here.
(parse)
[error] 205-205: expected ,
but instead found px
Remove px
(parse)
[error] 206-206: expected ,
but instead found (
Remove (
(parse)
[error] 206-206: Expected a relative selector but instead found '0 8'.
Expected a relative selector here.
(parse)
[error] 206-206: expected ,
but instead found px
Remove px
(parse)
[error] 206-206: Expected a compound selector but instead found '10'.
Expected a compound selector here.
(parse)
[error] 206-206: expected ,
but instead found px
Remove px
(parse)
[error] 206-206: Expected a compound selector but instead found '-6'.
Expected a compound selector here.
(parse)
[error] 206-206: expected ,
but instead found px
Remove px
(parse)
[error] 206-206: expected ,
but instead found (
Remove (
(parse)
[error] 206-208: expected ,
but instead found --shadow-2xl
Remove --shadow-2xl
(parse)
[error] 208-208: Unexpected value or character.
Expected one of:
(parse)
[error] 208-208: expected ,
but instead found px
Remove px
(parse)
[error] 208-208: Expected a compound selector but instead found '50'.
Expected a compound selector here.
(parse)
[error] 208-208: expected ,
but instead found px
Remove px
(parse)
[error] 208-208: Expected a compound selector but instead found '-12'.
Expected a compound selector here.
(parse)
[error] 208-208: expected ,
but instead found px
Remove px
(parse)
[error] 209-209: expected ,
but instead found (
Remove (
(parse)
[error] 209-210: expected ,
but instead found --shadow-inner
Remove --shadow-inner
(parse)
[error] 210-210: Expected a compound selector but instead found '0'.
Expected a compound selector here.
(parse)
[error] 210-210: expected ,
but instead found px
Remove px
(parse)
[error] 210-210: Expected a compound selector but instead found '4'.
Expected a compound selector here.
(parse)
[error] 210-210: expected ,
but instead found px
Remove px
(parse)
[error] 210-210: Expected a compound selector but instead found '0'.
Expected a compound selector here.
(parse)
[error] 210-210: expected ,
but instead found rgb
Remove rgb
(parse)
[error] 210-210: expected ,
but instead found (
Remove (
(parse)
[error] 211-212: expected ,
but instead found --transition-duration-75
Remove --transition-duration-75
(parse)
[error] 212-212: Unexpected value or character.
Expected one of:
(parse)
[error] 212-212: expected ,
but instead found ms
Remove ms
(parse)
[error] 212-212: expected ,
but instead found ;
Remove ;
(parse)
[error] 212-213: expected ,
but instead found --transition-duration-100
Remove --transition-duration-100
(parse)
[error] 213-213: Unexpected value or character.
Expected one of:
(parse)
[error] 213-213: expected ,
but instead found ms
Remove ms
(parse)
[error] 213-213: expected ,
but instead found ;
Remove ;
(parse)
[error] 213-214: expected ,
but instead found --transition-duration-150
Remove --transition-duration-150
(parse)
[error] 214-214: Unexpected value or character.
Expected one of:
(parse)
[error] 214-214: expected ,
but instead found ms
Remove ms
(parse)
[error] 214-214: expected ,
but instead found ;
Remove ;
(parse)
[error] 214-215: expected ,
but instead found --transition-duration-200
Remove --transition-duration-200
(parse)
[error] 215-215: Unexpected value or character.
Expected one of:
(parse)
[error] 215-215: expected ,
but instead found ms
Remove ms
(parse)
[error] 215-215: expected ,
but instead found ;
Remove ;
(parse)
[error] 215-216: expected ,
but instead found --transition-duration-300
Remove --transition-duration-300
(parse)
[error] 216-216: Unexpected value or character.
Expected one of:
(parse)
[error] 216-216: expected ,
but instead found ms
Remove ms
(parse)
[error] 216-216: expected ,
but instead found ;
Remove ;
(parse)
[error] 216-219: expected ,
but instead found --transition-duration-500
Remove --transition-duration-500
(parse)
[error] 219-219: Unexpected value or character.
Expected one of:
(parse)
[error] 219-219: expected ,
but instead found ms
Remove ms
(parse)
[error] 219-219: expected ,
but instead found ;
Remove ;
(parse)
[error] 219-219: expected ,
but instead found --transition-duration-700
Remove --transition-duration-700
(parse)
[error] 219-219: Unexpected value or character.
Expected one of:
(parse)
[error] 219-220: expected ,
but instead found ms
Remove ms
(parse)
[error] 220-220: expected ,
but instead found ;
Remove ;
(parse)
[error] 220-220: expected ,
but instead found --transition-duration-1000
Remove --transition-duration-1000
(parse)
[error] 220-220: Unexpected value or character.
Expected one of:
(parse)
[error] 220-220: expected ,
but instead found ms
Remove ms
(parse)
[error] 220-220: expected ,
but instead found ;
Remove ;
(parse)
[error] 220-221: expected ,
but instead found --animate-spin
Remove --animate-spin
(parse)
[error] 221-221: Expected a compound selector but instead found '1'.
Expected a compound selector here.
(parse)
[error] 221-221: expected ,
but instead found s
Remove s
(parse)
[error] 221-221: expected ,
but instead found ;
Remove ;
(parse)
[error] 221-221: expected ,
but instead found --animate-ping
Remove --animate-ping
(parse)
[error] 221-221: Expected a compound selector but instead found '1'.
Expected a compound selector here.
(parse)
[error] 221-221: expected ,
but instead found s
Remove s
(parse)
[error] 222-222: expected ,
but instead found (
Remove (
(parse)
[error] 222-222: Expected a relative selector but instead found '0'.
Expected a relative selector here.
(parse)
[error] 222-222: Expected a relative selector but instead found '0.2'.
Expected a relative selector here.
(parse)
[error] 222-222: Expected a relative selector but instead found '1)'.
Expected a relative selector here.
(parse)
[error] 222-222: expected ,
but instead found infinite
Remove infinite
(parse)
[error] 222-222: expected ,
but instead found ;
Remove ;
(parse)
[error] 222-223: expected ,
but instead found --animate-pulse
Remove --animate-pulse
(parse)
[error] 223-223: Expected a compound selector but instead found '2'.
Expected a compound selector here.
(parse)
[error] 223-223: expected ,
but instead found s
Remove s
(parse)
[error] 223-223: expected ,
but instead found (
Remove (
(parse)
[error] 223-223: Expected a relative selector but instead found '0'.
Expected a relative selector here.
(parse)
[error] 223-223: Expected a relative selector but instead found '0.6'.
Expected a relative selector here.
(parse)
[error] 223-223: Expected a relative selector but instead found '1)'.
Expected a relative selector here.
(parse)
[error] 223-224: expected ,
but instead found infinite
Remove infinite
(parse)
[error] 224-224: expected ,
but instead found ;
Remove ;
(parse)
[error] 224-224: expected ,
but instead found --animate-bounce
Remove --animate-bounce
(parse)
[error] 224-224: Expected a compound selector but instead found '1'.
Expected a compound selector here.
(parse)
[error] 224-224: expected ,
but instead found s
Remove s
(parse)
[error] 224-224: expected ,
but instead found ;
Remove ;
(parse)
[error] 224-226: expected ,
but instead found --animate-accordion-down
Remove --animate-accordion-down
(parse)
[error] 227-227: Expected a compound selector but instead found '0.2'.
Expected a compound selector here.
(parse)
[error] 227-227: expected ,
but instead found s
Remove s
(parse)
[error] 228-228: expected ,
but instead found ;
Remove ;
(parse)
[error] 228-229: expected ,
but instead found --animate-accordion-up
Remove --animate-accordion-up
(parse)
[error] 229-229: Expected a compound selector but instead found '0.2'.
Expected a compound selector here.
(parse)
[error] 229-229: expected ,
but instead found s
Remove s
(parse)
[error] 230-230: expected ,
but instead found ;
Remove ;
(parse)
[error] 230-231: expected ,
but instead found --breakpoint-sm
Remove --breakpoint-sm
(parse)
[error] 231-231: Unexpected value or character.
Expected one of:
(parse)
[error] 231-231: expected ,
but instead found px
Remove px
(parse)
[error] 231-231: expected ,
but instead found ;
Remove ;
(parse)
[error] 231-233: expected ,
but instead found --breakpoint-md
Remove --breakpoint-md
(parse)
[error] 233-233: Unexpected value or character.
Expected one of:
(parse)
[error] 233-233: expected ,
but instead found px
Remove px
(parse)
[error] 233-233: expected ,
but instead found ;
Remove ;
(parse)
[error] 233-233: expected ,
but instead found --breakpoint-lg
Remove --breakpoint-lg
(parse)
[error] 233-233: Unexpected value or character.
Expected one of:
(parse)
[error] 233-233: expected ,
but instead found px
Remove px
(parse)
[error] 233-233: expected ,
but instead found ;
Remove ;
(parse)
[error] 233-233: expected ,
but instead found --breakpoint-xl
Remove --breakpoint-xl
(parse)
[error] 233-233: Unexpected value or character.
Expected one of:
(parse)
[error] 233-233: expected ,
but instead found px
Remove px
(parse)
[error] 233-233: expected ,
but instead found ;
Remove ;
(parse)
[error] 233-234: expected ,
but instead found --breakpoint-2xl
Remove --breakpoint-2xl
(parse)
[error] 234-234: Unexpected value or character.
Expected one of:
(parse)
[error] 234-234: expected ,
but instead found px
Remove px
(parse)
[error] 234-234: expected ,
but instead found ;
Remove ;
(parse)
[error] 241-242: expected ,
but instead found --color-background
Remove --color-background
(parse)
[error] 242-242: expected ,
but instead found (
Remove (
(parse)
[error] 242-242: expected ,
but instead found --background
Remove --background
(parse)
[error] 242-242: expected ,
but instead found )
Remove )
(parse)
[error] 243-243: expected ,
but instead found --color-foreground
Remove --color-foreground
(parse)
[error] 243-243: expected ,
but instead found (
Remove (
(parse)
[error] 243-243: expected ,
but instead found --foreground
Remove --foreground
(parse)
[error] 243-243: expected ,
but instead found )
Remove )
(parse)
[error] 243-243: expected ,
but instead found --color-card
Remove --color-card
(parse)
[error] 244-244: expected ,
but instead found (
Remove (
(parse)
[error] 244-244: expected ,
but instead found --card
Remove --card
(parse)
[error] 244-244: expected ,
but instead found )
Remove )
(parse)
[error] 244-245: expected ,
but instead found --color-card-foreground
Remove --color-card-foreground
(parse)
[error] 245-245: expected ,
but instead found (
Remove (
(parse)
[error] 245-245: expected ,
but instead found --card-foreground
Remove --card-foreground
(parse)
[error] 245-245: expected ,
but instead found )
Remove )
(parse)
[error] 245-245: expected ,
but instead found --color-popover
Remove --color-popover
(parse)
[error] 245-245: expected ,
but instead found (
Remove (
(parse)
[error] 245-246: expected ,
but instead found --popover
Remove --popover
(parse)
[error] 246-246: expected ,
but instead found )
Remove )
(parse)
[error] 246-246: expected ,
but instead found --color-popover-foreground
Remove --color-popover-foreground
(parse)
[error] 247-247: expected ,
but instead found (
Remove (
(parse)
[error] 247-247: expected ,
but instead found --popover-foreground
Remove --popover-foreground
(parse)
[error] 247-247: expected ,
but instead found )
Remove )
(parse)
[error] 247-247: expected ,
but instead found --color-primary
Remove --color-primary
(parse)
[error] 247-247: expected ,
but instead found (
Remove (
(parse)
[error] 247-247: expected ,
but instead found --primary
Remove --primary
(parse)
[error] 247-247: expected ,
but instead found )
Remove )
(parse)
[error] 248-248: expected ,
but instead found --color-primary-foreground
Remove --color-primary-foreground
(parse)
[error] 249-249: expected ,
but instead found (
Remove (
(parse)
[error] 249-249: expected ,
but instead found --primary-foreground
Remove --primary-foreground
(parse)
[error] 249-249: expected ,
but instead found )
Remove )
(parse)
[error] 249-249: expected ,
but instead found --color-secondary
Remove --color-secondary
(parse)
[error] 249-249: expected ,
but instead found (
Remove (
(parse)
[error] 249-250: expected ,
but instead found --secondary
Remove --secondary
(parse)
[error] 250-250: expected ,
but instead found )
Remove )
(parse)
[error] 250-251: expected ,
but instead found --color-secondary-foreground
Remove --color-secondary-foreground
(parse)
[error] 251-251: expected ,
but instead found (
Remove (
(parse)
[error] 251-251: expected ,
but instead found --secondary-foreground
Remove --secondary-foreground
(parse)
[error] 251-251: expected ,
but instead found )
Remove )
(parse)
[error] 251-251: expected ,
but instead found --color-muted
Remove --color-muted
(parse)
[error] 252-252: expected ,
but instead found (
Remove (
(parse)
[error] 252-252: expected ,
but instead found --muted
Remove --muted
(parse)
[error] 252-252: expected ,
but instead found )
Remove )
(parse)
[error] 252-252: expected ,
but instead found --color-muted-foreground
Remove --color-muted-foreground
(parse)
[error] 253-253: expected ,
but instead found (
Remove (
(parse)
[error] 253-253: expected ,
but instead found --muted-foreground
Remove --muted-foreground
(parse)
[error] 253-253: expected ,
but instead found )
Remove )
(parse)
[error] 253-253: expected ,
but instead found --color-accent
Remove --color-accent
(parse)
[error] 253-253: expected ,
but instead found (
Remove (
(parse)
[error] 253-253: expected ,
but instead found --accent
Remove --accent
(parse)
[error] 253-253: expected ,
but instead found )
Remove )
(parse)
[error] 253-254: expected ,
but instead found --color-accent-foreground
Remove --color-accent-foreground
(parse)
[error] 254-254: expected ,
but instead found (
Remove (
(parse)
[error] 254-255: expected ,
but instead found --accent-foreground
Remove --accent-foreground
(parse)
[error] 255-255: expected ,
but instead found )
Remove )
(parse)
[error] 255-256: expected ,
but instead found --color-destructive
Remove --color-destructive
(parse)
[error] 256-256: expected ,
but instead found (
Remove (
(parse)
[error] 256-256: expected ,
but instead found --destructive
Remove --destructive
(parse)
[error] 256-256: expected ,
but instead found )
Remove )
(parse)
[error] 256-259: expected ,
but instead found --color-destructive-foreground
Remove --color-destructive-foreground
(parse)
[error] 259-259: expected ,
but instead found (
Remove (
(parse)
[error] 259-260: expected ,
but instead found --destructive-foreground
Remove --destructive-foreground
(parse)
[error] 260-260: expected ,
but instead found )
Remove )
(parse)
[error] 260-260: expected ,
but instead found --color-border
Remove --color-border
(parse)
[error] 260-260: expected ,
but instead found (
Remove (
(parse)
[error] 260-261: expected ,
but instead found --border
Remove --border
(parse)
[error] 261-261: expected ,
but instead found )
Remove )
(parse)
[error] 261-261: expected ,
but instead found --color-input
Remove --color-input
(parse)
[error] 261-261: expected ,
but instead found (
Remove (
(parse)
[error] 261-261: expected ,
but instead found --input
Remove --input
(parse)
[error] 261-261: expected ,
but instead found )
Remove )
(parse)
[error] 262-262: expected ,
but instead found --color-ring
Remove --color-ring
(parse)
[error] 262-262: expected ,
but instead found (
Remove (
(parse)
[error] 262-262: expected ,
but instead found --ring
Remove --ring
(parse)
[error] 262-262: expected ,
but instead found )
Remove )
(parse)
[error] 263-263: expected ,
but instead found --color-chart-1
Remove --color-chart-1
(parse)
[error] 265-265: expected ,
but instead found (
Remove (
(parse)
[error] 265-265: expected ,
but instead found --chart-1
Remove --chart-1
(parse)
[error] 265-265: expected ,
but instead found )
Remove )
(parse)
[error] 265-266: expected ,
but instead found --color-chart-2
Remove --color-chart-2
(parse)
[error] 266-266: expected ,
but instead found (
Remove (
(parse)
[error] 266-266: expected ,
but instead found --chart-2
Remove --chart-2
(parse)
[error] 266-266: expected ,
but instead found )
Remove )
(parse)
[error] 266-267: expected ,
but instead found --color-chart-3
Remove --color-chart-3
(parse)
[error] 267-267: expected ,
but instead found (
Remove (
(parse)
[error] 267-267: expected ,
but instead found --chart-3
Remove --chart-3
(parse)
[error] 267-267: expected ,
but instead found )
Remove )
(parse)
[error] 267-267: expected ,
but instead found --color-chart-4
Remove --color-chart-4
(parse)
[error] 267-267: expected ,
but instead found (
Remove (
(parse)
[error] 267-268: expected ,
but instead found --chart-4
Remove --chart-4
(parse)
[error] 268-268: expected ,
but instead found )
Remove )
(parse)
[error] 268-268: expected ,
but instead found --color-chart-5
Remove --color-chart-5
(parse)
[error] 268-268: expected ,
but instead found (
Remove (
(parse)
[error] 268-268: expected ,
but instead found --chart-5
Remove --chart-5
(parse)
[error] 268-268: expected ,
but instead found )
Remove )
(parse)
[error] 269-269: expected ,
but instead found --color-sidebar
Remove --color-sidebar
(parse)
[error] 269-269: expected ,
but instead found (
Remove (
(parse)
[error] 269-269: expected ,
but instead found --sidebar
Remove --sidebar
(parse)
[error] 269-269: expected ,
but instead found )
Remove )
(parse)
[error] 269-270: expected ,
but instead found --color-sidebar-foreground
Remove --color-sidebar-foreground
(parse)
[error] 270-270: expected ,
but instead found (
Remove (
(parse)
[error] 270-270: expected ,
but instead found --sidebar-foreground
Remove --sidebar-foreground
(parse)
[error] 270-270: expected ,
but instead found )
Remove )
(parse)
[error] 270-271: expected ,
but instead found --color-sidebar-primary
Remove --color-sidebar-primary
(parse)
[error] 271-271: expected ,
but instead found (
Remove (
(parse)
[error] 271-271: expected ,
but instead found --sidebar-primary
Remove --sidebar-primary
(parse)
[error] 271-271: expected ,
but instead found )
Remove )
(parse)
[error] 271-271: expected ,
but instead found --color-sidebar-primary-foreground
Remove --color-sidebar-primary-foreground
(parse)
[error] 272-272: expected ,
but instead found (
Remove (
(parse)
[error] 272-272: expected ,
but instead found --sidebar-primary-foreground
Remove --sidebar-primary-foreground
(parse)
[error] 272-272: expected ,
but instead found )
Remove )
(parse)
[error] 272-273: expected ,
but instead found --color-sidebar-accent
Remove --color-sidebar-accent
(parse)
[error] 273-273: expected ,
but instead found (
Remove (
(parse)
[error] 273-273: expected ,
but instead found --sidebar-accent
Remove --sidebar-accent
(parse)
[error] 273-273: expected ,
but instead found )
Remove )
(parse)
[error] 273-276: expected ,
but instead found --color-sidebar-accent-foreground
Remove --color-sidebar-accent-foreground
(parse)
[error] 276-276: expected ,
but instead found (
Remove (
(parse)
[error] 276-276: expected ,
but instead found --sidebar-accent-foreground
Remove --sidebar-accent-foreground
(parse)
[error] 276-276: expected ,
but instead found )
Remove )
(parse)
[error] 276-277: expected ,
but instead found --color-sidebar-border
Remove --color-sidebar-border
(parse)
[error] 277-277: expected ,
but instead found (
Remove (
(parse)
[error] 277-278: expected ,
but instead found --sidebar-border
Remove --sidebar-border
(parse)
[error] 278-278: expected ,
but instead found )
Remove )
(parse)
[error] 278-278: expected ,
but instead found --color-sidebar-ring
Remove --color-sidebar-ring
(parse)
[error] 278-278: expected ,
but instead found (
Remove (
(parse)
[error] 278-278: expected ,
but instead found --sidebar-ring
Remove --sidebar-ring
(parse)
[error] 278-278: expected ,
but instead found )
Remove )
(parse)
[error] 289-290: expected ,
but instead found layer
Remove layer
(parse)
🔇 Additional comments (90)
frontend/postcss.config.js (1)
3-3
:✅ Verification successful
LGTM! Proper Tailwind v4 PostCSS configuration.
The consolidation from separate
tailwindcss
andautoprefixer
plugins to the unified@tailwindcss/postcss
plugin is correct for Tailwind CSS v4 migration. This new plugin handles both CSS processing and autoprefixing internally.Verify that the corresponding package.json changes are present:
🏁 Script executed:
#!/bin/bash # Description: Verify the package dependencies align with PostCSS config changes # Check if @tailwindcss/postcss is added and autoprefixer is removed echo "=== Checking package.json dependencies ===" if [ -f "frontend/package.json" ]; then echo "Dependencies with @tailwindcss/postcss:" cat frontend/package.json | jq '.devDependencies | with_entries(select(.key | contains("tailwindcss")))' echo -e "\nChecking if autoprefixer is removed:" if cat frontend/package.json | jq '.devDependencies | has("autoprefixer")' | grep -q true; then echo "⚠️ autoprefixer is still present in devDependencies" else echo "✅ autoprefixer correctly removed from devDependencies" fi else echo "⚠️ frontend/package.json not found" fiLength of output: 685
✅ Verified PostCSS configuration and dependencies align with Tailwind v4 migration
@tailwindcss/[email protected]
is present in devDependencies.autoprefixer
has been correctly removed.tailwindcss@^4.1.7
remains as expected for the core CLI package.All looks good to merge!
.cursor/rules/frontend.mdc (1)
9-9
: LGTM! Clear version specification for developer guidance.The explicit mention of "Tailwind(v4) CSS" provides clear guidance for developers and ensures they use the correct version that aligns with the project's migration to Tailwind CSS v4.
frontend/app/customers/page.tsx (2)
187-187
: LGTM! Appropriate variant change for success messages.Changing from "success" to "default" for the profile update success message aligns with the updated alert component variants and provides a more subtle visual treatment for success notifications.
167-167
:✅ Verification successful
LGTM! Improved semantic alert variant usage.
Changing from "warning" to "destructive" for the "not logged in" alert is semantically more appropriate, as this represents a blocking authentication issue rather than just a warning.
Verify that the "destructive" variant is properly defined in the alert component:
🏁 Script executed:
#!/bin/bash # Description: Verify alert component variants are properly defined # Check the alert component implementation echo "=== Checking Alert component variants ===" ast-grep --pattern 'const alertVariants = $_' frontend/components/ui/alert.tsx || ast-grep --pattern 'alertVariants = $_' frontend/components/ui/alert.tsxLength of output: 1265
Alert variants confirmed
I’ve verified in
frontend/components/ui/alert.tsx
thatalertVariants
only definedefault
anddestructive
. The switch from"warning"
to"destructive"
is valid, and changing the former"success"
alert to use the existing"default"
variant is necessary since a"success"
variant isn’t defined. No further changes needed.frontend/__tests__/register.test.ts (1)
63-63
: LGTM! Improved test accuracy and clarity.Changing the password from "invalid_password" to "123" makes the test more explicit about what validation rule is being tested (minimum 8 characters). The shorter password clearly triggers the length validation, making the test intention more obvious.
frontend/components.json (1)
20-20
: LGTM! Clean configuration addition for icon library standardization.The addition of
"iconLibrary": "lucide"
properly declares the icon library used throughout the UI components, supporting the migration to lucide-react icons mentioned in the PR summary..cursor/rules/ui.mdc (2)
14-15
: Documentation accurately reflects the new token architecture.The update correctly documents that design tokens now live exclusively in
globals.css
, which aligns with the Tailwind v4 migration where theme extensions were moved out oftailwind.config.js
.
24-24
: Improved component scanning specificity.Narrowing the scan path from
/components/**
to/components/ui/**
is more precise and aligns with the UI component restructuring mentioned in the PR summary.frontend/jest.setup.js (2)
121-123
: Good addition of registration error suppressions.The new error message suppressions for login and registration errors follow the established pattern and help maintain clean test output when these expected errors occur during testing.
132-132
: Comment accurately reflects the updated suppressions.The updated comment correctly includes registration errors alongside the existing login credential error suppressions.
frontend/components/ui/skeleton.tsx (3)
3-3
: Good type simplification for plain function component.The change from
React.HTMLAttributes<HTMLDivElement>
toReact.ComponentProps<"div">
is more concise and appropriate for a plain function component without ref forwarding.
6-6
: Excellent addition of data-slot attribute for easier targeting.The
data-slot="skeleton"
attribute follows the new pattern mentioned in the PR summary and enables easier DOM targeting and styling.
7-7
:✅ Verification successful
Verify the background color change aligns with design system.
The change from
bg-primary/10
tobg-accent
should be verified to ensure it maintains the intended visual appearance and aligns with the new Tailwind v4 design token system.
🏁 Script executed:
#!/bin/bash # Description: Check if bg-accent is properly defined in the new design system and find other skeleton usages echo "Checking for bg-accent definition in globals.css:" rg -A 3 -B 3 "accent" frontend/app/globals.css echo -e "\nChecking for other Skeleton component usages:" rg -A 2 -B 2 "Skeleton" frontend/Length of output: 4173
#!/bin/bash # Locate Tailwind config files and search for “accent” definitions echo "Finding Tailwind config files in the repo:" configs=$(fd tailwind.config* -t f) if [ -z "$configs" ]; then echo "No Tailwind config files found." exit 0 fi for cfg in $configs; do echo -e "\n>> File: $cfg" rg -n "accent" $cfg || echo " (No 'accent' reference found)" done
#!/bin/bash # Locate Tailwind config files and search for “accent” in theme.extend.colors configs=$(fd 'tailwind.config.(js|ts|cjs|mjs)' -t f) if [ -z "$configs" ]; then echo "No Tailwind config files found." exit 0 fi echo "Found Tailwind config file(s):" echo "$configs" for cfg in $configs; do echo -e "\n>> File: $cfg" rg -n "theme\s*:\s*{[^}]*extend\s*:\s*{[^}]*colors" -C 3 "$cfg" || echo " (No theme.extend.colors block found)" echo -e "\n>> Searching for ‘accent’ in colors definitions:" rg -n "accent" -C 2 "$cfg" || echo " (No ‘accent’ definition found)" done
Accent token confirmed in design system
The--accent
custom property (and its--color-accent
alias) is defined infrontend/app/globals.css
, sobg-accent
will resolve correctly. AllSkeleton
usages now uniformly rely on this token, and no other instances of the oldbg-primary/10
remain. No further changes needed.frontend/components/ui/sonner.tsx (2)
4-4
: LGTM: Clean import simplificationThe direct import of
ToasterProps
from "sonner" simplifies the import structure.
13-19
: LGTM: CSS variables approach improves theming flexibilityThe replacement of
toastOptions
with CSS custom properties using design system variables (--popover
,--popover-foreground
,--border
) is a good modernization. This approach provides better theming flexibility and aligns with the Tailwind v4 migration strategy.The TypeScript casting to
React.CSSProperties
is appropriate for custom CSS properties.frontend/components/ui/separator.tsx (3)
16-16
: LGTM: data-slot attribute improves component targetingAdding
data-slot="separator-root"
provides a consistent way to target this component in CSS or tests, which aligns with the broader refactoring pattern.
20-20
: LGTM: Consolidated CSS classes using data attributesThe consolidation of orientation-specific styling using
data-[orientation=...]
selectors is cleaner and more maintainable than conditional className expressions.
8-13
:✅ Verification successful
Verify impact of removing ref forwarding
The refactoring from
React.forwardRef
to a plain function component removes the ability to forward refs to the underlying DOM element. This could be a breaking change if any parent components were passing refs toSeparator
.Please verify that no components in the codebase are passing refs to the
Separator
component:
🏁 Script executed:
#!/bin/bash # Search for ref usage with Separator component rg -A 3 -B 3 'ref.*[Ss]eparator|[Ss]eparator.*ref'Length of output: 52
To be thorough, let’s search specifically for any JSX usage of
<Separator>
that includes aref
prop, and list out all<Separator>
occurrences for manual inspection:
🏁 Script executed:
#!/bin/bash # 1. Find any JSX <Separator ... ref=...> rg -n -t tsx "<Separator[^>]*ref=" # 2. List all <Separator ...> usages (first 100) to spot any ref rg -n -t tsx "<Separator" | head -n 100Length of output: 134
Let’s retry without the tsx filetype filter and use globs instead:
🏁 Script executed:
#!/bin/bash # 1. Find any <Separator ... ref=> across JS/TS files rg -n "<Separator[^>]*ref=" --glob "*.{js,jsx,ts,tsx}" # 2. List the first 100 <Separator ...> usages for manual inspection rg -n "<Separator" --glob "*.{js,jsx,ts,tsx}" | head -n 100Length of output: 1887
Separator ref forwarding removal is safe
A search across all.js/.jsx/.ts/.tsx
files found no instances of<Separator … ref=…>
. All existing usages only pass props likeclassName
andorientation
. RemovingforwardRef
will not break any consumers.frontend/components/ui/checkbox.tsx (3)
9-12
: LGTM: Proper TypeScript typing and component structureThe component signature correctly uses
React.ComponentProps<typeof CheckboxPrimitive.Root>
to inherit all props from the Radix primitive, ensuring type safety and flexibility.
15-19
: LGTM: Comprehensive state styling with data-slot attributeThe styling classes comprehensively handle all checkbox states:
- Focus states with ring styling
- Checked/unchecked states with appropriate colors
- Disabled and invalid states
- Dark mode variants
- Consistent sizing and border radius
The
data-slot="checkbox"
attribute follows the established pattern for component targeting.
22-27
: LGTM: Well-structured indicator with proper icon integrationThe checkbox indicator is properly structured with:
- Consistent
data-slot
attribute for targeting- Centered layout with flexbox
- Appropriate icon sizing (
size-3.5
)- Clean transition handling
The use of
CheckIcon
from lucide-react is consistent with the broader icon strategy.frontend/components/ui/switch.tsx (4)
4-4
: LGTM: Consistent import namingThe change from
SwitchPrimitives
(plural) toSwitchPrimitive
(singular) improves naming consistency with other component imports.
14-18
: LGTM: Comprehensive root styling with data-slot attributeThe updated styling provides excellent coverage of all switch states:
- Checked/unchecked background colors
- Focus ring styling
- Dark mode variants
- Proper sizing and transitions
- Disabled state handling
The
data-slot="switch"
attribute maintains consistency with the refactoring pattern.
21-27
: LGTM: Well-structured thumb element with proper stylingThe explicit thumb element provides clear component structure with:
- Consistent
data-slot
attribute- Comprehensive styling for all states including dark mode
- Smooth translation animations
- Proper sizing and positioning
This makes the component more maintainable and easier to style.
8-12
:✅ Verification successful
Verify impact of removing ref forwarding
Similar to the Separator component, this refactoring removes
React.forwardRef
, which could be a breaking change if other components were passing refs toSwitch
.Please verify that no components in the codebase are passing refs to the
Switch
component:
🏁 Script executed:
#!/bin/bash # Search for ref usage with Switch component rg -A 3 -B 3 'ref.*[Ss]witch|[Ss]witch.*ref'Length of output: 46
🏁 Script executed:
#!/bin/bash # Search for JSX usage of Switch component with a ref attribute in TSX files rg -n "<Switch[^>]*ref=" --glob "*.tsx"Length of output: 41
🏁 Script executed:
#!/bin/bash # Search for multiline JSX usage of Switch with a ref attribute across TSX files rg -n -P -z "(?s)<Switch.*?ref=" --glob "*.tsx"Length of output: 49
Removal of ref forwarding from Switch is safe
I searched across all TSX/JSX files for any<Switch ref=…>
usage and found no occurrences. There are no components passing refs toSwitch
, so removingReact.forwardRef
will not introduce breaking changes.frontend/package.json (2)
26-27
: LGTM! New Radix UI dependencies align with component additions.The new Radix UI packages (
@radix-ui/react-checkbox
,@radix-ui/react-collapsible
,@radix-ui/react-hover-card
,@radix-ui/react-toggle
,@radix-ui/react-toggle-group
) correctly support the new UI components being introduced.Also applies to: 30-30, 45-46, 58-58, 62-62, 66-66
75-75
:❓ Verification inconclusive
Verify Tailwind v4 package versions and security advisories.
The upgrade to Tailwind CSS v4.1.7 and related packages represents a major version change. Verify these are the latest stable versions and check for any security advisories.
Also applies to: 100-100, 103-103
🏁 Script executed:
#!/bin/bash # Check latest versions and security advisories npm view tailwindcss@^4.1.7 version npm view @tailwindcss/[email protected] version npm view tw-animate-css@^1.3.0 version # Check for security advisories npm audit --audit-level=moderateLength of output: 530
Versions confirmed up-to-date; manual security audit needed
- tailwindcss@^4.1.7 → 4.1.7
- @tailwindcss/[email protected] → 4.1.7
- tw-animate-css@^1.3.0 → 1.3.0
npm audit
failed due to a missing lockfile. Please generate one and re-run the audit to catch any vulnerabilities:npm install --package-lock-only npm audit --audit-level=moderateAlso applies to lines 100-100 and 103-103 in frontend/package.json.
frontend/components/ui/collapsible.tsx (1)
1-34
: LGTM! Clean implementation following established patterns.The collapsible component implementation is excellent:
- Proper TypeScript typing using
React.ComponentProps
- Consistent
data-slot
attributes for DOM targeting- Clean functional component approach without unnecessary complexity
- Follows the same pattern as other Radix UI wrappers in the codebase
This aligns well with the broader UI component refactoring mentioned in the PR summary.
frontend/components/ui/toggle-group.tsx (2)
10-15
: Good use of React Context for prop sharing.The context implementation correctly shares variant and size props from the parent
ToggleGroup
to childToggleGroupItem
components. The default values are sensible and provide a good fallback.
51-51
: Proper fallback logic for context values.The implementation correctly prioritizes context values over individual item props (
context.variant || variant
), which ensures consistent styling within a group while allowing individual customization when needed.Also applies to: 56-57, 60-61
frontend/components/ui/toggle.tsx (3)
9-29
: Comprehensive toggle variants with proper CVA configuration.The
toggleVariants
configuration is well-structured with:
- Appropriate variant options (default, outline)
- Good size options with consistent spacing
- Proper default variants specified
The implementation correctly uses
class-variance-authority
for type-safe variant management.
31-44
: Clean component implementation with proper prop forwarding.The
Toggle
component correctly:
- Uses proper TypeScript typing with intersection of component props and variant props
- Forwards all props to the underlying Radix primitive
- Applies the
data-slot
attribute for consistent DOM targeting- Uses the
cn
utility for className merging
47-47
: Good export strategy enabling component reuse.Exporting both the
Toggle
component andtoggleVariants
allows other components (likeToggleGroup
) to reuse the styling configuration, promoting consistency across the UI system.frontend/__tests__/components/ProfileForm.test.tsx (1)
101-127
: Excellent improvement to the mock implementation!This refactoring properly separates avatar configuration properties from DOM-safe props, preventing React warnings about unknown DOM attributes. The explicit extraction of all avatar config properties and the
style
prop ensures the mock behaves more realistically.frontend/components/ui/hover-card.tsx (3)
8-12
: Clean implementation following established patterns!The HoverCard root component correctly adds the
data-slot
attribute and forwards all props to the Radix primitive.
14-20
: Consistent trigger component implementation.The HoverCardTrigger properly follows the same pattern with appropriate data-slot attributes.
22-42
: Well-structured content component with good defaults.The HoverCardContent component provides sensible defaults for
align
andsideOffset
while maintaining proper portal usage and comprehensive styling classes for animations and positioning.frontend/components/ui/progress.tsx (1)
8-29
: Successful refactoring to simplified function component!The refactoring correctly:
- Removes
React.forwardRef
complexity while maintaining functionality- Adds
data-slot
attributes for better DOM targeting- Simplifies TypeScript prop typing to
React.ComponentProps
- Preserves all styling and behavior
The class reordering (
bg-primary/20 relative
instead ofrelative bg-primary/20
) doesn't affect functionality and maintains visual consistency.frontend/components/ui/scroll-area.tsx (2)
8-29
: Excellent refactoring with accessibility improvements!The ScrollArea component refactoring correctly:
- Removes
React.forwardRef
complexity- Adds
data-slot
attributes for better DOM targeting- Enhances the viewport with improved focus-visible styling including ring effects and proper outline handling
- Simplifies the root className from complex overflow handling to simple
"relative"
The enhanced focus-visible styles improve accessibility and user experience.
31-56
: Clean ScrollBar refactoring with styling improvements.The ScrollBar component refactoring successfully:
- Follows the same pattern with
data-slot
attributes- Improves padding notation from
p-[1px]
top-px
(more concise)- Maintains conditional styling for orientation while improving readability
- Preserves all functionality
frontend/components/ui/calendar.tsx (3)
10-15
: Well-structured component props and typingThe component properly types its props using
React.ComponentProps<typeof DayPicker>
and provides sensible defaults likeshowOutsideDays = true
. The prop destructuring and spreading pattern is clean and maintainable.
37-42
: Excellent conditional styling for range modeThe conditional styling based on
props.mode === "range"
properly handles the different visual requirements for single date vs. date range selection. The class composition usingcn()
is well-structured and the range styling logic is correct.
62-69
: Clean icon component implementationThe custom icon components for navigation properly use the lucide-react icons with consistent sizing (
size-4
) and maintain the same prop pattern as the original DayPicker icons.frontend/components/ui/textarea.tsx (2)
10-10
: Comprehensive styling improvementsThe updated styling includes excellent accessibility features with
aria-invalid
states, dark mode support, and smooth transitions. The focus-visible ring effects and disabled states are well-implemented.
5-16
:❌ Incorrect review comment
Breaking change: Removal of React.forwardRef
Similar to the Label component, removing
React.forwardRef
is a breaking change that could affect form libraries and custom implementations that need direct DOM access to the textarea element.
🏁 Script executed:
#!/bin/bash # Search for ref usage with Textarea component rg -A 3 -B 3 "ref.*Textarea|Textarea.*ref" --type tsx --type tsLength of output: 93
🏁 Script executed:
#!/bin/bash # Search for any ref usage on the Textarea component rg -n '<Textarea[^>]*ref=' --glob '*.tsx' --glob '*.ts' # List all Textarea usages for context rg -n '<Textarea' --glob '*.tsx' --glob '*.ts'Length of output: 347
Ignore forwardRef removal as breaking change
Our search across the codebase found no instances of a
ref
being passed to<Textarea>
, so removingReact.forwardRef
does not break any existing usage.Textarea usages found:
- frontend/app/prompts/_components/PromptForm.tsx:223, 359
- frontend/components/layout/AddContentModal.tsx:284
No
<Textarea ref=…>
references detected. You can safely dropforwardRef
; reintroduce it later if external ref access becomes necessary.Likely an incorrect or invalid review comment.
frontend/components/ui/input.tsx (1)
11-11
: Excellent file input stylingThe comprehensive file input styling with
file:
pseudo-selectors provides consistent styling for file upload inputs, which is often overlooked. This ensures file inputs match the overall design system.frontend/components/ui/resizable.tsx (2)
9-23
: LGTM! Well-structured ResizablePanelGroup component.The component correctly follows the established pattern of adding data-slot attributes and using the cn utility for class composition. The default flex styling with vertical orientation support is appropriate for a resizable panel group.
25-29
: LGTM! Clean and minimal ResizablePanel wrapper.The component appropriately wraps the Panel primitive while maintaining the data-slot pattern for consistency across the UI library.
frontend/components/ui/button.tsx (2)
38-57
: LGTM! Button component refactoring follows established pattern.The refactoring from React.forwardRef to a plain function component with data-slot attribute is consistent with the broader UI library modernization. The conditional padding for SVG children (
has-[>svg]:px-*
) is a nice UX improvement.
8-8
: Consider the performance implications of transition-all.The change from
transition-colors
totransition-all
will now transition all animatable properties instead of just colors. This might have performance implications and could cause unwanted animations.Please verify if
transition-all
is necessary or if the more specifictransition-colors
was sufficient for the button's use cases. If only color and background transitions are needed, consider reverting totransition-colors
for better performance.frontend/lib/utils.ts (1)
8-49
: LGTM! Improved error handling with better type safety.The refactoring from
ErrorWithDetail
toErrorLike
interface simplifies the error handling while maintaining robustness. The addition of JSON.stringify fallback and explicit type guards improves debugging and code clarity.frontend/components/ui/tabs.tsx (3)
8-19
: LGTM! Tabs component refactoring follows established pattern.The refactoring from direct primitive export to an explicit function component with data-slot attribute is consistent with the UI library modernization effort.
21-35
: LGTM! TabsList component properly styled.The component correctly implements the muted background styling typical for tab lists with appropriate spacing and border radius.
53-64
: LGTM! TabsContent component appropriately minimal.The component correctly provides a minimal wrapper with proper flex styling and focus handling for tab content areas.
frontend/components/ui/badge.tsx (3)
2-2
: LGTM: Addition of Slot import for composition pattern.The import of
Slot
from@radix-ui/react-slot
enables theasChild
composition pattern, allowing flexible rendering of different element types.
8-26
: Excellent styling improvements with comprehensive accessibility features.The updated
badgeVariants
include significant enhancements:
- Better layout control with
justify-center
,w-fit
,whitespace-nowrap
,shrink-0
- SVG styling with
[&>svg]:size-3 gap-1 [&>svg]:pointer-events-none
- Comprehensive accessibility states:
focus-visible:*
,aria-invalid:*
- Smooth transitions and dark mode support
The
[a&]:hover:
pattern properly targets anchor elements specifically, which is a good practice for conditional hover states.
28-44
: Well-implemented component refactor with composition support.The refactor from
React.forwardRef
to a plain function component is clean and includes:
- Proper
asChild
pattern implementation withSlot
- Addition of
data-slot="badge"
for better DOM targeting- Correct TypeScript typing with
React.ComponentProps<"span">
- Proper prop spreading and variant application
The conditional component rendering
const Comp = asChild ? Slot : "span"
follows the established pattern correctly.frontend/components/ui/pagination.tsx (5)
1-10
: LGTM: Clean imports and dependencies.The imports are well-organized and use the new icon library (
lucide-react
) and existing UI utilities (Button
,buttonVariants
,cn
).
11-21
: Excellent accessibility implementation for main pagination wrapper.The
Pagination
component properly implements:
- Semantic
nav
element withrole="navigation"
- Clear
aria-label="pagination"
for screen readers- Consistent
data-slot="pagination"
attribute- Centered layout with proper spacing
40-66
: Well-designed PaginationLink with proper accessibility states.The component correctly implements:
aria-current="page"
for active state (WCAG compliance)data-active
attribute for styling hooks- Proper variant selection (
outline
for active,ghost
for inactive)- Flexible size prop with sensible default (
icon
)The type definition properly extends Button props while maintaining anchor semantics.
68-100
: Excellent responsive design for Previous/Next navigation.Both
PaginationPrevious
andPaginationNext
components feature:
- Clear
aria-label
attributes for accessibility- Responsive text visibility (
hidden sm:block
)- Proper icon placement (left for previous, right for next)
- Consistent spacing and sizing
The responsive approach improves UX on mobile devices while maintaining full functionality on larger screens.
102-117
: Proper ellipsis implementation with accessibility considerations.The
PaginationEllipsis
component correctly:
- Uses
aria-hidden
to hide decorative content from screen readers- Includes
sr-only
text for context- Maintains consistent sizing with other pagination elements
- Uses semantic
span
element appropriatelyfrontend/components/ui/popover.tsx (3)
8-18
: Clean wrapper implementations for Popover primitives.Both
Popover
andPopoverTrigger
properly wrap their respective Radix primitives while adding the consistentdata-slot
attributes for DOM targeting.
20-40
: Comprehensive PopoverContent implementation with excellent styling.The component includes:
- Proper Portal usage for correct rendering context
- Sensible defaults (
align="center"
,sideOffset=4
)- Comprehensive animation classes for smooth enter/exit transitions
- CSS custom property usage:
origin-(--radix-popover-content-transform-origin)
- Proper z-index layering (
z-50
)- Accessibility with
outline-hidden
The extensive animation classes provide polished UX with proper fade and slide transitions for all placement sides.
42-46
: Consistent wrapper implementation for PopoverAnchor.The
PopoverAnchor
wrapper follows the same pattern as other components with properdata-slot
attribute.frontend/components/ui/breadcrumb.tsx (6)
7-9
: Clean breadcrumb wrapper with proper semantics.The
Breadcrumb
component correctly uses semanticnav
element witharia-label="breadcrumb"
for accessibility compliance.
11-22
: Well-styled breadcrumb list with responsive design.The
BreadcrumbList
includes:
- Proper semantic
ol
element- Responsive gap spacing (
gap-1.5
tosm:gap-2.5
)- Text wrapping and overflow handling
- Consistent text styling with muted foreground
34-50
: Excellent composition support with asChild pattern.The
BreadcrumbLink
properly implements:
- Conditional rendering with
Slot
whenasChild
is true- Hover state transitions
- Consistent
data-slot
attribute- Flexible TypeScript typing
This allows for custom link components (e.g., Next.js Link) while maintaining styling consistency.
52-63
: Proper accessibility implementation for current page.The
BreadcrumbPage
correctly implements ARIA attributes:
role="link"
for semantic meaningaria-disabled="true"
to indicate non-interactive statearia-current="page"
for current page identificationThis follows WCAG guidelines for breadcrumb navigation.
65-81
: Clean separator implementation with flexible icon support.The
BreadcrumbSeparator
features:
- Default
ChevronRight
icon with fallback support- Proper accessibility (
role="presentation"
,aria-hidden="true"
)- Consistent SVG sizing with
[&>svg]:size-3.5
- Flexible children prop for custom separators
83-99
: Accessible ellipsis implementation with screen reader support.The
BreadcrumbEllipsis
properly handles:
- Decorative content hiding with
aria-hidden="true"
- Screen reader context with
sr-only
text- Consistent sizing and alignment
- Appropriate semantic markup with
span
frontend/components/ui/tooltip.tsx (1)
8-19
: LGTM on the refactoring pattern.The conversion from React.forwardRef to plain functional components with data-slot attributes follows a consistent pattern and improves DOM element identification. The addition of the arrow element enhances the tooltip's visual design.
Also applies to: 31-35, 37-59
frontend/components/ui/navigation-menu.tsx (5)
4-4
: LGTM on icon library migration.The switch from
@radix-ui/react-icons
tolucide-react
is consistent with the overall refactoring effort and provides a more comprehensive icon set.
8-30
: Excellent addition of viewport prop for flexibility.The conditional viewport rendering via the
viewport
prop provides good flexibility for different navigation menu use cases while maintaining backward compatibility with the defaulttrue
value.
85-100
: Clever conditional styling based on viewport prop.The use of
group-data-[viewport=false]/navigation-menu:
prefixes to conditionally apply styles when viewport is disabled is an elegant solution that maintains proper styling hierarchy.
124-138
: Enhanced NavigationMenuLink styling improves accessibility.The updated styling with proper focus-visible ring styles, SVG color handling, and active state management significantly improves the component's accessibility and visual feedback.
77-82
:❓ Verification inconclusive
Verify ChevronDownIcon size class compatibility.
The icon class changed from fixed
h-4 w-4
tosize-3
. Ensure this size change maintains visual consistency.
🏁 Script executed:
#!/bin/bash # Description: Check if size-3 (12px) is consistent with other UI components # Expected: Should show other icon size usage patterns in the codebase echo "=== Searching for icon size classes ===" rg "size-[0-9]" --type tsx --type ts -A 1 -B 1 echo "=== Searching for chevron icon usage ===" rg "ChevronDown" --type tsx --type ts -A 2 -B 1Length of output: 332
🏁 Script executed:
#!/bin/bash # Retry searching for icon size classes across .ts/.tsx files echo "=== Searching for icon size classes ===" rg 'size-[0-9]+' -g '*.tsx' -g '*.ts' -C1 echo "=== Searching for ChevronDownIcon usage ===" rg 'ChevronDownIcon' -g '*.tsx' -g '*.ts' -C2Length of output: 23783
Confirm ChevronDownIcon sizing in NavigationMenu
Most dropdown chevrons in our components usesize-4
(16px)—for example, inSelect
triggers—whereas here we’ve explicitly set the nav‐menu chevron tosize-3
(12px). Note thatsize-3
is otherwise only used for very small icons (e.g. badge SVGs), so please verify this smaller size aligns with the design spec.•
frontend/components/ui/navigation-menu.tsx
(≈ line 77):<ChevronDownIcon className="… size-3 …" />
•frontend/components/ui/select.tsx
:<ChevronDownIcon className="size-4 …" />
If the navigation-menu chevron should match other dropdowns, consider reverting to
size-4
.frontend/components/ui/alert.tsx (4)
7-7
: Excellent grid layout implementation for icon handling.The CSS grid approach with
has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr]
is much more robust than the previous flex/absolute positioning approach. This automatically handles icon presence and provides consistent spacing.
13-13
: Clever use of data attribute selector for destructive styling.Using
*:data-[slot=alert-description]:text-destructive/90
to target the alert description within destructive variants is an elegant approach that maintains component isolation while applying conditional styling.
22-35
: LGTM on component refactoring and grid positioning.The conversion to plain functional components with data-slot attributes is consistent, and the grid positioning classes (
col-start-2
) properly align with the new grid layout structure.Also applies to: 37-48, 50-64
11-14
:✅ Verification successful
Verify impact of variant reduction.
The removal of "warning" and "success" variants might be a breaking change for existing code. Only "default" and "destructive" variants remain.
🏁 Script executed:
#!/bin/bash # Description: Find usage of removed alert variants # Expected: Should identify any code using warning/success variants that need updating echo "=== Searching for removed alert variants ===" rg "variant.*[\"']warning[\"']" --type tsx --type ts rg "variant.*[\"']success[\"']" --type tsx --type ts echo "=== Searching for Alert component usage ===" rg -A 3 -B 1 "<Alert" --type tsx --type tsLength of output: 442
🏁 Script executed:
#!/bin/bash # Re-run search without relying on ripgrep file‐type definitions echo "=== Searching for removed alert variants ===" rg "variant\s*=\s*['\"](warning|success)['\"]" --glob "*.tsx" --glob "*.ts" echo "=== Searching for all Alert component usages ===" rg -n -A 3 -B 1 "<Alert" --glob "*.tsx" --glob "*.ts"Length of output: 24596
No breaking changes: “warning” and “success” variants aren’t used
Searched all *.tsx/ *.ts files for<Alert variant="warning">
or"success"
and found zero matches—every<Alert>
uses only “default” or “destructive.” Removing the unused variants is safe.frontend/components/ui/card.tsx (4)
5-16
: Enhanced card styling with modern CSS features.The updated card styling with flexbox layout, proper gap spacing, and shadow effects provides a more polished and maintainable design foundation.
18-29
: Sophisticated grid layout with container queries.The CardHeader's use of
@container/card-header
and conditional grid columns (has-data-[slot=card-action]:grid-cols-[1fr_auto]
) demonstrates modern CSS techniques for responsive design that adapts based on content presence.
51-62
: Valuable addition of CardAction component.The new
CardAction
component fills a common UI pattern need and its grid positioning (col-start-2 row-span-2 row-start-1
) integrates well with the CardHeader layout system.
78-78
:✅ Verification successful
Verify CSS selector syntax for conditional styling.
The
[.border-t]:pt-6
syntax for conditional padding appears to be a newer CSS feature. Ensure this is supported across target browsers.
🌐 Web query:
What is the browser support for CSS selector syntax like `[.border-t]:pt-6` in modern Tailwind CSS and CSS specifications?
💡 Result:
CSS Selector Syntax:
[.border-t]:pt-6
in Tailwind CSS and Browser SupportUnderstanding the Syntax
The selector
[.border-t]:pt-6
seen in Tailwind CSS is not standard CSS syntax.
- In pure CSS, attribute selectors like
[attr=value]
or[class~="value"]
are supported by all modern browsers, but the syntax must directly reflect actual HTML attribute values or classes on elements[6][10].- The notation
[.border-t]:pt-6
is a Tailwind CSS-specific "arbitrary variant," enabling you to apply a utility class (likept-6
) only when another class (like.border-t
) is present on the element. This relies on Tailwind’s build time processing, not on native browser CSS parsing.Browser Support: CSS Attribute Selectors
- Traditional CSS attribute selectors (e.g.,
[class~="foo"]
,[data-bar]
,[type="checkbox"]
) are universally supported in all modern browsers, including Chrome, Firefox, Safari, and Edge[2][6][10].- These selectors target HTML attributes and their values and are part of official CSS specifications and supported since CSS2 and widely in CSS3.
Tailwind CSS Arbitrary Variants and Their Support
- The syntax
[.border-t]:pt-6
is interpreted by Tailwind’s processor, not by browsers themselves. Tailwind parses this at build time to generate the necessary CSS, typically by outputting a selector like.border-t.pt-6
or using more advanced selector logic.- Tailwind CSS v3+ is fully supported in all modern browsers: Chrome, Firefox, Safari, and Edge, but not supported in any version of Internet Explorer[7][8].
- The actual browser-rendered CSS will use only standard selectors, ensuring compatibility as long as you target supported browsers.
Native CSS Selector Syntax: Limitations
- CSS does not support conditional selectors like
[.border-t]:pt-6
natively.- Any such logic must be handled at the preprocessing/transpilation level (e.g., by Tailwind’s engine).
- So, while the resulting CSS is browser-compatible, the original syntax is not directly usable in plain CSS files.
Summary Table: Browser Support
Syntax Native CSS Support Tailwind Support Modern Browser Support [class~="foo"]
Yes Yes Chrome, Firefox, Edge, Safari [.border-t]:pt-6
No Yes (v3+) Chrome, Firefox, Edge, Safari Key Takeaways
- Standard CSS attribute selectors have excellent browser support[2][6][10].
- Tailwind-specific arbitrary variants like
[.border-t]:pt-6
are processed by Tailwind at build time and generate compatible CSS for all modern browsers[7][8].- Internet Explorer is not supported by modern Tailwind CSS, nor for some newer CSS features[7][8].
- The original
[.border-t]:pt-6
syntax is not valid or supported by browsers themselves; only the output from Tailwind is.Tailwind CSS is designed to work with the latest stable versions of Chrome, Firefox, Safari, and Edge… it does not support any version of IE, including IE 11.[7]
If you use such syntax in Tailwind, you can be confident it will work in all modern browsers, so long as Tailwind itself is generating the CSS.
Citations:
- 1: https://www.lambdatest.com/blog/css-browser-compatibility-issues/
- 2: https://caniuse.com/?search=selectors
- 3: https://developer.mozilla.org/en-US/docs/Web/CSS/@supports
- 4: https://elementor.com/blog/css-selectors-reference/
- 5: https://www.zenrows.com/blog/xpath-vs-css-selector
- 6: https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors
- 7: https://v3.tailwindcss.com/docs/browser-support
- 8: https://kombai.com/tailwind/browser-support/
- 9: https://css-tricks.com/a-css-wishlist-for-2025/
- 10: https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Attribute_selectors
No Action Required – Valid Tailwind Arbitrary Variant
The
[.border-t]:pt-6
syntax is a Tailwind CSS arbitrary variant that’s compiled at build time into standard CSS selectors, so it works in all modern browsers supported by Tailwind (Chrome, Firefox, Safari, Edge). Internet Explorer isn’t supported by Tailwind, but this syntax itself poses no cross-browser issues.frontend/app/globals.css (1)
1-8
:@custom-variant
/@variant
syntax may not be recognised by PostCSS-based
toolingThese at-rules are still experimental and not yet supported in most
Tailwind / PostCSS parsers (the Biome parse errors stem from this). Make
sure your build pipeline explicitly enables thepostcss-custom-variant
plugin or replace with standard[.dark &]
or:where(.dark *)
patterns.frontend/components/ui/dialog.tsx (1)
60-62
: Custom radiusrounded-xs
may not exist
rounded-xs
is not part of the default Tailwind scale. Unless it’s extended intailwind.config.js
, this class is silently dropped and you get the default radius (0).Either use
rounded-sm
/rounded-md
or ensure the custom size is declared in the config.frontend/components/ui/sheet.tsx (1)
75-78
: Hard-coded close button position
absolute top-4 right-4
clashes with user-supplied padding if the consumer wants a large header. Provide a prop or at least use relative positioning inside a header slot so the button adapts naturally.frontend/components/ui/menubar.tsx (1)
106-108
: Unusual*:[svg]
selector may not compileThe class segment
data-[variant=destructive]:*:[svg]:!text-destructive
relies on an undocumented selector-arbitrary feature. Tailwind’s arbitrary selector syntax ([&_*_svg]
etc.) changed between v3 and v4; please verify that your Tailwind version parses this or the build will fail silently.frontend/components/ui/sidebar.tsx (1)
476-489
: Danger of important modifier suffix!
Classes like
size-8!
andp-2!
rely on the new Tailwind important modifier. If any consumer is still on Tailwind ≤ 3, these will be emitted as plain strings and not matched. Confirm the minimum Tailwind version inpackage.json
and README to avoid downstream breakage.
React.useEffect(() => { | ||
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); | ||
const onChange = () => { | ||
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); | ||
}; | ||
mql.addEventListener("change", onChange); | ||
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); | ||
return () => mql.removeEventListener("change", onChange); | ||
}, []); |
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
Add compatibility fallback for older browsers’ MediaQueryList
listeners
MediaQueryList.addEventListener
/ removeEventListener
aren’t supported in some older WebKit browsers (e.g., Safari < 14). You should feature-detect and fall back to the legacy addListener
/removeListener
APIs:
React.useEffect(() => {
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
- mql.addEventListener("change", onChange);
+ if (typeof mql.addEventListener === "function") {
+ mql.addEventListener("change", onChange);
+ } else {
+ mql.addListener(onChange);
+ }
// Set initial state...
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
- return () => mql.removeEventListener("change", onChange);
+ return () => {
+ if (typeof mql.removeEventListener === "function") {
+ mql.removeEventListener("change", onChange);
+ } else {
+ mql.removeListener(onChange);
+ }
+ };
}, []);
📝 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.
React.useEffect(() => { | |
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); | |
const onChange = () => { | |
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); | |
}; | |
mql.addEventListener("change", onChange); | |
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); | |
return () => mql.removeEventListener("change", onChange); | |
}, []); | |
React.useEffect(() => { | |
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); | |
const onChange = () => { | |
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); | |
}; | |
if (typeof mql.addEventListener === "function") { | |
mql.addEventListener("change", onChange); | |
} else { | |
mql.addListener(onChange); | |
} | |
// Set initial state... | |
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); | |
return () => { | |
if (typeof mql.removeEventListener === "function") { | |
mql.removeEventListener("change", onChange); | |
} else { | |
mql.removeListener(onChange); | |
} | |
}; | |
}, []); |
🤖 Prompt for AI Agents
In frontend/hooks/use-mobile.ts around lines 10 to 18, the code uses
mql.addEventListener and mql.removeEventListener which are not supported in
older WebKit browsers like Safari < 14. To fix this, add feature detection to
check if addEventListener/removeEventListener exist on the MediaQueryList
object; if not, fall back to using the legacy addListener/removeListener methods
for attaching and removing the change event listener.
@@ -50,12 +55,15 @@ | |||
"lucide-react": "^0.292.0", | |||
"next-i18next": "^15.4.2", | |||
"next-themes": "^0.4.6", | |||
"react-day-picker": "8.10.1", |
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
Verify the utility library versions for compatibility.
The additions of react-day-picker
, react-resizable-panels
, and vaul
support new component functionality. Ensure these versions are compatible with React 19.1.0.
Also applies to: 62-62, 66-66
🏁 Script executed:
#!/bin/bash
# Check compatibility of new packages with React 19
npm view [email protected] peerDependencies
npm view react-resizable-panels@^3.0.2 peerDependencies
npm view vaul@^1.1.2 peerDependencies
Length of output: 509
Confirm React-Day-Picker compatibility with React 19.1.0
Our peer-dependency audit shows:
- [email protected] only supports React ^16.8.0 – ^18.0.0
- [email protected] and [email protected] both include React ^19.0.0 in their ranges
Action items:
- Upgrade
react-day-picker
to a version that officially supports React 19 (for example v9.x), or - Revert/lock your app to React 18.x to match the current peerDependency range.
Locations:
- frontend/package.json: line 58 (react-day-picker)
🤖 Prompt for AI Agents
In frontend/package.json at line 58, the version of react-day-picker (8.10.1) is
incompatible with React 19.1.0 as it only supports up to React 18. To fix this,
upgrade react-day-picker to a version that officially supports React 19, such as
version 9.x, ensuring compatibility with your React version. Alternatively, if
upgrading is not feasible, revert your React version to 18.x to match the peer
dependency requirements of react-day-picker 8.10.1.
function Label({ | ||
className, | ||
...props | ||
}: React.ComponentProps<typeof LabelPrimitive.Root>) { | ||
return ( | ||
<LabelPrimitive.Root | ||
data-slot="label" | ||
className={cn( | ||
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", | ||
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.
💡 Verification agent
❓ Verification inconclusive
Breaking change: Removal of React.forwardRef
The refactoring from React.forwardRef
to a plain function component removes the ability to pass refs to the underlying label element. This could break existing code that relies on direct DOM access for focus management or form libraries.
Consider the impact on:
- Form libraries that need label refs for accessibility
- Custom focus management implementations
- Testing code that queries label elements via refs
🏁 Script executed:
#!/bin/bash
# Search for ref usage with Label component across the codebase
rg -A 3 -B 3 "ref.*Label|Label.*ref" --type tsx --type ts
Length of output: 87
🏁 Script executed:
#!/bin/bash
# Search for <Label ... ref usage across .ts/.tsx files
rg -n -B3 -A3 --glob '*.{ts,tsx}' "<Label[^>]*ref="
Length of output: 53
Preserve ref forwarding on Label
We ran a global search for <Label … ref=
across all .ts
/.tsx
files and found no internal usages. That means there are no immediate breakages in this codebase—but since Label
is a public UI component, removing React.forwardRef
will break any external consumers expecting to forward refs to the underlying <label>
element.
Recommendations:
- Wrap
Label
inReact.forwardRef
again to restore ref forwarding:- function Label({ - className, - ...props - }: React.ComponentProps<typeof LabelPrimitive.Root>) { - return ( - <LabelPrimitive.Root - data-slot="label" - className={cn(/* … */)} - {...props} - /> - ); - } + const Label = React.forwardRef< + HTMLLabelElement, + React.ComponentProps<typeof LabelPrimitive.Root> + >(({ className, ...props }, ref) => ( + <LabelPrimitive.Root + ref={ref} + data-slot="label" + className={cn(/* … */)} + {...props} + /> + ));
- Update or add a
Label.displayName = "Label";
after the forwardRef for clearer DevTools output (if needed).
📝 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.
function Label({ | |
className, | |
...props | |
}: React.ComponentProps<typeof LabelPrimitive.Root>) { | |
return ( | |
<LabelPrimitive.Root | |
data-slot="label" | |
className={cn( | |
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", | |
className, | |
)} | |
{...props} | |
/> | |
); | |
} | |
// frontend/components/ui/label.tsx | |
import * as React from "react"; | |
import { cn } from "@/lib/utils"; | |
import * as LabelPrimitive from "@radix-ui/react-label"; | |
const Label = React.forwardRef< | |
HTMLLabelElement, | |
React.ComponentProps<typeof LabelPrimitive.Root> | |
>(({ className, ...props }, ref) => ( | |
<LabelPrimitive.Root | |
ref={ref} | |
data-slot="label" | |
className={cn( | |
"flex items-center gap-2 text-sm leading-none font-medium select-none " + | |
"group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 " + | |
"peer-disabled:cursor-not-allowed peer-disabled:opacity-50", | |
className | |
)} | |
{...props} | |
/> | |
)); | |
Label.displayName = "Label"; | |
export { Label }; |
🤖 Prompt for AI Agents
In frontend/components/ui/label.tsx around lines 8 to 22, the Label component
was refactored from using React.forwardRef to a plain function, which removes
support for forwarding refs to the underlying label element. To fix this, wrap
the Label function component again with React.forwardRef to enable ref
forwarding, and add Label.displayName = "Label" after the forwardRef call for
better debugging and DevTools clarity.
className={cn( | ||
"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", | ||
"border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] 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.
💡 Verification agent
🧩 Analysis chain
Verify field-sizing-content browser support
The field-sizing-content
CSS property is relatively new and may not be supported in all browsers. This could cause layout issues in older browsers.
🌐 Web query:
What is the browser support for the CSS field-sizing-content property?
💡 Result:
The field-sizing
CSS property, particularly with the content
value (field-sizing: content;
), is an experimental feature designed to allow form controls like <input>
, <textarea>
, and <select>
elements to adjust their size based on their content. This property is currently not widely supported across major browsers.
Browser Support:
- Chrome: Supported from version 123 onwards.
- Firefox: Not supported.
- Safari: Not supported.
- Edge: Supported from version 123 onwards.
- Opera: Supported from version 109 onwards.
Given its limited support, it's advisable to check the Can I Use website for the most current compatibility information.
Recommendation:
Due to its experimental status and limited browser support, it's recommended to use the field-sizing
property cautiously and primarily for testing purposes. For production environments, consider using established CSS properties and techniques to control form element sizing, such as setting width
, min-width
, max-width
, and box-sizing
properties, which are widely supported and provide reliable results across all major browsers.
Replace experimental field-sizing-content with robust sizing fallbacks
The field-sizing: content
property is still experimental (supported only in Chrome 123+, Edge 123+, Opera 109+) and isn’t available in Firefox or Safari. For reliable cross-browser behavior in production, switch to well-supported CSS sizing utilities (e.g. width
, min-width
, max-width
, box-sizing
) or implement a small JS-driven autosize solution.
Locations to update:
- frontend/components/ui/textarea.tsx (line 10): class list includes
field-sizing-content
Suggested change:
- "… dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md …"
+ "… dark:bg-input/30 flex w-full min-w-0 min-h-16 rounded-md …"
• Remove field-sizing-content
• Add w-full
(or a fixed max-w-…
) and min-w-0
(with box-border
if needed)
• If you need true content-driven sizing, consider a lightweight JS autosize library or inline script.
📝 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 placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", | |
- "border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", | |
+ "border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex w-full min-w-0 min-h-16 rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", |
🤖 Prompt for AI Agents
In frontend/components/ui/textarea.tsx at line 10, replace the experimental CSS
class `field-sizing-content` with more widely supported sizing utilities to
ensure cross-browser compatibility. Remove `field-sizing-content` from the class
list and add classes like `w-full` and `min-w-0` (and `box-border` if necessary)
to control the textarea's width reliably. If dynamic content-based sizing is
required, implement a lightweight JavaScript autosize solution instead of
relying on the unsupported CSS property.
function Input({ className, type, ...props }: React.ComponentProps<"input">) { | ||
return ( | ||
<input | ||
type={type} | ||
data-slot="input" | ||
className={cn( | ||
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none 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, | ||
)} | ||
{...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.
💡 Verification agent
🧩 Analysis chain
Breaking change: Removal of React.forwardRef
The removal of React.forwardRef
is a breaking change that affects any code expecting to pass refs to the input element. This is particularly important for form libraries like React Hook Form that rely on refs for input registration.
🏁 Script executed:
#!/bin/bash
# Search for ref usage with Input component and form libraries
rg -A 5 -B 5 "register.*Input|useFormContext.*Input|ref.*Input" --type tsx --type ts
Length of output: 114
🏁 Script executed:
#!/bin/bash
# Gather all files importing or using the Input component, then check for register/ref usage
files=$(rg -l "import.*Input" -g "*.tsx")
if [ -z "$files" ]; then
echo "No explicit imports of Input found; falling back to any <Input usage…>"
files=$(rg -l "<Input" -g "*.tsx")
fi
if [ -z "$files" ]; then
echo "No .tsx files reference the Input component."
exit 0
fi
for file in $files; do
echo "==> $file"
echo "Input usage context:"
rg -Hn "<Input" -B2 -A2 "$file" || echo " (none)"
echo
echo "register(...) usage context:"
rg -Hn "register\(" -B2 -A2 "$file" || echo " (none)"
echo
echo "ref= attribute usage context:"
rg -Hn "ref=" -B2 -A2 "$file" || echo " (none)"
echo "────────────────────────────────────────────────────────────────"
done
Length of output: 74636
Ref forwarding broken in Input component
Removal of React.forwardRef
in frontend/components/ui/input.tsx
breaks any ref-based integrations—especially React Hook Form’s useController
/useFieldArray
flows that inject a ref
via {...field}
. I located two usages that will no longer attach the ref to the underlying <input>
:
• frontend/app/prompts/_components/PromptForm.tsx:209
• frontend/app/prompts/tags/_components/TagForm.tsx:106,120
Please restore ref forwarding on Input
, for example:
- function Input({ className, type, ...props }: React.ComponentProps<"input">) {
+ const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
+ function Input({ className, type, ...props }, ref) {
return (
<input
+ ref={ref}
type={type}
data-slot="input"
className={cn(/* … */)}
{...props}
/>
);
}
);
📝 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.
function Input({ className, type, ...props }: React.ComponentProps<"input">) { | |
return ( | |
<input | |
type={type} | |
data-slot="input" | |
className={cn( | |
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none 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, | |
)} | |
{...props} | |
/> | |
); | |
} | |
const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>( | |
function Input({ className, type, ...props }, ref) { | |
return ( | |
<input | |
ref={ref} | |
type={type} | |
data-slot="input" | |
className={cn( | |
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none 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, | |
)} | |
{...props} | |
/> | |
); | |
} | |
); |
🤖 Prompt for AI Agents
In frontend/components/ui/input.tsx around lines 5 to 19, the Input component no
longer forwards refs, breaking integrations that rely on ref forwarding such as
React Hook Form. To fix this, wrap the Input function component with
React.forwardRef and accept a ref parameter, then pass this ref to the
underlying <input> element. This will restore ref forwarding and maintain
compatibility with form libraries expecting refs.
function DropdownMenu({ | ||
...props | ||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) { | ||
return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...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
Loss of ref
forwarding may be a breaking change
All wrapper components were converted from React.forwardRef
to plain functions, so any ref
supplied by consumers is now swallowed and never reaches the underlying Radix primitive.
Radix items (Trigger, Item, etc.) often need the DOM node ref for imperative focus handling and type-safety – this was previously guaranteed by forwarding.
-function DropdownMenuTrigger({...props}) {
- return <DropdownMenuPrimitive.Trigger {...props} />
-}
+const DropdownMenuTrigger = React.forwardRef<
+ React.ElementRef<typeof DropdownMenuPrimitive.Trigger>,
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Trigger>
+>((props, ref) => (
+ <DropdownMenuPrimitive.Trigger ref={ref} {...props} />
+));
+DropdownMenuTrigger.displayName = DropdownMenuPrimitive.Trigger.displayName;
Consider restoring forwardRef
(with an explicit displayName
) for every public component to avoid silent runtime bugs.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In frontend/components/ui/dropdown-menu.tsx around lines 9 to 14, the
DropdownMenu component was changed from using React.forwardRef to a plain
function, causing any ref passed by consumers to be lost and not forwarded to
the underlying DropdownMenuPrimitive.Root. To fix this, refactor the component
to use React.forwardRef, explicitly forwarding the ref to
DropdownMenuPrimitive.Root, and set a displayName for the component to maintain
clarity and avoid runtime issues with imperative focus handling.
"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-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md", | ||
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.
Tailwind arbitrary value syntax is invalid
max-h-(--radix-dropdown-menu-content-available-height)
and origin-(--radix-dropdown-menu-content-transform-origin)
drop the required var()
wrapper.
Tailwind (v3 & v4-beta) expects either brackets [...]
(v3) or parentheses (...)
(v4) but still with the full CSS value, e.g.
- max-h-(--radix-dropdown-menu-content-available-height)
- origin-(--radix-dropdown-menu-content-transform-origin)
+ max-h-(var(--radix-dropdown-menu-content-available-height))
+ origin-(var(--radix-dropdown-menu-content-transform-origin))
Without var()
the build will output literally max-height: --radix…
, an invalid declaration.
📝 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-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto 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-x-hidden overflow-y-auto rounded-md border p-1 shadow-md", | |
className, | |
)} |
🤖 Prompt for AI Agents
In frontend/components/ui/dropdown-menu.tsx around lines 45 to 47, the Tailwind
CSS classes use invalid arbitrary value syntax by omitting the var() wrapper for
CSS variables in max-h and origin properties. Fix this by wrapping the CSS
variables with var() inside the appropriate brackets, for example, change
max-h-(--radix-dropdown-menu-content-available-height) to
max-h-[var(--radix-dropdown-menu-content-available-height)] and
origin-(--radix-dropdown-menu-content-transform-origin) to
origin-[var(--radix-dropdown-menu-content-transform-origin)] to ensure valid CSS
output.
function MenubarTrigger({ | ||
className, | ||
...props | ||
}: React.ComponentProps<typeof MenubarPrimitive.Sub>) { | ||
return <MenubarPrimitive.Sub data-slot="menubar-sub" {...props} />; | ||
}: React.ComponentProps<typeof MenubarPrimitive.Trigger>) { | ||
return ( | ||
<MenubarPrimitive.Trigger | ||
data-slot="menubar-trigger" | ||
className={cn( | ||
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex items-center rounded-sm px-2 py-1 text-sm font-medium outline-hidden select-none", | ||
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
Missing ref
propagation (same problem as dropdown-menu)
MenubarTrigger
(and other wrappers) no longer forward refs, potentially breaking code that relied on it to focus or measure the trigger element. Replicate the forwardRef
pattern to preserve the public API.
🤖 Prompt for AI Agents
In frontend/components/ui/menubar.tsx around lines 51 to 65, the MenubarTrigger
component does not forward refs, which can break functionality relying on ref
access. To fix this, wrap the MenubarTrigger function with React.forwardRef and
pass the ref to MenubarPrimitive.Trigger. Adjust the function signature to
accept ref as the second argument and ensure it is forwarded properly to
maintain the public API.
"bg-popover text-popover-foreground data-[state=open]:animate-in 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-[12rem] origin-(--radix-menubar-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-md", | ||
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.
Invalid origin-(--radix-menubar-content-transform-origin)
value
The arbitrary value is missing var()
, leading to invalid CSS. Use:
-origin-(--radix-menubar-content-transform-origin)
+origin-(var(--radix-menubar-content-transform-origin))
Check also MenubarSubContent
(lines 251-253).
📝 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]: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-[12rem] origin-(--radix-menubar-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-md", | |
className, | |
)} | |
// frontend/components/ui/menubar.tsx | |
… | |
className={cn( | |
"bg-popover text-popover-foreground " + | |
"data-[state=open]:animate-in 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-[12rem] origin-(var(--radix-menubar-content-transform-origin)) " + | |
"overflow-hidden rounded-md border p-1 shadow-md", | |
className, | |
)} | |
… |
🤖 Prompt for AI Agents
In frontend/components/ui/menubar.tsx around lines 82 to 84, the CSS class uses
an invalid arbitrary value origin-(--radix-menubar-content-transform-origin)
missing the var() function. Fix this by wrapping the custom property in var(),
changing it to origin-[var(--radix-menubar-content-transform-origin)]. Also,
check and apply the same fix to MenubarSubContent around lines 251 to 253.
"relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear", | ||
"group-data-[collapsible=offcanvas]:w-0", | ||
"group-data-[side=right]:rotate-180", | ||
variant === "floating" || variant === "inset" | ||
? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]" | ||
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon)", | ||
)} |
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 syntax for width CSS variable
w-(--sidebar-width)
and similar forms occur in many places. Unless you are on an unreleased Tailwind build that supports this shorthand, the correct v4 syntax is:
w-(var(--sidebar-width))
or for v3:
w-[var(--sidebar-width)]
Please audit all occurrences (--sidebar-width
, --sidebar-width-icon
, etc.).
🤖 Prompt for AI Agents
In frontend/components/ui/sidebar.tsx around lines 221 to 227, the Tailwind CSS
width classes use invalid syntax like w-(--sidebar-width). Update these to the
correct syntax by wrapping the CSS variable with var(), for example, change
w-(--sidebar-width) to w-[var(--sidebar-width)] for Tailwind v3 or
w-(var(--sidebar-width)) for v4. Audit and fix all similar occurrences such as
--sidebar-width-icon accordingly.
User description
🫰 Thanks for your Pull Request! Here are some helpful tips:
👀 Purpose and Importance of this PR:
🅰 Fixes for Issues:
Fixes #
📝 Notes for the Reviewer:
🎯 How to Verify this PR:
📑 Additional Documentation, e.g., KEPs (Telepace Enhancement Proposals), Usage Docs, etc.:
Description
Changes walkthrough 📝
sidebar.tsx
Refactor Sidebar Component for Improved Usability
frontend/components/ui/sidebar.tsx
SidebarProvider
andSidebar
components for betterreadability.
PanelLeftIcon
to replaceViewVerticalIcon
.globals.css
Update Tailwind CSS and Custom Variables
frontend/app/globals.css
menubar.tsx
Refactor Menubar Components for Accessibility
frontend/components/ui/menubar.tsx
accessibility.
dropdown-menu.tsx
Refactor Dropdown Menu Components for Accessibility
frontend/components/ui/dropdown-menu.tsx
better accessibility.
select.tsx
Refactor Select Components for Accessibility
frontend/components/ui/select.tsx
accessibility.
toggle.tsx
Add New Toggle Component with Variants
frontend/components/ui/toggle.tsx
Summary by CodeRabbit
New Features
Refactor
Style
Documentation
Chores
Bug Fixes
These updates provide a more flexible, accessible, and visually consistent UI foundation.