Skip to content

Conversation

@MananTank
Copy link
Member

@MananTank MananTank commented Aug 26, 2025


PR-Codex overview

This PR focuses on updating various UI components in the dashboard, primarily adjusting icon sizes, replacing some icons, and enhancing layout elements for improved aesthetics and usability.

Detailed summary

  • Changed size of PlusIcon in CreateWebhookModal and other components from size-4 to size-3.5.
  • Replaced SettingsIcon with Settings2Icon in ProjectSidebarLayout.
  • Added DatabaseIcon to the ProjectPage header.
  • Updated VaultPage actions to null.
  • Replaced ImportIcon with ArrowDownToLineIcon in multiple components.
  • Adjusted button styles and sizes for consistency across various components.
  • Added icon props to several ProjectPage headers, including WebhookIcon, TokenIcon, and PayIcon.
  • Enhanced layout and spacing in the Layout component and ProjectPageHeader.
  • Removed documentation links and adjusted actions to null in several pages.

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

Summary by CodeRabbit

  • New Features

    • Header icons added across many pages; headers now support a configurable project icon and a dedicated Settings control.
    • Single link renders as a direct action button; multiple links grouped under a labeled "Resources" menu with chevron.
  • Refactor

    • Project header redesigned to an icon-driven layout; mobile-specific branching removed and actions reorganized (top-right on desktop, bottom row on mobile).
  • Style

    • Button variants, spacing, iconography, dropdown alignment, and item padding adjusted (smaller icons, new arrow/chevron visuals).

@vercel
Copy link

vercel bot commented Aug 26, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
thirdweb-www Ready Ready Preview Comment Aug 26, 2025 10:47pm
4 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
docs-v2 Skipped Skipped Aug 26, 2025 10:47pm
nebula Skipped Skipped Aug 26, 2025 10:47pm
thirdweb_playground Skipped Skipped Aug 26, 2025 10:47pm
wallet-ui Skipped Skipped Aug 26, 2025 10:47pm

@vercel vercel bot temporarily deployed to Preview – wallet-ui August 26, 2025 19:40 Inactive
@vercel vercel bot temporarily deployed to Preview – nebula August 26, 2025 19:40 Inactive
@vercel vercel bot temporarily deployed to Preview – docs-v2 August 26, 2025 19:40 Inactive
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground August 26, 2025 19:40 Inactive
@changeset-bot
Copy link

changeset-bot bot commented Aug 26, 2025

⚠️ No Changeset found

Latest commit: e651d0a

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 26, 2025

Walkthrough

Replace avatar-based header with an icon renderer and optional settings button; remove the "settings" LinkType from LinkGroup and simplify single-link vs dropdown rendering; update many UI icons, button variants, and sizing. No backend or control-flow changes beyond header/link rendering.

Changes

Cohort / File(s) Summary
Header core components
apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx, apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
Removed "settings" LinkType and related mappings; LinkGroup now renders a direct Link-wrapped outline Button when one link exists and a labeled "Resources" button + dropdown for multiple links; dropped mobile-specific branching. ProjectPageHeader replaced avatar rendering with an icon renderer and isProjectIcon flag, added settings prop and reworked header layout.
Pages wiring header.icon / moving settings
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/*/page.tsx (e.g., account-abstraction, ai, contracts, engine, insight, payments, rpc, tokens, transactions, vault, wallets, webhooks/*)
Many pages now pass header.icon (various icons) and often set actions: null; several moved settings from header.links (type "settings") into header.settings with an href; some descriptions changed to JSX. No runtime logic changes.
Project index header (avatar → icon)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
Replaced header.imageUrl with header.icon rendering ProjectAvatar and set header.isProjectIcon: true.
Import / deploy / token / engine / webhook UI updates
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/*/{import-contract,modal,import-engine-dialog,import-contract-button,tokens/cards,contracts/page,engine/.../engine-instances-table,webhooks/components/CreateWebhookModal, ...}.tsx
Presentational updates only: swap many icons (e.g., ImportIcon/DownloadIcon/RocketIcon → ArrowDownToLineIcon / ArrowUpFromLineIcon / others), adjust icon sizes (size-4size-3.5), change Button variants/classes (many → outline / bg-card tweaks), and minor spacing adjustments. Behavior unchanged.
Sidebar & settings UI icon swap / layout
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx, .../settings/layout.tsx
Replaced SettingsIcon with Settings2Icon; updated settings layout header to include icon block, stacked title/subtitle, and adjusted padding.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Page as Page (various)
  participant Header as ProjectPageHeader
  participant LG as LinkGroup

  Page->>Header: Render(header: { icon?, isProjectIcon?, title, description, links?, settings?, actions? })
  alt header.settings exists
    Header->>Header: Render Settings button -> link to header.settings.href
  end

  alt header.links exists
    Header->>LG: Render LinkGroup(links)
    alt links.length == 1
      LG->>LG: Render direct Link (outline Button with Icon + label)
    else multiple links
      LG->>LG: Render "Resources" Button (label + chevron) -> open DropdownMenu
      note right of LG: DropdownMenuItems = Link-wrapped DropdownMenuItem (external handling preserved)
    end
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • jnsdls

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • TEAM-0000: Entity not found: Issue - Could not find referenced Issue.
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 08-27-dashboard_update_project_header_style

🪧 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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

@github-actions github-actions bot added the Dashboard Involves changes to the Dashboard. label Aug 26, 2025
@MananTank MananTank marked this pull request as ready for review August 26, 2025 19:40
@MananTank MananTank requested review from a team as code owners August 26, 2025 19:40
Copy link
Member Author

