Skip to content
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

feat: add new nested routes #3027

Merged
merged 25 commits into from
Apr 7, 2025
Merged

feat: add new nested routes #3027

merged 25 commits into from
Apr 7, 2025

Conversation

ogzhanolguncu
Copy link
Contributor

@ogzhanolguncu ogzhanolguncu commented Mar 24, 2025

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

  • Bug fix (non-breaking change which fixes an issue)
  • Chore (refactoring code, technical debt, workflow improvements)
  • Enhancement (small improvements)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How should this be tested?

  • Test A
  • Test B

Checklist

Required

  • Filled out the "How to test" section in this PR
  • Read Contributing Guide
  • Self-reviewed my own code
  • Commented on my code in hard-to-understand areas
  • Ran pnpm build
  • Ran pnpm fmt
  • Checked for warnings, there are none
  • Removed all console.logs
  • Merged the latest changes from main onto my branch with git pull origin main
  • My changes don't cause any responsiveness issues

Appreciated

  • If a UI change was made: Added a screen recording or screenshots to this PR
  • Updated the Unkey Docs if changes were necessary

Summary by CodeRabbit

  • New Features

    • Enhanced sidebar navigation with new expandable, nested items and improved load-more support.
    • Introduced an animated loading spinner for a smoother visual experience.
    • Updated the API creation flow to refresh the API overview automatically.
    • Added a new sidebar component for workspace navigation, integrating API and rate limit navigation.
    • Introduced new components for handling navigation items, including FlatNavItem, NavLink, NestedNavItem, ToggleSidebarButton, and AnimatedLoadingSpinner.
    • Added new custom hooks for API and rate limit navigation.
    • Enhanced the StatsTimeseriesBarChart with improved responsiveness.
    • Introduced new icons for enhanced visual representation.
    • Added a new ArrowDottedRotateAnticlockwise icon and an ArrowOppositeDirectionY icon.
  • Bug Fixes

    • Improved chart rendering performance for a more responsive display.
    • Enhanced error handling for icon rendering in navigation components.
  • Style

    • Refined dialog backgrounds and layout spacing for a cleaner and more consistent UI.
    • Updated sidebar menu styles to enhance nested item management.
    • Adjusted padding in the API list grid for better spacing.
    • Improved spacing in the sidebar menu to manage nested items effectively.

Copy link

changeset-bot bot commented Mar 24, 2025

⚠️ No Changeset found

Latest commit: 59d5c5f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link

vercel bot commented Mar 24, 2025

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

Name Status Preview Comments Updated (UTC)
dashboard ✅ Ready (Inspect) Visit Preview 💬 2 unresolved
✅ 7 resolved
Apr 7, 2025 5:57pm
engineering ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 7, 2025 5:57pm
play ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 7, 2025 5:57pm
www ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 7, 2025 5:57pm

Copy link
Contributor

coderabbitai bot commented Mar 24, 2025

📝 Walkthrough

Walkthrough

This pull request implements multiple changes across the dashboard. The ApiListCard component stops tracking the loading state, and API data fetching in actions is updated to include keyspace details. The AppSidebar and its associated navigation components are overhauled with new components, hooks, and utilities to support nested items, load-more actions, and revised styling. Additionally, new TRPC routers and schemas for ratelimit namespaces are introduced, an icon component is updated for dynamic sizing, and minor UI tweaks are applied to charts and API buttons to enhance cache invalidation and spacing.

Changes

