snapshot of https://github.com/shadcn-ui/ui.git (main, 2026-09-15; blobs > 131072B omitted)
All checks were successful
Release / Create Version PR or Publish Stable Release (push) Has been skipped
Release / Publish Prerelease to NPM (push) Has been skipped
Monitor Registries / Monitor registry health (push) Has been skipped

This commit is contained in:
upstream-mirror
2026-09-15 22:44:43 +05:00
commit 1416db152c
5727 changed files with 630238 additions and 0 deletions

View File

@@ -0,0 +1,238 @@
---
title: Blocks
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.ts`.
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" showLineNumbers
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="mt-6 w-full overflow-hidden rounded-2xl border dark:hidden"
/>
<Image
src="/images/block-preview-dark.png"
width="1432"
height="960"
alt="Block preview"
className="mt-6 hidden w-full overflow-hidden rounded-2xl border shadow-sm dark:block"
/>
### 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" showLineNumbers
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

@@ -0,0 +1,30 @@
---
title: Open in v0
description: Open components in v0 for customization.
---
Every component on ui.shadcn.com is editable on [v0 by Vercel](https://v0.dev). This allows you to easily customize the components in natural language and paste into your app.
<a href="https://vercel.com/signup?utm_source=shad&utm_medium=web&utm_campaign=docs_cta_signup">
<Image
src="/images/open-in-v0.png"
width="716"
height="420"
alt="Open in v0"
className="mt-6 w-full overflow-hidden rounded-2xl border dark:hidden"
/>
<Image
src="/images/open-in-v0-dark.png"
width="716"
height="420"
alt="Open in v0"
className="mt-6 hidden w-full overflow-hidden rounded-2xl border shadow-sm dark:block"
/>
<span className="sr-only">Open in v0</span>
</a>
To use v0, sign-up for a free [Vercel account here](https://vercel.com/signup?utm_source=shad&utm_medium=web&utm_campaign=docs_cta_signup). In addition to v0, this gives you free access to Vercel's frontend cloud platform by the creators of Next.js, where you can deploy and host your project for free.
Learn more about getting started with [Vercel here](https://vercel.com/docs/getting-started-with-vercel?utm_source=shadcn_site&utm_medium=web&utm_campaign=docs_cta_about_vercel).
Learn more about getting started with [v0 here](https://v0.dev/faq).

View File

@@ -0,0 +1,738 @@
---
title: shadcn
description: Use the shadcn CLI to add components to your project.
---
import { TriangleAlertIcon } from "lucide-react"
## init
Use the `init` command to initialize configuration and dependencies for an existing project, or create a new project with `--name`.
The `init` command installs dependencies, adds the `cn` util and configures CSS variables for the project.
```bash
npx shadcn@latest init
```
**Options**
```bash
Usage: shadcn init [options] [components...]
initialize your project and install dependencies
Arguments:
components names, url or local path to component
Options:
-t, --template <template> the template to use. (next, vite, start, react-router, laravel, astro)
-b, --base <base> the component library to use. (base, radix, aria)
-p, --preset [name] use a preset configuration
-y, --yes skip confirmation prompt. (default: true)
-d, --defaults use default configuration: --template=next --preset=nova (default: false)
-f, --force force overwrite of existing configuration. (default: false)
-c, --cwd <cwd> the working directory. defaults to the current directory.
-n, --name <name> the name for the new project.
-s, --silent mute output. (default: false)
--css-variables use css variables for theming. (default: true)
--no-css-variables do not use css variables for theming.
--monorepo scaffold a monorepo project.
--no-monorepo skip the monorepo prompt.
--rtl enable RTL support.
--no-rtl disable RTL support.
--pointer enable pointer cursor for buttons.
--no-pointer disable pointer cursor for buttons.
--reinstall re-install existing UI components.
--no-reinstall do not re-install existing UI components.
-h, --help display help for command
```
The `create` command is an alias for `init`:
```bash
npx shadcn@latest create
```
---
## add
Use the `add` command to add components and dependencies to your project.
```bash
npx shadcn@latest add [component]
```
**Options**
```bash
Usage: shadcn add [options] [components...]
add a component to your project
Arguments:
components name, url or local path to component
Options:
-y, --yes skip confirmation prompt. (default: false)
-o, --overwrite overwrite existing files. (default: false)
-c, --cwd <cwd> the working directory. defaults to the current directory.
-a, --all add all available components (default: false)
-p, --path <path> the path to add the component to.
-s, --silent mute output. (default: false)
--dry-run preview changes without writing files. (default: false)
--diff [path] show diff for a file.
--view [path] show file contents.
-h, --help display help for command
```
---
## apply
Use the `apply` command to apply a preset to an existing project.
```bash
npx shadcn@latest apply a2r6bw
```
You can apply only the theme or fonts from a preset without reinstalling UI components:
```bash
npx shadcn@latest apply a2r6bw --only theme
```
Supported values for `--only` are `theme` and `font`.
**Options**
```bash
Usage: shadcn apply [options] [preset]
apply a preset to an existing project
Arguments:
preset the preset to apply
Options:
--preset <preset> preset configuration to apply
--only [parts] apply only parts of a preset: theme, font
-y, --yes skip confirmation prompt. (default: false)
-c, --cwd <cwd> the working directory. defaults to the current directory.
-s, --silent mute output. (default: false)
-h, --help display help for command
```
---
## preset
Use the `preset` command to inspect preset codes and resolve the preset for an existing project.
```bash
npx shadcn@latest preset decode a2r6bw
```
### preset decode
Use `preset decode` to decode a preset code.
```bash
npx shadcn@latest preset decode a2r6bw
```
**Options**
```bash
Usage: shadcn preset decode [options] <code>
decode a preset code
Arguments:
code the preset code to decode
Options:
--json output as JSON. (default: false)
-h, --help display help for command
```
### preset resolve
Use `preset resolve` to resolve the preset from the current project.
```bash
npx shadcn@latest preset resolve
```
The `preset info` command is an alias for `preset resolve`:
```bash
npx shadcn@latest preset info
```
**Options**
```bash
Usage: shadcn preset resolve|info [options]
resolve a preset from your project
Options:
-c, --cwd <cwd> the working directory. defaults to the current directory.
--json output as JSON. (default: false)
-h, --help display help for command
```
### preset url
Use `preset url` to print the create URL for a preset code.
```bash
npx shadcn@latest preset url a2r6bw
```
**Options**
```bash
Usage: shadcn preset url [options] <code>
get the create URL for a preset code
Arguments:
code the preset code
Options:
-h, --help display help for command
```
### preset open
Use `preset open` to open a preset code in the browser.
```bash
npx shadcn@latest preset open a2r6bw
```
**Options**
```bash
Usage: shadcn preset open [options] <code>
open a preset code in the browser
Arguments:
code the preset code
Options:
-h, --help display help for command
```
---
## view
Use the `view` command to view items from the registry before installing them.
```bash
npx shadcn@latest view [item]
```
You can view multiple items at once:
```bash
npx shadcn@latest view button card dialog
```
Or view items from namespaced registries:
```bash
npx shadcn@latest view @acme/auth @v0/dashboard
```
**Options**
```bash
Usage: shadcn view [options] <items...>
view items from the registry
Arguments:
items the item names or URLs to view
Options:
-c, --cwd <cwd> the working directory. defaults to the current directory.
-h, --help display help for command
```
---
## search
Use the `search` command to search for items from registries.
```bash
npx shadcn@latest search [registry]
```
You can search with a query:
```bash
npx shadcn@latest search @shadcn -q "button"
```
Or search multiple registries at once:
```bash
npx shadcn@latest search @shadcn @v0 @acme
```
The `list` command is an alias for `search`:
```bash
npx shadcn@latest list @acme
```
**Options**
```bash
Usage: shadcn search|list [options] <registries...>
search items from registries
Arguments:
registries the registry names or urls to search items from. Names
must be prefixed with @.
Options:
-c, --cwd <cwd> the working directory. defaults to the current directory.
-q, --query <query> query string
-l, --limit <number> maximum number of items to display per registry (default: "100")
-o, --offset <number> number of items to skip (default: "0")
-h, --help display help for command
```
---
## build
Use the `build` command to generate the registry JSON files.
```bash
npx shadcn@latest build
```
This command reads the `registry.json` file and generates the registry JSON files in the `public/r` directory.
**Options**
```bash
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.
-h, --help display help for command
```
To customize the output directory, use the `--output` option.
```bash
npx shadcn@latest build --output ./public/registry
```
---
## docs
Use the `docs` command to fetch documentation and API references for components.
```bash
npx shadcn@latest docs [component]
```
**Options**
```bash
Usage: shadcn docs [options] [component]
fetch documentation and API references for components
Arguments:
component the component to get docs for
Options:
-c, --cwd <cwd> the working directory. defaults to the current directory.
-b, --base <base> the base to use: base, radix, or aria. defaults to project base.
--json output as JSON. (default: false)
-h, --help display help for command
```
---
## info
Use the `info` command to get information about your project.
```bash
npx shadcn@latest info
```
**Options**
```bash
Usage: shadcn info [options]
get information about your project
Options:
-c, --cwd <cwd> the working directory. defaults to the current directory.
--json output as JSON. (default: false)
-h, --help display help for command
```
---
## migrate
Use the `migrate` command to run migrations on your project.
```bash
npx shadcn@latest migrate [migration]
```
**Available Migrations**
| Migration | Description |
| ------------ | ------------------------------------------------------- |
| `cn` | Migrate `clsx` and `tailwind-merge` to `cn`. |
| `icons` | Migrate your UI components to a different icon library. |
| `base-color` | Migrate your theme to a different base color. |
| `radix` | Migrate to radix-ui. |
| `rtl` | Migrate your components to support RTL (right-to-left). |
**Options**
```bash
Usage: shadcn migrate [options] [migration] [path]
run a migration.
Arguments:
migration the migration to run.
path optional path or glob pattern to migrate.
Options:
-c, --cwd <cwd> the working directory. defaults to the current directory.
-l, --list list all migrations. (default: false)
-y, --yes skip confirmation prompt. (default: false)
-f, --from <name> the base color or icon library to migrate from.
-t, --to <name> the base color or icon library to migrate to.
-h, --help display help for command
```
---
### migrate cn
The `cn` migration replaces `clsx`, `tailwind-merge` and `cnfast` with [`cn`](https://github.com/shadcn-ui/cn).
```bash
npx shadcn@latest migrate cn
```
Unlike the other migrations, `migrate cn` does not require a `components.json` file. You can run it in any JavaScript or TypeScript package project using Tailwind CSS v4.
This will:
1. Rewrite imports from `clsx`, `clsx/lite`, `tailwind-merge` and `cnfast`.
2. Replace `twMerge(clsx(...))` compositions with direct `cn(...)` calls.
3. Replace the standard shadcn utility with a direct re-export.
4. Install `cn` and remove the old packages when no references remain.
**Before**
```tsx
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
```
**After**
```tsx
export { cn } from "cn"
```
The migration also preserves separate APIs when they are used independently:
```diff
- import { clsx } from "clsx"
- import { twMerge } from "tailwind-merge"
+ import { clsx, twMerge } from "cn"
```
Because `cnfast` has the same root API, its module specifiers are replaced directly:
```diff
- import { cn } from "cnfast"
+ import { cn } from "cn"
```
Custom configuration APIs are moved to `cn/config`. Existing local names are preserved when an export was renamed:
```diff
- import { createTailwindMerge, getDefaultConfig } from "tailwind-merge"
+ import {
+ createTwMerge as createTailwindMerge,
+ defaultConfig as getDefaultConfig,
+ } from "cn/config"
```
<Callout icon={<TriangleAlertIcon />}>
The `cn` merge engine supports Tailwind CSS v4, like `tailwind-merge` v3.
Projects using Tailwind CSS v3 should continue using `tailwind-merge` v2. A
`clsx`-only migration is safe in a Tailwind CSS v3 project.
</Callout>
**Migrate specific files**
You can migrate a file, directory or glob pattern:
```bash
# Migrate a specific file.
npx shadcn@latest migrate cn src/lib/utils.ts
# Migrate files matching a glob pattern.
npx shadcn@latest migrate cn "src/**/*.{ts,tsx}"
```
Scoped migrations install `cn` but keep `clsx`, `tailwind-merge` and `cnfast` in `package.json`, because files outside the selected path may still use them.
The command leaves unsupported imports unchanged and reports them for manual review. This includes `experimentalParseClassName`, namespace imports, dynamic import shapes, direct calls to `validators` and variadic `createTailwindMerge` calls that cannot be migrated safely. An old dependency is retained whenever one of its references remains.
---
### migrate icons
The `icons` migration moves your components from one icon library to another.
```bash
npx shadcn@latest migrate icons
```
This will prompt you for the source and target libraries, rewrite icon imports and JSX usage in your `ui` directory, install the target library and update `iconLibrary` in your `components.json` so future `npx shadcn add` installs use the new library.
The following libraries are supported: `lucide`, `tabler`, `hugeicons`, `phosphor`, `remixicon` and `radix` (legacy).
**Non-interactive**
Use `--from` and `--to` to skip the prompts:
```bash
npx shadcn@latest migrate icons --from lucide --to phosphor --yes
```
**Migrate specific files**
You can migrate specific files or use glob patterns. Scoped runs do not update `components.json`.
```bash
# Migrate a specific file.
npx shadcn@latest migrate icons src/components/ui/button.tsx --from lucide --to tabler
# Migrate files matching a glob pattern.
npx shadcn@latest migrate icons "src/components/**" --from lucide --to tabler
```
Icons without an equivalent in the target library are left untouched and reported at the end of the migration.
---
### migrate base-color
The `base-color` migration switches your theme from one base color to another.
```bash
npx shadcn@latest migrate base-color
```
This will prompt you for the source and target base colors, rewrite the theme CSS variables (the CSS file configured by `tailwind.css` in your `components.json`) and update `baseColor` so future `npx shadcn add` installs use the new base color.
The following base colors are supported: `neutral`, `zinc`, `stone`, `mauve`, `olive`, `mist` and `taupe`.
**Non-interactive**
Use `--to` to migrate from the current `baseColor` in your `components.json`, or pass both `--from` and `--to` explicitly.
```bash
npx shadcn@latest migrate base-color --to zinc --yes
```
Theme tokens that no longer match the source base color are left untouched and reported at the end of the migration.
---
### migrate rtl
The `rtl` migration transforms your components to support RTL (right-to-left) languages.
```bash
npx shadcn@latest migrate rtl
```
This will:
1. Update `components.json` to set `rtl: true`
2. Transform physical CSS properties to logical equivalents (e.g., `ml-4` → `ms-4`, `text-left` → `text-start`)
3. Add `rtl:` variants where needed (e.g., `space-x-4` → `space-x-4 rtl:space-x-reverse`)
**Migrate specific files**
You can migrate specific files or use glob patterns:
```bash
# Migrate a specific file
npx shadcn@latest migrate rtl src/components/ui/button.tsx
# Migrate files matching a glob pattern
npx shadcn@latest migrate rtl "src/components/ui/**"
```
If no path is provided, the migration will transform all files in your `ui` directory (from `components.json`).
---
### migrate radix
The `radix` migration updates your imports from individual `@radix-ui/react-*` packages to the unified `radix-ui` package.
```bash
npx shadcn@latest migrate radix
```
This will:
1. Transform imports from `@radix-ui/react-*` to `radix-ui`
2. Add the `radix-ui` package to your `package.json`
**Before**
```tsx
import * as DialogPrimitive from "@radix-ui/react-dialog"
import * as SelectPrimitive from "@radix-ui/react-select"
```
**After**
```tsx
import { Dialog as DialogPrimitive, Select as SelectPrimitive } from "radix-ui"
```
**Migrate specific files**
You can migrate specific files or use glob patterns:
```bash
# Migrate a specific file.
npx shadcn@latest migrate radix src/components/ui/dialog.tsx
# Migrate files matching a glob pattern.
npx shadcn@latest migrate radix "src/components/ui/**"
```
If no path is provided, the migration will transform all files in your `ui` directory (from `components.json`).
Once complete, you can remove any unused `@radix-ui/react-*` packages from your `package.json`.
---
## eject
When you run `init`, shadcn adds `@import "shadcn/tailwind.css"` to your global CSS file. This import provides shared Tailwind v4 utilities such as custom variants (`data-open:`, `data-closed:`, etc.) and accordion animations.
Use the `eject` command to inline `shadcn/tailwind.css` into your global CSS file and remove the `shadcn` dependency from your project.
<Callout icon={<TriangleAlertIcon />}>
**Note: This action is irreversible.** After ejecting, future shadcn CLI
updates to `shadcn/tailwind.css` will not apply automatically.
</Callout>
```bash
npx shadcn@latest eject
```
**Before**
```css
@import "tailwindcss";
@import "tw-animate-css";
@import "shadcn/tailwind.css";
```
**After**
```css
@import "tailwindcss";
@import "tw-animate-css";
/* ejected from shadcn@4.8.3 */
@theme inline {
@keyframes accordion-down {
from {
height: 0;
}
to {
height: var(
--radix-accordion-content-height,
var(--accordion-panel-height, auto)
);
}
}
}
@custom-variant data-open {
&:where([data-state="open"]),
&:where([data-open]:not([data-open="false"])) {
@slot;
}
}
@utility no-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
}
```
**Monorepo**
In a monorepo, run the command from the workspace that contains your `components.json` and global CSS file:
```bash
npx shadcn@latest eject -c packages/ui
```
**Options**
```bash
Usage: shadcn eject [options]
inline shadcn/tailwind.css and remove the shadcn dependency
Options:
-c, --cwd <cwd> the working directory. defaults to the current directory.
-y, --yes skip confirmation prompt. (default: false)
-s, --silent mute output. (default: false)
-h, --help display help for command
```

View File

@@ -0,0 +1,379 @@
---
title: components.json
description: Configuration for your project.
---
The `components.json` file holds configuration for your project.
We use it to understand how your project is set up and how to generate components customized for your project.
<Callout className="mt-6" title="Note: The `components.json` file is optional">
It is **only required if you're using the CLI** to add components to your
project. If you're using the copy and paste method, you don't need this file.
</Callout>
You can create a `components.json` file in your project by running the following command:
```bash
npx shadcn@latest init
```
See the <Link href="/docs/cli">CLI section</Link> for more information.
## $schema
You can see the JSON Schema for `components.json` [here](https://ui.shadcn.com/schema.json).
```json title="components.json"
{
"$schema": "https://ui.shadcn.com/schema.json"
}
```
## style
The style for your components. **This cannot be changed after initialization.**
```json title="components.json"
{
"style": "new-york"
}
```
The `default` style has been deprecated. Use the `new-york` style instead.
## tailwind
Configuration to help the CLI understand how Tailwind CSS is set up in your project.
See the <Link href="/docs/installation">installation section</Link> for how to set up Tailwind CSS.
### tailwind.config
Path to where your `tailwind.config.js` file is located. **For Tailwind CSS v4, leave this blank.**
```json title="components.json"
{
"tailwind": {
"config": "tailwind.config.js" | "tailwind.config.ts"
}
}
```
### tailwind.css
Path to the CSS file that imports Tailwind CSS into your project.
```json title="components.json"
{
"tailwind": {
"css": "styles/global.css"
}
}
```
### tailwind.baseColor
This is used to generate the default theme tokens for your components. **This cannot be changed after initialization.**
```json title="components.json"
{
"tailwind": {
"baseColor": "neutral" | "stone" | "zinc" | "mauve" | "olive" | "mist" | "taupe"
}
}
```
### tailwind.cssVariables
We use and recommend CSS variables for theming.
Set `tailwind.cssVariables` to `true` to generate semantic theme tokens like `background`, `foreground`, and `primary`. Set it to `false` to generate inline Tailwind color utilities instead.
```json title="components.json"
{
"tailwind": {
"cssVariables": `true` | `false`
}
}
```
For more information, see the <Link href="/docs/theming">theming docs</Link>.
**This cannot be changed after initialization.** To switch between CSS variables and utility classes, you'll have to delete and re-install your components.
### tailwind.prefix
The prefix to use for your Tailwind CSS utility classes. Components will be added with this prefix.
```json title="components.json"
{
"tailwind": {
"prefix": "tw-"
}
}
```
## rsc
Whether or not to enable support for React Server Components.
The CLI automatically adds a `use client` directive to client components when set to `true`.
```json title="components.json"
{
"rsc": `true` | `false`
}
```
## tsx
Choose between TypeScript or JavaScript components.
Setting this option to `false` allows components to be added as JavaScript with the `.jsx` file extension.
```json title="components.json"
{
"tsx": `true` | `false`
}
```
## aliases
The CLI uses these values to place generated components in the correct location and rewrite imports.
You can back these aliases with either:
1. `compilerOptions.paths` in your `tsconfig.json` or `jsconfig.json`
2. `package.json#imports` with TypeScript package import resolution enabled
The aliases in `components.json` are still required when using the CLI. They tell the CLI which import roots map to `components`, `ui`, `lib`, `hooks`, and `utils`.
<Callout className="mt-6">
**Important:** If you're using package imports, enable
`resolvePackageJsonImports` and use `moduleResolution: "bundler"` in your
`tsconfig.json`. If you're using `paths`, make sure your aliases include the
`src` directory when applicable.
</Callout>
### Using `tsconfig` or `jsconfig` paths
```json title="tsconfig.json"
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
```
### Using `package.json#imports`
Recommended setup for a single-package app:
```json title="package.json"
{
"imports": {
"#components/*": "./src/components/*.tsx",
"#lib/*": "./src/lib/*.ts",
"#hooks/*": "./src/hooks/*.ts"
}
}
```
```json title="tsconfig.json"
{
"compilerOptions": {
"moduleResolution": "bundler",
"resolvePackageJsonImports": true
}
}
```
```json title="components.json"
{
"aliases": {
"components": "#components",
"ui": "#components/ui",
"lib": "#lib",
"hooks": "#hooks",
"utils": "#lib/utils"
}
}
```
The aliases in `components.json` still tell the CLI where to place
`components`, `ui`, `lib`, `hooks`, and `utils`. `package.json#imports`
provides the runtime and TypeScript resolution for those `#...` specifiers.
The matched `imports` target also controls whether generated `#...` imports keep
file extensions:
- `"#components/*": "./src/components/*"` preserves source extensions and can
generate imports like
`#components/button.tsx`
- `"#components/*": "./src/components/*.tsx"` strips source extensions and
generates imports like
`#components/button`
For monorepos, see the <Link href="/docs/monorepo">monorepo docs</Link>. Local
workspace aliases can use `package.json#imports`, while shared workspace
imports such as `@workspace/ui/components` are resolved from the target
package's `exports`.
For framework-specific setup, see the [package imports guide](/docs/package-imports).
### aliases.utils
Import alias for your utility functions.
```json title="components.json"
{
"aliases": {
"utils": "@/lib/utils"
}
}
```
### aliases.components
Import alias for your components.
```json title="components.json"
{
"aliases": {
"components": "@/components"
}
}
```
### aliases.ui
Import alias for `ui` components.
The CLI will use the `aliases.ui` value to determine where to place your `ui` components. Use this config if you want to customize the installation directory for your `ui` components.
```json title="components.json"
{
"aliases": {
"ui": "@/app/ui"
}
}
```
### aliases.lib
Import alias for `lib` functions such as `format-date` or `generate-id`.
```json title="components.json"
{
"aliases": {
"lib": "@/lib"
}
}
```
### aliases.hooks
Import alias for `hooks` such as `use-media-query` or `use-toast`.
```json title="components.json"
{
"aliases": {
"hooks": "@/hooks"
}
}
```
## registries
Configure multiple resource registries for your project. This allows you to install components, libraries, utilities, and other resources from various sources including private registries.
See the <Link href="/docs/registry/namespace">Namespaced Registries</Link> documentation for detailed information.
### Basic Configuration
Configure registries with URL templates:
```json title="components.json"
{
"registries": {
"@v0": "https://v0.dev/chat/b/{name}",
"@acme": "https://registry.acme.com/{name}.json",
"@internal": "https://internal.company.com/{name}.json"
}
}
```
The `{name}` placeholder is replaced with the resource name when installing.
### Advanced Configuration with Authentication
For private registries that require authentication:
```json title="components.json"
{
"registries": {
"@private": {
"url": "https://api.company.com/registry/{name}.json",
"headers": {
"Authorization": "Bearer ${REGISTRY_TOKEN}",
"X-API-Key": "${API_KEY}"
},
"params": {
"version": "latest"
}
}
}
}
```
Environment variables in the format `${VAR_NAME}` are automatically expanded from your environment.
### Using Namespaced Registries
Once configured, install resources using the namespace syntax:
```bash
# Install from a configured registry
npx shadcn@latest add @v0/dashboard
# Install from private registry
npx shadcn@latest add @private/button
# Install multiple resources
npx shadcn@latest add @acme/header @internal/auth-utils
```
### Example: Multiple Registry Setup
```json title="components.json"
{
"registries": {
"@shadcn": "https://ui.shadcn.com/r/{name}.json",
"@company-ui": {
"url": "https://registry.company.com/ui/{name}.json",
"headers": {
"Authorization": "Bearer ${COMPANY_TOKEN}"
}
},
"@team": {
"url": "https://team.company.com/{name}.json",
"params": {
"team": "frontend",
"version": "${REGISTRY_VERSION}"
}
}
}
}
```
This configuration allows you to:
- Install public components from shadcn/ui
- Access private company UI components with authentication
- Use team-specific resources with versioning
For more information about authentication, see the <Link href="/docs/registry/authentication">Authentication</Link> documentation.

View File

@@ -0,0 +1,74 @@
---
title: Registry Directory
description: Discover community registries for shadcn/ui components and blocks.
---
These registries are built into the CLI with no additional configuration required. To add a component, run: `npx shadcn add @<registry>/<component>`.
<Callout className="bg-muted font-semibold">
Community registries are maintained by third-party developers. Always review
code on installation to ensure it meets your security and quality standards.
</Callout>
Don't see a registry? Learn how to [add it here](/docs/registry/registry-index).
<DirectoryList />
## Documentation
You can use the `shadcn` CLI to run your own code registry. Running your own registry allows you to distribute your custom components, hooks, pages, config, rules and other files to any project.
<div className="mt-6 grid gap-4 sm:grid-cols-2">
<LinkedCard href="/docs/registry/getting-started" className="items-start text-sm md:p-6">
<div className="font-medium">Getting Started</div>
<div className="text-muted-foreground">
Set up and build your own registry
</div>
</LinkedCard>
<LinkedCard
href="/docs/registry/authentication"
className="items-start text-sm md:p-6"
>
<div className="font-medium">Authentication</div>
<div className="text-muted-foreground">
Secure your registry with authentication
</div>
</LinkedCard>
<LinkedCard
href="/docs/registry/namespace"
className="items-start text-sm md:p-6"
>
<div className="font-medium">Namespaces</div>
<div className="text-muted-foreground">
Configure registries with namespaces
</div>
</LinkedCard>
<LinkedCard
href="/docs/registry/registry-index"
className="items-start text-sm md:p-6"
>
<div className="font-medium">Add a Registry</div>
<div className="text-muted-foreground">
Learn how to add a registry to the directory
</div>
</LinkedCard>
<LinkedCard
href="/docs/registry/examples"
className="items-start text-sm md:p-6"
>
<div className="font-medium">Examples</div>
<div className="text-muted-foreground">
Registry item examples and configurations
</div>
</LinkedCard>
<LinkedCard
href="/docs/registry/registry-json"
className="items-start text-sm md:p-6"
>
<div className="font-medium">Schema</div>
<div className="text-muted-foreground">
Schema specification for registry.json
</div>
</LinkedCard>
</div>

View File

@@ -0,0 +1,26 @@
---
title: Figma
description: Every component recreated in Figma. With customizable props, typography and icons.
---
<Callout>
**Note:** The Figma files are contributed by the community. If you have any
questions or feedback, please reach out to the Figma file maintainers.
</Callout>
## Free
- [shadcn/ui components](https://www.figma.com/community/file/1342715840824755935) by [Sitsiilia Bergmann](https://x.com/sitsiilia) - A well-structured component library aligned with the shadcn component system, regularly maintained.
- [shadcn/ui design system](https://www.figma.com/community/file/1203061493325953101) by [Pietro Schirano](https://twitter.com/skirano) - A design companion for shadcn/ui. Each component was painstakingly crafted to perfectly match the code implementation.
- [Obra shadcn/ui Community Edition](https://www.figma.com/community/file/1514746685758799870/) by [Obra Studio](https://obra.studio/) - The most complete free shadcn/ui kit for Figma, with all components and an easy theming system. Maintained by a team of designers.
- [shadcncraft Free Starter Kit](https://www.figma.com/community/file/1534076420225325960) by [shadcncraft](https://shadcncraft.com) - Native Figma variables for all eight shadcn/ui styles, import themes from tweakcn and shadcn/ui Create, icon switching, and matching React components. Actively maintained.
## Paid
- [shadcn/ui kit](https://shadcndesign.com) by [Matt Wierzbicki](https://x.com/matsugfx) - A premium, always up-to-date UI kit for Figma - shadcn/ui compatible and optimized for smooth design-to-dev handoff.
- [shadcncraft – shadcn/ui Figma kit](https://shadcncraft.com/figma) - All eight shadcn styles and hundreds of Pro components and blocks with matching React code. The plugin builds new styles, loads custom shadcn presets and tweakcn themes, and exports frames to React; agent skills turn designs into code through the Figma MCP.
- [shadcn/studio UI Kit](https://shadcnstudio.com/figma) - Accelerate design & development with a shadcn/ui compatible Figma kit with updated components, 550+ blocks, 10+ templates, 20+ themes, and an AI tool that converts designs into shadcn/ui code.
- [Shadcnblocks.com](https://www.shadcnblocks.com) - A Premium Shadcn Figma UI Kit with components, 500+ pro blocks, shadcn theme variables, light/dark mode and Figma MCP ready.
- [Obra shadcn/ui Pro](https://shadcn.obra.studio/products/obra-shadcn-ui-pro) by [Obra Studio](https://obra.studio/) - The best designer experience for shadcn/ui within Figma. All 8 styles, consistency with shadcn, Pro blocks, and a design-to-code plugin.
- [Shadcn Space](https://shadcnspace.com/figma) - A collection of beautifully designed 320+ blocks, 9+ templates, and 250+ components with a shadcn/ui-compatible Figma kit built for modern React and Next.js workflows. Design, prototype, and ship faster using Figma components that mirror real code architecture and production-ready implementation patterns.
- [Shadcn Design System](https://shadcnstore.com/) by [ShadcnStore](https://x.com/shadcnstore) - A complete Figma UI kit for shadcn/ui with components, variants, design tokens, production-ready blocks and templates. Built for fast workflows and pixel-perfect designer-to-developer handoff.

View File

@@ -0,0 +1,77 @@
---
title: Introduction
description: shadcn/ui is a set of beautifully-designed, accessible components and a code distribution platform. Works with your favorite frameworks and AI models. Open Source. Open Code.
---
**This is not a component library. It is how you build your component library.**
You know how most traditional component libraries work: you install a package from NPM, import the components, and use them in your app.
This approach works well until you need to customize a component to fit your design system or require one that isn’t included in the library. **Often, you end up wrapping library components, writing workarounds to override styles, or mixing components from different libraries with incompatible APIs.**
This is what shadcn/ui aims to solve. It is built around the following principles:
- **Open Code:** The top layer of your component code is open for modification.
- **Composition:** Every component uses a common, composable interface, making them predictable.
- **Distribution:** A flat-file schema and command-line tool make it easy to distribute components.
- **Beautiful Defaults:** Carefully chosen default styles, so you get great design out-of-the-box.
- **AI-Ready:** Open code for LLMs to read, understand, and improve.
## Open Code
shadcn/ui hands you the actual component code. You have full control to customize and extend the components to your needs. This means:
- **Full Transparency:** You see exactly how each component is built.
- **Easy Customization:** Modify any part of a component to fit your design and functionality requirements.
- **AI Integration:** Access to the code makes it straightforward for LLMs to read, understand, and even improve your components.
_In a typical library, if you need to change a button’s behavior, you have to override styles or wrap the component. With shadcn/ui, you simply edit the button code directly._
<Accordion type="single" collapsible>
<AccordionItem value="faq-1" className="border-none">
<AccordionTrigger>
How do I pull upstream updates in an Open Code approach?
</AccordionTrigger>
<AccordionContent className="flex flex-col gap-4">
<p>
shadcn/ui follows a headless component architecture. This means the core
of your app can receive fixes by updating your dependencies, for
instance, @base-ui/react or input-otp.
</p>
<p>
The topmost layer, i.e., the one closest to your design system, is not
coupled with the implementation of the library. It stays open for
modification.
</p>
</AccordionContent>
</AccordionItem>
</Accordion>
## Composition
Every component in shadcn/ui shares a common, composable interface. **If a component does not exist, we bring it in, make it composable, and adjust its style to match and work with the rest of the design system.**
_A shared, composable interface means it's predictable for both your team and LLMs. You are not learning different APIs for every new component. Even for third-party ones._
## Distribution
shadcn/ui is also a code distribution system. It defines a schema for components and a CLI to distribute them.
- **Schema:** A flat-file structure that defines the components, their dependencies, and properties.
- **CLI:** A command-line tool to distribute and install components across projects with cross-framework support.
_You can use the schema to distribute your components to other projects or have AI generate completely new components based on existing schema._
## Beautiful Defaults
shadcn/ui comes with a large collection of components that have carefully chosen default styles. They are designed to look good on their own and to work well together as a consistent system:
- **Good Out-of-the-Box:** Your UI has a clean and minimal look without extra work.
- **Unified Design:** Components naturally fit with one another. Each component is built to match the others, keeping your UI consistent.
- **Easily Customizable:** If you want to change something, it's simple to override and extend the defaults.
## AI-Ready
The design of shadcn/ui makes it easy for AI tools to work with your code. Its open code and consistent API allow AI models to read, understand, and even generate new components.
_An AI model can learn how your components work and suggest improvements or even create new components that integrate with your existing design._

View File

@@ -0,0 +1,44 @@
---
title: JavaScript
description: How to use shadcn/ui with JavaScript
---
This project and the components are written in TypeScript. We recommend using TypeScript for your project as well.
However we provide a JavaScript version of the components as well. The JavaScript version is available via the [cli](/docs/cli).
To opt-out of TypeScript, you can use the `tsx` flag in your `components.json` file.
```json {4} title="components.json" showLineNumbers
{
"style": "new-york",
"rsc": false,
"tsx": false,
"tailwind": {
"config": "",
"css": "src/app/globals.css",
"baseColor": "zinc",
"cssVariables": true
},
"iconLibrary": "lucide",
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
}
}
```
To configure import aliases, you can use the following `jsconfig.json`:
```json {4} title="jsconfig.json" showLineNumbers
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}
```

View File

@@ -0,0 +1,12 @@
---
title: Legacy Docs
description: View the legacy docs for shadcn/ui and Tailwind v3.
---
You're looking at the docs for shadcn/ui + Tailwind v4. If you're looking for the docs for shadcn/ui + Tailwind v3, you can find them [here](https://v3.shadcn.com).
<Button asChild className="mt-6 no-underline" size="sm">
<Link href="https://v3.shadcn.com" target="_blank">
View the legacy docs
</Link>
</Button>

View File

@@ -0,0 +1,338 @@
---
title: MCP Server
description: Use the shadcn MCP server to browse, search, and install components from registries.
---
The shadcn MCP Server allows AI assistants to interact with items from registries. You can browse available components, search for specific ones, and install them directly into your project using natural language.
For example, you can ask an AI assistant to "Build a landing page using components from the acme registry" or "Find me a login form from the shadcn registry".
Registries are configured in your project's `components.json` file.
```json title="components.json" showLineNumbers
{
"registries": {
"@acme": "https://acme.com/r/{name}.json"
}
}
```
---
## Quick Start
Select your MCP client and follow the instructions to configure the shadcn MCP server. If you'd like to do it manually, see the [Configuration](#configuration) section.
<Tabs defaultValue="claude">
<TabsList>
<TabsTrigger value="claude">Claude Code</TabsTrigger>
<TabsTrigger value="cursor">Cursor</TabsTrigger>
<TabsTrigger value="vscode">VS Code</TabsTrigger>
<TabsTrigger value="codex">Codex</TabsTrigger>
<TabsTrigger value="opencode">OpenCode</TabsTrigger>
</TabsList>
<TabsContent value="claude" className="mt-4">
**Run the following command** in your project:
```bash
npx shadcn@latest mcp init --client claude
```
**Restart Claude Code** and try the following prompts:
- Show me all available components in the shadcn registry
- Add the button, dialog and card components to my project
- Create a contact form using components from the shadcn registry
**Note:** You can use `/mcp` command in Claude Code to debug the MCP server.
</TabsContent>
<TabsContent value="cursor" className="mt-4">
**Run the following command** in your project:
```bash
npx shadcn@latest mcp init --client cursor
```
Open **Cursor Settings** and **Enable the MCP server** for shadcn. Then try the following prompts:
- Show me all available components in the shadcn registry
- Add the button, dialog and card components to my project
- Create a contact form using components from the shadcn registry
</TabsContent>
<TabsContent value="vscode" className="mt-4">
**Run the following command** in your project:
```bash
npx shadcn@latest mcp init --client vscode
```
Open `.vscode/mcp.json` and click **Start** next to the shadcn server. Then try the following prompts with GitHub Copilot:
- Show me all available components in the shadcn registry
- Add the button, dialog and card components to my project
- Create a contact form using components from the shadcn registry
</TabsContent>
<TabsContent value="codex" className="mt-4">
<Callout className="mt-0">
**Note:** The `shadcn` CLI cannot automatically update `~/.codex/config.toml`.
You'll need to add the configuration manually for Codex.
</Callout>
**Run the following command** in your project:
```bash
npx shadcn@latest mcp init --client codex
```
**Then, add the following configuration** to `~/.codex/config.toml`:
```toml
[mcp_servers.shadcn]
command = "npx"
args = ["shadcn@latest", "mcp"]
```
**Restart Codex** and try the following prompts:
- Show me all available components in the shadcn registry
- Add the button, dialog and card components to my project
- Create a contact form using components from the shadcn registry
</TabsContent>
<TabsContent value="opencode" className="mt-4">
**Run the following command** in your project:
```bash
npx shadcn@latest mcp init --client opencode
```
**Restart OpenCode** and try the following prompts:
- Show me all available components in the shadcn registry
- Add the button, dialog and card components to my project
- Create a contact form using components from the shadcn registry
</TabsContent>
</Tabs>
---
## What is MCP?
[Model Context Protocol (MCP)](https://modelcontextprotocol.io) is an open protocol that enables AI assistants to securely connect to external data sources and tools. With the shadcn MCP server, your AI assistant gains direct access to:
- **Browse Components** - List all available components, blocks, and templates from any configured registry
- **Search Across Registries** - Find specific components by name or functionality across multiple sources
- **Install with Natural Language** - Add components using simple conversational prompts like "add a login form"
- **Support for Multiple Registries** - Access public registries, private company libraries, and third-party sources
---
## How It Works
The MCP server acts as a bridge between your AI assistant, component registries and the shadcn CLI.
1. **Registry Connection** - MCP connects to configured registries (shadcn/ui, private registries, third-party sources)
2. **Natural Language** - You describe what you need in plain English
3. **AI Processing** - The assistant translates your request into registry commands
4. **Component Delivery** - Resources are fetched and installed in your project
---
## Supported Registries
The shadcn MCP server works out of the box with any shadcn-compatible registry.
- **shadcn/ui Registry** - The default registry with all shadcn/ui components
- **Third-Party Registries** - Any registry following the shadcn registry specification
- **Private Registries** - Your company's internal component libraries
- **Namespaced Registries** - Multiple registries configured with `@namespace` syntax
---
## Configuration
You can use any MCP client to interact with the shadcn MCP server. Here are the instructions for the most popular ones.
### Claude Code
To use the shadcn MCP server with Claude Code, add the following configuration to your project's `.mcp.json` file:
```json title=".mcp.json" showLineNumbers
{
"mcpServers": {
"shadcn": {
"command": "npx",
"args": ["shadcn@latest", "mcp"]
}
}
}
```
After adding the configuration, restart Claude Code and run `/mcp` to see the shadcn MCP server in the list. If you see `Connected`, you're good to go.
See the [Claude Code MCP documentation](https://code.claude.com/docs/en/mcp) for more details.
### Cursor
To configure MCP in Cursor, add the shadcn server to your project's `.cursor/mcp.json` configuration file:
```json title=".cursor/mcp.json" showLineNumbers
{
"mcpServers": {
"shadcn": {
"command": "npx",
"args": ["shadcn@latest", "mcp"]
}
}
}
```
After adding the configuration, enable the shadcn MCP server in Cursor Settings.
Once enabled, you should see a green dot next to the shadcn server in the MCP server list and a list of available tools.
See the [Cursor MCP documentation](https://docs.cursor.com/en/context/mcp#using-mcp-json) for more details.
### VS Code
To configure MCP in VS Code with GitHub Copilot, add the shadcn server to your project's `.vscode/mcp.json` configuration file:
```json title=".vscode/mcp.json" showLineNumbers
{
"servers": {
"shadcn": {
"command": "npx",
"args": ["shadcn@latest", "mcp"]
}
}
}
```
After adding the configuration, open `.vscode/mcp.json` and click **Start** next to the shadcn server.
See the [VS Code MCP documentation](https://code.visualstudio.com/docs/copilot/chat/mcp-servers) for more details.
### Codex
<Callout>
**Note:** The `shadcn` CLI cannot automatically update `~/.codex/config.toml`.
You'll need to add the configuration manually.
</Callout>
To configure MCP in Codex, add the shadcn server to `~/.codex/config.toml`:
```toml title="~/.codex/config.toml" showLineNumbers
[mcp_servers.shadcn]
command = "npx"
args = ["shadcn@latest", "mcp"]
```
After adding the configuration, restart Codex to load the MCP server.
---
## Configuring Registries
The MCP server supports multiple registries through your project's `components.json` configuration. This allows you to access components from various sources including private registries and third-party providers.
Configure additional registries in your `components.json`:
```json title="components.json" showLineNumbers
{
"registries": {
"@acme": "https://registry.acme.com/{name}.json",
"@internal": {
"url": "https://internal.company.com/{name}.json",
"headers": {
"Authorization": "Bearer ${REGISTRY_TOKEN}"
}
}
}
}
```
<Callout>
**Note:** No configuration is needed to access the standard shadcn/ui
registry.
</Callout>
---
## Authentication
For private registries requiring authentication, set environment variables in your `.env.local`:
```bash title=".env.local"
REGISTRY_TOKEN=your_token_here
API_KEY=your_api_key_here
```
For more details on registry authentication, see the [Authentication documentation](/docs/registry/authentication).
---
## Example Prompts
Once the MCP server is configured, you can use natural language to interact with registries. Try one of the following prompts:
### Browse & Search
- Show me all available components in the shadcn registry
- Find me a login form from the shadcn registry
### Install Items
- Add the button component to my project
- Create a login form using shadcn components
- Install the Cursor rules from the acme registry
### Work with Namespaces
- Show me components from acme registry
- Install @internal/auth-form
- Build me a landing page using hero, features and testimonials sections from the acme registry
---
## Troubleshooting
### MCP Not Responding
If the MCP server isn't responding to prompts:
1. **Check Configuration** - Verify the MCP server is properly configured and enabled in your MCP client
2. **Restart MCP Client** - Restart your MCP client after configuration changes
3. **Verify Installation** - Ensure `shadcn` is installed in your project
4. **Check Network** - Confirm you can access the configured registries
### Registry Access Issues
If components aren't loading from registries:
1. **Check components.json** - Verify registry URLs are correct
2. **Test Authentication** - Ensure environment variables are set for private registries
3. **Verify Registry** - Confirm the registry is online and accessible
4. **Check Namespace** - Ensure namespace syntax is correct (`@namespace/component`)
### Installation Failures
If components fail to install:
1. **Check Project Setup** - Ensure you have a valid `components.json` file
2. **Verify Paths** - Confirm the target directories exist
3. **Check Permissions** - Ensure write permissions for component directories
4. **Review Dependencies** - Check that required dependencies are installed
### No Tools or Prompts
If you see the `No tools or prompts` message, try the following:
1. **Clear the npx cache** - Run `npx clear-npx-cache`
2. **Re-enable the MCP server** - Try to re-enable the MCP server in your MCP client
3. **Check Logs** - In Cursor, you can see the logs under View -> Output and select `MCP: project-*` in the dropdown.
---
## Learn More
- [Registry Documentation](/docs/registry) - Complete guide to shadcn registries
- [Namespaces](/docs/registry/namespace) - Configure multiple registry sources
- [Authentication](/docs/registry/authentication) - Secure your private registries
- [MCP Specification](https://modelcontextprotocol.io) - Learn about Model Context Protocol

View File

@@ -0,0 +1,24 @@
{
"title": "Get Started",
"pages": [
"index",
"[Installation](/docs/installation)",
"components-json",
"package-imports",
"theming",
"typeset",
"[Dark Mode](/docs/dark-mode)",
"[RTL](/docs/rtl)",
"[CLI](/docs/cli)",
"monorepo",
"skills",
"javascript",
"blocks",
"figma",
"[Changelog](/docs/changelog)",
"[llms.txt](/llms.txt)",
"legacy",
"!official",
"!new"
]
}

View File

@@ -0,0 +1,254 @@
---
title: Monorepo
description: Using shadcn/ui components and CLI in a monorepo.
---
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 with the `--monorepo` flag.
```bash
npx shadcn@latest init --monorepo
```
Then select the template you want to use.
```bash
? Select a template ›
❯ Next.js
Vite
TanStack Start
React Router
Astro
```
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@latest 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@latest 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@latest 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 showLineNumbers title="apps/web/components.json"
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "base-nova",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "",
"css": "../../packages/ui/src/styles/globals.css",
"baseColor": "neutral",
"cssVariables": true
},
"iconLibrary": "lucide",
"aliases": {
"components": "@/components",
"hooks": "@/hooks",
"lib": "@/lib",
"utils": "@workspace/ui/lib/utils",
"ui": "@workspace/ui/components"
}
}
```
```json showLineNumbers title="packages/ui/components.json"
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "base-nova",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/styles/globals.css",
"baseColor": "neutral",
"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.
4. **For Tailwind CSS v4, leave the `tailwind` config empty in the `components.json` file.**
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.
<Callout className="mt-6">
`package.json#imports` works well for package-local aliases inside a
workspace, for example inside `packages/ui`. For shared workspace imports such
as `@workspace/ui/components`, keep explicit aliases in `components.json`. The
CLI uses those aliases to route files across workspace boundaries.
</Callout>
## Using `package.json#imports`
For a monorepo that uses package imports and does not rely on
`tsconfig.json` `paths`, use:
- local `#...` aliases for files inside each workspace
- workspace package `exports` for shared imports such as
`@workspace/ui/components`
For example, an app workspace can use local package imports:
```json showLineNumbers title="apps/web/package.json"
{
"name": "web",
"private": true,
"type": "module",
"imports": {
"#components/*": "./src/components/*.tsx",
"#lib/*": "./src/lib/*.ts",
"#hooks/*": "./src/hooks/*.ts"
},
"dependencies": {
"@workspace/ui": "workspace:*"
}
}
```
```json showLineNumbers title="apps/web/components.json"
{
"aliases": {
"components": "#components",
"ui": "@workspace/ui/components",
"lib": "#lib",
"hooks": "#hooks",
"utils": "@workspace/ui/lib/utils"
}
}
```
And the shared UI package can expose its install targets with `exports`:
```json showLineNumbers title="packages/ui/package.json"
{
"name": "@workspace/ui",
"private": true,
"type": "module",
"imports": {
"#components/*": "./src/components/*.tsx",
"#lib/*": "./src/lib/*.ts",
"#hooks/*": "./src/hooks/*.ts"
},
"exports": {
"./globals.css": "./src/styles/globals.css",
"./components/*": "./src/components/*.tsx",
"./lib/*": "./src/lib/*.ts",
"./hooks/*": "./src/hooks/*.ts"
}
}
```
```json showLineNumbers title="packages/ui/components.json"
{
"aliases": {
"components": "#components",
"ui": "#components",
"lib": "#lib",
"hooks": "#hooks",
"utils": "#lib/utils"
}
}
```
In this setup:
- files added from the app to the shared UI package are routed through
`@workspace/ui/...`
- files added inside `packages/ui` use the package-local `#...` aliases
- the shared package must export any path referenced by another workspace
For framework-specific package import setup, see the [package imports guide](/docs/package-imports).

View File

@@ -0,0 +1,106 @@
---
title: Your project is ready!
description: You've created a new project with shadcn/ui.
---
Here are a few things you can do to get started building with shadcn/ui.
## Add Components
Use the CLI to add components to your project.
```bash
npx shadcn@latest add button
```
Then import and use it in your code.
```tsx title="app/page.tsx"
import { Button } from "@/components/ui/button"
export default function Home() {
return <Button>Click me</Button>
}
```
Unlike traditional component libraries, shadcn/ui adds the component source code directly to your project under `components/ui/`. You own the code and can customize it however you want.
You can add multiple components at once or add all available components.
```bash
npx shadcn@latest add button card input label
```
```bash
npx shadcn@latest add --all
```
Browse all components on the [Components](/docs/components) page.
## Customize Your Theme
You can edit your theme directly in your CSS file. Learn more about [Theming](/docs/theming) and how to use CSS variables or utility classes.
If you want to try a new preset, you can create a custom theme visually on [ui.shadcn.com](https://ui.shadcn.com) and apply it to your project using a preset code.
```bash
npx shadcn@latest init --preset [CODE]
```
## Add a block
You can add a block to your project using the CLI.
```bash
npx shadcn@latest add login-03
```
This will add the `login-03` block to your project. Import and use it in your code.
```tsx title="app/page.tsx"
import { Login03 } from "@/components/login-03"
export default function Home() {
return <Login03 />
}
```
## Install from Registries
shadcn/ui has a growing ecosystem of community registries. You can install components from any registry URL using the CLI.
```bash
npx shadcn@latest add @[registry]/[name]
```
Browse the [Registry Directory](/docs/directory) for a list of available registries.
## Use AI to Build
shadcn/ui is designed to work with AI. Your AI assistant can read the component source code in your project, understand the APIs, and compose them together to build pages and features.
Here are some example prompts to try:
- _"Create a signup page with a form for entering name, email and password."_
- _"Create a settings page with a form for updating profile information."_
- _"Build a dashboard with a header, stats cards, and a data table."_
## Install the shadcn Skills
Install the shadcn skill in your AI assistant. This will give your AI assistant access to the full component registry, documentation, and search.
```bash
npx skills add shadcn/ui
```
Learn more about [skills](/docs/skills).
## Connect the MCP Server
The shadcn MCP server gives your AI assistant access to the full component registry, documentation, and search. Connect it in your editor for the best experience.
```bash
npx shadcn@latest mcp init
```
Learn more on the [MCP Server](/docs/mcp) page.

View File

@@ -0,0 +1,19 @@
---
title: Official shadcn/ui Website
description: The official website for shadcn/ui is ui.shadcn.com. Verify the documentation, source code, CLI, packages, and social accounts maintained by the project.
---
The official website for shadcn/ui is [ui.shadcn.com](https://ui.shadcn.com).
## Official resources
- **Website:** [ui.shadcn.com](https://ui.shadcn.com) is the official website and component documentation.
- **Source code:** [github.com/shadcn-ui/ui](https://github.com/shadcn-ui/ui) is the official source repository for shadcn/ui and the CLI.
- **CLI package:** [npmjs.com/package/shadcn](https://www.npmjs.com/package/shadcn) is the official `shadcn` package published on npm.
- **Project updates:** [@shadcn](https://twitter.com/shadcn) publishes official announcements and project updates.
## Third-party resources
Community websites and registries may use shadcn/ui components or the shadcn CLI, but they are independent unless they are explicitly identified as maintained by shadcn/ui on this page.
Review third-party code before installing it in your project. Browse community-maintained registries in the official [Registry Directory](/docs/directory).

View File

@@ -0,0 +1,234 @@
---
title: Package Imports
description: Configure shadcn/ui with package.json imports.
---
The `shadcn` CLI supports [package imports](https://nodejs.org/api/packages.html#imports)
for installing components, rewriting imports, and resolving third-party
registries.
Package imports let you use private `#...` import aliases from your
`package.json` instead of `compilerOptions.paths` in `tsconfig.json`.
## Example
You configure `imports` in your `package.json`:
```json title="package.json" showLineNumbers
{
"imports": {
"#components/*": "./src/components/*.tsx",
"#lib/*": "./src/lib/*.ts",
"#hooks/*": "./src/hooks/*.ts"
}
}
```
Then import generated components using `#...` specifiers:
```tsx
import { Button } from "#components/ui/button"
import { cn } from "#lib/utils"
```
<Callout className="mt-6">
Package import specifiers must start with `#`. Use TypeScript 5 or later with
`moduleResolution: "bundler"` and `resolvePackageJsonImports: true`.
</Callout>
## App
For Next.js, Vite, and TanStack Start apps that install
components into the same workspace.
<Steps>
### Configure `package.json`
Add imports for the shadcn/ui install targets.
```json title="package.json" showLineNumbers
{
"imports": {
"#components/*": "./src/components/*.tsx",
"#lib/*": "./src/lib/*.ts",
"#hooks/*": "./src/hooks/*.ts"
}
}
```
If your app does not use a `src` directory, remove `src/` from the targets. For
example:
```json title="package.json" showLineNumbers
{
"imports": {
"#components/*": "./components/*.tsx",
"#lib/*": "./lib/*.ts",
"#hooks/*": "./hooks/*.ts"
}
}
```
### Configure TypeScript
Enable package import resolution.
```json title="tsconfig.json" showLineNumbers
{
"compilerOptions": {
"moduleResolution": "bundler",
"resolvePackageJsonImports": true
}
}
```
You do not need `compilerOptions.paths` for these aliases.
### Configure `components.json`
Use the same `#...` roots in `components.json`.
```json title="components.json" showLineNumbers
{
"aliases": {
"components": "#components",
"ui": "#components/ui",
"lib": "#lib",
"hooks": "#hooks",
"utils": "#lib/utils"
}
}
```
The `ui` alias uses `#components/ui`. It is still covered by the
`#components/*` import in `package.json`.
The `utils` alias uses `#lib/utils`. It is covered by `#lib/*`, so you do not
need a separate `#utils` import.
</Steps>
## Monorepo
In a monorepo, use package imports for files inside each package and package
exports for files shared across workspaces.
For an app workspace:
```json title="apps/web/package.json" showLineNumbers
{
"name": "web",
"private": true,
"imports": {
"#components/*": "./src/components/*.tsx",
"#lib/*": "./src/lib/*.ts",
"#hooks/*": "./src/hooks/*.ts"
},
"dependencies": {
"@workspace/ui": "workspace:*"
}
}
```
```json title="apps/web/components.json" showLineNumbers
{
"aliases": {
"components": "#components",
"ui": "@workspace/ui/components",
"lib": "#lib",
"hooks": "#hooks",
"utils": "@workspace/ui/lib/utils"
}
}
```
For the shared UI package:
```json title="packages/ui/package.json" showLineNumbers
{
"name": "@workspace/ui",
"private": true,
"imports": {
"#components/*": "./src/components/*.tsx",
"#lib/*": "./src/lib/*.ts",
"#hooks/*": "./src/hooks/*.ts"
},
"exports": {
"./globals.css": "./src/styles/globals.css",
"./components/*": "./src/components/*.tsx",
"./lib/*": "./src/lib/*.ts",
"./hooks/*": "./src/hooks/*.ts"
}
}
```
```json title="packages/ui/components.json" showLineNumbers
{
"aliases": {
"components": "#components",
"ui": "#components",
"lib": "#lib",
"hooks": "#hooks",
"utils": "#lib/utils"
}
}
```
When you run `add` from `apps/web`, app-local files use `#...` imports and
shared UI files are imported from `@workspace/ui`.
```tsx
import { Button } from "@workspace/ui/components/button"
import { LoginForm } from "#components/login-form"
```
## File extensions
The target pattern in `package.json#imports` controls whether generated imports
include file extensions.
```json title="package.json" showLineNumbers
{
"imports": {
"#components/*": "./src/components/*.tsx"
}
}
```
This generates imports without extensions:
```tsx
import { Button } from "#components/ui/button"
```
If you use a target without the extension:
```json title="package.json" showLineNumbers
{
"imports": {
"#components/*": "./src/components/*"
}
}
```
The generated import keeps the source extension:
```tsx
import { Button } from "#components/ui/button.tsx"
```
For most apps, use the extension in the target pattern.
## Troubleshooting
If TypeScript cannot resolve a `#...` import, check that:
- the specifier starts with `#`
- the `imports` entry is in the nearest `package.json`
- `moduleResolution` is set to `bundler`
- `resolvePackageJsonImports` is enabled
- the matching target exists after components are added
If a component is installed but imports still point to `@/...`, check that
`components.json` uses the same `#...` aliases as your package imports.

View File

@@ -0,0 +1,166 @@
---
title: Next.js 15 + React 19
description: Using shadcn/ui with Next.js 15 and React 19.
---
<Callout className="">
**Update:** We have added full support for React 19 and Tailwind v4 in the
`latest` release. **This guide might be outdated. Proceed with caution.**
</Callout>
## TL;DR
If you're using `npm`, you can install shadcn/ui dependencies with a flag. The `shadcn` CLI will prompt you to select a flag when you run it. No flags required for pnpm, bun, or yarn.
See [Upgrade Status](#upgrade-status) for the status of React 19 support for each package.
## What's happening?
React 19 is now [rc](https://www.npmjs.com/package/react?activeTab=versions) and is [tested and supported in the latest Next.js 15 release](https://nextjs.org/blog/next-15#react-19).
To support React 19, package maintainers will need to test and update their packages to include React 19 as a peer dependency. This is [already](https://github.com/radix-ui/primitives/pull/2952) [in](https://github.com/pacocoursey/cmdk/pull/318) [progress](https://github.com/emilkowalski/vaul/pull/498).
```diff /^19.0/
"peerDependencies": {
- "react": "^16.8 || ^17.0 || ^18.0",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0",
- "react-dom": "^16.8 || ^17.0 || ^18.0"
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0"
},
```
<Callout>
You can check if a package lists React 19 as a peer dependency by running
`npm info <package> peerDependencies`.
</Callout>
In the meantime, if you are installing a package that **does not** list React 19 as a peer dependency, you will see an error message like this:
```bash
npm error code ERESOLVE
npm error ERESOLVE unable to resolve dependency tree
npm error
npm error While resolving: my-app@0.1.0
npm error Found: react@19.0.0-rc-69d4b800-20241021
npm error node_modules/react
npm error react@"19.0.0-rc-69d4b800-20241021" from the root project
```
<Callout>
**Note:** This is npm only. PNPM and Bun will only show a silent warning.
</Callout>
## How to fix this
### Solution 1: `--force` or `--legacy-peer-deps`
You can force install a package with the `--force` or the `--legacy-peer-deps` flag.
```bash
npm i <package> --force
npm i <package> --legacy-peer-deps
```
This will install the package and ignore the peer dependency warnings.
<Accordion type="multiple">
<AccordionItem value="flags">
<AccordionTrigger className="font-medium">
What do the `--force` and `--legacy-peer-deps` flag do?
</AccordionTrigger>
<AccordionContent className="[&_ul]:mt-0">
- `--force`: Ignores and overrides any dependency conflicts, forcing the
installation of packages.
- `--legacy-peer-deps`: Skips strict peer dependency checks, allowing
installation of packages with unmet peer dependencies to avoid errors.
</AccordionContent>
</AccordionItem>
</Accordion>
### Solution 2: Use React 18
You can downgrade `react` and `react-dom` to version 18, which is compatible with the package you are installing and upgrade when the dependency is updated.
```bash
npm i react@18 react-dom@18
```
Whichever solution you choose, make sure you test your app thoroughly to ensure
there are no regressions.
## Using shadcn/ui on Next.js 15
### Using pnpm, bun, or yarn
Follow the instructions in the [installation guide](/docs/installation/next) to install shadcn/ui. No flags are needed.
### Using npm
When you run `npx shadcn@latest init -d`, you will be prompted to select an option to resolve the peer dependency issues.
```bash
It looks like you are using React 19.
Some packages may fail to install due to peer dependency issues (see https://ui.shadcn.com/react-19).
? How would you like to proceed? › - Use arrow-keys. Return to submit.
❯ Use --force
Use --legacy-peer-deps
```
You can then run the command with the flag you choose.
## Adding components
The process for adding components is the same as above. Select a flag to resolve the peer dependency issues.
**Remember to always test your app after installing new dependencies.**
## Upgrade Status
To make it easy for you to track the progress of the upgrade, here is a table with the React 19 support status for the shadcn/ui dependencies.
- ✅ - Works with React 19 using npm, pnpm, and bun.
- 🚧 - Works with React 19 using pnpm and bun. Requires flag for npm. PR is in progress.
| Package | Status | Note |
| ---------------------------------------------------------------------------------- | ------ | ----------------------------------------------------------- |
| [radix-ui](https://www.npmjs.com/package/@radix-ui/react-icons) | ✅ | |
| [lucide-react](https://www.npmjs.com/package/lucide-react) | ✅ | |
| [class-variance-authority](https://www.npmjs.com/package/class-variance-authority) | ✅ | Does not list React 19 as a peer dependency. |
| [tailwindcss-animate](https://www.npmjs.com/package/tailwindcss-animate) | ✅ | Does not list React 19 as a peer dependency. |
| [embla-carousel-react](https://www.npmjs.com/package/embla-carousel-react) | ✅ | |
| [recharts](https://www.npmjs.com/package/recharts) | ✅ | See note [below](#recharts) |
| [react-hook-form](https://www.npmjs.com/package/react-hook-form) | ✅ | |
| [react-resizable-panels](https://www.npmjs.com/package/react-resizable-panels) | ✅ | |
| [sonner](https://www.npmjs.com/package/sonner) | ✅ | |
| [react-day-picker](https://www.npmjs.com/package/react-day-picker) | ✅ | Works with flag for npm. Work to upgrade to v9 in progress. |
| [input-otp](https://www.npmjs.com/package/input-otp) | ✅ | |
| [vaul](https://www.npmjs.com/package/vaul) | ✅ | |
| [@radix-ui/react-icons](https://www.npmjs.com/package/@radix-ui/react-icons) | ✅ | See [PR #194](https://github.com/radix-ui/icons/pull/194) |
| [cmdk](https://www.npmjs.com/package/cmdk) | ✅ | |
If you have any questions, please [open an issue](https://github.com/shadcn/ui/issues) on GitHub.
## Recharts
To use recharts with React 19, you will need to override the `react-is` dependency.
<Steps>
<Step>Add the following to your `package.json`</Step>
```json title="package.json"
"overrides": {
"react-is": "^19.0.0-rc-69d4b800-20241021"
}
```
Note: the `react-is` version needs to match the version of React 19 you are using. The above is an example.
<Step>Run `npm install --legacy-peer-deps`</Step>
</Steps>

View File

@@ -0,0 +1,71 @@
---
title: Skills
description: Give your AI assistant deep knowledge of shadcn/ui components, patterns, and best practices.
---
Skills give AI assistants like Claude Code project-aware context about shadcn/ui. When installed, your AI assistant knows how to find, install, compose, and customize components using the correct APIs and patterns for your project.
For example, you can ask your AI assistant to:
- _"Add a login form with email and password fields."_
- _"Create a settings page with a form for updating profile information."_
- _"Build a dashboard with a sidebar, stats cards, and a data table."_
- _"Switch to --preset [CODE]"_
- _"Can you add a hero from @tailark?"_
The skill reads your project's `components.json` and provides the assistant with your framework, aliases, installed components, icon library, and base library so it can generate correct code on the first try.
---
## Install
```bash
npx skills add shadcn/ui
```
This installs the shadcn skill into your project. Once installed, your AI assistant automatically loads it when working with shadcn/ui components.
Learn more about skills at [skills.sh](https://skills.sh).
---
## What's Included
The skill provides your AI assistant with the following knowledge:
### Project Context
On every interaction, the skill runs `shadcn info --json` to get your project's configuration: framework, Tailwind version, aliases, base library (`base`, `radix`, or `aria`), icon library, installed components, and resolved file paths.
### CLI Commands
Full reference for all CLI commands: `init`, `add`, `search`, `view`, `docs`, `diff`, `info`, and `build`. Includes flags, dry-run mode, smart merge workflows, presets, and templates.
### Theming and Customization
How CSS variables, OKLCH colors, dark mode, custom colors, border radius, and component variants work. Includes guidance for both Tailwind v3 and v4.
### Registry Authoring
How to build and publish custom component registries: `registry.json` format, item types, file objects, dependencies, CSS variables, building, hosting, and user configuration.
### MCP Server
Setup and tools for the shadcn MCP server, which lets AI assistants search, browse, and install components from registries.
---
## How It Works
1. **Project detection** — The skill activates when it finds a `components.json` file in your project.
2. **Context injection** — It runs `shadcn info --json` to read your project configuration and injects the result into the assistant's context.
3. **Pattern enforcement** — The assistant follows shadcn/ui composition rules: using `FieldGroup` for forms, `ToggleGroup` for option sets, semantic colors, and correct base-specific APIs.
4. **Component discovery** — The assistant uses `shadcn docs`, `shadcn search`, or MCP tools to find components and their documentation before generating code.
## Learn More
- [CLI](/docs/cli) — Full CLI command reference
- [MCP Server](/docs/mcp) — Connect the MCP server for registry access
- [Theming](/docs/theming) — CSS variables and customization
- [Registry](/docs/registry) — Building and publishing custom registries
- [skills.sh](https://skills.sh) — Learn more about AI skills

View File

@@ -0,0 +1,333 @@
---
title: Tailwind v4
description: How to use shadcn/ui with Tailwind v4 and React 19.
---
It’s here! Tailwind v4 and React 19. Ready for you to try out. You can start using it today.
## What's New
- The CLI can now initialize projects with Tailwind v4.
- Full support for the new `@theme` directive and `@theme inline` option.
- All components are updated for Tailwind v4 and React 19.
- We’ve removed the forwardRefs and adjusted the types.
- Every primitive now has a `data-slot` attribute for styling.
- We've fixed and cleaned up the style of the components.
- We're deprecating the `toast` component in favor of `sonner`.
- Buttons now use the default cursor.
- We're deprecating the `default` style. New projects will use `new-york`.
- HSL colors are now converted to OKLCH.
**Note: this is non-breaking. Your existing apps with Tailwind v3 and React 18 will still work. When you add new components, they'll still be in v3 and React 18 until you upgrade. Only new projects start with Tailwind v4 and React 19.**
## Try It Out
You can start using Tailwind v4 + React 19 today. See the framework specific guides below for how to get started.
<div className="mt-8 grid gap-4 sm:grid-cols-2 sm:gap-6">
<LinkedCard href="/docs/installation/next">
<svg
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
className="h-10 w-10"
fill="currentColor"
>
<title>Next.js</title>
<path d="M11.5725 0c-.1763 0-.3098.0013-.3584.0067-.0516.0053-.2159.021-.3636.0328-3.4088.3073-6.6017 2.1463-8.624 4.9728C1.1004 6.584.3802 8.3666.1082 10.255c-.0962.659-.108.8537-.108 1.7474s.012 1.0884.108 1.7476c.652 4.506 3.8591 8.2919 8.2087 9.6945.7789.2511 1.6.4223 2.5337.5255.3636.04 1.9354.04 2.299 0 1.6117-.1783 2.9772-.577 4.3237-1.2643.2065-.1056.2464-.1337.2183-.1573-.0188-.0139-.8987-1.1938-1.9543-2.62l-1.919-2.592-2.4047-3.5583c-1.3231-1.9564-2.4117-3.556-2.4211-3.556-.0094-.0026-.0187 1.5787-.0235 3.509-.0067 3.3802-.0093 3.5162-.0516 3.596-.061.115-.108.1618-.2064.2134-.075.0374-.1408.0445-.495.0445h-.406l-.1078-.068a.4383.4383 0 01-.1572-.1712l-.0493-.1056.0053-4.703.0067-4.7054.0726-.0915c.0376-.0493.1174-.1125.1736-.143.0962-.047.1338-.0517.5396-.0517.4787 0 .5584.0187.6827.1547.0353.0377 1.3373 1.9987 2.895 4.3608a10760.433 10760.433 0 004.7344 7.1706l1.9002 2.8782.096-.0633c.8518-.5536 1.7525-1.3418 2.4657-2.1627 1.5179-1.7429 2.4963-3.868 2.8247-6.134.0961-.6591.1078-.854.1078-1.7475 0-.8937-.012-1.0884-.1078-1.7476-.6522-4.506-3.8592-8.2919-8.2087-9.6945-.7672-.2487-1.5836-.42-2.4985-.5232-.169-.0176-1.0835-.0366-1.6123-.037zm4.0685 7.217c.3473 0 .4082.0053.4857.047.1127.0562.204.1642.237.2767.0186.061.0234 1.3653.0186 4.3044l-.0067 4.2175-.7436-1.14-.7461-1.14v-3.066c0-1.982.0093-3.0963.0234-3.1502.0375-.1313.1196-.2346.2323-.2955.0961-.0494.1313-.054.4997-.054z" />
</svg>
<p className="mt-2 font-medium">Next.js</p>
</LinkedCard>
<LinkedCard href="/docs/installation/vite">
<svg
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
className="h-10 w-10"
fill="currentColor"
>
<title>Vite</title>
<path d="m8.286 10.578.512-8.657a.306.306 0 0 1 .247-.282L17.377.006a.306.306 0 0 1 .353.385l-1.558 5.403a.306.306 0 0 0 .352.385l2.388-.46a.306.306 0 0 1 .332.438l-6.79 13.55-.123.19a.294.294 0 0 1-.252.14c-.177 0-.35-.152-.305-.369l1.095-5.301a.306.306 0 0 0-.388-.355l-1.433.435a.306.306 0 0 1-.389-.354l.69-3.375a.306.306 0 0 0-.37-.36l-2.32.536a.306.306 0 0 1-.374-.316zm14.976-7.926L17.284 3.74l-.544 1.887 2.077-.4a.8.8 0 0 1 .84.369.8.8 0 0 1 .034.783L12.9 19.93l-.013.025-.015.023-.122.19a.801.801 0 0 1-.672.37.826.826 0 0 1-.634-.302.8.8 0 0 1-.16-.67l1.029-4.981-1.12.34a.81.81 0 0 1-.86-.262.802.802 0 0 1-.165-.67l.63-3.08-2.027.468a.808.808 0 0 1-.768-.233.81.81 0 0 1-.217-.6l.389-6.57-7.44-1.33a.612.612 0 0 0-.64.906L11.58 23.691a.612.612 0 0 0 1.066-.004l11.26-20.135a.612.612 0 0 0-.644-.9z" />
</svg>
<p className="mt-2 font-medium">Vite</p>
</LinkedCard>
<LinkedCard href="/docs/installation/laravel">
<svg
role="img"
viewBox="0 0 62 65"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
className="h-10 w-10"
>
<path d="M61.8548 14.6253C61.8778 14.7102 61.8895 14.7978 61.8897 14.8858V28.5615C61.8898 28.737 61.8434 28.9095 61.7554 29.0614C61.6675 29.2132 61.5409 29.3392 61.3887 29.4265L49.9104 36.0351V49.1337C49.9104 49.4902 49.7209 49.8192 49.4118 49.9987L25.4519 63.7916C25.3971 63.8227 25.3372 63.8427 25.2774 63.8639C25.255 63.8714 25.2338 63.8851 25.2101 63.8913C25.0426 63.9354 24.8666 63.9354 24.6991 63.8913C24.6716 63.8838 24.6467 63.8689 24.6205 63.8589C24.5657 63.8389 24.5084 63.8215 24.456 63.7916L0.501061 49.9987C0.348882 49.9113 0.222437 49.7853 0.134469 49.6334C0.0465019 49.4816 0.000120578 49.3092 0 49.1337L0 8.10652C0 8.01678 0.0124642 7.92953 0.0348998 7.84477C0.0423783 7.8161 0.0598282 7.78993 0.0697995 7.76126C0.0884958 7.70891 0.105946 7.65531 0.133367 7.6067C0.152063 7.5743 0.179485 7.54812 0.20192 7.51821C0.230588 7.47832 0.256763 7.43719 0.290416 7.40229C0.319084 7.37362 0.356476 7.35243 0.388883 7.32751C0.425029 7.29759 0.457436 7.26518 0.498568 7.2415L12.4779 0.345059C12.6296 0.257786 12.8015 0.211853 12.9765 0.211853C13.1515 0.211853 13.3234 0.257786 13.475 0.345059L25.4531 7.2415H25.4556C25.4955 7.26643 25.5292 7.29759 25.5653 7.32626C25.5977 7.35119 25.6339 7.37362 25.6625 7.40104C25.6974 7.43719 25.7224 7.47832 25.7523 7.51821C25.7735 7.54812 25.8021 7.5743 25.8196 7.6067C25.8483 7.65656 25.8645 7.70891 25.8844 7.76126C25.8944 7.78993 25.9118 7.8161 25.9193 7.84602C25.9423 7.93096 25.954 8.01853 25.9542 8.10652V33.7317L35.9355 27.9844V14.8846C35.9355 14.7973 35.948 14.7088 35.9704 14.6253C35.9792 14.5954 35.9954 14.5692 36.0053 14.5405C36.0253 14.4882 36.0427 14.4346 36.0702 14.386C36.0888 14.3536 36.1163 14.3274 36.1375 14.2975C36.1674 14.2576 36.1923 14.2165 36.2272 14.1816C36.2559 14.1529 36.292 14.1317 36.3244 14.1068C36.3618 14.0769 36.3942 14.0445 36.4341 14.0208L48.4147 7.12434C48.5663 7.03694 48.7383 6.99094 48.9133 6.99094C49.0883 6.99094 49.2602 7.03694 49.4118 7.12434L61.3899 14.0208C61.4323 14.0457 61.4647 14.0769 61.5021 14.1055C61.5333 14.1305 61.5694 14.1529 61.5981 14.1803C61.633 14.2165 61.6579 14.2576 61.6878 14.2975C61.7103 14.3274 61.7377 14.3536 61.7551 14.386C61.7838 14.4346 61.8 14.4882 61.8199 14.5405C61.8312 14.5692 61.8474 14.5954 61.8548 14.6253ZM59.893 27.9844V16.6121L55.7013 19.0252L49.9104 22.3593V33.7317L59.8942 27.9844H59.893ZM47.9149 48.5566V37.1768L42.2187 40.4299L25.953 49.7133V61.2003L47.9149 48.5566ZM1.99677 9.83281V48.5566L23.9562 61.199V49.7145L12.4841 43.2219L12.4804 43.2194L12.4754 43.2169C12.4368 43.1945 12.4044 43.1621 12.3682 43.1347C12.3371 43.1097 12.3009 43.0898 12.2735 43.0624L12.271 43.0586C12.2386 43.0275 12.2162 42.9888 12.1887 42.9539C12.1638 42.9203 12.1339 42.8916 12.114 42.8567L12.1127 42.853C12.0903 42.8156 12.0766 42.7707 12.0604 42.7283C12.0442 42.6909 12.023 42.656 12.013 42.6161C12.0005 42.5688 11.998 42.5177 11.9931 42.4691C11.9881 42.4317 11.9781 42.3943 11.9781 42.3569V15.5801L6.18848 12.2446L1.99677 9.83281ZM12.9777 2.36177L2.99764 8.10652L12.9752 13.8513L22.9541 8.10527L12.9752 2.36177H12.9777ZM18.1678 38.2138L23.9574 34.8809V9.83281L19.7657 12.2459L13.9749 15.5801V40.6281L18.1678 38.2138ZM48.9133 9.14105L38.9344 14.8858L48.9133 20.6305L58.8909 14.8846L48.9133 9.14105ZM47.9149 22.3593L42.124 19.0252L37.9323 16.6121V27.9844L43.7219 31.3174L47.9149 33.7317V22.3593ZM24.9533 47.987L39.59 39.631L46.9065 35.4555L36.9352 29.7145L25.4544 36.3242L14.9907 42.3482L24.9533 47.987Z" />
</svg>
<p className="mt-2 font-medium">Laravel</p>
</LinkedCard>
<LinkedCard href="/docs/installation/react-router">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
className="h-10 w-10"
fill="currentColor"
>
<path d="M12.118 5.466a2.306 2.306 0 0 0-.623.08c-.278.067-.702.332-.953.583-.41.423-.49.609-.662 1.469-.08.423.41 1.43.847 1.734.45.317 1.085.502 2.065.608 1.429.16 1.84.636 1.84 2.197 0 1.377-.385 1.747-1.96 1.906-1.707.172-2.58.834-2.765 2.117-.106.781.41 1.76 1.125 2.091 1.627.768 3.15-.198 3.467-2.196.211-1.284.622-1.642 1.998-1.747 1.588-.133 2.409-.675 2.713-1.787.278-1.02-.304-2.157-1.297-2.554-.264-.106-.873-.238-1.35-.291-1.495-.16-1.879-.424-2.038-1.39-.225-1.337-.317-1.562-.794-2.09a2.174 2.174 0 0 0-1.613-.73zm-4.785 4.36a2.145 2.145 0 0 0-.497.048c-1.469.318-2.17 2.051-1.35 3.295 1.178 1.774 3.944.953 3.97-1.177.012-1.193-.98-2.143-2.123-2.166zM2.089 14.19a2.22 2.22 0 0 0-.427.052c-2.158.476-2.237 3.626-.106 4.182.53.145.582.145 1.111.013 1.191-.318 1.866-1.456 1.549-2.607-.278-1.02-1.144-1.664-2.127-1.64zm19.824.008c-.233.002-.477.058-.784.162-1.39.477-1.866 2.092-.98 3.336.557.794 1.96 1.058 2.82.516 1.416-.874 1.363-3.057-.093-3.746-.38-.186-.663-.271-.963-.268z" />
</svg>
<p className="mt-2 font-medium">React Router</p>
</LinkedCard>
<LinkedCard href="/docs/installation/astro">
<svg
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
className="h-10 w-10"
fill="currentColor"
>
<title>Astro</title>
<path
d="M16.074 16.86C15.354 17.476 13.917 17.895 12.262 17.895C10.23 17.895 8.527 17.263 8.075 16.412C7.914 16.9 7.877 17.458 7.877 17.814C7.877 17.814 7.771 19.564 8.988 20.782C8.988 20.15 9.501 19.637 10.133 19.637C11.216 19.637 11.215 20.582 11.214 21.349V21.418C11.214 22.582 11.925 23.579 12.937 24C12.7812 23.6794 12.7005 23.3275 12.701 22.971C12.701 21.861 13.353 21.448 14.111 20.968C14.713 20.585 15.383 20.161 15.844 19.308C16.0926 18.8493 16.2225 18.3357 16.222 17.814C16.2221 17.4903 16.1722 17.1685 16.074 16.86ZM15.551 0.6C15.747 0.844 15.847 1.172 16.047 1.829L20.415 16.176C18.7743 15.3246 17.0134 14.7284 15.193 14.408L12.35 4.8C12.3273 4.72337 12.2803 4.65616 12.2162 4.60844C12.152 4.56072 12.0742 4.53505 11.9943 4.53528C11.9143 4.5355 11.8366 4.56161 11.7727 4.60969C11.7089 4.65777 11.6623 4.72524 11.64 4.802L8.83 14.405C7.00149 14.724 5.23264 15.3213 3.585 16.176L7.974 1.827C8.174 1.171 8.274 0.843 8.471 0.6C8.64406 0.385433 8.86922 0.218799 9.125 0.116C9.415 0 9.757 0 10.443 0H13.578C14.264 0 14.608 0 14.898 0.117C15.1529 0.219851 15.3783 0.386105 15.551 0.6Z"
fill="currentColor"
/>
</svg>
<p className="mt-2 font-medium">Astro</p>
</LinkedCard>
<LinkedCard href="/docs/installation/tanstack">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
className="h-10 w-10"
fill="currentColor"
>
<path d="M6.93 13.688a.343.343 0 0 1 .468.132l.063.106c.48.851.98 1.66 1.5 2.426a35.65 35.65 0 0 0 2.074 2.742.345.345 0 0 1-.039.484l-.074.066c-2.543 2.223-4.191 2.665-4.953 1.333-.746-1.305-.477-3.672.808-7.11a.344.344 0 0 1 .153-.18ZM17.75 16.3a.34.34 0 0 1 .395.27l.02.1c.628 3.286.187 4.93-1.325 4.93-1.48 0-3.36-1.402-5.649-4.203a.327.327 0 0 1-.074-.222c0-.188.156-.34.344-.34h.121a32.984 32.984 0 0 0 2.809-.098c1.07-.086 2.191-.23 3.359-.437zm.871-6.977a.353.353 0 0 1 .445-.21l.102.034c3.262 1.11 4.504 2.332 3.719 3.664-.766 1.305-2.993 2.254-6.684 2.848a.362.362 0 0 1-.238-.047.343.343 0 0 1-.125-.476l.062-.106a34.07 34.07 0 0 0 1.367-2.523c.477-.989.93-2.051 1.352-3.184zM7.797 8.34a.362.362 0 0 1 .238.047.343.343 0 0 1 .125.476l-.062.106a34.088 34.088 0 0 0-1.367 2.523c-.477.988-.93 2.051-1.352 3.184a.353.353 0 0 1-.445.21l-.102-.034C1.57 13.742.328 12.52 1.113 11.188 1.88 9.883 4.106 8.934 7.797 8.34Zm5.281-3.984c2.543-2.223 4.192-2.664 4.953-1.332.746 1.304.477 3.671-.808 7.109a.344.344 0 0 1-.153.18.343.343 0 0 1-.468-.133l-.063-.106a34.64 34.64 0 0 0-1.5-2.426 35.65 35.65 0 0 0-2.074-2.742.345.345 0 0 1 .039-.484ZM7.285 2.274c1.48 0 3.364 1.402 5.649 4.203a.349.349 0 0 1 .078.218.348.348 0 0 1-.348.344l-.117-.004a34.584 34.584 0 0 0-2.809.102 35.54 35.54 0 0 0-3.363.437.343.343 0 0 1-.394-.273l-.02-.098c-.629-3.285-.188-4.93 1.324-4.93Zm2.871 5.812h3.688a.638.638 0 0 1 .55.316l1.848 3.22a.644.644 0 0 1 0 .628l-1.847 3.223a.638.638 0 0 1-.551.316h-3.688a.627.627 0 0 1-.547-.316L7.758 12.25a.644.644 0 0 1 0-.629L9.61 8.402a.627.627 0 0 1 .546-.316Zm3.23.793a.638.638 0 0 1 .552.316l1.39 2.426a.644.644 0 0 1 0 .629l-1.39 2.43a.638.638 0 0 1-.551.316h-2.774a.627.627 0 0 1-.546-.316l-1.395-2.43a.644.644 0 0 1 0-.629l1.395-2.426a.627.627 0 0 1 .546-.316Zm-.491.867h-1.79a.624.624 0 0 0-.546.316l-.899 1.56a.644.644 0 0 0 0 .628l.899 1.563a.632.632 0 0 0 .547.316h1.789a.632.632 0 0 0 .547-.316l.898-1.563a.644.644 0 0 0 0-.629l-.898-1.558a.624.624 0 0 0-.547-.317Zm-.477.828c.227 0 .438.121.547.317l.422.73a.625.625 0 0 1 0 .629l-.422.734a.627.627 0 0 1-.547.317h-.836a.632.632 0 0 1-.547-.317l-.422-.734a.625.625 0 0 1 0-.629l.422-.73a.632.632 0 0 1 .547-.317zm-.418.817a.548.548 0 0 0-.473.273.547.547 0 0 0 0 .547.544.544 0 0 0 .473.27.544.544 0 0 0 .473-.27.547.547 0 0 0 0-.547.548.548 0 0 0-.473-.273Zm-4.422.546h.98M18.98 7.75c.391-1.895.477-3.344.223-4.398-.148-.63-.422-1.137-.84-1.508-.441-.39-1-.582-1.625-.582-1.035 0-2.12.472-3.281 1.367a14.9 14.9 0 0 0-1.473 1.316 1.206 1.206 0 0 0-.136-.144c-1.446-1.285-2.66-2.082-3.7-2.39-.617-.184-1.195-.2-1.722-.024-.559.187-1.004.574-1.317 1.117-.515.894-.652 2.074-.46 3.527.078.59.214 1.235.402 1.934a1.119 1.119 0 0 0-.215.047C3.008 8.62 1.71 9.269.926 10.015c-.465.442-.77.938-.883 1.481-.113.578 0 1.156.312 1.7.516.894 1.465 1.597 2.817 2.155.543.223 1.156.426 1.844.61a1.023 1.023 0 0 0-.07.226c-.391 1.891-.477 3.344-.223 4.395.148.629.425 1.14.84 1.508.44.39 1 .582 1.625.582 1.035 0 2.12-.473 3.28-1.364.477-.37.973-.816 1.489-1.336a1.2 1.2 0 0 0 .195.227c1.446 1.285 2.66 2.082 3.7 2.39.617.184 1.195.2 1.722.024.559-.187 1.004-.574 1.317-1.117.515-.894.652-2.074.46-3.527a14.941 14.941 0 0 0-.425-2.012 1.225 1.225 0 0 0 .238-.047c1.828-.61 3.125-1.258 3.91-2.004.465-.441.77-.937.883-1.48.113-.578 0-1.157-.313-1.7-.515-.894-1.464-1.597-2.816-2.156a14.576 14.576 0 0 0-1.906-.625.865.865 0 0 0 .059-.195z" />
</svg>
<p className="mt-2 font-medium">TanStack Start</p>
</LinkedCard>
<LinkedCard href="/docs/installation/gatsby">
<svg
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
className="h-10 w-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="mt-2 font-medium">Gatsby</p>
</LinkedCard>
<LinkedCard href="/docs/installation/manual">
<svg
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
className="h-10 w-10"
fill="currentColor"
>
<title>React</title>
<path d="M14.23 12.004a2.236 2.236 0 0 1-2.235 2.236 2.236 2.236 0 0 1-2.236-2.236 2.236 2.236 0 0 1 2.235-2.236 2.236 2.236 0 0 1 2.236 2.236zm2.648-10.69c-1.346 0-3.107.96-4.888 2.622-1.78-1.653-3.542-2.602-4.887-2.602-.41 0-.783.093-1.106.278-1.375.793-1.683 3.264-.973 6.365C1.98 8.917 0 10.42 0 12.004c0 1.59 1.99 3.097 5.043 4.03-.704 3.113-.39 5.588.988 6.38.32.187.69.275 1.102.275 1.345 0 3.107-.96 4.888-2.624 1.78 1.654 3.542 2.603 4.887 2.603.41 0 .783-.09 1.106-.275 1.374-.792 1.683-3.263.973-6.365C22.02 15.096 24 13.59 24 12.004c0-1.59-1.99-3.097-5.043-4.032.704-3.11.39-5.587-.988-6.38-.318-.184-.688-.277-1.092-.278zm-.005 1.09v.006c.225 0 .406.044.558.127.666.382.955 1.835.73 3.704-.054.46-.142.945-.25 1.44-.96-.236-2.006-.417-3.107-.534-.66-.905-1.345-1.727-2.035-2.447 1.592-1.48 3.087-2.292 4.105-2.295zm-9.77.02c1.012 0 2.514.808 4.11 2.28-.686.72-1.37 1.537-2.02 2.442-1.107.117-2.154.298-3.113.538-.112-.49-.195-.964-.254-1.42-.23-1.868.054-3.32.714-3.707.19-.09.4-.127.563-.132zm4.882 3.05c.455.468.91.992 1.36 1.564-.44-.02-.89-.034-1.345-.034-.46 0-.915.01-1.36.034.44-.572.895-1.096 1.345-1.565zM12 8.1c.74 0 1.477.034 2.202.093.406.582.802 1.203 1.183 1.86.372.64.71 1.29 1.018 1.946-.308.655-.646 1.31-1.013 1.95-.38.66-.773 1.288-1.18 1.87-.728.063-1.466.098-2.21.098-.74 0-1.477-.035-2.202-.093-.406-.582-.802-1.204-1.183-1.86-.372-.64-.71-1.29-1.018-1.946.303-.657.646-1.313 1.013-1.954.38-.66.773-1.286 1.18-1.868.728-.064 1.466-.098 2.21-.098zm-3.635.254c-.24.377-.48.763-.704 1.16-.225.39-.435.782-.635 1.174-.265-.656-.49-1.31-.676-1.947.64-.15 1.315-.283 2.015-.386zm7.26 0c.695.103 1.365.23 2.006.387-.18.632-.405 1.282-.66 1.933-.2-.39-.41-.783-.64-1.174-.225-.392-.465-.774-.705-1.146zm3.063.675c.484.15.944.317 1.375.498 1.732.74 2.852 1.708 2.852 2.476-.005.768-1.125 1.74-2.857 2.475-.42.18-.88.342-1.355.493-.28-.958-.646-1.956-1.1-2.98.45-1.017.81-2.01 1.085-2.964zm-13.395.004c.278.96.645 1.957 1.1 2.98-.45 1.017-.812 2.01-1.086 2.964-.484-.15-.944-.318-1.37-.5-1.732-.737-2.852-1.706-2.852-2.474 0-.768 1.12-1.742 2.852-2.476.42-.18.88-.342 1.356-.494zm11.678 4.28c.265.657.49 1.312.676 1.948-.64.157-1.316.29-2.016.39.24-.375.48-.762.705-1.158.225-.39.435-.788.636-1.18zm-9.945.02c.2.392.41.783.64 1.175.23.39.465.772.705 1.143-.695-.102-1.365-.23-2.006-.386.18-.63.406-1.282.66-1.933zM17.92 16.32c.112.493.2.968.254 1.423.23 1.868-.054 3.32-.714 3.708-.147.09-.338.128-.563.128-1.012 0-2.514-.807-4.11-2.28.686-.72 1.37-1.536 2.02-2.44 1.107-.118 2.154-.3 3.113-.54zm-11.83.01c.96.234 2.006.415 3.107.532.66.905 1.345 1.727 2.035 2.446-1.595 1.483-3.092 2.295-4.11 2.295-.22-.005-.406-.05-.553-.132-.666-.38-.955-1.834-.73-3.703.054-.46.142-.944.25-1.438zm4.56.64c.44.02.89.034 1.345.034.46 0 .915-.01 1.36-.034-.44.572-.895 1.095-1.345 1.565-.455-.47-.91-.993-1.36-1.565z" />
</svg>
<p className="mt-2 font-medium">Manual</p>
</LinkedCard>
</div>
## Upgrade Your Project
<Callout className="mt-6 mb-6 border-blue-600 bg-blue-50 dark:border-blue-900 dark:bg-blue-950 [&_code]:bg-blue-100 dark:[&_code]:bg-blue-900">
**Important:** Before upgrading, please read the [Tailwind v4 Compatibility
Docs](https://tailwindcss.com/docs/compatibility) and make sure your project
is ready for the upgrade. Tailwind v4 uses bleeding-edge browser features and
is designed for modern browsers.
</Callout>
One of the major advantages of using `shadcn/ui` is that the code you end up with is exactly what you'd write yourself. There are no hidden abstractions.
This means when a dependency has a new release, you can just follow the official upgrade paths.
Here's how to upgrade your existing projects (full docs are on the way):
### 1. Follow the Tailwind v4 Upgrade Guide
- Upgrade to Tailwind v4 by following the official upgrade guide: https://tailwindcss.com/docs/upgrade-guide
- Use the `@tailwindcss/upgrade@next` codemod to remove deprecated utility classes and update tailwind config.
### 2. Update your CSS variables
The codemod will migrate your CSS variables as references under the `@theme` directive.
```css showLineNumbers
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
}
}
@theme {
--color-background: hsl(var(--background));
--color-foreground: hsl(var(--foreground));
}
```
This works. But to make it easier to work with colors and other variables, we'll need to move the `hsl` wrappers and use `@theme inline`.
Here's how you do it:
1. Move `:root` and `.dark` out of the `@layer` base.
2. Wrap the color values in `hsl()`
3. Add the `inline` option to `@theme` i.e `@theme inline`
4. Remove the `hsl()` wrappers from `@theme`
```css showLineNumbers
:root {
--background: hsl(0 0% 100%); // <-- Wrap in hsl
--foreground: hsl(0 0% 3.9%);
}
.dark {
--background: hsl(0 0% 3.9%); // <-- Wrap in hsl
--foreground: hsl(0 0% 98%);
}
@theme inline {
--color-background: var(--background); // <-- Remove hsl
--color-foreground: var(--foreground);
}
```
This change makes it much simpler to access your theme variables in both utility classes and outside of CSS, e.g. using color values in JavaScript.
### 3. Update colors for charts
Now that the theme colors come with `hsl()`, you can remove the wrapper in your `chartConfig`:
```diff
const chartConfig = {
desktop: {
label: "Desktop",
- color: "hsl(var(--chart-1))",
+ color: "var(--chart-1)",
},
mobile: {
label: "Mobile",
- color: "hsl(var(--chart-2))",
+ color: "var(--chart-2)",
},
} satisfies ChartConfig
```
### 4. Use new `size-*` utility
The new `size-*` utility (added in Tailwind v3.4), is now fully supported by `tailwind-merge`. You can replace `w-* h-*` with the new `size-*` utility:
```diff
- w-4 h-4
+ size-4
```
### 5. Update your dependencies
```bash
pnpm up "@radix-ui/*" cmdk lucide-react recharts tailwind-merge clsx --latest
```
### 6. Remove forwardRef
You can use the `remove-forward-ref` codemod to migrate your `forwardRef` to props or manually update the primitives.
For the codemod, see https://github.com/reactjs/react-codemod#remove-forward-ref.
If you want to do it manually, here's how to do it step by step:
1. Replace `React.forwardRef<...>` with `React.ComponentProps<...>`
2. Remove `ref={ref}` from the component.
3. Add a `data-slot` attribute. This will come in handy for styling with Tailwind.
4. You can optionally convert to a named function and remove the `displayName`.
#### Before
```tsx showLineNumbers
const AccordionItem = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
>(({ className, ...props }, ref) => (
<AccordionPrimitive.Item
ref={ref}
className={cn("border-b last:border-b-0", className)}
{...props}
/>
))
AccordionItem.displayName = "AccordionItem"
```
#### After
```tsx showLineNumbers
function AccordionItem({
className,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Item>) {
return (
<AccordionPrimitive.Item
data-slot="accordion-item"
className={cn("border-b last:border-b-0", className)}
{...props}
/>
)
}
```
## Changelog
### March 19, 2025 - Deprecate `tailwindcss-animate`
We've deprecated `tailwindcss-animate` in favor of `tw-animate-css`.
New projects will have `tw-animate-css` installed by default.
For existing projects, follow the steps below to migrate.
1. Remove `tailwindcss-animate` from your dependencies.
2. Remove the `@plugin 'tailwindcss-animate'` from your globals.css file.
3. Install `tw-animate-css` as a dev dependency.
4. Add the `@import "tw-animate-css"` to your globals.css file.
```diff showLineNumbers
- @plugin 'tailwindcss-animate';
+ @import "tw-animate-css";
```
### March 12, 2025 - New Dark Mode Colors
We've revisited the dark mode colors and updated them to be more accessible.
If you're running an existing Tailwind v4 project (**not an upgraded one**[^1]), you can update your components to use the new dark mode colors by re-adding your components using the CLI[^2].
<Steps>
<Step>Commit any changes</Step>
**The CLI will overwrite your existing components.** We recommend committing any changes you've made to your components before running the CLI.
```bash
git add .
git commit -m "..."
```
<Step>Update components</Step>
```bash
npx shadcn@latest add --all --overwrite
```
<Step>Update colors</Step>
Update the dark mode colors in your `globals.css` file to new OKLCH colors. See the [Base Colors](/docs/theming#base-colors) reference for a list of colors.
<Step>Review changes</Step>
Review and re-apply any changes you made to your components.
</Steps>
[^1]: Upgraded projects are not affected by this change. You can continue using the old dark mode colors.
[^2]: Updating your components will overwrite your existing components.

View File

@@ -0,0 +1,304 @@
---
title: Theming
description: Using CSS variables and theme tokens.
---
<Callout>
Want to build your theme visually? Use [shadcn/create](/create) to preview colors, radius, fonts, and icons, then generate a preset for your project.
</Callout>
We use and recommend CSS variables for theming.
This gives you semantic theme tokens like `background`, `foreground`, and `primary` that components use by default. Override those tokens in your CSS to change the look of your app without rewriting component classes.
```tsx /bg-background/ /text-foreground/
<div className="bg-background text-foreground" />
```
To use CSS variables for theming, set `tailwind.cssVariables` to `true` in your `components.json` file. This is the default.
```json {8} title="components.json" showLineNumbers
{
"style": "base-nova",
"rsc": true,
"tailwind": {
"config": "",
"css": "app/globals.css",
"baseColor": "neutral",
"cssVariables": true
}
}
```
Tailwind maps these tokens into utilities like `bg-background`, `text-foreground`, `border-border`, and `ring-ring`.
Dark mode works by overriding the same tokens inside a `.dark` selector. See the [dark mode docs](/docs/dark-mode/next) for adding a theme provider and toggling the `.dark` class.
## Token Convention
We use semantic background and foreground pairs. The base token controls the surface color and the `-foreground` token controls the text and icon color that sits on that surface.
<Callout className="mt-4">
The background suffix is omitted for the surface token. For example, `primary` pairs with `primary-foreground`.
</Callout>
Given the following CSS variables:
```css
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
```
The `background` color of the following component will be `var(--primary)` and the `foreground` color will be `var(--primary-foreground)`.
```tsx
<div className="bg-primary text-primary-foreground">Hello</div>
```
## Theme Tokens
These tokens live in your CSS file under `:root` and `.dark`.
| Token | What it controls | Used by |
| ------------------------------------------------ | ------------------------------------------------------ | ---------------------------------------------------------------------------- |
| `background` / `foreground` | The default app background and text color. | The page shell, page sections, and default text. |
| `card` / `card-foreground` | Elevated surfaces and the content inside them. | `Card`, dashboard panels, settings panels. |
| `popover` / `popover-foreground` | Floating surfaces and the content inside them. | `Popover`, `DropdownMenu`, `ContextMenu`, and other overlays. |
| `primary` / `primary-foreground` | High-emphasis actions and brand surfaces. | Default `Button`, selected states, badges, and active accents. |
| `secondary` / `secondary-foreground` | Lower-emphasis filled actions and supporting surfaces. | Secondary buttons, secondary badges, and supporting UI. |
| `muted` / `muted-foreground` | Subtle surfaces and lower-emphasis content. | Descriptions, placeholders, empty states, helper text, and subdued surfaces. |
| `accent` / `accent-foreground` | Interactive hover, focus, and active surfaces. | Ghost buttons, menu highlight states, hovered rows, and selected items. |
| `destructive` | Destructive actions and error emphasis. | Destructive buttons, invalid states, and destructive menu items. |
| `border` | Default borders and separators. | Cards, menus, tables, separators, and layout dividers. |
| `input` | Form control borders and input surface treatment. | `Input`, `Textarea`, `Select`, and outline-style controls. |
| `ring` | Focus rings and outlines. | Buttons, inputs, checkboxes, menus, and other focusable controls. |
| `chart-1` ... `chart-5` | The default chart palette. | Charts and chart-driven dashboard blocks. |
| `sidebar` / `sidebar-foreground` | The base sidebar surface and default sidebar text. | The `Sidebar` container and its default content. |
| `sidebar-primary` / `sidebar-primary-foreground` | High-emphasis actions inside the sidebar. | Active items, icon tiles, badges, and sidebar CTAs. |
| `sidebar-accent` / `sidebar-accent-foreground` | Hover and selected states inside the sidebar. | Sidebar menu hover states, open items, and interactive rows. |
| `sidebar-border` | Sidebar-specific borders and separators. | Sidebar headers, groups, and internal dividers. |
| `sidebar-ring` | Sidebar-specific focus rings. | Focused controls inside the sidebar. |
| `radius` | The base corner radius scale. | Cards, inputs, buttons, popovers, and the derived `radius-*` tokens. |
<Callout className="mt-4">
The chart tokens are covered in more detail in the [Chart theming docs](/docs/components/chart#theming).
</Callout>
## Radius Scale
`--radius` is the base radius token for your theme.
We derive a small radius scale from it so components can use consistent corner sizes while still sharing a single source of truth.
```css title="app/globals.css" showLineNumbers
@theme inline {
--radius-sm: calc(var(--radius) * 0.6);
--radius-md: calc(var(--radius) * 0.8);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) * 1.4);
--radius-2xl: calc(var(--radius) * 1.8);
--radius-3xl: calc(var(--radius) * 2.2);
--radius-4xl: calc(var(--radius) * 2.6);
}
```
This means:
- `radius-lg` is the base value.
- Smaller radii scale down from `--radius`.
- Larger radii scale up from `--radius`.
- Changing `--radius` updates the entire radius scale.
## Adding New Tokens
To add a new token, define it under `:root` and `.dark`, then expose it to Tailwind with `@theme inline`.
```css title="app/globals.css" showLineNumbers
:root {
--warning: oklch(0.84 0.16 84);
--warning-foreground: oklch(0.28 0.07 46);
}
.dark {
--warning: oklch(0.41 0.11 46);
--warning-foreground: oklch(0.99 0.02 95);
}
@theme inline {
--color-warning: var(--warning);
--color-warning-foreground: var(--warning-foreground);
}
```
You can now use `bg-warning` and `text-warning-foreground` in your components.
```tsx /bg-warning/ /text-warning-foreground/
<div className="bg-warning text-warning-foreground" />
```
## Base Colors
`tailwind.baseColor` controls the default token values generated for your project when you run `init` or use a preset.
The available base colors are: **Neutral**, **Stone**, **Zinc**, **Mauve**, **Olive**, **Mist**, and **Taupe**.
## Default Theme CSS
The following is the full default `neutral` theme scaffold. Copy it into your global CSS file and adjust the tokens as needed.
<CodeCollapsibleWrapper>
```css showLineNumbers title="app/globals.css"
@import "tailwindcss";
@import "shadcn/tailwind.css";
@custom-variant dark (&:is(.dark *));
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
--radius-sm: calc(var(--radius) * 0.6);
--radius-md: calc(var(--radius) * 0.8);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) * 1.4);
--radius-2xl: calc(var(--radius) * 1.8);
--radius-3xl: calc(var(--radius) * 2.2);
--radius-4xl: calc(var(--radius) * 2.6);
}
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.205 0 0);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.205 0 0);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.205 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.556 0 0);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.556 0 0);
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
}
```
</CodeCollapsibleWrapper>
## Without CSS Variables
If you do not want to use CSS variables, the CLI can generate components with inline Tailwind color utilities instead.
```bash
npx shadcn@latest init --no-css-variables
```
This sets `tailwind.cssVariables` to `false` in your `components.json` file.
```tsx /bg-zinc-950/ /text-zinc-50/ /dark:bg-white/ /dark:text-zinc-950/
<div className="bg-zinc-950 text-zinc-50 dark:bg-white dark:text-zinc-950" />
```
<Callout className="mt-4">
This is an installation-time choice. To switch an existing project, delete and re-install your components.
</Callout>

View File

@@ -0,0 +1,242 @@
---
title: Typeset
description: A styling system for HTML and rendered markdown, from blog posts to streaming chat. One CSS file you own.
---
You render markdown and get back plain unstyled HTML: headings, paragraphs, lists, and tables. So you style the elements one by one: font sizes, line heights, spacing.
You do it for your blog. Then you do it again for the docs. Then again for the chat app. Every time you're fighting the same thing: sizing and spacing.
To fix this, we created **shadcn/typeset**. It's one CSS file that styles everything inside a `typeset` container. The file lives in your project, so you can change it directly when you need to.
A typeset is just a small preset class. You can have multiple typesets in your app, for different contexts.
```css
.typeset-docs {
--typeset-font-body: var(--font-geist);
--typeset-font-heading: var(--font-geist);
--typeset-font-mono: var(--font-geist-mono);
--typeset-size: 15px;
--typeset-leading: 1.75;
--typeset-flow: 1.25em;
}
```
<Button asChild className="mt-6" size="sm">
<Link href="/typeset">Build your typeset</Link>
</Button>
---
## Principles
We read a lot about type: scale ratios, tracking, kerning, optical sizing, measure, leading, the space above and below every element. We tried exposing all of it, and it was too much. Nobody wants to set a dozen variables to make markdown look right.
So we sat down and condensed everything into three controls: size, leading, and flow. Everything else, heading sizes, list indents, the gap under a heading, the space around a rule, derives from them. Three controls. We called it rhythm.
---
## Features
- **It fits its container.** Put it in a chat bubble and it follows the smaller type around it. Put it in an article and it scales up with the page. On smaller screens, it gets a small bump for readability.
- **It uses your theme.** Colors, fonts, and radius come from your app. Dark mode follows the same tokens.
- **It's easy to tune.** Three values control the base size, line height, and space between blocks. Change them in a preset and the whole document follows.
- **It works well with streaming.** When a new block arrives, Typeset doesn't make earlier blocks switch margins, borders, or styles.
---
## Building Your Typeset
Create your typeset in the [typeset builder](/typeset). Pick your fonts and rhythm, then preview them on docs, chat, articles, and other real content.
The panel gives you the `typeset.css` file, the font setup for your framework, a preset class with your choices, and the wrapper to add around your content.
Copy `typeset.css` next to your main CSS file and import it after Tailwind:
```css
@import "tailwindcss";
@import "./typeset.css";
```
Then wrap your rendered markdown with `typeset` and your preset class:
```tsx
<div className="typeset typeset-docs">
<YourMarkdownRenderer>{content}</YourMarkdownRenderer>
</div>
```
`typeset` turns the styles on. `typeset-docs` is the preset you created in the builder.
---
## Custom Typesets
The file includes defaults, so you can use `typeset` by itself. Most of the reading rhythm comes from three values:
```css
.typeset {
--typeset-font-body: inherit;
--typeset-font-heading: var(--font-heading);
--typeset-font-mono: var(--font-mono);
--typeset-size: 1em; /* body font-size */
--typeset-leading: 1.75; /* line-height */
--typeset-flow: 1.25em; /* space between blocks */
}
```
- **`--typeset-size`** sets the base text size. `1em` follows the surrounding layout. On smaller screens, Typeset bumps it up a little.
- **`--typeset-leading`** sets the space between lines.
- **`--typeset-flow`** sets the space between blocks. Headings and other elements derive their spacing from it.
The font variables tell Typeset which families to use. Leave them alone and it follows your app. Colors and radius come from your theme too.
Typeset doesn't set a maximum width. Your layout owns that. The Measure control in the builder adds a `max-width` to the wrapper instead of hiding it in the stylesheet.
You can keep more than one preset in the same app. Here is a tighter one for chat and a roomier one for docs:
```css
.typeset-chat {
--typeset-flow: 1em;
--typeset-leading: 1.6;
}
.typeset-docs {
--typeset-size: 15px;
--typeset-flow: 1.5em;
}
```
```tsx
<div className="typeset typeset-chat">{message}</div>
<article className="typeset typeset-docs">{page}</article>
```
For a one-off change, skip the preset and set a value on the container:
```tsx
<article className="typeset [--typeset-flow:1.75em]">...</article>
```
---
## Custom Themes
A preset can change the whole feel of the content, not just the spacing. You can give readers a serif reading mode, a compact UI mode, or any other style that fits your product.
```css
/* Reading: serif, larger type, roomy rhythm. */
.typeset-reading {
--typeset-font-body: var(--font-lora);
--typeset-font-heading: var(--font-lora);
--typeset-size: 18px;
--typeset-leading: 1.9;
--typeset-flow: 2em;
}
/* Compact: sans, smaller type, tighter rhythm. */
.typeset-compact {
--typeset-font-body: var(--font-geist);
--typeset-font-heading: var(--font-geist);
--typeset-size: 14px;
--typeset-leading: 1.6;
--typeset-flow: 1em;
}
```
---
## Accessibility and Dark Mode
For readers who prefer larger type and more space, create a roomier typeset and expose it as a setting:
```css
.typeset-large {
--typeset-size: 16px;
--typeset-leading: 2;
--typeset-flow: 2em;
}
```
Dark mode already follows your theme colors. If the text feels a little tight on a dark surface, you can loosen the leading there:
```css
.dark .typeset {
--typeset-leading: 1.9;
}
```
---
## Responsive Table
Tables stay real tables and wrap to fit. To scroll a wide one horizontally instead, wrap it in `typeset-scroll`:
```tsx
<div className="typeset-scroll">
<table>...</table>
</div>
```
Do this in your renderer's table component or a small rehype plugin. It works for any wide block, not just tables.
---
## Overrides
Typeset lives in the `components` layer and uses `:where()` for its element selectors. Tailwind utilities on an element win without `!important`:
```tsx
<div className="typeset typeset-docs">
<p className="text-lg">...</p>
</div>
```
Plain CSS can override Typeset with a normal selector too.
---
## Opting Out
To keep a component out of Typeset, add `not-typeset` or `data-not-typeset`:
```tsx
<div className="typeset">
<p>Styled prose.</p>
<Card className="not-typeset">Untouched component.</Card>
</div>
```
Both options cover the component and everything inside it. Another `typeset` container inside that subtree stays opted out too.
---
## Streaming
Typeset is written so that adding a new block does not change the styles of the blocks already on screen.
- No forward-looking selectors. `:last-child`, `:has()`, and `:empty` are left out of layout rules because their matches can change as content is added.
- Spacing flows in one direction, using `margin-block-start` only. A new block adds its own space.
- Table separators live on the cells being added, so a new row does not restyle the row above it.
Text that is still streaming can grow and wrap normally. Typeset just avoids restyling the blocks that came before it.
---
## Prior Art
The `prose` class from `@tailwindcss/typography` is excellent at what it was built for: adding beautiful typographic defaults to plain HTML, including content rendered from Markdown or a CMS.
Typeset takes a different approach with container-aware sizing, app theme tokens, presets for different contexts, and streaming stability. Here's where they differ:
| | @tailwindcss/typography | Typeset |
| ------------ | -------------------------------------------- | ------------------------------------------------ |
| Sizing | Fixed `rem` scale, `prose-sm` to `prose-2xl` | Relative to the container, any size |
| Dark mode | `prose-invert`, a second palette | Your tokens flip, nothing to add |
| Theming | Prose color variables; scale baked in | Your theme tokens, plus font and rhythm controls |
| Overrides | `prose-a:`, `prose-headings:` modifier API | Plain utilities and CSS win |
| Streaming | No append-stability contract | Designed for stable appends |
| Distribution | npm plugin, generated CSS | One CSS file you own |
Typeset borrows the two best ideas from the plugin: the zero-specificity `:where()` guard pattern, and the escape-hatch class (`not-typeset`, in the spirit of `not-prose`).

View File

@@ -0,0 +1,482 @@
---
title: June 2023 - New CLI, Styles and more
description: Complete CLI rewrite with new styles, theming options, and more.
date: 2023-06-22
---
I have a lot of updates to share with you today:
- [**New CLI**](#new-cli) - Rewrote the CLI from scratch. You can now add components, dependencies and configure import paths.
- [**Theming**](#theming-with-css-variables-or-tailwind-colors) - Choose between using CSS variables or Tailwind CSS utility classes for theming.
- [**Base color**](#base-color) - Configure the base color for your project. This will be used to generate the default color palette for your components.
- [**React Server Components**](#react-server-components) - Opt out of using React Server Components. The CLI will automatically append or remove the `use client` directive.
- [**Styles**](#styles) - Introducing a new concept called _Style_. A style comes with its own set of components, animations, icons and more.
- [**Exit animations**](#exit-animations) - Added exit animations to all components.
- [**Other updates**](#other-updates) - New `icon` button size, updated `sheet` component and more.
- [**Updating your project**](#updating-your-project) - How to update your project to get the latest changes.
---
### New CLI
I've been working on a new CLI for the past few weeks. It's a complete rewrite. It comes with a lot of new features and improvements.
### `init`
```bash
npx shadcn@latest init
```
When you run the `init` command, you will be asked a few questions to configure `components.json`:
```txt showLineNumbers
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? › › app/globals.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
```
This file contains all the information about your components: where to install them, the import paths, how they are styled...etc.
You can use this file to change the import path of a component, set a baseColor or change the styling method.
```json title="components.json" showLineNumbers
{
"style": "default",
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/app/globals.css",
"baseColor": "zinc",
"cssVariables": true
},
"rsc": false,
"aliases": {
"utils": "~/lib/utils",
"components": "~/components"
}
}
```
This means you can now use the CLI with any directory structure including `src` and `app` directories.
### `add`
```bash
npx shadcn@latest add
```
The `add` command is now much more capable. You can now add UI components but also import more complex components (coming soon).
The CLI will automatically resolve all components and dependencies, format them based on your custom config and add them to your project.
### `diff` (experimental)
```bash
npx shadcn diff
```
We're also introducing a new `diff` command to help you keep track of upstream updates.
You can use this command to see what has changed in the upstream repository and update your project accordingly.
Run the `diff` command to get a list of components that have updates available:
```bash
npx shadcn diff
```
```txt
The following components have updates available:
- button
- /path/to/my-app/components/ui/button.tsx
- toast
- /path/to/my-app/components/ui/use-toast.ts
- /path/to/my-app/components/ui/toaster.tsx
```
Then run `diff [component]` to see the changes:
```bash
npx shadcn diff alert
```
```diff /pl-12/
const alertVariants = cva(
- "relative w-full rounded-lg border",
+ "relative w-full pl-12 rounded-lg border"
)
```
---
### Theming with CSS Variables or Tailwind Colors
You can choose between using CSS variables or Tailwind CSS utility classes for theming.
When you add new components, the CLI will automatically use the correct theming methods based on your `components.json` configuration.
#### Utility classes
```tsx /bg-zinc-950/ /text-zinc-50/ /dark:bg-white/ /dark:text-zinc-950/
<div className="bg-zinc-950 dark:bg-white" />
```
To use utility classes for theming set `tailwind.cssVariables` to `false` in your `components.json` file.
```json {6} title="components.json" showLineNumbers
{
"tailwind": {
"config": "tailwind.config.js",
"css": "app/globals.css",
"baseColor": "slate",
"cssVariables": false
}
}
```
#### CSS Variables
```tsx /bg-background/ /text-foreground/
<div className="bg-background text-foreground" />
```
To use CSS variables classes for theming set `tailwind.cssVariables` to `true` in your `components.json` file.
```json {6} title="components.json" showLineNumbers
{
"tailwind": {
"config": "tailwind.config.js",
"css": "app/globals.css",
"baseColor": "slate",
"cssVariables": true
}
}
```
---
### Base color
You can now configure the base color for your project. This will be used to generate the default color palette for your components.
```json {5} title="components.json" showLineNumbers
{
"tailwind": {
"config": "tailwind.config.js",
"css": "app/globals.css",
"baseColor": "zinc",
"cssVariables": false
}
}
```
Choose between `gray`, `neutral`, `slate`, `stone` or `zinc`.
If you have `cssVariables` set to `true`, we will set the base colors as CSS variables in your `globals.css` file. If you have `cssVariables` set to `false`, we will inline the Tailwind CSS utility classes in your components.
---
### React Server Components
If you're using a framework that does not support React Server Components, you can now opt out by setting `rsc` to `false`. We will automatically append or remove the `use client` directive when adding components.
```json title="components.json" showLineNumbers
{
"rsc": false
}
```
---
### Styles
We are introducing a new concept called _Style_.
_You can think of style as the visual foundation: shapes, icons, animations & typography._ A style comes with its own set of components, animations, icons and more.
We are shipping two styles: `default` and `new-york` (with more coming soon).
<Image
src="/images/style.jpg"
width="716"
height="402"
alt="Default vs New York style"
className="mt-6 overflow-hidden rounded-2xl border"
/>
The `default` style is the one you are used to. It's the one we've been using since the beginning of this project. It uses `lucide-react` for icons and `tailwindcss-animate` for animations.
The `new-york` style is a new style. It ships with smaller buttons, cards with shadows and a new set of icons from [Radix Icons](https://icons.radix-ui.com).
When you run the `init` command, you will be asked which style you would like to use. This is saved in your `components.json` file.
```json title="components.json" showLineNumbers
{
"style": "new-york"
}
```
### Theming
Start with a style as the base then theme using CSS variables or Tailwind CSS utility classes to completely change the look of your components.
<Image
src="/images/style-with-theming.jpg"
width="716"
height="402"
alt="Style with theming"
className="mt-6 overflow-hidden rounded-2xl border"
/>
---
### Exit animations
I added exit animations to all components. Click on the combobox below to see the subtle exit animation.
<ComponentPreview
styleName="new-york-v4"
name="combobox-demo"
className="[&_.preview]:items-start"
/>
The animations can be customized using utility classes.
---
### Other updates
### Button
- Added a new button size `icon`:
<ComponentPreview styleName="new-york-v4" name="button-icon" />
### Sheet
- Renamed `position` to `side` to match the other elements.
<ComponentPreview styleName="new-york-v4" name="sheet-side" />
- Removed the `size` props. Use `className="w-[200px] md:w-[450px]"` for responsive sizing.
---
### Updating your project
Since we follow a copy and paste approach, you will need to manually update your project to get the latest changes.
<Callout className="mt-4">
Note: we are working on a [`diff`](#diff-experimental) command to help you
keep track of upstream updates.
</Callout>
<Steps>
### Add `components.json`
Creating a `components.json` file at the root:
```json title="components.json" showLineNumbers
{
"style": "default",
"rsc": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "app/globals.css",
"baseColor": "slate",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}
```
Update the values for `tailwind.css` and `aliases` to match your project structure.
### Button
Add the `icon` size to the `buttonVariants`:
```tsx {7} title="components/ui/button.tsx" showLineNumbers
const buttonVariants = cva({
variants: {
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
})
```
### Sheet
1. Replace the content of `sheet.tsx` with the following:
```tsx title="components/ui/sheet.tsx" showLineNumbers
"use client"
import * as React from "react"
import * as SheetPrimitive from "@radix-ui/react-dialog"
import { cva, type VariantProps } from "class-variance-authority"
import { X } from "lucide-react"
import { cn } from "@/lib/utils"
const Sheet = SheetPrimitive.Root
const SheetTrigger = SheetPrimitive.Trigger
const SheetClose = SheetPrimitive.Close
const SheetPortal = ({
className,
...props
}: SheetPrimitive.DialogPortalProps) => (
<SheetPrimitive.Portal className={cn(className)} {...props} />
)
SheetPortal.displayName = SheetPrimitive.Portal.displayName
const SheetOverlay = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Overlay
className={cn(
"fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
className
)}
{...props}
ref={ref}
/>
))
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
const sheetVariants = cva(
"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:animate-in data-[state=open]:duration-500",
{
variants: {
side: {
top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
bottom:
"inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
right:
"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
},
},
defaultVariants: {
side: "right",
},
}
)
interface SheetContentProps
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
VariantProps<typeof sheetVariants> {}
const SheetContent = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Content>,
SheetContentProps
>(({ side = "right", className, children, ...props }, ref) => (
<SheetPortal>
<SheetOverlay />
<SheetPrimitive.Content
ref={ref}
className={cn(sheetVariants({ side }), className)}
{...props}
>
{children}
<SheetPrimitive.Close className="absolute top-4 right-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-none disabled:pointer-events-none data-[state=open]:bg-secondary">
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
</SheetPrimitive.Content>
</SheetPortal>
))
SheetContent.displayName = SheetPrimitive.Content.displayName
const SheetHeader = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col space-y-2 text-center sm:text-left",
className
)}
{...props}
/>
)
SheetHeader.displayName = "SheetHeader"
const SheetFooter = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className
)}
{...props}
/>
)
SheetFooter.displayName = "SheetFooter"
const SheetTitle = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Title
ref={ref}
className={cn("text-lg font-semibold text-foreground", className)}
{...props}
/>
))
SheetTitle.displayName = SheetPrimitive.Title.displayName
const SheetDescription = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Description
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
))
SheetDescription.displayName = SheetPrimitive.Description.displayName
export {
Sheet,
SheetTrigger,
SheetClose,
SheetContent,
SheetHeader,
SheetFooter,
SheetTitle,
SheetDescription,
}
```
2. Rename `position` to `side`
```diff /position/ /side/
- <Sheet position="right" />
+ <Sheet side="right" />
```
</Steps>
### Thank you
I'd like to thank everyone who has been using this project, providing feedback and contributing to it. I really appreciate it. Thank you.

View File

@@ -0,0 +1,45 @@
---
title: July 2023 - JavaScript
description: JavaScript version of components available via the CLI.
date: 2023-07-04
---
This project and the components are written in TypeScript. **We recommend using TypeScript for your project as well**.
However we provide a JavaScript version of the components, available via the [cli](/docs/cli).
```txt
Would you like to use TypeScript (recommended)? no
```
To opt-out of TypeScript, you can use the `tsx` flag in your `components.json` file.
```json {10} title="components.json" showLineNumbers
{
"style": "default",
"tailwind": {
"config": "tailwind.config.js",
"css": "src/app/globals.css",
"baseColor": "zinc",
"cssVariables": true
},
"rsc": false,
"tsx": false,
"aliases": {
"utils": "~/lib/utils",
"components": "~/components"
}
}
```
To configure import aliases, you can use the following `jsconfig.json`:
```json {4} title="jsconfig.json" showLineNumbers
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}
```

View File

@@ -0,0 +1,68 @@
---
title: December 2023 - New Components
description: Carousel, Drawer, Pagination, Resizable, Sonner, and CLI updates.
date: 2023-12-22
---
We've added new components to shadcn/ui and made a lot of improvements to the CLI.
Here's a quick overview of what's new:
- [**Carousel**](#carousel) - A carousel component with motion, swipe gestures and keyboard support.
- [**Drawer**](#drawer) - A drawer component that looks amazing on mobile.
- [**Pagination**](#pagination) - A pagination component with page navigation, previous and next buttons.
- [**Resizable**](#resizable) - A resizable component for building resizable panel groups and layouts.
- [**Sonner**](#sonner) - The last toast component you'll ever need.
- [**CLI updates**](#cli-updates) - Support for custom **Tailwind prefix** and `tailwind.config.ts`.
### Carousel
We've added a fully featured carousel component with motion, swipe gestures and keyboard support. Built on top of [Embla Carousel](https://www.embla-carousel.com).
It has support for infinite looping, autoplay, vertical orientation, and more.
<ComponentPreview styleName="new-york-v4" name="carousel-demo" />
### Drawer
Oh the drawer component. Built on top of [Vaul](https://github.com/emilkowalski/vaul) by [emilkowalski](https://twitter.com/emilkowalski).
Try opening the following drawer on mobile. It looks amazing!
<ComponentPreview styleName="new-york-v4" name="drawer-demo" />
### Pagination
We've added a pagination component with page navigation, previous and next buttons. Simple, flexible and works with your framework's `<Link />` component.
<ComponentPreview styleName="new-york-v4" name="pagination-demo" />
### Resizable
Build resizable panel groups and layouts with this `<Resizable />` component.
<ComponentPreview styleName="new-york-v4" name="resizable-demo-with-handle" />
`<Resizable />` is built using [react-resizable-panels](https://github.com/bvaughn/react-resizable-panels) by [bvaughn](https://github.com/bvaughn). It has support for mouse, touch and keyboard.
### Sonner
Another one by [emilkowalski](https://twitter.com/emilkowalski). The last toast component you'll ever need. Sonner is now available in shadcn/ui.
<ComponentPreview styleName="new-york-v4" name="sonner-demo" />
### CLI updates
This has been one of the most requested features. You can now configure a custom Tailwind prefix and the cli will automatically prefix your utility classes when adding components.
This means you can now easily add shadcn/ui components to existing projects like Docusaurus, Nextra...etc. A drop-in for your existing design system with no conflict.
```tsx /tw-/
<AlertDialog className="tw-grid tw-gap-4 tw-border tw-bg-background tw-shadow-lg" />
```
It works with `cn`, `cva` and CSS variables.
The cli can now also detect `tailwind.config.ts` and add the TypeScript version of the config for you.
That's it. Happy Holidays.

View File

@@ -0,0 +1,99 @@
---
title: March 2024 - Introducing Blocks
description: Ready-made components for dashboards and authentication pages.
date: 2024-03-22
---
One of the most requested features since launch has been layouts: admin dashboards with sidebar, marketing page sections, cards and more.
**Today, we're launching [Blocks](/blocks).**
<a href="/blocks">
<Image
src="/images/dashboard-1.jpg"
width="716"
height="430"
alt="Admin dashboard"
className="mt-6 w-full overflow-hidden rounded-2xl border dark:hidden"
/>
<Image
src="/images/dashboard-1-dark.jpg"
width="716"
height="430"
alt="Admin dashboard"
className="mt-6 hidden w-full overflow-hidden rounded-2xl border shadow-sm dark:block"
/>
<span className="sr-only">View the blocks library</span>
</a>
Blocks are ready-made components that you can use to build your apps. They are fully responsive, accessible, and composable, meaning they are built using the same principles as the rest of the components in shadcn/ui.
We're starting with dashboard layouts and authentication pages, with plans to add more blocks in the coming weeks.
### Open Source
Blocks are open source. You can find the source on GitHub. Use them in your projects, customize them and contribute back.
<a href="/blocks">
<Image
src="/images/dashboard-2.jpg"
width="716"
height="420"
alt="AI Playground"
className="mt-6 w-full overflow-hidden rounded-2xl border dark:hidden"
/>
<Image
src="/images/dashboard-2-dark.jpg"
width="716"
height="420"
alt="AI Playground"
className="mt-6 hidden w-full overflow-hidden rounded-2xl border shadow-sm dark:block"
/>
<span className="sr-only">View the blocks library</span>
</a>
### Request a Block
We're also introducing a "Request a Block" feature. If there's a specific block you'd like to see, simply create a request on GitHub and the community can upvote and build it.
<a href="/blocks">
<Image
src="/images/dashboard-3.jpg"
width="716"
height="420"
alt="Settings Page"
className="mt-6 w-full overflow-hidden rounded-2xl border dark:hidden"
/>
<Image
src="/images/dashboard-3-dark.jpg"
width="716"
height="420"
alt="Settings Page"
className="mt-6 hidden w-full overflow-hidden rounded-2xl border shadow-sm dark:block"
/>
<span className="sr-only">View the blocks library</span>
</a>
### v0
If you have a [v0](https://v0.dev) account, you can use the **Edit in v0** feature to open the code on v0 for prompting and further generation.
<div className="mt-6 flex aspect-video w-full items-center justify-center overflow-hidden rounded-2xl border bg-background shadow-sm">
<svg
viewBox="0 0 40 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="h-40 w-40 text-foreground"
>
<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>
</div>
That's it. _Looking forward to seeing what you build with Blocks_.

View File

@@ -0,0 +1,25 @@
---
title: March 2024 - Breadcrumb and Input OTP
description: New Breadcrumb and Input OTP components.
date: 2024-03-08
---
We've added a new Breadcrumb component and an Input OTP component.
### Breadcrumb
An accessible and flexible breadcrumb component. It has support for collapsed items, custom separators, bring-your-own routing `<Link />` and composable with other shadcn/ui components.
<ComponentPreview styleName="new-york-v4" name="breadcrumb-demo" />
[See more examples](/docs/components/breadcrumb)
### Input OTP
A fully featured input OTP component. It has support for numeric and alphanumeric codes, custom length, copy-paste and accessible. Input OTP is built on top of [input-otp](https://github.com/guilhermerodz/input-otp) by [@guilherme_rodz](https://twitter.com/guilherme_rodz).
<ComponentPreview styleName="new-york-v4" name="input-otp-demo" />
[Read the docs](/docs/components/input-otp)
If you have a [v0](https://v0.dev) account, the new components are available for generation.

View File

@@ -0,0 +1,31 @@
---
title: April 2024 - Lift Mode
description: A new mode for Blocks to lift smaller components for copy and paste.
date: 2024-04-05
---
We're introducing a new mode for [Blocks](/blocks) called **Lift Mode**.
Enable Lift Mode to automatically "lift" smaller components from a block template for copy and paste.
<a href="/blocks">
<Image
src="/images/lift-mode-light.png"
width="1432"
height="1050"
alt="Lift Mode"
className="mt-6 w-full overflow-hidden rounded-2xl border dark:hidden"
/>
<Image
src="/images/lift-mode-dark.png"
width="1432"
height="1069"
alt="Lift Mode"
className="mt-6 hidden w-full overflow-hidden rounded-2xl border shadow-sm dark:block"
/>
<span className="sr-only">View the blocks library</span>
</a>
With Lift Mode, you'll be able to copy the smaller components that make up a block template, like cards, buttons, and forms, and paste them directly into your project.
Visit the [Blocks](/blocks) page to try it out.

View File

@@ -0,0 +1,45 @@
---
title: August 2024 - npx shadcn init
description: Complete CLI rewrite with support for all major React frameworks.
date: 2024-08-31
---
The new CLI is now available. It's a complete rewrite with a lot of new features and improvements. You can now install components, themes, hooks, utils and more using `npx shadcn add`.
This is a major step towards distributing code that you and your LLMs can access and use.
1. First up, the CLI now has support for all major React frameworks out of the box. Next.js, Remix, Vite and Laravel. And when you init into a new app, we update your existing Tailwind files instead of overriding.
2. A component now ships its own dependencies. Take the accordion for example, it can define its Tailwind keyframes. When you add it to your project, we'll update your tailwind.config.ts file accordingly.
3. You can also install remote components using url. `npx shadcn add https://acme.com/registry/navbar.json`.
4. We have also improved the init command. It does framework detection and can even init a brand new Next.js app in one command. `npx shadcn init`.
5. We have created a new schema that you can use to ship your own component registry. And since it has support for urls, you can even use it to distribute private components.
6. And a few more updates like better error handling and monorepo support.
You can try the new cli today.
```bash
npx shadcn init sidebar-01 login-01
```
### Update Your Project
To update an existing project to use the new CLI, update your `components.json` file to include import aliases for your **components**, **utils**, **ui**, **lib** and **hooks**.
```json showLineNumbers {7-13} title="components.json"
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"tailwind": {
// ...
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
}
}
```
If you're using a different import alias prefix, e.g. `~`, replace `@` with your prefix.

View File

@@ -0,0 +1,11 @@
---
title: October 2024 - React 19
description: shadcn/ui is now compatible with React 19 and Next.js 15.
date: 2024-10-29
---
shadcn/ui is now compatible with React 19 and Next.js 15.
We published a guide to help you upgrade your project to React 19.
Read more [here](/docs/react-19).

View File

@@ -0,0 +1,13 @@
---
title: October 2024 - Sidebar
description: 25 components to help you build all kinds of sidebars.
date: 2024-10-18
---
Introducing sidebar.tsx: 25 components to help you build all kinds of sidebars.
I don't like building sidebars. So I built 30+ of them. All types. Then simplified the core into sidebar.tsx: a strong foundation to build on top of.
It works with Next.js, Remix, Vite & Laravel.
See the announcement [here](https://x.com/shadcn/status/1847359896557408461).

View File

@@ -0,0 +1,13 @@
---
title: November 2024 - Icons
description: The new-york style now uses Lucide as the default icon set.
date: 2024-11-06
---
An update on icons. The new-york style now uses Lucide as the default icon set.
- New projects will use Lucide by default
- No breaking changes for existing projects
- Use the CLI to (optionally) migrate primitives to Lucide
For more info on why we're doing this, see the [thread](https://x.com/shadcn/status/1853902179041702169).

View File

@@ -0,0 +1,18 @@
---
title: December 2024 - Monorepo Support
description: New monorepo support in the CLI.
date: 2024-12-20
---
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.
Read more in the [docs](/docs/monorepo).

View File

@@ -0,0 +1,11 @@
---
title: January 2025 - Blocks Community
description: Inviting the community to contribute to the blocks library.
date: 2025-01-14
---
We are inviting the community to contribute to the blocks library. 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.
See the [docs](/docs/blocks) page to get started.

View File

@@ -0,0 +1,13 @@
---
title: February 2025 - Updated Registry Schema
description: Updated registry schema to support more features.
date: 2025-02-06
---
We're updating the registry schema to support more features.
Define code as a flat JSON file and distribute it via the CLI.
- Custom styles: bring your own design system, components & tokens
- Extend, override, mix & match components from third-party registries and LLMs
- Install themes, CSS vars, hooks, animations, and Tailwind layers & utilities

View File

@@ -0,0 +1,22 @@
---
title: February 2025 - Tailwind v4
description: First preview of Tailwind v4 and React 19 support.
date: 2025-02-19
---
We shipped the first preview of Tailwind v4 and React 19. Ready for you to try out. You can start using it today.
What's New:
- The CLI can now initialize projects with Tailwind v4.
- Full support for the new @theme directive and @theme inline option.
- All components are updated for Tailwind v4 and React 19.
- We've removed the forwardRefs and adjusted the types.
- Every primitive now has a data-slot attribute for styling.
- We've fixed and cleaned up the style of the components.
- We're deprecating the toast component in favor of sonner.
- Buttons now use the default cursor.
- We're deprecating the default style. New projects will use new-york.
- HSL colors are now converted to OKLCH.
Read more in the [docs](/docs/tailwind-v4).

View File

@@ -0,0 +1,9 @@
---
title: April 2025 - Cross-framework Route Support
description: The shadcn CLI can now auto-detect your framework and adapt routes for you.
date: 2025-04-09
---
The shadcn CLI can now auto-detect your framework and adapt routes for you.
Works with all frameworks including Laravel, Vite and React Router.

View File

@@ -0,0 +1,17 @@
---
title: April 2025 - MCP
description: Zero-config MCP support for shadcn/ui registry.
date: 2025-04-30
---
We're working on zero-config MCP support for shadcn/ui registry. One command `npx shadcn registry:mcp` to make any registry mcp-compatible.
<Image
src="/images/mcp.jpeg"
width="1432"
height="1050"
alt="MCP Server"
className="mt-6 w-full overflow-hidden rounded-2xl border"
/>
Learn more in the [thread here](https://x.com/shadcn/status/1917597228513853603).

View File

@@ -0,0 +1,11 @@
---
title: April 2025 - shadcn 2.5.0
description: Resolve anywhere - registries can now place files anywhere in an app.
date: 2025-04-26
---
We tagged shadcn 2.5.0 earlier this week. It comes with a pretty cool feature: **resolve anywhere**.
Registries can now place files anywhere in an app and we'll properly resolve imports. No need to stick to a fixed file structure. It can even add files outside the registry itself.
On install, we track all files and perform a multi-pass resolution to correctly handle imports and aliases. It's fast.

View File

@@ -0,0 +1,11 @@
---
title: May 2025 - New Site
description: Upgraded ui.shadcn.com to Next.js 15.3 and Tailwind v4.
date: 2025-05-30
---
We've upgraded [ui.shadcn.com](https://ui.shadcn.com) to Next.js 15.3 and Tailwind v4. The site now uses the upgraded `new-york` components.
We've also made some minor design updates to make the site faster and easier to navigate.
This upgrade unlocks a lot of new features that we're working on. More to come.

View File

@@ -0,0 +1,13 @@
---
title: June 2025 - Calendar Component
description: Upgraded Calendar component with React DayPicker and 30+ calendar blocks.
date: 2025-06-06
---
We've upgraded the `Calendar` component to the latest version of [React DayPicker](https://daypicker.dev).
This is a major upgrade and includes a lot of new features and improvements.
<Image src="/images/calendar-2.png" alt="Calendar" width={676} height={895} />
To upgrade your project to the latest version of the `Calendar` component, see the [upgrade guide](/docs/components/calendar#upgrade-guide).

View File

@@ -0,0 +1,22 @@
---
title: June 2025 - radix-ui Migration
description: A new command to migrate to the new radix-ui package.
date: 2025-06-11
---
We've added a new command to migrate to the new `radix-ui` package. This command will replace all `@radix-ui/react-*` imports with `radix-ui`.
```bash
npx shadcn@latest migrate radix
```
It will automatically update all imports in your `ui` components and install `radix-ui` as a dependency.
```diff showLineNumbers title="components/ui/alert-dialog.tsx"
- import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
+ import { AlertDialog as AlertDialogPrimitive } from "radix-ui"
```
Make sure to test your components and project after running the command.
**Note:** To update imports for newly added components, run the migration command again.

View File

@@ -0,0 +1,22 @@
---
title: July 2025 - Local File Support
description: Initialize projects and add components from local JSON files.
date: 2025-07-07
---
The shadcn CLI now supports local files. Initialize projects and add components, themes, hooks, utils and more from local JSON files.
```bash
# Initialize a project from a local file
npx shadcn init ./template.json
# Add a component from a local file
npx shadcn add ./block.json
```
This feature enables powerful new workflows:
- **Zero setup** - No remote registries required
- **Faster development** - Test registry items locally before publishing
- **Enhanced workflow for agents and MCP** - Generate and run registry items locally
- **Private components** - Keep proprietary components local and private.

View File

@@ -0,0 +1,11 @@
---
title: July 2025 - Universal Registry Items
description: Create registry items that can be distributed to any project.
date: 2025-07-11
---
We've added support for universal registry items. This allows you to create registry items that can be distributed to any project i.e. no framework, no components.json, no tailwind, no react required.
This new registry item type unlocks a lot of new workflows. You can now distribute code, config, rules, docs, anything to any code project.
See the [docs](/docs/registry/examples) for more details and examples.

View File

@@ -0,0 +1,206 @@
---
title: August 2025 - shadcn CLI 3.0 and MCP Server
description: Namespaced registries, advanced authentication, new commands and a completely rewritten registry engine.
date: 2025-08-27
---
We just shipped shadcn CLI 3.0 with support for namespaced registries, advanced authentication, new commands and a completely rewritten registry engine.
### What's New
- [Namespaced Registries](#namespaced-registries) - Install components using `@registry/name` format.
- [Private Registries](#private-registries) - Secure your registry with advanced authentication.
- [Search & Discovery](#search--discovery) - New commands to find and view code before installing.
- [MCP Server](#mcp-server) - MCP server for all registries.
- [Faster Everything](#faster-everything) - Completely rewritten registry resolution.
- [Improved Error Handling](#improved-error-handling) - Better error messages for users and LLMs.
- [Upgrade Guide](#upgrade-guide) - Migration notes for existing users.
### Namespaced Registries
The biggest change in 3.0 is namespaced registries. You can now install components from registries: a community registry, your company's private registry or internal registry, using the `@registry/name` format.
This makes it easier to distribute code across teams and projects.
Configure registries in your `components.json`:
```json title="components.json"
{
"registries": {
"@acme": "https://acme.com/r/{name}.json",
"@internal": {
"url": "https://registry.company.com/{name}",
"headers": {
"Authorization": "Bearer ${REGISTRY_TOKEN}"
}
}
}
}
```
Then use the `@registry/name` format to install components:
```bash
npx shadcn add @acme/button @internal/auth-system
```
It's completely decentralized. There's no central registrar. Create any namespace you want and organize components however makes sense for your team.
```json title="components.json" showLineNumbers
{
"registries": {
"@design": "https://registry.company.com/create/{name}.json",
"@engineering": "https://registry.company.com/eng/{name}.json",
"@marketing": "https://registry.company.com/marketing/{name}.json"
}
}
```
Components can even depend on resources from different registries. Everything gets resolved and installed automatically from the right sources.
```json title="registry-item.json" showLineNumbers
{
"name": "dashboard",
"type": "registry:block",
"registryDependencies": [
"@shadcn/card", // From default registry
"@v0/chart", // From v0 registry
"@acme/data-table", // From acme registry
"@lib/data-fetcher", // Utility library
"@ai/analytics-prompt" // AI prompt resource
]
}
```
### Private Registries
Need to keep your components private? We've got you covered. Configure authentication with tokens, API keys, or custom headers:
```json title="components.json"
{
"registries": {
"@private": {
"url": "https://registry.company.com/{name}.json",
"headers": {
"Authorization": "Bearer ${REGISTRY_TOKEN}"
}
}
}
}
```
Your private components stay private. Perfect for enterprise teams with proprietary UI libraries.
We support all major authentication methods: basic auth, bearer token, API key query params and custom headers.
See the [authentication docs](/docs/registry/authentication) for more details.
### Search & Discovery
Three new commands make it easy to find exactly what you need:
1. View items from the registry before installing
```bash
npx shadcn view @acme/auth-system
```
2. Search items from registries
```bash
npx shadcn search @tweakcn -q "dark"
```
3. List all items from a registry
```bash
npx shadcn list @acme
```
Preview components before installing them. Search across multiple registries. See the code and all dependencies upfront.
### MCP Server
<Image
src="/images/mcp.jpeg"
width="1432"
height="1050"
alt="MCP Server"
className="mt-6 w-full overflow-hidden rounded-2xl border"
/>
Back in April, we [introduced](https://x.com/shadcn/status/1917597228513853603) the first version of the MCP server. Since then, we've taken everything we learned and built a better MCP server.
Here's what's new:
- Works with all registries. Zero config
- One command to add to your favorite MCP clients
- We improved the underlying tools
- Better integration with the CLI and registries
- Support for multiple registries in the same project
Add the MCP server to your project:
```bash
npx shadcn@latest mcp init
```
See the [docs](/docs/mcp) for more details.
### Faster Everything
We completely rewrote the registry resolution engine from scratch. It's faster, smarter, and handles even the trickiest dependency trees.
- Up to 3x faster dependency resolution
- Smarter file deduplication and merging
- Better monorepo support out of the box
- Updated `build` command for registry authors
### Improved Error Handling
Registry developers can now provide custom error messages to help guide users (and LLMs) when things go wrong. The CLI displays helpful, actionable errors for common issues:
```txt
Unknown registry "@acme". Make sure it is defined in components.json as follows:
{
"registries": {
"@acme": "[URL_TO_REGISTRY]"
}
}
```
Missing environment variables? The CLI tells you exactly what's needed:
```txt
Registry "@private" requires the following environment variables:
• REGISTRY_TOKEN
Set the required environment variables in your .env or .env.local file.
```
Registry authors can provide custom error messages in their responses to help users and AI agents understand and fix issues quickly.
```txt
Error:
You are not authorized to access the item at http://example.com/r/component.
Message:
[Unauthorized] Your API key has expired. Renew it at https://example.com/api/renew-key.
```
### Upgrade Guide
Here's the best part: there are no breaking changes for users. Your existing `components.json` works exactly the same. All your installed components work exactly the same.
For developers, if you're using the programmatic APIs directly, we've deprecated a few functions in favor of better ones:
- `fetchRegistry` → `getRegistry`
- `resolveRegistryTree` → `resolveRegistryItems`
- Schema moved from `shadcn/registry` to `shadcn/schema` package
```diff
- import { registryItemSchema } from "shadcn/registry"
+ import { registryItemSchema } from "shadcn/schema"
```
That's it. Seriously. Everything else just works.

View File

@@ -0,0 +1,19 @@
---
title: September 2025 - Registry Index
description: An index of open source registries that you can install items from.
date: 2025-09-02
---
We've created an index of open source registries that you can install items from.
You can search, view and add items from the registry index without configuring the `components.json` file.
They'll be automatically added to your `components.json` file for you.
```bash
npx shadcn add @ai-elements/prompt-input
```
The full list of registries is available at [https://ui.shadcn.com/r/registries.json](https://ui.shadcn.com/r/registries.json).
To add a registry to the index, submit a PR to the `shadcn/ui` repository. See the [registry index documentation](/docs/registry/registry-index) for more details.

View File

@@ -0,0 +1,418 @@
---
title: October 2025 - New Components
description: Spinner, Kbd, Button Group, Input Group, Field, Item, and Empty components.
date: 2025-10-03
---
For this round of components, I looked at what we build every day, the boring stuff we rebuild over and over, and made reusable abstractions you can actually use.
**These components work with every component library, Radix, Base UI, React Aria, you name it. Copy and paste to your projects.**
- [Spinner](#spinner): An indicator to show a loading state.
- [Kbd](#kbd): Display a keyboard key or group of keys.
- [Button Group](#button-group): A group of buttons for actions and split buttons.
- [Input Group](#input-group): Input with icons, buttons, labels and more.
- [Field](#field): One component. All your forms.
- [Item](#item): Display lists of items, cards, and more.
- [Empty](#empty): Use this one for empty states.
### Spinner
Okay let's start with the easiest ones: **Spinner** and **Kbd**. Pretty basic. We all know what they do.
Here's how you render a spinner:
```tsx
import { Spinner } from "@/components/ui/spinner"
```
```tsx
<Spinner />
```
Here's what it looks like:
<ComponentPreview styleName="new-york-v4"
name="spinner-basic"
/>
Here's what it looks like in a button:
<ComponentPreview styleName="new-york-v4"
name="spinner-button"
/>
You can edit the code and replace it with your own spinner.
<ComponentPreview styleName="new-york-v4"
name="spinner-custom"
/>
### Kbd
Kbd is a component that renders a keyboard key.
```tsx
import { Kbd, KbdGroup } from "@/components/ui/kbd"
```
```tsx
<Kbd>Ctrl</Kbd>
```
Use `KbdGroup` to group keyboard keys together.
```tsx showLineNumbers
<KbdGroup>
<Kbd>Ctrl</Kbd>
<Kbd>B</Kbd>
</KbdGroup>
```
<ComponentPreview styleName="new-york-v4"
name="kbd-demo"
/>
You can add it to buttons, tooltips, input groups, and more.
### Button Group
I got a lot of requests for this one: Button Group. It's a container that groups related buttons together with consistent styling. Great for action groups, split buttons, and more.
<ComponentPreview styleName="new-york-v4"
name="button-group-demo"
/>
Here's the code:
```tsx
import { ButtonGroup } from "@/components/ui/button-group"
```
```tsx showLineNumbers
<ButtonGroup>
<Button>Button 1</Button>
<Button>Button 2</Button>
</ButtonGroup>
```
You can nest button groups to create more complex layouts with spacing.
```tsx showLineNumbers
<ButtonGroup>
<ButtonGroup>
<Button>Button 1</Button>
<Button>Button 2</Button>
</ButtonGroup>
<ButtonGroup>
<Button>Button 3</Button>
<Button>Button 4</Button>
</ButtonGroup>
</ButtonGroup>
```
Use `ButtonGroupSeparator` to create split buttons. Classic dropdown pattern.
<ComponentPreview styleName="new-york-v4"
name="button-group-dropdown"
/>
You can also use it to add prefix or suffix buttons and text to inputs.
<ComponentPreview styleName="new-york-v4"
name="button-group-select"
/>
```tsx showLineNumbers
<ButtonGroup>
<ButtonGroupText>Prefix</ButtonGroupText>
<Input placeholder="Type something here..." />
<Button>Button</Button>
</ButtonGroup>
```
### Input Group
Input Group lets you add icons, buttons, and more to your inputs. You know, all those little bits you always need around your inputs.
```tsx
import {
InputGroup,
InputGroupAddon,
InputGroupInput,
} from "@/components/ui/input-group"
```
```tsx showLineNumbers
<InputGroup>
<InputGroupInput placeholder="Search..." />
<InputGroupAddon>
<SearchIcon />
</InputGroupAddon>
</InputGroup>
```
Here's a preview with icons:
<ComponentPreview
styleName="new-york-v4"
name="input-group-icon"
className="[&_.preview]:h-[300px] [&_pre]:h-[300px]!"
/>
You can also add buttons to the input group.
<ComponentPreview
styleName="new-york-v4"
name="input-group-button"
className="[&_.preview]:h-[300px] [&_pre]:h-[300px]!"
/>
Or text, labels, tooltips, ...
<ComponentPreview
styleName="new-york-v4"
name="input-group-text"
className="[&_.preview]:h-[350px] [&_pre]:h-[350px]!"
/>
It also works with textareas so you can build really complex components with lots of knobs and dials or yet another prompt form.
<ComponentPreview
styleName="new-york-v4"
name="input-group-textarea"
className="[&_.preview]:h-[450px] [&_pre]:h-[450px]!"
/>
Oh here are some cool ones with spinners:
<ComponentPreview
styleName="new-york-v4"
name="input-group-spinner"
className="[&_.preview]:h-[350px] [&_pre]:h-[350px]!"
/>
### Field
Introducing **Field**, a component for building really complex forms. The abstraction here is beautiful.
It took me a long time to get it right but I made it work with all your form libraries: Server Actions, React Hook Form, TanStack Form, Bring Your Own Form.
```tsx
import {
Field,
FieldDescription,
FieldError,
FieldLabel,
} from "@/components/ui/field"
```
Here's a basic field with an input:
```tsx showLineNumbers
<Field>
<FieldLabel htmlFor="username">Username</FieldLabel>
<Input id="username" placeholder="Max Leiter" />
<FieldDescription>
Choose a unique username for your account.
</FieldDescription>
</Field>
```
<ComponentPreview
styleName="new-york-v4"
name="field-input"
className="[&_.preview]:h-[350px] [&_pre]:h-[350px]!"
/>
It works with all form controls. Inputs, textareas, selects, checkboxes, radios, switches, sliders, you name it. Here's a full example:
<ComponentPreview
styleName="new-york-v4"
name="field-demo"
className="[&_.preview]:h-[850px] [&_pre]:h-[850px]!"
/>
Here are some checkbox fields:
<ComponentPreview
styleName="new-york-v4"
name="field-checkbox"
className="[&_.preview]:h-[500px] [&_pre]:h-[500px]!"
/>
You can group fields together using `FieldGroup` and `FieldSet`. Perfect for
multi-section forms.
```tsx showLineNumbers
<FieldSet>
<FieldLegend />
<FieldGroup>
<Field />
<Field />
</FieldGroup>
</FieldSet>
```
<ComponentPreview
styleName="new-york-v4"
name="field-fieldset"
className="[&_.preview]:h-[500px] [&_pre]:h-[500px]!"
/>
Making it responsive is easy. Use `orientation="responsive"` and it switches
between vertical and horizontal layouts based on container width. Done.
<ComponentPreview
styleName="new-york-v4"
name="field-responsive"
className="[&_.preview]:h-[600px] [&_pre]:h-[600px]!"
/>
Wait, here's more. Wrap your fields in `FieldLabel` to create a selectable field group. Really easy. And it looks great.
<ComponentPreview
styleName="new-york-v4"
name="field-choice-card"
className="[&_.preview]:h-[600px] [&_pre]:h-[600px]!"
/>
### Item
This one is a straightforward flex container that can house nearly any type of content.
I've built this so many times that I decided to create a component for it. Now I use it all the time. I use it to display lists of items, cards, and more.
```tsx
import {
Item,
ItemContent,
ItemDescription,
ItemMedia,
ItemTitle,
} from "@/components/ui/item"
```
Here's a basic item:
```tsx showLineNumbers
<Item>
<ItemMedia variant="icon">
<HomeIcon />
</ItemMedia>
<ItemContent>
<ItemTitle>Dashboard</ItemTitle>
<ItemDescription>Overview of your account and activity.</ItemDescription>
</ItemContent>
</Item>
```
<ComponentPreview
styleName="new-york-v4"
name="item-demo"
className="[&_.preview]:h-[300px] [&_.preview]:p-4 [&_pre]:h-[300px]!"
/>
You can add icons, avatars, or images to the item.
<ComponentPreview
styleName="new-york-v4"
name="item-icon"
className="[&_.preview]:h-[300px] [&_.preview]:p-4 [&_pre]:h-[300px]!"
/>
<ComponentPreview
styleName="new-york-v4"
name="item-avatar"
className="[&_.preview]:h-[300px] [&_.preview]:p-4 [&_pre]:h-[300px]!"
/>
And here's what a list of items looks like with `ItemGroup`:
<ComponentPreview
styleName="new-york-v4"
name="item-group"
className="[&_.preview]:h-[500px] [&_.preview]:p-4 [&_pre]:h-[500px]!"
/>
Need it as a link? Use the `asChild` prop:
```tsx showLineNumbers
<Item asChild>
<a href="/dashboard">
<ItemMedia variant="icon">
<HomeIcon />
</ItemMedia>
<ItemContent>
<ItemTitle>Dashboard</ItemTitle>
<ItemDescription>Overview of your account and activity.</ItemDescription>
</ItemContent>
</a>
</Item>
```
<ComponentPreview
styleName="new-york-v4"
name="item-link"
className="[&_.preview]:h-[400px] [&_.preview]:p-4 [&_pre]:h-[400px]!"
/>
### Empty
Okay last one: **Empty**. Use this to display empty states in your app.
```tsx
import {
Empty,
EmptyContent,
EmptyDescription,
EmptyMedia,
EmptyTitle,
} from "@/components/ui/empty"
```
Here's how you use it:
```tsx showLineNumbers
<Empty>
<EmptyMedia variant="icon">
<InboxIcon />
</EmptyMedia>
<EmptyTitle>No messages</EmptyTitle>
<EmptyDescription>You don't have any messages yet.</EmptyDescription>
<EmptyContent>
<Button>Send a message</Button>
</EmptyContent>
</Empty>
```
<ComponentPreview
styleName="new-york-v4"
name="empty-demo"
className="[&_.preview]:h-[400px] [&_.preview]:p-4 [&_pre]:h-[400px]!"
/>
You can use it with avatars:
<ComponentPreview
styleName="new-york-v4"
name="empty-avatar"
className="[&_.preview]:h-[400px] [&_pre]:h-[400px]!"
/>
Or with input groups for things like search results or email subscriptions:
<ComponentPreview
styleName="new-york-v4"
name="empty-input-group"
className="[&_.preview]:h-[450px] [&_pre]:h-[450px]!"
/>
That's it. Seven new components. Works with all your libraries. Ready for your projects.

View File

@@ -0,0 +1,11 @@
---
title: October 2025 - Registry Directory
description: A list of code registries you can browse and pull code and components from.
date: 2025-10-28
---
We just published the Registry Directory: a list of code registries you can browse and pull code and components from.
https://ui.shadcn.com/docs/directory
Built into the CLI. No config required.

View File

@@ -0,0 +1,46 @@
---
title: December 2025 - npx shadcn create
description: Customize everything. Pick your component library, icons, base color, theme, fonts and create your own version of shadcn/ui.
date: 2025-12-12
---
From the very first commit, the goal of shadcn/ui was to make it customizable.
The idea is to give you solid defaults, spacing, color tokens, animations, accessibility, and then let you take it from there. Tweak the code. Add new components. Change the colors. Build your own version.
But somewhere along the way, all apps started looking the same. I guess the defaults were a little _too_ good. My bad.
Today, we're changing that: **npx shadcn create**.
Customize Everything. Pick your component library, icons, base color, theme, fonts and create your own version of shadcn/ui.
We're starting with **5 new visual styles**, designed to help your UI actually feel like _your_ UI.
- **Vega** – The classic shadcn/ui look.
- **Nova** – Reduced padding and margins for compact layouts.
- **Maia** – Soft and rounded, with generous spacing.
- **Lyra** – Boxy and sharp. Pairs well with mono fonts.
- **Mira** – Compact. Made for dense interfaces.
**This goes beyond theming**.
Your config doesn't just change colors, it rewrites the component code to match your setup. Fonts, spacing, structure, even the libraries you use, everything adapts to your preferences.
The new CLI takes care of it all.
Start with a component library. Choose between Radix or Base UI.
We rebuilt every component for Base UI, keeping the same abstraction.
They are fully compatible with your existing components, even those pulled from remote registries.
When you pull down components, we auto-detect your library and apply the right transformations.
**It's time to build something that doesn't look like everything else.**
Now available for Next.js, Vite, TanStack Start and v0.
<Button asChild>
<Link href="/create" className="mt-6 no-underline!">
Get Started
</Link>
</Button>

View File

@@ -0,0 +1,45 @@
---
title: January 2026 - Base UI Documentation
description: Full documentation for Base UI components.
date: 2026-01-20
---
We've shipped full documentation for Base UI components.
<div className="mt-6 flex w-full items-center justify-center rounded-lg border bg-muted/50 py-32">
<svg width="17" height="24" viewBox="0 0 17 24" className="size-12">
<path
fill="currentColor"
d="M9.5001 7.01537C9.2245 6.99837 9 7.22385 9 7.49999V23C13.4183 23 17 19.4183 17 15C17 10.7497 13.6854 7.27351 9.5001 7.01537Z"
/>
<path
fill="currentColor"
d="M8 9.8V12V23C3.58172 23 0 19.0601 0 14.2V12V1C4.41828 1 8 4.93989 8 9.8Z"
/>
</svg>
</div>
When we launched `npx shadcn create` in December, we introduced the ability to choose between Radix and Base UI as your component library. Today, we're following up with complete documentation for all Base UI components.
### What's New
- **Full Base UI docs** - Every component now has dedicated documentation for Base UI, covering usage, props, and examples.
- **Rebuilt examples** - All component examples have been rebuilt for both Radix and Base UI. Switch between them to see the implementation differences.
- **Side-by-side comparison** - The docs make it easy to compare how components work across both libraries.
### Same Abstraction, Different Primitives
The goal remains the same: give you a consistent API regardless of which primitive library you choose. The components look and behave the same way. Only the underlying implementation changes.
```tsx
// Works the same whether you're using Radix or Base UI.
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog"
```
If you're starting a new project, run `npx shadcn create` and pick your preferred library. The CLI handles the rest.
<Button asChild size="sm">
<Link href="/create" className="mt-6 no-underline!">
Try shadcn/create
</Link>
</Button>

View File

@@ -0,0 +1,69 @@
---
title: January 2026 - Inline Start and End Styles
description: We've updated the styles for Base UI components to support inline-start and inline-end side values.
date: 2026-01-23
---
We've updated the styles for Base UI components to support `inline-start` and `inline-end` side values. The following components now support these values:
- Tooltip
- Popover
- Combobox
- Context Menu
- Dropdown Menu
- Hover Card
- Menubar
- Select
### What Changed
We added new Tailwind classes to handle the logical side values:
```diff
<PopoverPrimitive.Popup
className={cn(
"... data-[side=bottom]:slide-in-from-top-2
data-[side=left]:slide-in-from-right-2
data-[side=right]:slide-in-from-left-2
data-[side=top]:slide-in-from-bottom-2
+ data-[side=inline-start]:slide-in-from-right-2
+ data-[side=inline-end]:slide-in-from-left-2 ...",
className
)}
/>
```
### Usage
```tsx
<Popover>
<PopoverTrigger>Open</PopoverTrigger>
<PopoverContent side="inline-start">
{/* Opens on the left in LTR, right in RTL */}
</PopoverContent>
</Popover>
```
### LLM Prompt
Ask your LLM to update your components by running the following prompt:
```txt showLineNumbers
Add inline-start and inline-end support to my shadcn/ui components. Add the following Tailwind classes to each component:
| File | Component | Add Classes |
|------|-----------|-------------|
| tooltip.tsx | TooltipContent | `data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2` |
| tooltip.tsx | TooltipArrow | `data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2
data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2` |
| popover.tsx | PopoverContent | `data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2` |
| hover-card.tsx | HoverCardContent | `data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2` |
| select.tsx | SelectContent | `data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2
data-[align-trigger=true]:animate-none` and add `data-align-trigger={alignItemWithTrigger}` attribute |
| combobox.tsx | ComboboxContent | `data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2` |
| dropdown-menu.tsx | DropdownMenuContent | `data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2` |
| context-menu.tsx | ContextMenuContent | `data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2` |
| menubar.tsx | MenubarContent | `data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2` |
Add these classes next to the existing `data-[side=top]`, `data-[side=bottom]`, `data-[side=left]`, `data-[side=right]` classes.
```

View File

@@ -0,0 +1,82 @@
---
title: January 2026 - RTL Support
description: The shadcn CLI now supports RTL (right-to-left) layouts by automatically converting physical CSS classes to logical equivalents.
date: 2026-01-28
---
shadcn/ui now has first-class support for right-to-left (RTL) layouts. Your components automatically adapt for languages like Arabic, Hebrew, and Persian.
**This works with the [shadcn/ui components](/docs/components) as well as any component distributed on the shadcn registry.**
<ComponentPreview
styleName="base-nova"
name="alert-rtl"
direction="rtl"
previewClassName="h-auto sm:h-72 p-6"
/>
### Our approach to RTL
Traditionally, component libraries that support RTL ship with logical classes baked in. This means everyone has to work with classes like `ms-4` and `start-2`, even if they're only building for LTR layouts.
We took a different approach. The shadcn CLI transforms classes at install time, so you only see logical classes when you actually need them. If you're not building for RTL, you work with familiar classes like `ml-4` and `left-2`. When you enable RTL, the CLI handles the conversion for you.
**You don't have to learn RTL until you need it.**
### How it works
When you add components with `rtl: true` set in your `components.json`, the CLI automatically converts physical CSS classes like `ml-4` and `text-left` to their logical equivalents like `ms-4` and `text-start`.
- Physical positioning classes like `left-*` and `right-*` become `start-*` and `end-*`.
- Margin and padding classes like `ml-*` and `pr-*` become `ms-*` and `pe-*`.
- Text alignment classes like `text-left` become `text-start`.
- Directional props are updated to use logical values.
- Supported icons are automatically flipped using `rtl:rotate-180`.
- Animations like `slide-in-from-left` become `slide-in-from-start`.
### RTL examples for every component
We've added RTL examples for every component. You'll find live previews and code on each [component page](/docs/components).
<ComponentPreview
styleName="base-nova"
name="card-rtl"
direction="rtl"
previewClassName="h-auto"
/>
### CLI updates
**New projects**: Use the `--rtl` flag with `init` or `create` to enable RTL from the start.
```bash
npx shadcn@latest init --rtl
```
```bash
npx shadcn@latest create --rtl
```
**Existing projects**: Migrate your components with the `migrate rtl` command.
```bash
npx shadcn@latest migrate rtl
```
This transforms all components in your `ui` directory to use logical classes. You can also pass a specific path or glob pattern.
## Try it out
Click the link below to open a Next.js project with RTL support in v0.
[![Open in v0](https://v0.app/chat-static/button.svg)](https://v0.app/chat/api/open?url=https://github.com/shadcn-ui/next-template-rtl)
### Links
- [RTL Documentation](/docs/rtl)
- [Font Recommendations](/docs/rtl#font-recommendations)
- [Animations](/docs/rtl#animations)
- [Migrating Existing Components](/docs/rtl#migrating-existing-components)
- [Next.js Setup](/docs/rtl/next)
- [Vite Setup](/docs/rtl/vite)
- [TanStack Start Setup](/docs/rtl/start)

View File

@@ -0,0 +1,18 @@
---
title: February 2026 - Blocks for Radix and Base UI
description: All blocks are now available for both Radix and Base UI.
date: 2026-02-06
---
All [blocks](/blocks) are now available for both Radix and Base UI.
- **All blocks for both libraries** - Every block, including login, signup, sidebar and dashboard blocks, is now available in both Radix and Base UI variants.
- **Same CLI workflow** - Run `npx shadcn add` and the CLI will pull the correct block variant based on your project configuration.
If you've already set up your project with `npx shadcn create`, blocks will automatically use your chosen library. No additional configuration needed.
```bash
npx shadcn@latest add login-01
```
Browse the full collection on the [blocks](/blocks) page.

View File

@@ -0,0 +1,38 @@
---
title: February 2026 - Unified Radix UI Package
description: The new-york style now uses the unified radix-ui package.
date: 2026-02-02
---
The `new-york` style now uses the unified `radix-ui` package instead of individual `@radix-ui/react-*` packages.
### What's Changed
When you add components using the `new-york` style, they will now import from `radix-ui` instead of separate packages:
```diff title="components/ui/dialog.tsx"
- import * as DialogPrimitive from "@radix-ui/react-dialog"
+ import { Dialog as DialogPrimitive } from "radix-ui"
```
This results in a cleaner `package.json` with a single `radix-ui` dependency instead of multiple `@radix-ui/react-*` packages.
### Migrating Existing Projects
If you have an existing project using the `new-york` style, you can migrate to the new `radix-ui` package using the migrate command:
```bash
npx shadcn@latest migrate radix
```
This will update all imports in your UI components and add `radix-ui` to your dependencies.
To migrate components outside of your `ui` directory, use the `path` argument:
```bash
npx shadcn@latest migrate radix src/components/custom
```
Once complete, you can remove any unused `@radix-ui/react-*` packages from your `package.json`.
See the [migrate radix documentation](/docs/cli#migrate-radix) for more details.

View File

@@ -0,0 +1,153 @@
---
title: March 2026 - shadcn/cli v4
description: More capable, easier to use. Built for you and your coding agents. Skills, presets, dry run, new templates, monorepo and more.
date: 2026-03-06
---
We're releasing version 4 of shadcn/cli. More capable, easier to use. Built for you and your coding agents. Here's everything new.
## shadcn/skills
shadcn/skills gives coding agents the context they need to work with your components and registry correctly. It covers both Radix and Base UI primitives, updated APIs, component patterns and registry workflows. The skill also knows how to use the shadcn CLI, when to invoke it and which flags to pass. Agents make fewer mistakes and produce code that actually matches your design system.
You can ask your agent things like:
- "create a new vite monorepo"
- "find me a hero from tailark, add it to the homepage, animate the text using an animation from react-bits"
- "install and configure a sign in page from @clerk"
```bash
npx skills add shadcn/ui
```
## Introducing --preset
A preset packs your entire design system config into a short code. Colors, theme, icon library, fonts, radius. One string, everything included.
Build your preset on [shadcn/create](/create), preview it live and grab the code when you're ready.
```bash
npx shadcn@latest init --preset a1Dg5eFl
```
Use it to scaffold projects from custom config, share with your team or publish in your registry. Drop it in prompts so your agent knows where to start. Use it across Claude, Codex, v0, Replit. Take your preset with you.
## Switching presets
When you're working on a new app, it can take a few tries to find something you like so we've made switching presets really easy. Run `init --preset` in your app, and the CLI will take care of reconfiguring everything, including your components.
```bash
npx shadcn@latest init --preset ad3qkJ7
```
## Skills + Presets
Your agent knows how to use presets. Scaffold a project, switch design systems, try something new.
- "create a new next app using --preset adtk27v"
- "let's try --preset adtk27v"
## New shadcn/create
To help you build custom presets, we rebuilt [shadcn/create](/create). It now includes a library of UI components you can use to preview your presets. See how your colors, fonts and radius apply to real components before you start building.
## New --dry-run, --diff, and --view flags
Inspect what a registry will add to your project before anything gets written. Review the payload yourself or pipe it to your coding agent for a second look.
```bash
npx shadcn@latest add button --dry-run
npx shadcn@latest add button --diff
npx shadcn@latest add button --view
```
## Updating primitives
You can use the `--diff` flag to check for registry updates. Or ask your agent: "check for updates from @shadcn and merge with my local changes".
```bash
npx shadcn@latest add button --diff
```
## shadcn init --template
`shadcn init` now scaffolds full project templates for Next.js, Vite, Laravel, React Router, Astro and TanStack Start. Dark mode included for Next.js and Vite.
```bash
npx shadcn@latest init
Select a template › - Use arrow-keys. Return to submit.
❯ Next.js
Vite
TanStack Start
React Router
Astro
Laravel
```
Use `--monorepo` to set up a monorepo.
```bash
npx shadcn@latest init -t next --monorepo
```
## shadcn init --base
Pick your primitives. Use `--base` to start a project with Radix or Base UI.
```bash
npx shadcn@latest init --base radix
```
## shadcn info
The `info` command now shows the full picture: framework, version, CSS vars, which components are installed, and where to find docs and examples for every component. Great for giving coding agents the context they need to work with your project.
```bash
npx shadcn@latest info
```
## shadcn docs
Get docs, code and examples for any UI component right from the CLI. Gives your coding agent the context to use your primitives correctly.
```bash
npx shadcn@latest docs combobox
combobox
- docs https://ui.shadcn.com/docs/components/radix/combobox
- examples https://ui.shadcn.com/code/apps/v4/registry/bases/radix/examples/combobox-example.tsx
- api https://base-ui.com/react/components/combobox
```
## registry:base and registry:font
Registries can now distribute an entire design system as a single payload using `registry:base`. Components, dependencies, CSS vars, fonts, config. One install, everything set up.
Fonts are now a first-class registry type. Install and configure them the same way you install components.
```json title="font-inter.json" showLineNumbers
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "font-inter",
"type": "registry:font",
"font": {
"family": "'Inter Variable', sans-serif",
"provider": "google",
"import": "Inter",
"variable": "--font-sans",
"subsets": ["latin"]
}
}
```
```bash
npx shadcn@latest add font-inter
```
## Links
- [shadcn/skills](/skills)
- [shadcn/create](/create)
- [shadcn/cli](/cli)
- [shadcn/registry](/docs/registry)

View File

@@ -0,0 +1,37 @@
---
title: March 2026 - Introducing Luma
description: Rounded geometry. Soft elevation. Breathable layouts. Inspired by macOS Tahoe, minus the glass.
date: 2026-03-31
---
Introducing Luma, a new shadcn/ui style. Rounded geometry. Soft elevation. Breathable layouts. Inspired by macOS Tahoe, minus the glass.
<a href="/create">
<Image
src="/images/luma-light.png"
width="2160"
height="1832"
alt="Luma style preview"
className="mt-6 w-full overflow-hidden rounded-2xl border dark:hidden"
/>
<Image
src="/images/luma-dark.png"
width="2160"
height="1832"
alt="Luma style preview"
className="mt-6 hidden w-full overflow-hidden rounded-2xl border shadow-sm dark:block"
/>
<span className="sr-only">Try Luma in shadcn/create</span>
</a>
Luma is a new foundation for your next app. It gives components softer surfaces, more open spacing, and a calmer visual rhythm while keeping the same shadcn/ui workflow.
Like the other new styles, Luma goes beyond theming. It changes the geometry, spacing, and feel of the components so your app starts from a different visual baseline.
Available now in [shadcn/create](/create) for both Radix and Base UI.
<Button asChild size="sm">
<Link href="/create?preset=b2D0wqNxT" className="mt-6 no-underline!">
Try Luma
</Link>
</Button>

View File

@@ -0,0 +1,31 @@
---
title: April 2026 - Component Composition
description: Composition sections across component pages—structured trees that help you and your agents build correct UI.
date: 2026-04-06
---
We've added **Composition** sections across the component docs so you can see the correct structure at a glance: what wraps what, which subcomponents belong together, and how to avoid invalid nesting.
```text
Card
├── CardHeader
│ ├── CardTitle
│ ├── CardDescription
│ └── CardAction
├── CardContent
└── CardFooter
```
## Why we added this
We've found that **LLMs and coding agents compose elements more reliably** when they can see the full structure: fewer missing wrappers, fewer wrong hierarchies, better matches to the examples.
### Bring docs into your agent
You or your LLM can pull the same component documentation, including composition, usage, and examples, into context from the CLI:
```bash
npx shadcn@latest docs card
```
If you're using the [shadcn/skills](/docs/skills), this is done automatically for you.

View File

@@ -0,0 +1,35 @@
---
title: April 2026 - Partial Preset Apply
description: Apply only the theme or fonts from a preset while keeping your existing components.
date: 2026-04-22
---
You can now selectively apply a preset.
Say someone shares a preset with you and you already have your own components, but you like the theme or the fonts. Now you can apply just that.
Keep your components. Apply only what you want.
```bash
# Apply the full preset.
npx shadcn@latest apply --preset b2D0vQ7G4
# Apply only the theme.
npx shadcn@latest apply --preset b2D0vQ7G4 --only theme
# Apply only the fonts.
npx shadcn@latest apply --preset b2D0vQ7G4 --only font
# Apply theme and fonts.
npx shadcn@latest apply --preset b2D0vQ7G4 --only theme,font
```
The default behavior is unchanged. Running `shadcn apply --preset <preset>` still applies the full preset.
Partial preset apply currently supports `theme` and `font`.
<Button asChild size="sm">
<Link href="/create" className="mt-6 no-underline!">
Try a Preset
</Link>
</Button>

View File

@@ -0,0 +1,24 @@
---
title: April 2026 - Pointer Cursor
description: Add cursor pointer behavior for buttons during project setup.
date: 2026-04-25
---
You can now enable `cursor: pointer` for buttons when initializing a project.
```bash
npx shadcn@latest init --pointer
```
This adds the following CSS to your global CSS file:
```css title="globals.css"
@layer base {
button:not(:disabled),
[role="button"]:not(:disabled) {
cursor: pointer;
}
}
```
The `--pointer` option is not part of preset codes. It is applied as a project setup option, similar to `--rtl`.

View File

@@ -0,0 +1,93 @@
---
title: April 2026 - shadcn preset
description: Decode, share, open, and resolve preset codes from the shadcn CLI.
date: 2026-04-28
---
We added `shadcn preset` commands for working with preset codes.
## Decode a preset
You can decode a preset code to see exactly what it contains:
```bash
npx shadcn@latest preset decode b5owWMfJ8l
```
```txt
Preset
code b5owWMfJ8l
version b
style mira
baseColor mauve
theme mauve
chartColor amber
iconLibrary hugeicons
font inter
fontHeading oxanium
radius large
menuAccent subtle
menuColor inverted-translucent
url https://ui.shadcn.com/create?preset=b5owWMfJ8l
```
## Resolve from a project
Use `preset resolve` in an existing project to see the preset that matches your current configuration.
```bash
npx shadcn@latest preset resolve
```
```txt
Preset
code b5Kc6P0Vc
version b
style luma
baseColor olive
theme lime
chartColor sky
iconLibrary hugeicons
font geist
fontHeading inherit
radius default
menuAccent subtle
menuColor default
url https://ui.shadcn.com/create?preset=b5Kc6P0Vc
```
It works with monorepos too:
```bash
npx shadcn@latest preset resolve -c apps/web
```
## Share or open
Use `preset url` when you need a shareable link:
```bash
npx shadcn@latest preset url b5owWMfJ8l
```
```txt
https://ui.shadcn.com/create?preset=b5owWMfJ8l
```
Use `preset open` to open the preset on shadcn/create for customization:
```bash
npx shadcn@latest preset open b5owWMfJ8l
```
```txt
Opening https://ui.shadcn.com/create?preset=b5owWMfJ8l in your browser.
```
This makes presets easier to inspect, share, and hand off to coding agents without manually decoding codes or building URLs.
<Button asChild size="sm">
<Link href="/create" className="mt-6 no-underline!">
Try a Preset
</Link>
</Button>

View File

@@ -0,0 +1,37 @@
---
title: April 2026 - Introducing Sera
description: Minimal. Editorial. Typographic. Underline Controls and Uppercase Headings. Shaped by Print Design Principles.
date: 2026-04-16
---
Introducing Sera, a new shadcn/ui style. Minimal. Editorial. Typographic. Underline Controls and Uppercase Headings. Shaped by Print Design Principles.
<a href="/create?preset=b4xFeBLg4O">
<Image
src="/images/sera-01-light.png"
width="2160"
height="1832"
alt="Sera style preview"
className="mt-6 w-full overflow-hidden rounded-2xl border dark:hidden"
/>
<Image
src="/images/sera-01-dark.png"
width="2160"
height="1832"
alt="Sera style preview"
className="mt-6 hidden w-full overflow-hidden rounded-2xl border shadow-sm dark:block"
/>
<span className="sr-only">Try Sera in shadcn/create</span>
</a>
Sera is a typography-first style built on print design principles. It pairs serif headings with sans-serif body text, uses square corners, uppercase tracking, and underlined controls to create an editorial feel for your app.
Like the other new styles, Sera goes beyond theming. It changes the geometry, spacing, and feel of the components so your app starts from a different visual baseline.
Available now in [shadcn/create](/create) for both Radix and Base UI.
<Button asChild size="sm">
<Link href="/create?preset=b4xFeBLg4O" className="mt-6 no-underline!">
Try Sera
</Link>
</Button>

View File

@@ -0,0 +1,21 @@
---
title: April 2026 - shadcn apply
description: Switch presets in existing projects without starting over.
date: 2026-04-08
---
We added `shadcn apply` so you can switch presets in an existing project without starting over.
When you run `npx shadcn@latest apply` in an existing project, we apply a new preset, reinstall your existing components, and update your theme, colors, CSS variables, fonts, and icons.
```bash
npx shadcn@latest apply --preset b2D0vQ7G4
```
The CLI keeps the current base and RTL settings from your existing project, even when the preset URL was generated with different values.
<Button asChild size="sm">
<Link href="/create" className="mt-6 no-underline!">
Try a Preset
</Link>
</Button>

View File

@@ -0,0 +1,63 @@
---
title: May 2026 - Package Imports and Target Aliases
description: Configure shadcn/ui with package.json imports and portable registry target aliases.
date: 2026-05-05
---
We've added support for package imports and aliases in `files.target` in `shadcn@4.7.0`.
## Package imports
The `shadcn` CLI now supports `package.json#imports` for installing components,
rewriting imports, and resolving third-party registries. You can use private
`#...` import aliases from your `package.json` instead of relying only on
`compilerOptions.paths` in `tsconfig.json`.
```json title="package.json" showLineNumbers
{
"imports": {
"#components/*": "./src/components/*.tsx",
"#lib/*": "./src/lib/*.ts",
"#hooks/*": "./src/hooks/*.ts"
}
}
```
Then use the same roots in `components.json`:
```json title="components.json" showLineNumbers
{
"aliases": {
"components": "#components",
"ui": "#components/ui",
"lib": "#lib",
"hooks": "#hooks",
"utils": "#lib/utils"
}
}
```
This also works in monorepos where app-local files use package imports and
shared UI files are imported from workspace package exports.
See the [package imports guide](/docs/package-imports) for setup details.
## Target aliases
Registry items can now use target aliases in `files[].target` to install files
under the user's configured shadcn directories. For example, the following registry item will install the `prompt-input.tsx` file under the `ui/ai` directory.
```json title="example.json" showLineNumbers
{
"files": [
{
"path": "registry/default/ai/prompt-input.tsx",
"type": "registry:ui",
"target": "@ui/ai/prompt-input.tsx"
}
]
}
```
See the [registry examples](/docs/registry/examples#target-placeholders) for
more details.

View File

@@ -0,0 +1,120 @@
---
title: May 2026 - Registry Include and Validate
description: Organize and validate source registries.
date: 2026-05-20
---
This release adds two updates for registry authors:
- `include` for composing large source registries from multiple `registry.json`
files.
- `shadcn registry validate` for checking source registries before publishing.
This makes it easier to maintain source and dynamic registries without keeping
one large `registry.json` file by hand.
Registry authors can now organize a large source registry across multiple
`registry.json` files and compose them with `shadcn build`.
```txt /registry.json/
registry.json
components
└── ui
├── button.tsx
├── input.tsx
└── registry.json
hooks
├── registry.json
├── use-media-query.ts
└── use-toggle.ts
```
{/* prettier-ignore */}
```json title="registry.json" showLineNumbers {6-7}
{
"$schema": "https://ui.shadcn.com/schema/registry.json",
"name": "acme",
"homepage": "https://acme.com",
"include": [
"components/ui/registry.json",
"hooks/registry.json"
]
}
```
Included `registry.json` files are valid registry files for composition and may
omit `name` and `homepage`. Only the root `registry.json` must define the
registry metadata.
```json title="components/ui/registry.json" showLineNumbers
{
"$schema": "https://ui.shadcn.com/schema/registry.json",
"items": [
{
"name": "button",
"type": "registry:ui",
"files": [
{
"path": "button.tsx",
"type": "registry:ui"
}
]
}
]
}
```
## Build output
`shadcn build` resolves included registries and writes a flattened
`registry.json` without `include`. Item file paths are preserved from the root
registry, so a file declared in `components/ui/registry.json` is written as
`components/ui/button.tsx` in the built registry item.
## Validate your registry
You can now validate a source registry before publishing or serving it.
```bash
npx shadcn registry validate
```
Validation runs against the source registry files directly. You do not need to
run `shadcn build` first.
The command checks the root `registry.json`, included registry files, item
schema errors, duplicate item names, include rules, and local item file paths.
Validation reports all actionable errors it can find in one run.
## Registry loaders
The `shadcn/registry` package also exports `loadRegistry` and
`loadRegistryItem` for dynamic registry routes.
```ts title="app/r/registry.json/route.ts" showLineNumbers
import { loadRegistry } from "shadcn/registry"
export async function GET() {
const registry = await loadRegistry()
return Response.json(registry)
}
```
```ts title="app/r/[name].json/route.ts" showLineNumbers
import { loadRegistryItem } from "shadcn/registry"
export async function GET(
_: Request,
{ params }: { params: Promise<{ name: string }> }
) {
const { name } = await params
const item = await loadRegistryItem(name)
return Response.json(item)
}
```
See the [registry.json documentation](/docs/registry/registry-json#include) and
[getting started guide](/docs/registry/getting-started#structure-your-registry)
for more details.

View File

@@ -0,0 +1,45 @@
---
title: May 2026 - Introducing Rhea
description: A more compact Luma. Smaller spacing. Denser surfaces. Built for focused product interfaces.
date: 2026-05-26
---
Introducing Rhea, a new shadcn/ui style. A more compact Luma. Smaller spacing. Denser surfaces. Built for focused product interfaces.
<a href="/create?preset=b27GcrRo">
<Image
src="/images/rhea-light.png"
width="3840"
height="2160"
alt="Rhea style preview"
className="mt-6 w-full overflow-hidden rounded-2xl border dark:hidden"
/>
<Image
src="/images/rhea-dark.png"
width="3840"
height="2160"
alt="Rhea style preview"
className="mt-6 hidden w-full overflow-hidden rounded-2xl border shadow-sm dark:block"
/>
<span className="sr-only">Try Rhea in shadcn/create</span>
</a>
Rhea started from a simple request we've heard a lot: Luma, but more compact. We looked at how people were using the new styles and what they were asking for, and the pattern was clear. A lot of teams wanted the softness and shape of Luma with tighter spacing, smaller controls, and more information density.
Rhea keeps the same rounded foundation, but makes it more compact for product interfaces where space matters. Buttons, inputs, menus, cards, and lists all sit a little tighter so the UI can carry more without feeling crowded.
## Why a new style?
We considered making this a spacing tweak for Luma, but `--spacing` is a multiplier. Changing it would change what familiar utilities mean across your app. `p-2`, `w-4`, and `m-16` would no longer mean the same size.
That tradeoff felt wrong. Compactness should not force you to relearn Tailwind's spacing scale or wonder whether a utility means something different in one style than another.
So Rhea is a new style instead. It lets us adjust component sizes, gaps, and density directly while keeping the underlying utility scale predictable.
Available now in [shadcn/create](/create) for both Radix and Base UI.
<Button asChild size="sm">
<Link href="/create?preset=b27GcrRo" className="mt-6 no-underline!">
Try Rhea
</Link>
</Button>

View File

@@ -0,0 +1,61 @@
---
title: May 2026 - shadcn eject
description: Inline shadcn/tailwind.css and remove the shadcn dependency.
date: 2026-05-31
---
When we added support for both Radix and Base UI, we needed a place for shared Tailwind utilities that both libraries depend on, e.g. custom variants like `data-open:` and `data-closed:` and utilities like `no-scrollbar`.
We also ran into a few bugs while working on RTL support that were easier to fix in one shared place rather than duplicating across every component.
So we created `shadcn/tailwind.css`. When you run `init`, it adds `@import "shadcn/tailwind.css"` to your global CSS file. It works just like other CSS imports such as `tw-animate-css`: a small dependency that is tree-shaken in production and resolved at build time.
If you prefer not to depend on the `shadcn` package for that CSS, we've added the `shadcn eject` command. It inlines `shadcn/tailwind.css` into your global CSS file and removes the `shadcn` dependency from your project.
```bash
npx shadcn@latest eject
```
**Before**
```css
@import "tailwindcss";
@import "tw-animate-css";
@import "shadcn/tailwind.css";
```
**After**
```css
@import "tailwindcss";
@import "tw-animate-css";
/* ejected from shadcn@4.8.3 */
@theme inline {
@keyframes accordion-down {
from {
height: 0;
}
to {
height: var(
--radix-accordion-content-height,
var(--accordion-panel-height, auto)
);
}
}
}
@custom-variant data-open {
&:where([data-state="open"]),
&:where([data-open]:not([data-open="false"])) {
@slot;
}
}
```
In a monorepo, run the command from the workspace that contains your `components.json` and global CSS file:
```bash
npx shadcn@latest eject -c packages/ui
```
See the [CLI documentation](/docs/cli#eject) for more details.

View File

@@ -0,0 +1,117 @@
---
title: June 2026 - Components for Chat Interfaces
description: MessageScroller, Message, Bubble, Attachment, and Marker. Components for building chat interfaces.
date: 2026-06-26
---
<ComponentPreview
styleName="radix-rhea"
name="message-scroller-demo"
className="rounded-[34px] sm:rounded-4xl"
previewClassName="h-auto theme-blue bg-surface dark:bg-background p-4 min-[480px]:p-8 min-[560px]:p-10 sm:px-10 sm:py-16"
/>
Today, we’re releasing a new set of components for building chat interfaces:
[**MessageScroller**](/docs/components/message-scroller),
[**Message**](/docs/components/message), [**Bubble**](/docs/components/bubble),
[**Attachment**](/docs/components/attachment), and
[**Marker**](/docs/components/marker).
This is the first phase of the chat components work. We’re taking it one piece at a time, reimagining the abstraction behind each part, and shipping them as shadcn/ui components you can copy, compose, and adapt to your product.
We are starting with the conversation layer: scrolling, message rows, bubbles, attachments, and markers.
We asked ourselves: what makes a great streaming chat experience? Then we abstracted the core rules into a set of primitives: `MessageScroller`.
```bash
npx shadcn@latest add message-scroller message bubble attachment marker
```
## MessageScroller
`MessageScroller` is the scroll container for a conversation. It handles the
parts that are easy to get wrong: anchored turns, streamed replies, saved thread
restore, prepended history, jump-to-message, scroll controls, and visibility
tracking.
`MessageScroller` owns that behavior without owning your messages, AI state,
transport, persistence, or model state. You bring the content renderer.
The `MessageScroller` is also available as an unstyled headless component in `@shadcn/react`.
## Message, Bubble, Attachment, and Marker
The rest of the components cover the everyday pieces you need around the
scroller.
- `Message` lays out a row in the conversation with avatar, alignment, header,
content, footer, and grouped messages.
- `Bubble` renders the message surface, with variants, alignment, reactions,
links, buttons, and collapsible content.
- `Attachment` renders files and images with media, metadata, upload state,
actions, and a full-card trigger that keeps actions separately clickable.
- `Marker` renders status updates, system notes, bordered rows, and labeled
separators for things like streaming state, tool activity, and date breaks.
They are intentionally small. Compose them together for AI chats, support
inboxes, team threads, group chats, and product-specific conversations.
## scroll-fade and shimmer
We also added two new CSS utilities for the details that make chat interfaces
feel better.
[`scroll-fade`](/docs/utils/scroll-fade) adds scroll-aware edge fades to scroll
containers. Use it on `MessageScroller`, `ScrollArea`, attachment rows, and any
long list where you want to hint at more content without adding overlays or
scroll listeners.
<ComponentPreview
styleName="radix-rhea"
name="scroll-fade-demo"
previewClassName="h-auto"
/>
[`shimmer`](/docs/utils/shimmer) adds a text shimmer for live status. Use it
for things like "Thinking…", "Generating response…", running tools, and
streaming markers.
<ComponentPreview styleName="radix-rhea" name="shimmer-demo" />
Both utilities ship with `shadcn/tailwind.css`, so projects initialized with
`npx shadcn@latest init` already have them.
## @shadcn/react
We also created `@shadcn/react`, a new package for unstyled, headless React
components.
The first primitive is `@shadcn/react/message-scroller`. The registry component
wraps it with shadcn/ui styles, but the scroll behavior lives in the package:
anchoring, auto-follow, prepend preservation, scroll commands, and visibility.
This lets us ship behavior without locking it to a visual style. You still get
copy-and-paste components that match your project, and the hard interaction
logic stays tested in one place.
Available now for Radix and Base UI.
## AI Elements
This does not replace [AI Elements](https://ai-sdk.dev/elements/overview). You
can keep using AI Elements for AI interface components and patterns. This
release is about bringing the core pieces of chat into shadcn/ui, one component
at a time.
If you are already using a component from AI Elements, you do not need to
rewrite your app. Keep what works. Try the shadcn/ui version when you want the
newer abstraction, the updated styling, or support across Radix and Base UI.
The goal is to make these pieces easy to adopt independently. Replace one part,
compose it with what you already have, and keep building.
<Button asChild size="sm">
<Link href="/docs/components" className="mt-6 no-underline!">
View Components
</Link>
</Button>

View File

@@ -0,0 +1,98 @@
---
title: June 2026 - GitHub Registries
description: Turn any public GitHub repository into a shadcn registry.
date: 2026-06-01
---
**You can now turn any public GitHub repository into a registry.**
Add a `registry.json` file at the root of the repository, define the items you
want to distribute, and users can install them directly from GitHub with the
`shadcn` CLI.
```bash
npx shadcn@latest add <username>/<repo>/<item>
```
For example, to install the `project-conventions` item from the `acme/toolkit` repository:
```bash
npx shadcn@latest add acme/toolkit/project-conventions
```
GitHub registries are source registries. You do not need to run `shadcn build`,
publish generated item JSON files or set up a registry server. The CLI reads the
root `registry.json`, resolves `include` entries, finds the requested item and
installs the files declared by that item.
## Distribute anything
Registry items are not limited to components. A GitHub registry can distribute
components, hooks, utilities, design tokens, feature kits, project conventions,
agent instructions, testing setup, CI workflows, release workflows, templates,
codemods, migration kits and other project files.
For example, a repository can expose a `project-conventions` item that installs
shared docs, editor settings and agent instructions:
```json title="registry.json" showLineNumbers
{
"$schema": "https://ui.shadcn.com/schema/registry.json",
"name": "acme-toolkit",
"homepage": "https://github.com/acme/toolkit",
"items": [
{
"name": "project-conventions",
"type": "registry:item",
"files": [
{
"path": "AGENTS.md",
"type": "registry:file",
"target": "~/AGENTS.md"
},
{
"path": ".editorconfig",
"type": "registry:file",
"target": "~/.editorconfig"
},
{
"path": "docs/conventions.md",
"type": "registry:file",
"target": "~/docs/conventions.md"
}
]
}
]
}
```
## Commands
GitHub registry addresses work with the same commands as other registry
addresses.
List items from a GitHub registry:
```bash
npx shadcn@latest list acme/toolkit
```
Search items:
```bash
npx shadcn@latest search acme/toolkit --query conventions
```
View an item:
```bash
npx shadcn@latest view acme/toolkit/project-conventions
```
Install an item:
```bash
npx shadcn@latest add acme/toolkit/project-conventions
```
See the [GitHub Registries](/docs/registry/github) docs for the full guide.

View File

@@ -0,0 +1,125 @@
---
title: July 2026 - Base UI as the Default
description: New projects now use Base UI by default. Radix is still fully supported.
date: 2026-07-02
---
Starting today, **Base UI is the default component library in shadcn/ui**.
<div className="mt-6 flex w-full items-center justify-center rounded-2xl bg-muted/50 py-32 text-foreground ring ring-border dark:bg-muted">
<svg width="17" height="24" viewBox="0 0 17 24" className="size-16">
<path
fill="currentColor"
d="M9.5001 7.01537C9.2245 6.99837 9 7.22385 9 7.49999V23C13.4183 23 17 19.4183 17 15C17 10.7497 13.6854 7.27351 9.5001 7.01537Z"
/>
<path
fill="currentColor"
d="M8 9.8V12V23C3.58172 23 0 19.0601 0 14.2V12V1C4.41828 1 8 4.93989 8 9.8Z"
/>
</svg>
</div>
First, a bit of history. When shadcn/ui launched in January 2023, it was built on Radix. At the time, nothing else came close. Unstyled headless components, great APIs, great accessibility, battle-tested in millions of apps.
Fast forward a few years and the same folks who built Radix are building something new: [Base UI](https://www.base-ui.com). They've done it once. Now they get to do it again, with everything they learned the first time.
Last year, Base UI tagged a beta and a lot of you asked if we are going to replace Radix with it. I said "the worst thing you can do for your production app is switch component libraries". I meant it, and it still holds. So instead of switching, we did the shadcn thing: we rebuilt every component for Base UI, kept the same abstraction, and let you choose. December brought `npx shadcn create` with both libraries. January brought full Base UI docs.
Then we watched what you did with it.
---
## Why Now
- **Base UI is stable.** It's at 1.6.0 with 6M+ weekly downloads.
- **It keeps getting better.** The team ships new and useful components regularly.
- **We use it.** Every new project we've started runs on Base UI.
- **You use it.** Projects created on shadcn/create now pick Base UI over Radix 2 to 1.
The community already made the call. We're making it official.
---
## What's Changed
- **New projects default to Base UI.** Run `npx shadcn init` and Base UI is the default pick.
- **shadcn/create shows Base UI first.**
- **The docs default to Base UI.** Component pages open on the Base UI tab. Radix docs are one click away.
## What This Means for You
**Radix is not being deprecated.** We still support it, and every update and new component will ship for both libraries (unless a component only exists in Base UI).
**You do not need to migrate.** Radix is a mature, tested library. We still run it in production today and we're not migrating. If your app works, keep shipping.
**Prefer Radix for new projects?** It's one flag away:
```bash
npx shadcn init -b radix
```
If you have scripts or CI running `shadcn init` non-interactively and expecting Radix, add `-b radix` to keep them on the same path.
**Building a registry?** Ship a `registry:base` config if you want to pin a specific library. Items without one now init as Base UI.
**Starting something new?** We recommend Base UI.
## When You're Ready to Migrate
You don't need to migrate. But if you want to, we built a skill for it:
```bash
npx skills add shadcn/ui
```
Then ask your coding agent:
```txt
migrate accordion to base-ui
```
It's progressive by default: migrate one component and its usage at a time while your project stays green and shippable. Both libraries coexist while you work. Stop halfway, ship, come back next week and it picks up where you left off. Or ask for the whole project in one go.
### Why a skill and not a codemod?
Because you own the code. You've added variants, changed classes, threaded new props. A codemod handles the components you never touched and breaks on the ones you did.
So we shipped knowledge instead: every rename, every prop change, every behavior difference, hand-checked against both libraries. Your agent reads it, figures out what _you_ changed, and carries those changes over.
Mechanical things get fixed everywhere (`asChild` is now `render`). Behavior changes get flagged, never silently patched. You decide.
### What a migration produces
Every run leaves three things:
- **Working code.** Typechecked and built before it reports success.
- **A report per component** in `.migration/` at your project root: what changed, what was left alone, and a short checklist of things to verify by hand.
- **Clean git history.** One commit per component, on a branch. Rollback is deleting the branch.
Here's what a report looks like:
```md title=".migration/accordion.md"
# accordion
<!-- date, strategy used, and the one-line verdict -->
## Changed
<!-- every file touched, with what changed and why -->
## Left alone
<!-- files that look related but were intentionally not touched -->
## Behavior changes
<!-- differences that compile fine but act differently. flagged, not patched -->
## Verify by hand
<!-- a short checklist: open, click, tab through. takes a minute -->
```
No hidden state. Progress lives in your files and git history, so any agent, any session, any day picks up where the last one stopped.
It works with Claude Code, Cursor, or any agent that supports skills. We tested it on real projects: 60+ components, 36 of them on Radix. A full migration ran in about 25 minutes at roughly 10k tokens per component. Clean builds, customizations intact.

View File

@@ -0,0 +1,44 @@
---
title: July 2026 - Dynamic Search
description: Registries can now handle search server-side.
date: 2026-07-31
---
**Registries can now handle search server-side.**
When you run `shadcn search`, the CLI forwards the search parameters to your
registry as query params:
```txt
GET /r/registry.json?q=button&limit=50&offset=0
```
Return the matching items with a `pagination` object and the CLI uses your
results as-is. This makes search fast for large registries: no more downloading
the full catalog to search it.
```json title="registry.json?q=button&limit=1"
{
"name": "acme",
"homepage": "https://acme.com",
"items": [
{
"name": "button",
"type": "registry:ui",
"description": "A button component."
}
],
"pagination": {
"total": 12,
"offset": 0,
"limit": 1,
"hasMore": true
}
}
```
Dynamic search is opt-in. Static registries ignore the query params and keep
working without any changes.
See the [Dynamic Search](/docs/registry/dynamic-search) docs for the full
guide.

View File

@@ -0,0 +1,88 @@
---
title: July 2026 - Introducing @shadcn/helpers
description: Small, focused helpers for developing apps, starting with AI SDK and TanStack AI.
date: 2026-07-14
---
We are open sourcing **@shadcn/helpers**, a new package for small, focused
helpers that make developing apps easier.
Starting with a helper for AI SDK and TanStack AI. It lets you write a
conversation in code, then run it through the real `useChat` lifecycle without
a model, API route, network request, or API key.
Your UI receives native
framework messages and streaming events, so reasoning, tool calls, loading
states, and message components behave the same way they do in production.
Here is a conversation written with the AI SDK helper:
```ts showLineNumbers
import { createChat } from "@shadcn/helpers/ai-sdk"
const chat = createChat()
.user("What changed in this release?")
.assistant("The release adds keyboard shortcuts and faster search.")
.user("Can you check the full release notes?")
.sleep(500)
.assistant(({ writer }) => {
writer.stepStart()
// Reasoning.
writer.reasoning("I should read the release notes first.")
// Tool call.
writer
.tool("getReleaseNotes", {
title: "Reading release notes",
input: { version: "latest" },
})
.sleep(500)
.output({
highlights: ["Keyboard shortcuts", "Faster search"],
})
// Source.
writer.sourceUrl({
title: "Release notes",
url: "https://example.com/releases",
})
// Response.
writer.text("The release adds keyboard shortcuts and faster search.")
})
```
Pass its messages and transport to `useChat`:
```tsx showLineNumbers
import { useChat } from "@ai-sdk/react"
const initialMessages = chat.get(0)
const transport = chat.transport()
export function Chat() {
const { messages } = useChat({
messages: initialMessages,
transport,
})
}
```
The package includes two adapters:
- [`@shadcn/helpers/ai-sdk`](/docs/helpers/ai-sdk) plugs into AI SDK's `useChat`
as a transport.
- [`@shadcn/helpers/tanstack-ai`](/docs/helpers/tanstack-ai) plugs into TanStack
AI's `useChat` as a connection and streams real AG-UI events.
Use it to build components, create previews and demos, write documentation, or
test streaming interfaces with deterministic output and no backend dependency.
<div className="flex flex-wrap gap-2">
<Button asChild size="sm">
<Link href="/docs/helpers/ai-sdk" className="mt-6 no-underline!">
Read the Docs
</Link>
</Button>
</div>

View File

@@ -0,0 +1,55 @@
---
title: July 2026 - React Aria
description: React Aria is now available as a component base in shadcn/ui.
date: 2026-07-17
---
**React Aria** is now a first-class component base in shadcn/ui.
Build with React Aria Components alongside Base UI and Radix. Pick it in
shadcn/create or initialize a project with `--base aria`. The CLI handles the
dependencies, registry resolution, styles, and component installation.
<div className="mt-6 flex w-full items-center justify-center rounded-2xl bg-muted/50 py-32 text-foreground ring ring-border dark:bg-muted">
<svg viewBox="200 206 800 790" fill="none" className="size-16">
<path
fill="currentColor"
d="M720.67 205.995C867.583 205.995 986.679 325.091 986.68 472.003C986.68 590.753 908.865 691.325 801.446 725.521L979.312 948.055C994.438 966.98 980.963 995 956.736 995H795.612C778.743 995 762.715 987.629 751.734 974.823L697.365 911.421L493.126 653.39C457.134 607.918 489.518 540.979 547.511 540.977L720.67 540.971C758.758 540.971 789.635 510.091 789.635 472.003C789.634 433.915 758.758 403.038 720.67 403.038H429.939C404.955 403.038 388.623 391.886 373.994 373.623L277.349 252.966C262.194 234.045 275.664 205.996 299.905 205.995H720.67Z M396.605 720.706C407.798 705.406 430.443 704.843 442.381 719.568L503.816 797.018H502.786L535.569 838.934C548.074 854.358 549.943 877.191 538.047 893.09L476.638 972.545C465.692 986.707 448.803 995 430.903 995H242.276C218.18 995 204.665 967.248 219.523 948.278L337.992 797.018H337.923L396.605 720.706Z"
/>
</svg>
</div>
## What's New
- **A first-class React Aria base** - Choose React Aria anywhere you can choose
Base UI or Radix, including the CLI, presets, and shadcn/create.
- **Full component documentation** - React Aria components have dedicated
installation, usage, composition, examples, and API reference sections.
- **All eight styles** - Use React Aria with Vega, Nova, Maia, Lyra, Mira, Luma,
Rhea, or Sera.
- **Base-specific output** - React Aria state selectors and dependencies are
scoped to the Aria registry. Existing Base UI and Radix components are
unchanged.
## Start with React Aria
Use the `aria` base when initializing a project:
```bash
npx shadcn@latest init --base aria
```
Or choose **React Aria** in [shadcn/create](/create?base=aria). Once the project
is initialized, `shadcn add` installs the React Aria implementation for each
component.
Base UI remains the default, and Radix remains fully supported. Existing
projects stay on their current base.
<div className="flex flex-wrap gap-2">
<Button asChild size="sm">
<Link href="/create?base=aria" className="mt-6 no-underline!">
Create a React Aria project
</Link>
</Button>
</div>

View File

@@ -0,0 +1,17 @@
---
title: July 2026 - Toast
description: A new Toast component built on Base UI primitives.
date: 2026-07-23
---
A new [Toast](/docs/components/base/toast) component is now available for Base
UI projects. It supports actions, status types, promises, stacking, and swipe
dismissal.
<ComponentPreview styleName="base-nova" name="toast-demo" />
Add it to your project with the CLI:
```bash
npx shadcn@latest add toast
```

View File

@@ -0,0 +1,52 @@
---
title: July 2026 - Introducing shadcn/typeset
description: A complete typography system for HTML, from blog posts to streaming chat. One CSS file you own.
date: 2026-07-10
---
Today we're releasing **shadcn/typeset**: a styling system for HTML and rendered markdown, in one CSS file.
Your app renders the same HTML elements everywhere: headings, paragraphs, lists, tables, and code. You style them for your blog, then your docs, and now chat. Typeset lets you style them once, then tune the rhythm for each context.
```tsx
<div className="typeset">{content}</div>
```
Add one class and everything inside gets styled. Typeset follows the size of its container, uses your theme, and gives you three controls: size, leading, and flow.
You can create as many typesets as you need. Use a tighter rhythm for chat and a roomier one for docs:
```css
.typeset-chat {
--typeset-leading: 1.6;
--typeset-flow: 1em;
}
.typeset-docs {
--typeset-size: 15px;
--typeset-leading: 1.75;
--typeset-flow: 1.5em;
}
```
```tsx
<div className="typeset typeset-chat">{message}</div>
<article className="typeset typeset-docs">{page}</article>
```
It's also designed for streaming, so new blocks don't restyle earlier ones. The file lives in your project. There's no package or config layer to work around.
Open the [typeset builder](/typeset) to create yours, or read the [Typeset docs](/docs/typeset) for the full guide.
<div className="flex gap-2">
<Button asChild size="sm">
<Link href="/typeset" className="mt-6 no-underline!">
Build your typeset
</Link>
</Button>
<Button asChild size="sm" variant="outline">
<Link href="/docs/typeset" className="mt-6 no-underline!">
Read the docs
</Link>
</Button>
</div>

View File

@@ -0,0 +1,62 @@
---
title: August 2026 - Human in the Loop
description: Mock paused tool calls, approvals, and continuations for the AI SDK with @shadcn/helpers.
date: 2026-08-12
---
**@shadcn/helpers** can now mock human-in-the-loop flows for the AI SDK. A
scripted conversation can pause for real user input, wait for an approval, and
continue with whatever the user decided.
Everything streams through the real
`useChat` lifecycle, so your tool cards, approval prompts, and question flows
behave exactly as they would in production.
```ts showLineNumbers
import { createChat } from "@shadcn/helpers/ai-sdk"
const chat = createChat<ChatMessage>()
.user("Help me plan the next prototype.")
.assistant(({ writer }) => {
writer.text("A couple of questions before I start.")
writer.tool("askQuestions", { input: { questions } })
})
.assistant(({ writer, toolCall }) => {
writer.text(
toolCall?.name === "askQuestions" && toolCall.output
? `Starting with ${toolCall.output.answers.direction}.`
: "Starting now."
)
})
```
Pass `needsApproval` to pause behind the user's decision. The scripted output
streams after approval, and denial streams automatically.
```ts showLineNumbers
chat
.assistant(({ writer }) => {
writer.text("That will archive 3 drafts. I need your approval.")
writer.tool("archiveDrafts", {
input: { count: 3 },
needsApproval: true,
output: { archived: 3 },
})
})
.assistant(({ writer, toolCall }) => {
writer.text(
toolCall?.approved ? "Archived 3 drafts." : "Okay, leaving them in place."
)
})
```
<div className="flex flex-wrap gap-2">
<Button asChild size="sm">
<Link
href="/docs/helpers/ai-sdk#human-in-the-loop"
className="mt-6 no-underline!"
>
Read the Docs
</Link>
</Button>
</div>

View File

@@ -0,0 +1,83 @@
---
title: August 2026 - Private GitHub Registries
description: Install registry items from private GitHub repositories using the GitHub CLI or a token.
date: 2026-08-24
---
**GitHub registries now work with private repositories.**
In June, we made it possible to turn any public GitHub repository into a
registry. Teams asked for the same thing for their internal code: design
systems, feature kits, agent rules and conventions that should not be public.
You can now install from private repositories. If you can read the repository,
the CLI can install from it.
```bash
npx shadcn@latest add acme/internal-toolkit/auth-kit
```
## Zero configuration
If you are logged in to the GitHub CLI, there is nothing to set up.
```bash
gh auth login
```
When a repository is not publicly readable, the CLI reads it through `gh` using
your stored credentials. The token stays inside the GitHub CLI. It never enters
the shadcn process.
```txt
✔ Using gh credentials.
✔ Checking registry.
✔ Created 1 file:
- lib/auth.ts
```
## CI support
Where the GitHub CLI is not installed, set `GH_TOKEN` or `GITHUB_TOKEN`:
```bash
GH_TOKEN=github_pat_xxx npx shadcn@latest add acme/internal-toolkit/auth-kit
```
We recommend a fine-grained personal access token scoped to the repository with
**Contents: Read-only** access.
## Works with every command
Private repositories work with the same commands as public GitHub registries.
```bash
npx shadcn@latest list acme/internal-toolkit
```
```bash
npx shadcn@latest search acme/internal-toolkit --query auth
```
```bash
npx shadcn@latest view acme/internal-toolkit/auth-kit
```
```bash
npx shadcn@latest registry validate acme/internal-toolkit
```
## How it works
- Public repositories are read anonymously, exactly as before. No credentials
are used and the GitHub CLI is never invoked.
- The CLI tries anonymous access first and only uses your credentials when the
repository is not publicly readable.
- Private files are read through GitHub's Contents API, pinned to the resolved
commit SHA.
- A token from `GH_TOKEN` is only ever sent to `api.github.com`. Stored GitHub
CLI credentials are read by `gh`, not by the CLI.
See the
[Private repositories](/docs/registry/github#private-repositories) docs for
the full guide.

View File

@@ -0,0 +1,52 @@
---
title: August 2026 - Questionnaire
description: A new component for building multi-step question flows with fixed, freeform, multiple, and skippable answers.
date: 2026-08-05
---
Today, we're releasing [**Questionnaire**](/docs/components/base/questionnaire),
a new component for multi-step question flows. Use it for agent clarification
prompts, onboarding, surveys, intake forms, and configuration.
Questionnaire is available for Base UI, React Aria, and Radix across all eight
styles.
<ComponentPreview
align="end"
styleName="base-nova"
name="questionnaire-demo"
previewClassName="min-h-[560px] p-4 sm:p-8"
/>
## Features
- Single and multiple selection with native radios and checkboxes.
- Freeform answers alongside fixed choices.
- Explicit skipping for optional questions.
- Previous, next, submit, and custom progress controls.
- Required and custom validation.
- Controlled navigation, saved defaults, and conditional questions.
- Keyboard navigation with optional letter or number shortcuts.
- Native form serialization and server-rendered collection state.
- Standalone, Card, and Dialog composition.
## Installation
```bash
npx shadcn@latest add questionnaire
```
## @shadcn/react
The `<Questionnaire />` component is also available as an unstyled headless primitive in `@shadcn/react`. [Read the docs](/docs/react/questionnaire) to learn more.
<div className="flex flex-wrap gap-2">
<Button asChild size="sm">
<Link
href="/docs/components/base/questionnaire"
className="mt-6 no-underline!"
>
View Questionnaire
</Link>
</Button>
</div>

View File

@@ -0,0 +1,53 @@
---
title: September 2026 - cn
description: Components now import cn from the cn package. One dependency instead of two, and no local helper to maintain.
date: 2026-09-03
---
**Every shadcn component now imports `cn` from the `cn` package.**
For years, every shadcn project started with the same five lines in
`lib/utils.ts`: import `clsx`, import `twMerge`, wrap one in the other, export
it as `cn`. It worked, but it meant two dependencies and a helper you had to
copy into every project and every registry.
We have moved that into a package. [`cn`](https://github.com/shadcn-ui/cn) is a
drop-in replacement for `twMerge(clsx(...))`. It is smaller, faster and ships
the same API, so nothing changes at the call site.
```tsx
import { cn } from "cn"
;<div className={cn("flex items-center", className)} />
```
## What changed
- Registry components, blocks and examples import `cn` from `cn` instead of
`@/lib/utils`.
- `npx shadcn init` installs `cn` and generates a one-line `lib/utils.ts`.
- Every registry item that uses `cn` declares it as a dependency, so
`npx shadcn add` installs it in projects created before this change.
## lib/utils.ts
The `utils` registry item still exists. It now re-exports `cn` so your own code
keeps working and you still have a single place for project helpers.
```ts title="lib/utils.ts"
export { cn } from "cn"
```
## Existing projects
Nothing breaks. Your `lib/utils.ts` keeps working and new components install
`cn` next to it. To move the rest of your project over and drop `clsx` and
`tailwind-merge`, run the migration:
```bash
npx shadcn@latest migrate cn
```
It rewrites imports, replaces `twMerge(clsx(...))` calls and removes the old
packages when nothing references them anymore. See the
[CLI docs](/docs/cli#migrate-cn) for details.

View File

@@ -0,0 +1,6 @@
---
title: Changelog
description: Latest updates and announcements.
---
Latest updates and announcements for shadcn/ui.

View File

@@ -0,0 +1,4 @@
{
"title": "Changelog",
"pages": []
}

View File

@@ -0,0 +1,165 @@
---
title: Accordion
description: A vertically stacked set of interactive headings that each reveal a section of content.
base: aria
component: true
links:
doc: https://react-aria.adobe.com/DisclosureGroup
api: https://react-aria.adobe.com/DisclosureGroup#api
---
<ComponentPreview
styleName="aria-nova"
name="accordion-demo"
align="start"
previewClassName="*:data-[slot=accordion]:max-w-sm h-[300px]"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add accordion
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install react-aria-components
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="accordion"
title="components/ui/accordion.tsx"
styleName="aria-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion"
```
```tsx showLineNumbers
<Accordion defaultExpandedKeys={["item-1"]}>
<AccordionItem id="item-1">
<AccordionTrigger>Is it accessible?</AccordionTrigger>
<AccordionContent>
Yes. It adheres to the WAI-ARIA design pattern.
</AccordionContent>
</AccordionItem>
</Accordion>
```
## Composition
Use the following composition to build an `Accordion`:
```text
Accordion
├── AccordionItem
│ ├── AccordionTrigger
│ └── AccordionContent
└── AccordionItem
├── AccordionTrigger
└── AccordionContent
```
## Basic
A basic accordion that shows one item at a time. The first item is open by default.
<ComponentPreview
styleName="aria-nova"
name="accordion-basic"
align="start"
previewClassName="*:data-[slot=accordion]:max-w-sm h-[300px]"
/>
## Multiple
Use the `allowsMultipleExpanded` prop to allow multiple items to be open at the same time.
<ComponentPreview
styleName="aria-nova"
name="accordion-multiple"
align="start"
previewClassName="*:data-[slot=accordion]:max-w-sm h-[450px]"
/>
## Disabled
Use the `isDisabled` prop on `AccordionItem` to disable individual items.
<ComponentPreview
styleName="aria-nova"
name="accordion-disabled"
align="start"
previewClassName="*:data-[slot=accordion]:max-w-sm h-[300px]"
/>
## Borders
Add `border` to the `Accordion` and `border-b last:border-b-0` to the `AccordionItem` to add borders to the items.
<ComponentPreview
styleName="aria-nova"
name="accordion-borders"
align="start"
previewClassName="*:data-[slot=accordion]:max-w-sm h-[300px]"
/>
## Card
Wrap the `Accordion` in a `Card` component.
<ComponentPreview
styleName="aria-nova"
name="accordion-card"
align="start"
previewClassName="*:data-[slot=accordion]:max-w-sm h-[435px]"
/>
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview
styleName="aria-nova"
name="accordion-rtl"
align="start"
direction="rtl"
/>
## API Reference
See the [React Aria](https://react-aria.adobe.com/DisclosureGroup#api) documentation for more information.

View File

@@ -0,0 +1,182 @@
---
title: Alert Dialog
description: A modal dialog that interrupts the user with important content and expects a response.
featured: true
base: aria
component: true
links:
doc: https://react-aria.adobe.com/Modal
api: https://react-aria.adobe.com/Modal#api
---
<ComponentPreview
styleName="aria-nova"
name="alert-dialog-demo"
previewClassName="h-56"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add alert-dialog
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install react-aria-components
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="alert-dialog"
title="components/ui/alert-dialog.tsx"
styleName="aria-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog"
```
```tsx showLineNumbers
<AlertDialogTrigger>
<Button variant="outline">Show Dialog</Button>
<AlertDialog>
<AlertDialogHeader>
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
<AlertDialogDescription>
This action cannot be undone. This will permanently delete your account
from our servers.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction>Continue</AlertDialogAction>
</AlertDialogFooter>
</AlertDialog>
</AlertDialogTrigger>
```
## Composition
Use the following composition to build an `AlertDialog`:
```text
AlertDialogTrigger
├── Button
└── AlertDialog
├── AlertDialogHeader
│ ├── AlertDialogMedia
│ ├── AlertDialogTitle
│ └── AlertDialogDescription
└── AlertDialogFooter
├── AlertDialogCancel
└── AlertDialogAction
```
## Basic
A basic alert dialog with a title, description, and cancel and continue buttons.
<ComponentPreview
styleName="aria-nova"
name="alert-dialog-basic"
previewClassName="h-56"
/>
## Small
Use the `size="sm"` prop to make the alert dialog smaller.
<ComponentPreview
styleName="aria-nova"
name="alert-dialog-small"
previewClassName="h-56"
/>
## Media
Use the `AlertDialogMedia` component to add a media element such as an icon or image to the alert dialog.
<ComponentPreview
styleName="aria-nova"
name="alert-dialog-media"
previewClassName="h-56"
/>
## Small with Media
Use the `size="sm"` prop to make the alert dialog smaller and the `AlertDialogMedia` component to add a media element such as an icon or image to the alert dialog.
<ComponentPreview
styleName="aria-nova"
name="alert-dialog-small-media"
previewClassName="h-56"
/>
## Destructive
Use the `AlertDialogAction` component to add a destructive action button to the alert dialog.
<ComponentPreview
styleName="aria-nova"
name="alert-dialog-destructive"
previewClassName="h-56"
/>
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview
styleName="aria-nova"
name="alert-dialog-rtl"
direction="rtl"
previewClassName="h-56"
/>
## API Reference
### size
Use the `size` props on the `AlertDialogContent` component to control the size of the alert dialog. It accepts the following values:
| Prop | Type | Default |
| ------ | ------------------- | ----------- |
| `size` | `"default" \| "sm"` | `"default"` |
For more information about the other components and their props, see the [React Aria documentation](https://react-aria.adobe.com/Modal#api).

View File

@@ -0,0 +1,165 @@
---
title: Alert
description: Displays a callout for user attention.
base: aria
component: true
---
<ComponentPreview
styleName="aria-nova"
name="alert-demo"
previewClassName="h-auto sm:h-72 p-6"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add alert
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="alert" title="components/ui/alert.tsx" />
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Alert,
AlertAction,
AlertDescription,
AlertTitle,
} from "@/components/ui/alert"
```
```tsx showLineNumbers
<Alert>
<InfoIcon />
<AlertTitle>Heads up!</AlertTitle>
<AlertDescription>
You can add components and dependencies to your app using the cli.
</AlertDescription>
<AlertAction>
<Button variant="outline">Enable</Button>
</AlertAction>
</Alert>
```
## Composition
Use the following composition to build an `Alert`:
```text
Alert
├── Icon
├── AlertTitle
├── AlertDescription
└── AlertAction
```
## Basic
A basic alert with an icon, title and description.
<ComponentPreview
styleName="aria-nova"
name="alert-basic"
previewClassName="h-auto sm:h-72 p-6"
/>
## Destructive
Use `variant="destructive"` to create a destructive alert.
<ComponentPreview
styleName="aria-nova"
name="alert-destructive"
previewClassName="h-auto sm:h-72 p-6"
/>
## Action
Use `AlertAction` to add a button or other action element to the alert.
<ComponentPreview
styleName="aria-nova"
name="alert-action"
previewClassName="h-auto sm:h-72 p-6"
/>
## Custom Colors
You can customize the alert colors by adding custom classes such as `bg-amber-50 dark:bg-amber-950` to the `Alert` component.
<ComponentPreview
styleName="aria-nova"
name="alert-colors"
previewClassName="h-auto sm:h-72 p-6"
/>
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview
styleName="aria-nova"
name="alert-rtl"
direction="rtl"
previewClassName="h-auto sm:h-72 p-6"
/>
## API Reference
### Alert
The `Alert` component displays a callout for user attention.
| Prop | Type | Default |
| --------- | ---------------------------- | ----------- |
| `variant` | `"default" \| "destructive"` | `"default"` |
### AlertTitle
The `AlertTitle` component displays the title of the alert.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### AlertDescription
The `AlertDescription` component displays the description or content of the alert.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### AlertAction
The `AlertAction` component displays an action element (like a button) positioned absolutely in the top-right corner of the alert.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |

View File

@@ -0,0 +1,94 @@
---
title: Aspect Ratio
description: Displays content within a desired ratio.
base: aria
component: true
---
<ComponentPreview name="aspect-ratio-demo" styleName="aria-nova" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add aspect-ratio
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="aspect-ratio"
title="components/ui/aspect-ratio.tsx"
styleName="aria-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { AspectRatio } from "@/components/ui/aspect-ratio"
```
```tsx showLineNumbers
<AspectRatio ratio={16 / 9}>
<Image src="..." alt="Image" className="rounded-md object-cover" />
</AspectRatio>
```
## Square
A square aspect ratio component using the `ratio={1 / 1}` prop. This is useful for displaying images in a square format.
<ComponentPreview name="aspect-ratio-square" styleName="aria-nova" />
## Portrait
A portrait aspect ratio component using the `ratio={9 / 16}` prop. This is useful for displaying images in a portrait format.
<ComponentPreview
styleName="aria-nova"
name="aspect-ratio-portrait"
previewClassName="h-96"
/>
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview
styleName="aria-nova"
name="aspect-ratio-rtl"
direction="rtl"
previewClassName="h-96"
/>
## API Reference
### AspectRatio
The `AspectRatio` component displays content within a desired ratio.
| Prop | Type | Default | Required |
| ----------- | -------- | ------- | -------- |
| `ratio` | `number` | - | Yes |
| `className` | `string` | - | No |

View File

@@ -0,0 +1,303 @@
---
title: Attachment
description: Displays a file or image attachment with media, metadata, upload state, and actions.
base: aria
component: true
---
<ComponentPreview
styleName="aria-rhea"
name="attachment-demo"
previewClassName="h-auto theme-blue bg-surface dark:bg-background"
/>
The `Attachment` component displays a file or image attachment, its media, name, and metadata, with optional actions and upload state. Use it for files and images in chat composers, message threads, and upload lists.
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add attachment
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the required shadcn/ui dependencies:</Step>
```bash
npx shadcn@latest add button
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="attachment"
title="components/ui/attachment.tsx"
styleName="aria-rhea"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import {
Attachment,
AttachmentAction,
AttachmentActions,
AttachmentContent,
AttachmentDescription,
AttachmentMedia,
AttachmentTitle,
} from "@/components/ui/attachment"
```
```tsx
<Attachment>
<AttachmentMedia>
<FileTextIcon />
</AttachmentMedia>
<AttachmentContent>
<AttachmentTitle>sales-dashboard.pdf</AttachmentTitle>
<AttachmentDescription>PDF · 2.4 MB</AttachmentDescription>
</AttachmentContent>
<AttachmentActions>
<AttachmentAction aria-label="Remove sales-dashboard.pdf">
<XIcon />
</AttachmentAction>
</AttachmentActions>
</Attachment>
```
## Composition
Use the following composition to build an attachment:
```text
Attachment
├── AttachmentMedia
├── AttachmentContent
│ ├── AttachmentTitle
│ └── AttachmentDescription
├── AttachmentActions
│ └── AttachmentAction
└── AttachmentTrigger
```
Use `AttachmentGroup` to lay out multiple attachments in a scrollable row:
```text
AttachmentGroup
├── Attachment
└── Attachment
```
## Features
- Icon and image media through `AttachmentMedia`
- Upload states: `idle`, `uploading`, `processing`, `error`, and `done` with built-in styling and a shimmer while in progress
- Three sizes and horizontal or vertical orientation
- A full-card `AttachmentTrigger` that opens a link or dialog while the actions stay independently clickable
- Scrollable, snapping `AttachmentGroup` with an edge fade
- Customizable styling through the `className` prop on every part
## Image
Set `variant="image"` on `AttachmentMedia` and render an `<img>` inside it. Use `orientation="vertical"` to stack the media above the content.
<ComponentPreview
styleName="aria-rhea"
name="attachment-image"
previewClassName="h-auto theme-blue bg-surface dark:bg-background"
/>
## States
Set `state` to reflect the upload lifecycle. `uploading` and `processing` shimmer the title, and `error` switches to a destructive treatment.
<ComponentPreview
styleName="aria-rhea"
name="attachment-states"
previewClassName="h-auto theme-blue bg-surface dark:bg-background"
/>
## Sizes
Use `size` to switch between `default`, `sm`, and `xs`.
<ComponentPreview
styleName="aria-rhea"
name="attachment-sizes"
previewClassName="h-auto theme-blue bg-surface dark:bg-background"
/>
## Group
Wrap attachments in `AttachmentGroup` to lay them out in a horizontally scrollable, snapping row with an edge fade.
<ComponentPreview
styleName="aria-rhea"
name="attachment-group"
previewClassName="h-auto theme-blue bg-surface dark:bg-background"
/>
## Trigger
Add an `AttachmentTrigger` to make the whole card open a link or dialog. It fills the card behind the actions, so the actions stay clickable.
<ComponentPreview
styleName="aria-rhea"
name="attachment-trigger"
previewClassName="h-auto theme-blue bg-surface dark:bg-background"
/>
```tsx showLineNumbers
<Dialog>
<Attachment>
{/* media, content, actions */}
<DialogTrigger>
<AttachmentTrigger aria-label="Preview research-summary.pdf" />
</DialogTrigger>
</Attachment>
<DialogContent>{/* ... */}</DialogContent>
</Dialog>
```
## Accessibility
`AttachmentAction` renders a `Button`, and `AttachmentTrigger` renders a real `<button>` (or your element via `render`). Follow the guidance below so both are operable and announced.
### Label icon-only actions
`AttachmentAction` is usually icon-only, so give each one an `aria-label` describing the action and its target.
```tsx showLineNumbers
<AttachmentAction aria-label="Remove sales-dashboard.pdf">
<XIcon />
</AttachmentAction>
```
### Label the trigger
`AttachmentTrigger` covers the card with no text of its own, so give it an `aria-label` for what activating it does.
```tsx showLineNumbers
<AttachmentTrigger
render={(props) => (
<a
{...props}
href={url}
target="_blank"
rel="noreferrer"
aria-label="Open workspace.png"
/>
)}
/>
```
The trigger sits behind the actions in the stacking order, so an `AttachmentAction` and the `AttachmentTrigger` never trap each other — both remain separately focusable and clickable.
### Keyboard scrolling
An `AttachmentGroup` scrolls horizontally. When its attachments are interactive: a trigger or actions, keyboard users reach off-screen items by tabbing to them. For a row of presentational attachments, make the group itself focusable and scrollable by adding `tabIndex={0}`, `role="group"`, and an `aria-label`.
### Meaning beyond color
The `error` state uses a destructive color. Keep the failure reason in `AttachmentDescription` so the state is not conveyed by color alone.
## API Reference
### Attachment
The root attachment container.
| Prop | Type | Default | Description |
| ------------- | ------------------------------------------------------------ | -------------- | ------------------------------------------------- |
| `state` | `"idle" \| "uploading" \| "processing" \| "error" \| "done"` | `"done"` | The upload state. Drives styling and the shimmer. |
| `size` | `"default" \| "sm" \| "xs"` | `"default"` | The attachment size. |
| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Lay the media beside or above the content. |
| `className` | `string` | - | Additional classes to apply to the root element. |
### AttachmentMedia
The media slot for an icon or image preview.
| Prop | Type | Default | Description |
| ----------- | ------------------- | -------- | ---------------------------------------------- |
| `variant` | `"icon" \| "image"` | `"icon"` | Whether the media holds an icon or an `<img>`. |
| `className` | `string` | - | Additional classes to apply to the media slot. |
### AttachmentContent
Wraps the title and description.
| Prop | Type | Default | Description |
| ----------- | -------- | ------- | ------------------------------------------------ |
| `className` | `string` | - | Additional classes to apply to the content slot. |
### AttachmentTitle
The attachment name. Shimmers while the attachment is `uploading` or `processing`.
| Prop | Type | Default | Description |
| ----------- | -------- | ------- | ----------------------------------------- |
| `className` | `string` | - | Additional classes to apply to the title. |
### AttachmentDescription
Secondary metadata such as the file type, size, or upload status.
| Prop | Type | Default | Description |
| ----------- | -------- | ------- | ----------------------------------------------- |
| `className` | `string` | - | Additional classes to apply to the description. |
### AttachmentActions
A container for one or more actions, aligned to the end of the attachment.
| Prop | Type | Default | Description |
| ----------- | -------- | ------- | ------------------------------------------- |
| `className` | `string` | - | Additional classes to apply to the actions. |
### AttachmentAction
An action button. Renders a [`Button`](/docs/components/aria/button) and accepts all of its props.
| Prop | Type | Default | Description |
| ---------- | ------------------------------------- | ----------- | ---------------------------------------- |
| `size` | `Button["size"]` | `"icon-xs"` | The button size. |
| `...props` | `React.ComponentProps<typeof Button>` | - | Props spread to the underlying `Button`. |
### AttachmentTrigger
A full-card overlay that activates the attachment. Renders a `<button>` by default.
| Prop | Type | Default | Description |
| ---------- | -------------------------------- | ------- | ---------------------------------------------- |
| `render` | `ReactElement \| function` | - | Render as a different element, such as a link. |
| `...props` | `React.ComponentProps<"button">` | - | Props spread to the trigger element. |
### AttachmentGroup
Lays out attachments in a horizontally scrollable, snapping row.
| Prop | Type | Default | Description |
| ----------- | -------- | ------- | ----------------------------------------- |
| `className` | `string` | - | Additional classes to apply to the group. |

View File

@@ -0,0 +1,209 @@
---
title: Avatar
description: An image element with a fallback for representing the user.
base: aria
component: true
---
<ComponentPreview
styleName="aria-nova"
name="avatar-demo"
previewClassName="h-72"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add avatar
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="avatar"
title="components/ui/avatar.tsx"
styleName="aria-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
```
```tsx showLineNumbers
<Avatar>
<AvatarImage src="https://github.com/shadcn.png" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
```
## Composition
Use the following composition to build an `Avatar`:
```text
Avatar
├── AvatarImage
├── AvatarFallback
└── AvatarBadge
```
Use the following composition to build an `AvatarGroup`:
```text
AvatarGroup
├── Avatar
│ ├── AvatarImage
│ ├── AvatarFallback
│ └── AvatarBadge
├── Avatar
│ ├── AvatarImage
│ ├── AvatarFallback
│ └── AvatarBadge
└── AvatarGroupCount
```
## Basic
A basic avatar component with an image and a fallback.
<ComponentPreview styleName="aria-nova" name="avatar-basic" />
## Badge
Use the `AvatarBadge` component to add a badge to the avatar. The badge is positioned at the bottom right of the avatar.
<ComponentPreview styleName="aria-nova" name="avatar-badge" />
Use the `className` prop to add custom styles to the badge such as custom colors, sizes, etc.
```tsx showLineNumbers
<Avatar>
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
<AvatarFallback>CN</AvatarFallback>
<AvatarBadge className="bg-green-600 dark:bg-green-800" />
</Avatar>
```
## Badge with Icon
You can also use an icon inside `<AvatarBadge>`.
<ComponentPreview styleName="aria-nova" name="avatar-badge-icon" />
## Avatar Group
Use the `AvatarGroup` component to add a group of avatars.
<ComponentPreview styleName="aria-nova" name="avatar-group" />
## Avatar Group Count
Use `<AvatarGroupCount>` to add a count to the group.
<ComponentPreview styleName="aria-nova" name="avatar-group-count" />
## Avatar Group with Icon
You can also use an icon inside `<AvatarGroupCount>`.
<ComponentPreview styleName="aria-nova" name="avatar-group-count-icon" />
## Sizes
Use the `size` prop to change the size of the avatar.
<ComponentPreview styleName="aria-nova" name="avatar-size" />
## Dropdown
You can use the `Avatar` component as a trigger for a dropdown menu.
<ComponentPreview styleName="aria-nova" name="avatar-dropdown" />
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview
styleName="aria-nova"
name="avatar-rtl"
direction="rtl"
previewClassName="h-72"
/>
## API Reference
### Avatar
The `Avatar` component is the root component that wraps the avatar image and fallback.
| Prop | Type | Default |
| ----------- | --------------------------- | ----------- |
| `size` | `"default" \| "sm" \| "lg"` | `"default"` |
| `className` | `string` | - |
### AvatarImage
The `AvatarImage` component displays the avatar image.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `src` | `string` | - |
| `alt` | `string` | - |
| `className` | `string` | - |
### AvatarFallback
The `AvatarFallback` component displays a fallback when the image fails to load.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### AvatarBadge
The `AvatarBadge` component displays a badge indicator on the avatar, typically positioned at the bottom right.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### AvatarGroup
The `AvatarGroup` component displays a group of avatars with overlapping styling.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### AvatarGroupCount
The `AvatarGroupCount` component displays a count indicator in an avatar group, typically showing the number of additional avatars.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |

View File

@@ -0,0 +1,101 @@
---
title: Badge
description: Displays a badge or a component that looks like a badge.
base: aria
component: true
---
<ComponentPreview styleName="aria-nova" name="badge-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add badge
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="badge"
title="components/ui/badge.tsx"
styleName="aria-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import { Badge } from "@/components/ui/badge"
```
```tsx
<Badge variant="default | outline | secondary | destructive">Badge</Badge>
```
## Variants
Use the `variant` prop to change the variant of the badge.
<ComponentPreview styleName="aria-nova" name="badge-variants" />
## With Icon
You can render an icon inside the badge. Use `data-icon="inline-start"` to render the icon on the left and `data-icon="inline-end"` to render the icon on the right.
<ComponentPreview styleName="aria-nova" name="badge-icon" />
## With Spinner
You can render a spinner inside the badge. Remember to add the `data-icon="inline-start"` or `data-icon="inline-end"` prop to the spinner.
<ComponentPreview styleName="aria-nova" name="badge-spinner" />
## Link
Use the `render` prop to render a link as a badge.
<ComponentPreview styleName="aria-nova" name="badge-link" />
## Custom Colors
You can customize the colors of a badge by adding custom classes such as `bg-green-50 dark:bg-green-800` to the `Badge` component.
<ComponentPreview styleName="aria-nova" name="badge-colors" />
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview styleName="aria-nova" name="badge-rtl" direction="rtl" />
## API Reference
### Badge
The `Badge` component displays a badge or a component that looks like a badge.
| Prop | Type | Default |
| ----------- | ----------------------------------------------------------------------------- | ----------- |
| `variant` | `"default" \| "secondary" \| "destructive" \| "outline" \| "ghost" \| "link"` | `"default"` |
| `className` | `string` | - |

View File

@@ -0,0 +1,197 @@
---
title: Breadcrumb
description: Displays the path to the current resource using a hierarchy of links.
base: aria
component: true
links:
doc: https://react-aria.adobe.com/Breadcrumbs
api: https://react-aria.adobe.com/Breadcrumbs#api
---
<ComponentPreview
styleName="aria-nova"
name="breadcrumb-demo"
previewClassName="p-2"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add breadcrumb
```
</TabsContent>
<TabsContent value="manual">
<Step>Install the following dependencies:</Step>
```bash
npm install react-aria-components
```
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="breadcrumb"
title="components/ui/breadcrumb.tsx"
styleName="aria-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
} from "@/components/ui/breadcrumb"
```
```tsx showLineNumbers
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbItem>
<BreadcrumbLink href="/components">Components</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
```
## Composition
Use the following composition to build a `Breadcrumb`:
```text
Breadcrumb
└── BreadcrumbList
├── BreadcrumbItem
│ └── BreadcrumbLink
├── BreadcrumbItem
│ └── BreadcrumbLink
└── BreadcrumbItem
└── BreadcrumbPage
```
## Basic
A basic breadcrumb with a home link and a components link.
<ComponentPreview styleName="aria-nova" name="breadcrumb-basic" />
## Custom separator
Use a custom component as `children` for `<BreadcrumbSeparator />` to create a custom separator.
<ComponentPreview styleName="aria-nova" name="breadcrumb-separator" />
## Dropdown
You can compose `<BreadcrumbItem />` with a `<DropdownMenu />` to create a dropdown in the breadcrumb.
<ComponentPreview styleName="aria-nova" name="breadcrumb-dropdown" />
## Collapsed
We provide a `<BreadcrumbEllipsis />` component to show a collapsed state when the breadcrumb is too long.
<ComponentPreview
styleName="aria-nova"
name="breadcrumb-ellipsis"
previewClassName="p-2"
/>
## Link component
To use a custom link component from your routing library, you can use the `render` prop on `<BreadcrumbLink />`.
<ComponentPreview styleName="aria-nova" name="breadcrumb-link" />
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview
styleName="aria-nova"
name="breadcrumb-rtl"
direction="rtl"
previewClassName="p-2"
/>
## API Reference
### Breadcrumb
The `Breadcrumb` component is the root navigation element that wraps all breadcrumb components.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### BreadcrumbList
The `BreadcrumbList` component displays the ordered list of breadcrumb items.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### BreadcrumbItem
The `BreadcrumbItem` component wraps individual breadcrumb items.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### BreadcrumbLink
The `BreadcrumbLink` component displays a clickable link in the breadcrumb.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### BreadcrumbPage
The `BreadcrumbPage` component displays the current page in the breadcrumb (non-clickable).
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### BreadcrumbEllipsis
The `BreadcrumbEllipsis` component displays an ellipsis indicator for collapsed breadcrumb items.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
For more information, see the [React Aria documentation](https://react-aria.adobe.com/Breadcrumbs#api).

View File

@@ -0,0 +1,302 @@
---
title: Bubble
description: Displays conversational content in a message bubble. Supports variants, alignment, grouping, reactions, and collapsible content.
base: aria
component: true
---
<ComponentPreview
styleName="aria-rhea"
name="bubble-demo"
previewClassName="h-auto theme-blue"
/>
The `Bubble` component displays framed conversational content. Use it for chat text, short structured output, quoted replies, suggestions, and reactions.
For full-featured chat interfaces, use the [`Message`](/docs/components/aria/message) component. `Bubble` is intentionally scoped to the bubble surface. Place avatars, names, timestamps, metadata, and message-level actions in [`Message`](/docs/components/aria/message).
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add bubble
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="bubble"
title="components/ui/bubble.tsx"
styleName="aria-rhea"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { Bubble, BubbleContent, BubbleReactions } from "@/components/ui/bubble"
```
```tsx showLineNumbers
<Bubble>
<BubbleContent>
I checked the registry output and removed the stale route.
</BubbleContent>
<BubbleReactions>
<span>👍</span>
</BubbleReactions>
</Bubble>
```
## Composition
Use the following composition to build a bubble:
```text
Bubble
├── BubbleContent
└── BubbleReactions
```
Use `BubbleGroup` to group consecutive bubbles from the same sender:
```text
BubbleGroup
├── Bubble
│ └── BubbleContent
└── Bubble
└── BubbleContent
```
## Features
- Seven visual variants, from a strong primary bubble to unframed ghost content
- Start and end alignment for sender and receiver bubbles
- Reactions that anchor to the bubble edge with configurable side and alignment
- Bubbles size to their content, up to 80% of the container width
- Polymorphic content via `render` for link and button bubbles
- Customizable styling through the `className` prop on every part
## Variants
Use `variant` to change the visual treatment of the bubble.
<ComponentPreview
styleName="aria-rhea"
name="bubble-variants"
previewClassName="h-auto theme-blue"
/>
| Variant | Description |
| ------------- | ------------------------------------------------------ |
| `default` | A strong primary bubble, usually for the current user. |
| `secondary` | The standard neutral bubble for conversation content. |
| `muted` | A lower-emphasis bubble for quiet supporting content. |
| `tinted` | A subtle primary-tinted bubble. |
| `outline` | A bordered bubble for secondary or rich content. |
| `ghost` | Unframed content for assistant text or rich content. |
| `destructive` | A destructive bubble for error or failed actions. |
A bubble sizes to its content, up to 80% of the container width. The `ghost` variant removes the max-width so assistant text and rich content can span the full row.
## Alignment
Use `align` on `Bubble` to align the bubble to the start or end of the conversation.
<ComponentPreview
styleName="aria-rhea"
name="bubble-alignment"
previewClassName="h-auto theme-blue"
/>
| align | Description |
| ------- | -------------------------------------------------- |
| `start` | Align the bubble to the start of the conversation. |
| `end` | Align the bubble to the end of the conversation. |
**Note:** When building chat interfaces, you probably want to use alignment on the `Message` component itself, not the `Bubble` component. You can use the `role` prop on the `Message` component to automatically align the bubble to the start or end of the conversation.
## Bubble Group
Use `BubbleGroup` to group consecutive bubbles from the same sender. Note the `align` prop should be set on the `Bubble` component itself, not the `BubbleGroup` component.
```text
BubbleGroup
├── Bubble
│ └── BubbleContent
└── Bubble
└── BubbleContent
```
<ComponentPreview
styleName="aria-rhea"
name="bubble-group-demo"
previewClassName="h-auto theme-blue"
/>
## Links and Buttons
You can turn a bubble into a link or button by using the `render` prop on `BubbleContent`.
<ComponentPreview
styleName="aria-rhea"
name="bubble-link-button"
previewClassName="h-auto theme-blue"
/>
```tsx showLineNumbers
import { Bubble, BubbleContent } from "@/components/ui/bubble"
export function BubbleLinkDemo() {
return (
<Bubble variant="muted">
<BubbleContent render={(props) => <button {...props} type="button" />}>
Click here
</BubbleContent>
</Bubble>
)
}
```
## Reactions
Use `BubbleReactions` for bubble reactions. You can use it to display reactions or quick action buttons. Use `side` and `align` to position the row — `side="top"` anchors it to the upper edge. Reactions overlap the bubble edge, so leave vertical space between rows — the examples below use a larger `gap` for this reason.
<ComponentPreview
styleName="aria-rhea"
name="bubble-reactions"
previewClassName="h-auto theme-blue"
/>
## Show More / Collapsible
Long bubble content can be composed with [`Collapsible`](/docs/components/aria/collapsible) to allow for a show more or show less interaction. Use the `CollapsibleTrigger` component to trigger the collapsible content.
<ComponentPreview
styleName="aria-rhea"
name="bubble-collapsible"
previewClassName="h-auto theme-blue"
/>
## Tooltip
Wrap a bubble in a [`Tooltip`](/docs/components/aria/tooltip) to reveal metadata on hover, such as when a message was read.
<ComponentPreview
styleName="aria-rhea"
name="bubble-tooltip"
previewClassName="h-auto theme-blue"
/>
## Popover
Pair a bubble with a [`Popover`](/docs/components/aria/popover) to surface more information on demand, such as the full error message for a failed action.
<ComponentPreview
styleName="aria-rhea"
name="bubble-popover"
previewClassName="h-auto theme-blue"
/>
## Accessibility
`Bubble` renders the presentational message surface. Keep conversation-level semantics on the surrounding container and follow the guidelines below.
### Labeling Reactions
Reactions render as a row of emoji. A screen reader reads each glyph with no context, and counters like `+8` are announced as "plus eight". Group the row as a single image with a descriptive `aria-label` so it announces once. `role="img"` also hides the individual emoji from assistive tech, so no `aria-hidden` is needed.
```tsx showLineNumbers
<BubbleReactions role="img" aria-label="Reactions: thumbs up, fire, and 8 more">
<span>👍</span>
<span>🔥</span>
<span>+8</span>
</BubbleReactions>
```
When reactions are interactive, render buttons instead and give icon-only buttons an `aria-label`.
```tsx showLineNumbers
<BubbleReactions>
<Button aria-label="Thumbs up" variant="secondary" size="icon-xs">
<ThumbsUpIcon />
</Button>
</BubbleReactions>
```
### Interactive Bubbles
When a bubble is clickable, render it as a real `<button>` or `<a>` with the `render` prop so it is focusable and exposes the correct role. `BubbleContent` ships a visible focus ring for interactive elements, and the accessible name comes from the bubble text. No extra label is needed.
```tsx showLineNumbers
<Bubble variant="muted" align="end">
<BubbleContent
render={(props) => <button {...props} type="button" onClick={onReply} />}
>
I forgot my password
</BubbleContent>
</Bubble>
```
### Meaning Beyond Color
Bubble variants signal role and tone with color. Pair them with text, alignment, or icons so meaning is not conveyed by color alone. For a `destructive` bubble, keep the error context in the message text rather than relying on the color treatment.
## API Reference
### Bubble
The root bubble wrapper.
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------------------------------------------------------ | ----------- | ------------------------------------------------ |
| `variant` | `"default" \| "secondary" \| "muted" \| "tinted" \| "outline" \| "ghost" \| "destructive"` | `"default"` | The bubble visual treatment. |
| `align` | `"start" \| "end"` | `"start"` | The inline alignment of the bubble. |
| `className` | `string` | - | Additional classes to apply to the root element. |
### BubbleContent
The bubble content wrapper.
| Prop | Type | Default | Description |
| ----------- | -------------------------- | ------- | --------------------------------------------------------- |
| `render` | `ReactElement \| function` | - | Render the content as a different element such as a link. |
| `className` | `string` | - | Additional classes to apply to the content element. |
### BubbleReactions
Displays overlapped reactions for a bubble.
| Prop | Type | Default | Description |
| ----------- | ------------------- | ---------- | ------------------------------------------------ |
| `side` | `"top" \| "bottom"` | `"bottom"` | The side of the bubble to anchor the reactions. |
| `align` | `"start" \| "end"` | `"end"` | The inline alignment of the reactions. |
| `className` | `string` | - | Additional classes to apply to the reaction row. |
### BubbleGroup
Groups consecutive bubbles from the same sender.
| Prop | Type | Default | Description |
| ----------- | -------- | ------- | ---------------------------------------------- |
| `className` | `string` | - | Additional classes to apply to the group root. |

View File

@@ -0,0 +1,247 @@
---
title: Button Group
description: A container that groups related buttons together with consistent styling.
base: aria
component: true
---
<ComponentPreview styleName="aria-nova" name="button-group-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add button-group
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install react-aria-components
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="button-group"
title="components/ui/button-group.tsx"
styleName="aria-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import {
ButtonGroup,
ButtonGroupSeparator,
ButtonGroupText,
} from "@/components/ui/button-group"
```
```tsx
<ButtonGroup>
<Button>Button 1</Button>
<Button>Button 2</Button>
</ButtonGroup>
```
## Composition
Use the following composition to build a `ButtonGroup`:
```text
ButtonGroup
├── Button or Input
├── ButtonGroupSeparator
└── ButtonGroupText
```
## Accessibility
- The `ButtonGroup` component has the `role` attribute set to `group`.
- Use <Kbd>Tab</Kbd> to navigate between the buttons in the group.
- Use `aria-label` or `aria-labelledby` to label the button group.
```tsx showLineNumbers
<ButtonGroup aria-label="Button group">
<Button>Button 1</Button>
<Button>Button 2</Button>
</ButtonGroup>
```
## ButtonGroup vs ToggleGroup
- Use the `ButtonGroup` component when you want to group buttons that perform an action.
- Use the `ToggleGroup` component when you want to group buttons that toggle a state.
## Orientation
Set the `orientation` prop to change the button group layout.
<ComponentPreview styleName="aria-nova" name="button-group-orientation" />
## Size
Control the size of buttons using the `size` prop on individual buttons.
<ComponentPreview styleName="aria-nova" name="button-group-size" />
## Nested
Nest `<ButtonGroup>` components to create button groups with spacing.
<ComponentPreview styleName="aria-nova" name="button-group-nested" />
## Separator
The `ButtonGroupSeparator` component visually divides buttons within a group.
Buttons with variant `outline` do not need a separator since they have a border. For other variants, a separator is recommended to improve the visual hierarchy.
<ComponentPreview styleName="aria-nova" name="button-group-separator" />
## Split
Create a split button group by adding two buttons separated by a `ButtonGroupSeparator`.
<ComponentPreview styleName="aria-nova" name="button-group-split" />
## Input
Wrap an `Input` component with buttons.
<ComponentPreview styleName="aria-nova" name="button-group-input" />
## Input Group
Wrap an `InputGroup` component to create complex input layouts.
<ComponentPreview styleName="aria-nova" name="button-group-input-group" />
## Dropdown Menu
Create a split button group with a `DropdownMenu` component.
<ComponentPreview styleName="aria-nova" name="button-group-dropdown" />
## Select
Pair with a `Select` component.
<ComponentPreview styleName="aria-nova" name="button-group-select" />
## Popover
Use with a `Popover` component.
<ComponentPreview styleName="aria-nova" name="button-group-popover" />
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview
styleName="aria-nova"
name="button-group-rtl"
direction="rtl"
/>
## API Reference
### ButtonGroup
The `ButtonGroup` component is a container that groups related buttons together with consistent styling.
| Prop | Type | Default |
| ------------- | ---------------------------- | -------------- |
| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` |
```tsx
<ButtonGroup>
<Button>Button 1</Button>
<Button>Button 2</Button>
</ButtonGroup>
```
Nest multiple button groups to create complex layouts with spacing. See the [nested](#nested) example for more details.
```tsx
<ButtonGroup>
<ButtonGroup />
<ButtonGroup />
</ButtonGroup>
```
### ButtonGroupSeparator
The `ButtonGroupSeparator` component visually divides buttons within a group.
| Prop | Type | Default |
| ------------- | ---------------------------- | ------------ |
| `orientation` | `"horizontal" \| "vertical"` | `"vertical"` |
```tsx
<ButtonGroup>
<Button>Button 1</Button>
<ButtonGroupSeparator />
<Button>Button 2</Button>
</ButtonGroup>
```
### ButtonGroupText
Use this component to display text within a button group.
| Prop | Type | Default |
| -------- | --------- | ------- |
| `render` | `boolean` | `false` |
```tsx
<ButtonGroup>
<ButtonGroupText>Text</ButtonGroupText>
<Button>Button</Button>
</ButtonGroup>
```
Use the `render` prop to render a custom component as the text, for example a label.
```tsx showLineNumbers
import { ButtonGroupText } from "@/components/ui/button-group"
import { Label } from "@/components/ui/label"
export function ButtonGroupTextDemo() {
return (
<ButtonGroup>
<ButtonGroupText
render={(props) => (
<Label {...props} htmlFor="name">
Text
</Label>
)}
/>
<Input placeholder="Type something here..." id="name" />
</ButtonGroup>
)
}
```

View File

@@ -0,0 +1,166 @@
---
title: Button
description: Displays a button or a component that looks like a button.
featured: true
base: aria
component: true
links:
doc: https://react-aria.adobe.com/Button
api: https://react-aria.adobe.com/Button#api
---
<ComponentPreview styleName="aria-nova" name="button-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add button
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install react-aria-components
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="button"
title="components/ui/button.tsx"
styleName="aria-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import { Button } from "@/components/ui/button"
```
```tsx
<Button variant="outline">Button</Button>
```
## Cursor
Tailwind v4 [switched](https://tailwindcss.com/docs/upgrade-guide#buttons-use-the-default-cursor) from `cursor: pointer` to `cursor: default` for the button component.
If you want to keep the `cursor: pointer` behavior, add the following code to your CSS file:
You can also enable this during project setup with `npx shadcn@latest init --pointer`.
```css showLineNumbers title="globals.css"
@layer base {
button:not(:disabled),
[role="button"]:not(:disabled) {
cursor: pointer;
}
}
```
## Size
Use the `size` prop to change the size of the button.
<ComponentPreview styleName="aria-nova" name="button-size" />
## Default
<ComponentPreview styleName="aria-nova" name="button-default" />
## Outline
<ComponentPreview styleName="aria-nova" name="button-outline" />
## Secondary
<ComponentPreview styleName="aria-nova" name="button-secondary" />
## Ghost
<ComponentPreview styleName="aria-nova" name="button-ghost" />
## Destructive
<ComponentPreview styleName="aria-nova" name="button-destructive" />
## Link
<ComponentPreview styleName="aria-nova" name="button-link" />
## Icon
<ComponentPreview styleName="aria-nova" name="button-icon" />
## With Icon
Remember to add the `data-icon="inline-start"` or `data-icon="inline-end"` attribute to the icon for the correct spacing.
<ComponentPreview styleName="aria-nova" name="button-with-icon" />
## Rounded
Use the `rounded-full` class to make the button rounded.
<ComponentPreview styleName="aria-nova" name="button-rounded" />
## Spinner
Render a `<Spinner />` component inside the button to show a loading state. Remember to add the `data-icon="inline-start"` or `data-icon="inline-end"` attribute to the spinner for the correct spacing.
<ComponentPreview styleName="aria-nova" name="button-spinner" />
## Button Group
To create a button group, use the `ButtonGroup` component. See the [Button Group](/docs/components/aria/button-group) documentation for more details.
<ComponentPreview styleName="aria-nova" name="button-group-demo" />
## As Link
You can use the `buttonVariants` helper to make a link look like a button.
**Do not use `<Button>` for links.** The React Aria `Button` component always applies `role="button"`, which overrides the semantic link role on `<a>` elements. Use `buttonVariants` with a plain `<a>` tag instead.
<ComponentPreview styleName="aria-nova" name="button-render" />
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview styleName="aria-nova" name="button-rtl" direction="rtl" />
## API Reference
### Button
The `Button` component is a wrapper around the `button` element that adds a variety of styles and functionality.
| Prop | Type | Default |
| --------- | ------------------------------------------------------------------------------------ | ----------- |
| `variant` | `"default" \| "outline" \| "ghost" \| "destructive" \| "secondary" \| "link"` | `"default"` |
| `size` | `"default" \| "xs" \| "sm" \| "lg" \| "icon" \| "icon-xs" \| "icon-sm" \| "icon-lg"` | `"default"` |
See the [React Aria](https://react-aria.adobe.com/Button#api) documentation for more information.

View File

@@ -0,0 +1,202 @@
---
title: Calendar
description: A calendar component that allows users to select a date or a range of dates.
base: aria
component: true
links:
doc: https://react-aria.adobe.com/Calendar
api: https://react-aria.adobe.com/Calendar#api
---
<ComponentPreview
styleName="aria-nova"
name="calendar-demo"
previewClassName="h-96"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add calendar
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install react-aria-components @internationalized/date
```
<Step>Add the `Button` component to your project.</Step>
The `Calendar` component uses the `Button` component. Make sure you have it installed in your project.
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="calendar"
title="components/ui/calendar.tsx"
styleName="aria-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
getLocalTimeZone,
today,
type CalendarDate,
} from "@internationalized/date"
import { Calendar } from "@/components/ui/calendar"
```
```tsx showLineNumbers
const [date, setDate] = React.useState<CalendarDate | null>(
today(getLocalTimeZone())
)
return (
<Calendar value={date} onChange={setDate} className="rounded-lg border" />
)
```
See the [React Aria](https://react-aria.adobe.com/Calendar) documentation for more information.
## Date Picker
You can use the `<Calendar>` component to build a date picker. See the [Date Picker](/docs/components/aria/date-picker) page for more information.
## International Calendars
To use international calendar systems such as Persian, Islamic, or Buddhist, use React Aria's `I18nProvider` to set the locale.
<ComponentPreview
styleName="aria-nova"
name="calendar-hijri"
title="Persian / Hijri / Jalali Calendar"
description="A Persian calendar."
previewClassName="h-[400px]"
/>
## Basic
A basic calendar component. We used `className="rounded-lg border"` to style the calendar.
<ComponentPreview
styleName="aria-nova"
name="calendar-basic"
previewClassName="h-96"
/>
## Range Calendar
Use the `RangeCalendar` component to enable range selection.
<ComponentPreview
styleName="aria-nova"
name="calendar-range"
previewClassName="h-[36rem] md:h-96"
/>
## Month and Year Selector
Use `captionLayout="dropdown"` to show month and year dropdowns.
<ComponentPreview
styleName="aria-nova"
name="calendar-caption"
previewClassName="h-96"
/>
## Presets
<ComponentPreview
styleName="aria-nova"
name="calendar-presets"
previewClassName="h-[650px]"
/>
## Date and Time Picker
<ComponentPreview
styleName="aria-nova"
name="calendar-time"
previewClassName="h-[600px]"
/>
## Booked dates
<ComponentPreview
styleName="aria-nova"
name="calendar-booked-dates"
previewClassName="h-96"
/>
## Custom Cell Size
<ComponentPreview
styleName="aria-nova"
name="calendar-custom-days"
title="Custom Cell Size"
description="A calendar with custom cell size that's responsive."
className="**:[.preview]:h-[560px]"
/>
You can customize the size of calendar cells using the `--cell-size` CSS variable. You can also make it responsive by using breakpoint-specific values:
```tsx showLineNumbers
<Calendar
value={date}
onChange={setDate}
className="rounded-lg border [--cell-size:--spacing(11)] md:[--cell-size:--spacing(12)]"
/>
```
Or use fixed values:
```tsx showLineNumbers
<Calendar
value={date}
onChange={setDate}
className="rounded-lg border [--cell-size:2.75rem] md:[--cell-size:3rem]"
/>
```
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
See also the [International Calendars Guide](#international-calendars) for enabling the international calendars such as Persian / Hijri / Jalali.
<ComponentPreview
styleName="aria-nova"
name="calendar-rtl"
direction="rtl"
previewClassName="h-96"
/>
## API Reference
See the [React Aria](https://react-aria.adobe.com/Calendar) documentation for more information on the `Calendar` component.

View File

@@ -0,0 +1,267 @@
---
title: Card
description: Displays a card with header, content, and footer.
base: aria
component: true
---
<ComponentPreview
name="card-demo"
styleName="aria-nova"
previewClassName="h-[30rem]"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add card
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="card"
title="components/ui/card.tsx"
styleName="aria-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Card,
CardAction,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card"
```
```tsx showLineNumbers
<Card>
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card Description</CardDescription>
<CardAction>Card Action</CardAction>
</CardHeader>
<CardContent>
<p>Card Content</p>
</CardContent>
<CardFooter>
<p>Card Footer</p>
</CardFooter>
</Card>
```
## Composition
Use the following composition to build a `Card`:
```text
Card
├── CardHeader
│ ├── CardTitle
│ ├── CardDescription
│ └── CardAction
├── CardContent
└── CardFooter
```
## Size
Use the `size="sm"` prop to set the size of the card to small. The small size variant uses smaller spacing.
<ComponentPreview
styleName="aria-nova"
name="card-small"
previewClassName="h-96"
/>
## Spacing
In addition to the `size` prop, you can use the `--card-spacing` CSS variable to control the spacing between sections and the inset of card parts.
<ComponentPreview
styleName="aria-nova"
name="card-spacing"
previewClassName="h-[34rem]"
/>
Use negative margins with `-mx-(--card-spacing)` to make content go edge to edge while keeping it aligned with the card inset. When the edge-to-edge content sits above a footer, use `-mb-(--card-spacing)` on `CardContent` to remove the section gap.
<ComponentPreview
styleName="aria-nova"
name="card-edge-to-edge"
previewClassName="h-[24rem]"
/>
## Image
Add an image before the card header to create a card with an image.
<ComponentPreview
styleName="aria-nova"
name="card-image"
previewClassName="h-[32rem]"
/>
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview
styleName="aria-nova"
name="card-rtl"
direction="rtl"
previewClassName="h-[30rem]"
/>
## API Reference
### Card
The `Card` component is the root container for card content.
| Prop | Type | Default |
| ----------- | ------------------- | ----------- |
| `size` | `"default" \| "sm"` | `"default"` |
| `className` | `string` | - |
### CardHeader
The `CardHeader` component is used for a title, description, and optional action.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### CardTitle
The `CardTitle` component is used for the card title.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### CardDescription
The `CardDescription` component is used for helper text under the title.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### CardAction
The `CardAction` component places content in the top-right of the header (for example, a button or a badge).
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### CardContent
The `CardContent` component is used for the main card body.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### CardFooter
The `CardFooter` component is used for actions and secondary content at the bottom of the card.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
## Changelog
### Spacing Variable
If you're upgrading from a previous version of the `Card` component, you'll need to apply the following updates to use the `--card-spacing` variable:
<Steps>
<Step>Update the Card root spacing classes.</Step>
Replace the hard-coded gap and vertical padding with `--card-spacing`, and set the default and small size values on the root:
```diff
className={cn(
- "group/card flex flex-col gap-4 overflow-hidden rounded-xl bg-card py-4 text-sm text-card-foreground ring-1 ring-foreground/10 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
+ "group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
className
)}
```
<Step>Update CardHeader spacing classes.</Step>
Replace the horizontal padding and border spacing with the shared variable:
```diff
className={cn(
- "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3",
+ "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)",
className
)}
```
<Step>Update CardContent and CardFooter spacing classes.</Step>
Use `--card-spacing` for the content inset and footer padding:
```diff
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-content"
- className={cn("px-4 group-data-[size=sm]/card:px-3", className)}
+ className={cn("px-(--card-spacing)", className)}
{...props}
/>
)
}
```
```diff
className={cn(
- "flex items-center rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/card:p-3",
+ "flex items-center rounded-b-xl border-t bg-muted/50 p-(--card-spacing)",
className
)}
```
</Steps>
After applying these changes, you can customize card spacing by setting `--card-spacing` on the `Card` with an arbitrary property class:
```tsx
function Example() {
return <Card className="[--card-spacing:--spacing(6)]">...</Card>
}
```

View File

@@ -0,0 +1,333 @@
---
title: Carousel
description: A carousel with motion and swipe built using Embla.
base: aria
component: true
links:
doc: https://www.embla-carousel.com/docs/get-started/react
api: https://www.embla-carousel.com/docs/api
---
<ComponentPreview
styleName="aria-nova"
name="carousel-demo"
previewClassName="h-80 sm:h-[32rem]"
/>
## About
The carousel component is built using the [Embla Carousel](https://www.embla-carousel.com/) library.
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add carousel
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install embla-carousel-react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="carousel"
title="components/ui/carousel.tsx"
styleName="aria-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@/components/ui/carousel"
```
```tsx showLineNumbers
<Carousel>
<CarouselContent>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
```
## Composition
Use the following composition to build a `Carousel`:
```text
Carousel
├── CarouselContent
│ ├── CarouselItem
│ └── CarouselItem
├── CarouselPrevious
└── CarouselNext
```
## Sizes
To set the size of the items, you can use the `basis` utility class on the `<CarouselItem />`.
<ComponentPreview styleName="aria-nova" name="carousel-size" />
```tsx showLineNumbers {4-6}
// 33% of the carousel width.
<Carousel>
<CarouselContent>
<CarouselItem className="basis-1/3">...</CarouselItem>
<CarouselItem className="basis-1/3">...</CarouselItem>
<CarouselItem className="basis-1/3">...</CarouselItem>
</CarouselContent>
</Carousel>
```
```tsx showLineNumbers {4-6}
// 50% on small screens and 33% on larger screens.
<Carousel>
<CarouselContent>
<CarouselItem className="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
<CarouselItem className="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
<CarouselItem className="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
</CarouselContent>
</Carousel>
```
## Spacing
To set the spacing between the items, we use a `pl-[VALUE]` utility on the `<CarouselItem />` and a negative `-ml-[VALUE]` on the `<CarouselContent />`.
<ComponentPreview styleName="aria-nova" name="carousel-spacing" />
```tsx showLineNumbers /-ml-4/ /pl-4/
<Carousel>
<CarouselContent className="-ml-4">
<CarouselItem className="pl-4">...</CarouselItem>
<CarouselItem className="pl-4">...</CarouselItem>
<CarouselItem className="pl-4">...</CarouselItem>
</CarouselContent>
</Carousel>
```
```tsx showLineNumbers /-ml-2/ /pl-2/ /md:-ml-4/ /md:pl-4/
<Carousel>
<CarouselContent className="-ml-2 md:-ml-4">
<CarouselItem className="pl-2 md:pl-4">...</CarouselItem>
<CarouselItem className="pl-2 md:pl-4">...</CarouselItem>
<CarouselItem className="pl-2 md:pl-4">...</CarouselItem>
</CarouselContent>
</Carousel>
```
## Orientation
Use the `orientation` prop to set the orientation of the carousel.
<ComponentPreview
styleName="aria-nova"
name="carousel-orientation"
previewClassName="h-[32rem]"
/>
```tsx showLineNumbers /vertical | horizontal/
<Carousel orientation="vertical | horizontal">
<CarouselContent>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
</CarouselContent>
</Carousel>
```
## Options
You can pass options to the carousel using the `opts` prop. See the [Embla Carousel docs](https://www.embla-carousel.com/docs/api/options) for more information.
```tsx showLineNumbers {2-5}
<Carousel
opts={{
align: "start",
loop: true,
}}
>
<CarouselContent>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
</CarouselContent>
</Carousel>
```
## API
Use a state and the `setApi` props to get an instance of the carousel API.
<ComponentPreview
styleName="aria-nova"
name="carousel-api"
previewClassName="sm:h-[32rem]"
/>
```tsx showLineNumbers {1,4,22}
import { type CarouselApi } from "@/components/ui/carousel"
export function Example() {
const [api, setApi] = React.useState<CarouselApi>()
const [current, setCurrent] = React.useState(0)
const [count, setCount] = React.useState(0)
React.useEffect(() => {
if (!api) {
return
}
setCount(api.scrollSnapList().length)
setCurrent(api.selectedScrollSnap() + 1)
api.on("select", () => {
setCurrent(api.selectedScrollSnap() + 1)
})
}, [api])
return (
<Carousel setApi={setApi}>
<CarouselContent>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
</CarouselContent>
</Carousel>
)
}
```
## Events
You can listen to events using the api instance from `setApi`.
```tsx showLineNumbers {1,4-14,16}
import { type CarouselApi } from "@/components/ui/carousel"
export function Example() {
const [api, setApi] = React.useState<CarouselApi>()
React.useEffect(() => {
if (!api) {
return
}
api.on("select", () => {
// Do something on select.
})
}, [api])
return (
<Carousel setApi={setApi}>
<CarouselContent>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
</CarouselContent>
</Carousel>
)
}
```
See the [Embla Carousel docs](https://www.embla-carousel.com/docs/api/events) for more information on using events.
## Plugins
You can use the `plugins` prop to add plugins to the carousel.
```ts showLineNumbers {1,6-10}
import Autoplay from "embla-carousel-autoplay"
export function Example() {
return (
<Carousel
plugins={[
Autoplay({
delay: 2000,
}),
]}
>
// ...
</Carousel>
)
}
```
<ComponentPreview
styleName="aria-nova"
name="carousel-plugin"
previewClassName="sm:h-[32rem]"
/>
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview
styleName="aria-nova"
name="carousel-rtl"
direction="rtl"
previewClassName="h-80 sm:h-[32rem]"
/>
When localizing the carousel for RTL languages, you need to set the `direction` option in the `opts` prop to match the text direction. This ensures the carousel scrolls in the correct direction.
```tsx showLineNumbers {2-5}
<Carousel
dir={dir}
opts={{
direction: dir,
}}
>
<CarouselContent>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
</CarouselContent>
<CarouselPrevious className="rtl:rotate-180" />
<CarouselNext className="rtl:rotate-180" />
</Carousel>
```
The `direction` option accepts `"ltr"` or `"rtl"` and should match the `dir` prop value. You may also want to rotate the navigation buttons using the `rtl:rotate-180` class to ensure they point in the correct direction.
## API Reference
See the [Embla Carousel docs](https://www.embla-carousel.com/docs/api/plugins) for more information on props and plugins.

View File

@@ -0,0 +1,593 @@
---
title: Chart
description: Beautiful charts. Built using Recharts. Copy and paste into your apps.
base: aria
component: true
---
<Callout>
**Note:** We're working on upgrading to Recharts v3. In the meantime, if you'd like to start testing v3, see the code in the comment [here](https://github.com/shadcn-ui/ui/issues/7669#issuecomment-2998299159). We'll have an official release soon.
</Callout>
<ComponentPreview
styleName="aria-nova"
name="chart-demo"
className="theme-blue [&_.preview]:h-auto [&_.preview]:p-0 [&_.preview]:lg:min-h-[404px] [&_.preview>div]:w-full [&_.preview>div]:border-none [&_.preview>div]:shadow-none"
hideCode
/>
Introducing **Charts**. A collection of chart components that you can copy and paste into your apps.
Charts are designed to look great out of the box. They work well with the other components and are fully customizable to fit your project.
[Browse the Charts Library](/charts).
## Component
We use [Recharts](https://recharts.org/) under the hood.
We designed the `chart` component with composition in mind. **You build your charts using Recharts components and only bring in custom components, such as `ChartTooltip`, when and where you need it**.
```tsx showLineNumbers /ChartContainer/ /ChartTooltipContent/
import { Bar, BarChart } from "recharts"
import { ChartContainer, ChartTooltipContent } from "@/components/ui/chart"
export function MyChart() {
return (
<ChartContainer>
<BarChart data={data}>
<Bar dataKey="value" />
<ChartTooltip content={<ChartTooltipContent />} />
</BarChart>
</ChartContainer>
)
}
```
We do not wrap Recharts. This means you're not locked into an abstraction. When a new Recharts version is released, you can follow the official upgrade path to upgrade your charts.
**The components are yours**.
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add chart
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install recharts
```
<Step>Copy and paste the following code into `components/ui/chart.tsx`.</Step>
<ComponentSource
name="chart"
title="components/ui/chart.tsx"
styleName="aria-nova"
/>
<Step>Add the following colors to your CSS file</Step>
```css title="app/globals.css" showLineNumbers
@layer base {
:root {
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
}
.dark {
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
}
}
```
</Steps>
</TabsContent>
</CodeTabs>
## Your First Chart
Let's build your first chart. We'll build a bar chart, add a grid, axis, tooltip and legend.
<Steps>
<Step>Start by defining your data</Step>
The following data represents the number of desktop and mobile users for each month.
<Callout className="mt-4">
**Note:** Your data can be in any shape. You are not limited to the shape of the data below. Use the `dataKey` prop to map your data to the chart.
</Callout>
```tsx title="components/example-chart.tsx" showLineNumbers
const chartData = [
{ month: "January", desktop: 186, mobile: 80 },
{ month: "February", desktop: 305, mobile: 200 },
{ month: "March", desktop: 237, mobile: 120 },
{ month: "April", desktop: 73, mobile: 190 },
{ month: "May", desktop: 209, mobile: 130 },
{ month: "June", desktop: 214, mobile: 140 },
]
```
<Step>Define your chart config</Step>
The chart config holds configuration for the chart. This is where you place human-readable strings, such as labels, icons and color tokens for theming.
```tsx title="components/example-chart.tsx" showLineNumbers
import { type ChartConfig } from "@/components/ui/chart"
const chartConfig = {
desktop: {
label: "Desktop",
color: "#2563eb",
},
mobile: {
label: "Mobile",
color: "#60a5fa",
},
} satisfies ChartConfig
```
<Step>Build your chart</Step>
You can now build your chart using Recharts components.
<Callout className="mt-4 bg-amber-50 border-amber-200 dark:bg-amber-950/50 dark:border-amber-950">
**Important:** Remember to set a `min-h-[VALUE]` on the `ChartContainer` component. This is required for the chart to be responsive.
</Callout>
<ComponentPreview
styleName="aria-nova"
name="chart-example"
previewClassName="h-80"
/>
</Steps>
### Add a Grid
Let's add a grid to the chart.
<Steps className="mb-0 pt-2">
<Step>Import the `CartesianGrid` component.</Step>
```tsx /CartesianGrid/
import { Bar, BarChart, CartesianGrid } from "recharts"
```
<Step>Add the `CartesianGrid` component to your chart.</Step>
```tsx showLineNumbers {3}
<ChartContainer config={chartConfig} className="min-h-[200px] w-full">
<BarChart accessibilityLayer data={chartData}>
<CartesianGrid vertical={false} />
<Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
<Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
</BarChart>
</ChartContainer>
```
<ComponentPreview
styleName="aria-nova"
name="chart-example-grid"
previewClassName="h-80"
/>
</Steps>
### Add an Axis
To add an x-axis to the chart, we'll use the `XAxis` component.
<Steps className="mb-0 pt-2">
<Step>Import the `XAxis` component.</Step>
```tsx /XAxis/
import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"
```
<Step>Add the `XAxis` component to your chart.</Step>
```tsx showLineNumbers {4-10}
<ChartContainer config={chartConfig} className="h-[200px] w-full">
<BarChart accessibilityLayer data={chartData}>
<CartesianGrid vertical={false} />
<XAxis
dataKey="month"
tickLine={false}
tickMargin={10}
axisLine={false}
tickFormatter={(value) => value.slice(0, 3)}
/>
<Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
<Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
</BarChart>
</ChartContainer>
```
<ComponentPreview
styleName="aria-nova"
name="chart-example-axis"
previewClassName="h-80"
/>
</Steps>
### Add Tooltip
So far we've only used components from Recharts. They look great out of the box thanks to some customization in the `chart` component.
To add a tooltip, we'll use the custom `ChartTooltip` and `ChartTooltipContent` components from `chart`.
<Steps className="mb-0 pt-2">
<Step>Import the `ChartTooltip` and `ChartTooltipContent` components.</Step>
```tsx
import { ChartTooltip, ChartTooltipContent } from "@/components/ui/chart"
```
<Step>Add the components to your chart.</Step>
```tsx showLineNumbers {11}
<ChartContainer config={chartConfig} className="h-[200px] w-full">
<BarChart accessibilityLayer data={chartData}>
<CartesianGrid vertical={false} />
<XAxis
dataKey="month"
tickLine={false}
tickMargin={10}
axisLine={false}
tickFormatter={(value) => value.slice(0, 3)}
/>
<ChartTooltip content={<ChartTooltipContent />} />
<Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
<Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
</BarChart>
</ChartContainer>
```
<ComponentPreview
styleName="aria-nova"
name="chart-example-tooltip"
previewClassName="h-80"
/>
Hover to see the tooltips. Easy, right? Two components, and we've got a beautiful tooltip.
</Steps>
### Add Legend
We'll do the same for the legend. We'll use the `ChartLegend` and `ChartLegendContent` components from `chart`.
<Steps className="mb-0 pt-2">
<Step>Import the `ChartLegend` and `ChartLegendContent` components.</Step>
```tsx
import { ChartLegend, ChartLegendContent } from "@/components/ui/chart"
```
<Step>Add the components to your chart.</Step>
```tsx showLineNumbers {12}
<ChartContainer config={chartConfig} className="h-[200px] w-full">
<BarChart accessibilityLayer data={chartData}>
<CartesianGrid vertical={false} />
<XAxis
dataKey="month"
tickLine={false}
tickMargin={10}
axisLine={false}
tickFormatter={(value) => value.slice(0, 3)}
/>
<ChartTooltip content={<ChartTooltipContent />} />
<ChartLegend content={<ChartLegendContent />} />
<Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
<Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
</BarChart>
</ChartContainer>
```
<ComponentPreview
styleName="aria-nova"
name="chart-example-legend"
previewClassName="h-80"
/>
</Steps>
Done. You've built your first chart! What's next?
- [Themes and Colors](/docs/components/aria/chart#theming)
- [Tooltip](/docs/components/aria/chart#tooltip)
- [Legend](/docs/components/aria/chart#legend)
## Chart Config
The chart config is where you define the labels, icons and colors for a chart.
It is intentionally decoupled from chart data.
This allows you to share config and color tokens between charts. It can also work independently for cases where your data or color tokens live remotely or in a different format.
```tsx showLineNumbers /ChartConfig/
import { Monitor } from "lucide-react"
import { type ChartConfig } from "@/components/ui/chart"
const chartConfig = {
desktop: {
label: "Desktop",
icon: Monitor,
// A color like 'hsl(220, 98%, 61%)' or 'var(--color-name)'
color: "#2563eb",
// OR a theme object with 'light' and 'dark' keys
theme: {
light: "#2563eb",
dark: "#dc2626",
},
},
} satisfies ChartConfig
```
## Theming
Charts have built-in support for theming. You can use css variables (recommended) or color values in any color format, such as hex, hsl or oklch.
### CSS Variables
<Steps className="mb-0 pt-2">
<Step>Define your colors in your css file</Step>
```css title="app/globals.css" showLineNumbers
@layer base {
:root {
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
}
.dark: {
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
}
}
```
<Step>Add the color to your `chartConfig`</Step>
```tsx title="components/example-chart.tsx" showLineNumbers
const chartConfig = {
desktop: {
label: "Desktop",
color: "var(--chart-1)",
},
mobile: {
label: "Mobile",
color: "var(--chart-2)",
},
} satisfies ChartConfig
```
</Steps>
### hex, hsl or oklch
You can also define your colors directly in the chart config. Use the color format you prefer.
```tsx title="components/example-chart.tsx" showLineNumbers
const chartConfig = {
desktop: {
label: "Desktop",
color: "#2563eb",
},
mobile: {
label: "Mobile",
color: "hsl(220, 98%, 61%)",
},
tablet: {
label: "Tablet",
color: "oklch(0.5 0.2 240)",
},
laptop: {
label: "Laptop",
color: "var(--chart-2)",
},
} satisfies ChartConfig
```
### Using Colors
To use the theme colors in your chart, reference the colors using the format `var(--color-KEY)`.
#### Components
```tsx
<Bar dataKey="desktop" fill="var(--color-desktop)" />
```
#### Chart Data
```tsx title="components/example-chart.tsx" showLineNumbers
const chartData = [
{ browser: "chrome", visitors: 275, fill: "var(--color-chrome)" },
{ browser: "safari", visitors: 200, fill: "var(--color-safari)" },
]
```
#### Tailwind
```tsx title="components/example-chart.tsx"
<LabelList className="fill-[--color-desktop]" />
```
## Tooltip
A chart tooltip contains a label, name, indicator and value. You can use a combination of these to customize your tooltip.
<ComponentPreview styleName="aria-nova" name="chart-tooltip" hideCode />
You can turn on/off any of these using the `hideLabel`, `hideIndicator` props and customize the indicator style using the `indicator` prop.
Use `labelKey` and `nameKey` to use a custom key for the tooltip label and name.
Chart comes with the `<ChartTooltip>` and `<ChartTooltipContent>` components. You can use these two components to add custom tooltips to your chart.
```tsx title="components/example-chart.tsx"
import { ChartTooltip, ChartTooltipContent } from "@/components/ui/chart"
```
```tsx title="components/example-chart.tsx"
<ChartTooltip content={<ChartTooltipContent />} />
```
### Props
Use the following props to customize the tooltip.
| Prop | Type | Description |
| :-------------- | :----------------------- | :------------------------------------------- |
| `labelKey` | string | The config or data key to use for the label. |
| `nameKey` | string | The config or data key to use for the name. |
| `indicator` | `dot` `line` or `dashed` | The indicator style for the tooltip. |
| `hideLabel` | boolean | Whether to hide the label. |
| `hideIndicator` | boolean | Whether to hide the indicator. |
### Colors
Colors are automatically referenced from the chart config.
### Custom
To use a custom key for tooltip label and names, use the `labelKey` and `nameKey` props.
```tsx showLineNumbers /browser/
const chartData = [
{ browser: "chrome", visitors: 187, fill: "var(--color-chrome)" },
{ browser: "safari", visitors: 200, fill: "var(--color-safari)" },
]
const chartConfig = {
visitors: {
label: "Total Visitors",
},
chrome: {
label: "Chrome",
color: "var(--chart-1)",
},
safari: {
label: "Safari",
color: "var(--chart-2)",
},
} satisfies ChartConfig
```
```tsx title="components/example-chart.tsx"
<ChartTooltip
content={<ChartTooltipContent labelKey="visitors" nameKey="browser" />}
/>
```
This will use `Total Visitors` for label and `Chrome` and `Safari` for the tooltip names.
## Legend
You can use the custom `<ChartLegend>` and `<ChartLegendContent>` components to add a legend to your chart.
```tsx title="components/example-chart.tsx"
import { ChartLegend, ChartLegendContent } from "@/components/ui/chart"
```
```tsx title="components/example-chart.tsx"
<ChartLegend content={<ChartLegendContent />} />
```
### Colors
Colors are automatically referenced from the chart config.
### Custom
To use a custom key for legend names, use the `nameKey` prop.
```tsx showLineNumbers /browser/
const chartData = [
{ browser: "chrome", visitors: 187, fill: "var(--color-chrome)" },
{ browser: "safari", visitors: 200, fill: "var(--color-safari)" },
]
const chartConfig = {
chrome: {
label: "Chrome",
color: "var(--chart-1)",
},
safari: {
label: "Safari",
color: "var(--chart-2)",
},
} satisfies ChartConfig
```
```tsx title="components/example-chart.tsx"
<ChartLegend content={<ChartLegendContent nameKey="browser" />} />
```
This will use `Chrome` and `Safari` for the legend names.
## Accessibility
You can turn on the `accessibilityLayer` prop to add an accessible layer to your chart.
This prop adds keyboard access and screen reader support to your charts.
```tsx title="components/example-chart.tsx"
<LineChart accessibilityLayer />
```
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview
styleName="aria-nova"
name="chart-rtl"
direction="rtl"
previewClassName="h-92"
/>

View File

@@ -0,0 +1,136 @@
---
title: Checkbox
description: A control that allows the user to toggle between checked and not checked.
base: aria
component: true
links:
doc: https://react-aria.adobe.com/Checkbox
api: https://react-aria.adobe.com/Checkbox#api
---
<ComponentPreview
styleName="aria-nova"
name="checkbox-demo"
previewClassName="h-80"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add checkbox
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install react-aria-components
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="checkbox"
title="components/ui/checkbox.tsx"
styleName="aria-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import { Checkbox } from "@/components/ui/checkbox"
```
```tsx
<Checkbox />
```
## Checked State
Use `defaultSelected` for uncontrolled checkboxes, or `isSelected` and
`onChange` to control the state.
```tsx showLineNumbers
import * as React from "react"
export function Example() {
const [checked, setChecked] = React.useState(false)
return <Checkbox isSelected={checked} onChange={setChecked} />
}
```
## Invalid State
Set `isInvalid` on the checkbox and `data-invalid` on the field wrapper to
show the invalid styles.
<ComponentPreview styleName="aria-nova" name="checkbox-invalid" />
## Basic
Pair the checkbox with `Field` and `FieldLabel` for proper layout and labeling.
<ComponentPreview styleName="aria-nova" name="checkbox-basic" />
## Description
Use `FieldContent` and `FieldDescription` for helper text.
<ComponentPreview styleName="aria-nova" name="checkbox-description" />
## Disabled
Use the `isDisabled` prop to prevent interaction and add the `data-disabled` attribute to the `<Field>` component for disabled styles.
<ComponentPreview styleName="aria-nova" name="checkbox-disabled" />
## Group
Use multiple fields to create a checkbox list.
<ComponentPreview styleName="aria-nova" name="checkbox-group" />
## Table
<ComponentPreview
styleName="aria-nova"
name="checkbox-table"
previewClassName="p-4 md:p-8"
/>
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview
styleName="aria-nova"
name="checkbox-rtl"
direction="rtl"
previewClassName="h-80"
/>
## API Reference
See the [React Aria](https://react-aria.adobe.com/Checkbox#api) documentation for more information.

View File

@@ -0,0 +1,142 @@
---
title: Collapsible
description: An interactive component which expands/collapses a panel.
base: aria
component: true
featured: true
links:
doc: https://react-aria.adobe.com/Disclosure
api: https://react-aria.adobe.com/Disclosure#api
---
<ComponentPreview styleName="aria-nova" name="collapsible-demo" align="start" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add collapsible
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install react-aria-components
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="collapsible"
title="components/ui/collapsible.tsx"
styleName="aria-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible"
```
```tsx showLineNumbers
<Collapsible>
<CollapsibleTrigger>Can I use this in my project?</CollapsibleTrigger>
<CollapsibleContent>
Yes. Free to use for personal and commercial projects. No attribution
required.
</CollapsibleContent>
</Collapsible>
```
## Composition
Use the following composition to build a `Collapsible`:
```text
Collapsible
├── CollapsibleTrigger
└── CollapsibleContent
```
## Controlled State
Use the `isExpanded` and `onExpandedChange` props to control the state.
```tsx showLineNumbers
import * as React from "react"
export function Example() {
const [open, setOpen] = React.useState(false)
return (
<Collapsible isExpanded={open} onExpandedChange={setOpen}>
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
<CollapsibleContent>Content</CollapsibleContent>
</Collapsible>
)
}
```
## Basic
<ComponentPreview
styleName="aria-nova"
name="collapsible-basic"
align="start"
/>
## Settings Panel
Use a trigger button to reveal additional settings.
<ComponentPreview styleName="aria-nova" name="collapsible-settings" />
## File Tree
Use nested collapsibles to build a file tree.
<ComponentPreview
styleName="aria-nova"
name="collapsible-file-tree"
previewClassName="h-[36rem]"
/>
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview
styleName="aria-nova"
name="collapsible-rtl"
direction="rtl"
align="start"
/>
## API Reference
See the [React Aria](https://react-aria.adobe.com/Disclosure#api) documentation for more information.

View File

@@ -0,0 +1,314 @@
---
title: Combobox
description: Autocomplete input with a list of suggestions.
base: aria
component: true
links:
doc: https://react-aria.adobe.com/ComboBox
api: https://react-aria.adobe.com/ComboBox#api
---
<ComponentPreview
styleName="aria-nova"
name="combobox-demo"
description="A combobox with a list of frameworks."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add combobox
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install react-aria-components
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="combobox"
title="components/ui/combobox.tsx"
styleName="aria-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from "@/components/ui/combobox"
```
```tsx showLineNumbers
const frameworks = ["Next.js", "SvelteKit", "Nuxt.js", "Remix", "Astro"]
export function ExampleCombobox() {
return (
<Combobox allowsEmptyCollection>
<ComboboxInput placeholder="Select a framework" />
<ComboboxContent>
<ComboboxList
renderEmptyState={() => (
<ComboboxEmpty>No items found.</ComboboxEmpty>
)}
>
{frameworks.map((item) => (
<ComboboxItem key={item} id={item}>
{item}
</ComboboxItem>
))}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}
```
## Composition
### Simple
A single-line input and a flat list (see [Basic](#basic)).
```text
Combobox
├── ComboboxInput
└── ComboboxContent
└── ComboboxList
├── ComboboxItem
└── ComboboxItem
```
### With chips
Multi-select with `multiple`, chips, and a chips input (see [Multiple](#multiple)).
```text
Combobox
├── ComboboxChips
│ ├── ComboboxChipList
│ │ └── ComboboxChip
│ └── ComboboxChipsInput
└── ComboboxContent
└── ComboboxList
├── ComboboxItem
└── ComboboxItem
```
### With groups and collection
Nested items per group using `ComboboxGroup`, with a separator between groups (see [Groups](#groups)).
```text
Combobox
├── ComboboxInput
└── ComboboxContent
└── ComboboxList
├── ComboboxGroup
│ ├── ComboboxLabel
│ ├── ComboboxItem
│ └── ComboboxItem
├── ComboboxSeparator
└── ComboboxGroup
├── ComboboxLabel
├── ComboboxItem
└── ComboboxItem
```
## Custom Items
Use `textValue` when your items render JSX children.
```tsx showLineNumbers
import * as React from "react"
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from "@/components/ui/combobox"
type Framework = {
label: string
value: string
}
const frameworks: Framework[] = [
{ label: "Next.js", value: "next" },
{ label: "SvelteKit", value: "sveltekit" },
{ label: "Nuxt", value: "nuxt" },
]
export function ExampleComboboxCustomItems() {
return (
<Combobox allowsEmptyCollection>
<ComboboxInput placeholder="Select a framework" />
<ComboboxContent>
<ComboboxList
renderEmptyState={() => (
<ComboboxEmpty>No items found.</ComboboxEmpty>
)}
items={frameworks}
>
{(framework) => (
<ComboboxItem id={framework.value} textValue={framework.label}>
<span>{framework.label}</span>
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}
```
## Multiple Selection
Use `multiple` with chips for multi-select behavior.
```tsx showLineNumbers
import * as React from "react"
import {
Combobox,
ComboboxChip,
ComboboxChipList,
ComboboxChips,
ComboboxChipsInput,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from "@/components/ui/combobox"
const frameworks = ["Next.js", "SvelteKit", "Nuxt.js", "Remix", "Astro"]
export function ExampleComboboxMultiple() {
const [value, setValue] = React.useState<string[]>([])
return (
<Combobox
selectionMode="multiple"
value={value}
onChange={setValue}
allowsEmptyCollection
>
<ComboboxChips>
<ComboboxChipList<{ name: string }>>
{(value) => <ComboboxChip id={value.name}>{value.name}</ComboboxChip>}
</ComboboxChipList>
<ComboboxChipsInput placeholder="Add framework" />
</ComboboxChips>
<ComboboxContent>
<ComboboxList
renderEmptyState={() => (
<ComboboxEmpty>No items found.</ComboboxEmpty>
)}
>
{frameworks.map((item) => (
<ComboboxItem key={item} id={item}>
{item}
</ComboboxItem>
))}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}
```
## Basic
A simple combobox with a list of frameworks.
<ComponentPreview styleName="aria-nova" name="combobox-basic" />
## Multiple
A combobox with multiple selection using `multiple` and `ComboboxChips`.
<ComponentPreview styleName="aria-nova" name="combobox-multiple" />
## Clear Button
Use the `showClear` prop to show a clear button.
<ComponentPreview styleName="aria-nova" name="combobox-clear" />
## Groups
Use `ComboboxGroup` and `ComboboxSeparator` to group items.
<ComponentPreview styleName="aria-nova" name="combobox-groups" />
## Custom Items
You can render custom component inside `ComboboxItem`.
<ComponentPreview styleName="aria-nova" name="combobox-custom" />
## Invalid
Use the `isInvalid` prop to make the combobox invalid.
<ComponentPreview styleName="aria-nova" name="combobox-invalid" />
## Disabled
Use the `isDisabled` prop to disable the combobox.
<ComponentPreview styleName="aria-nova" name="combobox-disabled" />
## Input Group
You can add an addon to the combobox by using the `InputGroupAddon` component inside the `ComboboxInput`.
<ComponentPreview styleName="aria-nova" name="combobox-input-group" />
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview
styleName="aria-nova"
name="combobox-rtl"
direction="rtl"
align="start"
/>
## API Reference
See the [React Aria](https://react-aria.adobe.com/ComboBox#api) documentation for more information.

View File

@@ -0,0 +1,150 @@
---
title: Command
description: Command menu for search and quick actions.
base: aria
component: true
links:
doc: https://react-aria.adobe.com/Autocomplete
api: https://react-aria.adobe.com/Autocomplete#api
---
<ComponentPreview
styleName="aria-nova"
name="command-demo"
align="start"
previewClassName="h-[24.5rem]"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add command
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install react-aria-components
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="command"
title="components/ui/command.tsx"
styleName="aria-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Command,
CommandDialog,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
CommandShortcut,
} from "@/components/ui/command"
```
```tsx showLineNumbers
<Command className="max-w-sm rounded-lg border">
<CommandInput placeholder="Type a command or search..." />
<CommandList
renderEmptyState={() => <CommandEmpty>No results found.</CommandEmpty>}
>
<CommandGroup heading="Suggestions">
<CommandItem>Calendar</CommandItem>
<CommandItem>Search Emoji</CommandItem>
<CommandItem>Calculator</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Settings">
<CommandItem>Profile</CommandItem>
<CommandItem>Billing</CommandItem>
<CommandItem>Settings</CommandItem>
</CommandGroup>
</CommandList>
</Command>
```
## Composition
Use the following composition to build a `Command`:
```text
Command
├── CommandInput
└── CommandList
├── CommandGroup
│ ├── CommandItem
│ └── CommandItem
├── CommandSeparator
└── CommandGroup
├── CommandItem
└── CommandItem
```
## Basic
A simple command menu in a dialog.
<ComponentPreview styleName="aria-nova" name="command-basic" />
## Shortcuts
<ComponentPreview styleName="aria-nova" name="command-shortcuts" />
## Groups
A command menu with groups, icons and separators.
<ComponentPreview styleName="aria-nova" name="command-groups" />
## Scrollable
Scrollable command menu with multiple items.
<ComponentPreview styleName="aria-nova" name="command-scrollable" />
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview
styleName="aria-nova"
name="command-rtl"
direction="rtl"
align="start"
previewClassName="h-[24.5rem]"
/>
## API Reference
See the [React Aria](https://react-aria.adobe.com/Autocomplete) documentation for more information.

View File

@@ -0,0 +1,192 @@
---
title: Context Menu
description: Displays a menu of actions triggered by a right click.
base: aria
component: true
links:
doc: https://react-aria.adobe.com/Menu
api: https://react-aria.adobe.com/Menu#api
---
<ComponentPreview
styleName="aria-nova"
name="context-menu-demo"
description="A context menu with sub menu items."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add context-menu
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install react-aria-components
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="context-menu"
title="components/ui/context-menu.tsx"
styleName="aria-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { Pressable } from "react-aria-components"
import {
ContextMenu,
ContextMenuItem,
ContextMenuTrigger,
} from "@/components/ui/context-menu"
```
```tsx showLineNumbers
<ContextMenuTrigger>
<Pressable>
<div role="button">Right click here</div>
</Pressable>
<ContextMenu>
<ContextMenuItem>Profile</ContextMenuItem>
<ContextMenuItem>Billing</ContextMenuItem>
<ContextMenuItem>Team</ContextMenuItem>
<ContextMenuItem>Subscription</ContextMenuItem>
</ContextMenu>
</ContextMenuTrigger>
```
## Composition
Use the following composition to build a `ContextMenu`:
```text
ContextMenuTrigger
├── Pressable
└── ContextMenuContent
├── ContextMenuGroup
│ ├── ContextMenuLabel
│ ├── ContextMenuItem
│ └── ContextMenuItem
├── ContextMenuSeparator
├── ContextMenuGroup
│ ├── ContextMenuLabel
│ ├── ContextMenuItem
│ └── ContextMenuItem
└── ContextMenuSub
├── ContextMenuSubTrigger
└── ContextMenuSubContent
└── ContextMenuGroup
├── ContextMenuItem
└── ContextMenuItem
```
## Basic
A simple context menu with a few actions.
<ComponentPreview styleName="aria-nova" name="context-menu-basic" />
## Submenu
Use `ContextMenuSub` to nest secondary actions.
<ComponentPreview styleName="aria-nova" name="context-menu-submenu" />
## Shortcuts
Add `ContextMenuShortcut` to show keyboard hints.
<ComponentPreview styleName="aria-nova" name="context-menu-shortcuts" />
## Groups
Group related actions and separate them with dividers.
<ComponentPreview styleName="aria-nova" name="context-menu-groups" />
## Icons
Combine icons with labels for quick scanning.
<ComponentPreview styleName="aria-nova" name="context-menu-icons" />
## Checkboxes
Use `selectionMode="multiple"` for toggles.
<ComponentPreview styleName="aria-nova" name="context-menu-checkboxes" />
## Radio
Use `selectionMode="single"` for exclusive choices.
<ComponentPreview styleName="aria-nova" name="context-menu-radio" />
## Destructive
Use `variant="destructive"` to style the menu item as destructive.
<ComponentPreview styleName="aria-nova" name="context-menu-destructive" />
## Placement
Control submenu placement with the `placement` prop.
<ComponentPreview styleName="aria-nova" name="context-menu-sides" />
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview
styleName="aria-nova"
name="context-menu-rtl"
direction="rtl"
/>
Use `placement="end"` to place the menu on the logical end side of the trigger.
```tsx showLineNumbers
<ContextMenuTrigger>
<Pressable>
<div role="button">Right click here</div>
</Pressable>
<ContextMenu placement="end">
<ContextMenuItem>Profile</ContextMenuItem>
<ContextMenuItem>Billing</ContextMenuItem>
<ContextMenuItem>Team</ContextMenuItem>
<ContextMenuItem>Subscription</ContextMenuItem>
</ContextMenu>
</ContextMenuTrigger>
```
## API Reference
See the [React Aria](https://react-aria.adobe.com/Menu#api) documentation for more information.

View File

@@ -0,0 +1,920 @@
---
title: Data Table
description: Powerful table and datagrids built using TanStack Table.
base: aria
component: true
links:
doc: https://tanstack.com/table/latest/docs/overview
---
<ComponentPreview
styleName="aria-nova"
name="data-table-demo"
align="start"
previewClassName="items-start h-auto px-4 md:px-8"
hideCode
/>
## Introduction
Every data table or datagrid I've created has been unique. They all behave differently, have specific sorting and filtering requirements, and work with different data sources.
It doesn't make sense to combine all of these variations into a single component. If we do that, we'll lose the flexibility that [headless UI](https://tanstack.com/table/latest/docs/overview#what-is-headless-ui) provides.
So instead of a data-table component, I thought it would be more helpful to provide a guide on how to build your own.
We'll start with the basic `<Table />` component and build a complex data table from scratch.
<Callout className="mt-4">
**Tip:** If you find yourself using the same table in multiple places in your app, you can always extract it into a reusable component.
</Callout>
## Table of Contents
This guide will show you how to use [TanStack Table](https://tanstack.com/table) and the `<Table />` component to build your own custom data table. We'll cover the following topics:
- [Set up Table Features](#set-up-table-features)
- [Basic Table](#basic-table)
- [Row Actions](#row-actions)
- [Pagination](#pagination)
- [Sorting](#sorting)
- [Filtering](#filtering)
- [Visibility](#visibility)
- [Row Selection](#row-selection)
- [Reusable Components](#reusable-components)
## Installation
1. Add the `<Table />` component to your project:
```bash
npx shadcn@latest add table
```
2. Add the `@tanstack/react-table` dependency. This guide uses **TanStack Table v9**:
```bash
npm install @tanstack/react-table
```
## Prerequisites
We are going to build a table to show recent payments. Here's what our data looks like:
```tsx showLineNumbers
type Payment = {
id: string
amount: number
status: "pending" | "processing" | "success" | "failed"
email: string
}
export const payments: Payment[] = [
{
id: "728ed52f",
amount: 100,
status: "pending",
email: "m@example.com",
},
{
id: "489e1d42",
amount: 125,
status: "processing",
email: "user@example.com",
},
// ...
]
```
## Project Structure
Start by creating the following file structure:
```txt
app
└── payments
├── columns.tsx
├── data-table-features.ts
├── data-table.tsx
└── page.tsx
```
I'm using a Next.js example here but this works for any other React framework.
- `columns.tsx` (client component) will contain our column definitions.
- `data-table-features.ts` will contain the shared `features` object that tells TanStack Table which behavior to enable.
- `data-table.tsx` (client component) will contain our `<DataTable />` component.
- `page.tsx` (server component) is where we'll fetch data and render our table.
## Set up Table Features
TanStack Table v9 is feature-based: you opt into the behavior you want — sorting, filtering, pagination, and so on — by declaring it with `tableFeatures()`. Anything you don't list is tree-shaken out of your bundle. That includes the built-in filter and sort functions: register the ones your columns rely on under `filterFns` and `sortFns` (our email filter uses `includesString`, and string columns sort with `text` / `alphanumeric`).
```tsx showLineNumbers title="app/payments/data-table-features.ts"
import {
columnFilteringFeature,
columnVisibilityFeature,
createFilteredRowModel,
createPaginatedRowModel,
createSortedRowModel,
filterFn_includesString,
rowPaginationFeature,
rowSelectionFeature,
rowSortingFeature,
sortFn_alphanumeric,
sortFn_text,
tableFeatures,
} from "@tanstack/react-table"
// New in v9: declare the features this table uses — anything you don't
// register is tree-shaken out of the bundle.
export const features = tableFeatures({
columnFilteringFeature,
columnVisibilityFeature,
rowPaginationFeature,
rowSelectionFeature,
rowSortingFeature,
filteredRowModel: createFilteredRowModel(),
paginatedRowModel: createPaginatedRowModel(),
sortedRowModel: createSortedRowModel(),
filterFns: { includesString: filterFn_includesString },
sortFns: { alphanumeric: sortFn_alphanumeric, text: sortFn_text },
})
// Pass this as the first generic argument to `ColumnDef`, `Column`, `Table`,
// and `Row` so each type knows which feature APIs are available.
export type DataTableFeatures = typeof features
```
<Callout className="mt-4">
**Note:** The core row model is always included, so you never register it yourself. Row models for optional features are created with `create*RowModel()` and registered on the features object — there are no more `get*RowModel` table options.
</Callout>
## Basic Table
Let's start by building a basic table.
<Steps className="mb-0 pt-2">
### Column Definitions
First, we'll define our columns.
```tsx showLineNumbers title="app/payments/columns.tsx" {3,5,16-17,19-29}
"use client"
import { createColumnHelper } from "@tanstack/react-table"
import { type DataTableFeatures } from "./data-table-features"
// This type is used to define the shape of our data.
// You can use a Zod schema here if you want.
export type Payment = {
id: string
amount: number
status: "pending" | "processing" | "success" | "failed"
email: string
}
// Use `accessor` for data columns and `display` for columns without one.
const columnHelper = createColumnHelper<DataTableFeatures, Payment>()
export const columns = columnHelper.columns([
columnHelper.accessor("status", {
header: "Status",
}),
columnHelper.accessor("email", {
header: "Email",
}),
columnHelper.accessor("amount", {
header: "Amount",
}),
])
```
<Callout className="mt-4">
**Note:** Columns are where you define the core of what your table
will look like. They define the data that will be displayed, how it will be
formatted, sorted and filtered.
</Callout>
### `<DataTable />` component
Next, we'll create a `<DataTable />` component to render our table.
```tsx showLineNumbers title="app/payments/data-table.tsx"
"use client"
import { useTable, type ColumnDef, type RowData } from "@tanstack/react-table"
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table"
import { features, type DataTableFeatures } from "./data-table-features"
interface DataTableProps<TData extends RowData> {
columns: ColumnDef<DataTableFeatures, TData>[]
data: TData[]
}
export function DataTable<TData extends RowData>({
columns,
data,
}: DataTableProps<TData>) {
const table = useTable({
features,
data,
columns,
})
return (
<div className="overflow-hidden rounded-md border">
<Table>
<TableHeader>
{table.getFlatHeaders().map((header) => (
<TableHead
key={header.id}
id={header.id}
isRowHeader={header.index === 0}
>
{header.isPlaceholder ? null : (
<table.FlexRender header={header} />
)}
</TableHead>
))}
</TableHeader>
<TableBody renderEmptyState={() => "No results."}>
{table.getRowModel().rows.map((row) => (
<TableRow key={row.id} id={row.id}>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
<table.FlexRender cell={cell} />
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
</div>
)
}
```
<Callout>
**Tip**: If you find yourself using `<DataTable />` in multiple places, this is the component you could make reusable by extracting it to `components/ui/data-table.tsx`.
`<DataTable columns={columns} data={data} />`
</Callout>
<Callout className="mt-4">
**`<table.FlexRender />` vs `flexRender`:** This guide uses v9's `<table.FlexRender header={header} />` and `<table.FlexRender cell={cell} />` component, available right on the table instance — no extra import needed. The classic `flexRender(component, context)` helper from v8 still works too, if you prefer the function form (or need to render outside the component that owns `table`, where you can also import the standalone `<FlexRender />`).
</Callout>
### Render the table
Finally, we'll render our table in our page component.
```tsx showLineNumbers title="app/payments/page.tsx" {22}
import { columns, Payment } from "./columns"
import { DataTable } from "./data-table"
async function getData(): Promise<Payment[]> {
// Fetch data from your API here.
return [
{
id: "728ed52f",
amount: 100,
status: "pending",
email: "m@example.com",
},
// ...
]
}
export default async function DemoPage() {
const data = await getData()
return (
<div className="container mx-auto py-10">
<DataTable columns={columns} data={data} />
</div>
)
}
```
</Steps>
## Cell Formatting
Let's format the amount cell to display the dollar amount. We'll also align the cell to the right.
<Steps className="mb-0 pt-2">
### Update columns definition
Update the `header` and `cell` definitions for amount as follows:
```tsx showLineNumbers title="app/payments/columns.tsx" {3-13}
export const columns = columnHelper.columns([
columnHelper.accessor("amount", {
header: () => <div className="text-right">Amount</div>,
cell: ({ row }) => {
const amount = parseFloat(row.getValue("amount"))
const formatted = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
}).format(amount)
return <div className="text-right font-medium">{formatted}</div>
},
}),
])
```
You can use the same approach to format other cells and headers.
</Steps>
## Row Actions
Let's add row actions to our table. We'll use a `<Dropdown />` component for this.
<Steps className="mb-0 pt-2">
### Update columns definition
Update our columns definition to add a new `actions` column. The `actions` cell returns a `<Dropdown />` component.
```tsx showLineNumbers title="app/payments/columns.tsx" {4,6-13,17-46}
"use client"
import { createColumnHelper } from "@tanstack/react-table"
import { MoreHorizontal } from "lucide-react"
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
export const columns = columnHelper.columns([
// ...
columnHelper.display({
id: "actions",
cell: ({ row }) => {
const payment = row.original
return (
<DropdownMenuTrigger>
<Button variant="ghost" size="icon-xs">
<span className="sr-only">Open menu</span>
<MoreHorizontal />
</Button>
<DropdownMenu placement="bottom end" className="w-44">
<DropdownMenuGroup>
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuItem
onClick={() => navigator.clipboard.writeText(payment.id)}
>
Copy payment ID
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem>View customer</DropdownMenuItem>
<DropdownMenuItem>View payment details</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenu>
</DropdownMenuTrigger>
)
},
}),
// ...
])
```
You can access the row data using `row.original` in the `cell` function. Use this to handle actions for your row eg. use the `id` to make a DELETE call to your API.
</Steps>
## Pagination
Next, we'll add pagination to our table.
<Steps className="mb-0 pt-2">
### Pagination is already enabled
Because our features object includes `rowPaginationFeature` and `createPaginatedRowModel()`, the table automatically paginates rows into pages of 10 — there's nothing to add to `useTable`. See the [pagination docs](https://tanstack.com/table/latest/docs/framework/react/guide/pagination) for more information on customizing page size and implementing manual pagination.
### Add pagination controls
We can add pagination controls to our table using the `<Button />` component and the `table.previousPage()`, `table.nextPage()` API methods.
```tsx showLineNumbers title="app/payments/data-table.tsx" {1,20-37}
import { Button } from "@/components/ui/button"
export function DataTable<TData extends RowData>({
columns,
data,
}: DataTableProps<TData>) {
const table = useTable({
features,
data,
columns,
})
return (
<div>
<div className="overflow-hidden rounded-md border">
<Table>
{ // .... }
</Table>
</div>
<div className="flex items-center justify-end space-x-2 py-4">
<Button
variant="outline"
size="sm"
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
>
Previous
</Button>
<Button
variant="outline"
size="sm"
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
>
Next
</Button>
</div>
</div>
)
}
```
See [Reusable Components](#reusable-components) section for a more advanced pagination component.
</Steps>
## Sorting
Let's make the email column sortable.
The `rowSortingFeature` and sorted row model are already registered in our features object, so all that's left is wiring up the sorting state.
<Steps className="mb-0 pt-2">
### Update `<DataTable>`
```tsx showLineNumbers title="app/payments/data-table.tsx" showLineNumbers {3,8,15,21-24,31-46}
"use client"
import * as React from "react"
import {
useTable,
type ColumnDef,
type RowData,
type SortingState,
} from "@tanstack/react-table"
export function DataTable<TData extends RowData>({
columns,
data,
}: DataTableProps<TData>) {
const [sorting, setSorting] = React.useState<SortingState>([])
const table = useTable({
features,
data,
columns,
onSortingChange: setSorting,
state: {
sorting,
},
})
return (
<div>
<div className="overflow-hidden rounded-md border">
<Table
sortDescriptor={
sorting.length
? {
column: sorting[0].id,
direction: sorting[0].desc ? "descending" : "ascending",
}
: undefined
}
onSortChange={(sortDescriptor) => {
table.setSorting([
{
id: "" + sortDescriptor.column,
desc: sortDescriptor.direction === "descending",
},
]);
}}>
{ ... }
</Table>
</div>
</div>
)
}
```
### Make header cell sortable
We can now update the `email` header cell to add sorting controls.
```tsx showLineNumbers title="app/payments/columns.tsx" {4,10-17}
"use client"
import { createColumnHelper } from "@tanstack/react-table"
import { ArrowUpDown } from "lucide-react"
import { buttonVariants } from "@/components/ui/button"
export const columns = columnHelper.columns([
columnHelper.accessor("email", {
header: ({ column }) => {
return (
<div className={buttonVariants({ variant: "ghost" })}>
Email
<ArrowUpDown className="ml-2 h-4 w-4" />
</div>
)
},
}),
])
```
This will automatically sort the table (asc and desc) when the user toggles on the header cell.
</Steps>
## Filtering
Let's add a search input to filter emails in our table.
The `columnFilteringFeature` and filtered row model are already part of our features object, so we only need to wire up the filter state and render an input.
<Steps className="mb-0 pt-2">
### Update `<DataTable>`
```tsx showLineNumbers title="app/payments/data-table.tsx" {7,13,20-22,29,32,38-46}
"use client"
import * as React from "react"
import {
useTable,
type ColumnDef,
type ColumnFiltersState,
type RowData,
type SortingState,
} from "@tanstack/react-table"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
export function DataTable<TData extends RowData>({
columns,
data,
}: DataTableProps<TData>) {
const [sorting, setSorting] = React.useState<SortingState>([])
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
)
const table = useTable({
features,
data,
columns,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
state: {
sorting,
columnFilters,
},
})
return (
<div>
<div className="flex items-center py-4">
<Input
placeholder="Filter emails..."
value={(table.getColumn("email")?.getFilterValue() as string) ?? ""}
onChange={(event) =>
table.getColumn("email")?.setFilterValue(event.target.value)
}
className="max-w-sm"
/>
</div>
<div className="overflow-hidden rounded-md border">
<Table>{ ... }</Table>
</div>
</div>
)
}
```
Filtering is now enabled for the `email` column. You can add filters to other columns as well. See the [filtering docs](https://tanstack.com/table/latest/docs/framework/react/guide/column-filtering) for more information on customizing filters.
</Steps>
## Visibility
Adding column visibility is fairly simple using `@tanstack/react-table` visibility API.
<Steps className="mb-0 pt-2">
### Update `<DataTable>`
```tsx showLineNumbers title="app/payments/data-table.tsx" {8,14-19,29-30,38,42,57-99}
"use client"
import * as React from "react"
import {
useTable,
type ColumnDef,
type ColumnFiltersState,
type ColumnVisibilityState,
type RowData,
type SortingState,
} from "@tanstack/react-table"
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
export function DataTable<TData extends RowData>({
columns,
data,
}: DataTableProps<TData>) {
const [sorting, setSorting] = React.useState<SortingState>([])
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
)
const [columnVisibility, setColumnVisibility] =
React.useState<ColumnVisibilityState>({})
const table = useTable({
features,
data,
columns,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
onColumnVisibilityChange: setColumnVisibility,
state: {
sorting,
columnFilters,
columnVisibility,
},
})
return (
<div>
<div className="flex items-center py-4">
<Input
placeholder="Filter emails..."
value={table.getColumn("email")?.getFilterValue() as string}
onChange={(event) =>
table.getColumn("email")?.setFilterValue(event.target.value)
}
className="max-w-sm"
/>
<DropdownMenuTrigger>
<Button variant="outline" className="ml-auto">
Columns
</Button>
<DropdownMenu placement="bottom end">
<DropdownMenuGroup
selectionMode="multiple"
selectedKeys={
table
.getVisibleFlatColumns()
.filter((column) => column.getCanHide())
.map(column => column.id)
}
onSelectionChange={(keys) => {
table.setColumnVisibility(
Object.fromEntries(
table
.getAllFlatColumns()
.map((c) => [
c.id,
!c.getCanHide() || keys === "all" || keys.has(c.id),
])
)
)
}}
>
{table
.getAllColumns()
.filter((column) => column.getCanHide())
.map((column) => {
return (
<DropdownMenuItem
key={column.id}
id={column.id}
className="capitalize"
>
{column.id}
</DropdownMenuItem>
)
})}
</DropdownMenuGroup>
</DropdownMenu>
</DropdownMenuTrigger>
</div>
<div className="overflow-hidden rounded-md border">
<Table>{ ... }</Table>
</div>
</div>
)
}
```
This adds a dropdown menu that you can use to toggle column visibility.
</Steps>
## Row Selection
Next, we're going to add row selection to our table.
<Steps className="mb-0 pt-2">
### Update column definitions
```tsx showLineNumbers title="app/payments/columns.tsx" {6,9-15}
"use client"
import { createColumnHelper } from "@tanstack/react-table"
import { Badge } from "@/components/ui/badge"
import { Checkbox } from "@/components/ui/checkbox"
export const columns = columnHelper.columns([
columnHelper.display({
id: "select",
header: () => <Checkbox slot="selection" />,
cell: () => <Checkbox slot="selection" />,
enableSorting: false,
enableHiding: false,
}),
])
```
### Update `<DataTable>`
```tsx showLineNumbers title="app/payments/data-table.tsx" {11,20,25,33-43}
export function DataTable<TData extends RowData>({
columns,
data,
}: DataTableProps<TData>) {
const [sorting, setSorting] = React.useState<SortingState>([])
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
)
const [columnVisibility, setColumnVisibility] =
React.useState<ColumnVisibilityState>({})
const [rowSelection, setRowSelection] = React.useState({})
const table = useTable({
features,
data,
columns,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
onColumnVisibilityChange: setColumnVisibility,
onRowSelectionChange: setRowSelection,
state: {
sorting,
columnFilters,
columnVisibility,
rowSelection,
},
})
return (
<div>
<div className="overflow-hidden rounded-md border">
<Table
selectionMode="multiple"
selectedKeys={table.getSelectedRowModel().rows.map((row) => row.id)}
onSelectionChange={(selection) => {
if (selection === "all") {
table.toggleAllRowsSelected()
} else {
table.setRowSelection(
Object.fromEntries([...selection].map((key) => [key, true]))
)
}
}}
/>
</div>
</div>
)
}
```
This adds a checkbox to each row and a checkbox in the header to select all rows.
### Show selected rows
You can show the number of selected rows using the `table.getFilteredSelectedRowModel()` API.
```tsx
<div className="flex-1 text-sm text-muted-foreground">
{table.getFilteredSelectedRowModel().rows.length} of{" "}
{table.getFilteredRowModel().rows.length} row(s) selected.
</div>
```
</Steps>
## Reusable Components
Here are some components you can use to build your data tables. This is from the [Tasks](/examples/tasks) demo, which shares its features object (and the matching `TasksTableFeatures` type) across every component via a `data-table-features.ts` module — the same pattern we set up in [Set up Table Features](#set-up-table-features).
### Column header
Make any column header sortable and hideable.
<ComponentSource
src="/app/(app)/examples/tasks/components/data-table-column-header.tsx"
title="components/data-table-column-header.tsx"
/>
```tsx showLineNumbers {4}
export const columns = columnHelper.columns([
columnHelper.accessor("email", {
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Email" />
),
}),
])
```
### Pagination
Add pagination controls to your table including page size and selection count.
<ComponentSource
src="/app/(app)/examples/tasks/components/data-table-pagination.tsx"
styleName="aria-nova"
/>
```tsx
<DataTablePagination table={table} />
```
### Column toggle
A component to toggle column visibility.
<ComponentSource
src="/app/(app)/examples/tasks/components/data-table-view-options.tsx"
styleName="aria-nova"
/>
```tsx
<DataTableViewOptions table={table} />
```
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview
styleName="aria-nova"
name="data-table-rtl"
direction="rtl"
previewClassName="items-start h-auto px-4 md:px-8"
hideCode
/>

View File

@@ -0,0 +1,114 @@
---
title: Date Picker
description: A date picker component with range and presets.
base: aria
component: true
---
<ComponentPreview styleName="aria-nova" name="date-picker-demo" />
## Installation
The Date Picker is built using a composition of the `<Popover />` and the `<Calendar />` components.
See installation instructions for the [Popover](/docs/components/aria/popover#installation) and the [Calendar](/docs/components/aria/calendar#installation) components.
## Usage
```tsx showLineNumbers title="components/example-date-picker.tsx"
"use client"
import * as React from "react"
import { getLocalTimeZone, type CalendarDate } from "@internationalized/date"
import { cn } from "cn"
import { Calendar as CalendarIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Popover, PopoverTrigger } from "@/components/ui/popover"
export function DatePickerDemo() {
const [date, setDate] = React.useState<CalendarDate | null>(null)
return (
<PopoverTrigger>
<Button
variant="outline"
data-empty={!date}
className="justify-start text-left font-normal data-[empty=true]:text-muted-foreground"
>
<CalendarIcon />
{date ? (
date
.toDate(getLocalTimeZone())
.toLocaleDateString(undefined, { dateStyle: "long" })
) : (
<span>Pick a date</span>
)}
</Button>
<Popover className="w-auto p-0">
<Calendar value={date} onChange={setDate} />
</Popover>
</PopoverTrigger>
)
}
```
See the [React Aria](https://react-aria.adobe.com/Calendar) documentation for more information.
## Composition
A date picker is built from `Popover` and `Calendar` (there is no `DatePicker` root component):
```text
PopoverTrigger
├── Button
└── Popover
└── Calendar
```
## Basic
A basic date picker component.
<ComponentPreview styleName="aria-nova" name="date-picker-basic" />
## Range Picker
A date picker component for selecting a range of dates.
<ComponentPreview styleName="aria-nova" name="date-picker-range" />
## Date of Birth
A date picker component for selecting a date of birth. This component includes a dropdown caption layout for date and month selection.
<ComponentPreview styleName="aria-nova" name="date-picker-dob" />
## Input
A date picker component with an input field for selecting a date.
<ComponentPreview styleName="aria-nova" name="date-picker-input" />
## Time Picker
A date picker component with a time input field for selecting a time.
<ComponentPreview styleName="aria-nova" name="date-picker-time" />
## Natural Language Picker
This component uses the `chrono-node` library to parse natural language dates.
<ComponentPreview styleName="aria-nova" name="date-picker-natural-language" />
## RTL
To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
<ComponentPreview
styleName="aria-nova"
name="date-picker-rtl"
direction="rtl"
/>

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