-
Notifications
You must be signed in to change notification settings - Fork 618
Create shared UI library - @workspace/ui #7855
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
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. |
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughAdds a new shared UI workspace package (@workspace/ui) with components, styles, and build configs; apps adopt it via workspace deps and Next.js transpilePackages. Local Button implementations, Tailwind/PostCSS and many global CSS files are replaced by re-exports or wrappers; some thirdweb type imports/re-exports updated. Changes
Sequence Diagram(s)mermaid App->>UI: import Button, buttonVariants, ButtonProps, global.css, tailwind/postcss configs Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes ✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7855 +/- ##
=======================================
Coverage 56.54% 56.54%
=======================================
Files 904 904
Lines 58586 58586
Branches 4140 4140
=======================================
Hits 33126 33126
Misses 25354 25354
Partials 106 106
*This pull request uses carry forward flags. Click here to find out more. 🚀 New features to boost your workflow:
|
e9dcacb to
5cc22af
Compare
size-limit report 📦
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🔭 Outside diff range comments (2)
apps/dashboard/package.json (1)
28-32: Fix dependency order to unblock CI (alphabetical ordering).CI is failing with "dependencies should be ordered alphabetically." Move "@workspace/ui" after the "@vercel/*" entries.
Apply this diff:
- "@workspace/ui": "workspace:*", "@thirdweb-dev/vault-sdk": "workspace:*", "@vercel/functions": "2.2.2", "@vercel/og": "^0.6.8", + "@workspace/ui": "workspace:*", "abitype": "1.0.8",apps/playground-web/package.json (1)
17-21: Fix dependency order to satisfy CI (alphabetical ordering).Move "@workspace/ui" into the block of scoped packages, right after "@tanstack/react-query".
Apply this diff:
"@tanstack/react-query": "5.81.5", + "@workspace/ui": "workspace:*", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "date-fns": "4.1.0", @@ - "@workspace/ui": "workspace:*", "use-debounce": "^10.0.5",Also applies to: 40-43
♻️ Duplicate comments (1)
packages/ui/src/components/button.tsx (1)
21-33: Variant parity: font weight and “upsell” styling diverge from playground-web (confirm intent or restore)If this design change is intentional across apps, document it. If parity is desired, restore the previous classes (including
font-semiboldon several variants and the gradient forupsell).Example diff:
variant: { default: "bg-foreground text-background hover:bg-foreground/90", destructive: - "bg-destructive hover:bg-destructive/90 text-destructive-foreground ", + "bg-destructive hover:bg-destructive/90 text-destructive-foreground font-semibold", ghost: "hover:bg-accent hover:text-accent-foreground", - link: "underline-offset-4 hover:underline", + link: "underline-offset-4 hover:underline font-semibold", outline: - "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground", + "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground font-semibold", - primary: "bg-primary hover:bg-primary/90 text-primary-foreground ", + primary: "bg-primary hover:bg-primary/90 text-primary-foreground font-semibold", - secondary: - "bg-secondary hover:bg-secondary/80 text-secondary-foreground ", + secondary: + "bg-secondary hover:bg-secondary/80 text-secondary-foreground font-semibold", upsell: - "bg-green-600 text-white hover:bg-green-700 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5 transition-all duration-200", + "bg-gradient-to-r from-purple-500 to-pink-500 text-white hover:from-purple-600 hover:to-pink-600 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5 transition-all duration-200", },
🧹 Nitpick comments (7)
packages/ui/tsconfig.json (1)
3-26: Tighten tsconfig for a library: fix lib target, drop Next plugin, and disallow JS.
- Use a lib that matches your target (ES2020 or ESNext) instead of "es6".
- This package isn’t a Next app; remove the "next" TS plugin to avoid unnecessary coupling.
- Prefer "allowJs": false to keep the UI package source strictly typed.
Apply:
"compilerOptions": { "target": "ES2020", - "lib": ["dom", "dom.iterable", "es6"], - "allowJs": true, + "lib": ["dom", "dom.iterable", "ES2020"], + "allowJs": false, "skipLibCheck": true, "strict": true, "forceConsistentCasingInFileNames": true, "noEmit": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "incremental": true, - "plugins": [ - { - "name": "next" - } - ], "baseUrl": ".", "paths": { "@/*": ["./src/*"] } },Optionally, add a dedicated build config to emit type declarations without changing this tsconfig:
// packages/ui/tsconfig.build.json { "extends": "./tsconfig.json", "compilerOptions": { "noEmit": false, "declaration": true, "emitDeclarationOnly": true, "outDir": "dist/types" }, "include": ["src/**/*.ts", "src/**/*.tsx"] }Then wire it into your build tooling as needed.
packages/ui/src/lib/utils.ts (1)
4-6: Add an explicit return type and spread inputs into clsx.Keeps with explicit typing guidelines and aligns with common clsx usage.
-export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)); +export function cn(...inputs: ClassValue[]): string { + return twMerge(clsx(...inputs)); }packages/ui/package.json (1)
4-6: Mark package as side-effect free for better tree-shaking.The UI package should be tree-shakeable. Declare sideEffects: false.
Apply this diff:
"private": true, + "sideEffects": false, "main": "./src/index.ts",packages/ui/src/components/button.tsx (4)
38-42: Prefer a type alias for ButtonProps (per repo guidelines)Switching to a type alias aligns with the project’s TypeScript conventions.
-export interface ButtonProps - extends React.ButtonHTMLAttributes<HTMLButtonElement>, - VariantProps<typeof buttonVariants> { - asChild?: boolean; -} +export type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & + VariantProps<typeof buttonVariants> & { + asChild?: boolean; + };
15-19: Minor: remove redundantrounded-mdfrom size variants
rounded-mdis already in the base classes (Line 7). Avoid duplication inlgandsm.lg: "h-11 rounded-md px-8", - sm: "h-9 rounded-md px-3", + sm: "h-9 px-3",Optionally drop
rounded-mdfromlgtoo if relying solely on the base class:- lg: "h-11 rounded-md px-8", + lg: "h-11 px-8",
25-25: Link variant lacks explicit color; considertext-primaryfor consistencyWithout a color token, links rely on inherited text color and can blend in.
- link: "underline-offset-4 hover:underline", + link: "text-primary underline-offset-4 hover:underline",
66-77: Accessibility: consider making non-button disabled elements unfocusable/inertFor
asChildcases (e.g., ), addingtabIndex={-1}and preventing default onClick whendisabledimproves a11y and UX.Example (apply alongside the earlier disabled-prop change):
- <Comp - aria-disabled={disabled ? true : undefined} + <Comp + aria-disabled={disabled ? true : undefined} + {...(!("type" in (btnOnlyProps ?? {})) && disabled + ? { tabIndex: -1, onClick: (e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); } } + : undefined)} className={cn( buttonVariants({ size, variant }), disabledClass, className, )} - disabled={disabled} ref={ref} {...props} {...btnOnlyProps} />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (11)
apps/dashboard/package.json(1 hunks)apps/dashboard/src/@/components/ui/button.tsx(1 hunks)apps/dashboard/tailwind.config.js(1 hunks)apps/playground-web/package.json(1 hunks)apps/playground-web/src/components/ui/button.tsx(1 hunks)apps/playground-web/tailwind.config.ts(1 hunks)packages/ui/package.json(1 hunks)packages/ui/src/components/button.tsx(1 hunks)packages/ui/src/index.ts(1 hunks)packages/ui/src/lib/utils.ts(1 hunks)packages/ui/tsconfig.json(1 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@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes
Avoidanyandunknownunless 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/playground-web/tailwind.config.tspackages/ui/src/index.tspackages/ui/src/lib/utils.tsapps/playground-web/src/components/ui/button.tsxpackages/ui/src/components/button.tsxapps/dashboard/src/@/components/ui/button.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/playground-web/tailwind.config.tsapps/dashboard/tailwind.config.jspackages/ui/src/index.tspackages/ui/src/lib/utils.tsapps/playground-web/src/components/ui/button.tsxpackages/ui/src/components/button.tsxapps/dashboard/src/@/components/ui/button.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
UseNavLinkfor internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()from@/lib/utilsfor conditional class logic
Use design system tokens (e.g.,bg-card,border-border,text-muted-foreground)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader – never embed tokens in URLs
Return typed results (e.g.,Project[],User[]) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysfor React Query cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components
Files:
apps/playground-web/tailwind.config.tsapps/playground-web/src/components/ui/button.tsxapps/dashboard/src/@/components/ui/button.tsx
🧠 Learnings (16)
📓 Common learnings
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
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"`.
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.
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 Tailwind CSS only – no inline styles or CSS modules
📚 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 Tailwind CSS only – no inline styles or CSS modules
Applied to files:
apps/playground-web/tailwind.config.tsapps/dashboard/tailwind.config.js
📚 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/playground-web/tailwind.config.tsapps/dashboard/tailwind.config.jsapps/dashboard/package.jsonpackages/ui/src/index.tsapps/playground-web/src/components/ui/button.tsxpackages/ui/package.jsonapps/dashboard/src/@/components/ui/button.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} : Tailwind CSS is the styling system – avoid inline styles or CSS modules.
Applied to files:
apps/playground-web/tailwind.config.tsapps/dashboard/tailwind.config.js
📚 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} : Never hard-code colors – always go through Tailwind variables.
Applied to files:
apps/dashboard/tailwind.config.js
📚 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/tailwind.config.jspackages/ui/src/index.tspackages/ui/src/lib/utils.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} : Always import from the central UI library under `@/components/ui/*` – e.g. `import { Button } from "@/components/ui/button"`.
Applied to files:
apps/dashboard/tailwind.config.jspackages/ui/src/index.tsapps/playground-web/src/components/ui/button.tsxapps/dashboard/src/@/components/ui/button.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/tailwind.config.js
📚 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/**/api/**/*.{ts,tsx} : Prefix files with `import "server-only";` so they never end up in the client bundle.
Applied to files:
apps/dashboard/tailwind.config.js
📚 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/**/index.ts : Group related components in their own folder and expose a single barrel `index.ts` where necessary.
Applied to files:
apps/dashboard/tailwind.config.js
📚 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/tailwind.config.js
📚 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/exports/react.native.ts : React Native specific exports are in `src/exports/react.native.ts`
Applied to files:
packages/ui/src/index.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} : Combine class names via `cn`, expose `className` prop if useful.
Applied to files:
packages/ui/src/index.tspackages/ui/src/lib/utils.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 apps/{dashboard,playground-web}/**/*.{ts,tsx} : Use `cn()` from `@/lib/utils` for conditional class logic
Applied to files:
packages/ui/src/index.tspackages/ui/src/lib/utils.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} : Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Applied to files:
packages/ui/src/index.tsapps/playground-web/src/components/ui/button.tsxapps/dashboard/src/@/components/ui/button.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/playground-web/src/components/ui/button.tsxapps/dashboard/src/@/components/ui/button.tsx
🪛 GitHub Actions: CI
apps/dashboard/package.json
[error] 1-1: dependencies should be ordered alphabetically. unordered-dependencies
apps/playground-web/package.json
[error] 1-1: dependencies should be ordered alphabetically. unordered-dependencies
🔇 Additional comments (8)
apps/playground-web/tailwind.config.ts (1)
5-5: Including the UI package in Tailwind content is correct.This ensures classes used inside the shared UI components are picked up during compilation for playground-web.
apps/dashboard/tailwind.config.js (1)
5-5: Good add: scanning the shared UI package for Tailwind classes.This ensures dashboard picks up classes used by the shared components.
packages/ui/src/index.ts (1)
1-6: Public API surface looks clean and minimal.Type-only export for ButtonProps, named exports for Button, buttonVariants, and cn are appropriate for tree-shaking and DX.
apps/playground-web/src/components/ui/button.tsx (2)
1-2: Re-export façade looks good.Pass-through to the shared UI package keeps app imports stable and centralizes the implementation.
1-2: No changes needed: direct imports in UI wrapper modules are intentionalThe only occurrences of
from "@workspace/ui"are in each app’s local UI wrapper files, which are meant to re-export the shared primitives:
- apps/dashboard/src/@/components/ui/button.tsx
- apps/playground-web/src/components/ui/button.tsx
All other app code correctly imports UI components via
@/components/ui/*. You can ignore the earlier suggestion.Likely an incorrect or invalid review comment.
apps/dashboard/src/@/components/ui/button.tsx (2)
1-2: Re-export façade looks good.Keeps dashboard imports stable while delegating implementation to the shared UI lib.
1-2: No direct @workspace/ui imports outside the UI wrapperThe only occurrences of direct imports from
@workspace/uiare in your dashboard’s central UI façade (apps/dashboard/src/@/components/ui/button.tsx), which is the intended pattern for re-exporting shared primitives. No other files import@workspace/uidirectly—all other components should continue to import from@/components/ui/*.• apps/dashboard/src/@/components/ui/button.tsx: intentional re-exports of
ButtonandButtonPropsfrom@workspace/uipackages/ui/src/components/button.tsx (1)
68-71: Critical: className is being dropped by passing it into cva (buttonVariants); consumer styles won’t applycva only accepts defined variant keys;
classNameis ignored and never merged. ExternalclassNameprops from consumers currently don’t make it into the DOM.Apply this diff to merge
classNameoutside ofbuttonVariants:- className={cn( - buttonVariants({ className, size, variant }), - disabledClass, - )} + className={cn( + buttonVariants({ size, variant }), + disabledClass, + className, + )}⛔ Skipped due to learnings
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 overridesLearnt 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.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.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.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 logicLearnt 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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🔭 Outside diff range comments (1)
apps/playground-web/package.json (1)
1-77: Add Next.jstranspilePackagesfor the UI workspace packageThe Next.js config for playground-web is missing the
transpilePackagessetting, so the TypeScript sources in@workspace/uiwon’t be compiled. Updateapps/playground-web/next.config.mjsto include it:// apps/playground-web/next.config.mjs -import { withContentlayer } from 'next-contentlayer' - -export default withContentlayer({ +import { withContentlayer } from 'next-contentlayer' + +export default withContentlayer({ // existing config… + // Ensure TS sources from @workspace/ui are transpiled + transpilePackages: ['@workspace/ui'], })Tailwind’s content scan already includes
../../packages/ui/src/**/*.{ts,tsx}, so no changes are needed there.
♻️ Duplicate comments (1)
packages/ui/src/components/button.tsx (1)
20-33: Consider preserving original styling for consistency.The shared UI library's button variants differ from the original
playground-webimplementation in styling choices that may cause visual inconsistencies when apps adopt the shared implementation. Consider either preserving the original styling or documenting these intentional design changes.
🧹 Nitpick comments (2)
packages/ui/src/lib/utils.ts (1)
4-6: Add explicit return type to align with TS guidelines.Explicit return type improves clarity and adheres to the repo’s TS rules.
-export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)); -} +export function cn(...inputs: ClassValue[]): string { + return twMerge(clsx(inputs)); +}packages/ui/package.json (1)
1-29: Consider future-proofing package entry and build for potential publication.Current setup points main/types/exports to TS sources. That’s fine for private workspaces if apps transpile the package (ensure transpilePackages). If you plan to publish or consume outside Next, consider:
- Emitting JS and d.ts (tsup/rollup), and pointing exports to dist.
- Adding "sideEffects": false for better tree-shaking.
- Keeping only "exports" and removing "main"/"types" if you rely solely on exports map.
Example minimal adjustments (optional, if/when you add a build step):
"name": "@workspace/ui", "version": "0.0.1", "private": true, - "main": "./src/index.ts", - "types": "./src/index.ts", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "sideEffects": false, "exports": { ".": { - "types": "./src/index.ts", - "import": "./src/index.ts" + "types": "./dist/index.d.ts", + "import": "./dist/index.js" } },If you’d like, I can sketch a tsup config and scripts for a tiny build pipeline.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (11)
apps/dashboard/package.json(1 hunks)apps/dashboard/src/@/components/ui/button.tsx(1 hunks)apps/dashboard/tailwind.config.js(1 hunks)apps/playground-web/package.json(1 hunks)apps/playground-web/src/components/ui/button.tsx(1 hunks)apps/playground-web/tailwind.config.ts(1 hunks)packages/ui/package.json(1 hunks)packages/ui/src/components/button.tsx(1 hunks)packages/ui/src/index.ts(1 hunks)packages/ui/src/lib/utils.ts(1 hunks)packages/ui/tsconfig.json(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{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/tailwind.config.jspackages/ui/src/lib/utils.tsapps/playground-web/tailwind.config.tspackages/ui/src/index.tspackages/ui/src/components/button.tsxapps/dashboard/src/@/components/ui/button.tsxapps/playground-web/src/components/ui/button.tsx
**/*.{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@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes
Avoidanyandunknownunless 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:
packages/ui/src/lib/utils.tsapps/playground-web/tailwind.config.tspackages/ui/src/index.tspackages/ui/src/components/button.tsxapps/dashboard/src/@/components/ui/button.tsxapps/playground-web/src/components/ui/button.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
UseNavLinkfor internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()from@/lib/utilsfor conditional class logic
Use design system tokens (e.g.,bg-card,border-border,text-muted-foreground)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader – never embed tokens in URLs
Return typed results (e.g.,Project[],User[]) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysfor React Query cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components
Files:
apps/playground-web/tailwind.config.tsapps/dashboard/src/@/components/ui/button.tsxapps/playground-web/src/components/ui/button.tsx
🧠 Learnings (12)
📓 Common learnings
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
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"`.
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.
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 Tailwind CSS only – no inline styles or CSS modules
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`.
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';`
📚 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 Tailwind CSS only – no inline styles or CSS modules
Applied to files:
apps/dashboard/tailwind.config.jsapps/playground-web/tailwind.config.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} : Tailwind CSS is the styling system – avoid inline styles or CSS modules.
Applied to files:
apps/dashboard/tailwind.config.jsapps/playground-web/tailwind.config.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 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/tailwind.config.jsapps/playground-web/package.jsonapps/playground-web/tailwind.config.tspackages/ui/src/index.tsapps/dashboard/src/@/components/ui/button.tsxpackages/ui/package.jsonapps/playground-web/src/components/ui/button.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} : Never hard-code colors – always go through Tailwind variables.
Applied to files:
apps/dashboard/tailwind.config.js
📚 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:
packages/ui/src/lib/utils.tspackages/ui/src/index.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} : Combine class names via `cn`, expose `className` prop if useful.
Applied to files:
packages/ui/src/lib/utils.tspackages/ui/src/index.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 apps/{dashboard,playground-web}/**/*.{ts,tsx} : Use `cn()` from `@/lib/utils` for conditional class logic
Applied to files:
packages/ui/src/lib/utils.tspackages/ui/src/index.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} : Always import from the central UI library under `@/components/ui/*` – e.g. `import { Button } from "@/components/ui/button"`.
Applied to files:
packages/ui/src/index.tsapps/dashboard/src/@/components/ui/button.tsxapps/playground-web/src/components/ui/button.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 src/exports/react.native.ts : React Native specific exports are in `src/exports/react.native.ts`
Applied to files:
packages/ui/src/index.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} : Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Applied to files:
packages/ui/src/index.tsapps/dashboard/src/@/components/ui/button.tsxapps/playground-web/src/components/ui/button.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:
packages/ui/src/components/button.tsxapps/dashboard/src/@/components/ui/button.tsx
🧬 Code Graph Analysis (2)
packages/ui/src/lib/utils.ts (1)
packages/ui/src/index.ts (1)
cn(6-6)
packages/ui/src/components/button.tsx (1)
packages/ui/src/lib/utils.ts (1)
cn(4-6)
🪛 GitHub Actions: CI
apps/playground-web/package.json
[error] 1-1: pnpm lint: dependencies should be ordered alphabetically. (unordered-dependencies)
apps/dashboard/package.json
[error] 1-1: pnpm lint: dependencies should be ordered alphabetically. (unordered-dependencies)
🔇 Additional comments (13)
apps/dashboard/tailwind.config.js (1)
5-5: LGTM: Tailwind content now scans shared UI package.The added glob will ensure classes used in the shared UI are included in the dashboard build.
apps/playground-web/tailwind.config.ts (1)
5-5: LGTM: Tailwind content extended to include UI package.This aligns the playground app with the shared UI consumption.
packages/ui/src/lib/utils.ts (1)
1-6: Import usage ofcnin apps is correct
A search forimport { cn } from "@workspace/ui"underappsreturned no matches. All apps continue to importcnfrom@/lib/utilsas intended.packages/ui/src/index.ts (1)
1-6: LGTM: clean public surface for UI primitives.Type-only re-export and minimal surface are solid. This aligns with centralizing UI primitives.
apps/dashboard/src/@/components/ui/button.tsx (1)
1-2: LGTM: dashboard now sources Button from the shared UI package.This aligns with the consolidation goal and our UI primitive reuse guidance.
apps/playground-web/src/components/ui/button.tsx (1)
1-2: LGTM: playground button now proxies the shared UI component.Consistent with the central UI package adoption.
packages/ui/src/components/button.tsx (7)
1-4: LGTM! Clean imports and proper dependency setup.The imports are well-structured with external libraries first, React second, and internal utilities last. The import path
@/lib/utilscorrectly uses the path alias configured in the TypeScript config.
6-36: Well-structured button variants with comprehensive styling.The
cvaimplementation provides a solid foundation with appropriate base styles and comprehensive variant coverage. The focus management, accessibility features, and transition effects are well-implemented.
38-42: Excellent interface design with proper type composition.The
ButtonPropsinterface correctly extends both React's native button attributes and the variant props, with the optionalasChildprop for Radix Slot integration. This follows TypeScript best practices for component prop types.
44-79: Robust component implementation with excellent accessibility handling.The Button component implementation is exemplary:
- Properly handles both native button and Slot rendering via
asChild- Comprehensive disabled state management for both native and custom elements
- Correct accessibility attributes with
aria-disabled- Proper ref forwarding
- Default button type handling for native elements
- Clean class name composition using the
cnutilityThe component follows React best practices and provides excellent developer experience.
48-54: Excellent disabled state handling for accessibility.The detailed comment and implementation for handling disabled state across different element types demonstrates thorough consideration of accessibility requirements. The approach of using
pointer-events-none opacity-50witharia-disabledfor non-button elements is exactly right.
56-63: Smart conditional prop handling for type safety.The
btnOnlyPropslogic correctly ensures that button-specific properties (liketype) are only applied to actual button elements, with a sensible default of"button"to prevent form submission issues.
80-82: Proper component naming and exports.Setting the
displayNameaids in debugging, and the clean export structure makes the component and its variants easily consumable by other parts of the application.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🔭 Outside diff range comments (1)
apps/dashboard/package.json (1)
27-32: Fix dependency order to satisfy CI (unordered-dependencies).The newly added dependency "@workspace/ui" is out of alphabetical order, which is causing the CI failure. Place it after "@vercel/og".
Apply this diff to re-order the entry:
@@ - "@thirdweb-dev/service-utils": "workspace:*", - "@workspace/ui": "workspace:*", - "@thirdweb-dev/vault-sdk": "workspace:*", + "@thirdweb-dev/service-utils": "workspace:*", + "@thirdweb-dev/vault-sdk": "workspace:*", "@vercel/functions": "2.2.2", "@vercel/og": "^0.6.8", + "@workspace/ui": "workspace:*",
♻️ Duplicate comments (1)
packages/ui/src/components/button.tsx (1)
6-36: Button variant styling looks good overall, but be aware of intentional design changes.The
buttonVariantsimplementation is well-structured usingcvawith comprehensive size and variant options. The base classes provide good accessibility features with focus-visible states and proper disabled handling.Note: This implementation intentionally differs from the original
playground-webbutton in two ways:
- Removes
font-semiboldfrom several variants- Changes the
upsellvariant from a purple-to-pink gradient to solid greenThese changes will affect visual consistency when apps migrate to this shared library, so ensure this is intentional.
🧹 Nitpick comments (7)
packages/ui/src/lib/utils.ts (1)
4-6: Add explicit return type tocnfor API clarity and consistencyOur TS guidelines call for explicit return types.
twMergereturns a string, so we can lock this down for better DX and to prevent accidental regressions.-export function cn(...inputs: ClassValue[]) { +export function cn(...inputs: ClassValue[]): string { return twMerge(clsx(inputs)); }apps/playground-web/tailwind.config.ts (1)
5-5: Tailwind content path updated correctly; consider making it path-resilientThe additional glob ensures UI package classes are scanned. To avoid brittle relative paths (repo reorgs, symlink variance), consider resolving the path via Node’s path API.
- content: ["./src/**/*.{ts,tsx}", "../../packages/ui/src/**/*.{ts,tsx}"], + // Optionally make the UI path resolution robust to directory moves + // at the top: import { join } from "node:path"; + content: ["./src/**/*.{ts,tsx}", join(__dirname, "../../packages/ui/src/**/*.{ts,tsx}")],If you prefer CommonJS in config files, you can instead:
-const { fontFamily } = require("tailwindcss/defaultTheme"); +const { fontFamily } = require("tailwindcss/defaultTheme"); +const { join } = require("node:path"); module.exports = { - content: ["./src/**/*.{ts,tsx}", "../../packages/ui/src/**/*.{ts,tsx}"], + content: ["./src/**/*.{ts,tsx}", join(__dirname, "../../packages/ui/src/**/*.{ts,tsx}")],packages/ui/tsconfig.json (2)
17-21: Remove Next.js TS plugin from a library tsconfigThis package isn’t a Next.js app. Keeping the config minimal avoids unintended type plugin side-effects for consumers.
- "plugins": [ - { - "name": "next" - } - ],
5-5: Tighten TS config:allowJsis unnecessary for a TS-only libraryIf this package only ships TS/TSX, disabling JS keeps the surface stricter and catches accidental JS files.
- "allowJs": true, + "allowJs": false,packages/ui/package.json (2)
1-29: Mark package as side-effect free to improve tree-shakingUI components/utilities here shouldn’t have side-effects. Adding this helps bundlers drop unused exports reliably.
{ "name": "@workspace/ui", "version": "0.0.1", "private": true, + "sideEffects": false, "main": "./src/index.ts", "types": "./src/index.ts", "exports": { ".": { "types": "./src/index.ts", "import": "./src/index.ts" } },
5-12: TS source entry: ensure consumer apps transpile thisPointing main/types to TS is fine for private workspaces, but requires consumers to transpile. Confirm your Next apps are configured (transpilePackages or equivalent) or consider adding a build step with dist outputs later if you plan to publish.
I can generate a minimal build config (tsup/rollup) and update fields to dist if you want to future-proof this package. Want me to open a follow-up PR?
packages/ui/src/index.ts (1)
1-6: Condense exports for clarity.Minor cleanup: combine type and value exports from the same module into a single line.
-// button -export type { ButtonProps } from "./components/button"; -export { Button, buttonVariants } from "./components/button"; - -// utils -export { cn } from "./lib/utils"; +// button +export { type ButtonProps, Button, buttonVariants } from "./components/button"; + +// utils +export { cn } from "./lib/utils";
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (11)
apps/dashboard/package.json(1 hunks)apps/dashboard/src/@/components/ui/button.tsx(1 hunks)apps/dashboard/tailwind.config.js(1 hunks)apps/playground-web/package.json(1 hunks)apps/playground-web/src/components/ui/button.tsx(1 hunks)apps/playground-web/tailwind.config.ts(1 hunks)packages/ui/package.json(1 hunks)packages/ui/src/components/button.tsx(1 hunks)packages/ui/src/index.ts(1 hunks)packages/ui/src/lib/utils.ts(1 hunks)packages/ui/tsconfig.json(1 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@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes
Avoidanyandunknownunless 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/playground-web/tailwind.config.tspackages/ui/src/index.tspackages/ui/src/components/button.tsxpackages/ui/src/lib/utils.tsapps/dashboard/src/@/components/ui/button.tsxapps/playground-web/src/components/ui/button.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/playground-web/tailwind.config.tsapps/dashboard/tailwind.config.jspackages/ui/src/index.tspackages/ui/src/components/button.tsxpackages/ui/src/lib/utils.tsapps/dashboard/src/@/components/ui/button.tsxapps/playground-web/src/components/ui/button.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
UseNavLinkfor internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()from@/lib/utilsfor conditional class logic
Use design system tokens (e.g.,bg-card,border-border,text-muted-foreground)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader – never embed tokens in URLs
Return typed results (e.g.,Project[],User[]) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysfor React Query cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components
Files:
apps/playground-web/tailwind.config.tsapps/dashboard/src/@/components/ui/button.tsxapps/playground-web/src/components/ui/button.tsx
🧠 Learnings (14)
📓 Common learnings
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
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"`.
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 Tailwind CSS only – no inline styles or CSS modules
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.
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`.
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} : Tailwind CSS is the styling system – avoid inline styles or CSS modules.
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';`
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
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.
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.
📚 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 Tailwind CSS only – no inline styles or CSS modules
Applied to files:
apps/playground-web/tailwind.config.tsapps/dashboard/tailwind.config.js
📚 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/playground-web/tailwind.config.tsapps/dashboard/tailwind.config.jsapps/dashboard/package.jsonpackages/ui/src/index.tsapps/dashboard/src/@/components/ui/button.tsxapps/playground-web/src/components/ui/button.tsxpackages/ui/package.json
📚 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} : Tailwind CSS is the styling system – avoid inline styles or CSS modules.
Applied to files:
apps/playground-web/tailwind.config.tsapps/dashboard/tailwind.config.js
📚 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} : Never hard-code colors – always go through Tailwind variables.
Applied to files:
apps/dashboard/tailwind.config.js
📚 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:
packages/ui/src/index.tsapps/dashboard/src/@/components/ui/button.tsxapps/playground-web/src/components/ui/button.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:
packages/ui/src/index.tspackages/ui/src/lib/utils.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} : Combine class names via `cn`, expose `className` prop if useful.
Applied to files:
packages/ui/src/index.tspackages/ui/src/lib/utils.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 apps/{dashboard,playground-web}/**/*.{ts,tsx} : Use `cn()` from `@/lib/utils` for conditional class logic
Applied to files:
packages/ui/src/index.tspackages/ui/src/lib/utils.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} : Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Applied to files:
packages/ui/src/index.tsapps/dashboard/src/@/components/ui/button.tsxapps/playground-web/src/components/ui/button.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:
packages/ui/src/components/button.tsxapps/dashboard/src/@/components/ui/button.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/**/index.ts : Group related components in their own folder and expose a single barrel `index.ts` where necessary.
Applied to files:
apps/dashboard/src/@/components/ui/button.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/ui/button.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/*.{tsx,jsx} : Place the file close to its feature: `feature/components/MyComponent.tsx`.
Applied to files:
apps/dashboard/src/@/components/ui/button.tsx
🪛 GitHub Actions: CI
apps/playground-web/package.json
[error] 1-1: Unordered dependencies in './apps/playground-web/package.json' (unordered-dependencies).
apps/dashboard/package.json
[error] 1-1: Unordered dependencies in './apps/dashboard/package.json' (unordered-dependencies).
🔇 Additional comments (11)
packages/ui/src/lib/utils.ts (1)
1-2: LGTM: idiomatic clsx + tailwind-merge comboImports and usage are standard and correct for a Tailwind-aware className utility.
apps/dashboard/tailwind.config.js (1)
5-5: Include UI package in Tailwind content globs – LGTM.This ensures classes used in the shared UI package are picked up by JIT. Path looks correct from apps/dashboard to packages/ui/src.
packages/ui/src/index.ts (1)
1-6: Add’use client’directive to Button componentThe
packages/ui/src/components/button.tsxfile is missing the required Client Component directive. SinceButtonattaches event handlers, prepend the file with:+ 'use client'; import React from "react"; // rest of imports…This ensures
Buttonis treated as a React Client Component.⛔ Skipped due to learnings
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.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';`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.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).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"`.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 appsLearnt 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.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.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`.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/*.{tsx,jsx} : Name files after the component in PascalCase; append `.client.tsx` when interactive.apps/dashboard/src/@/components/ui/button.tsx (1)
1-2: Pass-through re-exports to shared UI – LGTM.Keeps app imports stable (
@/components/ui/button) while centralizing implementation in the UI package.apps/playground-web/src/components/ui/button.tsx (1)
1-2: Pass-through re-exports to shared UI – LGTM.Matches the dashboard approach for consistency across apps.
packages/ui/src/components/button.tsx (6)
1-4: LGTM! Clean imports with appropriate dependencies.The imports are well-structured and align with the modern UI library pattern using Radix UI, class-variance-authority for variants, and a utility function for class merging.
38-42: Well-designed interface with proper type composition.The
ButtonPropsinterface correctly extends both native button attributes and variant props, with the optionalasChildprop for Radix Slot compatibility. This follows modern React component patterns effectively.
44-54: Excellent handling of the asChild pattern with proper disabled state management.The component correctly implements the Radix Slot pattern and handles the complex case where disabled state needs to work for both native buttons and non-button elements rendered via
asChild. The comment clearly explains the reasoning behind thedisabledClassapproach.
56-63: Smart type-specific prop handling.The
btnOnlyPropslogic correctly applies thetypeattribute only to actual button elements, with a sensible default of "button". The conditional typing and spreading approach is clean and type-safe.
65-79: Robust component rendering with comprehensive prop handling.The render logic properly handles:
- Accessibility with
aria-disabled- Class merging with variant styles and disabled state
- Conditional prop spreading for button-specific attributes
- Proper ref forwarding
The implementation is thorough and follows React best practices.
80-82: Proper component setup and exports.The display name is set correctly for debugging, and the exports include both the component and variants function, providing a complete API surface for consumers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
♻️ Duplicate comments (1)
packages/ui/src/components/button.tsx (1)
21-33: Align button variant styles with prior implementation (font weight and upsell gradient)This has been flagged previously: variants dropped the bold weight and the upsell style changed from a purple-pink gradient to solid green. Unless this is an intentional design update, keep parity to avoid regressions in playground-web.
Apply this diff if parity is desired:
variant: { default: "bg-foreground text-background hover:bg-foreground/90", destructive: - "bg-destructive hover:bg-destructive/90 text-destructive-foreground ", + "bg-destructive hover:bg-destructive/90 text-destructive-foreground font-semibold", ghost: "hover:bg-accent hover:text-accent-foreground", - link: "underline-offset-4 hover:underline", + link: "underline-offset-4 hover:underline font-semibold", outline: - "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground", - primary: "bg-primary hover:bg-primary/90 text-primary-foreground ", + "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground font-semibold", + primary: "bg-primary hover:bg-primary/90 text-primary-foreground font-semibold", secondary: - "bg-secondary hover:bg-secondary/80 text-secondary-foreground ", + "bg-secondary hover:bg-secondary/80 text-secondary-foreground font-semibold", upsell: - "bg-green-600 text-white hover:bg-green-700 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5 transition-all duration-200", + "bg-gradient-to-r from-purple-500 to-pink-500 text-white hover:from-purple-600 hover:to-pink-600 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5 transition-all duration-200", },If the change is intentional, consider documenting it in the UI package README and a migration note for consuming apps.
🧹 Nitpick comments (5)
packages/ui/package.json (1)
20-23: Consider more flexible React version constraints.The peer dependencies specify React 19.0.0, but using more flexible version ranges like
"^18.0.0 || ^19.0.0"would improve compatibility across different projects that might not have upgraded to React 19 yet."peerDependencies": { - "react": "^19.0.0", - "react-dom": "^19.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" },packages/ui/src/components/button.tsx (4)
38-42: Prefer a type alias over interface for props to match guidelinesPer the repo’s TS guidelines, use a type alias for structural props.
Apply this diff:
-export interface ButtonProps - extends React.ButtonHTMLAttributes<HTMLButtonElement>, - VariantProps<typeof buttonVariants> { - asChild?: boolean; -} +export type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & + VariantProps<typeof buttonVariants> & { + asChild?: boolean; + };
23-30: Remove trailing whitespace in class stringsMinor cleanup for consistency.
Apply this diff:
- "bg-destructive hover:bg-destructive/90 text-destructive-foreground ", + "bg-destructive hover:bg-destructive/90 text-destructive-foreground", - primary: "bg-primary hover:bg-primary/90 text-primary-foreground ", + primary: "bg-primary hover:bg-primary/90 text-primary-foreground", - secondary: - "bg-secondary hover:bg-secondary/80 text-secondary-foreground ", + secondary: + "bg-secondary hover:bg-secondary/80 text-secondary-foreground",
66-71: Optional: passclassNameoutside CVA for clarityBoth patterns work, but it’s more explicit to keep variant selection inside CVA and merge external classes with
cnseparately. Current code is fine; sharing an alternative for readability:Apply this diff:
- className={cn( - buttonVariants({ className, size, variant }), - disabledClass, - )} + className={cn(buttonVariants({ size, variant }), className, disabledClass)}
44-52: Optional: polymorphic typing forasChildWhen
asChildis true, the ref and props may not matchHTMLButtonElement. Consider a polymorphic prop pattern (e.g.,as?: ElementType) or overloads to improve type-safety. Not blocking.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (11)
apps/dashboard/package.json(1 hunks)apps/dashboard/src/@/components/ui/button.tsx(1 hunks)apps/dashboard/tailwind.config.js(1 hunks)apps/playground-web/package.json(1 hunks)apps/playground-web/src/components/ui/button.tsx(1 hunks)apps/playground-web/tailwind.config.ts(1 hunks)packages/ui/package.json(1 hunks)packages/ui/src/components/button.tsx(1 hunks)packages/ui/src/index.ts(1 hunks)packages/ui/src/lib/utils.ts(1 hunks)packages/ui/tsconfig.json(1 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@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes
Avoidanyandunknownunless 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/playground-web/tailwind.config.tspackages/ui/src/index.tspackages/ui/src/components/button.tsxapps/playground-web/src/components/ui/button.tsxapps/dashboard/src/@/components/ui/button.tsxpackages/ui/src/lib/utils.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
apps/playground-web/tailwind.config.tsapps/dashboard/tailwind.config.jspackages/ui/src/index.tspackages/ui/src/components/button.tsxapps/playground-web/src/components/ui/button.tsxapps/dashboard/src/@/components/ui/button.tsxpackages/ui/src/lib/utils.ts
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
UseNavLinkfor internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()from@/lib/utilsfor conditional class logic
Use design system tokens (e.g.,bg-card,border-border,text-muted-foreground)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader – never embed tokens in URLs
Return typed results (e.g.,Project[],User[]) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysfor React Query cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components
Files:
apps/playground-web/tailwind.config.tsapps/playground-web/src/components/ui/button.tsxapps/dashboard/src/@/components/ui/button.tsx
🧠 Learnings (15)
📓 Common learnings
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
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"`.
📚 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 Tailwind CSS only – no inline styles or CSS modules
Applied to files:
apps/playground-web/tailwind.config.tsapps/dashboard/tailwind.config.js
📚 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/playground-web/tailwind.config.tsapps/dashboard/tailwind.config.jspackages/ui/src/index.tsapps/dashboard/package.jsonpackages/ui/package.jsonapps/playground-web/src/components/ui/button.tsxapps/dashboard/src/@/components/ui/button.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} : Tailwind CSS is the styling system – avoid inline styles or CSS modules.
Applied to files:
apps/playground-web/tailwind.config.tsapps/dashboard/tailwind.config.jsapps/dashboard/src/@/components/ui/button.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} : Never hard-code colors – always go through Tailwind variables.
Applied to files:
apps/dashboard/tailwind.config.js
📚 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:
packages/ui/src/index.tsapps/playground-web/src/components/ui/button.tsxapps/dashboard/src/@/components/ui/button.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:
packages/ui/src/index.tspackages/ui/src/lib/utils.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} : Combine class names via `cn`, expose `className` prop if useful.
Applied to files:
packages/ui/src/index.tspackages/ui/src/lib/utils.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 apps/{dashboard,playground-web}/**/*.{ts,tsx} : Use `cn()` from `@/lib/utils` for conditional class logic
Applied to files:
packages/ui/src/index.tspackages/ui/src/lib/utils.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} : Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Applied to files:
packages/ui/src/index.tsapps/playground-web/src/components/ui/button.tsxapps/dashboard/src/@/components/ui/button.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:
packages/ui/src/components/button.tsxapps/dashboard/src/@/components/ui/button.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/*.{tsx,jsx} : Place the file close to its feature: `feature/components/MyComponent.tsx`.
Applied to files:
apps/dashboard/src/@/components/ui/button.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/**/index.ts : Group related components in their own folder and expose a single barrel `index.ts` where necessary.
Applied to files:
apps/dashboard/src/@/components/ui/button.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/ui/button.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/ui/button.tsx
🧬 Code Graph Analysis (1)
packages/ui/src/lib/utils.ts (1)
packages/ui/src/index.ts (1)
cn(6-6)
🪛 GitHub Actions: CI
apps/dashboard/package.json
[error] 1-1: Command: pnpm lint. ESLint: dependencies should be ordered alphabetically (unordered-dependencies).
apps/playground-web/package.json
[error] 1-1: Command: pnpm lint. ESLint: dependencies should be ordered alphabetically (unordered-dependencies).
🔇 Additional comments (5)
apps/playground-web/tailwind.config.ts (1)
5-5: LGTM! Proper UI package integration.The content array is correctly updated to include TypeScript/TSX files from the shared UI package, ensuring Tailwind CSS can process classes used by the UI components.
packages/ui/src/lib/utils.ts (1)
4-6: LGTM! Standard class composition utility.The
cnfunction correctly implements the standard pattern for combining and merging Tailwind classes usingclsxandtailwind-merge. This aligns with the coding guidelines for usingcn()for conditional class logic.apps/dashboard/tailwind.config.js (1)
5-5: Including the shared UI package in Tailwind content globs looks correctThis ensures classes used inside packages/ui are picked up in the Dashboard build.
packages/ui/src/index.ts (2)
2-6: Good, minimal public surface re-exportsCleanly re-exporting Button, buttonVariants, ButtonProps, and cn from the root keeps the consumer API simple and tree-shakeable.
1-6: Add Next.js transpilePackages for @workspace/ui to all appsThe UI package ships TypeScript sources, so each Next.js app must transpile it. None of your
next.config.*files currently includetranspilePackagesor reference@workspace/ui. Without this, builds may fail or behave inconsistently.Files needing an update:
- apps/dashboard/next.config.ts
- apps/nebula/next.config.ts
- apps/playground-web/next.config.mjs
- apps/portal/next.config.mjs
- apps/wallet-ui/next.config.mjs
Suggested change (add inside your existing
nextConfigobject):/** @type {import('next').NextConfig} */ const nextConfig = { + transpilePackages: ["@workspace/ui"], // …other config }; export default nextConfig;⛔ Skipped due to learnings
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 appsLearnt 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 Tailwind CSS only – no inline styles or CSS modulesLearnt 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';`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} : Server Components (Node edge): Start files with `import "server-only";`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"`.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} : Wrap client-side data fetching calls in React Query (`tanstack/react-query`)
dc72a4a to
e44b2a0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (1)
apps/dashboard/package.json (1)
31-31: Dependency ordering fix looks correctPlacing "@workspace/ui" after "@vercel/og" aligns with the linter’s alphabetical ordering requirement noted earlier. This should unblock the unordered-dependencies error.
If convenient, re-run the dashboard lint locally to confirm the fix:
- From repo root: pnpm -w --filter ./apps/dashboard lint
🧹 Nitpick comments (9)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/_common/chain-overview.tsx (1)
5-8: Nits: add explicit return type and props alias; prefer nullish coalescing over logical OR
- Add a props type alias and explicit
JSX.Elementreturn type per repo guidelines.- Use
??instead of||so empty strings aren’t unintentionally overridden.import { ChainIconClient } from "@/icons/ChainIcon"; +type ChainOverviewProps = { + chainId: string; + client: ThirdwebClient; +}; + -export function ChainOverview(props: { - chainId: string; - client: ThirdwebClient; -}) { +export function ChainOverview(props: ChainOverviewProps): JSX.Element { const { idToChain } = useAllChainsData(); const chainMetadata = idToChain.get(Number(props.chainId)); return ( <div className="flex items-center gap-2"> <ChainIconClient className="size-3.5" client={props.client} - src={chainMetadata?.icon?.url || ""} + src={chainMetadata?.icon?.url ?? ""} /> <p className="text-foreground text-sm"> - {chainMetadata?.name || `Chain ${props.chainId}`} + {chainMetadata?.name ?? `Chain ${props.chainId}`} </p> </div> ); }Also applies to: 17-20
apps/dashboard/src/app/pay/layout.tsx (1)
1-1: (Nit) Mark server components explicitlyAdd the server-only directive to ensure this layout is never bundled for the client.
Apply this diff:
+import "server-only"; +// global styles are imported at the root layoutapps/portal/package.json (1)
2-44: Classify @workspace/ui as a runtime dependency, not a devDependencyThe app imports components and CSS from @workspace/ui; that’s part of the build/runtime graph, so it should live under dependencies (to avoid surprises in prod installs that omit devDependencies).
Apply this diff:
@@ "dependencies": { @@ - "typedoc-better-json": "0.9.4" + "typedoc-better-json": "0.9.4", + "@workspace/ui": "workspace:*" }, @@ "devDependencies": { @@ - "@workspace/ui": "workspace:*",Also applies to: 45-71
packages/ui/tsconfig.json (1)
6-6: Tighten compiler settings: disable JS, set JSX runtime, and drop unused declaration flagsGiven this package is TS-only and doesn’t emit artifacts, these settings reduce noise and make intent explicit.
Apply this diff:
- "allowJs": true, + "allowJs": false, @@ - "declaration": true, - "declarationMap": true, + // noEmit is true; declarations won't be written anyway + "declaration": false, + "declarationMap": false, @@ - "jsx": "preserve", + "jsx": "react-jsx",Also applies to: 10-11, 21-21
packages/ui/tailwind.config.ts (1)
5-10: Centralize and export UI content globs for reuse in appsTo avoid brittle relative paths in consumers (e.g., ../../packages/ui/src/**) and keep purge content in sync across apps, consider exporting a reusable content helper from the UI package.
Apply this change in the UI package to export a content helper:
import type { Config } from "tailwindcss"; import { fontFamily } from "tailwindcss/defaultTheme"; import tailwindcssAnimate from "tailwindcss-animate"; +// Optional: export helper paths for consumers to include UI sources in their Tailwind content +export const uiContentGlobs = ["./src/**/*.{ts,tsx}"] as const; + const config: Config = { - content: [ - "./src/**/*.{ts,tsx}", - // Note: when importing this config in website project, - // add a relative path to the ui package here - ], + content: [...uiContentGlobs], darkMode: ["class"], plugins: [tailwindcssAnimate],Then in app configs (example), replace ad-hoc relative paths:
// apps/portal/tailwind.config.ts import tailwindConfig, { uiContentGlobs } from "@workspace/ui/tailwind.config"; const config: Config = { ...tailwindConfig, content: [ "./components/**/*.{ts,tsx}", "./app/**/*.{ts,tsx,mdx}", "./src/**/*.{ts,tsx,mdx}", // include UI content by resolving from the package root // when needed, resolve absolute path(s) here based on monorepo layout "../../packages/ui/src/**/*.{ts,tsx}", ], // ... }; export default config;apps/portal/tailwind.config.ts (2)
10-12: Resolve UI content path programmatically to avoid brittle relative pathsHard-coding "../../packages/ui/src/**" works in this monorepo, but using a resolved path tied to the package is more robust to refactors.
Example using ESM createRequire:
// at top of file import { createRequire } from "node:module"; import path from "node:path"; const require = createRequire(import.meta.url); const uiPkgRoot = path.dirname(require.resolve("@workspace/ui/package.json")); const uiContent = path.join(uiPkgRoot, "src/**/*.{ts,tsx}"); // then in content: content: [ "./components/**/*.{ts,tsx}", "./app/**/*.{ts,tsx,mdx}", "./src/**/*.{ts,tsx,mdx}", uiContent, ],
23-39: Nit: use numeric values for zIndexTailwind accepts both strings and numbers, but numeric values are a bit cleaner and consistent with Tailwind defaults.
- zIndex: { - // base - base: "0", - // - codeToken: "5", - codeTokenHighlight: "1", - // - copyCodeButton: "20", - dropdownMenu: "1200", - floatingButton: "1000", - menu: "1100", - modal: "1400", - modalOverlay: "1300", - stickyMobileSidebar: "500", - // - stickyTop: "1000", - }, + zIndex: { + // base + base: 0, + // + codeToken: 5, + codeTokenHighlight: 1, + // + copyCodeButton: 20, + dropdownMenu: 1200, + floatingButton: 1000, + menu: 1100, + modal: 1400, + modalOverlay: 1300, + stickyMobileSidebar: 500, + // + stickyTop: 1000, + },packages/ui/package.json (1)
5-15: Mark CSS as side-effectful to prevent tree-shaking from dropping stylesSince consumers import "@workspace/ui/global.css", add a sideEffects entry so bundlers don’t remove CSS-only imports.
{ "name": "@workspace/ui", "version": "0.0.1", "private": true, + "sideEffects": [ + "./src/global.css", + "*.css" + ], "exports": { "./global.css": "./src/global.css", "./postcss.config": "./postcss.config.mjs", "./tailwind.config": "./tailwind.config.ts", "./lib/*": "./src/lib/*.ts", "./hooks/*": [ "./src/hooks/*.ts", "./src/hooks/*.tsx" ], "./components/*": "./src/components/*.tsx" },apps/portal/src/components/ui/button.tsx (1)
2-3: Re-export pattern is clean; consider avoiding deep-import coupling if root exports existIf
@workspace/uiexposesButton,buttonVariants, andButtonPropsat its package root, prefer importing from the root to avoid coupling to internal paths and to simplify future refactors. If not, this is fine to keep as-is.Example (only if root exports exist):
-export type { ButtonProps } from "@workspace/ui/components/button"; -export { Button, buttonVariants } from "@workspace/ui/components/button"; +export type { ButtonProps } from "@workspace/ui"; +export { Button, buttonVariants } from "@workspace/ui";
📜 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.
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (45)
apps/dashboard/knip.json(1 hunks)apps/dashboard/next.config.ts(1 hunks)apps/dashboard/package.json(1 hunks)apps/dashboard/postcss.config.js(0 hunks)apps/dashboard/postcss.config.mjs(1 hunks)apps/dashboard/src/@/components/sponsored-transactions-table/SponsoredTransactionsTable.tsx(1 hunks)apps/dashboard/src/@/components/ui/button.tsx(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/components/types.ts(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/hooks.ts(2 hunks)apps/dashboard/src/app/(app)/layout.tsx(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/_common/chain-overview.tsx(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsx(1 hunks)apps/dashboard/src/app/bridge/layout.tsx(1 hunks)apps/dashboard/src/app/login/layout.tsx(1 hunks)apps/dashboard/src/app/pay/layout.tsx(1 hunks)apps/dashboard/tailwind.config.ts(1 hunks)apps/dashboard/tsconfig.json(2 hunks)apps/playground-web/knip.json(1 hunks)apps/playground-web/next.config.mjs(1 hunks)apps/playground-web/package.json(1 hunks)apps/playground-web/postcss.config.js(0 hunks)apps/playground-web/postcss.config.mjs(1 hunks)apps/playground-web/src/app/ai/api/chat.ts(1 hunks)apps/playground-web/src/app/ai/api/types.ts(0 hunks)apps/playground-web/src/app/ai/components/ChatPageContent.tsx(2 hunks)apps/playground-web/src/app/globals.css(0 hunks)apps/playground-web/src/app/layout.tsx(1 hunks)apps/playground-web/src/components/ui/button.tsx(1 hunks)apps/playground-web/tailwind.config.ts(1 hunks)apps/portal/next.config.mjs(1 hunks)apps/portal/package.json(1 hunks)apps/portal/src/app/globals.css(0 hunks)apps/portal/src/app/layout.tsx(1 hunks)apps/portal/src/components/ui/button.tsx(1 hunks)apps/portal/tailwind.config.ts(1 hunks)apps/wallet-ui/next.config.mjs(0 hunks)packages/thirdweb/src/exports/extensions/marketplace.ts(1 hunks)packages/thirdweb/src/exports/utils.ts(1 hunks)packages/ui/package.json(1 hunks)packages/ui/postcss.config.mjs(1 hunks)packages/ui/src/components/button.tsx(1 hunks)packages/ui/src/global.css(2 hunks)packages/ui/src/lib/utils.ts(1 hunks)packages/ui/tailwind.config.ts(2 hunks)packages/ui/tsconfig.json(1 hunks)
💤 Files with no reviewable changes (6)
- apps/wallet-ui/next.config.mjs
- apps/dashboard/postcss.config.js
- apps/playground-web/postcss.config.js
- apps/playground-web/src/app/globals.css
- apps/playground-web/src/app/ai/api/types.ts
- apps/portal/src/app/globals.css
✅ Files skipped from review due to trivial changes (1)
- apps/portal/src/app/layout.tsx
🚧 Files skipped from review as they are similar to previous changes (26)
- apps/playground-web/knip.json
- apps/playground-web/postcss.config.mjs
- apps/dashboard/src/@/components/sponsored-transactions-table/SponsoredTransactionsTable.tsx
- apps/dashboard/src/app/(app)/layout.tsx
- apps/playground-web/package.json
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsx
- packages/ui/postcss.config.mjs
- apps/dashboard/src/app/bridge/layout.tsx
- packages/thirdweb/src/exports/extensions/marketplace.ts
- packages/thirdweb/src/exports/utils.ts
- apps/playground-web/src/app/ai/components/ChatPageContent.tsx
- apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/components/types.ts
- apps/playground-web/src/app/layout.tsx
- apps/dashboard/postcss.config.mjs
- apps/dashboard/src/@/components/ui/button.tsx
- apps/dashboard/next.config.ts
- apps/playground-web/tailwind.config.ts
- apps/playground-web/src/components/ui/button.tsx
- packages/ui/src/lib/utils.ts
- apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/hooks.ts
- apps/dashboard/src/app/login/layout.tsx
- packages/ui/src/global.css
- apps/playground-web/src/app/ai/api/chat.ts
- apps/dashboard/tailwind.config.ts
- apps/dashboard/knip.json
- packages/ui/src/components/button.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@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes
Avoidanyandunknownunless 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/pay/layout.tsxpackages/ui/tailwind.config.tsapps/portal/src/components/ui/button.tsxapps/portal/tailwind.config.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/_common/chain-overview.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/pay/layout.tsxpackages/ui/tailwind.config.tsapps/portal/src/components/ui/button.tsxapps/portal/tailwind.config.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/_common/chain-overview.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
UseNavLinkfor internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()from@/lib/utilsfor conditional class logic
Use design system tokens (e.g.,bg-card,border-border,text-muted-foreground)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader – never embed tokens in URLs
Return typed results (e.g.,Project[],User[]) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysfor React Query cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components
Files:
apps/dashboard/src/app/pay/layout.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/_common/chain-overview.tsx
🧠 Learnings (18)
📓 Common learnings
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
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"`.
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 Tailwind CSS only – no inline styles or CSS modules
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.
📚 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/package.jsonapps/dashboard/src/app/pay/layout.tsxapps/portal/src/components/ui/button.tsxpackages/ui/package.jsonapps/portal/tailwind.config.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 apps/{dashboard,playground-web}/**/*.{ts,tsx} : Use Tailwind CSS only – no inline styles or CSS modules
Applied to files:
apps/dashboard/src/app/pay/layout.tsxapps/dashboard/tsconfig.jsonpackages/ui/tailwind.config.tspackages/ui/package.jsonapps/portal/tailwind.config.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/**/layout.tsx : Building layout shells (`layout.tsx`) and top-level pages that mainly assemble data.
Applied to files:
apps/dashboard/src/app/pay/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} : Tailwind CSS is the styling system – avoid inline styles or CSS modules.
Applied to files:
apps/dashboard/src/app/pay/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} : Merge class names with `cn` from `@/lib/utils` to keep conditional logic readable.
Applied to files:
apps/dashboard/src/app/pay/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} : Always import from the central UI library under `@/components/ui/*` – e.g. `import { Button } from "@/components/ui/button"`.
Applied to files:
apps/dashboard/src/app/pay/layout.tsxapps/portal/src/components/ui/button.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/app/pay/layout.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} : Server Components (Node edge): Start files with `import "server-only";`
Applied to files:
apps/dashboard/tsconfig.json
📚 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/**/api/**/*.{ts,tsx} : Prefix files with `import "server-only";` so they never end up in the client bundle.
Applied to files:
apps/dashboard/tsconfig.json
📚 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/**/*.{ts,tsx} : Export default async functions without `'use client';` – they run on the Node edge.
Applied to files:
apps/dashboard/tsconfig.json
📚 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/portal/src/components/ui/button.tsx
📚 Learning: 2025-07-10T10:18:33.238Z
Learnt from: arcoraven
PR: thirdweb-dev/js#7505
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/analytics/components/WebhookAnalyticsCharts.tsx:186-204
Timestamp: 2025-07-10T10:18:33.238Z
Learning: The ThirdwebBarChart component in apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/analytics/components/WebhookAnalyticsCharts.tsx does not accept standard accessibility props like `aria-label` and `role` in its TypeScript interface, causing compilation errors when added.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/_common/chain-overview.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)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/_common/chain-overview.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)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/_common/chain-overview.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)/tokens/create/_common/chain-overview.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)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/_common/chain-overview.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 **/*.{ts,tsx} : Write idiomatic TypeScript with explicit function declarations and return types
Applied to files:
packages/ui/tsconfig.json
🧬 Code Graph Analysis (1)
apps/portal/tailwind.config.ts (1)
packages/ui/postcss.config.mjs (1)
config(2-7)
⏰ 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). (9)
- GitHub Check: Socket Security: Pull Request Alerts
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: Size
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: Lint Packages
- GitHub Check: Build Packages
- GitHub Check: Unit Tests
- GitHub Check: Analyze (javascript)
🔇 Additional comments (10)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/_common/chain-overview.tsx (1)
1-1: Type-only import from "thirdweb" is correct and preferredGood move to import the
ThirdwebClienttype from the package root usingimport type— keeps bundles clean and aligns with the migration away from deep imports.apps/dashboard/tsconfig.json (2)
12-14: ESNext + Bundler resolution + ES2022 target look correct for Next 15These align with Next 15/SWC and modern ESM. No issues spotted.
Also applies to: 25-25
12-14: ✅ TypeScript version meets requirementThe dashboard app declares TypeScript 5.8.3, which is above the 5.2 minimum needed for
moduleResolution: "Bundler". No further changes required.apps/portal/next.config.mjs (2)
50-50: Transpiling @workspace/ui is the right callEnsures TS/ESM inside the workspace package compiles correctly under Next. Looks good.
48-86: Confirm webpack externals removal safetyA search across the codebase didn’t turn up any direct imports or requires of
pino-pretty,lokijs, orencoding.
- No occurrences of
from 'pino-pretty',require('pino-pretty'),lokijs, orencodingwere found outsidenode_modules.Please verify that none of your transitive dependencies still expect these modules at runtime, ensuring the removal of the old
externalsconfig won’t introduce missing-module errors.packages/ui/tailwind.config.ts (1)
1-3: Typed Tailwind config and ESM export are solidUsing Config typing and default ESM export improves DX and aligns with modern Tailwind setups. Plugin import via tailwindcss-animate is also correct.
apps/portal/tailwind.config.ts (1)
1-5: Nice composition with the shared UI Tailwind configSpreading the base UI config keeps plugins/darkMode/theme aligned across apps and reduces duplication.
packages/ui/package.json (1)
24-27: Peer deps aligned with React 19Peer versions match the apps’ React 19 usage; no concerns from me.
apps/portal/src/components/ui/button.tsx (2)
1-1: LGTM: "use client" is correctly applied for this re-exportSince you re-export runtime values from a Client Component module, marking this file as a client module avoids the “Server Component importing Client Component” constraint in Next.js. Looks good.
1-3: All sanity-check configurations for@workspace/uiare correctly set up in Portal
Verified:
apps/portal/next.config.mjs:transpilePackages: ["@workspace/ui"](line 50)apps/portal/src/app/layout.tsx:import "@workspace/ui/global.css";presentapps/portal/tailwind.config.ts: imports/extending from@workspace/ui/tailwind.configNo further changes needed—this re-export will work end-to-end.
...app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/_common/chain-overview.tsx
Show resolved
Hide resolved
e44b2a0 to
171eb7e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (3)
packages/ui/src/components/button.tsx (3)
54-76: Do not passdisabledto non-button elements; apply manual disabled styles only withasChildRight now
disabledis applied to all render targets, including when usingasChild(e.g., ), wheredisabledis invalid and won’t trigger Tailwind’s:disabledstyles. Also, native buttons already getdisabled:utilities from the base class, so the manual disabledClass duplicates styling. MovedisabledintobtnOnlyPropswhen the rendered element is a native , and only apply the manual disabled visuals forasChild.Apply this diff:
- const disabledClass = disabled ? "pointer-events-none opacity-50" : ""; + // Apply manual disabled visuals only when not rendering a native <button> + const disabledClass = + asChild && disabled ? "pointer-events-none opacity-50" : ""; const btnOnlyProps = Comp === "button" ? { - type: - (props as React.ButtonHTMLAttributes<HTMLButtonElement>).type || - ("button" as const), + disabled, + type: + (props as React.ButtonHTMLAttributes<HTMLButtonElement>).type ?? + ("button" as const), } - : undefined; + : disabled + ? { tabIndex: -1 } + : undefined; return ( <Comp - aria-disabled={disabled ? true : undefined} + aria-disabled={asChild && disabled ? true : undefined} className={cn( buttonVariants({ className, size, variant }), disabledClass, )} - disabled={disabled} ref={ref} {...props} {...btnOnlyProps} /> );Optional follow-up: for non-button elements in the disabled state, also prevent interaction with an onClick guard that no-ops when disabled.
21-33: Confirm intended design changes vs. app parity (font weight andupsellvariant restyle)Compared to prior app-specific buttons, this central version uses base
font-mediumand removesfont-semiboldfrom several variants, and restylesupsellfrom a purple-pink gradient to solid green. If unintentional, this will cause visual drift when apps adopt the shared component. Either restore parity or document the new design as intentional.If parity is desired, apply:
variant: { default: "bg-foreground text-background hover:bg-foreground/90", - destructive: - "bg-destructive hover:bg-destructive/90 text-destructive-foreground ", - ghost: "hover:bg-accent hover:text-accent-foreground", - link: "underline-offset-4 hover:underline", - outline: - "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground", - primary: "bg-primary hover:bg-primary/90 text-primary-foreground ", - secondary: - "bg-secondary hover:bg-secondary/80 text-secondary-foreground ", - upsell: - "bg-green-600 text-white hover:bg-green-700 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5 transition-all duration-200", + destructive: + "bg-destructive hover:bg-destructive/90 text-destructive-foreground font-semibold", + ghost: "hover:bg-accent hover:text-accent-foreground font-semibold", + link: "underline-offset-4 hover:underline font-semibold", + outline: + "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground font-semibold", + primary: + "bg-primary hover:bg-primary/90 text-primary-foreground font-semibold", + secondary: + "bg-secondary hover:bg-secondary/80 text-secondary-foreground font-semibold", + upsell: + "bg-gradient-to-r from-purple-500 to-pink-500 text-white hover:from-purple-600 hover:to-pink-600 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5 transition-all duration-200", },If the new green upsell is intentional, consider a new variant name (e.g., upsellGreen) to keep both styles available during migration.
4-4: Replace workspace alias with relative import to avoid unresolved paths in the published packageUsing "@/lib/utils" inside a published package relies on consumers’ alias configuration. Without a bundler/plugin to rewrite TS path aliases at build time, this will break for consumers. Switch to a relative import within the package.
Apply this diff:
-import { cn } from "@/lib/utils"; +import { cn } from "../lib/utils";
🧹 Nitpick comments (8)
packages/ui/src/components/button.tsx (1)
44-46: Optional: improve polymorphic typing forasChildThe ref is typed as HTMLButtonElement even when rendering via Slot (e.g., ). This is common and workable, but if you want stricter types, consider a polymorphic typing approach so the ref/props match the rendered element.
For example, you can type the component with a generic ElementType and map props accordingly, or use React.ElementRef for the ref when asChild is true. This is optional and can be deferred.
apps/portal/knip.json (1)
10-14: It looks like the import-scan step is still failing to run properly in CI. Could you please manually verify that, in apps/portal/src:
- No files import from either
@/components/ui/orsrc/components/ui/- No files import from either
@/icons/orsrc/icons/- No files import the standalone
Banner.tsxundersrc/components/others/- There are no stray Next.js auto-injected files matching
instrumentation.*orglobal-error.*that should be added to your Knip “entry” patternsIf all of those checks confirm there’s truly no usage, the ignored folders/files can be safely deleted (or moved) and removed from
knip.json. Otherwise, keep the ignores for any persistent false positives.apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsx (3)
181-186: BigInt on possibly fractional quantities can throw; confirm units for airdrop amountsIf recipient.quantity can be fractional (e.g., "1.5"), BigInt(recipient.quantity) will throw. Also, unit expectations for distributeToken.amount may be in token units or base units depending on API; current code assumes integer token units → base unit bigint.
Two safe options depending on API expectations:
- If distributeToken expects base units (recommended when decimals are known): convert with toUnits and the token’s decimals.
- If it expects whole tokens only: validate and disallow fractional quantities before converting to BigInt.
Option A (convert to base units – assumes 18 decimals; adjust if different):
- contents: values.airdropAddresses.map((recipient) => ({ - amount: BigInt(recipient.quantity), - recipient: recipient.address, - })), + contents: values.airdropAddresses.map((recipient) => ({ + amount: toUnits(String(recipient.quantity), 18), + recipient: recipient.address, + })),Option B (enforce whole tokens only and surface a clear error):
- contents: values.airdropAddresses.map((recipient) => ({ - amount: BigInt(recipient.quantity), - recipient: recipient.address, - })), + contents: values.airdropAddresses.map((recipient) => { + const q = String(recipient.quantity); + if (q.includes(".")) + throw new Error("Airdrop quantity must be a whole number of tokens"); + return { + amount: BigInt(q), + recipient: recipient.address, + }; + }),
306-309: Redundant null check on accountgetAccount() throws if no activeAccount, so account is never falsy here. The check is unreachable and can be removed.
- if (!account) { - throw new Error("No connected account"); - }
90-94: Align function naming: use consistent “ERC20Asset” casingOther helpers use “ERC20Asset_*”. Rename Erc20Asset_deployContract for consistency and easier grepability.
- async function Erc20Asset_deployContract(params: { + async function ERC20Asset_deployContract(params: {And update the usage:
- deployContract: Erc20Asset_deployContract, + deployContract: ERC20Asset_deployContract,Also applies to: 431-435
apps/portal/tailwind.config.ts (3)
4-5: Prefer Tailwind’spresetsover object spread to compose configsUsing
presetsavoids subtle overrides (e.g., future plugin changes, flags, or experimental toggles) and communicates intent more clearly than spreading the entire base config.Apply this diff:
-const config: Config = { - ...tailwindConfig, +const config: Config = { + presets: [tailwindConfig as Config], content: [ @@ - theme: { - ...tailwindConfig.theme, - extend: { - ...tailwindConfig.theme?.extend, + theme: { + extend: {Also applies to: 14-17
6-12: Merge base content globs and add a fallback for the published UI packageOverriding
contentdrops any globs the UI config might define. Also, when the app consumes the published UI package instead of a workspace path, adding a node_modules fallback prevents missing classes in production builds. Note: scanning node_modules can increase build time; weigh this tradeoff.Apply this diff:
content: [ + // include any content globs defined by the shared UI config + ...(tailwindConfig.content ?? []), "./components/**/*.{ts,tsx}", "./app/**/*.{ts,tsx,mdx}", "./src/**/*.{ts,tsx,mdx}", // add contents of ui package "../../packages/ui/src/**/*.{ts,tsx}", + // fallback when consuming published @workspace/ui + "../../node_modules/@workspace/ui/**/*.{js,jsx,ts,tsx}", ],
23-39: Use numeric z-index values (nit)Tailwind accepts either strings or numbers here, but numbers are conventional and slightly clearer when scanning configs.
Apply this diff:
zIndex: { - // base - base: "0", - // - codeToken: "5", - codeTokenHighlight: "1", - // - copyCodeButton: "20", - dropdownMenu: "1200", - floatingButton: "1000", - menu: "1100", - modal: "1400", - modalOverlay: "1300", - stickyMobileSidebar: "500", - // - stickyTop: "1000", + // base + base: 0, + // + codeToken: 5, + codeTokenHighlight: 1, + // + copyCodeButton: 20, + dropdownMenu: 1200, + floatingButton: 1000, + menu: 1100, + modal: 1400, + modalOverlay: 1300, + stickyMobileSidebar: 500, + // + stickyTop: 1000, },
📜 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.
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (46)
apps/dashboard/knip.json(1 hunks)apps/dashboard/next.config.ts(1 hunks)apps/dashboard/package.json(1 hunks)apps/dashboard/postcss.config.js(0 hunks)apps/dashboard/postcss.config.mjs(1 hunks)apps/dashboard/src/@/components/sponsored-transactions-table/SponsoredTransactionsTable.tsx(1 hunks)apps/dashboard/src/@/components/ui/button.tsx(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/components/types.ts(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/hooks.ts(2 hunks)apps/dashboard/src/app/(app)/layout.tsx(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/_common/chain-overview.tsx(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsx(1 hunks)apps/dashboard/src/app/bridge/layout.tsx(1 hunks)apps/dashboard/src/app/login/layout.tsx(1 hunks)apps/dashboard/src/app/pay/layout.tsx(1 hunks)apps/dashboard/tailwind.config.ts(1 hunks)apps/dashboard/tsconfig.json(2 hunks)apps/playground-web/knip.json(1 hunks)apps/playground-web/next.config.mjs(1 hunks)apps/playground-web/package.json(1 hunks)apps/playground-web/postcss.config.js(0 hunks)apps/playground-web/postcss.config.mjs(1 hunks)apps/playground-web/src/app/ai/api/chat.ts(1 hunks)apps/playground-web/src/app/ai/api/types.ts(0 hunks)apps/playground-web/src/app/ai/components/ChatPageContent.tsx(2 hunks)apps/playground-web/src/app/globals.css(0 hunks)apps/playground-web/src/app/layout.tsx(1 hunks)apps/playground-web/src/components/ui/button.tsx(1 hunks)apps/playground-web/tailwind.config.ts(1 hunks)apps/portal/knip.json(1 hunks)apps/portal/next.config.mjs(1 hunks)apps/portal/package.json(1 hunks)apps/portal/src/app/globals.css(0 hunks)apps/portal/src/app/layout.tsx(1 hunks)apps/portal/src/components/ui/button.tsx(1 hunks)apps/portal/tailwind.config.ts(1 hunks)apps/wallet-ui/next.config.mjs(0 hunks)packages/thirdweb/src/exports/extensions/marketplace.ts(1 hunks)packages/thirdweb/src/exports/utils.ts(1 hunks)packages/ui/package.json(1 hunks)packages/ui/postcss.config.mjs(1 hunks)packages/ui/src/components/button.tsx(1 hunks)packages/ui/src/global.css(2 hunks)packages/ui/src/lib/utils.ts(1 hunks)packages/ui/tailwind.config.ts(2 hunks)packages/ui/tsconfig.json(1 hunks)
💤 Files with no reviewable changes (6)
- apps/dashboard/postcss.config.js
- apps/wallet-ui/next.config.mjs
- apps/playground-web/src/app/globals.css
- apps/playground-web/postcss.config.js
- apps/playground-web/src/app/ai/api/types.ts
- apps/portal/src/app/globals.css
✅ Files skipped from review due to trivial changes (2)
- apps/portal/src/app/layout.tsx
- apps/dashboard/src/app/(app)/layout.tsx
🚧 Files skipped from review as they are similar to previous changes (34)
- apps/dashboard/postcss.config.mjs
- apps/playground-web/package.json
- packages/thirdweb/src/exports/utils.ts
- apps/dashboard/next.config.ts
- apps/dashboard/src/@/components/sponsored-transactions-table/SponsoredTransactionsTable.tsx
- apps/playground-web/src/app/ai/api/chat.ts
- apps/dashboard/tsconfig.json
- apps/playground-web/knip.json
- apps/dashboard/src/app/pay/layout.tsx
- packages/ui/package.json
- apps/playground-web/postcss.config.mjs
- apps/playground-web/next.config.mjs
- apps/portal/next.config.mjs
- apps/dashboard/tailwind.config.ts
- packages/thirdweb/src/exports/extensions/marketplace.ts
- apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/components/types.ts
- apps/dashboard/package.json
- apps/portal/package.json
- apps/playground-web/src/app/layout.tsx
- apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/hooks.ts
- packages/ui/src/lib/utils.ts
- packages/ui/tsconfig.json
- apps/playground-web/tailwind.config.ts
- packages/ui/src/global.css
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/_common/chain-overview.tsx
- packages/ui/postcss.config.mjs
- apps/dashboard/src/@/components/ui/button.tsx
- packages/ui/tailwind.config.ts
- apps/playground-web/src/components/ui/button.tsx
- apps/dashboard/knip.json
- apps/dashboard/src/app/bridge/layout.tsx
- apps/dashboard/src/app/login/layout.tsx
- apps/playground-web/src/app/ai/components/ChatPageContent.tsx
- apps/portal/src/components/ui/button.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@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes
Avoidanyandunknownunless 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)/tokens/create/token/create-token-page-impl.tsxpackages/ui/src/components/button.tsxapps/portal/tailwind.config.ts
**/*.{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)/tokens/create/token/create-token-page-impl.tsxpackages/ui/src/components/button.tsxapps/portal/tailwind.config.ts
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
UseNavLinkfor internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()from@/lib/utilsfor conditional class logic
Use design system tokens (e.g.,bg-card,border-border,text-muted-foreground)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader – never embed tokens in URLs
Return typed results (e.g.,Project[],User[]) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysfor React Query cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsx
🧠 Learnings (9)
📓 Common learnings
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
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"`.
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.
📚 Learning: 2025-05-20T19:03:35.954Z
Learnt from: MananTank
PR: thirdweb-dev/js#7081
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page-impl.tsx:160-165
Timestamp: 2025-05-20T19:03:35.954Z
Learning: The `claimTo` function in Thirdweb's ERC20 extension does not require converting the quantity to the smallest units (using toUnits) as it handles unit conversion internally or works with the units as provided.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsx
📚 Learning: 2025-06-18T02:01:06.006Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7363
File: apps/dashboard/src/app/(app)/layout.tsx:63-74
Timestamp: 2025-06-18T02:01:06.006Z
Learning: In Next.js applications, instrumentation files (instrumentation.ts or instrumentation-client.ts) placed in the src/ directory are automatically handled by the framework and included in the client/server bundles without requiring manual imports. The framework injects these files as part of the build process.
Applied to files:
apps/portal/knip.json
📚 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:
packages/ui/src/components/button.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:
packages/ui/src/components/button.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:
packages/ui/src/components/button.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:
packages/ui/src/components/button.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 Tailwind CSS only – no inline styles or CSS modules
Applied to files:
apps/portal/tailwind.config.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 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/portal/tailwind.config.ts
🧬 Code Graph Analysis (2)
packages/ui/src/components/button.tsx (1)
packages/ui/src/lib/utils.ts (1)
cn(4-6)
apps/portal/tailwind.config.ts (1)
packages/ui/postcss.config.mjs (1)
config(2-7)
⏰ 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, esbuild)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: Unit Tests
- GitHub Check: Size
- GitHub Check: Lint Packages
- GitHub Check: Build Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (6)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsx (4)
27-27: Type import moved to public module looks correctSwitching ClaimConditionsInput to thirdweb/utils is cleaner and avoids deep-imports. Using import type keeps it out of the bundle. Good change.
382-394: Hard-coded 18 decimals for maxClaimableSupply; confirm token decimalstoUnits(totalSupply.toString(), 18) assumes 18 decimals for DropERC20. If this contract ever uses non-18 decimals, claim supply math will be off. Validate that DropERC20 is always 18 decimals or derive decimals from the contract before converting.
355-359: claimTo quantity usage is correct per prior guidancePassing quantity as a token-denominated string (not pre-converted to base units) matches our prior learning that claimTo handles units internally.
1-2: All deep imports forClaimConditionsInputhave been removed
I searched the entire repo for any imports fromthirdweb/dist/types/utils/extensions/drops/typesand forimport type { ClaimConditionsInput } from 'thirdweb/utils'. No matches were found.apps/portal/tailwind.config.ts (2)
10-12: LGTM on including the UI source in content globsPointing to the shared UI package’s src ensures utility classes used inside the library’s components make it into the app build. This aligns with the PR objective to centralize UI.
1-1: No issues:tailwind.configis correctly exported by @workspace/ui
- packages/ui/tailwind.config.ts exists.
package.jsonexports include"./tailwind.config": "./tailwind.config.ts", so the import will resolve as expected.
Merge activity
|
created a @workspace/ui package - shared by dashboard and playground. for now it only has button component for testing
<!-- start pr-codex -->
---
## PR-Codex overview
This PR focuses on refactoring the `postcss` and `tailwind` configurations across multiple applications to centralize styles in the `@workspace/ui` package, along with various updates to components and layouts.
### Detailed summary
- Deleted `postcss.config.js` files and replaced them with `postcss.config.mjs` referencing `@workspace/ui`.
- Updated CSS imports to use `@workspace/ui/global.css`.
- Added `tailwindcss` configuration in `@workspace/ui` and updated references.
- Introduced new utility functions in `packages/ui/src/lib/utils.ts`.
- Modified component imports to utilize centralized components from `@workspace/ui`.
- Updated `package.json` files to include `@workspace/ui` as a dependency.
- Refactored button components to use a centralized button definition in `@workspace/ui`.
- Adjusted TypeScript configurations to align with the new structure.
- Enhanced global styles and configurations across multiple applications to ensure consistency.
> ✨ 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
- Added a shared UI package and unified Button component used across apps.
- Style
- Apps now load shared global styles and animations from the UI package; global CSS and theme tokens consolidated.
- Bug Fixes
- AI chat header uses a safe fallback when the client ID is missing.
- Refactor
- Replaced local UI implementations with shared re-exports and composed Tailwind configs.
- Chores
- Added UI package dependencies, PostCSS delegation, and enabled Next.js transpilation for the UI package; lint/scan ignore lists updated.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
171eb7e to
92896dd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🔭 Outside diff range comments (2)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/hooks.ts (2)
284-296: SnapshotEntry type mismatch: mapping returns bigint where strings are expected
SnapshotEntrydefinesmaxClaimable: stringandprice?: string, but the mapper returnsbigintfor both. This will either fail type-checking or leak non-JSON-serializable bigints at runtime.Apply this diff to normalize to strings:
- return raw.claims.map( - (claim: { - address: string; - maxClaimable: bigint; - price: bigint; - currencyAddress: string; - }) => ({ - address: claim.address, - currencyAddress: claim.currencyAddress, - maxClaimable: claim.maxClaimable, - price: claim.price, - }), - ); + return raw.claims.map( + (claim: { + address: string; + maxClaimable: string | number | bigint; + price?: string | number | bigint; + currencyAddress?: string; + }) => ({ + address: claim.address, + currencyAddress: claim.currencyAddress, + maxClaimable: claim.maxClaimable.toString(), + price: claim.price !== undefined ? claim.price.toString() : undefined, + }), + );
275-282: Normalize sharded snapshot payload to SnapshotEntry[] instead of returning raw JSONFor sharded trees you currently return the raw JSON for
originalEntriesUri. Normalize it toSnapshotEntry[]so downstream consumers get a consistent shape.Apply this diff:
- return download({ - client: client, - uri: raw.originalEntriesUri, - }) - .then((r) => r.json()) - .catch(() => null); + return download({ + client: client, + uri: raw.originalEntriesUri, + }) + .then((r) => r.json()) + .then( + ( + entries: Array< + string | { address: string; maxClaimable: string | number | bigint; price?: string | number | bigint; currencyAddress?: string } + >, + ) => + entries.map((entry) => + typeof entry === "string" + ? { address: entry } + : { + address: entry.address, + currencyAddress: entry.currencyAddress, + maxClaimable: entry.maxClaimable.toString(), + price: entry.price !== undefined ? entry.price.toString() : undefined, + }, + ), + ) + .catch(() => null);
♻️ Duplicate comments (3)
packages/ui/src/components/button.tsx (2)
4-4: Replace repo-local alias import in shared UI packageConsumers won’t resolve
@/lib/utils, so update the import inpackages/ui/src/components/button.tsx:
- File: packages/ui/src/components/button.tsx, Line 4
-import { cn } from "@/lib/utils"; +import { cn } from "../lib/utils";I ran:
rg -nP "from\s+['\"]@/" packages/ui/srcand confirmed this is the only alias usage in the UI package.
48-76: Fix disabled semantics for non-button renders (asChild) and avoid invalid DOM attributesCurrently,
disabledis forwarded to non-button elements (e.g., ), which is invalid, and disabled styles are duplicated on native buttons. Passdisabledonly to real buttons, usearia-disabledand inert behavior for non-buttons, and only apply manual disabled classes when not rendering a native button.Apply this diff:
@@ - // "button" elements automatically handle the `disabled` attribute. - // For non-button elements rendered via `asChild` (e.g. <a>), we still want - // to visually convey the disabled state and prevent user interaction. - // We do that by conditionally adding the same utility classes that the - // `disabled:` pseudo-variant would normally apply and by setting - // `aria-disabled` for accessibility. - const disabledClass = disabled ? "pointer-events-none opacity-50" : ""; + // "button" elements automatically handle the `disabled` attribute. + // For non-button elements rendered via `asChild` (e.g. <a>), we still want + // to visually convey the disabled state and prevent user interaction. + // Apply manual disabled styling only when not rendering a native <button>. + const disabledClass = + asChild && disabled ? "pointer-events-none opacity-50" : ""; @@ - const btnOnlyProps = - Comp === "button" - ? { - type: - (props as React.ButtonHTMLAttributes<HTMLButtonElement>).type || - ("button" as const), - } - : undefined; + const btnOnlyProps = + Comp === "button" + ? { + disabled, + type: + (props as React.ButtonHTMLAttributes<HTMLButtonElement>).type ?? + ("button" as const), + } + : disabled + ? { tabIndex: -1 } + : undefined; @@ - <Comp - aria-disabled={disabled ? true : undefined} + <Comp + aria-disabled={asChild && disabled ? true : undefined} className={cn( buttonVariants({ className, size, variant }), disabledClass, )} - disabled={disabled} ref={ref} {...props} {...btnOnlyProps} />apps/portal/knip.json (1)
20-23: Don’t ignore @workspace/ui and UI impl details in dependencies (carry-forward)Keeping "@workspace/ui", "@radix-ui/react-slot", and "tailwindcss-animate" in ignoreDependencies masks true unused-dep signals. Let @workspace/ui own its implementation details and only keep type-only ignores if needed.
Proposed minimal change:
"ignoreDependencies": [ "@thirdweb-dev/chains", "@thirdweb-dev/wallets", "thirdweb", - "@workspace/ui", "@types/flexsearch", - "@radix-ui/react-slot", - "tailwindcss-animate" ],If radix-slot or tailwindcss-animate are required by UI components, declare them in packages/ui (dependency or peerDependency) rather than in apps/portal, and remove them from apps/portal/package.json accordingly.
🧹 Nitpick comments (11)
apps/dashboard/tsconfig.json (1)
12-14: Bundler-friendly TS settings look good; consider adding verbatimModuleSyntax for cleaner ESM/CJS interopNice move to ESNext modules, Bundler resolution, and ES2022 target. Add
"verbatimModuleSyntax": trueto align with TS 5 bundler flows and improve tree-shaking by avoiding synthetic default interop.Apply this minimal change:
"lib": ["dom", "dom.iterable", "esnext"], "module": "ESNext", "moduleResolution": "Bundler", "moduleDetection": "force", + "verbatimModuleSyntax": true, "noEmit": true,Also applies to: 25-25
packages/ui/src/components/button.tsx (1)
21-33: Remove stray trailing spaces in variant class stringsThere are extra spaces at the end of some variant class strings (
destructive,primary,secondary). Small cleanup to keep diffs tidy.- destructive: - "bg-destructive hover:bg-destructive/90 text-destructive-foreground ", + destructive: + "bg-destructive hover:bg-destructive/90 text-destructive-foreground", @@ - primary: "bg-primary hover:bg-primary/90 text-primary-foreground ", + primary: "bg-primary hover:bg-primary/90 text-primary-foreground", @@ - secondary: - "bg-secondary hover:bg-secondary/80 text-secondary-foreground ", + secondary: + "bg-secondary hover:bg-secondary/80 text-secondary-foreground",apps/playground-web/src/app/ai/components/ChatPageContent.tsx (3)
600-601: Avoid "undefined" token in className; use cn() for safe composition.Interpolating props.className can yield a literal "undefined" class. Use cn() per app guidelines.
Apply this diff:
- <div className={`flex flex-col gap-5 py-6 pb-8 ${props.className}`}> + <div className={cn("flex flex-col gap-5 py-6 pb-8", props.className)}>And add the import at the top of the file:
import { cn } from "@/lib/utils";
144-147: Add explicit return type to exported component for consistency with TS guidelines.Explicit return types help with refactors and align with the repo’s TS conventions.
For example:
export function ChatPageContent(props: { client: ThirdwebClient; type: "landing" | "new-chat"; }): JSX.Element { // ... }
585-585: Remove unusedsetEnableAutoScrollprop from SimpleChatsThe
SimpleChatscomponent no longer usesprops.setEnableAutoScroll, so it should be removed from both its signature and its callsite in ChatPageContent.tsx.• In apps/playground-web/src/app/ai/components/ChatPageContent.tsx, update the
SimpleChatsdeclaration (around line 580) to dropsetEnableAutoScroll:-function SimpleChats(props: { - messages: Array<ChatMessage>; - isChatStreaming: boolean; - className?: string; - client: ThirdwebClient; - setEnableAutoScroll: (enable: boolean) => void; - enableAutoScroll: boolean; - sendMessage: (message: NebulaUserMessage) => void; -}) { +function SimpleChats(props: { + messages: Array<ChatMessage>; + isChatStreaming: boolean; + className?: string; + client: ThirdwebClient; + enableAutoScroll: boolean; + sendMessage: (message: NebulaUserMessage) => void; +}) {• In the JSX where
SimpleChatsis rendered (around lines 372–376), remove the prop:<SimpleChats className="min-w-0" client={props.client} enableAutoScroll={enableAutoScroll} isChatStreaming={isChatStreaming} messages={messages} - setEnableAutoScroll={setEnableAutoScroll} sendMessage={handleSendMessage} />[optional_refactors_recommended]
apps/portal/src/app/layout.tsx (1)
9-9: Consider migrating cn to the shared util from @workspace/uiGiven the new centralized utility (cn in @workspace/ui), consider importing it from the UI package to avoid divergence of implementations.
Apply this minimal diff if the UI package re-exports cn:
-import { cn } from "../lib/utils"; +import { cn } from "@workspace/ui/lib/utils";apps/portal/knip.json (1)
10-14: Narrow the ignore globs to avoid masking unused export detectionIgnoring entire trees like src/components/ui/** and src/icons/** can hide real issues. Prefer targeted ignores (per-file comments or narrower patterns), and plan to remove these once the UI migration stabilizes.
For example, consider dropping the broad UI folder ignore and keeping only specific dynamic cases:
"ignore": [ - "src/components/ui/**", "src/icons/**", "src/components/others/Banner.tsx" ],apps/portal/tailwind.config.ts (1)
4-5: Prefer Tailwind “presets” over object spread for compositionUsing presets ensures Tailwind merges themes/plugins correctly and avoids accidental overrides or duplicate plugin execution.
Apply this diff:
const config: Config = { - ...tailwindConfig, + presets: [tailwindConfig as Config], content: [ @@ theme: { - ...tailwindConfig.theme, extend: { - ...tailwindConfig.theme?.extend, spacing: { "offset-top": "calc(var(--sticky-top-height) + 18px)", "offset-top-mobile": "calc(var(--sticky-top-height) + 100px)", "sidebar-height": "calc(100vh - var(--sticky-top-height))", "sticky-top-height": "var(--sticky-top-height)", }, zIndex: { // base base: "0", // codeToken: "5", codeTokenHighlight: "1", // copyCodeButton: "20", dropdownMenu: "1200", floatingButton: "1000", menu: "1100", modal: "1400", modalOverlay: "1300", stickyMobileSidebar: "500", // stickyTop: "1000", }, }, }, };Also applies to: 14-17
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/hooks.ts (3)
70-86: Don’t await inside Promise.all — you’re serializing the first requestThe leading
awaitinsidePromise.allforcesgetCurrencyMetadatato complete before the other two start, defeating concurrency.Apply this diff:
const [currencyMetadata, metadata, contractMetadata] = await Promise.all([ - await ERC20Ext.getCurrencyMetadata({ + ERC20Ext.getCurrencyMetadata({ contract: getContract({ ...options.contract, address: condition.currency, }), }).then((m) => ({ ...m, displayValue: toTokens(condition.pricePerToken, m.decimals), value: condition.pricePerToken, })), download({ client: options.contract.client, uri: condition.metadata, }).then((r) => r.json()), getContractMetadata(options), ]);
230-233: Handle decimals=0 correctly; use strict undefined checkUsing
if (decimals)treats0as falsy. Tokens can have 0 decimals. Preferdecimals !== undefinedin both conversions.Apply this diff:
- if (decimals) { + if (decimals !== undefined) { return toUnits(value.toString(), decimals); }- if (decimals) { + if (decimals !== undefined) { return toTokens(value, decimals); }Also applies to: 246-248
125-128: Consider annotating an explicit return type for setClaimPhasesTxConsistency with the TypeScript guidelines: make return types explicit. If all three
setClaimConditionsoverloads return the same type (e.g., PreparedTransaction), you can reuse that.Potential change:
-export function setClaimPhasesTx( +export function setClaimPhasesTx( baseOptions: BaseTransactionOptions<Options> & { isSinglePhase?: boolean }, rawPhases: PhaseInput[], -) { +): ReturnType<typeof ERC20Ext.setClaimConditions> {Please verify
ERC721Ext.setClaimConditionsandERC1155Ext.setClaimConditionsreturn the same type; if not, a shared exported type (e.g.,PreparedTransaction) fromthirdweb/extensions would be preferable.
📜 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.
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (46)
apps/dashboard/knip.json(1 hunks)apps/dashboard/next.config.ts(1 hunks)apps/dashboard/package.json(1 hunks)apps/dashboard/postcss.config.js(0 hunks)apps/dashboard/postcss.config.mjs(1 hunks)apps/dashboard/src/@/components/sponsored-transactions-table/SponsoredTransactionsTable.tsx(1 hunks)apps/dashboard/src/@/components/ui/button.tsx(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/components/types.ts(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/hooks.ts(2 hunks)apps/dashboard/src/app/(app)/layout.tsx(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/_common/chain-overview.tsx(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsx(1 hunks)apps/dashboard/src/app/bridge/layout.tsx(1 hunks)apps/dashboard/src/app/login/layout.tsx(1 hunks)apps/dashboard/src/app/pay/layout.tsx(1 hunks)apps/dashboard/tailwind.config.ts(1 hunks)apps/dashboard/tsconfig.json(2 hunks)apps/playground-web/knip.json(1 hunks)apps/playground-web/next.config.mjs(1 hunks)apps/playground-web/package.json(1 hunks)apps/playground-web/postcss.config.js(0 hunks)apps/playground-web/postcss.config.mjs(1 hunks)apps/playground-web/src/app/ai/api/chat.ts(1 hunks)apps/playground-web/src/app/ai/api/types.ts(0 hunks)apps/playground-web/src/app/ai/components/ChatPageContent.tsx(2 hunks)apps/playground-web/src/app/globals.css(0 hunks)apps/playground-web/src/app/layout.tsx(1 hunks)apps/playground-web/src/components/ui/button.tsx(1 hunks)apps/playground-web/tailwind.config.ts(1 hunks)apps/portal/knip.json(1 hunks)apps/portal/next.config.mjs(1 hunks)apps/portal/package.json(1 hunks)apps/portal/src/app/globals.css(0 hunks)apps/portal/src/app/layout.tsx(1 hunks)apps/portal/src/components/ui/button.tsx(1 hunks)apps/portal/tailwind.config.ts(1 hunks)apps/wallet-ui/next.config.mjs(0 hunks)packages/thirdweb/src/exports/extensions/marketplace.ts(1 hunks)packages/thirdweb/src/exports/utils.ts(1 hunks)packages/ui/package.json(1 hunks)packages/ui/postcss.config.mjs(1 hunks)packages/ui/src/components/button.tsx(1 hunks)packages/ui/src/global.css(2 hunks)packages/ui/src/lib/utils.ts(1 hunks)packages/ui/tailwind.config.ts(2 hunks)packages/ui/tsconfig.json(1 hunks)
💤 Files with no reviewable changes (6)
- apps/dashboard/postcss.config.js
- apps/playground-web/src/app/globals.css
- apps/wallet-ui/next.config.mjs
- apps/playground-web/postcss.config.js
- apps/playground-web/src/app/ai/api/types.ts
- apps/portal/src/app/globals.css
🚧 Files skipped from review as they are similar to previous changes (31)
- apps/playground-web/postcss.config.mjs
- apps/dashboard/tailwind.config.ts
- apps/portal/package.json
- apps/playground-web/package.json
- apps/dashboard/src/@/components/sponsored-transactions-table/SponsoredTransactionsTable.tsx
- packages/ui/postcss.config.mjs
- apps/dashboard/package.json
- packages/thirdweb/src/exports/utils.ts
- apps/dashboard/src/app/pay/layout.tsx
- apps/playground-web/src/app/layout.tsx
- apps/dashboard/src/app/login/layout.tsx
- apps/dashboard/postcss.config.mjs
- apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/components/types.ts
- apps/portal/next.config.mjs
- apps/playground-web/src/components/ui/button.tsx
- packages/ui/package.json
- apps/dashboard/src/app/(app)/layout.tsx
- apps/playground-web/next.config.mjs
- apps/playground-web/src/app/ai/api/chat.ts
- packages/ui/src/global.css
- packages/ui/src/lib/utils.ts
- apps/dashboard/src/app/bridge/layout.tsx
- packages/thirdweb/src/exports/extensions/marketplace.ts
- apps/playground-web/knip.json
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/_common/chain-overview.tsx
- apps/portal/src/components/ui/button.tsx
- packages/ui/tsconfig.json
- packages/ui/tailwind.config.ts
- apps/playground-web/tailwind.config.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsx
- apps/dashboard/knip.json
🧰 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@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes
Avoidanyandunknownunless 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/portal/src/app/layout.tsxapps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/hooks.tsapps/playground-web/src/app/ai/components/ChatPageContent.tsxapps/dashboard/src/@/components/ui/button.tsxpackages/ui/src/components/button.tsxapps/portal/tailwind.config.tsapps/dashboard/next.config.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
apps/portal/src/app/layout.tsxapps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/hooks.tsapps/playground-web/src/app/ai/components/ChatPageContent.tsxapps/dashboard/src/@/components/ui/button.tsxpackages/ui/src/components/button.tsxapps/portal/tailwind.config.tsapps/dashboard/next.config.ts
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
UseNavLinkfor internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()from@/lib/utilsfor conditional class logic
Use design system tokens (e.g.,bg-card,border-border,text-muted-foreground)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader – never embed tokens in URLs
Return typed results (e.g.,Project[],User[]) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysfor React Query cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components
Files:
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/hooks.tsapps/playground-web/src/app/ai/components/ChatPageContent.tsxapps/dashboard/src/@/components/ui/button.tsxapps/dashboard/next.config.ts
🧠 Learnings (21)
📓 Common learnings
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
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"`.
📚 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/portal/src/app/layout.tsxapps/dashboard/src/@/components/ui/button.tsxapps/portal/tailwind.config.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 apps/{dashboard,playground-web}/**/*.{ts,tsx} : Use Tailwind CSS only – no inline styles or CSS modules
Applied to files:
apps/portal/src/app/layout.tsxapps/dashboard/tsconfig.jsonapps/portal/tailwind.config.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 apps/{dashboard,playground-web}/**/*.{ts,tsx} : Server Components (Node edge): Start files with `import "server-only";`
Applied to files:
apps/dashboard/tsconfig.jsonapps/dashboard/src/@/components/ui/button.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/**/api/**/*.{ts,tsx} : Prefix files with `import "server-only";` so they never end up in the client bundle.
Applied to files:
apps/dashboard/tsconfig.jsonapps/dashboard/src/@/components/ui/button.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/ui/button.tsxpackages/ui/src/components/button.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/ui/button.tsxpackages/ui/src/components/button.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/ui/button.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/ui/button.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/ui/button.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/ui/button.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/**/*.{ts,tsx} : Export default async functions without `'use client';` – they run on the Node edge.
Applied to files:
apps/dashboard/src/@/components/ui/button.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/@/components/ui/button.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/ui/button.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/ui/button.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/ui/button.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/@/components/ui/button.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/@/components/ui/button.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:
packages/ui/src/components/button.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:
packages/ui/src/components/button.tsx
📚 Learning: 2025-06-18T02:01:06.006Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7363
File: apps/dashboard/src/app/(app)/layout.tsx:63-74
Timestamp: 2025-06-18T02:01:06.006Z
Learning: In Next.js applications, instrumentation files (instrumentation.ts or instrumentation-client.ts) placed in the src/ directory are automatically handled by the framework and included in the client/server bundles without requiring manual imports. The framework injects these files as part of the build process.
Applied to files:
apps/portal/knip.json
🧬 Code Graph Analysis (1)
apps/portal/tailwind.config.ts (1)
packages/ui/postcss.config.mjs (1)
config(2-7)
⏰ 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, webpack)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: Lint Packages
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: Unit Tests
- GitHub Check: Size
- GitHub Check: Build Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (7)
apps/dashboard/next.config.ts (1)
118-118: Adding transpilePackages for @workspace/ui is correctThis ensures TS/modern syntax in the shared UI compiles under Next and allows CSS imports (global.css) from the package to work properly.
apps/dashboard/src/@/components/ui/button.tsx (1)
1-3: Client boundary + re-export pattern LGTMExplicit 'use client' on this proxy prevents server/client boundary pitfalls. Re-exporting from the shared UI package is clean and centralizes the API.
apps/playground-web/src/app/ai/components/ChatPageContent.tsx (1)
35-35: No leftover history types/helpers in playground-web
Ran a project-wide search forNebulaSessionHistoryMessageandparseHistoryToMessagesand confirmed there are no occurrences under apps/playground-web.apps/portal/src/app/layout.tsx (1)
1-2: No duplicate Tailwind preflight rules detectedVerified that only packages/ui/src/global.css contains the
@tailwind base/components/utilitiesdirectives and that the local apps/portal/src/globals.css has no Tailwind layer directives. Your import order is correct—there will be only one preflight reset.apps/portal/tailwind.config.ts (1)
10-12: Including UI sources in content is correct for JIT class extractionScanning "../../packages/ui/src/**/*.{ts,tsx}" ensures classes used in shared UI components are not purged in the app bundle.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/hooks.ts (2)
28-36: Prettify removal is fine; type remains clear and accurateDropping
Prettify<>is harmless here and keeps the shape readable without altering the effective surface.
13-15: Consolidate thirdweb/utils importsNo occurrences of the old
thirdweb/dist/...path were found—feel free to merge these into a single import:-import type { OverrideEntry } from "thirdweb/utils"; -import { maxUint256 } from "thirdweb/utils"; +import { maxUint256, type OverrideEntry } from "thirdweb/utils";

created a @workspace/ui package - shared by dashboard and playground. for now it only has button component for testing
PR-Codex overview
This PR focuses on restructuring the codebase by introducing a new
@workspace/uipackage, which centralizes UI components and styles. It replaces direct imports and configurations across various applications, enhancing maintainability and consistency.Detailed summary
@workspace/uipackage for shared components and styles.@workspace/ui/global.cssin multiple apps.postcss.configfiles to use@workspace/ui/postcss.config.Buttonfrom@workspace/ui.@workspace/ui/tailwind.config.Summary by CodeRabbit
New Features
Style
Bug Fixes
Refactor
Chores