File(s) Change Summary
apps/dashboard/app/(app)/apis/_components/api-list-card.tsx
apps/dashboard/app/(app)/apis/actions.ts
apps/dashboard/app/(app)/apis/_components/create-api-button.tsx
apps/dashboard/app/(app)/apis/_components/api-list-grid.tsx
API Components & Actions: ApiListCard now uses a hardcoded loading state; actions.ts is updated to fetch keyAuth details with a Promise.all transformation; CreateApiButton now invalidates the API overview cache; ApiListGrid gains extra padding for improved spacing.
apps/dashboard/app/(app)/layout.tsx
apps/dashboard/components/navigation/sidebar/app-sidebar/**
apps/dashboard/components/ui/sidebar.tsx
apps/dashboard/components/navigation/sidebar/workspace-navigations.tsx
Sidebar Navigation & Layout Updates: Updated import path in layout; introduced new components (AnimatedLoadingSpinner, FlatNavItem, NavItems, NestedNavItem, ToggleSidebarButton, NavLink) and utilities; added hooks (useApiNavigation, useRatelimitNavigation) to enable nested navigation with load-more functionality; enhanced NavItem type with sub-item support and adjusted styling in SidebarMenuSub.
apps/dashboard/components/stats-card/components/chart/stats-chart.tsx Stats Chart Update: Added a debounce property (set to 1000) to the ResponsiveContainer in the StatsTimeseriesBarChart.
apps/dashboard/lib/trpc/routers/api/overview/query-overview/schemas.ts
apps/dashboard/lib/trpc/routers/index.ts
apps/dashboard/lib/trpc/routers/ratelimit/query-keys/index.ts
apps/dashboard/lib/trpc/routers/ratelimit/query-keys/schemas.ts
TRPC & Rate Limit Schemas/Routers: Added a new TRPC router and schemas for querying ratelimit namespaces, included a backward compatibility comment in the API overview schema, and provided helper functions and types for ratelimit queries.
internal/icons/src/icons/caret-right.tsx Icon Component Update: Modified the CaretRight component to destructure a size prop (default "xl-thin"), allowing dynamic adjustment of pixel size and stroke width based on a sizeMap.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant Sidebar as AppSidebar
    participant Hook as useApiNavigation / useRatelimitNavigation
    participant TRPC as TRPC Server

    User->>Sidebar: Interact with sidebar/navigation
    Sidebar->>Hook: Request enhanced navigation items
    Hook->>TRPC: Fetch paginated API/ratelimit data
    TRPC-->>Hook: Return navigation data with pagination info
    Hook-->>Sidebar: Return enhanced navigation items (including "Load More")
    Sidebar->>User: Render updated sidebar menu
Loading

Possibly related PRs

  • feat: apis overview v2 #2918: The changes in the main PR, which involve modifications to the ApiListCard component, are related to the retrieved PR as both involve the ApiListCard component and its interaction with the useFetchVerificationTimeseries hook. Specifically, the main PR alters how loading states are handled in the ApiListCard, while the retrieved PR introduces the ApiListCard component itself, which also utilizes the same hook for fetching data.

Suggested labels

Feature, Dashboard, 🕹️ oss.gg, :joystick: 300 points, hacktoberfest


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c6da336 and 59d5c5f.

📒 Files selected for processing (1)
  • apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/nested-nav-item.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/nested-nav-item.tsx
⏰ Context from checks skipped due to timeout of 90000ms (16)
  • GitHub Check: Test Go API Local / Test (Shard 8/8)
  • GitHub Check: Test Go API Local / Test (Shard 3/8)
  • GitHub Check: Test Go API Local / Test (Shard 7/8)
  • GitHub Check: Test Go API Local / Test (Shard 2/8)
  • GitHub Check: Test Go API Local / Test (Shard 5/8)
  • GitHub Check: Test Go API Local / Test (Shard 4/8)
  • GitHub Check: Test Go API Local / Test (Shard 6/8)
  • GitHub Check: Test Agent Local / test_agent_local
  • GitHub Check: Test Go API Local / Test (Shard 1/8)
  • GitHub Check: Test Packages / Test ./internal/resend
  • GitHub Check: Test Packages / Test ./internal/clickhouse
  • GitHub Check: Test Packages / Test ./internal/id
  • GitHub Check: Test API / API Test Local
  • GitHub Check: Build / Build
  • GitHub Check: autofix
  • GitHub Check: Analyze (javascript-typescript)

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

github-actions bot commented Mar 24, 2025

Thank you for following the naming conventions for pull request titles! 🙏

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (24)
apps/dashboard/app/(app)/apis/_components/api-list-card.tsx (1)

29-31: Performance improvement: Eliminated loading state for multiple charts

Replacing the dynamic loading state with a hardcoded false value is a good optimization for scenarios with multiple charts. The comment clearly explains the rationale behind this change.

However, consider implementing a staggered loading approach if users experience a perception of unresponsiveness with no loading indicators.

apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/toggle-sidebar-button.tsx (1)

20-20: Consider adding size fallback for icon

While using the size="xl-medium" prop is good, consider implementing a fallback or default size in case the icon component doesn't support this specific size prop.

-        {toggleNavItem.icon && <toggleNavItem.icon size="xl-medium" />}
+        {toggleNavItem.icon && <toggleNavItem.icon size="xl-medium" className="size-5" />}
apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-link.tsx (1)

17-23: Enhance accessibility for load more button

The button implementation for load more functionality should include accessibility attributes to improve screen reader support.

-      <button type="button" onClick={onClick} className="w-full text-left">
+      <button 
+        type="button" 
+        onClick={onClick} 
+        className="w-full text-left"
+        aria-label="Load more items"
+      >
        {children}
      </button>
apps/dashboard/app/(app)/apis/actions.ts (1)

63-88: Improved data transformation with detailed key information

The transformation logic now includes key details and maintains backward compatibility with the previous structure. Consider adding error handling for any potential failures during the Promise.all execution.

 const apiList = await Promise.all(
   apiItems.map(async (api) => {
-    const keyspaceId = api.keyAuth?.id || null;
+    try {
+      const keyspaceId = api.keyAuth?.id || null;

       // Transform the keys data for the new keyDetails field
       const keyDetails =
         api.keyAuth?.keys?.map((key) => ({
           id: key.id,
           name: key.name,
         })) || [];

       return {
         id: api.id,
         name: api.name,
         keyspaceId,
         keyDetails,
         // Include count for backward compatibility
         keys: [
           {
             count: api.keyAuth?.sizeApprox || 0,
           },
         ],
       };
+    } catch (error) {
+      console.error(`Error transforming API data for ${api.id}:`, error);
+      // Return a minimal object with required fields
+      return {
+        id: api.id,
+        name: api.name,
+        keyspaceId: null,
+        keyDetails: [],
+        keys: [{ count: 0 }],
+      };
+    }
   }),
 );
apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/utils.ts (1)

13-25: SVG path utility needs bounds checking

While the implementation of getPathForSegment works, it's missing validation for out-of-range indices, which could lead to undefined being returned.

 export function getPathForSegment(index: number) {
   const paths = [
     "M13.162,3.82c-.148,0-.299-.044-.431-.136-.784-.552-1.662-.915-2.61-1.08-.407-.071-.681-.459-.61-.867,.071-.408,.459-.684,.868-.61,1.167,.203,2.248,.65,3.216,1.33,.339,.238,.42,.706,.182,1.045-.146,.208-.378,.319-.614,.319Z",
     "M16.136,8.5c-.357,0-.675-.257-.738-.622-.163-.942-.527-1.82-1.082-2.608-.238-.339-.157-.807,.182-1.045,.34-.239,.809-.156,1.045,.182,.683,.97,1.132,2.052,1.334,3.214,.07,.408-.203,.796-.611,.867-.043,.008-.086,.011-.129,.011Z",
     "M14.93,13.913c-.148,0-.299-.044-.431-.137-.339-.238-.42-.706-.182-1.045,.551-.784,.914-1.662,1.078-2.609,.071-.408,.466-.684,.867-.611,.408,.071,.682,.459,.611,.867-.203,1.167-.65,2.25-1.33,3.216-.146,.208-.378,.318-.614,.318Z",
     "M10.249,16.887c-.357,0-.675-.257-.738-.621-.07-.408,.202-.797,.61-.868,.945-.165,1.822-.529,2.608-1.082,.34-.238,.807-.156,1.045,.182,.238,.338,.157,.807-.182,1.045-.968,.682-2.05,1.13-3.214,1.333-.044,.008-.087,.011-.13,.011Z",
     "M7.751,16.885c-.043,0-.086-.003-.13-.011-1.167-.203-2.249-.651-3.216-1.33-.339-.238-.42-.706-.182-1.045,.236-.339,.702-.421,1.045-.183,.784,.551,1.662,.915,2.61,1.08,.408,.071,.681,.459,.61,.868-.063,.364-.381,.621-.738,.621Z",
     "M3.072,13.911c-.236,0-.469-.111-.614-.318-.683-.97-1.132-2.052-1.334-3.214-.07-.408,.203-.796,.611-.867,.403-.073,.796,.202,.867,.61,.163,.942,.527,1.82,1.082,2.608,.238,.339,.157,.807-.182,1.045-.131,.092-.282,.137-.431,.137Z",
     "M1.866,8.5c-.043,0-.086-.003-.129-.011-.408-.071-.682-.459-.611-.867,.203-1.167,.65-2.25,1.33-3.216,.236-.339,.703-.422,1.045-.182,.339,.238,.42,.706,.182,1.045-.551,.784-.914,1.662-1.078,2.609-.063,.365-.381,.622-.738,.622Z",
     "M4.84,3.821c-.236,0-.468-.111-.614-.318-.238-.338-.157-.807,.182-1.045,.968-.682,2.05-1.13,3.214-1.333,.41-.072,.797,.202,.868,.61,.07,.408-.202,.797-.61,.868-.945,.165-1.822,.529-2.608,1.082-.131,.092-.282,.137-.431,.137Z",
   ];
-  return paths[index];
+  if (index >= 0 && index < paths.length) {
+    return paths[index];
+  }
+  console.warn(`Invalid path index: ${index}. Expected 0-${paths.length - 1}`);
+  return paths[0]; // Default to first path as fallback
 }
apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/animated-loading-spinner.tsx (1)

8-33: Consider using a CSS-in-JS solution for handling styles.

The direct DOM manipulation to inject styles, while appropriately guarded against duplication with the STYLE_ID check, could be replaced with a more React-friendly approach like CSS modules or a CSS-in-JS library that's already in use in the project.

- // Add styles only once when module is loaded
- if (typeof document !== "undefined" && !document.getElementById(STYLE_ID)) {
-   const style = document.createElement("style");
-   style.id = STYLE_ID;
-   style.textContent = `
-     @media (prefers-reduced-motion: reduce) {
-       [data-prefers-reduced-motion="respect-motion-preference"] {
-         animation: none !important;
-         transition: none !important;
-       }
-     }
-     
-     @keyframes spin-slow {
-       from {
-         transform: rotate(0deg);
-       }
-       to {
-         transform: rotate(360deg);
-       }
-     }
-     
-     .animate-spin-slow {
-       animation: spin-slow 1.5s linear infinite;
-     }
-   `;
-   document.head.appendChild(style);
- }

Consider moving these styles to a CSS module or using your project's existing styling solution.

apps/dashboard/components/navigation/sidebar/app-sidebar/hooks/use-api-navigation.tsx (2)

87-88: Remove TypeScript ignore comment and fix the type issue.

The code includes a @ts-expect-error with a comment "will fix that later", which should be addressed now rather than left for future work.

- //@ts-expect-error will fix that later
- label: <div className="font-normal decoration-dotted underline ">More</div>,
+ label: <div className="font-normal decoration-dotted underline ">More</div> as React.ReactNode,

Alternatively, update the NavItem type to properly type the label property to accept React nodes.


57-95: Ensure consistent implementation between "More" items across hooks.

In this hook, the "More" button is styled with an underline, while in the useRatelimitNavigation hook, it's a plain text. Consider standardizing the UI for consistency.

apps/dashboard/components/navigation/sidebar/app-sidebar/hooks/use-ratelimit-navigation.tsx (2)

85-86: Standardize styling for "More" buttons across navigation hooks.

Unlike in useApiNavigation, this hook uses a plain string for the "More" button without styling. Ensure consistent styling across similar UI elements.

- label: "More",
+ label: <div className="font-normal decoration-dotted underline ">More</div>,

77-92: Add showSubItems property for consistency with useApiNavigation.

In useApiNavigation, you set showSubItems: true for the APIs section, but this property is missing here for the ratelimits section. For consistency, consider adding it.

if (ratelimitsItemIndex !== -1) {
  const ratelimitsItem = { ...items[ratelimitsItemIndex] };
+ // Always set showSubItems to true for the Ratelimits section
+ ratelimitsItem.showSubItems = true;
  ratelimitsItem.items = [...(ratelimitsItem.items || []), ...ratelimitNavItems];
apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/flat-nav-item.tsx (1)

50-50: Simplify conditional rendering of loading spinner or icon.

The current implementation has a nested ternary expression which can be simplified for better readability.

- {showLoader ? <AnimatedLoadingSpinner /> : Icon ? <Icon size="xl-medium" /> : null}
+ {showLoader ? <AnimatedLoadingSpinner /> : Icon && <Icon size="xl-medium" />}
apps/dashboard/components/ui/sidebar.tsx (1)

525-546: Consider validating depth and maxDepth inputs.

Currently, negative or otherwise unexpected values for depth or maxDepth may cause unpredictable styles or logic if not handled. While this scenario may be unlikely, adding basic validation or clamping the values can prevent subtle bugs, especially in dynamic sidebar configurations.

apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/nested-nav-item.tsx (4)

36-40: Ensure keyboard accessibility for chevron toggle.

Handling click events is fine, but users navigating via keyboard and screen readers may need a keypress handler or an accessible element (e.g., a button). Consider adding a role="button" and handling Enter/Space keys for inclusive design.


42-54: Add noopener noreferrer for external links.

When opening external links in a new tab with _blank, set rel="noopener noreferrer" to avoid potential security vulnerabilities where the new page can access window.opener.

- window.open(item.href, "_blank");
+ window.open(item.href, "_blank", "noopener,noreferrer");

56-129: Revisit the 300ms timeout after navigation.

The fixed 300ms delay in resetting the sub-item loading state might become brittle. For instance, if the actual navigation or rendering takes longer than 300ms, your UI might revert to a non-loading state prematurely. Consider using route change events or callbacks to ensure your loader state aligns with actual navigation completion.


131-175: Improve accessibility for nested items.

Embedding the chevron click area inside the main button is thorough, but ensure that nested sub-items and deeper collapsibles remain keyboard-accessible. You might provide a dedicated keyboard handler on the chevron section or unify the toggling with the main button to meet WCAG guidelines.

Would you like help creating an accessible wrapper or reworking the click event for this nested structure?

apps/dashboard/components/navigation/sidebar/app-sidebar/index.tsx (2)

45-56: Unify load-more actions for clarity.

Currently, load-more logic is bifurcated between APIs and Ratelimits. Although it works, consider extracting a shared handler or naming them distinctly (e.g., loadMoreApis vs. loadMoreRatelimits) to avoid confusion. This can future-proof the code for additional resource types.


72-90: Add a tooltip for the hide icon when sidebar is not collapsed.

For consistency, you could show a quick tooltip or label for the icon at line 83 to communicate its action—for users who may not recognize the icon at a glance. This minor UX improvement can help discoverability.

apps/dashboard/lib/trpc/routers/ratelimit/query-keys/schemas.ts (3)

1-27: Schema structure looks good, consider adding documentation.

The Zod schemas for ratelimit namespaces are well-structured, with appropriate types and validations. Consider adding JSDoc comments to document the purpose of each schema and its fields for better developer experience.

You could enhance this file with documentation like:

+/**
+ * Represents a ratelimit namespace with unique identifier and display name
+ */
 export const ratelimitNamespace = z.object({
   id: z.string(),
   name: z.string(),
 });

