Skip to content

Conversation

GiselleNessi
Copy link
Contributor

@GiselleNessi GiselleNessi commented Aug 21, 2025


PR-Codex overview

This PR introduces a user feedback feature in the dashboard application, allowing users to submit feedback through a modal on both desktop and mobile interfaces. It captures this feedback using PostHog for analysis and displays a success notification upon submission.

Detailed summary

  • Added reportProductFeedback function in report.ts to capture user feedback.
  • Implemented feedback submission modal in SecondaryNav component for desktop.
  • Added feedback button and modal in MobileBurgerMenuButton for mobile.
  • Integrated success notifications using toast after feedback submission.
  • Removed direct feedback link and replaced it with a feedback dropdown/modal interface.

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

Summary by CodeRabbit

  • New Features

    • Replaced external Feedback link with in-app feedback panel in header and mobile menu; textarea (max 1000 chars), Cancel and Submit (disabled when empty), shows success message, clears input and closes panel.
    • Added in-panel “Contact support” link for technical issues.
    • Feedback submissions now record a product-feedback event (desktop/mobile source).
  • Style

    • Expandable/collapsible feedback UI with visual indicators, improved positioning and mobile menu scrolling.

@GiselleNessi GiselleNessi self-assigned this Aug 21, 2025
@GiselleNessi GiselleNessi requested review from a team as code owners August 21, 2025 15:00
Copy link

changeset-bot bot commented Aug 21, 2025

⚠️ No Changeset found

Latest commit: 04862de

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 Aug 21, 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 Sep 16, 2025 4:46pm
4 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
docs-v2 Skipped Skipped Sep 16, 2025 4:46pm
nebula Skipped Skipped Sep 16, 2025 4:46pm
thirdweb_playground Skipped Skipped Sep 16, 2025 4:46pm
wallet-ui Skipped Skipped Sep 16, 2025 4:46pm

Copy link
Contributor

coderabbitai bot commented Aug 21, 2025

Walkthrough

Replaces external Feedback links with in-app feedback UIs in the desktop secondary nav and mobile burger menu: adds client-side state, toggleable panels containing a textarea, Cancel/Submit handlers, an internal "Contact support" NavLink, and calls a new analytics reporter; Submit shows a success toast, clears input, and closes the panel.

Changes

