Skip to content

Commit

Permalink
feat(monorepo): use tailwindcss v4 in monorepo example (#6724)
Browse files Browse the repository at this point in the history
* feat(monorepo): use tailwindcss v4 in monorepo example

* feat(shadcn): add monorepo tailwind detection

* feat: update default monorepo template

* fix: minor fixes

* chore(shadcn): changeset

* docs(www): update monorepo docs

* docs: updates

---------

Co-authored-by: shadcn <[email protected]>
  • Loading branch information
Kaikaikaifang and shadcn authored Mar 5, 2025
1 parent 3baef99 commit a3fe507
Show file tree
Hide file tree
Showing 19 changed files with 1,285 additions and 1,601 deletions.
5 changes: 5 additions & 0 deletions .changeset/cold-impalas-call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"shadcn": patch
---

support for version detection in monorepo
2 changes: 1 addition & 1 deletion apps/www/content/docs/components-json.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ See the <Link href="/docs/installation">installation section</Link> for how to s

### tailwind.config

Path to where your `tailwind.config.js` file is located.
Path to where your `tailwind.config.js` file is located. **For Tailwind CSS v4, leave this blank.**

```json title="components.json"
{
Expand Down
82 changes: 68 additions & 14 deletions apps/www/content/docs/monorepo.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,6 @@ title: Monorepo
description: Using shadcn/ui components and CLI in a monorepo.
---

<Callout>
**Note:** We're releasing monorepo support in the CLI as __experimental__.
Help us improve it by testing it out and sending feedback. If you have any
questions, please [reach out to
us](https://github.com/shadcn-ui/ui/discussions).
</Callout>

Until now, using shadcn/ui in a monorepo was a bit of a pain. You could add
components using the CLI, but you had to manage where the components
were installed and manually fix import paths.
Expand Down Expand Up @@ -47,6 +40,8 @@ and [Turborepo](https://turbo.build/repo/docs) as the build system.

Everything is set up for you, so you can start adding components to your project.

Note: The monorepo uses React 19 and Tailwind CSS v4.

### Add components to your project

To add components to your project, run the `add` command **in the path of your app**.
Expand Down Expand Up @@ -118,7 +113,66 @@ turbo.json

2. The `components.json` file must properly define aliases for the workspace. This tells the CLI how to import components, hooks, utilities, etc.

```json title="apps/web/components.json"
<Tabs defaultValue="v4">

<TabsList>
<TabsTrigger value="v4">Tailwind CSS v4</TabsTrigger>
<TabsTrigger value="v3">Tailwind CSS v3</TabsTrigger>
</TabsList>

<TabsContent value="v4">

```json showLineNumbers title="apps/web/components.json"
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "",
"css": "../../packages/ui/src/styles/globals.css",
"baseColor": "zinc",
"cssVariables": true
},
"iconLibrary": "lucide",
"aliases": {
"components": "@/components",
"hooks": "@/hooks",
"lib": "@/lib",
"utils": "@workspace/ui/lib/utils",
"ui": "@workspace/ui/components"
}
}
```

```json showLineNumbers title="packages/ui/components.json"
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/styles/globals.css",
"baseColor": "zinc",
"cssVariables": true
},
"iconLibrary": "lucide",
"aliases": {
"components": "@workspace/ui/components",
"utils": "@workspace/ui/lib/utils",
"hooks": "@workspace/ui/hooks",
"lib": "@workspace/ui/lib",
"ui": "@workspace/ui/components"
}
}
```

</TabsContent>

<TabsContent value="v3">

```json showLineNumbers title="apps/web/components.json"
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
Expand All @@ -141,7 +195,7 @@ turbo.json
}
```

```json title="packages/ui/components.json"
```json showLineNumbers title="packages/ui/components.json"
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
Expand All @@ -164,12 +218,12 @@ turbo.json
}
```

3. Ensure you have the same `style`, `iconLibrary` and `baseColor` in both `components.json` files.
</TabsContent>

By following these requirements, the CLI will be able to install ui components, blocks, libs and hooks to the correct paths and handle imports for you.
</Tabs>

## Help us improve monorepo support
3. Ensure you have the same `style`, `iconLibrary` and `baseColor` in both `components.json` files.

We're releasing monorepo support in the CLI as **experimental**. Help us improve it by testing it out and sending feedback.
4. **For Tailwind CSS v4, leave the `tailwind` config empty in the `components.json` file.**

If you have any questions, please reach out to us on [GitHub Discussions](https://github.com/shadcn-ui/ui/discussions).
By following these requirements, the CLI will be able to install ui components, blocks, libs and hooks to the correct paths and handle imports for you.
10 changes: 9 additions & 1 deletion packages/shadcn/src/utils/get-project-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,15 @@ export async function getProjectInfo(cwd: string): Promise<ProjectInfo | null> {
export async function getTailwindVersion(
cwd: string
): Promise<ProjectInfo["tailwindVersion"]> {
const packageInfo = getPackageInfo(cwd)
const [packageInfo, config] = await Promise.all([
getPackageInfo(cwd),
getConfig(cwd),
])

// If the config file is empty, we can assume that it's a v4 project.
if (config?.tailwind?.config === "") {
return "v4"
}

if (
!packageInfo?.dependencies?.tailwindcss &&
Expand Down
6 changes: 4 additions & 2 deletions packages/shadcn/src/utils/transformers/transform-import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ export const transformImport: Transformer = async ({
importDeclaration.setModuleSpecifier(moduleSpecifier)

// Replace `import { cn } from "@/lib/utils"`
if (utilsImport === moduleSpecifier) {
if (utilsImport === moduleSpecifier || moduleSpecifier === "@/lib/utils") {
const namedImports = importDeclaration.getNamedImports()
const cnImport = namedImports.find((i) => i.getName() === "cn")
if (cnImport) {
importDeclaration.setModuleSpecifier(
moduleSpecifier.replace(utilsImport, config.aliases.utils)
utilsImport === moduleSpecifier
? moduleSpecifier.replace(utilsImport, config.aliases.utils)
: config.aliases.utils
)
}
}
Expand Down
4 changes: 2 additions & 2 deletions templates/monorepo-next/apps/web/components.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"rsc": true,
"tsx": true,
"tailwind": {
"config": "../../packages/ui/tailwind.config.ts",
"config": "",
"css": "../../packages/ui/src/styles/globals.css",
"baseColor": "zinc",
"baseColor": "neutral",
"cssVariables": true
},
"iconLibrary": "lucide",
Expand Down
18 changes: 9 additions & 9 deletions templates/monorepo-next/apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,24 @@
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "next lint",
"lint:fix": "next lint --fix",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@workspace/ui": "workspace:*",
"lucide-react": "0.456.0",
"next-themes": "^0.4.3",
"next": "^15.1.0",
"lucide-react": "^0.475.0",
"next": "^15.2.0",
"next-themes": "^0.4.4",
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "18.3.0",
"@types/react-dom": "18.3.1",
"@types/react": "^19",
"@types/react-dom": "^19",
"@workspace/eslint-config": "workspace:^",
"@workspace/typescript-config": "workspace:*",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"typescript": "^5"
"typescript": "^5.7.3"
}
}
1 change: 0 additions & 1 deletion templates/monorepo-next/apps/web/tailwind.config.ts

This file was deleted.

2 changes: 1 addition & 1 deletion templates/monorepo-next/apps/web/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
},
"include": [
"next-env.d.ts",
"next.config.mjs",
"next.config.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts"
Expand Down
8 changes: 4 additions & 4 deletions templates/monorepo-next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
"devDependencies": {
"@workspace/eslint-config": "workspace:*",
"@workspace/typescript-config": "workspace:*",
"prettier": "^3.2.5",
"turbo": "^2.3.0",
"typescript": "5.5.4"
"prettier": "^3.5.1",
"turbo": "^2.4.2",
"typescript": "5.7.3"
},
"packageManager": "pnpm@9.12.3",
"packageManager": "pnpm@10.4.1",
"engines": {
"node": ">=20"
}
Expand Down
20 changes: 10 additions & 10 deletions templates/monorepo-next/packages/eslint-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@
"./react-internal": "./react-internal.js"
},
"devDependencies": {
"@next/eslint-plugin-next": "^15.1.0",
"@typescript-eslint/eslint-plugin": "^8.15.0",
"@typescript-eslint/parser": "^8.15.0",
"eslint": "^9.15.0",
"@next/eslint-plugin-next": "^15.1.7",
"@typescript-eslint/eslint-plugin": "^8.24.1",
"@typescript-eslint/parser": "^8.24.1",
"eslint": "^9.20.1",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-only-warn": "^1.1.0",
"eslint-plugin-react": "^7.37.2",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-turbo": "^2.3.0",
"globals": "^15.12.0",
"typescript": "^5.3.3",
"typescript-eslint": "^8.15.0"
"eslint-plugin-react": "^7.37.4",
"eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-turbo": "^2.4.2",
"globals": "^15.15.0",
"typescript": "^5.7.3",
"typescript-eslint": "^8.24.1"
}
}
4 changes: 2 additions & 2 deletions templates/monorepo-next/packages/ui/components.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"config": "",
"css": "src/styles/globals.css",
"baseColor": "zinc",
"baseColor": "neutral",
"cssVariables": true
},
"iconLibrary": "lucide",
Expand Down
29 changes: 13 additions & 16 deletions templates/monorepo-next/packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,31 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
"@radix-ui/react-slot": "^1.1.1",
"class-variance-authority": "^0.7.0",
"@radix-ui/react-slot": "^1.1.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "0.456.0",
"next-themes": "^0.4.3",
"lucide-react": "^0.475.0",
"next-themes": "^0.4.4",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"tailwind-merge": "^2.5.4",
"tailwind-merge": "^3.0.1",
"tailwindcss-animate": "^1.0.7",
"zod": "^3.23.8"
"zod": "^3.24.2"
},
"devDependencies": {
"@turbo/gen": "^2.2.3",
"@types/node": "^22.9.0",
"@types/react": "18.3.0",
"@types/react-dom": "18.3.1",
"@tailwindcss/postcss": "^4.0.8",
"@turbo/gen": "^2.4.2",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"@workspace/eslint-config": "workspace:*",
"@workspace/typescript-config": "workspace:*",
"autoprefixer": "^10.4.20",
"postcss": "^8.4.47",
"react": "^18.3.1",
"tailwindcss": "^3.4.14",
"typescript": "^5.6.3"
"tailwindcss": "^4.0.8",
"typescript": "^5.7.3"
},
"exports": {
"./globals.css": "./src/styles/globals.css",
"./postcss.config": "./postcss.config.mjs",
"./tailwind.config": "./tailwind.config.ts",
"./lib/*": "./src/lib/*.ts",
"./components/*": "./src/components/*.tsx",
"./hooks/*": "./src/hooks/*.ts"
Expand Down
7 changes: 2 additions & 5 deletions templates/monorepo-next/packages/ui/postcss.config.mjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
plugins: { "@tailwindcss/postcss": {} },
};

export default config;
export default config;
Loading

0 comments on commit a3fe507

Please sign in to comment.