Compare commits

...

14 Commits

Author SHA1 Message Date
github-actions[bot]
c8c4027b6b chore(release): version packages (#6349)
* chore(release): version packages

* chore(release): version packages

* chore: fix version

* deps: update lock file

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: shadcn <m@shadcn.com>
2025-01-28 15:26:05 +04:00
shadcn
699195ba77 deps(shadcn): remove unused lodash.template (#6475)
* deps(shadcn): remove unused lodash.template

* chore: changeset
2025-01-28 15:13:39 +04:00
shadcn
9643db42cf feat: add docs for registry (#6380)
* chore: 2.2.0-canary.2

* feat: add docs for registry

* docs(www): update registry docs

* fix: update dep

* docs(www): update docs

* docs(www): update registry docs

* feat: add new label

* fix: lint
2025-01-28 15:06:22 +04:00
JEM
dd71498762 feat(sidebar blocks): adds sidebar-16 block with components and styles (#5889)
Introduces a new sidebar-16 block with an inset sidebar and site header navigation.
Includes components for main navigation, projects, secondary navigation, and user menu.
Updates registry and scripts to include the new sidebar block.

Addresses: #5629

![image](https://github.com/user-attachments/assets/769148aa-ec83-46f4-b4f0-77947e253d28)
![image](https://github.com/user-attachments/assets/38532b4d-21f6-4ce1-9e92-08edc4f72e46)
2025-01-27 12:40:45 +00:00
Jordan Cruz-Correa
ddf761e802 feat: add oklch color format support for /colors (#6441) 2025-01-24 17:53:45 +04:00
shadcn
5f7957ab51 feat(shadcn): add new registry:file type (#6377)
* feat(shadcn): add new registry:file type

* chore: add changeset

* fix: file target
2025-01-16 15:46:33 +04:00
shadcn
f07c7ad5d0 feat(shadcn): handle nested paths for components (#6369)
* feat(shadcn): handle nested paths for components

* chore: add changeset
2025-01-15 18:01:44 +04:00
shadcn
d5aa527f0b docs(www): add block preview image 2025-01-15 15:14:12 +04:00
shadcn
5ec990a474 docs(www): add blocks contribution docs (#6354)
* docs(www): add blocks contrib docs

* docs(www): update intro

* feat: update banner

* docs: add link

* docs: update block types
2025-01-14 21:56:45 +04:00
shadcn
cb742e9825 feat: add new registry build command (#6350)
* feat: implement shadcn/registry

* feat: add schema field

* fix: import

* chore: add changeset

* chore: remove console

* fix: tests

* fix: diff command

* feat: move to schema/registy-item.json

* fix

* ci: switch to node 20

* ci: build packages

* fix: types

* chore: update schema

* chore: update build registry script

* feat(shadcn): add build command
2025-01-14 15:59:41 +04:00
shadcn
254198b4bf feat: add shadcn/registry (#6339)
* feat: implement shadcn/registry

* feat: add schema field

* fix: import

* chore: add changeset

* chore: remove console

* fix: tests

* fix: diff command

* feat: move to schema/registy-item.json

* fix

* ci: switch to node 20

* ci: build packages
2025-01-14 10:50:19 +04:00
shadcn
1081536246 fix: path 2024-12-20 19:12:22 +04:00
shadcn
811bb59a8f feat(shadcn): monorepo support (#6104) 2024-12-20 19:07:17 +04:00
shadcn
ea677cc74e fix: open in v0 2024-12-17 23:14:59 +04:00
805 changed files with 14586 additions and 668 deletions

8
.eslintignore Normal file
View File

@@ -0,0 +1,8 @@
node_modules/
target/
.next/
build/
dist/
/templates/
/fixtures/

View File

@@ -16,7 +16,7 @@ jobs:
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 18
node-version: 20
- uses: pnpm/action-setup@v4
name: Install pnpm
@@ -52,7 +52,7 @@ jobs:
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 18
node-version: 20
- uses: pnpm/action-setup@v4
name: Install pnpm
@@ -90,7 +90,7 @@ jobs:
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 18
node-version: 20
- uses: pnpm/action-setup@v4
name: Install pnpm
@@ -113,4 +113,7 @@ jobs:
- name: Install dependencies
run: pnpm install
- name: Build packages
run: pnpm --filter=shadcn build
- run: pnpm typecheck

View File

@@ -49,7 +49,7 @@ jobs:
A new prerelease is available for testing:
```sh
npx shadcn@${{ env.BETA_PACKAGE_VERSION }}
pnpm dlx shadcn@${{ env.BETA_PACKAGE_VERSION }}
```
- name: "Remove the autorelease label once published"

1
.npmrc
View File

@@ -1 +1,2 @@
auto-install-peers=true
link-workspace-packages=true

11
apps/www/.eslintrc.json Normal file
View File

@@ -0,0 +1,11 @@
{
"$schema": "https://json.schemastore.org/eslintrc",
"overrides": [
{
"files": ["scripts/**/*.{ts,mts}"],
"parserOptions": {
"project": "tsconfig.scripts.json"
}
}
]
}

View File

@@ -0,0 +1,134 @@
"use client"
import * as React from "react"
import { Command, Sidebar } from "lucide-react"
import { AppSidebar } from "@/registry/default/block/sidebar-16/components/app-sidebar"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/default/ui/breadcrumb"
import { Button } from "@/registry/default/ui/button"
import { Separator } from "@/registry/default/ui/separator"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/registry/default/ui/sidebar"
export const iframeHeight = "800px"
export const description = "An inset sidebar with site header navigation."
const HEADER_HEIGHT = "4rem"
export default function Page() {
const [open, setOpen] = React.useState(true)
return (
<div
style={
{
"--header-height": HEADER_HEIGHT,
} as React.CSSProperties
}
>
<header className="bg-sidebar sticky h-[--header-height] top-0 z-50 w-full border-b border-border/40 backdrop-blur">
<div className="flex h-14 items-center px-4">
<div className="mr-4 hidden md:flex">
<Button
className="hidden md:flex"
variant="ghost"
size="icon"
onClick={() => setOpen(!open)}
>
<Sidebar />
</Button>
<a href="#" className="mr-4 flex items-center gap-2 lg:mr-6">
<div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
<Command className="size-4" />
</div>
</a>
<nav className="flex items-center gap-4 text-sm xl:gap-6">
<a
href="#"
className="transition-colors hover:text-foreground/80"
>
Docs
</a>
<a
href="#"
className="transition-colors hover:text-foreground/80"
>
Components
</a>
<a
href="#"
className="transition-colors hover:text-foreground/80"
>
Blocks
</a>
<a
href="#"
className="transition-colors hover:text-foreground/80"
>
Charts
</a>
<a
href="#"
className="transition-colors hover:text-foreground/80"
>
Themes
</a>
<a
href="#"
className="transition-colors hover:text-foreground/80"
>
Colors
</a>
</nav>
</div>
</div>
</header>
<SidebarProvider open={open} onOpenChange={setOpen}>
<AppSidebar />
<SidebarInset>
<header className=" flex shrink-0 items-center gap-2 border-b py-2">
<div className="flex items-center gap-2 px-4 py-2">
<div className="flex md:hidden items-center gap-2">
<SidebarTrigger />
<Separator orientation="vertical" className="mr-2 h-4" />
</div>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">
Building Your Application
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</div>
</header>
<div className="flex flex-1 flex-col gap-4 p-4">
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
</div>
<div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
</div>
</SidebarInset>
</SidebarProvider>
</div>
)
}

View File

@@ -0,0 +1,30 @@
import { AppSidebar } from "@/registry/default/blocks/sidebar-16/components/app-sidebar"
import { SiteHeader } from "@/registry/default/blocks/sidebar-16/components/site-header"
import { SidebarInset, SidebarProvider } from "@/registry/default/ui/sidebar"
export const iframeHeight = "800px"
export const description = "A sidebar with a header and a search form."
export default function Page() {
return (
<div className="[--header-height:calc(theme(spacing.14))]">
<SidebarProvider className="flex flex-col">
<SiteHeader />
<div className="flex flex-1">
<AppSidebar />
<SidebarInset>
<div className="flex flex-1 flex-col gap-4 p-4">
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
</div>
<div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
</div>
</SidebarInset>
</div>
</SidebarProvider>
</div>
)
}

View File

@@ -1139,6 +1139,49 @@ export const Index: Record<string, any> = {
source: "__registry__/new-york/blocks/sidebar-15/page.tsx",
meta: undefined,
},
"sidebar-16": {
name: "sidebar-16",
description: "A sidebar with a sticky site header.",
type: "registry:block",
registryDependencies: ["sidebar","breadcrumb","separator","collapsible","dropdown-menu","avatar","button"],
files: [{
path: "registry/new-york/blocks/sidebar-16/page.tsx",
type: "registry:page",
target: "app/dashboard/page.tsx"
},{
path: "registry/new-york/blocks/sidebar-16/components/app-sidebar.tsx",
type: "registry:component",
target: ""
},{
path: "registry/new-york/blocks/sidebar-16/components/nav-main.tsx",
type: "registry:component",
target: ""
},{
path: "registry/new-york/blocks/sidebar-16/components/nav-projects.tsx",
type: "registry:component",
target: ""
},{
path: "registry/new-york/blocks/sidebar-16/components/nav-secondary.tsx",
type: "registry:component",
target: ""
},{
path: "registry/new-york/blocks/sidebar-16/components/nav-user.tsx",
type: "registry:component",
target: ""
},{
path: "registry/new-york/blocks/sidebar-16/components/search-form.tsx",
type: "registry:component",
target: ""
},{
path: "registry/new-york/blocks/sidebar-16/components/site-header.tsx",
type: "registry:component",
target: ""
}],
categories: ["sidebar","dashboard"],
component: React.lazy(() => import("@/registry/new-york/blocks/sidebar-16/page.tsx")),
source: "__registry__/new-york/blocks/sidebar-16/page.tsx",
meta: undefined,
},
"login-01": {
name: "login-01",
description: "A simple login form.",
@@ -6394,6 +6437,49 @@ export const Index: Record<string, any> = {
source: "__registry__/default/blocks/sidebar-15/page.tsx",
meta: undefined,
},
"sidebar-16": {
name: "sidebar-16",
description: "A sidebar with a sticky site header.",
type: "registry:block",
registryDependencies: ["sidebar","breadcrumb","separator","collapsible","dropdown-menu","avatar","button"],
files: [{
path: "registry/default/blocks/sidebar-16/page.tsx",
type: "registry:page",
target: "app/dashboard/page.tsx"
},{
path: "registry/default/blocks/sidebar-16/components/app-sidebar.tsx",
type: "registry:component",
target: ""
},{
path: "registry/default/blocks/sidebar-16/components/nav-main.tsx",
type: "registry:component",
target: ""
},{
path: "registry/default/blocks/sidebar-16/components/nav-projects.tsx",
type: "registry:component",
target: ""
},{
path: "registry/default/blocks/sidebar-16/components/nav-secondary.tsx",
type: "registry:component",
target: ""
},{
path: "registry/default/blocks/sidebar-16/components/nav-user.tsx",
type: "registry:component",
target: ""
},{
path: "registry/default/blocks/sidebar-16/components/search-form.tsx",
type: "registry:component",
target: ""
},{
path: "registry/default/blocks/sidebar-16/components/site-header.tsx",
type: "registry:component",
target: ""
}],
categories: ["sidebar","dashboard"],
component: React.lazy(() => import("@/registry/default/blocks/sidebar-16/page.tsx")),
source: "__registry__/default/blocks/sidebar-16/page.tsx",
meta: undefined,
},
"login-01": {
name: "login-01",
description: "A simple login form.",

View File

@@ -0,0 +1,134 @@
"use client"
import * as React from "react"
import { Command, Sidebar } from "lucide-react"
import { AppSidebar } from "@/registry/new-york/block/sidebar-16/components/app-sidebar"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/new-york/ui/breadcrumb"
import { Button } from "@/registry/new-york/ui/button"
import { Separator } from "@/registry/new-york/ui/separator"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/registry/new-york/ui/sidebar"
export const iframeHeight = "800px"
export const description = "An inset sidebar with site header navigation."
const HEADER_HEIGHT = "4rem"
export default function Page() {
const [open, setOpen] = React.useState(true)
return (
<div
style={
{
"--header-height": HEADER_HEIGHT,
} as React.CSSProperties
}
>
<header className="bg-sidebar sticky h-[--header-height] top-0 z-50 w-full border-b border-border/40 backdrop-blur">
<div className="flex h-14 items-center px-4">
<div className="mr-4 hidden md:flex">
<Button
className="hidden md:flex"
variant="ghost"
size="icon"
onClick={() => setOpen(!open)}
>
<Sidebar />
</Button>
<a href="#" className="mr-4 flex items-center gap-2 lg:mr-6">
<div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
<Command className="size-4" />
</div>
</a>
<nav className="flex items-center gap-4 text-sm xl:gap-6">
<a
href="#"
className="transition-colors hover:text-foreground/80"
>
Docs
</a>
<a
href="#"
className="transition-colors hover:text-foreground/80"
>
Components
</a>
<a
href="#"
className="transition-colors hover:text-foreground/80"
>
Blocks
</a>
<a
href="#"
className="transition-colors hover:text-foreground/80"
>
Charts
</a>
<a
href="#"
className="transition-colors hover:text-foreground/80"
>
Themes
</a>
<a
href="#"
className="transition-colors hover:text-foreground/80"
>
Colors
</a>
</nav>
</div>
</div>
</header>
<SidebarProvider open={open} onOpenChange={setOpen}>
<AppSidebar />
<SidebarInset>
<header className=" flex shrink-0 items-center gap-2 border-b py-2">
<div className="flex items-center gap-2 px-4 py-2">
<div className="flex md:hidden items-center gap-2">
<SidebarTrigger />
<Separator orientation="vertical" className="mr-2 h-4" />
</div>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">
Building Your Application
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</div>
</header>
<div className="flex flex-1 flex-col gap-4 p-4">
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
</div>
<div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
</div>
</SidebarInset>
</SidebarProvider>
</div>
)
}

View File

@@ -0,0 +1,30 @@
import { AppSidebar } from "@/registry/new-york/blocks/sidebar-16/components/app-sidebar"
import { SiteHeader } from "@/registry/new-york/blocks/sidebar-16/components/site-header"
import { SidebarInset, SidebarProvider } from "@/registry/new-york/ui/sidebar"
export const iframeHeight = "800px"
export const description = "A sidebar with a header and a search form."
export default function Page() {
return (
<div className="[--header-height:calc(theme(spacing.14))]">
<SidebarProvider className="flex flex-col">
<SiteHeader />
<div className="flex flex-1">
<AppSidebar />
<SidebarInset>
<div className="flex flex-1 flex-col gap-4 p-4">
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
</div>
<div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
</div>
</SidebarInset>
</div>
</SidebarProvider>
</div>
)
}

View File

@@ -34,6 +34,9 @@ export async function editInV0({
// Remove v0 prefix from the name
registryItem.name = registryItem.name.replace(/^v0-/, "")
const projectName = capitalCase(name.replace(/\d+/g, ""))
registryItem.description = registryItem.description || projectName
// Replace `@/registry/new-york/` in files.
registryItem.files = registryItem.files?.map((file) => {
if (file.content?.includes("@/registry/new-york/ui")) {
@@ -53,7 +56,7 @@ export async function editInV0({
url,
},
meta: {
project: capitalCase(name.replace(/\d+/g, "")),
project: projectName,
file: `${name}.tsx`,
},
}

View File

@@ -11,6 +11,7 @@ import {
import { Button } from "@/registry/new-york/ui/button"
import "@/styles/mdx.css"
import Link from "next/link"
export const metadata: Metadata = {
title: "Building Blocks.",
@@ -37,12 +38,7 @@ export default function BlocksLayout({
<a href="#blocks">Browse Blocks</a>
</Button>
<Button asChild variant="ghost" size="sm">
<a
href="https://github.com/shadcn-ui/ui/discussions/new?category=blocks-request"
target="_blank"
>
Request a block
</a>
<Link href="/docs/blocks">Add a block</Link>
</Button>
</PageActions>
</PageHeader>

View File

@@ -4,11 +4,11 @@ import { ArrowRight } from "lucide-react"
export function Announcement() {
return (
<Link
href="/docs/components/sidebar"
href="/docs/blocks"
className="group mb-2 inline-flex items-center px-0.5 text-sm font-medium"
>
<span className="underline-offset-4 group-hover:underline">
New sidebar component
Blocks are open for contributions
</span>
<ArrowRight className="ml-1 h-4 w-4" />
</Link>

View File

@@ -1,4 +1,5 @@
import * as React from "react"
import { registryItemFileSchema } from "shadcn/registry"
import { z } from "zod"
import { highlightCode } from "@/lib/highlight-code"
@@ -7,7 +8,6 @@ import {
getRegistryItem,
} from "@/lib/registry"
import { BlockViewer } from "@/components/block-viewer"
import { registryItemFileSchema } from "@/registry/schema"
export async function BlockDisplay({ name }: { name: string }) {
const item = await getCachedRegistryItem(name)

View File

@@ -16,6 +16,7 @@ import {
Terminal,
} from "lucide-react"
import { ImperativePanelHandle } from "react-resizable-panels"
import { registryItemFileSchema, registryItemSchema } from "shadcn/registry"
import { z } from "zod"
import { trackEvent } from "@/lib/events"
@@ -51,7 +52,6 @@ import {
ToggleGroupItem,
} from "@/registry/new-york/ui/toggle-group"
import { Style } from "@/registry/registry-styles"
import { registryItemFileSchema, registryItemSchema } from "@/registry/schema"
type BlockViewerContext = {
item: z.infer<typeof registryItemSchema>

View File

@@ -1,11 +1,11 @@
import * as React from "react"
import { registryItemSchema } from "shadcn/registry"
import { z } from "zod"
import { highlightCode } from "@/lib/highlight-code"
import { getRegistryItem } from "@/lib/registry"
import { cn } from "@/lib/utils"
import { ChartToolbar } from "@/components/chart-toolbar"
import { registryItemSchema } from "@/registry/schema"
export type Chart = z.infer<typeof registryItemSchema> & {
highlightedCode: string

View File

@@ -17,7 +17,12 @@ export function DocsNav({ config }: { config: DocsConfig }) {
{items.map((item, index) => (
<div key={index} className="flex flex-col gap-1">
<h4 className="rounded-md px-2 py-1 text-sm font-semibold">
{item.title}
{item.title}{" "}
{item.label && (
<span className="ml-2 rounded-md bg-[#adfa1d] px-1.5 py-0.5 text-xs font-normal leading-none text-[#000000] no-underline group-hover:no-underline">
{item.label}
</span>
)}
</h4>
{item?.items?.length && (
<DocsNavItems items={item.items} pathname={pathname} />

View File

@@ -71,6 +71,12 @@ export const docsConfig: DocsConfig = {
href: "/docs/cli",
items: [],
},
{
title: "Monorepo",
href: "/docs/monorepo",
items: [],
label: "New",
},
{
title: "Next.js 15 + React 19",
href: "/docs/react-19",
@@ -86,6 +92,12 @@ export const docsConfig: DocsConfig = {
href: "/docs/v0",
items: [],
},
{
title: "Blocks",
href: "/docs/blocks",
items: [],
label: "New",
},
{
title: "Figma",
href: "/docs/figma",
@@ -141,12 +153,6 @@ export const docsConfig: DocsConfig = {
{
title: "Components",
items: [
{
title: "Sidebar",
href: "/docs/components/sidebar",
items: [],
label: "New",
},
{
title: "Accordion",
href: "/docs/components/accordion",
@@ -337,6 +343,11 @@ export const docsConfig: DocsConfig = {
href: "/docs/components/sheet",
items: [],
},
{
title: "Sidebar",
href: "/docs/components/sidebar",
items: [],
},
{
title: "Skeleton",
href: "/docs/components/skeleton",
@@ -394,6 +405,42 @@ export const docsConfig: DocsConfig = {
},
],
},
{
title: "Registry",
label: "New",
items: [
{
title: "Introduction",
href: "/docs/registry",
items: [],
},
{
title: "Getting Started",
href: "/docs/registry/getting-started",
items: [],
},
{
title: "Open in v0",
href: "/docs/registry/open-in-v0",
items: [],
},
{
title: "FAQ",
href: "/docs/registry/faq",
items: [],
},
{
title: "registry.json",
href: "/docs/registry/registry-json",
items: [],
},
{
title: "registry-item.json",
href: "/docs/registry/registry-item-json",
items: [],
},
],
},
],
chartsNav: [
{

View File

@@ -0,0 +1,238 @@
---
title: Add a block
description: Contribute components to the blocks library.
---
We are inviting the community to contribute to the [blocks library](/blocks). Share your components and blocks with other developers and help build a library of high-quality, reusable components.
We'd love to see all types of blocks: applications, marketing, products, and more.
## Setup your workspace
<Steps>
### Fork the repository
```bash
git clone https://github.com/shadcn-ui/ui.git
```
### Create a new branch
```bash
git checkout -b username/my-new-block
```
### Install dependencies
```bash
pnpm install
```
### Start the dev server
```bash
pnpm www:dev
```
</Steps>
## Add a block
A block can be a single component (eg. a variation of a ui component) or a complex component (eg. a dashboard) with multiple components, hooks, and utils.
<Steps>
### Create a new block
Create a new folder in the `apps/www/registry/new-york/blocks` directory. Make sure the folder is named in kebab-case and under `new-york`.
```txt
apps
└── www
└── registry
└── new-york
└── blocks
└── dashboard-01
```
<Callout className="mt-6">
**Note:** The build script will take care of building the block for the `default` style.
</Callout>
### Add your block files
Add your files to the block folder. Here is an example of a block with a page, components, hooks, and utils.
```txt
dashboard-01
└── page.tsx
└── components
└── hello-world.tsx
└── example-card.tsx
└── hooks
└── use-hello-world.ts
└── lib
└── format-date.ts
```
<Callout className="mt-6">
**Note:** You can start with one file and add more files later.
</Callout>
</Steps>
## Add your block to the registry
<Steps>
### Add your block definition to `registry-blocks.tsx`
To add your block to the registry, you need to add your block definition to `registry-blocks.tsx`.
This follows the registry schema at [https://ui.shadcn.com/schema/registry-item.json](https://ui.shadcn.com/schema/registry-item.json).
```tsx title="apps/www/registry/registry-blocks.tsx"
export const blocks = [
// ...
{
name: "dashboard-01",
author: "shadcn (https://ui.shadcn.com)",
title: "Dashboard",
description: "A simple dashboard with a hello world component.",
type: "registry:block",
registryDependencies: ["input", "button", "card"],
dependencies: ["zod"],
files: [
{
path: "blocks/dashboard-01/page.tsx",
type: "registry:page",
target: "app/dashboard/page.tsx",
},
{
path: "blocks/dashboard-01/components/hello-world.tsx",
type: "registry:component",
},
{
path: "blocks/dashboard-01/components/example-card.tsx",
type: "registry:component",
},
{
path: "blocks/dashboard-01/hooks/use-hello-world.ts",
type: "registry:hook",
},
{
path: "blocks/dashboard-01/lib/format-date.ts",
type: "registry:lib",
},
],
categories: ["dashboard"],
},
]
```
Make sure you add a name, description, type, registryDependencies, dependencies, files, and categories. We'll go over each of these in more detail in the schema docs (coming soon).
### Run the build script
```bash
pnpm registry:build
```
<Callout className="mt-6">
**Note:** you do not need to run this script for every change. You only need to run it when you update the block definition.
</Callout>
### View your block
Once the build script is finished, you can view your block at `http://localhost:3333/blocks/[CATEGORY]` or a full screen preview at `http://localhost:3333/view/styles/new-york/dashboard-01`.
<Image
src="/images/block-preview-light.png"
width="1432"
height="960"
alt="Block preview"
className="border dark:hidden shadow-sm rounded-lg overflow-hidden mt-6 w-full"
/>
<Image
src="/images/block-preview-dark.png"
width="1432"
height="960"
alt="Block preview"
className="border hidden dark:block shadow-sm rounded-lg overflow-hidden mt-6 w-full"
/>
### Build your block
You can now build your block by editing the files in the block folder and viewing the changes in the browser.
If you add more files, make sure to add them to the `files` array in the block definition.
</Steps>
## Publish your block
Once you're ready to publish your block, you can submit a pull request to the main repository.
<Steps>
### Run the build script
```bash
pnpm registry:build
```
### Capture a screenshot
```bash
pnpm registry:capture
```
<Callout className="mt-6">
**Note:** If you've run the capture script before, you might need to delete the existing screenshots (both light and dark) at `apps/www/public/r/styles/new-york` and run the script again.
</Callout>
### Submit a pull request
Commit your changes and submit a pull request to the main repository.
Your block will be reviewed and merged. Once merged it will be published to the website and available to be installed via the CLI.
</Steps>
## Categories
The `categories` property is used to organize your block in the registry.
### Add a category
If you need to add a new category, you can do so by adding it to the `registryCategories` array in `apps/www/registry/registry-categories.ts`.
```tsx title="apps/www/registry/registry-categories.ts"
export const registryCategories = [
// ...
{
name: "Input",
slug: "input",
hidden: false,
},
]
```
## Guidelines
Here are some guidelines to follow when contributing to the blocks library.
- The following properties are required for the block definition: `name`, `description`, `type`, `files`, and `categories`.
- Make sure to list all registry dependencies in `registryDependencies`. A registry dependency is the name of the component in the registry eg. `input`, `button`, `card`, etc.
- Make sure to list all dependencies in `dependencies`. A dependency is the name of the package in the registry eg. `zod`, `sonner`, etc.
- If your block has a page (optional), it should be the first entry in the `files` array and it should have a `target` property. This helps the CLI place the page in the correct location for file-based routing.
- **Imports should always use the `@/registry` path.** eg. `import { Input } from "@/registry/new-york/input"`

View File

@@ -90,16 +90,33 @@ Options:
-h, --help display help for command
```
## Monorepo
## build
In a monorepo, you can specify the path to your workspace with the `-c` or `--cwd` option.
Use the `build` command to generate the registry JSON files.
```bash
npx shadcn@latest init -c ./apps/www
npx shadcn@latest build
```
or
This command reads the `registry.json` file and generates the registry JSON files in the `public/r` directory.
```txt
Usage: shadcn build [options] [registry]
build components for a shadcn registry
Arguments:
registry path to registry.json file (default: "./registry.json")
Options:
-o, --output <path> destination directory for json files (default: "./public/r")
-c, --cwd <cwd> the working directory. defaults to the current directory. (default:
"/Users/shadcn/Code/shadcn/ui/packages/shadcn")
-h, --help display help for command
```
To customize the output directory, use the `--output` option.
```bash
npx shadcn@latest add alert-dialog -c ./apps/www
npx shadcn@latest build --output ./public/registry
```

View File

@@ -0,0 +1,175 @@
---
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.
With the new monorepo support in the CLI, we've made it a lot easier to use
shadcn/ui in a monorepo.
The CLI now understands the monorepo structure and will install the components,
dependencies and registry dependencies to the correct paths and handle imports
for you.
## Getting started
<Steps>
### Create a new monorepo project
To create a new monorepo project, run the `init` command. You will be prompted
to select the type of project you are creating.
```bash
npx shadcn@canary init
```
Select the `Next.js (Monorepo)` option.
```bash
? Would you like to start a new project?
Next.js
Next.js (Monorepo)
```
This will create a new monorepo project with two workspaces: `web` and `ui`,
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.
### Add components to your project
To add components to your project, run the `add` command **in the path of your app**.
```bash
cd apps/web
```
```bash
npx shadcn@canary add [COMPONENT]
```
The CLI will figure out what type of component you are adding and install the
correct files to the correct path.
For example, if you run `npx shadcn@canary add button`, the CLI will install the button component under `packages/ui` and update the import path for components in `apps/web`.
If you run `npx shadcn@canary add login-01`, the CLI will install the `button`, `label`, `input` and `card` components under `packages/ui` and the `login-form` component under `apps/web/components`.
### Importing components
You can import components from the `@workspace/ui` package as follows:
```tsx
import { Button } from "@workspace/ui/components/button"
```
You can also import hooks and utilities from the `@workspace/ui` package.
```tsx
import { useTheme } from "@workspace/ui/hooks/use-theme"
import { cn } from "@workspace/ui/lib/utils"
```
</Steps>
## File Structure
When you create a new monorepo project, the CLI will create the following file structure:
```txt
apps
└── web # Your app goes here.
├── app
│ └── page.tsx
├── components
│ └── login-form.tsx
├── components.json
└── package.json
packages
└── ui # Your components and dependencies are installed here.
├── src
│ ├── components
│ │ └── button.tsx
│ ├── hooks
│ ├── lib
│ │ └── utils.ts
│ └── styles
│ └── globals.css
├── components.json
└── package.json
package.json
turbo.json
```
## Requirements
1. Every workspace must have a `components.json` file. A `package.json` file tells npm how to install the dependencies. A `components.json` file tells the CLI how and where to install components.
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"
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "../../packages/ui/tailwind.config.ts",
"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 title="packages/ui/components.json"
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"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"
}
}
```
3. Ensure you have the same `style`, `iconLibrary` and `baseColor` in both `components.json` files.
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.
## Help us improve monorepo support
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 on [GitHub Discussions](https://github.com/shadcn-ui/ui/discussions).

View File

@@ -0,0 +1,125 @@
---
title: FAQ
description: Frequently asked questions about running a registry.
---
## Frequently asked questions
### What does a complex component look like?
Here's an example of a complex component that installs a page, two components, a hook, a format-date utils and a config file.
```json showLineNumbers
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "hello-world",
"title": "Hello World",
"type": "registry:block",
"description": "A complex hello world component",
"files": [
{
"path": "registry/hello-world/page.tsx",
"type": "registry:page",
"target": "app/hello/page.tsx"
},
{
"path": "registry/hello-world/components/hello-world.tsx",
"type": "registry:component"
},
{
"path": "registry/hello-world/components/formatted-message.tsx",
"type": "registry:component"
},
{
"path": "registry/hello-world/hooks/use-hello.ts",
"type": "registry:hook"
},
{
"path": "registry/hello-world/lib/format-date.ts",
"type": "registry:utils"
},
{
"path": "registry/hello-world/hello.config.ts",
"type": "registry:file",
"target": "~/hello.config.ts"
}
]
}
```
### How do I add a new Tailwind color?
To add a new color you need to add it to `cssVars` and `tailwind.config.theme.extend.colors`.
```json showLineNumbers {10-19} {24-29}
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "hello-world",
"title": "Hello World",
"type": "registry:block",
"description": "A complex hello world component",
"files": [
// ...
],
"cssVars": {
"light": {
"brand-background": "20 14.3% 4.1%",
"brand-accent": "20 14.3% 4.1%"
},
"dark": {
"brand-background": "20 14.3% 4.1%",
"brand-accent": "20 14.3% 4.1%"
}
},
"tailwind": {
"config": {
"theme": {
"extend": {
"colors": {
"brand": {
"DEFAULT": "hsl(var(--brand-background))",
"accent": "hsl(var(--brand-accent))"
}
}
}
}
}
}
}
```
The CLI will update the project CSS file and tailwind.config.js file. Once updated, the new colors will be available to be used as utility classes: `bg-brand` and `text-brand-accent`.
### How do I add a Tailwind animation?
To add a new animation you add it to `tailwind.config.theme.extend.animation` and `tailwind.config.theme.extend.keyframes`.
```json showLineNumbers {14-22}
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "hello-world",
"title": "Hello World",
"type": "registry:block",
"description": "A complex hello world component",
"files": [
// ...
],
"tailwind": {
"config": {
"theme": {
"extend": {
"keyframes": {
"wiggle": {
"0%, 100%": { "transform": "rotate(-3deg)" },
"50%": { "transform": "rotate(3deg)" }
}
},
"animation": {
"wiggle": "wiggle 1s ease-in-out infinite"
}
}
}
}
}
}
```

View File

@@ -0,0 +1,186 @@
---
title: Getting Started
description: Learn how to get setup and run your own component registry.
---
This guide will walk you through the process of setting up your own component registry.
It assumes you already have a project with components and would like to turn it into a registry.
If you're starting a new registry project, you can use the [registry template](https://github.com/shadcn-ui/registry-template) as a starting point. We have already configured it for you.
## registry.json
The `registry.json` file is only required if you're using the `shadcn` CLI to build your registry.
If you're using a different build system, you can skip this step as long as your build system produces valid JSON files that conform to the [registry-item schema specification](/docs/registry/registry-item-json).
<Steps>
### Add a registry.json file
Create a `registry.json` file in the root of your project. Your project can be a Next.js, Remix, Vite, or any other project that supports React.
```json title="registry.json" showLineNumbers
{
"$schema": "https://ui.shadcn.com/schema/registry.json",
"name": "acme",
"homepage": "https://acme.com",
"items": [
// ...
]
}
```
This `registry.json` file must conform to the [registry schema specification](/docs/registry/registry-json).
</Steps>
## Add a registry item
<Steps>
### Create your component
Add your first component. Here's an example of a simple `<HelloWorld />` component:
```tsx title="registry/hello-world/hello-world.tsx" showLineNumbers
import { Button } from "@/components/ui/button"
export function HelloWorld() {
return <Button>Hello World</Button>
}
```
<Callout className="mt-6">
**Note:** This example places the component in the `registry` directory. You
can place it anywhere in your project as long as you set the correct path in
the `registry.json` file.
</Callout>
```txt
registry
└── hello-world
└── hello-world.tsx
```
<Callout className="mt-6 [&_[data-rehype-pretty-code-title]]:pt-1 [&_pre]:mb-0">
**Important:** If you're placing your component in a custom directory, make
sure it is configured in your `tailwind.config.ts` file.
```ts showLineNumbers
// tailwind.config.ts
export default {
content: ["./registry/**/*.{js,ts,jsx,tsx}"],
}
```
</Callout>
### Add your component to the registry
To add your component to the registry, you need to add your component definition to `registry.json`.
```json title="registry.json" showLineNumbers {6-17}
{
"$schema": "https://ui.shadcn.com/schema/registry.json",
"name": "acme",
"homepage": "https://acme.com",
"items": [
{
"name": "hello-world",
"type": "registry:block",
"title": "Hello World",
"description": "A simple hello world component.",
"files": [
{
"path": "registry/hello-world/hello-world.tsx",
"type": "registry:component"
}
]
}
]
}
```
You define your registry item by adding a `name`, `type`, `title`, `description` and `files`.
For every file you add, you must specify the `path` and `type` of the file. The `path` is the relative path to the file from the root of your project. The `type` is the type of the file.
You can read more about the registry item schema and file types in the [registry item schema docs](/docs/registry/registry-item-json).
</Steps>
## Build your registry
<Steps>
### Install the shadcn CLI
Note: the `build` command is currently only available in the `shadcn@canary` version of the CLI.
```bash
npm install shadcn@canary
```
### Add a build script
Add a `registry:build` script to your `package.json` file.
```json title="package.json" showLineNumbers
{
"scripts": {
"registry:build": "shadcn build"
}
}
```
### Run the build script
Run the build script to generate the registry JSON files.
```bash
npm run registry:build
```
<Callout className="mt-6">
**Note:** By default, the build script will generate the registry JSON files
in `public/r` e.g `public/r/hello-world.json`.
You can change the output directory by passing the `--output` option. See the [shadcn build command](/docs/cli#build) for more information.
</Callout>
</Steps>
## Serve your registry
If you're running your registry on Next.js, you can now serve your registry by running the `next` server. The command might differ for other frameworks.
```bash
npm run dev
```
Your files will now be served at `http://localhost:3000/r/[NAME].json` eg. `http://localhost:3000/r/hello-world.json`.
## Publish your registry
To make your registry available to other developers, you can publish it by deploying your project to a public URL.
## Guidelines
Here are some guidelines to follow when building components for a registry.
- The following properties are required for the block definition: `name`, `description`, `type` and `files`.
- Make sure to list all registry dependencies in `registryDependencies`. A registry dependency is the name of the component in the registry eg. `input`, `button`, `card`, etc or a URL to a registry item eg. `http://localhost:3000/r/editor.json`.
- Make sure to list all dependencies in `dependencies`. A dependency is the name of the package in the registry eg. `zod`, `sonner`, etc. To set a version, you can use the `name@version` format eg. `zod@^3.20.0`.
- **Imports should always use the `@/registry` path.** eg. `import { HelloWorld } from "@/registry/hello-world/hello-world"`
- Ideally, place your files within a registry item in `components`, `hooks`, `lib` directories.
## Install using the CLI
To install a registry item using the `shadcn` CLI, use the `add` command followed by the URL of the registry item.
```bash
npx shadcn@latest add http://localhost:3000/r/hello-world.json
```

View File

@@ -0,0 +1,40 @@
---
title: Registry
description: Run your own component registry.
---
<Callout>
**Note:** This feature is currently 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>
You can use the `shadcn` CLI to run your own component registry. Running your own registry allows you to distribute your custom components, hooks, pages, and other files to any React project.
<figure className="flex flex-col gap-4">
<Image
src="/images/registry-light.png"
width="1432"
height="960"
alt="Registry"
className="border dark:hidden shadow-sm rounded-lg overflow-hidden mt-6 w-full"
/>
<Image
src="/images/registry-dark.png"
width="1432"
height="960"
alt="Registry"
className="border hidden dark:block shadow-sm rounded-lg overflow-hidden mt-6 w-full"
/>
<figcaption className="text-center text-sm text-gray-500">
Distribute code to any React project.
</figcaption>
</figure>
Registry items are automatically compatible with the `shadcn` CLI and `Open in v0`.
## Requirements
You are free to design and host your custom registry as you see fit. The only requirement is that your registry items must be valid JSON files that conform to the [registry-item schema specification](/docs/registry/registry-item-json).
If you'd like to see an example of a registry, we have a [template project](https://github.com/shadcn-ui/registry-template) for you to use as a starting point.

View File

@@ -0,0 +1,59 @@
---
title: Open in v0
description: Integrate your registry with Open in v0.
---
If your registry is hosted and publicly accessible via a URL, you can open a registry item in v0 by using the `https://v0.dev/chat/api/open?url=[URL]` endpoint.
eg. [https://v0.dev/chat/api/open?url=https://example.com/r/hello-world.json](https://v0.dev/chat/api/open?url=https://example.com/r/hello-world.json)
## Button
You can copy and paste the following code to add a `Open in v0` button to your site.
```jsx
import { Button } from "@/components/ui/button"
export function OpenInV0Button({ url }: { url: string }) {
return (
<Button
aria-label="Open in v0"
className="h-8 gap-1 rounded-[6px] bg-black px-3 text-xs text-white hover:bg-black hover:text-white dark:bg-white dark:text-black"
asChild
>
<a
href={`https://v0.dev/chat/api/open?url=${url}`}
target="_blank"
rel="noreferrer"
>
Open in{" "}
<svg
viewBox="0 0 40 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5 text-current"
>
<path
d="M23.3919 0H32.9188C36.7819 0 39.9136 3.13165 39.9136 6.99475V16.0805H36.0006V6.99475C36.0006 6.90167 35.9969 6.80925 35.9898 6.71766L26.4628 16.079C26.4949 16.08 26.5272 16.0805 26.5595 16.0805H36.0006V19.7762H26.5595C22.6964 19.7762 19.4788 16.6139 19.4788 12.7508V3.68923H23.3919V12.7508C23.3919 12.9253 23.4054 13.0977 23.4316 13.2668L33.1682 3.6995C33.0861 3.6927 33.003 3.68923 32.9188 3.68923H23.3919V0Z"
fill="currentColor"
></path>
<path
d="M13.7688 19.0956L0 3.68759H5.53933L13.6231 12.7337V3.68759H17.7535V17.5746C17.7535 19.6705 15.1654 20.6584 13.7688 19.0956Z"
fill="currentColor"
></path>
</svg>
</a>
</Button>
)
}
```
## Usage
```jsx
<OpenInV0Button url="https://example.com/r/hello-world.json" />
```
## Known issues
- The `Open in v0` button does not support `cssVars` and `tailwind` properties.

View File

@@ -0,0 +1,272 @@
---
title: registry-item.json
description: Specification for registry items.
---
The `registry-item.json` schema is used to define your custom registry items.
```json title="registry-item.json" showLineNumbers
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "hello-world",
"type": "registry:block",
"title": "Hello World",
"description": "A simple hello world component.",
"files": [
{
"path": "registry/hello-world/hello-world.tsx",
"type": "registry:component"
},
{
"path": "registry/hello-world/use-hello-world.ts",
"type": "registry:hook"
}
]
}
```
## Definitions
You can see the JSON Schema for `registry-item.json` [here](https://ui.shadcn.com/schema/registry-item.json).
### $schema
The `$schema` property is used to specify the schema for the `registry-item.json` file.
```json title="registry-item.json" showLineNumbers
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json"
}
```
### name
The `name` property is used to specify the name of your registry item.
```json title="registry-item.json" showLineNumbers
{
"name": "hello-world"
}
```
### title
A human-readable title for your registry item. Keep it short and descriptive.
```json title="registry-item.json" showLineNumbers
{
"title": "Hello World"
}
```
### description
A description of your registry item. This can be longer and more detailed than the `title`.
```json title="registry-item.json" showLineNumbers
{
"description": "A simple hello world component."
}
```
### type
The `type` property is used to specify the type of your registry item.
```json title="registry-item.json" showLineNumbers
{
"type": "registry:block"
}
```
The following types are supported:
| Type | Description |
| -------------------- | ------------------------------------------------ |
| `registry:block` | Use for complex components with multiple files. |
| `registry:component` | Use for simple components. |
| `registry:lib` | Use for lib and utils. |
| `registry:hook` | Use for hooks. |
| `registry:ui` | Use for UI components and single-file primitives |
| `registry:page` | Use for page or file-based routes. |
| `registry:file` | Use for miscellaneous files. |
### author
The `author` property is used to specify the author of the registry item.
It can be unique to the registry item or the same as the author of the registry.
```json title="registry-item.json" showLineNumbers
{
"author": "John Doe <john@doe.com>"
}
```
### dependencies
The `dependencies` property is used to specify the dependencies of your registry item. This is for `npm` packages.
Use `@version` to specify the version of your registry item.
```json title="registry-item.json" showLineNumbers
{
"dependencies": [
"@radix-ui/react-accordion",
"zod",
"lucide-react",
"name@1.0.2"
]
}
```
### registryDependencies
Used for registry dependencies. Can be names or URLs.
- For `shadcn/ui` registry items such as `button`, `input`, `select`, etc use the name eg. `['button', 'input', 'select']`.
- For custom registry items use the URL of the registry item eg. `['https://example.com/r/hello-world.json']`.
```json title="registry-item.json" showLineNumbers
{
"registryDependencies": [
"button",
"input",
"select",
"https://example.com/r/editor.json"
]
}
```
Note: The CLI will automatically resolve remote registry dependencies.
### files
The `files` property is used to specify the files of your registry item. Each file has a `path`, `type` and `target` (optional) property.
**The `target` property is required for `registry:page` and `registry:file` types.**
```json title="registry-item.json" showLineNumbers
{
"files": [
{
"path": "registry/hello-world/page.tsx",
"type": "registry:page",
"target": "app/hello/page.tsx"
},
{
"path": "registry/hello-world/hello-world.tsx",
"type": "registry:component"
},
{
"path": "registry/hello-world/use-hello-world.ts",
"type": "registry:hook"
},
{
"path": "registry/hello-world/.env",
"type": "registry:file",
"target": "~/.env"
}
]
}
```
#### path
The `path` property is used to specify the path to the file in your registry. This path is used by the build script to parse, transform and build the registry JSON payload.
#### type
The `type` property is used to specify the type of the file. See the [type](#type) section for more information.
#### target
The `target` property is used to indicate where the file should be placed in a project. This is optional and only required for `registry:page` and `registry:file` types.
By default, the `shadcn` cli will read a project's `components.json` file to determine the target path. For some files, such as routes or config you can specify the target path manually.
Use `~` to refer to the root of the project e.g `~/foo.config.js`.
### tailwind
The `tailwind` property is used for tailwind configuration such as `theme`, `plugins` and `content`.
You can use the `tailwind.config` property to add colors, animations and plugins to your registry item.
```json title="registry-item.json" showLineNumbers
{
"tailwind": {
"config": {
"theme": {
"extend": {
"colors": {
"brand": "hsl(var(--brand))"
},
"keyframes": {
"wiggle": {
"0%, 100%": { "transform": "rotate(-3deg)" },
"50%": { "transform": "rotate(3deg)" }
}
},
"animation": {
"wiggle": "wiggle 1s ease-in-out infinite"
}
}
}
}
}
}
```
### cssVars
Use to define CSS variables for your registry item.
```json title="registry-item.json" showLineNumbers
{
"cssVars": {
"light": {
"brand": "20 14.3% 4.1%",
"radius": "0.5rem"
},
"dark": {
"brand": "20 14.3% 4.1%"
}
}
}
```
<Callout>
**Note:** When adding colors, make sure to also add them to the
`tailwind.config.theme.extend.colors` property.
</Callout>
### docs
Use `docs` to show custom documentation or message when installing your registry item via the CLI.
```json title="registry-item.json" showLineNumbers
{
"docs": "Remember to add the FOO_BAR environment variable to your .env file."
}
```
### categories
Use `categories` to organize your registry item.
```json title="registry-item.json" showLineNumbers
{
"categories": ["sidebar", "dashboard"]
}
```
### meta
Use `meta` to add additional metadata to your registry item. You can add any key/value pair that you want to be available to the registry item.
```json title="registry-item.json" showLineNumbers
{
"meta": { "foo": "bar" }
}
```

View File

@@ -0,0 +1,87 @@
---
title: registry.json
description: Schema for running your own component registry.
---
The `registry.json` schema is used to define your custom component registry.
```json title="registry.json" showLineNumbers
{
"$schema": "https://ui.shadcn.com/schema/registry.json",
"name": "shadcn",
"homepage": "https://ui.shadcn.com",
"items": [
{
"name": "hello-world",
"type": "registry:block",
"title": "Hello World",
"description": "A simple hello world component.",
"files": [
{
"path": "registry/hello-world/hello-world.tsx",
"type": "registry:component"
}
]
}
]
}
```
## Definitions
You can see the JSON Schema for `registry.json` [here](https://ui.shadcn.com/schema/registry.json).
### $schema
The `$schema` property is used to specify the schema for the `registry.json` file.
```json title="registry.json" showLineNumbers
{
"$schema": "https://ui.shadcn.com/schema/registry.json"
}
```
### name
The `name` property is used to specify the name of your registry. This is used for data attributes and other metadata.
```json title="registry.json" showLineNumbers
{
"name": "acme"
}
```
### homepage
The homepage of your registry. This is used for data attributes and other metadata.
```json title="registry.json" showLineNumbers
{
"homepage": "https://acme.com"
}
```
### items
The `items` in your registry. Each item must implement the [registry-item schema specification](https://ui.shadcn.com/schema/registry-item.json).
```json title="registry.json" showLineNumbers
{
"items": [
{
"name": "hello-world",
"type": "registry:block",
"title": "Hello World",
"description": "A simple hello world component.",
"files": [
{
"path": "registry/hello-world/hello-world.tsx",
"type": "registry:component"
}
]
}
]
}
```
See the [registry-item schema documentation](/docs/registry/registry-item) for more information.

View File

@@ -1,9 +1,9 @@
"use server"
import { registryItemSchema } from "shadcn/registry"
import { z } from "zod"
import { Style } from "@/registry/registry-styles"
import { registryItemSchema } from "@/registry/schema"
export async function getAllBlockIds(
types: z.infer<typeof registryItemSchema>["type"][] = [

View File

@@ -11,6 +11,7 @@ const colorSchema = z.object({
rgb: z.string(),
hsl: z.string(),
foreground: z.string(),
oklch: z.string(),
})
const colorPaletteSchema = z.object({
@@ -26,6 +27,7 @@ export function getColorFormat(color: Color) {
hex: color.hex,
rgb: color.rgb,
hsl: color.hsl,
oklch: color.oklch,
}
}
@@ -57,6 +59,10 @@ export function getColors() {
/^hsl\(([\d.]+),([\d.]+%),([\d.]+%)\)$/,
"$1 $2 $3"
),
oklch: color.oklch.replace(
/^oklch\(([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\)$/,
"$1 $2 $3"
),
foreground: getForegroundFromBackground(rgb),
}
}),

View File

@@ -2,11 +2,11 @@ import { promises as fs } from "fs"
import { tmpdir } from "os"
import path from "path"
import { Index } from "@/__registry__"
import { registryItemFileSchema, registryItemSchema } from "shadcn/registry"
import { Project, ScriptKind, SourceFile, SyntaxKind } from "ts-morph"
import { z } from "zod"
import { Style } from "@/registry/registry-styles"
import { registryItemFileSchema, registryItemSchema } from "@/registry/schema"
export const DEFAULT_REGISTRY_STYLE = "new-york" satisfies Style["name"]
@@ -157,7 +157,7 @@ function getFileTarget(file: z.infer<typeof registryItemFileSchema>) {
}
}
return target
return target ?? ""
}
async function createTempSourceFile(filename: string) {

View File

@@ -79,6 +79,21 @@ export function rehypeNpmCommand() {
"bunx --bun"
)
}
// npm run.
if (node.properties?.["__rawString__"]?.startsWith("npm run")) {
const npmCommand = node.properties?.["__rawString__"]
node.properties["__npmCommand__"] = npmCommand
node.properties["__yarnCommand__"] = npmCommand.replace(
"npm run",
"yarn"
)
node.properties["__pnpmCommand__"] = npmCommand.replace(
"npm run",
"pnpm"
)
node.properties["__bunCommand__"] = npmCommand.replace("npm run", "bun")
}
})
}
}

View File

@@ -80,6 +80,7 @@
"react-resizable-panels": "^2.0.22",
"react-wrap-balancer": "^0.4.1",
"recharts": "2.12.7",
"shadcn": "2.3.0",
"sharp": "^0.31.3",
"sonner": "^1.2.3",
"swr": "2.2.6-beta.3",

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
{
"$schema": "https://ui.shadcn.com/registry.json",
"name": "facebook",
"type": "registry:block",
"registryDependencies": [],
"dependencies": ["motion"],
"devDependencies": [],
"tailwind": {},
"cssVars": {
"light": {},
"dark": {}
},
"files": [
{
"path": "facebook.tsx",
"content": "'use client';\n\nimport type { Variants } from 'motion/react';\nimport { motion, useAnimation } from 'motion/react';\n\nconst facebookVariants: Variants = {\n normal: {\n opacity: 1,\n pathLength: 1,\n pathOffset: 0,\n transition: {\n duration: 0.4,\n opacity: { duration: 0.1 },\n },\n },\n animate: {\n opacity: [0, 1],\n pathLength: [0, 1],\n pathOffset: [1, 0],\n transition: {\n duration: 0.6,\n ease: 'linear',\n opacity: { duration: 0.1 },\n },\n },\n};\n\nconst FacebookIcon = () => {\n const controls = useAnimation();\n\n return (\n <div\n className=\"cursor-pointer select-none p-2 hover:bg-accent rounded-md transition-colors duration-200 flex items-center justify-center\"\n onMouseEnter={() => {\n controls.start('animate');\n }}\n onMouseLeave={() => {\n controls.start('normal');\n }}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <motion.path\n variants={facebookVariants}\n animate={controls}\n initial=\"normal\"\n d=\"M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z\"\n />\n </svg>\n </div>\n );\n};\n\nexport { FacebookIcon };\n",
"type": "registry:ui"
}
]
}

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "accordion-demo",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"accordion"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "accordion",
"type": "registry:ui",
"author": "shadcn (https://ui.shadcn.com)",
"dependencies": [
"@radix-ui/react-accordion"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "alert-demo",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"alert"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "alert-destructive",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"alert"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "alert-dialog-demo",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"alert-dialog",
"button"

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "alert-dialog",
"type": "registry:ui",
"author": "shadcn (https://ui.shadcn.com)",
"dependencies": [
"@radix-ui/react-alert-dialog"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "alert",
"type": "registry:ui",
"author": "shadcn (https://ui.shadcn.com)",
"files": [
{
"path": "ui/alert.tsx",

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "aspect-ratio-demo",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"aspect-ratio"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "aspect-ratio",
"type": "registry:ui",
"author": "shadcn (https://ui.shadcn.com)",
"dependencies": [
"@radix-ui/react-aspect-ratio"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "avatar-demo",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"avatar"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "avatar",
"type": "registry:ui",
"author": "shadcn (https://ui.shadcn.com)",
"dependencies": [
"@radix-ui/react-avatar"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "badge-demo",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"badge"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "badge-destructive",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"badge"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "badge-outline",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"badge"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "badge-secondary",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"badge"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "badge",
"type": "registry:ui",
"author": "shadcn (https://ui.shadcn.com)",
"files": [
{
"path": "ui/badge.tsx",

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "breadcrumb-demo",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"breadcrumb"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "breadcrumb-dropdown",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"breadcrumb"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "breadcrumb-ellipsis",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"breadcrumb"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "breadcrumb-link",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"breadcrumb"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "breadcrumb-responsive",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"breadcrumb"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "breadcrumb-separator",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"breadcrumb"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "breadcrumb",
"type": "registry:ui",
"author": "shadcn (https://ui.shadcn.com)",
"dependencies": [
"@radix-ui/react-slot"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "button-as-child",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"button"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "button-demo",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"button"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "button-destructive",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"button"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "button-ghost",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"button"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "button-icon",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"button"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "button-link",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"button"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "button-loading",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"button"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "button-outline",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"button"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "button-secondary",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"button"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "button-with-icon",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"button"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "button",
"type": "registry:ui",
"author": "shadcn (https://ui.shadcn.com)",
"dependencies": [
"@radix-ui/react-slot"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "calendar-demo",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"calendar"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "calendar-form",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"calendar",
"form",

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "calendar",
"type": "registry:ui",
"author": "shadcn (https://ui.shadcn.com)",
"dependencies": [
"react-day-picker@8.10.1",
"date-fns"

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "card-demo",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"card",
"button",

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "card-with-form",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"button",
"card",

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "card",
"type": "registry:ui",
"author": "shadcn (https://ui.shadcn.com)",
"files": [
{
"path": "ui/card.tsx",

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "carousel-api",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"carousel"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "carousel-demo",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"carousel"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "carousel-orientation",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"carousel"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "carousel-plugin",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"carousel"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "carousel-size",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"carousel"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "carousel-spacing",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"carousel"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "carousel",
"type": "registry:ui",
"author": "shadcn (https://ui.shadcn.com)",
"dependencies": [
"embla-carousel-react"
],

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "chart-area-axes",
"type": "registry:block",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"card",
"chart"

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "chart-area-default",
"type": "registry:block",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"card",
"chart"

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "chart-area-gradient",
"type": "registry:block",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"card",
"chart"

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "chart-area-icons",
"type": "registry:block",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"card",
"chart"

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "chart-area-interactive",
"type": "registry:block",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"card",
"chart",

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "chart-area-legend",
"type": "registry:block",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"card",
"chart"

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "chart-area-linear",
"type": "registry:block",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"card",
"chart"

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "chart-area-stacked-expand",
"type": "registry:block",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"card",
"chart"

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "chart-area-stacked",
"type": "registry:block",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"card",
"chart"

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "chart-area-step",
"type": "registry:block",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"card",
"chart"

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "chart-bar-active",
"type": "registry:block",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"card",
"chart"

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "chart-bar-default",
"type": "registry:block",
"author": "shadcn (https://ui.shadcn.com)",
"registryDependencies": [
"card",
"chart"

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "chart-bar-demo-axis",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"files": [
{
"path": "examples/chart-bar-demo-axis.tsx",

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "chart-bar-demo-grid",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"files": [
{
"path": "examples/chart-bar-demo-grid.tsx",

View File

@@ -1,6 +1,8 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "chart-bar-demo-legend",
"type": "registry:example",
"author": "shadcn (https://ui.shadcn.com)",
"files": [
{
"path": "examples/chart-bar-demo-legend.tsx",

Some files were not shown because too many files have changed in this diff Show More