Cohort / File(s) Summary
Secondary nav feedback dropdown
apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx
Added client-side state (showFeedbackDropdown, modalFeedback) and handlers (handleModalSubmit, handleModalCancel); replaced external Feedback link with an in-page dropdown dialog (textarea, Cancel/Submit); invokes reportProductFeedback with { feedback, source: "desktop" }; shows success toast; added NavLink to /team/~/support; positioned absolutely with z-index and accessibility attributes.
Mobile menu feedback section
apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.tsx
Introduced collapsible feedback section (showFeedbackSection, modalFeedback) with Chevron toggle, textarea (maxLength 1000), Cancel/Submit handlers; replaced external Feedback navigation with in-menu interactive panel; invokes reportProductFeedback with { feedback, source: "mobile" }; shows success toast, clears input, hides section; added overflow-y-auto for drawer.
Analytics reporter
apps/dashboard/src/@/analytics/report.ts
Added exported function `reportProductFeedback(properties: { feedback: string; source: "desktop"

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant UI as Nav/Menu UI
  participant State as Local State
  participant Handler as Submit/Cancel Handler
  participant Analytics as reportProductFeedback
  participant Toast as sonner.toast

  User->>UI: Open Feedback panel
  UI->>State: set showFeedback = true
  UI->>User: Render textarea + actions

  User->>UI: Type feedback
  UI->>State: update modalFeedback

  alt Submit
    User->>UI: Click Submit
    UI->>Handler: invoke handleModalSubmit
    Handler->>Analytics: reportProductFeedback({feedback, source})
    Analytics-->>Handler: ack
    Handler->>Toast: show success toast
    Handler->>State: clear modalFeedback
    Handler->>State: set showFeedback = false
    UI->>User: Hide panel
  else Cancel
    User->>UI: Click Cancel
    UI->>Handler: invoke handleModalCancel
    Handler->>State: clear modalFeedback
    Handler->>State: set showFeedback = false
    UI->>User: Hide panel
  end

  User->>UI: Click "Contact support"
  UI->>UI: Navigate to /team/~/support
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The PR description contains a clear PR-Codex overview and a detailed summary of the implemented changes (addition of reportProductFeedback and feedback UI in SecondaryNav and MobileBurgerMenuButton), but the repository's template fields remain unfilled and are left as commented placeholders at the top of the description. Specifically, the description does not populate the required template sections such as the formatted PR title/issue tag, "Notes for the reviewer", and an explicit "How to test" section with step-by-step verification and expected analytics events/payloads. Because those template fields are important for reviewer context and reproducible testing, the description does not fully meet the repository's template requirements. Please populate the template by adding the required formatted title or issue tag, a "Notes for the reviewer" section calling out any edge cases or implementation details, and an explicit "How to test" section with desktop and mobile steps, the expected PostHog event name and payload, and any required environment flags; once those are added reviewers can more easily validate the UI and analytics behavior.
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed The title "feat: add feedback collection UI to navigation" succinctly and accurately summarizes the primary change in this PR — adding in-app feedback UI to the navigation for desktop and mobile — and uses a conventional "feat:" prefix. It is concise, focused on the main user-visible change, and matches the modifications in SecondaryNav, MobileBurgerMenuButton, and the analytics reporter. No substantive clarification of intent is required for a reviewer to understand the PR's purpose.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch gi/product-feedback-top-menu

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • 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 057c54e and 04862de.

📒 Files selected for processing (3)
  • apps/dashboard/src/@/analytics/report.ts (1 hunks)
  • apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.tsx (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/dashboard/src/@/analytics/report.ts
  • apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx
  • apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.tsx
⏰ 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). (5)
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: Size
  • GitHub Check: E2E Tests (pnpm, esbuild)
  • GitHub Check: Lint Packages
  • GitHub Check: Analyze (javascript)

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.

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added the Dashboard Involves changes to the Dashboard. label Aug 21, 2025
Copy link
Contributor

graphite-app bot commented Aug 21, 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.

Copy link

codecov bot commented Aug 21, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 56.54%. Comparing base (ea46572) to head (04862de).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7895   +/-   ##
=======================================
  Coverage   56.54%   56.54%           
=======================================
  Files         904      904           
  Lines       58871    58871           
  Branches     4170     4170           
=======================================
  Hits        33287    33287           
  Misses      25478    25478           
  Partials      106      106           
Flag Coverage Δ
packages 56.54% <ø> (ø)
🚀 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.

Copy link
Contributor

github-actions bot commented Aug 21, 2025

size-limit report 📦

Path Size Loading time (3g) Running time (snapdragon) Total time
thirdweb (esm) 63.96 KB (-0.12% 🔽) 1.3 s (-0.12% 🔽) 232 ms (+338.07% 🔺) 1.6 s
thirdweb (cjs) 361.44 KB (0%) 7.3 s (0%) 634 ms (+32.43% 🔺) 7.9 s
thirdweb (minimal + tree-shaking) 5.73 KB (0%) 115 ms (0%) 107 ms (+4311.09% 🔺) 221 ms
thirdweb/chains (tree-shaking) 526 B (0%) 11 ms (0%) 112 ms (+8364.65% 🔺) 123 ms
thirdweb/react (minimal + tree-shaking) 19.15 KB (0%) 383 ms (0%) 131 ms (+4429.94% 🔺) 514 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: 6

🧹 Nitpick comments (5)
apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx (2)

64-72: Add accessibility attributes and use functional state toggle on the trigger.

Expose expanded state, wire it to the popup, and prefer functional updates.

Apply this diff:

-        <button
-          type="button"
-          onClick={() => setShowFeedbackDropdown(!showFeedbackDropdown)}
-          className="text-muted-foreground text-sm hover:text-foreground"
-        >
+        <button
+          type="button"
+          aria-expanded={showFeedbackDropdown}
+          aria-controls="feedback-dropdown"
+          onClick={() => setShowFeedbackDropdown((v) => !v)}
+          className="text-muted-foreground text-sm hover:text-foreground"
+        >

73-117: Reduce duplication by extracting a shared FeedbackPanel.

This panel is largely duplicated in MobileBurgerMenuButton. Extracting a small client component improves consistency and maintenance.

Example shape (new file):

// apps/dashboard/src/app/(app)/components/feedback/FeedbackPanel.client.tsx
"use client";
import React from "react";
import Link from "next/link";

type FeedbackPanelProps = {
  value: string;
  onChange: (v: string) => void;
  onCancel: () => void;
  onSubmit: (e?: React.FormEvent) => void;
  id?: string;
};

export function FeedbackPanel({
  value,
  onChange,
  onCancel,
  onSubmit,
  id = "feedback",
}: FeedbackPanelProps): React.ReactElement {
  const isEmpty = !value.trim();
  return (
    <form onSubmit={onSubmit} aria-labelledby={`${id}-heading`} className="space-y-4">
      <h2 id={`${id}-heading`} className="text-foreground text-base font-sans">
        Share your feedback with us:
      </h2>
      <label htmlFor={`${id}-text`} className="sr-only">
        Feedback
      </label>
      <textarea
        id={`${id}-text`}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        maxLength={1000}
        aria-describedby={`${id}-help`}
        className="w-full bg-background text-foreground rounded-lg p-4 min-h-[120px] resize-none border border-border placeholder-muted-foreground font-sans text-sm"
        placeholder="Tell us what you think..."
      />
      <div className="flex items-start justify-between gap-4">
        <div className="text-muted-foreground text-xs font-sans">
          <div>Have a technical issue?</div>
          <div>
            <Link id={`${id}-help`} href="/team/~/~/support" className="underline hover:text-foreground transition-colors">
              Contact support
            </Link>
            .
          </div>
        </div>
        <div className="flex gap-3 flex-shrink-0">
          <button type="button" onClick={onCancel} className="bg-transparent text-foreground px-4 py-1.5 rounded-full font-sans text-sm border border-border hover:bg-muted">
            Cancel
          </button>
          <button type="submit" disabled={isEmpty} aria-disabled={isEmpty} className="bg-primary text-primary-foreground px-4 py-1.5 rounded-full font-sans text-sm hover:bg-primary/90 disabled:opacity-50">
            Submit
          </button>
        </div>
      </div>
    </form>
  );
}
apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.tsx (3)

41-43: State additions are fine, but consider extracting to a small hook.

You can centralize feedback state/handlers across desktop and mobile (e.g., useFeedbackPanel).


210-221: A11y: reflect expanded state and use functional toggling.

Expose the expanded state and associate the control with the collapsible region.

Apply this diff:

-                <button
-                  type="button"
-                  className="flex items-center justify-between text-muted-foreground hover:text-foreground"
-                  onClick={() => setShowFeedbackSection(!showFeedbackSection)}
-                >
+                <button
+                  type="button"
+                  aria-expanded={showFeedbackSection}
+                  aria-controls="mobile-feedback-section"
+                  className="flex items-center justify-between text-muted-foreground hover:text-foreground"
+                  onClick={() => setShowFeedbackSection((v) => !v)}
+                >

62-72: Restore original body overflow instead of hardcoding “initial”.

This avoids clobbering a pre-existing body overflow style when multiple overlays are used.

Example:

useLayoutEffect(() => {
  const prev = document.body.style.overflow;
  document.body.style.overflow = isMenuOpen ? "hidden" : prev;
  return () => {
    document.body.style.overflow = prev;
  };
}, [isMenuOpen]);
📜 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 2d12249 and 1c8a9c6.

📒 Files selected for processing (2)
  • apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.tsx (5 hunks)
🧰 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)/components/MobileBurgerMenuButton.tsx
  • apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.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)/components/MobileBurgerMenuButton.tsx
  • apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.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)/components/MobileBurgerMenuButton.tsx
  • apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx
🧠 Learnings (12)
📚 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)/components/MobileBurgerMenuButton.tsx
  • apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.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/app/(app)/components/Header/SecondaryNav/SecondaryNav.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/app/(app)/components/Header/SecondaryNav/SecondaryNav.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)/components/Header/SecondaryNav/SecondaryNav.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/app/(app)/components/Header/SecondaryNav/SecondaryNav.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/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx
📚 Learning: 2025-05-30T17:14:25.332Z
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.

Applied to files:

  • apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.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/app/(app)/components/Header/SecondaryNav/SecondaryNav.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/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx
📚 Learning: 2025-06-17T18:30:52.976Z
Learnt from: MananTank
PR: thirdweb-dev/js#7356
File: apps/nebula/src/app/not-found.tsx:1-1
Timestamp: 2025-06-17T18:30:52.976Z
Learning: In the thirdweb/js project, the React namespace is available for type annotations (like React.FC) without needing to explicitly import React. This is project-specific configuration that differs from typical TypeScript/React setups.

Applied to files:

  • apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.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 : Use React Query (`tanstack/react-query`) for all client data fetching.

Applied to files:

  • apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.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/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx
⏰ 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). (7)
  • GitHub Check: E2E Tests (pnpm, esbuild)
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: Size
  • GitHub Check: Unit Tests
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: Lint Packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (4)
apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx (2)

1-1: Correct: client component directive is present.

This component uses React state, so having "use client" is required and correct.


5-5: Importing useState is appropriate here.

No concerns with this addition.

apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.tsx (2)

4-6: Icon imports for expand/collapse LGTM.

These are appropriate for the new collapsible section.


89-89: Good: make drawer scrollable.

Adding overflow-y-auto to the drawer fixes content clipping on smaller screens.

@vercel vercel bot temporarily deployed to Preview – nebula August 21, 2025 18:23 Inactive
@vercel vercel bot temporarily deployed to Preview – docs-v2 August 21, 2025 18:23 Inactive
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground August 21, 2025 18:23 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui August 21, 2025 18:23 Inactive
@GiselleNessi GiselleNessi added the DO NOT MERGE This pull request is still in progress and is not ready to be merged. label Aug 21, 2025
@vercel vercel bot temporarily deployed to Preview – wallet-ui August 21, 2025 18:33 Inactive
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground August 21, 2025 18:33 Inactive
@vercel vercel bot temporarily deployed to Preview – docs-v2 August 21, 2025 18:33 Inactive
@vercel vercel bot temporarily deployed to Preview – nebula August 21, 2025 18:33 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 (2)
apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.tsx (2)

265-279: Use design-system Button primitives for actions (consistency + a11y).

Replace raw buttons with <Button> and keep disabled semantics; aligns with apps/dashboard UI guidelines.

-                          <button
-                            type="button"
-                            onClick={handleModalCancel}
-                            className="flex-1 bg-transparent text-foreground px-3 py-2 rounded-full font-sans text-sm border border-border hover:bg-muted transition-colors"
-                          >
-                            Cancel
-                          </button>
-                          <button
-                            type="submit"
-                            disabled={!modalFeedback.trim()}
-                            aria-disabled={!modalFeedback.trim()}
-                            className="flex-1 bg-primary text-primary-foreground px-3 py-2 rounded-full font-sans text-sm hover:bg-primary/90 transition-colors disabled:opacity-50"
-                          >
-                            Submit
-                          </button>
+                          <Button
+                            type="button"
+                            onClick={handleModalCancel}
+                            variant="outline"
+                            className="flex-1"
+                          >
+                            Cancel
+                          </Button>
+                          <Button
+                            type="submit"
+                            disabled={!modalFeedback.trim()}
+                            aria-disabled={!modalFeedback.trim()}
+                            className="flex-1 disabled:opacity-50"
+                          >
+                            Submit
+                          </Button>

256-263: Fix the hard-coded support link to use the team slug from the router

The “Contact support” link currently points to /team/~/support, which will 404 unless you literally have a team named “~”. It needs to read the team_slug from useParams() and build the correct path, falling back to the team overview at /team if no slug is present.

• Add the useParams import alongside the existing imports.
• Inside your MobileBurgerMenuButton component (near the other hooks), derive the slug and compute supportHref.
• Swap the hard-coded href on the NavLink to use this new variable.

Relevant diff:

--- a/apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.tsx
+++ b/apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.tsx
@@ 3,6 ✎
 import Link from "next/link";
+import { useParams } from "next/navigation";

@@ function MobileBurgerMenuButton() {
   "use client";

   // …other hooks…
+  const { team_slug } = useParams<{ team_slug?: string }>() ?? {};
+  const supportHref = team_slug ? `/team/${team_slug}/~/support` : "/team";

   // …JSX…
@@ 258,263 ✎
-  <NavLink
-    href="/team/~/support"
+  <NavLink
+    href={supportHref}
     className="underline hover:text-foreground transition-colors"
   >
     Contact support

With these changes, the link will correctly resolve for the current team or redirect to /team when no slug is available.

🧹 Nitpick comments (6)
apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.tsx (6)

42-43: State is scoped and minimal, but consider a clearer name.

Nit: modalFeedback reads like a modal; this UI is an in-panel section. Consider feedbackText to reduce confusion.

-  const [modalFeedback, setModalFeedback] = useState("");
+  const [feedbackText, setFeedbackText] = useState("");

Note: update corresponding references in handlers and JSX.


52-52: Narrow the event type for better DX.

Type the form event precisely.

-  const handleModalSubmit = (e?: React.FormEvent) => {
+  const handleModalSubmit = (e?: React.FormEvent<HTMLFormElement>) => {

214-226: Toggler: add a11y attributes and use functional state update.

  • Add aria-expanded and aria-controls for screen readers.
  • Use functional update to avoid stale closures.
-                <button
+                <button
                   type="button"
-                  className="flex items-center justify-between text-muted-foreground hover:text-foreground"
-                  onClick={() => setShowFeedbackSection(!showFeedbackSection)}
+                  className="flex items-center justify-between text-muted-foreground hover:text-foreground"
+                  aria-expanded={showFeedbackSection}
+                  aria-controls="mobile-feedback-section"
+                  onClick={() => setShowFeedbackSection((v) => !v)}
                 >
                   <span>Feedback</span>

228-236: Wrap the feedback block with region semantics for better navigation.

Give the container an id (to match aria-controls) and landmark semantics.

-                {showFeedbackSection && (
-                  <div className="pl-0 pr-4 space-y-4 mb-6">
+                {showFeedbackSection && (
+                  <div
+                    id="mobile-feedback-section"
+                    role="region"
+                    aria-labelledby="mobile-feedback-heading"
+                    className="pl-0 pr-4 space-y-4 mb-6"
+                  >
                     <h3
                       id="mobile-feedback-heading"
                       className="text-sm font-medium text-foreground mb-2"
                     >
                       Share your feedback with us:
                     </h3>

241-248: Textarea: add basic form semantics.

Add name and required to play nicely with forms and validation.

-                      <textarea
+                      <textarea
                         id="mobile-feedback-text"
-                        value={modalFeedback}
-                        onChange={(e) => setModalFeedback(e.target.value)}
+                        name="feedback"
+                        required
+                        value={modalFeedback}
+                        onChange={(e) => setModalFeedback(e.target.value)}
                         maxLength={1000}
                         aria-describedby="mobile-feedback-help"
                         className="w-full bg-background text-foreground rounded-lg p-3 min-h-[100px] resize-none border border-border focus:border-border focus:outline-none placeholder-muted-foreground font-sans text-sm"
                         placeholder="Tell us what you think..."
                       />

214-285: Optional: auto-focus the textarea when opening the feedback section.

Improves UX on mobile; focus only when the panel transitions open.

Add outside the shown range:

import { useEffect, useRef } from "react";

// inside component
const feedbackRef = useRef<HTMLTextAreaElement>(null);
useEffect(() => {
  if (showFeedbackSection) {
    feedbackRef.current?.focus();
  }
}, [showFeedbackSection]);

And attach to the textarea:

-  <textarea
+  <textarea
+    ref={feedbackRef}
📜 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 04e750c and 5da4e3b.

📒 Files selected for processing (2)
  • apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.tsx (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.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)/components/MobileBurgerMenuButton.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)/components/MobileBurgerMenuButton.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)/components/MobileBurgerMenuButton.tsx
🧠 Learnings (7)
📚 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/app/(app)/components/MobileBurgerMenuButton.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/app/(app)/components/MobileBurgerMenuButton.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/app/(app)/components/MobileBurgerMenuButton.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/app/(app)/components/MobileBurgerMenuButton.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)/components/MobileBurgerMenuButton.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)/components/MobileBurgerMenuButton.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/app/(app)/components/MobileBurgerMenuButton.tsx
⏰ 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). (8)
  • GitHub Check: Size
  • GitHub Check: Unit Tests
  • GitHub Check: Lint Packages
  • GitHub Check: E2E Tests (pnpm, esbuild)
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: Build Packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (5)
apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.tsx (5)

4-6: LGTM: Chevron icons wired for the collapsible feedback control.

Imports are minimal and tree-shake clean.


19-19: Good move: adopt NavLink for internal navigation (support link).

This aligns with dashboard navigation guidelines; consider standardizing other internal Links in a follow-up.


52-60: No PII + form-safe submit — nice.

Preventing default and logging only length in non-prod addresses the earlier privacy concern.


62-65: Clear cancel behavior.

Resets input and closes the section without side effects.


94-94: Scrollable drawer container is the right call.

Adding overflow-y-auto prevents viewport lock on long content.

@vercel vercel bot temporarily deployed to Preview – thirdweb_playground August 22, 2025 16:46 Inactive
@vercel vercel bot temporarily deployed to Preview – nebula August 22, 2025 16:46 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui August 22, 2025 16:46 Inactive
@vercel vercel bot temporarily deployed to Preview – docs-v2 August 22, 2025 16:46 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: 3

♻️ Duplicate comments (1)
apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.tsx (1)

261-273: Ensure the support link includes the current team_slug

The <NavLink> is currently hard-coded to "/team/~/support", but your routing setup defines a literal ~ segment after a dynamic [team_slug]. You need to pull in the active team_slug via useParams() and interpolate it into the href.

– File: apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.tsx
– Lines: ~261–273

Suggested changes:

+ import { useParams } from "next/navigation";
  // …inside your component body…
+ const { team_slug } = useParams() as { team_slug: string };

   <div className="flex flex-col gap-3">
     <p
       id="mobile-feedback-help"
       className="text-muted-foreground text-xs"
     >
       Have a technical issue?{" "}
-      <NavLink
-        href="/team/~/support"
+      <NavLink
+        href={`/team/${team_slug}/~/support`}
         className="underline hover:text-foreground transition-colors"
       >
         Contact support
       </NavLink>
       .
  • Import and invoke useParams() from next/navigation to retrieve the dynamic team_slug.
  • Interpolate both the slug and the literal ~ segment into your path.
🧹 Nitpick comments (8)
apps/dashboard/src/@/analytics/report.ts (1)

565-575: Pass the properties object unchanged to posthog.capture for consistency.

Across this file we typically forward a single typed properties object directly. After the privacy refactor above, keep forwarding a single object to align with our analytics style guide.

-  posthog.capture("product feedback submitted", {
-    feedbackLength,
-    source: properties.source,
-  });
+  posthog.capture("product feedback submitted", { feedbackLength, source: properties.source });
apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.tsx (4)

226-237: Improve a11y on the Feedback toggle.

Expose state to AT and link the control to the content region.

-                <button
+                <button
                   type="button"
                   className="flex items-center justify-between text-muted-foreground hover:text-foreground"
-                  onClick={() => setShowFeedbackSection(!showFeedbackSection)}
+                  onClick={() => setShowFeedbackSection(!showFeedbackSection)}
+                  aria-expanded={showFeedbackSection}
+                  aria-controls="mobile-feedback-section"
                 >

And add id="mobile-feedback-section" on the container (see next comment).


239-295: Wrap the feedback area with landmark semantics and a stable id; use Button primitives for actions.

  • Add region semantics + id for aria-controls target.
  • Replace raw buttons with our design-system Button components per dashboard guidelines.
-                {showFeedbackSection && (
-                  <div className="pl-0 pr-4 space-y-4 mb-6">
+                {showFeedbackSection && (
+                  <div
+                    id="mobile-feedback-section"
+                    role="region"
+                    aria-labelledby="mobile-feedback-heading"
+                    className="pl-0 pr-4 space-y-4 mb-6"
+                  >
@@
-                        <div className="flex gap-3">
-                          <button
-                            type="button"
-                            onClick={handleModalCancel}
-                            className="flex-1 bg-transparent text-foreground px-3 py-2 rounded-full font-sans text-sm border border-border hover:bg-muted transition-colors"
-                          >
-                            Cancel
-                          </button>
-                          <button
-                            type="submit"
-                            disabled={!modalFeedback.trim()}
-                            aria-disabled={!modalFeedback.trim()}
-                            className="flex-1 bg-primary text-primary-foreground px-3 py-2 rounded-full font-sans text-sm hover:bg-primary/90 transition-colors disabled:opacity-50"
-                          >
-                            Submit
-                          </button>
-                        </div>
+                        <div className="flex gap-3">
+                          <Button
+                            type="button"
+                            onClick={handleModalCancel}
+                            variant="outline"
+                            className="flex-1"
+                          >
+                            Cancel
+                          </Button>
+                          <Button
+                            type="submit"
+                            disabled={!modalFeedback.trim()}
+                            aria-disabled={!modalFeedback.trim()}
+                            className="flex-1 disabled:opacity-50"
+                          >
+                            Submit
+                          </Button>
+                        </div>

Note: Button is already imported at line 21.


78-88: Prefer useEffect over useLayoutEffect for scroll locking.

No layout measurements here; useEffect avoids unnecessary sync blocking.

-import { useLayoutEffect, useState } from "react";
+import { useEffect, useState } from "react";
@@
-  useLayoutEffect(() => {
+  useEffect(() => {

136-152: Use NavLink for internal routes to align with dashboard navigation patterns.

Swap internal Links to NavLink: /account, /chainlist, /explore, /home. Keep external links (Docs, Playground) as is.

-                <Link
+                <NavLink
                   className="flex items-center gap-2 py-1 text-base text-muted-foreground hover:text-foreground"
                   href="/account"
                 >
@@
-                </Link>
+                </NavLink>
@@
-            <Link
+            <NavLink
               className="text-muted-foreground hover:text-foreground "
               href="/chainlist"
             >
               Chainlist
-            </Link>
+            </NavLink>
@@
-            <Link
+            <NavLink
               className="text-muted-foreground hover:text-foreground "
               href="/explore"
             >
               Explore Contracts
-            </Link>
+            </NavLink>
@@
-            <Link
+            <NavLink
               className="text-base text-muted-foreground hover:text-foreground"
               href="/home"
             >
               Home Page
-            </Link>
+            </NavLink>

Imports already include NavLink (line 21).

Also applies to: 183-189, 199-205, 206-212

apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx (3)

80-87: Add a11y state and dialog semantics.

  • Reflect expanded state on the toggle and connect it to the dialog with aria-controls.
  • Mark the popup as a modal dialog (role + aria-modal).
-        <button
+        <button
           type="button"
           onClick={() => setShowFeedbackDropdown(!showFeedbackDropdown)}
           className="text-muted-foreground text-sm hover:text-foreground border border-border px-3 py-1.5 rounded-full hover:bg-muted transition-colors"
+          aria-expanded={showFeedbackDropdown}
+          aria-controls="feedback-dropdown"
         >
@@
-          <div
+          <div
             id="feedback-dropdown"
-            role="dialog"
+            role="dialog"
+            aria-modal="true"
             aria-labelledby="feedback-heading"
             className="absolute top-full right-0 mt-2 bg-background border border-border rounded-2xl p-3 w-96 z-50"
           >

Also applies to: 89-101


130-145: Use Button primitives for actions (design system consistency).

Replace raw buttons with <Button> from @/components/ui/button.

+ import { Button } from "@/components/ui/button";
@@
-                  <button
-                    type="button"
-                    onClick={handleModalCancel}
-                    className="bg-transparent text-foreground px-4 py-1.5 rounded-full font-sans text-sm border border-border hover:bg-muted transition-colors"
-                  >
-                    Cancel
-                  </button>
-                  <button
-                    type="submit"
-                    disabled={!modalFeedback.trim()}
-                    aria-disabled={!modalFeedback.trim()}
-                    className="bg-primary text-primary-foreground px-4 py-1.5 rounded-full font-sans text-sm hover:bg-primary/90 transition-colors disabled:opacity-50"
-                  >
-                    Submit
-                  </button>
+                  <Button type="button" onClick={handleModalCancel} variant="outline">
+                    Cancel
+                  </Button>
+                  <Button type="submit" disabled={!modalFeedback.trim()} aria-disabled={!modalFeedback.trim()} className="disabled:opacity-50">
+                    Submit
+                  </Button>

120-128: Minor: ensure help text is associated with the textarea.

You already set aria-describedby="feedback-help" on the textarea; move id="feedback-help" to the wrapping text block (not the NavLink only) to guarantee association if the link gets focus.

-                <div className="text-muted-foreground text-xs font-sans">
+                <div id="feedback-help" className="text-muted-foreground text-xs font-sans">
📜 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 5da4e3b and 8b2716d.

📒 Files selected for processing (3)
  • apps/dashboard/src/@/analytics/report.ts (1 hunks)
  • apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.tsx (6 hunks)
🧰 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/@/analytics/report.ts
  • apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx
  • apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.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/@/analytics/report.ts
  • apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx
  • apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.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/@/analytics/report.ts
  • apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx
  • apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.tsx
🧠 Learnings (18)
📚 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 src/@/analytics/report.ts : Review `src/@/analytics/report.ts` before adding analytics events to check for duplicates

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
📚 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 src/@/analytics/report.ts : Analytics event name: human-readable `<subject> <verb>` (e.g., "contract deployed"); function: `report<Subject><Verb>` (PascalCase)

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
📚 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/src/@/analytics/report.ts : Mandatory JSDoc: explain Why the event exists and Who owns it (`username`).

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
📚 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/src/@/analytics/report.ts : Typed properties: accept a single `properties` object and pass it unchanged to `posthog.capture`.

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
📚 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/src/@/analytics/report.ts : Reporting helper: `report<Subject><Verb>` (PascalCase); all live in `src/@/analytics/report.ts`.

Applied to files:

  • apps/dashboard/src/@/analytics/report.ts
📚 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/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx
  • apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.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/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx
  • apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.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)/components/Header/SecondaryNav/SecondaryNav.tsx
  • apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.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/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx
  • apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.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/app/(app)/components/Header/SecondaryNav/SecondaryNav.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/app/(app)/components/Header/SecondaryNav/SecondaryNav.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/app/(app)/components/Header/SecondaryNav/SecondaryNav.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)/components/Header/SecondaryNav/SecondaryNav.tsx
  • apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.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 : Pages requiring fast transitions where data is prefetched on the client.

Applied to files:

  • apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.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/app/(app)/components/Header/SecondaryNav/SecondaryNav.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 : Use React Query (`tanstack/react-query`) for all client data fetching.

Applied to files:

  • apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.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/app/(app)/components/MobileBurgerMenuButton.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/app/(app)/components/MobileBurgerMenuButton.tsx
🧬 Code graph analysis (2)
apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx (1)
apps/dashboard/src/@/analytics/report.ts (1)
  • reportProductFeedback (565-575)
apps/dashboard/src/app/(app)/components/MobileBurgerMenuButton.tsx (1)
apps/dashboard/src/@/analytics/report.ts (1)
  • reportProductFeedback (565-575)
⏰ 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). (8)
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: Size
  • GitHub Check: Unit Tests
  • GitHub Check: Lint Packages
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: Build Packages
  • GitHub Check: E2E Tests (pnpm, esbuild)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (1)
apps/dashboard/src/@/analytics/report.ts (1)

555-564: Verify analytics event naming, uniqueness, and ownership

  • The event name "product feedback submitted" correctly follows the <subject> <verb> pattern, and the function reportProductFeedback matches the PascalCase requirement.
  • A search in apps/dashboard/src/@/analytics/report.ts shows this is the only occurrence of both the event name and its reporting function, so there are no duplicates.
  • Please confirm that @gisellechacon is the intended owner of this event (the PR author is @GiselleNessi).

Copy link
Contributor

graphite-app bot commented Sep 16, 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 introduces a new feature for collecting user feedback within the application. It implements feedback submission forms in both desktop and mobile components, capturing user feedback and sending it to PostHog for analysis.

### Detailed summary
- Added `reportProductFeedback` function in `report.ts` to handle feedback submissions.
- Implemented feedback submission in the `SecondaryNavLinks` component.
- Added feedback dropdown with a form in `SecondaryNavLinks`.
- Integrated feedback functionality in the `MobileBurgerMenuButton` component.
- Included success notifications using `toast` for feedback submissions in both 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**
  * Replaced external Feedback link with an in-app feedback panel in the header and mobile menu.
  * Panel includes a textarea (max 1000 chars), Cancel and Submit actions; Submit is disabled when empty, shows a success message, clears input and closes the panel.
  * Adds an in-panel “Contact support” link for technical issues and preserves existing header controls.

* **Style**
  * Expandable/collapsible feedback UI with visual indicators, improved positioning and mobile menu scrolling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@graphite-app graphite-app bot force-pushed the gi/product-feedback-top-menu branch from 6263aff to 04862de Compare September 16, 2025 16:37
@vercel vercel bot temporarily deployed to Preview – nebula September 16, 2025 16:37 Inactive
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground September 16, 2025 16:37 Inactive
@vercel vercel bot temporarily deployed to Preview – docs-v2 September 16, 2025 16:37 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui September 16, 2025 16:37 Inactive
@GiselleNessi GiselleNessi added the merge-queue Adds the pull request to Graphite's merge queue. label Sep 16, 2025
@graphite-app graphite-app bot merged commit 04862de into main Sep 16, 2025
25 checks passed
@graphite-app graphite-app bot deleted the gi/product-feedback-top-menu branch September 16, 2025 16:47
@vercel vercel bot temporarily deployed to Production – nebula September 16, 2025 16:47 Inactive
@vercel vercel bot temporarily deployed to Production – thirdweb_playground September 16, 2025 16:47 Inactive
@vercel vercel bot temporarily deployed to Production – docs-v2 September 16, 2025 16:47 Inactive
@vercel vercel bot temporarily deployed to Production – wallet-ui September 16, 2025 16: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. merge-queue Adds the pull request to Graphite's merge queue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants