-
Notifications
You must be signed in to change notification settings - Fork 620
packages/ui: Add storybook, Add Badge, Input #7923
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.
|
|
WalkthroughAdds a new shared UI package ( Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant SB as Storybook UI
participant Preview as packages/ui Preview
participant Providers as ThemeProvider & QueryClientProvider
participant Story as Story Component
participant Toaster as Toaster
User->>SB: select story
SB->>Preview: render story
Preview->>Providers: wrap story (theme, react-query)
Providers->>Story: render story component
Story-->>Toaster: emit notifications (optional)
Note right of Preview: Inter font, theme toggle, viewports configured
sequenceDiagram
autonumber
participant Story as Story file
participant Utils as packages/ui/src/storybook/utils.tsx
Story->>Utils: import BadgeContainer & storybookLog
Story->>Utils: use BadgeContainer to render labeled wrapper
Story->>Utils: call storybookLog(...messages)
Utils-->>Story: console.debug("Storybook", ...messages)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (1)
✨ 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 (
|
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. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7923 +/- ##
=======================================
Coverage 56.53% 56.54%
=======================================
Files 904 904
Lines 58592 58592
Branches 4143 4140 -3
=======================================
+ Hits 33126 33131 +5
+ Misses 25360 25355 -5
Partials 106 106
🚀 New features to boost your workflow:
|
1b0a434 to
440fdce
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: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/dashboard/.storybook/preview.tsx (1)
39-43: Add the viewport addon to Storybook configThe dashboard Storybook is currently missing the
@storybook/addon-viewport, so the toolbar won’t render your custom viewports. Please update your main configuration:• File:
apps/dashboard/.storybook/main.ts
• In theaddonsarray, include the viewport addon:module.exports = { // … addons: [ + '@storybook/addon-viewport', /* existing addons */ ], // … };This ensures the viewport toolbar appears when you’ve set custom viewports under
parameters.viewport.
🧹 Nitpick comments (17)
packages/ui/src/components/button.stories.tsx (2)
14-16: Optional: add controls to make this story interactive.You can expose Button props via args for quick ad‑hoc testing in Canvas.
export const AllVariants: Story = { - args: {}, + args: { size: "default", variant: "primary" }, };
3-3: Ensure Storybook resolves the@alias in the UI packageWe verified that
packages/ui/tsconfig.jsondefines"baseUrl": ".", "paths": { "@/*": ["./src/*"] }but the Storybook config at
packages/ui/.storybook/main.tsdoes not include anywebpackFinalhook,resolve.aliasoverride, or use ofTsconfigPathsPlugin. Without this, imports likeimport { Button } from "@/components/button";will not be resolved by Storybook and will cause build failures.
Please address this by choosing one of the following options:
• Option A – Wire up tsconfig paths in Storybook’s webpack config
- Install the plugin:
npm install --save-dev tsconfig-paths-webpack-plugin- Update
packages/ui/.storybook/main.tsto include awebpackFinalhook:import { dirname, join } from "node:path"; import type { StorybookConfig } from "@storybook/nextjs";
import TsconfigPathsPlugin from "tsconfig-paths-webpack-plugin";
function getAbsolutePath(value: string): string {
return dirname(require.resolve(join(value, "package.json")));
}const config: StorybookConfig = {
stories: ["../src/**/*.stories.tsx"],
addons: [
getAbsolutePath("@storybook/addon-onboarding"),
getAbsolutePath("@storybook/addon-links"),
getAbsolutePath("@chromatic-com/storybook"),
getAbsolutePath("@storybook/addon-docs"),
],
framework: {
name: getAbsolutePath("@storybook/nextjs"),
options: {},
},webpackFinal: async (storybookConfig) => {storybookConfig.resolve = storybookConfig.resolve || {};storybookConfig.resolve.plugins = [...(storybookConfig.resolve.plugins || []),new TsconfigPathsPlugin({configFile: path.resolve(__dirname, "../tsconfig.json"),}),];return storybookConfig;}, features: { experimentalRSC: true, },};
export default config;• Option B – Convert the story to use a relative import:
— packages/ui/src/components/button.stories.tsx import React from "react"; - import { Button } from "@/components/button"; + import { Button } from "./button"; export default { component: Button, title: "Components/Button", };packages/ui/.storybook/main.ts (2)
14-19: Add viewport and controls addons to match preview parameters.preview.tsx configures custom viewports and controls. Without these addons, the toolbar panels won’t appear.
addons: [ getAbsolutePath("@storybook/addon-onboarding"), getAbsolutePath("@storybook/addon-links"), getAbsolutePath("@chromatic-com/storybook"), - getAbsolutePath("@storybook/addon-docs"), + getAbsolutePath("@storybook/addon-docs"), + getAbsolutePath("@storybook/addon-controls"), + getAbsolutePath("@storybook/addon-viewport"), ],
1-10: Suggestion: Add ESM-saferequireonly if/when migrating to ESMThe
packages/ui/.storybook/main.tsfile currently uses CommonJSrequire, and neither the root norpackages/uipackage.json declares"type": "module", sorequireis available today. If and when you convert this package (or the repo) to ESM, plainrequirewill break at runtime. At that point, you can switch tocreateRequireto preserverequire.resolvebehavior:• File:
packages/ui/.storybook/main.ts
• Snippet:import { dirname, join } from "node:path"; +import { createRequire } from "node:module"; +const require = createRequire(import.meta.url); /** * This function is used to resolve the absolute path of a package. * It is needed in projects that use Yarn PnP or are set up within a monorepo. */ function getAbsolutePath(value: string): string { return dirname(require.resolve(join(value, "package.json"))); }No change is strictly needed now—keep using CommonJS
requireuntil you adopt ESM. When you do, apply the above diff to ensurerequire.resolvecontinues to work.apps/dashboard/.storybook/preview.tsx (1)
74-76: Avoid overwriting body className; append classes instead.Overwriting can drop classes added by Storybook/addons. Append to classList to keep other body classes.
- useEffect(() => { - document.body.className = `font-sans antialiased ${fontSans.variable}`; - }, []); + useEffect(() => { + document.body.classList.add("font-sans", "antialiased"); + // fontSans.variable is already a class name like `__className_xyz` + document.body.classList.add(fontSans.variable); + return () => { + document.body.classList.remove("font-sans", "antialiased", fontSans.variable); + }; + }, []);packages/ui/src/components/input.tsx (2)
8-9: Default input type to "text".Avoids an undefined type and matches expected semantics.
- ({ className, type, ...props }, ref) => { + ({ className, type = "text", ...props }, ref) => {
4-6: Prefer a type alias over interface per guidelines.Semantically identical here and matches the codebase convention.
-export interface InputProps - extends React.InputHTMLAttributes<HTMLInputElement> {} +export type InputProps = React.InputHTMLAttributes<HTMLInputElement>;packages/ui/.storybook/preview.tsx (3)
12-13: Avoid React Query cache bleed between stories by scoping a fresh QueryClient per storyCreating a single module-level client shares cache across stories and can cause surprising results.
Refactor to create the client inside the decorator and remove the provider from StoryLayout:
-import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; @@ -const queryClient = new QueryClient(); +// QueryClient is created per-story in the decorator to avoid cache bleed. @@ decorators: [ (Story) => { - return ( - <ThemeProvider + const queryClient = new QueryClient({ + defaultOptions: { queries: { retry: false } }, + }); + return ( + <ThemeProvider attribute="class" disableTransitionOnChange enableSystem={false} defaultTheme="dark" > - <StoryLayout> - <Story /> - </StoryLayout> + <QueryClientProvider client={queryClient}> + <StoryLayout> + <Story /> + </StoryLayout> + </QueryClientProvider> </ThemeProvider> ); }, ], @@ - return ( - <QueryClientProvider client={queryClient}> - <div className="flex min-h-dvh min-w-0 flex-col bg-background text-foreground"> + return ( + <div className="flex min-h-dvh min-w-0 flex-col bg-background text-foreground"> @@ - </div> - </QueryClientProvider> + </div> );Also applies to: 51-66, 79-100
82-94: Nit: show the target theme icon and add a11y labelsImproves clarity and accessibility for the toggle.
Patch:
<Button onClick={() => setTheme(theme === "dark" ? "light" : "dark")} size="sm" variant="outline" className="h-auto w-auto shrink-0 rounded-full p-2" + aria-label={`Switch to ${theme === "dark" ? "light" : "dark"} theme`} + title={`Switch to ${theme === "dark" ? "light" : "dark"} theme`} > - {theme === "dark" ? ( - <MoonIcon className="size-4" /> - ) : ( - <SunIcon className="size-4" /> - )} + {theme === "dark" ? ( + <SunIcon className="size-4" /> + ) : ( + <MoonIcon className="size-4" /> + )} </Button>
71-71: Add explicit return types per repo TS guidelinesKeeps TS surfaces consistent across the UI package.
Apply:
-function StoryLayout(props: { children: React.ReactNode }) { +function StoryLayout(props: { children: React.ReactNode }): JSX.Element { @@ -function ToasterSetup() { +function ToasterSetup(): JSX.Element {Also applies to: 103-106
packages/ui/src/components/badge.tsx (1)
29-36: Prefer span for inline semanticsBadge is an inline element; span avoids unexpected block semantics in flow content.
-export interface BadgeProps - extends React.HTMLAttributes<HTMLDivElement>, +export interface BadgeProps + extends React.HTMLAttributes<HTMLSpanElement>, VariantProps<typeof badgeVariants> {} function Badge({ className, variant, ...props }: BadgeProps) { return ( - <div className={cn(badgeVariants({ variant }), className)} {...props} /> + <span className={cn(badgeVariants({ variant }), className)} {...props} /> ); }apps/dashboard/src/@/components/ui/badge.tsx (1)
1-1: Forward BadgeProps as a type for consistency.
Preempt type-only import regressions.export { Badge, badgeVariants } from "@workspace/ui/components/badge"; +export type { BadgeProps } from "@workspace/ui/components/badge";apps/playground-web/src/components/ui/badge.tsx (1)
1-1: Consider re-exporting BadgeProps for type consumers.
Keeps local import sites working if they pull BadgeProps from this path.export { Badge, badgeVariants } from "@workspace/ui/components/badge"; +export type { BadgeProps } from "@workspace/ui/components/badge";packages/ui/src/storybook/utils.tsx (3)
4-13: Add explicit return type to comply with TS guidelines.-function StoryBadge(props: { label: string }) { +function StoryBadge(props: { label: string }): JSX.Element {
27-33: Rename mesages -> messages and add return type.
Tiny typo; makes logs clearer and satisfies explicit return types.-export function storybookLog(...mesages: unknown[]) { - console.debug( +export function storybookLog(...messages: unknown[]): void { + console.debug( "%cStorybook", "color: white; background-color: black; padding: 2px 4px; border-radius: 4px;", - ...mesages, + ...messages, ); }
1-1: Import ReactNode and add explicit return typeConfirmed that packages/ui/tsconfig.json uses
"jsx": "preserve", so TypeScript won’t automatically provide a globalReactnamespace for types. It’s therefore best to import theReactNodetype explicitly and annotate the function’s return type.Please update in
packages/ui/src/storybook/utils.tsx:
- At the top of the file, add:
import type { ReactNode } from "react";- Change the
BadgeContainersignature (also applies to lines 15–18):+import type { ReactNode } from "react"; @@ -export function BadgeContainer(props: { - label: string; - children: React.ReactNode; -}) { +export function BadgeContainer( + props: { label: string; children: ReactNode }, +): JSX.Element {This makes the component’s props and return type explicit and avoids potential TS errors around the
Reactnamespace.packages/ui/package.json (1)
16-29: Right-sizeuideps for optimal bundle
All Storybook-only packages can live indevDependencies, and shared libs should be peers to prevent duplicate bundles.• packages/ui/package.json (dependencies → devDependencies/peerDependencies)
"dependencies": { "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-slot": "^1.2.3", - "@tanstack/react-query": "5.81.5", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "lucide-react": "0.525.0", - "next": "15.3.5", - "next-themes": "^0.4.6", - "sonner": "2.0.6", "tailwind-merge": "^2.6.0", - "tailwindcss-animate": "^1.0.7", - "thirdweb": "workspace:*" + "tailwindcss-animate": "^1.0.7" }, "peerDependencies": { + "lucide-react": "^0.525.0", + "next": ">=14 <16", "react": "^19.0.0", "react-dom": "^19.0.0" }, "devDependencies": { "@chromatic-com/storybook": "4.0.1", "@storybook/addon-docs": "9.0.15", "@storybook/addon-links": "9.0.15", "@storybook/addon-onboarding": "9.0.15", "@storybook/nextjs": "9.0.15", + "@tanstack/react-query": "5.81.5", "@types/react": "19.1.8", "@types/react-dom": "19.1.6", "autoprefixer": "^10.4.21", "postcss": "8.5.6", "storybook": "9.0.15", "tailwindcss": "3.4.17", "typescript": "5.8.3", + "thirdweb": "workspace:*", + "next-themes": "^0.4.6", + "sonner": "2.0.6", + "next": "15.3.5" }• Verified no runtime imports of thirdweb, react-query, next-themes, sonner, or next outside Storybook code.
📜 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 (15)
apps/dashboard/.storybook/preview.tsx(2 hunks)apps/dashboard/src/@/components/ui/badge.tsx(1 hunks)apps/dashboard/src/@/components/ui/input.tsx(1 hunks)apps/playground-web/src/components/ui/badge.tsx(1 hunks)apps/playground-web/src/components/ui/input.tsx(1 hunks)apps/portal/src/components/ui/badge.tsx(1 hunks)apps/portal/src/components/ui/input.tsx(1 hunks)packages/ui/.storybook/main.ts(1 hunks)packages/ui/.storybook/preview.tsx(1 hunks)packages/ui/package.json(1 hunks)packages/ui/src/components/badge.tsx(1 hunks)packages/ui/src/components/button.stories.tsx(1 hunks)packages/ui/src/components/input.tsx(1 hunks)packages/ui/src/storybook/utils.tsx(1 hunks)packages/ui/tailwind.config.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{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/tailwind.config.tspackages/ui/src/components/input.tsxpackages/ui/src/components/button.stories.tsxpackages/ui/src/storybook/utils.tsxapps/portal/src/components/ui/input.tsxapps/dashboard/src/@/components/ui/input.tsxapps/dashboard/src/@/components/ui/badge.tsxapps/playground-web/src/components/ui/badge.tsxpackages/ui/src/components/badge.tsxapps/playground-web/src/components/ui/input.tsxapps/portal/src/components/ui/badge.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
packages/ui/tailwind.config.tspackages/ui/src/components/input.tsxpackages/ui/src/components/button.stories.tsxpackages/ui/src/storybook/utils.tsxapps/portal/src/components/ui/input.tsxapps/dashboard/src/@/components/ui/input.tsxapps/dashboard/src/@/components/ui/badge.tsxapps/playground-web/src/components/ui/badge.tsxpackages/ui/src/components/badge.tsxapps/playground-web/src/components/ui/input.tsxapps/portal/src/components/ui/badge.tsx
**/*.stories.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
For new UI components, add Storybook stories (
*.stories.tsx) alongside the code
Files:
packages/ui/src/components/button.stories.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/@/components/ui/input.tsxapps/dashboard/src/@/components/ui/badge.tsxapps/playground-web/src/components/ui/badge.tsxapps/playground-web/src/components/ui/input.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: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/wallets/page.tsx:1-1
Timestamp: 2025-08-20T10:37:10.123Z
Learning: In apps/dashboard, prefer importing UI components from "workspace/ui/components/*" where possible, as per jnsdls preference, rather than from "@/components/ui/*".
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.stories.tsx : For new UI components, add Storybook stories (`*.stories.tsx`) alongside the code
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`.
📚 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 **/*.stories.tsx : For new UI components, add Storybook stories (`*.stories.tsx`) alongside the code
Applied to files:
packages/ui/.storybook/main.tspackages/ui/tailwind.config.tspackages/ui/src/components/button.stories.tsxpackages/ui/src/storybook/utils.tsxpackages/ui/.storybook/preview.tsxapps/dashboard/.storybook/preview.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/*.{stories,test}.{tsx,ts} : Provide a Storybook story (`MyComponent.stories.tsx`) or unit test alongside the component.
Applied to files:
packages/ui/.storybook/main.tspackages/ui/tailwind.config.tspackages/ui/src/components/button.stories.tsxpackages/ui/.storybook/preview.tsxapps/dashboard/.storybook/preview.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:
packages/ui/tailwind.config.tsapps/dashboard/.storybook/preview.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.stories.tsxapps/dashboard/src/@/components/ui/input.tsxapps/playground-web/src/components/ui/input.tsxapps/dashboard/.storybook/preview.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Import UI primitives from `@/components/ui/*` (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Applied to files:
packages/ui/src/components/button.stories.tsxapps/portal/src/components/ui/input.tsxapps/dashboard/src/@/components/ui/input.tsxapps/dashboard/src/@/components/ui/badge.tsxapps/playground-web/src/components/ui/badge.tsxapps/playground-web/src/components/ui/input.tsxapps/portal/src/components/ui/badge.tsxapps/dashboard/.storybook/preview.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:
packages/ui/src/storybook/utils.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:
apps/portal/src/components/ui/input.tsxapps/dashboard/src/@/components/ui/input.tsxapps/playground-web/src/components/ui/input.tsx
📚 Learning: 2025-08-20T10:37:10.123Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/wallets/page.tsx:1-1
Timestamp: 2025-08-20T10:37:10.123Z
Learning: In apps/dashboard, prefer importing UI components from "workspace/ui/components/*" where possible, as per jnsdls preference, rather than from "@/components/ui/*".
Applied to files:
apps/dashboard/src/@/components/ui/input.tsxapps/dashboard/.storybook/preview.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/input.tsxapps/dashboard/src/@/components/ui/badge.tsxapps/dashboard/.storybook/preview.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/.storybook/preview.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/.storybook/preview.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/.storybook/preview.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Use React Query (`tanstack/react-query`) for all client data fetching.
Applied to files:
apps/dashboard/.storybook/preview.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/.storybook/preview.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} : Wrap client-side data fetching calls in React Query (`tanstack/react-query`)
Applied to files:
apps/dashboard/.storybook/preview.tsx
🧬 Code graph analysis (1)
packages/ui/src/storybook/utils.tsx (3)
packages/ui/src/components/badge.tsx (1)
Badge(39-39)packages/thirdweb/test/src/test-clients.js (1)
clientId(3-3)packages/thirdweb/src/exports/thirdweb.ts (1)
createThirdwebClient(24-24)
⏰ 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). (2)
- GitHub Check: Size
- GitHub Check: Analyze (javascript)
🔇 Additional comments (13)
packages/ui/tailwind.config.ts (1)
8-8: LGTM: include Storybook files in Tailwind content scan.This prevents missing classes in stories. No further action.
apps/dashboard/.storybook/preview.tsx (1)
2-5: Good: imports centralized to workspace UI.Imports align with the workspace convention (per jnsdls preference), reducing duplication across apps.
packages/ui/src/components/input.tsx (2)
7-21: LGTM overall.ForwardRef typing, class merge via cn, and export are solid.
2-2: Alias Configuration Verified – Please Test Storybook Import Resolution
- packages/ui/tsconfig.json defines
• baseUrl: "."
• paths: { "@/": ["./src/"] }
(so the build will resolve@/lib/utilstopackages/ui/src/lib/utils.ts)- The
cnfunction is exported frompackages/ui/src/lib/utils.ts, and the file exists as expected- Storybook is configured in
packages/ui/.storybook/main.tsusing the Next.js framework adapter, but there’s no explicit webpack alias or tsconfig-paths plugin appliedPlease start Storybook locally and confirm that importing via
import { cn } from "@/lib/utils";does not error. If Storybook cannot resolve the@alias, add one of the following topackages/ui/.storybook/main.ts:• Use the
tsconfig-paths-webpack-plugin:import { TsconfigPathsPlugin } from 'tsconfig-paths-webpack-plugin'; export default { // … webpackFinal: async (config) => { + config.resolve.plugins = [ + ...(config.resolve.plugins || []), + new TsconfigPathsPlugin({ configFile: '../tsconfig.json' }), + ]; return config; }, };• Or switch to a relative import:
-import { cn } from "@/lib/utils"; +import { cn } from "../lib/utils";apps/dashboard/src/@/components/ui/input.tsx (1)
1-1: Add centralInputPropsre-exportTo preserve typing and allow downstream modules to import the props type alongside the component, add the following line to
apps/dashboard/src/@/components/ui/input.tsx. We’ve verified that no existing call sites importInputPropsfrom this file, so introducing the re-export is safe and non-breaking.export { Input } from "@workspace/ui/components/input"; +export type { InputProps } from "@workspace/ui/components/input";File to update:
- apps/dashboard/src/@/components/ui/input.tsx
apps/playground-web/src/components/ui/input.tsx (1)
1-1: Approve: Add InputProps re-exportNo existing references to
InputPropswere found inapps/playground-web(aside from the substring match inAggregateParameterInputProps), but exporting the type now ensures downstream stories/tests won’t break if they start importing it.• Diff remains unchanged:
export { Input } from "@workspace/ui/components/input"; +export type { InputProps } from "@workspace/ui/components/input";packages/ui/src/components/badge.tsx (2)
6-27: Good use of cva; variants and defaults read cleanlyVariant set looks sensible and tokens align with the design system.
4-4: Verify build setup for@/*alias or switch to relative import
- packages/ui/tsconfig.json defines
confirming that"compilerOptions": { "paths": { "@/*": ["./src/*"] } }@/lib/utilsresolves topackages/ui/src/lib/utils.ts.- The
cnhelper is exported frompackages/ui/src/lib/utils.ts.- In
packages/ui/src/components/badge.tsx, the import is currently:import { cn } from "@/lib/utils";TypeScript’s path alias is only used at compile time and does not rewrite import paths in the emitted JavaScript. Unless your build or bundler (e.g., Rollup/Vite with an alias plugin) is explicitly transforming
@/*imports into relative paths, the published package will contain imports from"@/lib/utils", which consumers cannot resolve.Please verify your build configuration. If your bundler does not handle this alias, update the import to a relative path:
- import { cn } from "@/lib/utils"; + import { cn } from "../lib/utils";apps/portal/src/components/ui/badge.tsx (1)
1-1: LGTM — centralized re-export keeps imports stable.
This aligns with the shared UI consolidation.apps/dashboard/src/@/components/ui/badge.tsx (1)
1-1: LGTM — matches our dashboard convention of importing from "@/components/ui/*".
Keeps the public surface unchanged while sourcing from the workspace.apps/playground-web/src/components/ui/badge.tsx (1)
1-1: LGTM — re-export pattern is consistent across apps.
No runtime logic; safe change.packages/ui/src/storybook/utils.tsx (2)
2-2: Alias import is valid – no change neededThe
packages/ui/tsconfig.jsonalready defines a local path mapping"paths": { "@/*": ["./src/*"] }so using
import { Badge } from "@/components/badge";resolves correctly in both Storybook and your build. You can safely ignore the suggested relative-import refactor.
Likely an incorrect or invalid review comment.
35-41: No changes required for optional lazy client creationA global search shows that
storybookThirdwebClientis imported in well over a hundred story files acrossapps/dashboard,apps/nebula, andpackages/ui. Converting the export to a lazy function would require updating every import site to callgetStorybookThirdwebClient()instead of referencingstorybookThirdwebClientdirectly. Given the high refactor cost and the fact that we configureNEXT_PUBLIC_STORYBOOK_TW_CLIENT_IDin our Storybook setup, it’s safe to keep the current import-time validation. We can revisit a lazy-creation refactor in the future if we encounter stories that don’t need the client and still fail due to missing env vars.
440fdce to
5ab3fe3
Compare
5ab3fe3 to
1f5ed60
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
🧹 Nitpick comments (3)
apps/dashboard/src/@/components/ui/input.tsx (2)
1-1: Optional: also re-export the prop type to avoid downstream type breaksIf consumers import
type InputPropsfrom this module, re-export it from the workspace package.Apply if
InputPropsis exported upstream:-export { Input } from "@workspace/ui/components/input"; +export { Input } from "@workspace/ui/components/input"; +export type { InputProps } from "@workspace/ui/components/input";
1-1: Gotcha: client boundary across re-exportsIf Next flags a “Client Component” import error through this wrapper, add
'use client';here to propagate the client boundary. Only do this if you hit the error to avoid widening the client graph.Proposed change (only if needed):
+'use client'; export { Input } from "@workspace/ui/components/input";packages/ui/src/components/button.stories.tsx (1)
33-59: Add aria-label for icon-only buttons (a11y).When
size="icon", the button has no accessible name. Add an aria-label to each icon-only usage.- <Button size={props.size}> + <Button size={props.size} aria-label={props.size === "icon" ? "Star" : undefined}> {props.size === "icon" ? <StarIcon className="size-4" /> : "Default"} </Button> - <Button size={props.size} variant="primary"> + <Button size={props.size} variant="primary" aria-label={props.size === "icon" ? "Star" : undefined}> {props.size === "icon" ? <StarIcon className="size-4" /> : "Primary"} </Button> - <Button size={props.size} variant="secondary"> + <Button size={props.size} variant="secondary" aria-label={props.size === "icon" ? "Star" : undefined}> {props.size === "icon" ? ( <StarIcon className="size-4" /> ) : ( "Secondary" )} </Button> - <Button size={props.size} variant="ghost"> + <Button size={props.size} variant="ghost" aria-label={props.size === "icon" ? "Star" : undefined}> {props.size === "icon" ? <StarIcon className="size-4" /> : "Ghost"} </Button> - <Button size={props.size} variant="outline"> + <Button size={props.size} variant="outline" aria-label={props.size === "icon" ? "Star" : undefined}> {props.size === "icon" ? <StarIcon className="size-4" /> : "Outline"} </Button> - <Button size={props.size} variant="destructive"> + <Button size={props.size} variant="destructive" aria-label={props.size === "icon" ? "Star" : undefined}> {props.size === "icon" ? ( <StarIcon className="size-4" /> ) : ( "Destructive" )} </Button>
📜 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 (16)
apps/dashboard/.storybook/preview.tsx(2 hunks)apps/dashboard/src/@/components/ui/badge.tsx(1 hunks)apps/dashboard/src/@/components/ui/input.tsx(1 hunks)apps/playground-web/src/components/ui/badge.tsx(1 hunks)apps/playground-web/src/components/ui/input.tsx(1 hunks)apps/portal/knip.json(1 hunks)apps/portal/src/components/ui/badge.tsx(1 hunks)apps/portal/src/components/ui/input.tsx(1 hunks)packages/ui/.storybook/main.ts(1 hunks)packages/ui/.storybook/preview.tsx(1 hunks)packages/ui/package.json(1 hunks)packages/ui/src/components/badge.tsx(1 hunks)packages/ui/src/components/button.stories.tsx(1 hunks)packages/ui/src/components/input.tsx(1 hunks)packages/ui/src/storybook/utils.tsx(1 hunks)packages/ui/tailwind.config.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (13)
- packages/ui/src/components/input.tsx
- packages/ui/src/storybook/utils.tsx
- packages/ui/.storybook/main.ts
- packages/ui/tailwind.config.ts
- apps/portal/src/components/ui/input.tsx
- apps/playground-web/src/components/ui/input.tsx
- packages/ui/.storybook/preview.tsx
- apps/dashboard/src/@/components/ui/badge.tsx
- apps/portal/src/components/ui/badge.tsx
- apps/playground-web/src/components/ui/badge.tsx
- packages/ui/src/components/badge.tsx
- packages/ui/package.json
- apps/dashboard/.storybook/preview.tsx
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{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/components/button.stories.tsxapps/dashboard/src/@/components/ui/input.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
packages/ui/src/components/button.stories.tsxapps/dashboard/src/@/components/ui/input.tsx
**/*.stories.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
For new UI components, add Storybook stories (
*.stories.tsx) alongside the code
Files:
packages/ui/src/components/button.stories.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/@/components/ui/input.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.
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/wallets/page.tsx:1-1
Timestamp: 2025-08-20T10:37:10.123Z
Learning: In apps/dashboard, prefer importing UI components from "workspace/ui/components/*" where possible, as per jnsdls preference, rather than from "@/components/ui/*".
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.stories.tsx : For new UI components, add Storybook stories (`*.stories.tsx`) alongside the code
📚 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/knip.json
📚 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 **/*.stories.tsx : For new UI components, add Storybook stories (`*.stories.tsx`) alongside the code
Applied to files:
packages/ui/src/components/button.stories.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Import UI primitives from `@/components/ui/*` (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Applied to files:
packages/ui/src/components/button.stories.tsxapps/dashboard/src/@/components/ui/input.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.stories.tsxapps/dashboard/src/@/components/ui/input.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/*.{stories,test}.{tsx,ts} : Provide a Storybook story (`MyComponent.stories.tsx`) or unit test alongside the component.
Applied to files:
packages/ui/src/components/button.stories.tsx
📚 Learning: 2025-08-20T10:37:10.123Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/wallets/page.tsx:1-1
Timestamp: 2025-08-20T10:37:10.123Z
Learning: In apps/dashboard, prefer importing UI components from "workspace/ui/components/*" where possible, as per jnsdls preference, rather than from "@/components/ui/*".
Applied to files:
apps/dashboard/src/@/components/ui/input.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/input.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:
apps/dashboard/src/@/components/ui/input.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Size
- GitHub Check: Build Packages
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: Lint Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (4)
apps/dashboard/src/@/components/ui/input.tsx (2)
1-1: LGTM: centralized re-export keeps the@/components/ui/*surface stableThis aligns with the dashboard guideline to import primitives via
@/components/ui/*while sourcing from the shared UI package.
1-1: No changes needed: @workspace/ui is already resolved and transpiledThe dashboard app installs
@workspace/uivia your Yarn workspace and relies on Node’s module resolution instead of custom TS path aliases, so nopathsentry is required intsconfig.json. Yourapps/dashboard/next.config.tsalready lists:transpilePackages: ["@workspace/ui"],which ensures the UI package is compiled by Next.js.
packages/ui/src/components/button.stories.tsx (1)
3-3: Confirm alias resolution in Storybook configuration
- packages/ui/tsconfig.json correctly maps
"@/*": ["./src/*"]to the UI source folder.- .storybook/main.ts (using the
@storybook/nextjsframework) has no explicit webpack alias or TsconfigPathsPlugin configured. Storybook will not automatically pick up your TSpathsmappings without one of these.Please verify (or add) one of the following in packages/ui/.storybook/main.ts to ensure
import { Button } from "@/components/button"resolves correctly:• Add a webpack alias:
import path from "path"; const config: StorybookConfig = { // …existing config… webpackFinal: async (config) => { config.resolve.alias = { ...(config.resolve.alias || {}), "@": path.resolve(__dirname, "../src"), }; return config; }, }; export default config;• Or register TsconfigPathsPlugin:
import { TsconfigPathsPlugin } from "tsconfig-paths-webpack-plugin"; const config: StorybookConfig = { // …existing config… webpackFinal: async (config) => { config.resolve.plugins = [ ...(config.resolve.plugins || []), new TsconfigPathsPlugin({ extensions: config.resolve.extensions }), ]; return config; }, }; export default config;This will prevent any path-resolution issues in your UI stories.
apps/portal/knip.json (1)
23-25: cva and tailwindcss-animate confirmed unused — safe to ignoreRipgrep across apps/portal found only entries in knip.json and package.json, and no direct imports in code or Tailwind config. Keeping them in the knip.json ignore list is correct.
1f5ed60 to
56a4ba2
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 (1)
packages/ui/.storybook/preview.tsx (1)
74-76: Don’t overwrite body.className; append and clean up insteadOverwriting can remove Storybook’s own classes and break theming/layout.
Apply:
- useEffect(() => { - document.body.className = `font-sans antialiased ${fontSans.variable}`; - }, []); + useEffect(() => { + const classes = ["font-sans", "antialiased", fontSans.variable]; + document.body.classList.add(...classes); + return () => { + document.body.classList.remove(...classes); + }; + }, [fontSans.variable]);
🧹 Nitpick comments (3)
packages/ui/src/storybook/utils.tsx (2)
26-31: Typo in parameter name; add explicit return typeMinor nit: rename
mesages→messages; declare return type.Apply:
-export function storybookLog(...mesages: unknown[]) { +export function storybookLog(...messages: unknown[]): void { console.debug( "%cStorybook", "color: white; background-color: black; padding: 2px 4px; border-radius: 4px;", - ...mesages, + ...messages, ); }
14-24: Optional: extract props type and explicit return types for exported APIsImproves DX and satisfies our TS guidelines.
Apply:
-export function BadgeContainer(props: { - label: string; - children: React.ReactNode; -}) { +export type BadgeContainerProps = { + label: string; + children: React.ReactNode; +}; + +export function BadgeContainer(props: BadgeContainerProps): JSX.Element {packages/ui/package.json (1)
16-28: Move Storybook-only dependencies to devDependenciesNone of the following packages is imported by any runtime code under
packages/ui/src/components(they only appear in.stories.tsx):
•@tanstack/react-query
•next
•next-themes
•sonner
•lucide-reactShifting them out of
dependencieskeeps the UI package lean and avoids unnecessary bloat or duplicate installs for consumers. Apply the diff below to move them intodevDependencies:--- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -16,12 +16,8 @@ "dependencies": { "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-slot": "^1.2.3", - "@tanstack/react-query": "5.81.5", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "lucide-react": "0.525.0", - "next": "15.3.5", - "next-themes": "^0.4.6", - "sonner": "2.0.6", "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7" }, @@ -37,6 +33,11 @@ "devDependencies": { + "@tanstack/react-query": "5.81.5", + "lucide-react": "0.525.0", + "next": "15.3.5", + "next-themes": "^0.4.6", + "sonner": "2.0.6", "@chromatic-com/storybook": "4.0.1", "@storybook/addon-docs": "9.0.15", "@storybook/addon-links": "9.0.15",
📜 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 (16)
apps/dashboard/.storybook/preview.tsx(2 hunks)apps/dashboard/src/@/components/ui/badge.tsx(1 hunks)apps/dashboard/src/@/components/ui/input.tsx(1 hunks)apps/playground-web/src/components/ui/badge.tsx(1 hunks)apps/playground-web/src/components/ui/input.tsx(1 hunks)apps/portal/knip.json(1 hunks)apps/portal/src/components/ui/badge.tsx(1 hunks)apps/portal/src/components/ui/input.tsx(1 hunks)packages/ui/.storybook/main.ts(1 hunks)packages/ui/.storybook/preview.tsx(1 hunks)packages/ui/package.json(1 hunks)packages/ui/src/components/badge.tsx(1 hunks)packages/ui/src/components/button.stories.tsx(1 hunks)packages/ui/src/components/input.tsx(1 hunks)packages/ui/src/storybook/utils.tsx(1 hunks)packages/ui/tailwind.config.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (12)
- packages/ui/.storybook/main.ts
- packages/ui/tailwind.config.ts
- apps/portal/src/components/ui/badge.tsx
- apps/playground-web/src/components/ui/badge.tsx
- apps/playground-web/src/components/ui/input.tsx
- apps/portal/knip.json
- apps/dashboard/src/@/components/ui/badge.tsx
- apps/dashboard/.storybook/preview.tsx
- apps/portal/src/components/ui/input.tsx
- packages/ui/src/components/button.stories.tsx
- packages/ui/src/components/input.tsx
- packages/ui/src/components/badge.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:
packages/ui/src/storybook/utils.tsxapps/dashboard/src/@/components/ui/input.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
packages/ui/src/storybook/utils.tsxapps/dashboard/src/@/components/ui/input.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/@/components/ui/input.tsx
🧠 Learnings (11)
📓 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: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.stories.tsx : For new UI components, add Storybook stories (`*.stories.tsx`) alongside the code
📚 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 **/*.stories.tsx : For new UI components, add Storybook stories (`*.stories.tsx`) alongside the code
Applied to files:
packages/ui/src/storybook/utils.tsxpackages/ui/.storybook/preview.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/*.{stories,test}.{tsx,ts} : Provide a Storybook story (`MyComponent.stories.tsx`) or unit test alongside the component.
Applied to files:
packages/ui/src/storybook/utils.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Add `className` to the root element of every component for external overrides.
Applied to files:
packages/ui/.storybook/preview.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Import UI primitives from `@/components/ui/*` (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Applied to files:
apps/dashboard/src/@/components/ui/input.tsx
📚 Learning: 2025-08-20T10:37:10.123Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/wallets/page.tsx:1-1
Timestamp: 2025-08-20T10:37:10.123Z
Learning: In apps/dashboard, prefer importing UI components from "workspace/ui/components/*" where possible, as per jnsdls preference, rather than from "@/components/ui/*".
Applied to files:
apps/dashboard/src/@/components/ui/input.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/input.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/input.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:
apps/dashboard/src/@/components/ui/input.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:
packages/ui/package.json
📚 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:
packages/ui/package.json
⏰ 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: Unit Tests
- GitHub Check: Size
- GitHub Check: Build Packages
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: Lint Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (2)
apps/dashboard/src/@/components/ui/input.tsx (1)
1-1: Add’use client’directive and re-exportInputPropsTo ensure this wrapper is treated as a Client Component and to preserve type imports, update
apps/dashboard/src/@/components/ui/input.tsxas follows. Although our search didn’t find any current imports ofInputProps, please verify manually in case there are references we missed.• File:
apps/dashboard/src/@/components/ui/input.tsx
• Change:+ 'use client'; + -export { Input } from "@workspace/ui/components/input"; +export { Input } from "@workspace/ui/components/input"; +export type { InputProps } from "@workspace/ui/components/input";• After applying, double-check imports across both dashboard and playground-web apps for any direct type references to
InputProps.packages/ui/.storybook/preview.tsx (1)
51-67: Preview decorator structure looks goodThemeProvider + layout wrapper pattern is solid for Storybook 9 + Next.js.
Merge activity
|
<!--
## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"
If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):
## Notes for the reviewer
Anything important to call out? Be sure to also clarify these in your comments.
## How to test
Unit tests, playground, etc.
-->
<!-- start pr-codex -->
---
## PR-Codex overview
This PR introduces several updates focused on enhancing the UI components, improving Storybook integration, and updating dependencies. It also refactors some components for better modularity and performance.
### Detailed summary
- Added `class-variance-authority` and updated `tailwindcss-animate` in `knip.json`.
- Updated `tailwind.config.ts` to include `.storybook` directory in content.
- Refactored imports for `Button` and `Input` components.
- Created `Badge` component and its variants in `badge.tsx`.
- Updated Storybook configuration in `.storybook/main.ts` and `preview.tsx`.
- Refactored `Input` components in multiple locations to use a shared implementation.
- Added `Toaster` setup in Storybook preview for better notifications.
- Updated dependencies in `package.json` and `pnpm-lock.yaml`.
> ✨ 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**
- Shared Badge and Input components added to the UI package and made available to apps.
- Themed Storybook for the UI library with mobile viewports, notifications, data-fetching context, and an in-app theme toggle.
- **Refactor**
- Apps now re-export Badge/Input from the shared UI package; story utilities and preview/layout centralized.
- **Chores**
- Storybook script and dependencies added, Tailwind content updated, and import paths standardized.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
56a4ba2 to
afd1150
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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/ui/src/components/input.tsx (1)
1-25: Add Storybook story for Input componentPer team guidelines, every new UI primitive must include a Storybook story (
*.stories.tsx). I didn’t find any existinginput.stories.tsxunderpackages/ui/src/components/—please add one.• Create a new file:
packages/ui/src/components/input.stories.tsx• Include a basic CSF3 setup with controls and variants for default, disabled, and invalid states. For example:
+ import React from 'react'; + import { Meta, Story } from '@storybook/react'; + import { Input, InputProps } from './input'; + + const meta: Meta<InputProps> = { + title: 'Components/Input', + component: Input, + argTypes: { + placeholder: { control: 'text' }, + disabled: { control: 'boolean' }, + 'aria-invalid': { control: 'boolean' }, + }, + }; + + export default meta; + + const Template: Story<InputProps> = (args) => <Input {...args} />; + + export const Default = Template.bind({}); + Default.args = { + placeholder: 'Type here…', + }; + + export const Disabled = Template.bind({}); + Disabled.args = { + disabled: true, + placeholder: 'Cannot type', + }; + + export const Invalid = Template.bind({}); + Invalid.args = { + placeholder: 'Error state', + 'aria-invalid': true, + };Let me know if you’d like any help setting up controls or knobs!
🧹 Nitpick comments (2)
packages/ui/src/components/input.tsx (2)
4-6: Prefer a type alias for props per guidelinesProject guideline prefers type aliases over interfaces for structural types.
-export interface InputProps - extends React.InputHTMLAttributes<HTMLInputElement> {} +export type InputProps = React.InputHTMLAttributes<HTMLInputElement>;
7-21: Default to type='text'Small DX win and parity with native default. Keeps intent explicit and avoids undefined drifting through.
-const Input = React.forwardRef<HTMLInputElement, InputProps>( - ({ className, type, ...props }, ref) => { +const Input = React.forwardRef<HTMLInputElement, InputProps>( + ({ className, type = "text", ...props }, ref) => {
📜 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 (16)
apps/dashboard/.storybook/preview.tsx(2 hunks)apps/dashboard/src/@/components/ui/badge.tsx(1 hunks)apps/dashboard/src/@/components/ui/input.tsx(1 hunks)apps/playground-web/src/components/ui/badge.tsx(1 hunks)apps/playground-web/src/components/ui/input.tsx(1 hunks)apps/portal/knip.json(1 hunks)apps/portal/src/components/ui/badge.tsx(1 hunks)apps/portal/src/components/ui/input.tsx(1 hunks)packages/ui/.storybook/main.ts(1 hunks)packages/ui/.storybook/preview.tsx(1 hunks)packages/ui/package.json(1 hunks)packages/ui/src/components/badge.tsx(1 hunks)packages/ui/src/components/button.stories.tsx(1 hunks)packages/ui/src/components/input.tsx(1 hunks)packages/ui/src/storybook/utils.tsx(1 hunks)packages/ui/tailwind.config.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (15)
- apps/portal/src/components/ui/badge.tsx
- apps/playground-web/src/components/ui/input.tsx
- apps/dashboard/src/@/components/ui/badge.tsx
- packages/ui/.storybook/main.ts
- packages/ui/tailwind.config.ts
- apps/portal/knip.json
- packages/ui/package.json
- apps/dashboard/src/@/components/ui/input.tsx
- packages/ui/src/storybook/utils.tsx
- apps/portal/src/components/ui/input.tsx
- apps/playground-web/src/components/ui/badge.tsx
- packages/ui/.storybook/preview.tsx
- apps/dashboard/.storybook/preview.tsx
- packages/ui/src/components/badge.tsx
- packages/ui/src/components/button.stories.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{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/components/input.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
packages/ui/src/components/input.tsx
🧠 Learnings (1)
📓 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: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.stories.tsx : For new UI components, add Storybook stories (`*.stories.tsx`) alongside the code
⏰ 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). (2)
- GitHub Check: Size
- GitHub Check: Analyze (javascript)
🔇 Additional comments (2)
packages/ui/src/components/input.tsx (2)
10-18: LGTM: forwardRef + class merge are correct
- Correct ref typing and displayName.
- cn merge order allows consumer overrides; focus-visible/ring/disabled states are sensible.
1-2: Review alias usage in published UI package buildI ran a local check in
packages/uiand found no evidence of an@/*alias being handled in this package:
packages/ui/tsconfig.jsondoes not define a"@/*"path alias.- No
tsup.config.*or other bundler config in this package mentionsalias,tsconfig-paths, oresbuildplugins.- The local Storybook setup (
.storybook/main.ts/preview.tsx) has no explicit alias resolution.Unless you have a root-level alias resolver that applies to this package’s build and Storybook, the import
-import { cn } from "@/lib/utils"; +import { cn } from "../lib/utils";will break for downstream consumers. Please either switch to the relative path above or configure alias resolution for both the package build and Storybook.

PR-Codex overview
This PR focuses on enhancing the UI components in the project by restructuring imports, adding new features, and improving configuration for Storybook, along with dependency updates.
Detailed summary
tailwind.config.tsto include.storybookcontent.ButtonandInputcomponents.Badgecomponent with variants.pnpm-lock.yamlfor new dependencies and versions.preview.tsxfor Storybook with a theme toggle feature.Summary by CodeRabbit
New Features
Refactor
Chores