Overview
Leveraging Shadcn UI effectively in a monorepo involves more than just adding components to individual apps. This lesson focuses on centralizing these components by moving them into your shared packages/ui workspace, ensuring consistency and reusability across all applications.
Key Points
-
Extract Shadcn Components to
packages/ui: Instead of letting Shadcn UI components live inapps/web/components/ui, move them to yourpackages/uidirectory. This makes them accessible to all applications. -
Adjust
components.json: When initializing Shadcn UI inpackages/ui, configurecomponents.jsonto place components in asrc/components/uipath within that package. -
Export from
packages/ui: Ensure that all shared Shadcn UI components are properly exported from yourpackages/uipackage'sindex.tsfile. -
Import in Next.js Apps: Your Next.js applications will now import these components from
@repo/uiinstead of their localcomponents/uidirectory. -
Consistent Theming: Maintain a single Tailwind CSS configuration (possibly in a shared
packages/configworkspace) that all applications and theuipackage can reference. This guarantees a consistent look and feel.
Quick Example
1. packages/ui/src/components/ui/button.tsx (moved from Next.js app):
typescript "use client"; import * as React from "react"; import { Slot } from "@radix-ui/react-slot"; import { cva } from "class-variance-authority"; import { cn } from "@repo/utils"; // Assuming @repo/utils for utility functions like cn
const buttonVariants = cva( "inline-flex ...", // Tailwind classes { /* variants */ } );
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> { asChild?: boolean; }
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( ({ className, variant, size, asChild = false, ...props }, ref) => { const Comp = asChild ?
Slot :
"button"; return ( <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} /> ); } ); Button.displayName = "Button";
export { Button, buttonVariants };
2. packages/ui/index.ts (export):
typescript export * from "./src/components/ui/button"; // ... other components
Summary
Centralizing Shadcn UI components in a shared packages/ui workspace is a powerful monorepo pattern. It enforces consistency, simplifies maintenance, and allows all applications to benefit from a single source of truth for their design system, all while retaining the full customizability of Shadcn UI.