mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-06-16 12:21:35 +00:00
Compare commits
15 Commits
shadcn@2.0
...
shadcn@2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cfba3fdf70 | ||
|
|
4e4118f3cf | ||
|
|
faa7a67fb3 | ||
|
|
701e1160ea | ||
|
|
f5931f8d09 | ||
|
|
5a28937c6e | ||
|
|
0b74059d38 | ||
|
|
fab9877586 | ||
|
|
0f7591f67c | ||
|
|
81c7e44863 | ||
|
|
2fac3e40c2 | ||
|
|
5ad11ff851 | ||
|
|
6b92dd8eaf | ||
|
|
84540f551d | ||
|
|
99588fff8f |
13
apps/www/__registry__/default/block/login-01/page.tsx
Normal file
13
apps/www/__registry__/default/block/login-01/page.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { LoginForm } from "@/registry/default/block/login-01/components/login-form"
|
||||
|
||||
export const iframeHeight = "870px"
|
||||
|
||||
export const containerClassName = "w-full h-full"
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<div className="flex h-screen w-full items-center justify-center px-4">
|
||||
<LoginForm />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
25
apps/www/__registry__/default/block/sidebar-01/page.tsx
Normal file
25
apps/www/__registry__/default/block/sidebar-01/page.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import { AppSidebar } from "@/registry/default/block/sidebar-01/components/app-sidebar"
|
||||
import {
|
||||
SidebarLayout,
|
||||
SidebarTrigger,
|
||||
} from "@/registry/default/block/sidebar-01/ui/sidebar"
|
||||
|
||||
export const iframeHeight = "870px"
|
||||
|
||||
export const containerClassName = "w-full h-full"
|
||||
|
||||
export default async function Page() {
|
||||
const { cookies } = await import("next/headers")
|
||||
return (
|
||||
<SidebarLayout
|
||||
defaultOpen={cookies().get("sidebar:state")?.value === "true"}
|
||||
>
|
||||
<AppSidebar />
|
||||
<main className="flex flex-1 flex-col p-2 transition-all duration-300 ease-in-out">
|
||||
<div className="h-full rounded-md border-2 border-dashed p-2">
|
||||
<SidebarTrigger />
|
||||
</div>
|
||||
</main>
|
||||
</SidebarLayout>
|
||||
)
|
||||
}
|
||||
@@ -2145,7 +2145,7 @@ export const Index: Record<string, any> = {
|
||||
registryDependencies: ["avatar","button","collapsible","dropdown-menu","drawer","separator","input","popover","sheet","progress","card","use-mobile"],
|
||||
files: ["registry/new-york/block/sidebar-01/page.tsx","registry/new-york/block/sidebar-01/components/app-sidebar.tsx","registry/new-york/block/sidebar-01/components/nav-main.tsx","registry/new-york/block/sidebar-01/components/nav-projects.tsx","registry/new-york/block/sidebar-01/components/nav-secondary.tsx","registry/new-york/block/sidebar-01/components/nav-user.tsx","registry/new-york/block/sidebar-01/components/storage-card.tsx","registry/new-york/block/sidebar-01/components/team-switcher.tsx","registry/new-york/block/sidebar-01/hooks/use-sidebar.tsx","registry/new-york/block/sidebar-01/ui/sidebar.tsx"],
|
||||
component: React.lazy(() => import("@/registry/new-york/block/sidebar-01/page.tsx")),
|
||||
source: "__registry__/new-york/block/sidebar-01.tsx",
|
||||
source: "__registry__/new-york/block/sidebar-01/page.tsx",
|
||||
category: "Application",
|
||||
subcategory: "Dashboard",
|
||||
chunks: []
|
||||
@@ -2156,7 +2156,7 @@ export const Index: Record<string, any> = {
|
||||
registryDependencies: ["button","card","input","label"],
|
||||
files: ["registry/new-york/block/login-01/page.tsx","registry/new-york/block/login-01/components/login-form.tsx"],
|
||||
component: React.lazy(() => import("@/registry/new-york/block/login-01/page.tsx")),
|
||||
source: "__registry__/new-york/block/login-01.tsx",
|
||||
source: "__registry__/new-york/block/login-01/page.tsx",
|
||||
category: "Authentication",
|
||||
subcategory: "Login",
|
||||
chunks: []
|
||||
@@ -5501,7 +5501,7 @@ export const Index: Record<string, any> = {
|
||||
registryDependencies: ["avatar","button","collapsible","dropdown-menu","drawer","separator","input","popover","sheet","progress","card","use-mobile"],
|
||||
files: ["registry/default/block/sidebar-01/page.tsx","registry/default/block/sidebar-01/components/app-sidebar.tsx","registry/default/block/sidebar-01/components/nav-main.tsx","registry/default/block/sidebar-01/components/nav-projects.tsx","registry/default/block/sidebar-01/components/nav-secondary.tsx","registry/default/block/sidebar-01/components/nav-user.tsx","registry/default/block/sidebar-01/components/storage-card.tsx","registry/default/block/sidebar-01/components/team-switcher.tsx","registry/default/block/sidebar-01/hooks/use-sidebar.tsx","registry/default/block/sidebar-01/ui/sidebar.tsx"],
|
||||
component: React.lazy(() => import("@/registry/default/block/sidebar-01/page.tsx")),
|
||||
source: "__registry__/default/block/sidebar-01.tsx",
|
||||
source: "__registry__/default/block/sidebar-01/page.tsx",
|
||||
category: "Application",
|
||||
subcategory: "Dashboard",
|
||||
chunks: []
|
||||
@@ -5512,7 +5512,7 @@ export const Index: Record<string, any> = {
|
||||
registryDependencies: ["button","card","input","label"],
|
||||
files: ["registry/default/block/login-01/page.tsx","registry/default/block/login-01/components/login-form.tsx"],
|
||||
component: React.lazy(() => import("@/registry/default/block/login-01/page.tsx")),
|
||||
source: "__registry__/default/block/login-01.tsx",
|
||||
source: "__registry__/default/block/login-01/page.tsx",
|
||||
category: "Authentication",
|
||||
subcategory: "Login",
|
||||
chunks: []
|
||||
|
||||
13
apps/www/__registry__/new-york/block/login-01/page.tsx
Normal file
13
apps/www/__registry__/new-york/block/login-01/page.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { LoginForm } from "@/registry/new-york/block/login-01/components/login-form"
|
||||
|
||||
export const iframeHeight = "870px"
|
||||
|
||||
export const containerClassName = "w-full h-full"
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<div className="flex h-screen w-full items-center justify-center px-4">
|
||||
<LoginForm />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
25
apps/www/__registry__/new-york/block/sidebar-01/page.tsx
Normal file
25
apps/www/__registry__/new-york/block/sidebar-01/page.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import { AppSidebar } from "@/registry/new-york/block/sidebar-01/components/app-sidebar"
|
||||
import {
|
||||
SidebarLayout,
|
||||
SidebarTrigger,
|
||||
} from "@/registry/new-york/block/sidebar-01/ui/sidebar"
|
||||
|
||||
export const iframeHeight = "870px"
|
||||
|
||||
export const containerClassName = "w-full h-full"
|
||||
|
||||
export default async function Page() {
|
||||
const { cookies } = await import("next/headers")
|
||||
return (
|
||||
<SidebarLayout
|
||||
defaultOpen={cookies().get("sidebar:state")?.value === "true"}
|
||||
>
|
||||
<AppSidebar />
|
||||
<main className="flex flex-1 flex-col p-2 transition-all duration-300 ease-in-out">
|
||||
<div className="h-full rounded-md border-2 border-dashed p-2">
|
||||
<SidebarTrigger />
|
||||
</div>
|
||||
</main>
|
||||
</SidebarLayout>
|
||||
)
|
||||
}
|
||||
@@ -5,7 +5,10 @@ import { ThemesSwitcher } from "@/components/themes-selector"
|
||||
|
||||
export default async function BlocksPage() {
|
||||
const blocks = (await getAllBlockIds()).filter(
|
||||
(name) => !name.startsWith("chart-")
|
||||
(name) =>
|
||||
!name.startsWith("chart-") &&
|
||||
!name.startsWith("sidebar-01") &&
|
||||
!name.startsWith("login-01")
|
||||
)
|
||||
|
||||
// These themes are not compatible with the blocks yet.
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Separator } from "@/registry/new-york/ui/separator"
|
||||
export function Announcement() {
|
||||
return (
|
||||
<Link
|
||||
href="/docs/components/chart"
|
||||
href="/docs/changelog"
|
||||
className="group inline-flex items-center px-0.5 text-sm font-medium"
|
||||
>
|
||||
<PieChart className="h-4 w-4" />{" "}
|
||||
|
||||
@@ -89,6 +89,46 @@ export const docsConfig: DocsConfig = {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Installation",
|
||||
items: [
|
||||
{
|
||||
title: "Next.js",
|
||||
href: "/docs/installation/next",
|
||||
items: [],
|
||||
},
|
||||
{
|
||||
title: "Vite",
|
||||
href: "/docs/installation/vite",
|
||||
items: [],
|
||||
},
|
||||
{
|
||||
title: "Remix",
|
||||
href: "/docs/installation/remix",
|
||||
items: [],
|
||||
},
|
||||
{
|
||||
title: "Astro",
|
||||
href: "/docs/installation/astro",
|
||||
items: [],
|
||||
},
|
||||
{
|
||||
title: "Laravel",
|
||||
href: "/docs/installation/laravel",
|
||||
items: [],
|
||||
},
|
||||
{
|
||||
title: "Gatsby",
|
||||
href: "/docs/installation/gatsby",
|
||||
items: [],
|
||||
},
|
||||
{
|
||||
title: "Manual",
|
||||
href: "/docs/installation/manual",
|
||||
items: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Components",
|
||||
items: [
|
||||
|
||||
@@ -5,7 +5,7 @@ description: Use the CLI to add components to your project.
|
||||
|
||||
<Callout>
|
||||
|
||||
**Note:** We just released a new `shadcn` CLI to make it easier to add components to your project. See the [changelog](/docs/changelog) for more information.
|
||||
**Note:** We just released a new `shadcn` CLI. See the [changelog](/docs/changelog) for more information.
|
||||
|
||||
</Callout>
|
||||
|
||||
|
||||
@@ -18,18 +18,12 @@ npm create astro@latest
|
||||
You will be asked a few questions to configure your project:
|
||||
|
||||
```txt showLineNumbers
|
||||
- Where should we create your new project?
|
||||
./your-app-name
|
||||
- How would you like to start your new project?
|
||||
Choose a starter template (or Empty)
|
||||
- Install dependencies?
|
||||
Yes
|
||||
- Do you plan to write TypeScript?
|
||||
Yes
|
||||
- How strict should TypeScript be?
|
||||
Strict
|
||||
- Initialize a new git repository? (optional)
|
||||
Yes/No
|
||||
- Where should we create your new project? ./your-app-name
|
||||
- How would you like to start your new project? Choose a template
|
||||
- Do you plan to write TypeScript? Yes
|
||||
- How strict should TypeScript be? Strict
|
||||
- Install dependencies? Yes
|
||||
- Initialize a new git repository? (optional) Yes/No
|
||||
```
|
||||
|
||||
### Add React to your project
|
||||
@@ -48,23 +42,47 @@ Answer `Yes` to all the question prompted by the CLI when installing React.
|
||||
|
||||
### Add Tailwind CSS to your project
|
||||
|
||||
Install Tailwind CSS using the Astro CLI:
|
||||
|
||||
```bash
|
||||
npx astro add tailwind
|
||||
```
|
||||
|
||||
<Callout className="mt-4">
|
||||
<Step>Create a `styles/globals.css` file in the `src` folder.</Step>
|
||||
|
||||
Answer `Yes` to all the question prompted by the CLI when installing Tailwind CSS.
|
||||
```css title="styles/globals.css" showLineNumbers
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
```
|
||||
|
||||
</Callout>
|
||||
<Step>Import the `globals.css` file</Step>
|
||||
|
||||
Import the `styles/globals.css` file in the `src/pages/index.astro` file:
|
||||
|
||||
```ts title="src/pages/index.astro" showLineNumbers
|
||||
---
|
||||
import '@/styles/globals.css'
|
||||
---
|
||||
```
|
||||
|
||||
<Step>Update `astro.config.mjs` and set `applyBaseStyles` to `false`</Step>
|
||||
|
||||
To prevent serving the Tailwind base styles twice, we need to tell Astro not to apply the base styles, since we already include them in our own `globals.css` file. To do this, set the `applyBaseStyles` config option for the tailwind plugin in `astro.config.mjs` to `false`.
|
||||
|
||||
```js title="astro.config.mjs" {3-5} showLineNumbers
|
||||
export default defineConfig({
|
||||
integrations: [
|
||||
tailwind({
|
||||
applyBaseStyles: false,
|
||||
}),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
### Edit tsconfig.json file
|
||||
|
||||
Add the following code to the `tsconfig.json` file to resolve paths:
|
||||
|
||||
```ts {4-9} showLineNumbers
|
||||
```ts title="tsconfig.json" {4-9} showLineNumbers
|
||||
{
|
||||
"compilerOptions": {
|
||||
// ...
|
||||
@@ -81,62 +99,12 @@ Add the following code to the `tsconfig.json` file to resolve paths:
|
||||
|
||||
### Run the CLI
|
||||
|
||||
Run the `shadcn-ui` init command to setup your project:
|
||||
Run the `shadcn` init command to setup your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init
|
||||
```
|
||||
|
||||
### Configure components.json
|
||||
|
||||
You will be asked a few questions to configure `components.json`:
|
||||
|
||||
```txt showLineNumbers
|
||||
Would you like to use TypeScript (recommended)? no / yes
|
||||
Which style would you like to use? › Default
|
||||
Which color would you like to use as base color? › Slate
|
||||
Where is your global CSS file? › › ./src/styles/globals.css
|
||||
Do you want to use CSS variables for colors? › no / yes
|
||||
Where is your tailwind.config.js located? › tailwind.config.mjs
|
||||
Configure the import alias for components: › @/components
|
||||
Configure the import alias for utils: › @/lib/utils
|
||||
Are you using React Server Components? › no
|
||||
```
|
||||
|
||||
### Import the globals.css file
|
||||
|
||||
Import the `globals.css` file in the `src/pages/index.astro` file:
|
||||
|
||||
```ts {2} showLineNumbers
|
||||
---
|
||||
import '@/styles/globals.css'
|
||||
---
|
||||
```
|
||||
|
||||
### Update astro tailwind config
|
||||
|
||||
To prevent serving the Tailwind base styles twice, we need to tell Astro not to apply the base styles, since we already include them in our own `globals.css` file. To do this, set the `applyBaseStyles` config option for the tailwind plugin in `astro.config.mjs` to `false`.
|
||||
|
||||
```ts {3-5} showLineNumbers
|
||||
export default defineConfig({
|
||||
integrations: [
|
||||
tailwind({
|
||||
applyBaseStyles: false,
|
||||
}),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
### Update tailwind.config.mjs
|
||||
|
||||
When running `npx shadcn@latest init`, your tailwind config for content will be overwritten. To fix this, change the `module.exports` to `export default` and the `content` section with the code below to your `tailwind.config.mjs` file:
|
||||
|
||||
```js {1-4} showLineNumbers
|
||||
export default {
|
||||
content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
|
||||
}
|
||||
```
|
||||
|
||||
### That's it
|
||||
|
||||
You can now start adding components to your project.
|
||||
|
||||
@@ -45,19 +45,6 @@ description: How to install dependencies and structure your app.
|
||||
</svg>
|
||||
<p className="font-medium mt-2">Remix</p>
|
||||
</LinkedCard>
|
||||
<LinkedCard href="/docs/installation/gatsby">
|
||||
<svg
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="w-10 h-10"
|
||||
fill="currentColor"
|
||||
>
|
||||
<title>Gatsby</title>
|
||||
<path d="M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.6 0 12 0zm0 2.571c3.171 0 5.915 1.543 7.629 3.858l-1.286 1.115C16.886 5.572 14.571 4.286 12 4.286c-3.343 0-6.171 2.143-7.286 5.143l9.857 9.857c2.486-.857 4.373-3 4.973-5.572h-4.115V12h6c0 4.457-3.172 8.228-7.372 9.17L2.83 9.944C3.772 5.743 7.543 2.57 12 2.57zm-9.429 9.6l9.344 9.258c-2.4-.086-4.801-.943-6.601-2.743-1.8-1.8-2.743-4.201-2.743-6.515z" />
|
||||
</svg>
|
||||
<p className="font-medium mt-2">Gatsby</p>
|
||||
</LinkedCard>
|
||||
<LinkedCard href="/docs/installation/astro">
|
||||
<svg
|
||||
role="img"
|
||||
@@ -86,6 +73,19 @@ description: How to install dependencies and structure your app.
|
||||
</svg>
|
||||
<p className="font-medium mt-2">Laravel</p>
|
||||
</LinkedCard>
|
||||
<LinkedCard href="/docs/installation/gatsby">
|
||||
<svg
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="w-10 h-10"
|
||||
fill="currentColor"
|
||||
>
|
||||
<title>Gatsby</title>
|
||||
<path d="M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.6 0 12 0zm0 2.571c3.171 0 5.915 1.543 7.629 3.858l-1.286 1.115C16.886 5.572 14.571 4.286 12 4.286c-3.343 0-6.171 2.143-7.286 5.143l9.857 9.857c2.486-.857 4.373-3 4.973-5.572h-4.115V12h6c0 4.457-3.172 8.228-7.372 9.17L2.83 9.944C3.772 5.743 7.543 2.57 12 2.57zm-9.429 9.6l9.344 9.258c-2.4-.086-4.801-.943-6.601-2.743-1.8-1.8-2.743-4.201-2.743-6.515z" />
|
||||
</svg>
|
||||
<p className="font-medium mt-2">Gatsby</p>
|
||||
</LinkedCard>
|
||||
<LinkedCard href="/docs/installation/manual">
|
||||
<svg
|
||||
role="img"
|
||||
|
||||
@@ -15,7 +15,7 @@ laravel new my-app --typescript --breeze --stack=react --git --no-interaction
|
||||
|
||||
### Run the CLI
|
||||
|
||||
Run the `shadcn-ui` init command to setup your project:
|
||||
Run the `shadcn` init command to setup your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init
|
||||
@@ -26,106 +26,9 @@ npx shadcn@latest init
|
||||
You will be asked a few questions to configure `components.json`:
|
||||
|
||||
```txt showLineNumbers
|
||||
Would you like to use TypeScript (recommended)? no / yes
|
||||
Which style would you like to use? › Default
|
||||
Which color would you like to use as base color? › Slate
|
||||
Where is your global CSS file? › resources/css/app.css
|
||||
Do you want to use CSS variables for colors? › no / yes
|
||||
Where is your tailwind.config.js located? › tailwind.config.js
|
||||
Configure the import alias for components: › @/Components
|
||||
Configure the import alias for utils: › @/lib/utils
|
||||
Are you using React Server Components? › no / yes
|
||||
```
|
||||
|
||||
### Update tailwind.config.js
|
||||
|
||||
The `shadcn-ui` CLI will automatically overwrite your `tailwind.config.js`. Update it to look like this:
|
||||
|
||||
```js
|
||||
import forms from "@tailwindcss/forms"
|
||||
import defaultTheme from "tailwindcss/defaultTheme"
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
darkMode: "class",
|
||||
content: [
|
||||
"./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php",
|
||||
"./storage/framework/views/*.php",
|
||||
"./resources/views/**/*.blade.php",
|
||||
"./resources/js/**/*.tsx",
|
||||
],
|
||||
|
||||
theme: {
|
||||
container: {
|
||||
center: true,
|
||||
padding: "2rem",
|
||||
screens: {
|
||||
"2xl": "1400px",
|
||||
},
|
||||
},
|
||||
extend: {
|
||||
colors: {
|
||||
border: "hsl(var(--border))",
|
||||
input: "hsl(var(--input))",
|
||||
ring: "hsl(var(--ring))",
|
||||
background: "hsl(var(--background))",
|
||||
foreground: "hsl(var(--foreground))",
|
||||
primary: {
|
||||
DEFAULT: "hsl(var(--primary))",
|
||||
foreground: "hsl(var(--primary-foreground))",
|
||||
},
|
||||
secondary: {
|
||||
DEFAULT: "hsl(var(--secondary))",
|
||||
foreground: "hsl(var(--secondary-foreground))",
|
||||
},
|
||||
destructive: {
|
||||
DEFAULT: "hsl(var(--destructive))",
|
||||
foreground: "hsl(var(--destructive-foreground))",
|
||||
},
|
||||
muted: {
|
||||
DEFAULT: "hsl(var(--muted))",
|
||||
foreground: "hsl(var(--muted-foreground))",
|
||||
},
|
||||
accent: {
|
||||
DEFAULT: "hsl(var(--accent))",
|
||||
foreground: "hsl(var(--accent-foreground))",
|
||||
},
|
||||
popover: {
|
||||
DEFAULT: "hsl(var(--popover))",
|
||||
foreground: "hsl(var(--popover-foreground))",
|
||||
},
|
||||
card: {
|
||||
DEFAULT: "hsl(var(--card))",
|
||||
foreground: "hsl(var(--card-foreground))",
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
lg: `var(--radius)`,
|
||||
md: `calc(var(--radius) - 2px)`,
|
||||
sm: "calc(var(--radius) - 4px)",
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ["Figtree", ...defaultTheme.fontFamily.sans],
|
||||
},
|
||||
keyframes: {
|
||||
"accordion-down": {
|
||||
from: { height: 0 },
|
||||
to: { height: "var(--radix-accordion-content-height)" },
|
||||
},
|
||||
"accordion-up": {
|
||||
from: { height: "var(--radix-accordion-content-height)" },
|
||||
to: { height: 0 },
|
||||
},
|
||||
},
|
||||
animation: {
|
||||
"accordion-down": "accordion-down 0.2s ease-out",
|
||||
"accordion-up": "accordion-up 0.2s ease-out",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
plugins: [forms, require("tailwindcss-animate")],
|
||||
}
|
||||
Which style would you like to use?
|
||||
Which color would you like to use as base color?
|
||||
Do you want to use CSS variables for colors? › yes
|
||||
```
|
||||
|
||||
### That's it
|
||||
|
||||
@@ -13,6 +13,16 @@ Run the `init` command to create a new Next.js project or to setup an existing o
|
||||
npx shadcn@latest init
|
||||
```
|
||||
|
||||
<Callout className="mt-4">
|
||||
|
||||
You can use the `-d` flag for defaults i.e `new-york`, `zinc` and `yes` for the css variables.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init -d
|
||||
```
|
||||
|
||||
</Callout>
|
||||
|
||||
### Configure components.json
|
||||
|
||||
You will be asked a few questions to configure `components.json`:
|
||||
@@ -23,40 +33,6 @@ Which color would you like to use as base color? › Zinc
|
||||
Do you want to use CSS variables for colors? › no / yes
|
||||
```
|
||||
|
||||
### App structure
|
||||
|
||||
Here's how I structure my Next.js apps. You can use this as a reference:
|
||||
|
||||
```txt {6-10,14-15}
|
||||
.
|
||||
├── app
|
||||
│ ├── layout.tsx
|
||||
│ └── page.tsx
|
||||
├── components
|
||||
│ ├── ui
|
||||
│ │ ├── alert-dialog.tsx
|
||||
│ │ ├── button.tsx
|
||||
│ │ ├── dropdown-menu.tsx
|
||||
│ │ └── ...
|
||||
│ ├── main-nav.tsx
|
||||
│ ├── page-header.tsx
|
||||
│ └── ...
|
||||
├── lib
|
||||
│ └── utils.ts
|
||||
├── styles
|
||||
│ └── globals.css
|
||||
├── next.config.js
|
||||
├── package.json
|
||||
├── postcss.config.js
|
||||
├── tailwind.config.ts
|
||||
└── tsconfig.json
|
||||
```
|
||||
|
||||
- I place the UI components in the `components/ui` folder.
|
||||
- The rest of the components such as `<PageHeader />` and `<MainNav />` are placed in the `components` folder.
|
||||
- The `lib` folder contains all the utility functions. I have a `utils.ts` where I define the `cn` helper.
|
||||
- The `styles` folder contains the global CSS.
|
||||
|
||||
### That's it
|
||||
|
||||
You can now start adding components to your project.
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
"dependencies": [
|
||||
"tailwindcss-animate",
|
||||
"class-variance-authority",
|
||||
"lucide-react",
|
||||
""
|
||||
"lucide-react"
|
||||
],
|
||||
"registryDependencies": [
|
||||
"utils"
|
||||
|
||||
@@ -231,6 +231,18 @@ export const Index: Record<string, any> = {
|
||||
|
||||
// // Write the source file for blocks only.
|
||||
sourceFilename = `__registry__/${style.name}/${type}/${item.name}.tsx`
|
||||
|
||||
if (item.files) {
|
||||
const files = item.files.map((file) =>
|
||||
typeof file === "string"
|
||||
? { type: "registry:page", path: file }
|
||||
: file
|
||||
)
|
||||
if (files?.length) {
|
||||
sourceFilename = `__registry__/${style.name}/${files[0].path}`
|
||||
}
|
||||
}
|
||||
|
||||
const sourcePath = path.join(process.cwd(), sourceFilename)
|
||||
if (!existsSync(sourcePath)) {
|
||||
await fs.mkdir(sourcePath, { recursive: true })
|
||||
@@ -414,16 +426,21 @@ async function buildStylesIndex() {
|
||||
for (const style of styles) {
|
||||
const targetPath = path.join(REGISTRY_PATH, "styles", style.name)
|
||||
|
||||
const dependencies = [
|
||||
"tailwindcss-animate",
|
||||
"class-variance-authority",
|
||||
"lucide-react",
|
||||
]
|
||||
|
||||
// TODO: Remove this when we migrate to lucide-react.
|
||||
if (style.name === "new-york") {
|
||||
dependencies.push("@radix-ui/react-icons")
|
||||
}
|
||||
|
||||
const payload: RegistryEntry = {
|
||||
name: style.name,
|
||||
type: "registry:style",
|
||||
dependencies: [
|
||||
"tailwindcss-animate",
|
||||
"class-variance-authority",
|
||||
"lucide-react",
|
||||
// TODO: Remove this when we migrate to lucide-react.
|
||||
style.name === "new-york" ? "@radix-ui/react-icons" : "",
|
||||
],
|
||||
dependencies,
|
||||
registryDependencies: ["utils"],
|
||||
tailwind: {
|
||||
config: {
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
"shadcn:dev": "turbo --filter=shadcn dev",
|
||||
"shadcn": "pnpm --filter=shadcn start:dev",
|
||||
"shadcn:build": "pnpm --filter=shadcn build",
|
||||
"shadcn:test": "pnpm --filter=shadcn test",
|
||||
"docs:build": "pnpm --filter=www build:docs",
|
||||
"www:dev": "pnpm --filter=www dev",
|
||||
"www:build": "pnpm --filter=www build",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @shadcn/ui
|
||||
|
||||
## 2.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4729](https://github.com/shadcn-ui/ui/pull/4729) [`701e116`](https://github.com/shadcn-ui/ui/commit/701e1160ea86b2ddd9f43121b447477caaf7aefa) Thanks [@shadcn](https://github.com/shadcn)! - add --src-dir
|
||||
|
||||
- [#4731](https://github.com/shadcn-ui/ui/pull/4731) [`faa7a67`](https://github.com/shadcn-ui/ui/commit/faa7a67fb30c741c2f2559fc64b34f103aac9d79) Thanks [@shadcn](https://github.com/shadcn)! - fix routes for src dir
|
||||
|
||||
## 2.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "shadcn",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.3",
|
||||
"description": "Add components to your apps.",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -13,7 +13,7 @@
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/shadcn/ui.git",
|
||||
"directory": "packages/cli"
|
||||
"directory": "packages/shadcn"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
|
||||
@@ -21,6 +21,7 @@ export const addOptionsSchema = z.object({
|
||||
all: z.boolean(),
|
||||
path: z.string().optional(),
|
||||
silent: z.boolean(),
|
||||
srcDir: z.boolean().optional(),
|
||||
})
|
||||
|
||||
export const add = new Command()
|
||||
@@ -40,6 +41,11 @@ export const add = new Command()
|
||||
.option("-a, --all", "add all available components", false)
|
||||
.option("-p, --path <path>", "the path to add the component to.")
|
||||
.option("-s, --silent", "mute output.", false)
|
||||
.option(
|
||||
"--src-dir",
|
||||
"use the src directory when creating a new project.",
|
||||
false
|
||||
)
|
||||
.action(async (components, opts) => {
|
||||
try {
|
||||
const options = addOptionsSchema.parse({
|
||||
@@ -100,6 +106,7 @@ export const add = new Command()
|
||||
skipPreflight: false,
|
||||
silent: true,
|
||||
isNewProject: false,
|
||||
srcDir: options.srcDir,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -108,6 +115,7 @@ export const add = new Command()
|
||||
const { projectPath } = await createProject({
|
||||
cwd: options.cwd,
|
||||
force: options.overwrite,
|
||||
srcDir: options.srcDir,
|
||||
})
|
||||
if (!projectPath) {
|
||||
logger.break()
|
||||
@@ -123,6 +131,7 @@ export const add = new Command()
|
||||
skipPreflight: true,
|
||||
silent: true,
|
||||
isNewProject: true,
|
||||
srcDir: options.srcDir,
|
||||
})
|
||||
|
||||
shouldUpdateAppIndex =
|
||||
|
||||
@@ -32,6 +32,7 @@ export const initOptionsSchema = z.object({
|
||||
force: z.boolean(),
|
||||
silent: z.boolean(),
|
||||
isNewProject: z.boolean(),
|
||||
srcDir: z.boolean().optional(),
|
||||
})
|
||||
|
||||
export const init = new Command()
|
||||
@@ -50,6 +51,11 @@ export const init = new Command()
|
||||
process.cwd()
|
||||
)
|
||||
.option("-s, --silent", "mute output.", false)
|
||||
.option(
|
||||
"--src-dir",
|
||||
"use the src directory when creating a new project.",
|
||||
false
|
||||
)
|
||||
.action(async (components, opts) => {
|
||||
try {
|
||||
const options = initOptionsSchema.parse({
|
||||
|
||||
@@ -10,15 +10,20 @@ import prompts from "prompts"
|
||||
import { z } from "zod"
|
||||
|
||||
export async function createProject(
|
||||
options: Pick<z.infer<typeof initOptionsSchema>, "cwd" | "force">
|
||||
options: Pick<z.infer<typeof initOptionsSchema>, "cwd" | "force" | "srcDir">
|
||||
) {
|
||||
options = {
|
||||
srcDir: false,
|
||||
...options,
|
||||
}
|
||||
|
||||
if (!options.force) {
|
||||
const { proceed } = await prompts({
|
||||
type: "confirm",
|
||||
name: "proceed",
|
||||
message: `The path ${highlighter.info(
|
||||
options.cwd
|
||||
)} is empty. Would you like to start a new ${highlighter.info(
|
||||
)} is does not contain a package.json file. Would you like to start a new ${highlighter.info(
|
||||
"Next.js"
|
||||
)} project?`,
|
||||
initial: true,
|
||||
@@ -81,7 +86,7 @@ export async function createProject(
|
||||
"--eslint",
|
||||
"--typescript",
|
||||
"--app",
|
||||
"--no-src-dir",
|
||||
options.srcDir ? "--src-dir" : "--no-src-dir",
|
||||
"--no-import-alias",
|
||||
`--use-${packageManager}`,
|
||||
]
|
||||
@@ -97,7 +102,7 @@ export async function createProject(
|
||||
} catch (error) {
|
||||
logger.break()
|
||||
logger.error(
|
||||
`Something went wront creating a new Next.js project. Please try again.`
|
||||
`Something went wrong creating a new Next.js project. Please try again.`
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
@@ -164,7 +164,6 @@ async function fetchRegistry(paths: string[]) {
|
||||
const results = await Promise.all(
|
||||
paths.map(async (path) => {
|
||||
const url = getRegistryUrl(path)
|
||||
console.log("👉", url)
|
||||
const response = await fetch(url, { agent })
|
||||
|
||||
if (!response.ok) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { existsSync, promises as fs } from "fs"
|
||||
import path, { basename } from "path"
|
||||
import { Config } from "@/src/utils/get-config"
|
||||
import { getProjectInfo } from "@/src/utils/get-project-info"
|
||||
import { highlighter } from "@/src/utils/highlighter"
|
||||
import { logger } from "@/src/utils/logger"
|
||||
import {
|
||||
@@ -37,7 +38,12 @@ export async function updateFiles(
|
||||
const filesCreatedSpinner = spinner(`Updating files.`, {
|
||||
silent: options.silent,
|
||||
})?.start()
|
||||
const baseColor = await getRegistryBaseColor(config.tailwind.baseColor)
|
||||
|
||||
const [projectInfo, baseColor] = await Promise.all([
|
||||
getProjectInfo(config.resolvedPaths.cwd),
|
||||
getRegistryBaseColor(config.tailwind.baseColor),
|
||||
])
|
||||
|
||||
const filesCreated = []
|
||||
const filesUpdated = []
|
||||
const filesSkipped = []
|
||||
@@ -52,7 +58,9 @@ export async function updateFiles(
|
||||
let filePath = path.join(targetDir, fileName)
|
||||
|
||||
if (file.target) {
|
||||
filePath = path.join(config.resolvedPaths.cwd, file.target)
|
||||
filePath = projectInfo?.isSrcDir
|
||||
? path.join(config.resolvedPaths.cwd, "src", file.target)
|
||||
: path.join(config.resolvedPaths.cwd, file.target)
|
||||
targetDir = path.dirname(filePath)
|
||||
}
|
||||
|
||||
|
||||
@@ -196,12 +196,14 @@ async function addTailwindConfigTheme(
|
||||
const themeObject = await parseObjectLiteral(themeObjectString)
|
||||
const result = deepmerge(themeObject, theme)
|
||||
const resultString = objectToString(result)
|
||||
.replace(/\'\"/g, "'")
|
||||
.replace(/\"\'/g, "'")
|
||||
.replace(/\'\[/g, "[")
|
||||
.replace(/\]\'/g, "]")
|
||||
.replace(/\\\'/g, "")
|
||||
.replace(/\\\'/g, "")
|
||||
.replace(/\'\"/g, "'") // Replace `\" with "
|
||||
.replace(/\"\'/g, "'") // Replace `\" with "
|
||||
.replace(/\'\[/g, "[") // Replace `[ with [
|
||||
.replace(/\]\'/g, "]") // Replace `] with ]
|
||||
.replace(/\'\\\'/g, "'") // Replace `\' with '
|
||||
.replace(/\\\'/g, "'") // Replace \' with '
|
||||
.replace(/\\\'\'/g, "'")
|
||||
.replace(/\'\'/g, "'")
|
||||
themeInitializer.replaceWithText(resultString)
|
||||
}
|
||||
|
||||
|
||||
@@ -369,6 +369,41 @@ export default config
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`transformTailwindConfig -> theme > should keep quotes in strings 1`] = `
|
||||
"import type { Config } from 'tailwindcss'
|
||||
|
||||
const config: Config = {
|
||||
darkMode: ["class"],
|
||||
content: [
|
||||
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
sans: ['Figtree', ...defaultTheme.fontFamily.sans]
|
||||
},
|
||||
colors: {
|
||||
...defaultColors,
|
||||
background: 'hsl(var(--background))',
|
||||
foreground: 'hsl(var(--foreground))',
|
||||
primary: {
|
||||
DEFAULT: 'hsl(var(--primary))',
|
||||
foreground: 'hsl(var(--primary-foreground))'
|
||||
},
|
||||
card: {
|
||||
DEFAULT: 'hsl(var(--card))',
|
||||
foreground: 'hsl(var(--card-foreground))'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
export default config
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`transformTailwindConfig -> theme > should keep spread assignments 1`] = `
|
||||
"import type { Config } from 'tailwindcss'
|
||||
|
||||
|
||||
@@ -760,6 +760,55 @@ export default config
|
||||
expect(output3).toBe(output1)
|
||||
expect(output3).toBe(output2)
|
||||
})
|
||||
|
||||
test("should keep quotes in strings", async () => {
|
||||
expect(
|
||||
await transformTailwindConfig(
|
||||
`import type { Config } from 'tailwindcss'
|
||||
|
||||
const config: Config = {
|
||||
content: [
|
||||
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
sans: ['Figtree', ...defaultTheme.fontFamily.sans],
|
||||
},
|
||||
colors: {
|
||||
...defaultColors,
|
||||
background: "hsl(var(--background))",
|
||||
foreground: "hsl(var(--foreground))",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
export default config
|
||||
`,
|
||||
{
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: {
|
||||
DEFAULT: "hsl(var(--primary))",
|
||||
foreground: "hsl(var(--primary-foreground))",
|
||||
},
|
||||
card: {
|
||||
DEFAULT: "hsl(var(--card))",
|
||||
foreground: "hsl(var(--card-foreground))",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
config: SHARED_CONFIG,
|
||||
}
|
||||
)
|
||||
).toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
|
||||
describe("nestSpreadProperties", () => {
|
||||
|
||||
Reference in New Issue
Block a user