+/**
+ * Pagination cursor used for fetching subsequent pages
+ */
 const Cursor = z.object({
   id: z.string(),
 });

14-19: Consider exposing Cursor schema for consistency.

While the Cursor schema is used internally within this file, it might be useful to export it for reuse elsewhere, especially since it's referenced in multiple schemas.

-const Cursor = z.object({
+export const Cursor = z.object({
   id: z.string(),
 });

23-26: Validate cursor id if cursor is provided.

The current schema doesn't validate the cursor id when a cursor is provided. Consider adding a refinement to ensure the cursor id is not empty when it's present.

 export const queryRatelimitNamespacesPayload = z.object({
   limit: z.number().min(1).max(18).default(9),
-  cursor: Cursor.optional(),
+  cursor: Cursor.optional().refine(
+    (data) => !data || data.id.trim().length > 0,
+    { message: "Cursor ID cannot be empty if cursor is provided" }
+  ),
 });
apps/dashboard/lib/trpc/routers/ratelimit/query-keys/index.ts (2)

22-25: Consider structured error logging.

The current error logging concatenates the error object as a JSON string, which might not capture all error properties correctly, especially for non-serializable properties.

-      console.error(
-        "Something went wrong when fetching ratelimit namespaces",
-        JSON.stringify(error),
-      );
+      console.error(
+        "Something went wrong when fetching ratelimit namespaces",
+        error instanceof Error ? { message: error.message, stack: error.stack } : error,
+      );

45-55: Consider optimizing the total count query.

The separate query for the total count could be inefficient for large datasets. Consider using a single query with a count window function if your database supports it, or implementing cursor-based pagination without requiring the total count.

apps/dashboard/components/navigation/sidebar/workspace-navigations.tsx (1)

173-186: Consider updating resourcesNavigation to match new NavItem type.

The resourcesNavigation array items should be updated to explicitly set the newly added properties to maintain consistency, even if they're optional.

 export const resourcesNavigation: NavItem[] = [
   {
     icon: BookBookmark,
     href: "https://unkey.dev/docs",
     external: true,
     label: "Docs",
+    items: undefined,
+    showSubItems: undefined,
   },
   {
     icon: DiscordIcon,
     href: "https://www.unkey.com/discord",
     external: true,
     label: "Discord",
+    items: undefined,
+    showSubItems: undefined,
   },
 ];
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 3ef6b02 and ae91abd.

📒 Files selected for processing (23)
  • apps/dashboard/app/(app)/apis/_components/api-list-card.tsx (2 hunks)
  • apps/dashboard/app/(app)/apis/actions.ts (3 hunks)
  • apps/dashboard/app/(app)/layout.tsx (1 hunks)
  • apps/dashboard/app/(app)/settings/root-keys/new/client.tsx (1 hunks)
  • apps/dashboard/components/app-sidebar.tsx (0 hunks)
  • apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/animated-loading-spinner.tsx (1 hunks)
  • apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/flat-nav-item.tsx (1 hunks)
  • apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/index.tsx (1 hunks)
  • apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/nested-nav-item.tsx (1 hunks)
  • apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/toggle-sidebar-button.tsx (1 hunks)
  • apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/utils.ts (1 hunks)
  • apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-link.tsx (1 hunks)
  • apps/dashboard/components/navigation/sidebar/app-sidebar/hooks/use-api-navigation.tsx (1 hunks)
  • apps/dashboard/components/navigation/sidebar/app-sidebar/hooks/use-ratelimit-navigation.tsx (1 hunks)
  • apps/dashboard/components/navigation/sidebar/app-sidebar/index.tsx (1 hunks)
  • apps/dashboard/components/navigation/sidebar/workspace-navigations.tsx (4 hunks)
  • apps/dashboard/components/stats-card/components/chart/stats-chart.tsx (1 hunks)
  • apps/dashboard/components/ui/sidebar.tsx (1 hunks)
  • apps/dashboard/lib/trpc/routers/api/overview/query-overview/schemas.ts (2 hunks)
  • apps/dashboard/lib/trpc/routers/index.ts (2 hunks)
  • apps/dashboard/lib/trpc/routers/ratelimit/query-keys/index.ts (1 hunks)
  • apps/dashboard/lib/trpc/routers/ratelimit/query-keys/schemas.ts (1 hunks)
  • internal/icons/src/icons/caret-right.tsx (1 hunks)
💤 Files with no reviewable changes (1)
  • apps/dashboard/components/app-sidebar.tsx
🧰 Additional context used
🧬 Code Definitions (9)
apps/dashboard/lib/trpc/routers/index.ts (1)
apps/dashboard/lib/trpc/routers/ratelimit/query-keys/index.ts (1)
  • queryRatelimitNamespaces (10-31)
apps/dashboard/app/(app)/apis/_components/api-list-card.tsx (1)
apps/dashboard/app/(app)/apis/_components/hooks/use-query-timeseries.ts (1)
  • useFetchVerificationTimeseries (8-73)
apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/index.tsx (3)
apps/dashboard/components/navigation/sidebar/workspace-navigations.tsx (1)
  • NavItem (16-29)
apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/flat-nav-item.tsx (1)
  • FlatNavItem (10-57)
apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/nested-nav-item.tsx (1)
  • NestedNavItem (18-176)
apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/toggle-sidebar-button.tsx (2)
apps/dashboard/components/navigation/sidebar/workspace-navigations.tsx (1)
  • NavItem (16-29)
apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/utils.ts (1)
  • getButtonStyles (3-11)
apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/animated-loading-spinner.tsx (1)
apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/utils.ts (1)
  • getPathForSegment (13-25)
apps/dashboard/components/navigation/sidebar/app-sidebar/index.tsx (5)
apps/dashboard/components/navigation/sidebar/workspace-navigations.tsx (3)
  • createWorkspaceNavigation (59-171)
  • NavItem (16-29)
  • resourcesNavigation (173-186)
apps/dashboard/components/navigation/sidebar/app-sidebar/hooks/use-api-navigation.tsx (1)
  • useApiNavigation (11-111)
apps/dashboard/components/navigation/sidebar/app-sidebar/hooks/use-ratelimit-navigation.tsx (1)
  • useRatelimitNavigation (11-108)
apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/toggle-sidebar-button.tsx (1)
  • ToggleSidebarButton (5-25)
apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/index.tsx (1)
  • NavItems (5-19)
apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/flat-nav-item.tsx (4)
apps/dashboard/components/navigation/sidebar/workspace-navigations.tsx (1)
  • NavItem (16-29)
apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-link.tsx (1)
  • NavLink (3-35)
apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/utils.ts (1)
  • getButtonStyles (3-11)
apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/animated-loading-spinner.tsx (1)
  • AnimatedLoadingSpinner (46-91)
apps/dashboard/app/(app)/apis/actions.ts (1)
internal/clickhouse/src/index.ts (1)
  • api (177-196)
apps/dashboard/lib/trpc/routers/ratelimit/query-keys/index.ts (1)
apps/dashboard/lib/trpc/routers/ratelimit/query-keys/schemas.ts (3)
  • queryRatelimitNamespacesPayload (23-26)
  • ratelimitNamespacesResponse (14-19)
  • RatelimitNamespacesResponse (21-21)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Test Agent Local / test_agent_local
  • GitHub Check: Test API / API Test Local
  • GitHub Check: Build / Build
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (38)
apps/dashboard/components/stats-card/components/chart/stats-chart.tsx (1)

46-46: Performance optimization with debounce parameter

Adding the debounce parameter to the ResponsiveContainer is a good improvement. This will reduce the number of re-renders when resizing the window by waiting 1000ms before triggering a re-render, which can help improve performance especially on slower devices.

apps/dashboard/lib/trpc/routers/index.ts (2)

40-40: LGTM: New ratelimit namespaces import

Importing the queryRatelimitNamespaces function to support the new nested routes feature.


151-151: Added support for ratelimit namespace queries

Good addition of the namespace query endpoint to the ratelimit router. This supports the new nested routes feature by enabling retrieval of ratelimit namespace data.

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

1-1: Updated import path to new sidebar structure

The import path change reflects the restructured sidebar organization. This adaptation is needed for the new nested routes feature.

apps/dashboard/app/(app)/settings/root-keys/new/client.tsx (1)

282-282: Enhanced dialog styling with proper dark mode support

The DialogContent styling has been improved to explicitly support both light and dark modes. The addition of bg-white for light mode and maintaining dark:bg-grayA-1 for dark mode ensures consistent appearance across theme settings.

apps/dashboard/app/(app)/apis/_components/api-list-card.tsx (1)

15-15: Performance optimization: Removed loading state from hook destructuring

The isLoading state has been removed from the destructured hook return, aligning with the hardcoded false value passed to the chart component.

apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/toggle-sidebar-button.tsx (1)

1-25: LGTM: Well-implemented sidebar toggle button component

This component effectively handles sidebar toggling functionality with proper type definitions and follows the project's UI patterns. The implementation correctly uses the provided utility functions and component hierarchy.

apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-link.tsx (1)

3-35: Versatile navigation link component with conditional rendering

This component elegantly handles both standard navigation and "load more" functionality, providing appropriate behavior for each use case. The external link handling is also properly implemented with target="_blank" and prefetch control.

apps/dashboard/lib/trpc/routers/api/overview/query-overview/schemas.ts (3)

3-8: Well-structured key detail schema implementation

The new keyDetail schema is cleanly defined with appropriate types for the required properties.


13-20: Good backward compatibility handling with new schema field

Making keyDetails optional while maintaining the existing keys array with a clear comment about backward compatibility is a thoughtful approach to schema evolution.


42-43: Properly exported type for wider usage

Exporting the KeyDetail type derived from the schema is good practice for maintaining type consistency across the codebase.

apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/index.tsx (1)

1-19: Well-structured component with clear conditional rendering logic!

This implementation cleanly handles both flat and nested navigation items. The component properly forwards the onLoadMore callback, which is essential for pagination functionality in navigation lists.

internal/icons/src/icons/caret-right.tsx (3)

13-16: Good enhancement to support dynamic sizing!

The update to include sizeMap and extract dynamic values improves the component's flexibility.


18-24: Properly implemented dynamic dimensions while maintaining fixed viewBox

The SVG now uses dynamic height and width from the size map while maintaining a fixed viewBox, which is a good approach for scalable icons.


32-32: Dynamic stroke width implementation

Using the dynamic strokeWidth from the size map ensures consistent proportions across different icon sizes.

apps/dashboard/app/(app)/apis/actions.ts (1)

22-51: Enhanced query with more detailed key information

The updated query now includes the keyspace ID and fetches actual keys, providing richer data for the navigation components. This will be valuable for the nested routes feature.

apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/utils.ts (1)

3-11: Well-implemented button styling utility

The getButtonStyles function provides a clean way to generate consistent button styles based on active and loading states.

apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/animated-loading-spinner.tsx (3)

35-44: Good use of descriptive comments for segment positions.

The comments clearly document the position of each segment in the spinner, which enhances code readability.


49-56: Proper cleanup of interval in useEffect.

The interval is correctly cleared in the useEffect cleanup function, which prevents memory leaks when the component unmounts.


58-90: Good accessibility implementation with reduced motion preferences.

The component respects user preferences for reduced motion using the data-prefers-reduced-motion attribute, which is excellent for accessibility.

apps/dashboard/components/navigation/sidebar/app-sidebar/hooks/use-api-navigation.tsx (2)

11-23: Implementation of infinite query for API data looks good.

The hook properly sets up an infinite query with pagination handling using TRPC. The use of getNextPageParam to extract the cursor from the response is appropriate.


25-71: Well-structured navigation item creation with clear comments.

The code effectively transforms API data into navigation items with appropriate sub-items. The comments explaining the purpose of each section enhance readability.

apps/dashboard/components/navigation/sidebar/app-sidebar/hooks/use-ratelimit-navigation.tsx (2)

11-23: Well-implemented infinite query for ratelimit namespaces.

The hook correctly sets up an infinite query using TRPC with appropriate pagination handling.


25-71: Good structure for namespace navigation items with multiple sub-items.

The creation of ratelimit namespace navigation items with logs, settings, and overrides sub-items is well-organized and clearly commented.

apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/flat-nav-item.tsx (3)

17-19: Good use of delayed loading indicator for better UX.

The combination of React's useTransition with a custom useDelayLoader hook creates a smoother user experience by preventing flickering of loading indicators during quick transitions.


24-35: Well-structured navigation handling with support for load more action.

The click handler properly differentiates between load more buttons and regular navigation items, with appropriate transition handling for internal navigation.


37-55: Good component composition with appropriate props passing.

The component properly composes SidebarMenuItem, NavLink, and SidebarMenuButton with appropriate props, making the code modular and maintainable.

apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/nested-nav-item.tsx (2)

1-16: Imports look organized.

The introduced imports are consistent with the rest of the code and appear to be used properly. No issues identified here.


18-35: Align maxDepth defaults across components.

You are setting maxDepth = 1 here, whereas the SidebarMenuSub in sidebar.tsx defaults to maxDepth = 2. Consider whether different defaults are intended or if keeping them in sync would ensure consistent behavior across nested items.

apps/dashboard/components/navigation/sidebar/app-sidebar/index.tsx (2)

28-37: Good modular approach for AppSidebar.

Your function properly composes pieces from the workspace navigation, API, and rate limit hooks, keeping concerns separate. This is a well-structured entry point to the new nested routing logic.


94-121: Consider adding test coverage for toggling and load-more flows.

Your code modifies the navigation items depending on user interaction. Automated tests covering the toggle button (lines 100-102) and the dynamic load-more process (lines 103-109) could help prevent regressions, especially as you refine or add more nested resources.

Would you like to generate a basic test suite to confirm that toggling, load-more calls, and the resulting UI match expectations?

apps/dashboard/lib/trpc/routers/ratelimit/query-keys/index.ts (3)

10-31: Well-structured TRPC procedure with proper error handling.

The queryRatelimitNamespaces procedure is well-implemented with appropriate input/output schemas and error handling. The use of rateLimitedProcedure ensures rate limiting is applied correctly.


57-72: Good use of database query builders for pagination.

The implementation correctly uses the query builder pattern to construct a paginated query with proper conditions based on the cursor. The ordering and limit handling for pagination is implemented correctly.


74-87: Well-implemented cursor-based pagination logic.

The pagination logic correctly determines if there are more items by fetching one extra item, and properly calculates the next cursor based on the last item in the result set.

apps/dashboard/components/navigation/sidebar/workspace-navigations.tsx (4)

16-29: Good update to NavItem type to support nested navigation.

The NavItem type has been enhanced to support nested navigation with the addition of items, loadMoreAction, and showSubItems properties. The change to allow null for icons is appropriate for sub-items that don't need icons.


69-69: APIs navigation item prepared for future sub-items.

The showSubItems: false property suggests that the APIs navigation might have nested items in the future that can be toggled. This is consistent with the PR's goal of adding nested routes.


82-96: Well-structured nested navigation for Authorization section.

The Authorization section now has a clear hierarchical structure with Roles and Permissions as sub-items. The implementation correctly sets the active state based on the URL segments.


137-169: Comprehensive nested navigation for Settings section.

The Settings section now has a well-organized structure with multiple sub-items (Team, Root Keys, Billing, Vercel Integration, User). The implementation correctly sets the active state based on the URL segments.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
apps/dashboard/components/app-sidebar.tsx (2)

159-203: Consider moving AnimatedLoadingSpinner to a separate file

I notice that this component appears to be duplicated, as the relevant code snippets show that it already exists in apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/animated-loading-spinner.tsx. Duplicating components can lead to maintenance issues if changes are needed in the future.

-const AnimatedLoadingSpinner = memo(() => {
-  const [segmentIndex, setSegmentIndex] = useState(0);
-
-  useEffect(() => {
-    // Animate the segments in sequence
-    const timer = setInterval(() => {
-      setSegmentIndex((prevIndex) => (prevIndex + 1) % SEGMENTS.length);
-    }, 125); // 125ms per segment = 1s for full rotation
-    return () => clearInterval(timer);
-  }, []);
-
-  return (
-    <svg
-      xmlns="http://www.w3.org/2000/svg"
-      width="18"
-      height="18"
-      viewBox="0 0 18 18"
-      className="animate-spin-slow"
-      data-prefers-reduced-motion="respect-motion-preference"
-    >
-      <g>
-        {SEGMENTS.map((id, index) => {
-          const distance = (SEGMENTS.length + index - segmentIndex) % SEGMENTS.length;
-          const opacity = distance <= 4 ? 1 - distance * 0.2 : 0.1;
-          return (
-            <path
-              key={id}
-              id={id}
-              style={{
-                fill: "currentColor",
-                opacity: opacity,
-                transition: "opacity 0.12s ease-in-out",
-              }}
-              d={getPathForSegment(index)}
-            />
-          );
-        })}
-        <path
-          d="M9,6.5c-1.379,0-2.5,1.121-2.5,2.5s1.121,2.5,2.5,2.5,2.5-1.121,2.5-2.5-1.121-2.5-2.5-2.5Z"
-          style={{ fill: "currentColor", opacity: 0.6 }}
-        />
-      </g>
-    </svg>
-  );
-});

And add the import at the top:

+import { AnimatedLoadingSpinner } from "@/components/navigation/sidebar/app-sidebar/components/nav-items/animated-loading-spinner";

357-381: Consider moving CSS styles to a stylesheet

Dynamically injecting styles via JavaScript is harder to maintain and could cause flashes of unstyled content. Consider moving these styles to a CSS or SCSS file for better maintainability and performance.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2d7239f and 5dc0af9.

📒 Files selected for processing (1)
  • apps/dashboard/components/app-sidebar.tsx (4 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
apps/dashboard/components/app-sidebar.tsx (1)
apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/animated-loading-spinner.tsx (1)
  • AnimatedLoadingSpinner (46-91)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Test API / API Test Local
  • GitHub Check: Build / Build
🔇 Additional comments (4)
apps/dashboard/components/app-sidebar.tsx (4)

241-241: Improved error handling for icon rendering

The conditional rendering pattern here prevents potential runtime errors by checking if the Icon exists before attempting to render it. This is a good defensive programming practice.


267-267: Good implementation of consistent icon rendering pattern

This follows the same robust pattern as in the FlatNavItem component, ensuring proper icon rendering with appropriate fallbacks.


339-340: Well-structured icon assignment from props

Extracting the icon into a local variable makes the code more readable and consistent with the pattern used in other components.


349-349: Improved conditional icon rendering

The conditional check before rendering the icon prevents potential runtime errors if the icon is undefined or null.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/dashboard/app/(app)/ratelimits/_components/create-namespace-button.tsx (1)

53-54: LGTM: Enhancing data consistency after mutation.

The addition of revalidate("/ratelimits") and cache invalidation ensures UI data remains consistent after creating a namespace. This is an excellent improvement for user experience.

Consider adding error handling for the revalidation operation:

- await revalidate("/ratelimits");
+ try {
+   await revalidate("/ratelimits");
+ } catch (error) {
+   console.error("Failed to revalidate ratelimits:", error);
+   // Optional: Show a toast warning that some data might not be updated
+ }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5dc0af9 and efabd52.

📒 Files selected for processing (1)
  • apps/dashboard/app/(app)/ratelimits/_components/create-namespace-button.tsx (3 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
apps/dashboard/app/(app)/ratelimits/_components/create-namespace-button.tsx (3)
apps/dashboard/lib/trpc/server.ts (1)
  • trpc (7-14)
apps/dashboard/lib/trpc/routers/index.ts (1)
  • router (78-202)
apps/dashboard/app/(app)/authorization/roles/[roleId]/page.tsx (1)
  • revalidate (8-8)
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: Test Go API Local / Test (Shard 7/8)
  • GitHub Check: Test Go API Local / Test (Shard 8/8)
  • GitHub Check: Test Packages / Test ./internal/keys
  • GitHub Check: Test Packages / Test ./internal/id
  • GitHub Check: Test Agent Local / test_agent_local
  • GitHub Check: Test API / API Test Local
  • GitHub Check: Build / Build
  • GitHub Check: autofix
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (3)
apps/dashboard/app/(app)/ratelimits/_components/create-namespace-button.tsx (3)

3-3: LGTM: Good addition for route revalidation.

The import statement for revalidate is essential for triggering Next.js route revalidation after namespace creation.


36-37: LGTM: Proper setup for cache invalidation.

Extracting the ratelimit utils from trpc.useUtils() provides access to cache invalidation methods, which is a good practice for keeping UI data in sync after mutations.


50-50: LGTM: Making the handler async.

Adding async to the onSuccess handler is required since we'll be awaiting the revalidate function call.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (5)
apps/dashboard/components/navigation/sidebar/app-sidebar/hooks/use-api-navigation.tsx (5)

1-8: Use a single icon library for stylistic consistency (optional).

The code imports icons from both @unkey/icons and lucide-react, which may result in inconsistent icon sizes or styles in the UI. Consider consolidating icon usage under a single library for a more uniform look and feel.


9-10: Consider making DEFAULT_LIMIT configurable.

Using a hard-coded limit might be restrictive if the app requires different pagination parameters. Exposing DEFAULT_LIMIT via environment variables or function arguments could offer more flexibility.


11-22: Add error state handling for the infinite query.

Currently, the component handles loading states but not errors. If the request fails, a user might be confused by the missing data. Consider returning or displaying an error state to improve user feedback.


80-106: Remove //@ts-expect-error by adjusting the NavItem type.

You’re using a React node for label (line 95) while the NavItem interface declares it as a string. Remove the ts-expect-error comment by expanding the NavItem type to accept React.ReactNode. For example, in workspace-navigations.tsx:

// Proposed snippet for updating the NavItem definition:
export type NavItem = {
  disabled?: boolean;
  tooltip?: string;
  icon: React.ElementType | null;
  href: string;
  external?: boolean;
  label: string | React.ReactNode;
  active?: boolean;
  tag?: React.ReactNode;
  hidden?: boolean;
  items?: NavItem[];
  loadMoreAction?: boolean;
  showSubItems?: boolean;
};

113-118: Optionally handle or expose error states alongside isLoading.

If you need to display specific UI based on errors, consider returning or consuming an isError or similar state to inform the user if the data fails to load.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between efabd52 and c6da336.

📒 Files selected for processing (6)
  • apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/nested-nav-item.tsx (1 hunks)
  • apps/dashboard/components/navigation/sidebar/app-sidebar/hooks/use-api-navigation.tsx (1 hunks)
  • apps/dashboard/components/navigation/sidebar/app-sidebar/hooks/use-ratelimit-navigation.tsx (1 hunks)
  • internal/icons/src/icons/arrow-dotted-rotate-anticlockwise.tsx (1 hunks)
  • internal/icons/src/icons/arrow-opposite-direction-y.tsx (1 hunks)
  • internal/icons/src/index.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/dashboard/components/navigation/sidebar/app-sidebar/components/nav-items/nested-nav-item.tsx
  • apps/dashboard/components/navigation/sidebar/app-sidebar/hooks/use-ratelimit-navigation.tsx
🧰 Additional context used
🧬 Code Definitions (3)
internal/icons/src/icons/arrow-opposite-direction-y.tsx (1)
internal/icons/src/props.ts (2)
  • IconProps (30-35)
  • sizeMap (7-28)
internal/icons/src/icons/arrow-dotted-rotate-anticlockwise.tsx (1)
internal/icons/src/props.ts (2)
  • IconProps (30-35)
  • sizeMap (7-28)
apps/dashboard/components/navigation/sidebar/app-sidebar/hooks/use-api-navigation.tsx (4)
apps/dashboard/components/navigation/sidebar/workspace-navigations.tsx (1)
  • NavItem (16-29)
apps/dashboard/lib/trpc/server.ts (1)
  • trpc (7-14)
internal/icons/src/icons/gear.tsx (1)
  • Gear (15-197)
internal/icons/src/icons/arrow-opposite-direction-y.tsx (1)
  • ArrowOppositeDirectionY (15-68)
⏰ Context from checks skipped due to timeout of 90000ms (15)
  • GitHub Check: Test Go API Local / Test (Shard 4/8)
  • GitHub Check: Test Go API Local / Test (Shard 8/8)
  • GitHub Check: Test Go API Local / Test (Shard 6/8)
  • GitHub Check: Test Go API Local / Test (Shard 3/8)
  • GitHub Check: Test Go API Local / Test (Shard 5/8)
  • GitHub Check: Test Packages / Test ./internal/resend
  • GitHub Check: Test Go API Local / Test (Shard 2/8)
  • GitHub Check: Test Go API Local / Test (Shard 7/8)
  • GitHub Check: Test Packages / Test ./packages/nextjs
  • GitHub Check: Test Packages / Test ./internal/encryption
  • GitHub Check: Test Packages / Test ./internal/clickhouse
  • GitHub Check: Test Agent Local / test_agent_local
  • GitHub Check: Build / Build
  • GitHub Check: Test API / API Test Local
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (5)
internal/icons/src/icons/arrow-dotted-rotate-anticlockwise.tsx (1)

15-57: Implementation looks good!

The component follows the established icon pattern with proper typing, default props, and consistent SVG structure.

internal/icons/src/index.ts (1)

71-72: Icon exports correctly added

New exports follow the established pattern and make the icons available to consumers.

internal/icons/src/icons/arrow-opposite-direction-y.tsx (1)

15-68: Implementation looks good!

The component correctly implements the icon pattern and properly uses both the size and strokeWidth parameters from sizeMap.

apps/dashboard/components/navigation/sidebar/app-sidebar/hooks/use-api-navigation.tsx (2)

24-79: Well-structured transformation of API data into nav items.

Your approach of mapping API data to main and sub-navigation items is clear and follows a logical structure. Great job!


107-111: The loadMore handler is straightforward and effective.

Your check on !isFetchingNextPage && hasNextPage is sufficient to prevent redundant calls and ensure correct pagination.

Showing the loader only for items that has icon will prevent layout
shift
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants