Conversation
|
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
📝 WalkthroughWalkthroughThis pull request restructures the dashboard layout and sidebar architecture. The previous sidebar components have been replaced with new ones—AppSidebar, SidebarInset, and SidebarProvider—with updated styling and layout structure. Workspace navigations now import icons from a different library and adjust the corresponding type definitions. Several new UI components have been added, including breadcrumb navigation and a customizable button, along with comprehensive sidebar subcomponents and a new mobile detection hook. Additional configuration updates include changes to the Tailwind setup and an upgraded dependency in the package manifest. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Layout
participant SidebarProvider
participant AppSidebar
participant SidebarInset
User->>Layout: Load application
Layout->>SidebarProvider: Initialize sidebar state
SidebarProvider->>AppSidebar: Render sidebar UI components
AppSidebar->>SidebarInset: Display navigation & main content
User->>AppSidebar: Interact (toggle/sidebar action)
Possibly related PRs
Suggested labels
Suggested reviewers
Tip ⚡🧪 Multi-step agentic review comment chat (experimental)
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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 (
|
|
Thank you for following the naming conventions for pull request titles! 🙏 |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (6)
apps/dashboard/hooks/use-mobile.tsx (1)
5-7: Consider handling SSR more gracefully.Because
windowis only available in the browser, this logic won’t run on the server. That’s fine, but when the component first mounts,isMobileremainsundefinedbriefly. Consider initializing it tofalseor clarifying this behavior in documentation to avoid confusion in a server-side render scenario.apps/dashboard/components/ui/button.tsx (1)
43-56: Set a defaulttype="button"if not otherwise specified.When
<button>is used inside forms, browsers default totype="submit", which can produce unintended behavior. Consider using a default type ofbuttonunless the user specifies otherwise.const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( ({ className, variant, size, asChild = false, ...props }, ref) => { const Comp = asChild ? Slot : "button" return ( <Comp - className={cn(buttonVariants({ variant, size, className }))} + className={cn(buttonVariants({ variant, size, className }))} + type={props.type || "button"} ref={ref} {...props} /> ) } )apps/dashboard/app/(app)/layout.tsx (2)
31-33: Enhance cross-browser compatibility of viewport units.The
h-[100dvh]unit is supported on most modern browsers. Some older or mobile browsers might mishandle it due to browser UI chrome. This is likely fine for a dashboard, but consider known cross-browser caveats if usage on mobile is critical.
40-65: Evaluate user experience for a disabled workspace.The fallback for when
workspace.enabledisfalseis consistent, but it leaves the user in a partially rendered layout with a static message. Consider offering a more explicit call to action (e.g., a button linking to support resources) or additional instructions so users clearly know what to do next.apps/dashboard/app/(app)/workspace-navigations.tsx (1)
45-48: Add test coverage for the Tag component.
This newTagcomponent is a useful addition. Consider adding a light test suite to verify that it correctly renders the provided label and applies custom class names.apps/dashboard/components/app-sidebar.tsx (1)
48-57: Ensure future expansions of nested navigation are handled.
AlthoughcreateNestedNavigationsimply returnsbaseNavfor now, its structure indicates future sub-item logic. Verify that deeper sub-navigation needs are addressed in subsequent iterations.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (11)
apps/dashboard/app/(app)/layout.tsx(2 hunks)apps/dashboard/app/(app)/workspace-navigations.tsx(6 hunks)apps/dashboard/components.json(1 hunks)apps/dashboard/components/app-sidebar.tsx(1 hunks)apps/dashboard/components/ui/breadcrumb.tsx(1 hunks)apps/dashboard/components/ui/button.tsx(1 hunks)apps/dashboard/components/ui/collapsible.tsx(1 hunks)apps/dashboard/components/ui/sidebar.tsx(1 hunks)apps/dashboard/hooks/use-mobile.tsx(1 hunks)apps/dashboard/package.json(1 hunks)internal/ui/tailwind.config.js(1 hunks)
🧰 Additional context used
🧬 Code Definitions (2)
apps/dashboard/app/(app)/workspace-navigations.tsx (1)
apps/dashboard/lib/utils.ts (1) (1)
cn(5-7)
apps/dashboard/app/(app)/layout.tsx (3)
apps/dashboard/components/ui/sidebar.tsx (2) (2)
SidebarProvider(768-768)SidebarInset(758-758)apps/dashboard/components/app-sidebar.tsx (1) (1)
AppSidebar(171-206)internal/ui/src/components/empty.tsx (1) (1)
Empty(6-18)
🪛 Biome (1.9.4)
apps/dashboard/components/ui/breadcrumb.tsx
[error] 64-71: The HTML element with the interactive role "link" is not focusable.
A non-interactive HTML element that is not focusable may not be reachable for users that rely on keyboard navigation, even with an added role like "link".
Add a tabIndex attribute to make this element focusable.
(lint/a11y/useFocusableInteractive)
⏰ Context from checks skipped due to timeout of 90000ms (12)
- GitHub Check: Test Go API Local / Test
- GitHub Check: Test Packages / Test ./internal/resend
- GitHub Check: Test Agent Local / test_agent_local
- GitHub Check: Test Packages / Test ./internal/clickhouse
- GitHub Check: Test Packages / Test ./packages/cache
- GitHub Check: Test API / API Test Local
- GitHub Check: Build / Build
- GitHub Check: Test Packages / Test ./internal/id
- GitHub Check: Test Packages / Test ./internal/hash
- GitHub Check: Docs
- GitHub Check: autofix
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (17)
apps/dashboard/components.json (1)
5-5: Configuration updates look good for supporting the new sidebar componentsThe addition of TSX support and the empty prefix for Tailwind classes will provide a cleaner development experience. The new aliases for UI components, libraries, and hooks create a well-organized import structure that will help maintain consistency across the codebase.
Also applies to: 10-11, 15-18
internal/ui/tailwind.config.js (1)
79-79: New "base" color palette is a good additionThe inclusion of a "base" color set provides more design flexibility for the sidebar implementation. This follows the established pattern for color definition in the application.
Consider documenting this color's purpose and usage in a design system document if not already done.
apps/dashboard/package.json (1)
100-100: Package update to tailwind-merge looks goodUpdating to the newer version (2.5.4) is appropriate when introducing new UI components like the sidebar. This update likely includes performance improvements and bug fixes that will benefit the new implementation.
apps/dashboard/components/ui/collapsible.tsx (1)
1-11: Style formatting changes for consistencyThe removal of semicolons appears to be for code style consistency. While this doesn't affect functionality, maintaining a consistent code style across the project is important.
Ensure these changes align with the project's ESLint configuration or style guide.
apps/dashboard/hooks/use-mobile.tsx (1)
18-19: Enforce consistency on the returned value.Returning
!!isMobileforces a boolean output, which is good. Just ensure all consumers interpretfalsecorrectly for loading states or SSR scenarios.apps/dashboard/components/ui/button.tsx (1)
7-35: Button variants look consistent with the design system.The
class-variance-authoritysetup is neat and covers common variant cases. No issues here.apps/dashboard/app/(app)/layout.tsx (1)
34-39: Check for potential global state overlaps.Wrapping the layout in
<SidebarProvider>might affect anything that uses this global context. Ensure that the new context is only influencing components that need it, particularly if other parts of the dashboard layout expect a different context or layout structure.apps/dashboard/app/(app)/workspace-navigations.tsx (2)
6-14: Switch to the new icon library and broader icon type looks good.
The import changes fromlucide-reactto@unkey/iconsand adjusting theiconproperty from a narrower type toReact.ElementTypeprovide flexibility. This aligns with the PR's objective of refining the dashboard UX.Also applies to: 16-19
62-129: Updated navigation icons align with the new design system.
All icon references have been successfully updated to the@unkey/iconslibrary. This fully supports the PR’s directive for a more unified style.apps/dashboard/components/app-sidebar.tsx (4)
38-46: Utility function for button styles is concise.
ThegetButtonStylesfunction cleanly merges conditional classNames, which simplifies style management in various states.
59-168: Good use of concurrent UI state transitions.
EmployinguseTransitionfor navigation feedback is a neat pattern. It keeps the UI responsive by showing a spinner while transitioning.
170-206: AppSidebar integrates neatly into the layout.
The structure, includingSidebarHeader,SidebarContent, andSidebarFooter, helps maintain a clear separation of layout elements.
208-281: Animated spinner handles reduced motion gracefully.
The logic respects user motion preferences withprefers-reduced-motion. This attention to accessibility is commendable.apps/dashboard/components/ui/sidebar.tsx (4)
56-163: SidebarProvider properly manages sidebar state with cookies.
Storing and restoring the sidebar state via cookies and providing a controlled vs. uncontrolled API is a solid design.
165-270: Core Sidebar component logic is clear and flexible.
The variant-based approach (sidebar, floating, inset) keeps styling concerns organized. Collapsible patterns are well handled.
546-603: Tooltip logic for collapsed sidebars is well-structured.
Conditionally displaying the tooltip when the sidebar is collapsed is a nice touch, improving discoverability of icons.
712-717: Sub-item structure is straightforward.
SidebarMenuSubItemis a simple container that cleanly separates sub-menu item logic.
| 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.
🛠️ Refactor suggestion
Provide a fallback for older browsers.
mql.addEventListener("change", onChange) is not supported in some older browsers, which still rely on mql.addListener. You may want a small compatibility fallback if older browsers must be supported.
React.useEffect(() => {
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
- mql.addEventListener("change", onChange)
+ if (mql.addEventListener) {
+ mql.addEventListener("change", onChange)
+ } else {
+ mql.addListener(onChange)
+ }
return () => {
- mql.removeEventListener("change", onChange)
+ if (mql.removeEventListener) {
+ 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 (mql.addEventListener) { | |
| mql.addEventListener("change", onChange) | |
| } else { | |
| mql.addListener(onChange) | |
| } | |
| setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) | |
| return () => { | |
| if (mql.removeEventListener) { | |
| mql.removeEventListener("change", onChange) | |
| } else { | |
| mql.removeListener(onChange) | |
| } | |
| } | |
| }, []) |
| <span | ||
| ref={ref} | ||
| role="link" | ||
| aria-disabled="true" | ||
| aria-current="page" | ||
| className={cn("font-normal text-foreground", className)} | ||
| {...props} | ||
| /> |
There was a problem hiding this comment.
Resolve accessibility issue with non-focusable link role.
Using role="link" on a <span> that lacks focusability conflicts with accessibility guidelines. Either remove the link role or add a tabIndex={0} and an appropriate click handler if you want keyboard users to navigate.
- <span
- role="link"
- aria-disabled="true"
- aria-current="page"
- ...
- />
+ <span
+ aria-disabled="true"
+ aria-current="page"
+ ...
+ />📝 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.
| <span | |
| ref={ref} | |
| role="link" | |
| aria-disabled="true" | |
| aria-current="page" | |
| className={cn("font-normal text-foreground", className)} | |
| {...props} | |
| /> | |
| <span | |
| ref={ref} | |
| aria-disabled="true" | |
| aria-current="page" | |
| className={cn("font-normal text-foreground", className)} | |
| {...props} | |
| /> |
🧰 Tools
🪛 Biome (1.9.4)
[error] 64-71: The HTML element with the interactive role "link" is not focusable.
A non-interactive HTML element that is not focusable may not be reachable for users that rely on keyboard navigation, even with an added role like "link".
Add a tabIndex attribute to make this element focusable.
(lint/a11y/useFocusableInteractive)
What does this PR do?
Fixes # (issue)
If there is not an issue for this, please create one first. This is used to tracking purposes and also helps use understand why this PR exists
Type of change
How should this be tested?
Checklist
Required
pnpm buildpnpm fmtconsole.logsgit pull origin mainAppreciated
Summary by CodeRabbit
New Features
Style
Chores