MananTank commented Aug 26, 2025


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • merge-queue - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@codecov
Copy link

codecov bot commented Aug 26, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 56.53%. Comparing base (34239ea) to head (e651d0a).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7920   +/-   ##
=======================================
  Coverage   56.53%   56.53%           
=======================================
  Files         904      904           
  Lines       58592    58592           
  Branches     4143     4143           
=======================================
  Hits        33126    33126           
  Misses      25360    25360           
  Partials      106      106           
Flag Coverage Δ
packages 56.53% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Contributor

github-actions bot commented Aug 26, 2025

size-limit report 📦

Path Size Loading time (3g) Running time (snapdragon) Total time
thirdweb (esm) 64.01 KB (-0.08% 🔽) 1.3 s (-0.08% 🔽) 230 ms (+74.21% 🔺) 1.6 s
thirdweb (cjs) 357.05 KB (0%) 7.2 s (0%) 962 ms (+5.61% 🔺) 8.2 s
thirdweb (minimal + tree-shaking) 5.73 KB (0%) 115 ms (0%) 52 ms (+699.85% 🔺) 166 ms
thirdweb/chains (tree-shaking) 526 B (0%) 11 ms (0%) 35 ms (+1289.61% 🔺) 46 ms
thirdweb/react (minimal + tree-shaking) 19.15 KB (0%) 383 ms (0%) 78 ms (+408.09% 🔺) 461 ms

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/import/import-engine-dialog.tsx (1)

186-193: Disable submit while pending to avoid duplicate imports

Without disabling, rapid clicks can fire multiple mutations and create duplicate Engine records. You already render a spinner; wire it to the disabled state.

Apply this diff:

-              <Button className="min-w-28 gap-1.5 rounded-full" type="submit">
+              <Button
+                className="min-w-28 gap-1.5 rounded-full"
+                type="submit"
+                disabled={importMutation.isPending}
+                aria-busy={importMutation.isPending}
+              >

Optional follow-up: also disable the form fields while isPending to prevent edits mid-request.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/layout.tsx (1)

3-9: Fix params typing and avoid unnecessary async

params is not a Promise in Next.js app router layouts, and the function isn’t awaiting anything. Also add an explicit return type.

Apply:

-export default async function Layout(props: {
-  children: React.ReactNode;
-  params: Promise<{
-    team_slug: string;
-    project_slug: string;
-  }>;
-}) {
+export default function Layout(props: {
+  children: React.ReactNode;
+  params: {
+    team_slug: string;
+    project_slug: string;
+  };
+}): JSX.Element {
🧹 Nitpick comments (12)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/import/import-engine-dialog.tsx (5)

110-116: Prevent accidental form submit: set the trigger button’s type to "button"

The DialogTrigger sits inside a form. Depending on our Button default, this may submit the form when opening the dialog. Be explicit.

Apply this diff:

-            <Button
-              className="gap-2 rounded-full bg-card"
-              size="sm"
-              variant="outline"
-            >
+            <Button
+              type="button"
+              className="gap-2 rounded-full bg-card"
+              size="sm"
+              variant="outline"
+            >

114-114: Icon sizing nit: size-3.5 is fine and on-scale

The 14px target works well for a small trigger. No issues.

If you want tighter optical alignment with the label baseline, consider size-4 with a slight negative tracking on the text, but current choice is acceptable.


74-80: Prefer defaultValues over values to avoid unintended resets

Using values can cause form resets when the object identity changes across renders. defaultValues is safer here; if you need to react to prefillImportUrl changes, call form.reset in an effect.

Apply this diff:

   const form = useForm<ImportEngineParams>({
     resolver: zodResolver(formSchema),
-    values: {
+    defaultValues: {
       name: "",
       url: props.prefillImportUrl || "",
     },
   });

82-87: Move navigation to onSuccess for cleaner separation of concerns

Keep the mutation function pure (data work only) and handle side-effects in React Query callbacks.

Apply this diff:

-  const importMutation = useMutation({
-    mutationFn: async (importParams: ImportEngineParams) => {
-      await importEngine({ ...importParams, teamIdOrSlug: props.teamSlug });
-      router.push(`/team/${props.teamSlug}/${props.projectSlug}/engine`);
-    },
-  });
+  const importMutation = useMutation({
+    mutationFn: async (importParams: ImportEngineParams) =>
+      importEngine({ ...importParams, teamIdOrSlug: props.teamSlug }),
+    onSuccess: () => {
+      router.push(`/team/${props.teamSlug}/${props.projectSlug}/engine`);
+    },
+  });

63-66: Verify apiServerProxy error shape before accessing res.error

If apiServerProxy returns a Fetch Response-like object, res.error may be undefined. Guard the access or provide a fallback message.

Possible tweak:

-  if (!res.ok) {
-    throw new Error(res.error);
-  }
+  if (!res.ok) {
+    const message =
+      typeof (res as any).error === "string"
+        ? (res as any).error
+        : "Failed to import Engine";
+    throw new Error(message);
+  }

If apiServerProxy guarantees { ok: boolean; error?: string }, feel free to ignore this.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/insight/page.tsx (1)

8-8: InsightIcon import resolves locally; consider centralizing duplicate implementations

Importing

import { InsightIcon } from "@/icons/InsightIcon";

in the dashboard app correctly resolves to
apps/dashboard/src/@/icons/InsightIcon.tsx and does not pull in the playground-web or portal versions.

• apps/dashboard/src/@/icons/InsightIcon.tsx (local implementation)
• apps/playground-web/src/icons/InsightIcon.tsx (duplicate in playground-web)
• apps/portal/src/icons/products/InsightIcon.tsx (duplicate in portal)

Optional refactor: extract all icons into a shared package (e.g. packages/ui/icons), export them from a single barrel (e.g. packages/ui/icons/index.ts), and update imports across apps to eliminate drift.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/page.tsx (1)

1-1: Mark this as a Server Component

Per dashboard guidelines, add the server-only directive to prevent accidental client-side import of this module.

Apply this diff:

+import "server-only";
 import { ArrowUpFromLineIcon } from "lucide-react";
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx (1)

23-27: Add an explicit return type for the component

Keep TS strict and consistent with repo guidelines by annotating the return type.

Apply:

-export function ProjectSidebarLayout(props: {
+export function ProjectSidebarLayout(props: {
   layoutPath: string;
   children: React.ReactNode;
   hasEngineInstances: boolean;
-}) {
+}): JSX.Element {
apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx (4)

60-62: Broaden icon type to accept lucide and custom icons

lucide-react icons are ComponentType/forwardRef-based, not strictly React.FC. Using React.ComponentType is more accurate and flexible.

Apply:

-  icon: React.FC<{ className?: string }>;
+  icon: React.ComponentType<{ className?: string }>;

26-41: Map “secondary” to the new outline style and add bg-card

The PR standardizes secondary actions to variant="outline" with bg-card. Reflect that here.

Apply:

-function Action(props: { action: Action; variant?: "default" | "secondary" }) {
+function Action(props: { action: Action; variant?: "default" | "secondary" }) {
   const action = props.action;
+  const buttonVariant = props.variant === "secondary" ? "outline" : (props.variant ?? "default");
 
   return "component" in action ? (
     action.component
   ) : (
     <Button
       asChild
       className={cn(
         "rounded-full",
-        props.variant === "secondary" && "border border-border",
+        buttonVariant === "outline" && "border border-border bg-card",
       )}
       size="sm"
-      variant={props.variant}
+      variant={buttonVariant}
     >

77-79: Add explicit return type

Keep component signatures explicit per TS guidelines.

Apply:

-export function ProjectPageHeader(props: ProjectPageHeaderProps) {
+export function ProjectPageHeader(props: ProjectPageHeaderProps): JSX.Element {

55-75: Remove unused client and imageUrl props from ProjectPageHeaderProps

I ran the ripgrep checks and confirmed:

  • No instances of client= or imageUrl= when rendering <ProjectPageHeader /> anywhere in apps/dashboard.
  • No internal references to props.client or props.imageUrl within project-page-header.tsx beyond their type declarations.

Those props are unused and can safely be removed to slim the API surface and avoid confusion.

• File needing update:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx (lines 55–75)
    • Remove client: ThirdwebClient;
    • Remove imageUrl?: string | null;

• Call sites: none found—no further updates required.

If you anticipate future use for either prop, please reintroduce and implement accordingly; otherwise, go ahead and delete them.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 671b409 and d5eb851.

📒 Files selected for processing (24)
  • apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx (4 hunks)
  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx (2 hunks)
  • apps/dashboard/src/@/components/contracts/import-contract/modal.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/account-abstraction/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/import-contract-button.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/page.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/import/import-engine-dialog.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/overview/engine-instances-table.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/insight/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx (4 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/rpc/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/layout.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/cards.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/page.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/vault/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/contracts/page.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (18)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/page.tsx
  • apps/dashboard/src/@/components/contracts/import-contract/modal.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/overview/engine-instances-table.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/rpc/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/cards.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/import-contract-button.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/contracts/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/vault/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/account-abstraction/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx
  • apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from @/types or local types.ts barrels
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose

Files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/layout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/import/import-engine-dialog.tsx
  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/insight/page.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)

Files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/layout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/import/import-engine-dialog.tsx
  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/insight/page.tsx
apps/{dashboard,playground-web}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/{dashboard,playground-web}/**/*.{ts,tsx}: Import UI primitives from @/components/ui/* (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Use NavLink for internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Use cn() from @/lib/utils for conditional class logic
Use design system tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components (Node edge): Start files with import "server-only";
Client Components (browser): Begin files with 'use client';
Always call getAuthToken() to retrieve JWT from cookies on server side
Use Authorization: Bearer header – never embed tokens in URLs
Return typed results (e.g., Project[], User[]) – avoid any
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stable queryKeys for React Query cache hits
Configure staleTime/cacheTime in React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never import posthog-js in server components

Files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/layout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/import/import-engine-dialog.tsx
  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/insight/page.tsx
🧠 Learnings (8)
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Icons come from `lucide-react` or the project-specific `…/icons` exports – never embed raw SVG.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/import/import-engine-dialog.tsx
📚 Learning: 2025-08-20T10:35:18.543Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx:77-81
Timestamp: 2025-08-20T10:35:18.543Z
Learning: The webhooks/payments route exists at apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx and was added as part of the unified project layout changes.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/layout.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Layouts should reuse `SidebarLayout` / `FullWidthSidebarLayout` (`@/components/blocks/SidebarLayout`).

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/layout.tsx
📚 Learning: 2025-08-20T10:35:18.543Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx:77-81
Timestamp: 2025-08-20T10:35:18.543Z
Learning: The webhooks/payments route exists at apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx and was added as part of the unified project layout PR #7888.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx
📚 Learning: 2025-07-07T21:21:47.488Z
Learnt from: saminacodes
PR: thirdweb-dev/js#7543
File: apps/portal/src/app/pay/page.mdx:4-4
Timestamp: 2025-07-07T21:21:47.488Z
Learning: In the thirdweb-dev/js repository, lucide-react icons must be imported with the "Icon" suffix (e.g., ExternalLinkIcon, RocketIcon) as required by the new linting rule, contrary to the typical lucide-react convention of importing without the suffix.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/import/import-engine-dialog.tsx
  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-06-24T21:38:03.155Z
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/page.tsx
📚 Learning: 2025-07-31T16:17:42.753Z
Learnt from: MananTank
PR: thirdweb-dev/js#7768
File: apps/playground-web/src/app/navLinks.ts:1-1
Timestamp: 2025-07-31T16:17:42.753Z
Learning: Configuration files that import and reference React components (like icon components from lucide-react) need the "use client" directive, even if they primarily export static data, because the referenced components need to be executed in a client context when used by other client components.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/page.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Import UI primitives from `@/components/ui/*` (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/import/import-engine-dialog.tsx
🧬 Code graph analysis (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/page.tsx (1)
apps/playground-web/src/icons/ContractIcon.tsx (1)
  • ContractIcon (1-21)
apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx (1)
apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx (2)
  • ActionLink (51-54)
  • LinkGroup (56-119)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/insight/page.tsx (1)
apps/playground-web/src/icons/InsightIcon.tsx (1)
  • InsightIcon (1-21)
🔇 Additional comments (11)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/import/import-engine-dialog.tsx (2)

6-9: Icon swap to ArrowDownToLineIcon matches repo convention and PR intent — LGTM

  • Uses the Icon-suffixed lucide exports as per repo lint rule.
  • Consistent with the PR-wide replacement of Import/Download icons.

190-190: Submit button icon swap — consistent with trigger icon

Using ArrowDownToLineIcon here keeps the pattern consistent. Good.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/insight/page.tsx (2)

53-53: Header icon prop is correctly typed as React.FC<{ className?: string }>

I’ve confirmed in apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx that ProjectPageHeaderProps.icon is declared as React.FC<{ className?: string }> (line 55), so passing InsightIcon (satisfying React.FC<{ className?: string }>) is fully compatible with the header API. No changes are required here.


57-57: Please verify that ProjectPage properly omits its actions container when header.actions is null

I wasn’t able to locate a guard in the ProjectPage implementation that skips rendering (and any associated spacing) when actions is null. Since you’re explicitly passing actions: null on the Insight page (and elsewhere in the sidebar), please confirm both in code and in the running UI that:

  • No empty wrapper is rendered for actions.
  • No horizontal padding, margin, or reserved space remains when actions is null.

If you find that an empty container or gap still appears, wrap the actions block in a conditional, for example:

{header.actions && (
  <div className="project-page__actions">
    {header.actions}
  </div>
)}

And gate any related layout styles on Boolean(header.actions) so the header collapses fully when there are no actions.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/page.tsx (4)

1-1: Lucide import naming LGTM

ArrowUpFromLineIcon follows the repo rule to import lucide-react icons with the Icon suffix. Consistent with prior learnings.


59-59: Icon sizing change aligns with the PR’s design update

Using size-3.5 on the primary action icon matches the global change in this PR and keeps icons visually balanced with text.


8-8: ContractIcon import path is valid

I confirmed that the dashboard app includes its own ContractIcon implementation at apps/dashboard/src/@/icons/ContractIcon.tsx, so the import from @/icons/ContractIcon will resolve correctly in this workspace. No further changes are needed here.


46-46: No change needed for the icon prop

The ProjectPageHeaderProps definition specifies:

export type ProjectPageHeaderProps = {
  // …
  icon: React.FC<{ className?: string }>;
  // …
};

Since icon expects a component type (i.e. a React.FC accepting a className), passing ContractIcon directly is correct. No conversion to a ReactNode (e.g. <ContractIcon />) is required.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx (2)

10-12: Settings icon swap LGTM

Using Settings2Icon aligns with the repo-wide icon convention and the PR’s visual direction. No behavioral impact.

Also applies to: 140-143


132-138: Contracts is the intended default Webhooks destination

The root Webhooks page at
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/page.tsx
performs a redirect to /webhooks/contracts, confirming that contracts is the default landing route. The sidebar’s href: ${props.layoutPath}/webhooks/contracts`` in
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx
lines 132–138 correctly matches this behavior. No code changes are required unless you intend to switch the default to payments.

If you do want payments as the new default, please update both:

  • the redirect target in …/webhooks/page.tsx
  • and the sidebar href in ProjectSidebarLayout.tsx
apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx (1)

100-111: Settings button rendering LGTM

Button variant/class matches the updated design tokens and icon usage is consistent.

@MananTank MananTank force-pushed the 08-27-dashboard_update_project_header_style branch from d5eb851 to b015f20 Compare August 26, 2025 22:26
@vercel vercel bot temporarily deployed to Preview – docs-v2 August 26, 2025 22:26 Inactive
@vercel vercel bot temporarily deployed to Preview – nebula August 26, 2025 22:26 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui August 26, 2025 22:26 Inactive
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground August 26, 2025 22:26 Inactive
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx (1)

1-4: Make this a Client Component and use the dashboard Button import

This header renders interactive controls and consumes a client subcomponent (LinkGroup). Add the "use client" directive and switch the Button import to the app’s UI primitive path.

Apply:

+ "use client";
-import { Button } from "@workspace/ui/components/button";
+import { Button } from "@/components/ui/button";
🧹 Nitpick comments (6)
apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx (6)

60-62: Unify icon rendering and ensure predictable sizing

When isProjectIcon is true, the icon is rendered without a className, leading to inconsistent sizes across pages. Pass a default className in both branches and mark decorative icons aria-hidden.

-  icon: React.FC<{ className?: string }>;
+  icon: React.ComponentType<{ className?: string }>;
   isProjectIcon?: boolean;

And below (see top-row icon):

-          {props.isProjectIcon ? (
-            <props.icon />
-          ) : (
-            <div className="border rounded-full p-2.5 bg-card">
-              <props.icon className="size-5 text-muted-foreground" />
-            </div>
-          )}
+          {props.isProjectIcon ? (
+            <props.icon className="size-6" aria-hidden="true" />
+          ) : (
+            <div className="border rounded-full p-2.5 bg-card">
+              <props.icon className="size-5 text-muted-foreground" aria-hidden="true" />
+            </div>
+          )}

68-70: settings prop shape looks good

Simple and focused API for a Settings link. Consider allowing an optional label for localization in the future, defaulting to “Settings”.


76-89: Add explicit return types and root className override

  • Per guidelines, add explicit return types on components.
  • Expose a className prop and merge with cn for theming/overrides.
-export function ProjectPageHeader(props: ProjectPageHeaderProps) {
+export function ProjectPageHeader(props: ProjectPageHeaderProps): JSX.Element {
   return (
-    <header className="container max-w-7xl py-6 relative">
+    <header className={cn("container max-w-7xl py-6 relative", (props as any).className)}>

And extend the props:

 export type ProjectPageHeaderProps = {
   title: string;
   description?: React.ReactNode;
   icon: React.ComponentType<{ className?: string }>;
   isProjectIcon?: boolean;
+  className?: string;
   actions: {
     primary: Action;
     secondary?: Action;
   } | null;

78-89: Optional: expose iconContainerClassName for styling hooks

If consumers need to tweak the container (e.g., remove border on specific pages), add an iconContainerClassName prop and merge with cn.

-            <div className="border rounded-full p-2.5 bg-card">
+            <div className={cn("border rounded-full p-2.5 bg-card", (props as any).iconContainerClassName)}>
               <props.icon className="size-5 text-muted-foreground" aria-hidden="true" />
             </div>

113-124: Align secondary action styling with outline pattern

PR-wide changes prefer outline with bg-card. Consider migrating the “secondary” action here to outline for consistency, and widen the Action helper’s variant type accordingly.

-function Action(props: { action: Action; variant?: "default" | "secondary" }) {
+function Action(props: { action: Action; variant?: "default" | "secondary" | "outline" }): JSX.Element {
   const action = props.action;
   return "component" in action ? (
     action.component
   ) : (
     <Button
       asChild
-      className={cn(
-        "rounded-full",
-        props.variant === "secondary" && "border border-border",
-      )}
+      className={cn("rounded-full", props.variant === "outline" && "gap-2 bg-card")}
       size="sm"
       variant={props.variant}
     >

And use outline for the secondary call site:

-              {props.actions.secondary && (
-                <Action action={props.actions.secondary} variant="secondary" />
-              )}
+              {props.actions.secondary && (
+                <Action action={props.actions.secondary} variant="outline" />
+              )}

92-110: Replace Next.js Link with NavLink for internal “Settings” navigation

NavLink is already defined in apps/dashboard/src/@/components/ui/NavLink.tsx and imported elsewhere to provide automatic active‐state styling and consistent prefetch behavior. Swapping in NavLink here will align this internal link with the rest of the dashboard.

Files to update:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx (lines 92–110)

Suggested diff:

-import Link from "next/link";
+import { NavLink } from "@/components/ui/NavLink";-            {props.settings && (
-              <Link href={props.settings.href}>
+            {props.settings && (
+              <NavLink href={props.settings.href}>
                 <Button
                   variant="outline"
                   size="sm"
                   className="rounded-full gap-2 bg-card"
                 >
                   <Settings2Icon className="size-4 text-muted-foreground" />
                   Settings
                 </Button>
-              </Link>
+              </NavLink>
             )}

• Don’t forget to remove the unused Link import if it’s no longer referenced.
• This change is optional but recommended to ensure internal links use NavLink’s built-in active states.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d5eb851 and b015f20.

📒 Files selected for processing (24)
  • apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx (4 hunks)
  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx (2 hunks)
  • apps/dashboard/src/@/components/contracts/import-contract/modal.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/account-abstraction/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/import-contract-button.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/page.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/import/import-engine-dialog.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/overview/engine-instances-table.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/insight/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx (4 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/rpc/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/layout.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/cards.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/page.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/vault/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/contracts/page.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx (3 hunks)
✅ Files skipped from review due to trivial changes (2)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/overview/engine-instances-table.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx
🚧 Files skipped from review as they are similar to previous changes (21)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/page.tsx
  • apps/dashboard/src/@/components/contracts/import-contract/modal.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/layout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/import-contract-button.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/account-abstraction/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/cards.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/vault/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/insight/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/rpc/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/import/import-engine-dialog.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/contracts/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx
  • apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from @/types or local types.ts barrels
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose

Files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)

Files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
apps/{dashboard,playground-web}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/{dashboard,playground-web}/**/*.{ts,tsx}: Import UI primitives from @/components/ui/* (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Use NavLink for internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Use cn() from @/lib/utils for conditional class logic
Use design system tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components (Node edge): Start files with import "server-only";
Client Components (browser): Begin files with 'use client';
Always call getAuthToken() to retrieve JWT from cookies on server side
Use Authorization: Bearer header – never embed tokens in URLs
Return typed results (e.g., Project[], User[]) – avoid any
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stable queryKeys for React Query cache hits
Configure staleTime/cacheTime in React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never import posthog-js in server components

Files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
🧠 Learnings (18)
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Icons come from `lucide-react` or the project-specific `…/icons` exports – never embed raw SVG.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/components/*.client.tsx : Client components must start with `'use client';` before imports.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Import UI primitives from `@/components/ui/*` (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Client Components (browser): Begin files with `'use client';`

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Always import from the central UI library under `@/components/ui/*` – e.g. `import { Button } from "@/components/ui/button"`.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Anything that consumes hooks from `tanstack/react-query` or thirdweb SDKs.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Reuse core UI primitives; avoid re-implementing buttons, cards, modals.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Prefer composable primitives over custom markup: `Button`, `Input`, `Select`, `Tabs`, `Card`, `Sidebar`, `Separator`, `Badge`.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Components that listen to user events, animations or live updates.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : When you need access to browser APIs (localStorage, window, IntersectionObserver etc.).

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Use the `container` class with a `max-w-7xl` cap for page width consistency.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Combine class names via `cn`, expose `className` prop if useful.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Merge class names with `cn` from `@/lib/utils` to keep conditional logic readable.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{tsx} : Expose `className` prop on root element of components for overrides

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Add `className` to the root element of every component for external overrides.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Use `cn()` from `@/lib/utils` for conditional class logic

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-07T21:21:47.488Z
Learnt from: saminacodes
PR: thirdweb-dev/js#7543
File: apps/portal/src/app/pay/page.mdx:4-4
Timestamp: 2025-07-07T21:21:47.488Z
Learning: In the thirdweb-dev/js repository, lucide-react icons must be imported with the "Icon" suffix (e.g., ExternalLinkIcon, RocketIcon) as required by the new linting rule, contrary to the typical lucide-react convention of importing without the suffix.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
🧬 Code graph analysis (1)
apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx (1)
apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx (2)
  • ActionLink (51-54)
  • LinkGroup (56-119)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Size
  • GitHub Check: E2E Tests (pnpm, esbuild)
  • GitHub Check: Lint Packages
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: Unit Tests
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (4)
apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx (4)

2-2: Icon import style is correct

Good use of lucide-react with the required Icon suffix (ArrowUpRightIcon, Settings2Icon).


128-139: Typography and description layout look solid

Good use of tracking-tight and muted foreground. The description is safely clamped for both sm and md viewports.


140-151: Mobile actions grouping: good separation

Hiding the action cluster on lg+ and providing a compact mobile row is consistent with the rest of the dashboard.


55-60: The scripts will output the component’s code and any usage of client, imageUrl, and icon within it so we can confirm which props are truly unused and whether the icon type should be widened. Once we have that, I’ll update the review comment accordingly.

@graphite-app
Copy link
Contributor

graphite-app bot commented Aug 26, 2025

Merge activity

<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on updating UI components across various files in the application. It includes adjustments to icon sizes, component styles, and the introduction of new icons, enhancing the overall user interface and experience.

### Detailed summary
- Changed `PlusIcon` size from `size-4` to `size-3.5` in multiple buttons.
- Replaced `SettingsIcon` with `Settings2Icon`.
- Added `DatabaseIcon`, `WebhookIcon`, `TokenIcon`, `ArrowDownToLineIcon`, and others to various headers.
- Updated button styles to `bg-card` and changed variants to `outline`.
- Modified header layouts to include new icons and adjusted spacing.
- Removed actions from several `ProjectPage` components and replaced them with links.
- Adjusted descriptions and added new links in the `ContractsPage`, `PaymentsPage`, and other components.

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- New Features
  - Header icons added across many pages; Settings now appears as a dedicated header control where provided.
  - Single link renders as a direct action button; multiple links grouped under a labeled "Resources" menu with chevron.

- Refactor
  - Project header redesigned to an icon-driven layout; mobile-specific branching removed and actions reorganized.

- Style
  - Button variants, spacing, iconography, and dropdown alignment adjusted (smaller icons, new arrow/chevron visuals, reduced item padding).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@graphite-app graphite-app bot force-pushed the 08-27-dashboard_update_project_header_style branch from b015f20 to e651d0a Compare August 26, 2025 22:35
@vercel vercel bot temporarily deployed to Preview – docs-v2 August 26, 2025 22:35 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui August 26, 2025 22:35 Inactive
@vercel vercel bot temporarily deployed to Preview – nebula August 26, 2025 22:35 Inactive
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground August 26, 2025 22:35 Inactive
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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx (1)

3-3: Use the dashboard Button primitive

Follow the dashboard convention to import UI primitives from "@/components/ui/*".

Apply:

-import { Button } from "@workspace/ui/components/button";
+import { Button } from "@/components/ui/button";
♻️ Duplicate comments (1)
apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx (1)

1-3: Make this a client component and use the dashboard UI Button import

This header composes LinkGroup (a client component) and renders interactive Buttons. Align with app conventions.

Apply:

+ "use client";
-
-import { Button } from "@workspace/ui/components/button";
+import { Button } from "@/components/ui/button";
 import { ArrowUpRightIcon, Settings2Icon } from "lucide-react";
🧹 Nitpick comments (5)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx (1)

112-119: Potential TS type mismatch for header.icon

header.icon is typed as React.FC<{ className?: string }>, but the inline icon is declared as () => JSX.Element (no props). Depending on tsconfig settings, this can fail assignability. Minimal fix: accept an optional props object (even if unused).

Apply:

-          icon: () => (
+          icon: (_?: { className?: string }) => (
             <ProjectAvatar
               className="size-12"
               client={client}
               src={project.image ?? ""}
             />
           ),

Alternatively, define a named component with the prop typed and pass it.

apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx (2)

60-62: Broaden icon prop to React.ComponentType for better interoperability

React.ComponentType is more idiomatic and accepts both FC and forwardRef components. This also improves compatibility with parameterless components.

Apply:

-  icon: React.FC<{ className?: string }>;
+  icon: React.ComponentType<{ className?: string }>;
   isProjectIcon?: boolean;

59-61: Remove unused imageUrl prop from ProjectPageHeaderProps

After verifying that props.imageUrl is never referenced in ProjectPageHeader (only declared on line 59) and there are no direct JSX calls passing an imageUrl prop into that component, it’s safe—and clearer—to drop it entirely.

• In apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
– Remove line
ts imageUrl?: string | null;
• Call sites spread in all of props.header (e.g. in project-page.tsx) won’t break—any existing imageUrl field on those header objects will simply be ignored by the component.
• For full cleanup, you may also omit the imageUrl property from whatever object builds props.header in the parent ProjectPage component.

apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx (2)

82-89: Minor: outline variant already adds a border

border class is likely redundant with variant="outline". Consider removing to avoid double borders if themes change.

Apply:

-        <Button
-          variant="outline"
-          size="sm"
-          className="rounded-full border gap-2 bg-card [&[data-state=open]>svg]:rotate-180"
-        >
+        <Button
+          variant="outline"
+          size="sm"
+          className="rounded-full gap-2 bg-card [&[data-state=open]>svg]:rotate-180"
+        >

105-112: Optional: Use NavLink for internal resources

For internal links (non-http), prefer NavLink to get active states “for free” per dashboard guidelines. You can keep Link for external URLs.

Example:

-              <Link
+              {isExternal ? (
+                <Link
                   href={link.href}
                   target={isExternal ? "_blank" : undefined}
                   rel={isExternal ? "noopener noreferrer" : undefined}
-              >
-                <Icon className="size-4 text-muted-foreground" />
-                {linkTypeToLabel[link.type]}
-              </Link>
+                >
+                  <Icon className="size-4 text-muted-foreground" />
+                  {linkTypeToLabel[link.type]}
+                </Link>
+              ) : (
+                <NavLink href={link.href}>
+                  <Icon className="size-4 text-muted-foreground" />
+                  {linkTypeToLabel[link.type]}
+                </NavLink>
+              )}

Note: import { NavLink } from "@/components/ui/NavLink".

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b015f20 and e651d0a.

📒 Files selected for processing (24)
  • apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx (4 hunks)
  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx (2 hunks)
  • apps/dashboard/src/@/components/contracts/import-contract/modal.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/account-abstraction/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/import-contract-button.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/page.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/import/import-engine-dialog.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/overview/engine-instances-table.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/insight/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx (4 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/rpc/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/layout.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/cards.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/page.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/vault/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/contracts/page.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (20)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/layout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/overview/engine-instances-table.tsx
  • apps/dashboard/src/@/components/contracts/import-contract/modal.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/cards.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/rpc/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/import-contract-button.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/contracts/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/(general)/import/import-engine-dialog.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/insight/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/vault/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/account-abstraction/page.tsx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from @/types or local types.ts barrels
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose

Files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx
  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
  • apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)

Files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx
  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
  • apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx
apps/{dashboard,playground-web}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/{dashboard,playground-web}/**/*.{ts,tsx}: Import UI primitives from @/components/ui/* (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Use NavLink for internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Use cn() from @/lib/utils for conditional class logic
Use design system tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components (Node edge): Start files with import "server-only";
Client Components (browser): Begin files with 'use client';
Always call getAuthToken() to retrieve JWT from cookies on server side
Use Authorization: Bearer header – never embed tokens in URLs
Return typed results (e.g., Project[], User[]) – avoid any
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stable queryKeys for React Query cache hits
Configure staleTime/cacheTime in React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never import posthog-js in server components

Files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx
  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
  • apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx
🧠 Learnings (22)
📚 Learning: 2025-08-20T10:35:18.543Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx:77-81
Timestamp: 2025-08-20T10:35:18.543Z
Learning: The webhooks/payments route exists at apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx and was added as part of the unified project layout changes.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx
📚 Learning: 2025-08-20T10:35:18.543Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx:77-81
Timestamp: 2025-08-20T10:35:18.543Z
Learning: The webhooks/payments route exists at apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx and was added as part of the unified project layout PR #7888.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx
  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/components/*.client.tsx : Client components must start with `'use client';` before imports.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Import UI primitives from `@/components/ui/*` (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Client Components (browser): Begin files with `'use client';`

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Always import from the central UI library under `@/components/ui/*` – e.g. `import { Button } from "@/components/ui/button"`.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Anything that consumes hooks from `tanstack/react-query` or thirdweb SDKs.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Reuse core UI primitives; avoid re-implementing buttons, cards, modals.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Prefer composable primitives over custom markup: `Button`, `Input`, `Select`, `Tabs`, `Card`, `Sidebar`, `Separator`, `Badge`.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Components that listen to user events, animations or live updates.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : When you need access to browser APIs (localStorage, window, IntersectionObserver etc.).

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Use the `container` class with a `max-w-7xl` cap for page width consistency.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Combine class names via `cn`, expose `className` prop if useful.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Merge class names with `cn` from `@/lib/utils` to keep conditional logic readable.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{tsx} : Expose `className` prop on root element of components for overrides

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Add `className` to the root element of every component for external overrides.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Use `cn()` from `@/lib/utils` for conditional class logic

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
📚 Learning: 2025-07-07T21:21:47.488Z
Learnt from: saminacodes
PR: thirdweb-dev/js#7543
File: apps/portal/src/app/pay/page.mdx:4-4
Timestamp: 2025-07-07T21:21:47.488Z
Learning: In the thirdweb-dev/js repository, lucide-react icons must be imported with the "Icon" suffix (e.g., ExternalLinkIcon, RocketIcon) as required by the new linting rule, contrary to the typical lucide-react convention of importing without the suffix.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx
  • apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Use `NavLink` for internal navigation with automatic active states in dashboard and playground apps

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Use `NavLink` (`@/components/ui/NavLink`) for internal navigation so active states are handled automatically.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Icons come from `lucide-react` or the project-specific `…/icons` exports – never embed raw SVG.

Applied to files:

  • apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx
🧬 Code graph analysis (1)
apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx (1)
apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx (2)
  • ActionLink (51-54)
  • LinkGroup (56-119)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: E2E Tests (pnpm, esbuild)
  • GitHub Check: Lint Packages
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: Size
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (5)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx (4)

10-10: Icon import looks correct and aligns with the new header API.

Importing WalletProductIcon and using it as header.icon is consistent with the PR’s icon-driven headers.


58-59: Good use of the new icon slot.

Passing WalletProductIcon via header.icon (without isProjectIcon) correctly renders it inside the bordered circular container in the header.


69-69: Explicitly nulling actions matches the new header contract.

Setting actions: null is consistent with the removal of per-page action buttons in favor of links/settings.


70-72: Route Verification Completed: The settings/wallets route exists

• Confirmed presence of apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/wallets/page.tsx containing the wallet settings page.
• Noted ancillary files under that directory (e.g. components/InAppWalletSettingsUI.stories.tsx) and references such as loginRedirect('/team/${team_slug}/settings/wallets') and inAppConfig: ${projectLayout}/settings/wallets``.

No broken link risk—this route is implemented. Proceed with merge.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx (1)

29-29: Avatar import for project header: looks good.

Using ProjectAvatar for the project overview icon aligns with the new isProjectIcon flow.

Comment on lines +63 to +75
<Link
href={link.href}
target={link.href.startsWith("http") ? "_blank" : undefined}
>
<Button
variant="outline"
size="sm"
className="rounded-full border gap-2 bg-card"
>
<Icon className="size-3.5 text-muted-foreground" />
{linkTypeToLabel[link.type]}
</Button>
</Link>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix invalid nesting (Link wrapping Button) and add rel for external links

Current markup likely renders , which is invalid and harms accessibility. Use Button asChild to render an anchor styled as a button and add rel for external links.

Apply:

-      <Link
-        href={link.href}
-        target={link.href.startsWith("http") ? "_blank" : undefined}
-      >
-        <Button
-          variant="outline"
-          size="sm"
-          className="rounded-full border gap-2 bg-card"
-        >
-          <Icon className="size-3.5 text-muted-foreground" />
-          {linkTypeToLabel[link.type]}
-        </Button>
-      </Link>
+      <Button
+        asChild
+        variant="outline"
+        size="sm"
+        className="rounded-full border gap-2 bg-card"
+      >
+        <Link
+          href={link.href}
+          target={link.href.startsWith("http") ? "_blank" : undefined}
+          rel={link.href.startsWith("http") ? "noopener noreferrer" : undefined}
+        >
+          <Icon className="size-3.5 text-muted-foreground" />
+          {linkTypeToLabel[link.type]}
+        </Link>
+      </Button>
📝 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.

Suggested change
<Link
href={link.href}
target={link.href.startsWith("http") ? "_blank" : undefined}
>
<Button
variant="outline"
size="sm"
className="rounded-full border gap-2 bg-card"
>
<Icon className="size-3.5 text-muted-foreground" />
{linkTypeToLabel[link.type]}
</Button>
</Link>
<Button
asChild
variant="outline"
size="sm"
className="rounded-full border gap-2 bg-card"
>
<Link
href={link.href}
target={link.href.startsWith("http") ? "_blank" : undefined}
rel={link.href.startsWith("http") ? "noopener noreferrer" : undefined}
>
<Icon className="size-3.5 text-muted-foreground" />
{linkTypeToLabel[link.type]}
</Link>
</Button>
🤖 Prompt for AI Agents
In apps/dashboard/src/@/components/blocks/project-page/header/link-group.tsx
around lines 63 to 75, the code currently wraps a Button inside a Link which
produces invalid <a><button/></a> nesting; replace this by rendering the Button
as the anchor (use Button's asChild prop) and forward href/target/rel to the
anchor: remove the outer Link, render Button asChild so it outputs an <a> with
href; set target to "_blank" for external hrefs and add rel="noopener
noreferrer" for those external links; keep Icon and label children unchanged.

@graphite-app graphite-app bot merged commit e651d0a into main Aug 26, 2025
25 checks passed
@graphite-app graphite-app bot deleted the 08-27-dashboard_update_project_header_style branch August 26, 2025 22:47
@vercel vercel bot temporarily deployed to Production – docs-v2 August 26, 2025 22:47 Inactive
@vercel vercel bot temporarily deployed to Production – nebula August 26, 2025 22:47 Inactive
@vercel vercel bot temporarily deployed to Production – wallet-ui August 26, 2025 22:47 Inactive
@vercel vercel bot temporarily deployed to Production – thirdweb_playground August 26, 2025 22:47 Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Dashboard Involves changes to the Dashboard.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants