```
---
---
url: /docs/installation/astro.md
description: Install and configure Astro.
---
**Note:** The following guide is for Tailwind v4. If you are using Tailwind
v3, use `shadcn-vue@1.0.3`.
### Create project
Start by creating a new Astro project:
```bash
npx create-astro@latest astro-app --template with-tailwindcss --install --add vue --git
```
### Edit tsconfig.json file
Add the following code to the `tsconfig.json` file to resolve paths:
```ts:line-numbers title="tsconfig.json" {4-9}
{
"compilerOptions": {
// ...
"baseUrl": ".",
"paths": {
"@/*": [
"./src/*"
]
}
// ...
}
}
```
### Run the CLI
Run the `shadcn` init command to setup your project:
```bash
npx shadcn-vue@latest init
```
### Add Components
You can now start adding components to your project.
```bash
npx shadcn-vue@latest add button
```
The command above will add the `Button` component to your project. You can then import it like this:
```astro:line-numbers {2,10}
---
import { Button } from "@/components/ui/button"
---
Astro
```
---
---
url: /docs/dark-mode/astro.md
description: Adding dark mode to your astro app.
---
## Dark mode
### Create an inline theme script
```astro title="src/pages/index.astro"
---
import '../styles/globals.css'
---
Astro
```
### Install Dependencies
```bash
npm install @vueuse/core
```
Optional, to include icons for theme button.
```bash
npm install -D @iconify/vue @iconify-json/radix-icons
```
### Add a mode toggle
Place a mode toggle on your site to toggle between light and dark mode.
We're using [`useColorMode`](https://vueuse.org/core/usecolormode/) from [`@vueuse/core`](https://vueuse.org/core/).
> Reactive color mode (dark / light / customs) with auto data persistence.
```vue
Light
Dark
System
```
### Display the mode toggle
Place a mode toggle on your site to toggle between light and dark mode.
```astro title="src/pages/index.astro"
---
import '../styles/globals.css'
import ModeToggle from '@/components/ModeToggle.vue';
---
Astro
```
---
---
url: /docs/components/auto-form.md
description: Automatically generate a form from Zod schema.
---
**Legacy**: Component will be moved to [extended repo](https://github.com/unovue/shadcn-vue/issues/1077) with Tailwind v4 support.
---
Credit: Heavily inspired by [AutoForm](https://github.com/vantezzen/auto-form) by Vantezzen
## What is AutoForm
AutoForm is a drop-in form builder for your internal and low-priority forms with existing zod schemas. For example, if you already have zod schemas for your API and want to create a simple admin panel to edit user profiles, simply pass the schema to AutoForm and you're done.
## Installation
### Run the following command
```bash
npx shadcn-vue@latest update form
npx shadcn-vue@latest add auto-form
```
## Field types
Currently, these field types are supported out of the box:
- boolean (checkbox, switch)
- date (date picker)
- enum (select, radio group)
- number (input)
- string (input, textfield)
- file (file)
You can add support for other field types by adding them to the `INPUT_COMPONENTS` object in `auto-form/constants.ts`.
## Zod configuration
### Validations
Your form schema can use any of zod's validation methods including refine.
⚠️ However, there's a known issue with Zod’s `refine` and `superRefine` not executing whenever some object keys are missing.
[Read more](https://github.com/logaretm/vee-validate/issues/4338)
### Descriptions
You can use the `describe` method to set a label for each field. If no label is set, the field name will be used and un-camel-cased.
```ts
const formSchema = z.object({
username: z.string().describe('Your username'),
someValue: z.string(), // Will be "Some Value"
})
```
You can also configure the label with [`fieldConfig`](#label) too.
### Optional fields
By default, all fields are required. You can make a field optional by using the `optional` method.
```ts
const formSchema = z.object({
username: z.string().optional(),
})
```
### Default values
You can set a default value for a field using the `default` method.
```ts
const formSchema = z.object({
favouriteNumber: z.number().default(5),
})
```
If you want to set default value of date, convert it to Date first using `new Date(val)`.
### Sub-objects
You can nest objects to create accordion sections.
```ts
const formSchema = z.object({
address: z.object({
street: z.string(),
city: z.string(),
zip: z.string(),
// You can nest objects as deep as you want
nested: z.object({
foo: z.string(),
bar: z.string(),
nested: z.object({
foo: z.string(),
bar: z.string(),
}),
}),
}),
})
```
Like with normal objects, you can use the `describe` method to set a label and description for the section:
```ts
const formSchema = z.object({
address: z
.object({
street: z.string(),
city: z.string(),
zip: z.string(),
})
.describe('Your address'),
})
```
### Select/Enums
AutoForm supports `enum` and `nativeEnum` to create select fields.
```ts
const formSchema = z.object({
color: z.enum(['red', 'green', 'blue']),
})
enum BreadTypes {
// For native enums, you can alternatively define a backed enum to set a custom label
White = 'White bread',
Brown = 'Brown bread',
Wholegrain = 'Wholegrain bread',
Other,
}
// Keep in mind that zod will validate and return the enum labels, not the enum values!
const formSchema = z.object({
bread: z.nativeEnum(BreadTypes),
})
```
### Arrays
AutoForm supports arrays _of objects_. Because inferring things like field labels from arrays of strings/numbers/etc. is difficult, only objects are supported.
```ts
const formSchema = z.object({
guestListName: z.string(),
invitedGuests: z
.array(
// Define the fields for each item
z.object({
name: z.string(),
age: z.number(),
})
)
// Optionally set a custom label - otherwise this will be inferred from the field name
.describe('Guests invited to the party'),
})
```
Arrays are not supported as the root element of the form schema.
You also can set default value of an array using .default(), but please make sure the array element has same structure with the schema.
```ts
const formSchema = z.object({
guestListName: z.string(),
invitedGuests: z
.array(
// Define the fields for each item
z.object({
name: z.string(),
age: z.number(),
})
)
.describe('Guests invited to the party')
.default([
{ name: 'John', age: 24, },
{ name: 'Jane', age: 20, },
]),
})
```
## Field configuration
As zod doesn't allow adding other properties to the schema, you can use the `fieldConfig` prop to add additional configuration for the UI of each field.
```vue
```
### Label
You can use the `label` property to customize label if you want to overwrite the pre-defined label via [Zod's description](#descriptions).
```vue
```
### Description
You can use the `description` property to add a description below the field.
```vue
```
### Input props
You can use the `inputProps` property to pass props to the input component. You can use any props that the HTML component accepts.
```vue
// This will be rendered as:
```
Disabling the label of an input can be done by using the `showLabel` property in `inputProps`.
```vue
```
### Component
By default, AutoForm will use the Zod type to determine which input component to use. You can override this by using the `component` property.
```vue
```
The complete list of supported field types is typed. Current supported types are:
- `checkbox` (default for booleans)
- `switch`
- `date` (default for dates)
- `select` (default for enums)
- `radio`
- `textarea`
Alternatively, you can pass a Vue component to the `component` property to use a custom component.
In `CustomField.vue`
```vue
{{ config?.label }}
{{ config.description }}
```
Pass the above component in `fieldConfig`.
```vue
```
### Named slot
You can use Vue named slot to customize the rendered `AutoFormField`.
```vue
```
### Accessing the form data
There are two ways to access the form data:
### @submit
The preferred way is to use the `submit` emit. This will be called when the form is submitted and the data is valid.
```vue
{
// Do something with the data
}"
/>
```
### Controlled form
By passing the `form` as props, you can control and use the method provided by `Form`.
```vue
```
### Submitting the form
You can use any `button` component to create a submit button. Most importantly is to add attributes `type="submit"`.
```vue
Send now
// or
```
### Adding other elements
All children passed to the `AutoForm` component will be rendered below the form.
```vue
```
### Dependencies
AutoForm allows you to add dependencies between fields to control fields based on the value of other fields. For this, a `dependencies` array can be passed to the `AutoForm` component.
```vue
```
The following dependency types are supported:
- `DependencyType.HIDES`: Hides the target field when the `when` function returns true
- `DependencyType.DISABLES`: Disables the target field when the `when` function returns true
- `DependencyType.REQUIRES`: Sets the target field to required when the `when` function returns true
- `DependencyType.SETS_OPTIONS`: Sets the options of the target field to the `options` array when the `when` function returns true
The `when` function is called with the value of the source field and the value of the target field and should return a boolean to indicate if the dependency should be applied.
Please note that dependencies will not cause the inverse action when returning `false` - for example, if you mark a field as required in your zod schema (i.e. by not explicitly setting `optional`), returning `false` in your `REQURIES` dependency will not mark it as optional. You should instead use zod's `optional` method to mark as optional by default and use the `REQURIES` dependency to mark it as required when the dependency is met.
Please note that dependencies do not have any effect on the validation of the form. You should use zod's `refine` method to validate the form based on the value of other fields.
You can create multiple dependencies for the same field and dependency type - for example to hide a field based on multiple other fields. This will then hide the field when any of the dependencies are met.
## Example
### Basic
### Input Without Label
This example shows how to use AutoForm input without label.
### Sub Object
Automatically generate a form from a Zod schema.
### Controlled
This example shows how to use AutoForm in a controlled way.
### Confirm Password
Refined schema to validate that two fields match.
### API Example
The form select options are fetched from an API.
### Array support
You can use arrays in your schemas to create dynamic forms.
### Dependencies
Create dependencies between fields.
---
---
url: /docs/components/avatar.md
description: An image element with a fallback for representing the user.
---
## Installation
```bash
npx shadcn-vue@latest add avatar
```
## Usage
```vue
CN
```
---
---
url: /docs/components/badge.md
description: Displays a badge or a component that looks like a badge.
---
## Installation
```bash
npx shadcn-vue@latest add badge
```
### Copy and paste the following code into your project
```vue
```
## Usage
```vue
Badge
```
## Examples
### Default
### Secondary
### Outline
### Destructive
---
---
url: /docs/charts/bar.md
description: >-
A line chart visually represents data using rectangular bars of varying
lengths to compare quantities across different categories or groups.
---
## Installation
Only works with Vue >3.3
### Run the following command
```bash
npx shadcn-vue@latest add chart-bar
```
### Setup
Follow the [guide](/docs/charts.html#installation) to complete the setup.
## API
## Example
### Stacked
You can stack the bar chart by settings prop `type` to `stacked`.
### Rounded
### Custom Tooltip
If you want to render custom tooltip, you can easily pass in a custom component. Refer to prop definition [here](/docs/charts.html#custom-tooltip).
---
---
url: /block-renderer.md
---
---
---
url: /docs/components/breadcrumb.md
description: Displays the path to the current resource using a hierarchy of links.
---
## Installation
```bash
npx shadcn-vue@latest add breadcrumb
```
## Usage
```vue
Home
Components
Breadcrumb
```
## Examples
### Custom separator
Use a custom component as `slot` for `` to create a custom separator.
```vue showLineNumbers {2,20-22}
Home
Components
```
---
### Dropdown
You can compose `` with a `` to create a dropdown in the breadcrumb.
```vue showLineNumbers {2-7,16-26}
Components
DocumentationThemesGitHub
```
---
### Collapsed
We provide a `` component to show a collapsed state when the breadcrumb is too long.
```vue showLineNumbers {3,15}
```
---
### Link component
To use a custom link component from your routing library, you can use the `asChild` prop on ``.
```vue showLineNumbers {15-19}
Home
```
---
### Responsive
Here's an example of a responsive breadcrumb that composes `` with ``, ``, and ``.
It displays a dropdown on desktop and a drawer on mobile.
---
---
url: /docs/components/button.md
description: Displays a button or a component that looks like a button.
---
## Installation
```bash
npx shadcn-vue@latest add button
```
### Copy and paste the following code into your project
```vue
```
## Usage
```vue
```
## Examples
### Primary
### Secondary
### Destructive
### Outline
### Ghost
### Link
### Icon
### With Icon
### Loading
### As Child
---
---
url: /docs/components/calendar.md
description: A date field component that allows users to enter and edit date.
---
## About
The `` component is built on top of the [RadixVue Calendar](https://www.reka-ui.com/docs/components/calendar.html) component, which uses the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package to handle dates.
If you're looking for a range calendar, check out the [Range Calendar](/docs/components/range-calendar) component.
## Installation
```bash
npx shadcn-vue@latest add calendar
```
::: tip
The component depends on the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package, which solves a lot of the problems that come with working with dates and times in JavaScript.
Check [Dates & Times in Radix Vue](https://www.reka-ui.com/docs/guides/dates.html) for more information and installation instructions.
:::
## Datepicker
You can use the `` component to build a date picker. See the [Date Picker](/docs/components/date-picker) page for more information.
## Examples
### Form
## Advanced Customization
### Month & Year Selects
---
---
url: /docs/components/card.md
description: 'Displays a card with header, content, and footer.'
---
## Installation
```bash
npx shadcn-vue@latest add card
```
## Usage
```vue
Card TitleCard Description
Card Content
Card Footer
```
## Examples
---
---
url: /docs/components/carousel.md
description: A carousel with motion and swipe built using Embla.
---
## About
The carousel component is built using the [Embla Carousel](https://www.embla-carousel.com/) library.
## Installation
```bash
npx shadcn-vue@latest add carousel
```
## Usage
```vue
.........
```
## Examples
### Sizes
To set the size of the items, you can use the `basis` utility class on the ``.
Example
```vue:line-numbers title="Example" {4-6}
// 33% of the carousel width.
.........
```
Responsive
```vue:line-numbers title="Responsive" {4-6}
// 50% on small screens and 33% on larger screens.
.........
```
### Spacing
To set the spacing between the items, we use a `pl-[VALUE]` utility on the `` and a negative `-ml-[VALUE]` on the ``.
**Why:** I tried to use the `gap` property or a `grid` layout on the `
CarouselContent` but it required a lot of math and mental effort to get the
spacing right. I found `pl-[VALUE]` and `-ml-[VALUE]` utilities much easier to
use.
You can always adjust this in your own project if you need to.
Example
```vue:line-numbers /-ml-4/ /pl-4/
...
...
...
```
Responsive
```vue:line-numbers /-ml-2/ /pl-2/ /md:-ml-4/ /md:pl-4/
...
...
...
```
### Orientation
Use the `orientation` prop to set the orientation of the carousel.
```vue
...
```
### Thumbnails
## Options
You can pass options to the carousel using the `opts` prop. See the [Embla Carousel docs](https://www.embla-carousel.com/api/options/) for more information.
```vue:line-numbers {3-6}
.........
```
## API
### Method 1
Use the `@init-api` emit method on `` component to set the instance of the API.
### Method 2
You can access it through setting a template ref on the `` component.
```vue:line-numbers {2,5,10}
...
```
## Events
You can listen to events using the API. To get the API instance use the `@init-api` emit method on the `` component
```vue:line-numbers {5,7-9,25}
...
```
See the [Embla Carousel docs](https://www.embla-carousel.com/api/events/) for more information on using events.
## Slot Props
You can get the reactive slot props like `carouselRef, canScrollNext..Prev, scrollNext..Prev` using the `v-slot` directive in the `` component to extend the functionality.
```vue:line-numbers {2}
...
```
## Plugins
You can use the `plugins` prop to add plugins to the carousel.
```bash
npm install embla-carousel-autoplay
```
```vue:line-numbers {2,8-10}
...
```
See the [Embla Carousel docs](https://www.embla-carousel.com/api/plugins/) for more information on using plugins.
---
---
url: /docs/changelog.md
description: Latest updates and announcements.
---
## February 2025 - Reka UI & npx shadcn-vue@latest init
We've updated the latest registry to support Reka UI instead of Radix Vue.
The updated CLI is now available. You can now install components, themes, composables, utils and more using `npx shadcn-vue add`.
This is a major step towards distributing code that you and your LLMs can access and use.
With the released of [Reka UI v2](https://reka-ui.com/), `shadcn-vue@latest` command will now install Reka UI. If you want to keep using [Radix Vue](https://radix-vue.com/), please visit [here](https://radix.shadcn-vue.com/) and run `shadcn-vue@radix` command instead.
1. First up, when you init into a new app, we update your existing Tailwind files instead of overriding.
2. A component now ship 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-vue add https://acme.com/registry/navbar.json`.
4. 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.
5. And a few more updates like better error handling and monorepo support.
You can try the new cli today.
```bash
npx shadcn-vue@latest init Sidebar01 Login01
```
### Update Your Project
### Update `components.json`
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 **composables**.
```json:line-numbers {7-13} title="components.json" inert
{
"$schema": "https://shadcn-vue.com/schema.json",
"style": "new-york",
"tailwind": {
// ...
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"composables": "@/composables"
}
}
```
If you're using a different import alias prefix eg `~`, replace `@` with your prefix.
### Run add components
In order to perform Radix Vue to Reka UI migration easily, you can run `add` command for all your existing components.
```bash
npx shadcn-vue@latest add
```
If you're using custom component, you need to migrate them [manually](https://reka-ui.com/docs/guides/migration).
## June 2024
### New Component - Number Field
A new component has been added to the project [`NumberField`](/docs/components/number-field.html).
A number field allows a user to enter a number and increment or decrement the value using stepper buttons.
## May 2024
### New Component - Charts
Several kinds of chart components has been added to the project.
Charts are versatile visualization tools, allowing users to represent data using various options for effective analysis.
1. [`Area Chart`](/docs/charts/area) - An area chart visually represents data over time, displaying trends and patterns through filled-in areas under a line graph.
2. [`Bar Chart`](/docs/charts/bar) - A line chart visually represents data using rectangular bars of varying lengths to compare quantities across different categories or groups.
3. [`Donut Chart`](/docs/charts/donut) - A line chart visually represents data in a circular form, similar to a pie chart but with a central void, emphasizing proportions within categories.
4. [`Line Chart`](/docs/charts/line) - A line chart visually displays data points connected by straight lines, illustrating trends or relationships over a continuous axis.
### New Component - Auto Form
[`Auto Form`](/docs/components/auto-form.html) is a drop-in form builder for your internal and low-priority forms with existing zod schemas.
For example, if you already have zod schemas for your API and want to create a simple admin panel to edit user profiles, simply pass the schema to AutoForm and you're done.
The following form has been created by passing a `zod` schema object to our `AutoForm` component.
## April 2024
### Component Updated - Calendar
The [`Calendar`](/docs/components/calendar.html) component has been updated and is now built on top of the [RadixVue Calendar](https://www.reka-ui.com/components/calendar.html) component, which uses the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package to handle dates.
If you're looking for a range calendar, check out the [`Range Calendar`](/docs/components/range-calendar.html) component.
And if you're looking for a date picker input, check out the [`Date Picker`](/docs/components/date-picker.html) component.
### Building Blocks for the Web
[`Blocks`](/blocks) are composed of different components that can be used to build your apps, with each block being a standalone section of your application. These blocks are fully responsive, accessible, and composable, and are built using the same principles as the other components in `shadcn-vue`.
## March 2024
### New Component - Breadcrumb
[`Breadcrumb`](/docs/components/breadcrumb.html) displays the path to the current resource using a hierarchy of links.
### New Component - Pin Input (OTP Input)
[`Pin Input`](/docs/components/pin-input.html) allows users to input a sequence of one-character alphanumeric inputs.
### New Component - Resizable
[`Resizable`](/docs/components/resizable.html) - Accessible resizable panel groups and layouts with keyboard support.
### New Component - Drawer
[`Drawer`](/docs/components/drawer.html) - A drawer component for vue that is built on top of [Vaul Vue](https://github.com/unovue/vaul-vue).
## February 2024
### New Component - Tag Inputs
[`Tag inputs`](/docs/components/tags-input.html) render tags inside an input, followed by an actual text input.
## January 2024
### New Component - Sonner
[`Sonner`](/docs/components/sonner.html) is an opinionated toast component for Vue.
The Sonner component is provided by [vue-sonner](https://vue-sonner.vercel.app/), which is a Vue port of Sonner, originally created by [Emil Kowalski](https://twitter.com/emilkowalski_) for React.
### New Component - Toggle Group
[`Toggle Group`](/docs/components/toggle-group.html) - A set of two-state buttons that can be toggled on or off.
### New Component - Carousel
[`Carousel`](/docs/components/carousel.html) - A carousel with motion and swipe built using [Embla](https://www.embla-carousel.com/) library.
---
---
url: /docs/charts.md
description: >-
Versatile visualization tool, allowing users to represent data using various
types of charts for effective analysis.
---
**Legacy**: Component will be moved to [extended repo](https://github.com/unovue/shadcn-vue/issues/1077) with Tailwind v4 support.
---
Only works with Vue >3.3
`Charts` components were built on top of [Unovis](https://unovis.dev/) (a modular data visualization framework), and inspired by [tremor](https://www.tremor.so).
## Chart type
Area
Line
Bar
Donut
## Installation
### Update `css`
Add the following tooltip styling to your `tailwind.css` file:
```css
@layer base {
:root {
/* ... */
--vis-tooltip-background-color: none !important;
--vis-tooltip-border-color: none !important;
--vis-tooltip-text-color: none !important;
--vis-tooltip-shadow-color: none !important;
--vis-tooltip-backdrop-filter: none !important;
--vis-tooltip-padding: none !important;
--vis-primary-color: var(--primary);
/* change to any hsl value you want */
--vis-secondary-color: 160 81% 40%;
--vis-text-color: var(--muted-foreground);
}
}
```
If you are not using `css-variables` for your component, you need to update the `--vis-primary-color` and `--vis-text-color` to your desired hsl value.
You may use [this tool](https://redpixelthemes.com/blog/tailwindcss-colors-different-formats/) to help you find the hsl value for your primary color and text color. Be sure to provide `dark` mode styling as well.
## Colors
By default, we construct the primary theme color, and secondary (`--vis-secondary-color`) color with different opacity for the graph.
However, you can always pass in the desired `color` into each chart.
```vue
```
## Custom tooltip
If you want to customize the `Tooltip` for the chart, you can pass `customTooltip` prop with a custom Vue component.
The custom component would receive `title` and `data` props, check out [ChartTooltip.vue component](https://github.com/unovue/shadcn-vue/tree/dev/apps/www/registry/default/ui/chart/ChartTooltip.vue) for example.
The expected prop definition would be:
```ts
defineProps<{
title?: string
data: {
name: string
color: string
value: any
}[]
}>()
```
---
---
url: /docs/components/checkbox.md
description: A control that allows the user to toggle between checked and not checked.
---
## Installation
```bash
npx shadcn-vue@latest add checkbox
```
## Usage
```vue
```
## Examples
### With text
### Disabled
### Form
Please first read `vee-validate` section for [Checkbox and Radio Inputs](https://vee-validate.logaretm.com/v4/examples/checkboxes-and-radio/)
---
---
url: /docs/cli.md
description: Use the CLI to add components to your project.
---
## init
Use the `init` command to initialize configuration and dependencies for a new project.
The `init` command installs dependencies, adds the `cn` util, configures `tailwind.config.js`, and CSS variables for the project.
```bash
npx shadcn-vue@latest init
```
You will be asked a few questions to configure `components.json`:
```:line-numbers
Which style would you like to use? › New York
Which color would you like to use as base color? › Zinc
Do you want to use CSS variables for colors? › no / yes
```
### Options
```txt
Usage: shadcn-vue init [options] [components...]
initialize your project and install dependencies
Arguments:
components the components to add or a url to the component.
Options:
-d, --defaults use default values i.e new-york, zinc and css variables. (default: false)
-f, --force force overwrite of existing components.json. (default: false)
-y, --yes skip confirmation prompt. (default: false)
-c, --cwd the working directory. defaults to the current directory.
-h, --help display help for command
```
## add
Use the `add` command to add components and dependencies to your project.
```bash
npx shadcn-vue@latest add [component]
```
You will be presented with a list of components to choose from:
```txt
Which components would you like to add? › Space to select. A to toggle all.
Enter to submit.
◯ accordion
◯ alert
◯ alert-dialog
◯ aspect-ratio
◯ avatar
◯ badge
◯ button
◯ calendar
◯ card
◯ checkbox
```
### Options
```txt
Usage: shadcn-vue add [options] [components...]
add a component to your project
Arguments:
components the components to add or a url to the component.
Options:
-y, --yes skip confirmation prompt. (default: false)
-o, --overwrite overwrite existing files. (default: false)
-c, --cwd the working directory. defaults to the current directory.
-a, --all add all available components. (default: false)
-p, --path the path to add the component to.
-h, --help display help for command
```
## Monorepo
In a monorepo, you can specify the path to your workspace with the `-c` or `--cwd` option.
```bash
npx shadcn-vue@latest init -c ./apps/www
```
or
```bash
npx shadcn-vue@latest add alert-dialog -c ./apps/www
```
---
---
url: /docs/components/collapsible.md
description: An interactive component which expands/collapses a panel.
---
## Installation
```bash
npx shadcn-vue@latest add collapsible
```
## Usage
```vue
Can I use this in my project?
Yes. Free to use for personal and commercial projects. No attribution
required.
```
---
---
url: /docs/components/combobox.md
description: Autocomplete input and command palette with a list of suggestions.
---
## Installation
```bash
npx shadcn-vue@latest add combobox
```
## Usage
```vue
No framework found.
{{ framework.label }}
```
## Examples
### Combobox Trigger
### Form
---
---
url: /docs/components/command.md
description: 'Fast, composable, unstyled command menu.'
---
## Installation
```bash
npx shadcn-vue@latest add command
```
## Usage
```vue
No results found.
Calendar
Search Emoji
Calculator
Profile
Billing
Settings
```
## Examples
### Dialog
To show the command menu in a dialog, use the `` component.
```vue
Press
⌘J
No results found.
Calendar
Search Emoji
Calculator
Profile
Billing
Settings
```
You can use the `` component like a combobox.
### Popover
### Dropdown menu
### Responsive
You can create a responsive combobox by using the `` on desktop and the `` components on mobile.
### Form
---
---
url: /docs/components-json.md
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.
Note: The `components.json` file is optional and **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.
You can create a `components.json` file in your project by running the following command:
```bash
npx shadcn-vue@latest init
```
See the [CLI section](/docs/cli) for more information.
## $schema
You can see the JSON Schema for `components.json` [here](https://shadcn-vue.com/schema.json).
```json title="components.json"
{
"$schema": "https://shadcn-vue.com/schema.json"
}
```
## style
The style for your components. **This cannot be changed after initialization.**
```json title="components.json"
{
"style": "default" | "new-york"
}
```
## Tailwind
Configuration to help the CLI understand how Tailwind CSS is set up in your project.
See the [installation section](/docs/installation) for how to set up Tailwind CSS.
### tailwind.config
Path to where your `tailwind.config.js` file is located.
```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": "src/assets/index.css"
}
}
```
### tailwind.baseColor
This is used to generate the default color palette for your components. **This cannot be changed after initialization.**
```json title="components.json"
{
"tailwind": {
"baseColor": "gray" | "neutral" | "slate" | "stone" | "zinc"
}
}
```
### tailwind.cssVariables
You can choose between using CSS variables or Tailwind CSS utility classes for theming.
To use utility classes for theming set `tailwind.cssVariables` to `false`. For CSS variables, set `tailwind.cssVariables` to `true`.
```json title="components.json"
{
"tailwind": {
"cssVariables": `true` | `false`
}
}
```
For more information, see the [theming docs](/docs/theming).
**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-"
}
}
```
## aliases
The CLI uses these values and the `paths` config from your `tsconfig.json` or `jsconfig.json` file to place generated components in the correct location.
Path aliases have to be set up in your `tsconfig.json` or `jsconfig.json` file.
> A fallback to `tsconfig.app.json` if no `paths` were found in `tsconfig.json`
**Important:** If you're using the `src` directory, make sure it is included
under `paths` in your `tsconfig.json` or `jsconfig.json` file.
### 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 `cn` or `valueUpdater`.
```json title="components.json"
{
"aliases": {
"lib": "@/lib"
}
}
```
### aliases.composables
Import alias for `composables` such as `useMediaQuery` or `useToast`.
```json title="components.json"
{
"aliases": {
"composables": "@/composables"
}
}
```
---
---
url: /docs/components/context-menu.md
description: >-
Displays a menu to the user — such as a set of actions or functions —
triggered by a button.
---
## Installation
```bash
npx shadcn-vue@latest add context-menu
```
## Usage
```vue
Right clickProfileBillingTeamSubscription
```
---
---
url: /docs/dark-mode.md
description: Adding dark mode to your site.
---
Vite
Nuxt
Vitepress
Astro
---
---
url: /docs/components/data-table.md
description: Powerful table and datagrids built using TanStack Table.
---
## 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/introduction#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 `
` component and build a complex data table from scratch.
**Tip:** If you find yourself using the same table in multiple places in your app, you can always extract it into a reusable component.
## Table of Contents
This guide will show you how to use [TanStack Table](https://tanstack.com/table/v8) and the `
` component to build your own custom data table. We'll cover the following topics:
- [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 `
` component to your project:
```bash
npx shadcn-vue@latest add table
```
2. Add `tanstack/vue-table` dependency:
```bash
npm install @tanstack/vue-table
```
## Examples
### Column Pinning
### Reactive Table
A reactive table was added in `v8.20.0` of the TanStack Table. You can see the [docs](https://tanstack.com/table/latest/docs/framework/vue/guide/table-state#using-reactive-data) for more information. We added an example where we are randomizing `status` column. One main point is that you need to mutate **full** data, as it is a `shallowRef` object.
> __*⚠️ `shallowRef` is used under the hood for performance reasons, meaning that the data is not deeply reactive, only the `.value` is. To update the data you have to mutate the data directly.*__
Relative PR: [Tanstack/table #5687](https://github.com/TanStack/table/pull/5687#issuecomment-2281067245)
If you want to mutate `props.data`, you should use [`defineModel`](https://vuejs.org/api/sfc-script-setup.html#definemodel).
There is no difference between using `ref` or `shallowRef` for your data object; it will be automatically mutated by the TanStack Table to `shallowRef`.
## Prerequisites
We are going to build a table to show recent payments. Here's what our data looks like:
```ts:line-numbers
interface 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: 'example@gmail.com',
},
// ...
]
```
## Project Structure
Start by creating the following file structure:
```ansi
components
└── payments
├── columns.ts
├── data-table.vue
├── data-table-dropdown.vue
└── app.vue
```
I'm using a Nuxt example here but this works for any other Vue framework.
- `columns.ts` It will contain our column definitions.
- `data-table.vue` It will contain our `` component.
- `data-table-dropdown.vue` It will contain our `` component.
- `app.vue` This is where we'll fetch data and render our table.
## Basic Table
Let's start by building a basic table.
### Column Definitions
First, we'll define our columns in the `columns.ts` file.
```ts:line-numbers
import { h } from 'vue'
export const columns: ColumnDef[] = [
{
accessorKey: 'amount',
header: () => h('div', { class: 'text-right' }, 'Amount'),
cell: ({ row }) => {
const amount = Number.parseFloat(row.getValue('amount'))
const formatted = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
}).format(amount)
return h('div', { class: 'text-right font-medium' }, formatted)
},
}
]
```
**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.
### `` component
Next, we'll create a `` component to render our table.
```vue
No results.
```
**Tip**: If you find yourself using `` in multiple places, this is the component you could make reusable by extracting it to `components/ui/data-table.vue`.
``
### Render the table
Finally, we'll render our table in our index component.
```vue
```
## Cell Formatting
Let's format the amount cell to display the dollar amount. We'll also align the cell to the right.
### Update columns definition
Update the `header` and `cell` definitions for amount as follows:
```ts
import { h } from 'vue'
export const columns: ColumnDef[] = [
{
accessorKey: 'amount',
header: () => h('div', { class: 'text-right' }, 'Amount'),
cell: ({ row }) => {
const amount = Number.parseFloat(row.getValue('amount'))
const formatted = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
}).format(amount)
return h('div', { class: 'text-right font-medium' }, formatted)
},
}
]
```
You can use the same approach to format other cells and headers.
## Row Actions
Let's add row actions to our table. We'll use a `` component for this.
### Add the following into your `DataTableDropDown.vue` component
```vue
Actions
Copy payment ID
View customerView payment details
```
### Update columns definition
Update our columns definition to add a new `actions` column. The `actions` cell returns a `` component.
```ts
import DropdownAction from '@/components/DataTableDropDown.vue'
import { ColumnDef } from '@tanstack/vue-table'
export const columns: ColumnDef[] = [
// ...
{
id: 'actions',
enableHiding: false,
cell: ({ row }) => {
const payment = row.original
return h('div', { class: 'relative' }, h(DropdownAction, {
payment,
}))
},
},
]
```
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.
## Pagination
Next, we'll add pagination to our table.
### Update ``
```ts:line-numbers {4,12}
import {
FlexRender,
getCoreRowModel,
getPaginationRowModel,
useVueTable,
} from "@tanstack/vue-table"
const table = useVueTable({
get data() { return props.data },
get columns() { return props.columns },
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
})
```
This will automatically paginate your rows into pages of 10. See the [pagination docs](https://tanstack.com/table/v8/docs/api/features/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 `` component and the `table.previousPage()`, `table.nextPage()` API methods.
```vue
{ // .... }
```
See [Reusable Components](#reusable-components) section for a more advanced pagination component.
## Sorting
Let's make the email column sortable.
### Add the following into your `utils` file
```ts
import type { Updater } from '@tanstack/vue-table'
import type { ClassValue } from 'clsx'
import type { Ref } from 'vue'
import { clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
export function valueUpdater>(updaterOrValue: T, ref: Ref) {
ref.value = typeof updaterOrValue === 'function'
? updaterOrValue(ref.value)
: updaterOrValue
}
```
The `valueUpdater` function updates a Vue `ref` object's value. It handles both direct assignments and transformations using a function. If `updaterOrValue` is a function, it's called with the current `ref` value, and the result is assigned to `ref.value`. If it's not a function, it's directly assigned to `ref.value`. This utility enhances flexibility in updating `ref` values. While Vue `ref` can manage reactive state directly, `valueUpdater` simplifies value updates, improving code readability and maintainability when the new state can be a direct value or a function generating it based on the current one.
### Update ``
```vue:line-numbers {4,14,17,33,40-44}
{ ... }
```
### Make header cell sortable
We can now update the `email` header cell to add sorting controls.
```ts:line-numbers {5,10-17}
// components/payments/columns.ts
import type {
ColumnDef,
} from '@tanstack/vue-table'
import { ArrowUpDown, ChevronDown } from 'lucide-vue-next'
import { Button } from '@/components/ui/button'
export const columns: ColumnDef[] = [
{
accessorKey: 'email',
header: ({ column }) => {
return h(Button, {
variant: 'ghost',
onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'),
}, () => ['Email', h(ArrowUpDown, { class: 'ml-2 h-4 w-4' })])
},
cell: ({ row }) => h('div', { class: 'lowercase' }, row.getValue('email')),
},
]
```
This will automatically sort the table (asc and desc) when the user toggles on the header cell.
## Filtering
Let's add a search input to filter emails in our table.
### Update ``
```vue:line-numbers {4,11,19,39,48-49,52,60-64}
{ ... }
```
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/v8/docs/guide/filters) for more information on customizing filters.
## Visibility
Adding column visibility is fairly simple using `@tanstack/vue-table` visibility API.
### Update ``
```vue:line-numbers {6,9-14,48,59,63,75-91}
```
This adds a dropdown menu that you can use to toggle column visibility.
## Row Selection
Next, we're going to add row selection to our table.
### Update column definitions
```ts:line-numbers {3,6-20}
import type { ColumnDef } from '@tanstack/vue-table'
import { Checkbox } from '@/components/ui/checkbox'
export const columns: ColumnDef[] = [
{
id: 'select',
header: ({ table }) => h(Checkbox, {
'modelValue': table.getIsAllPageRowsSelected(),
'onUpdate:modelValue': (value: boolean) => table.toggleAllPageRowsSelected(!!value),
'ariaLabel': 'Select all',
}),
cell: ({ row }) => h(Checkbox, {
'modelValue': row.getIsSelected(),
'onUpdate:modelValue': (value: boolean) => row.toggleSelected(!!value),
'ariaLabel': 'Select row',
}),
enableSorting: false,
enableHiding: false,
},
]
```
### Update ``
```vue:line-numbers {10,22,27}
```
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.
```vue:line-numbers {8-11}
{{ table.getFilteredSelectedRowModel().rows.length }} of
{{ table.getFilteredRowModel().rows.length }} row(s) selected.
```
### Add the expand action to the `DataTableDropDown.vue` component
```vue:line-numbers {12-14,34-36}
Actions
Copy payment ID
Expand
View customerView payment details
```
### Make rows expandable
Now we can update the action cell to add the expand control.
```vue:line-numbers {11}
```
## Reusable Components
Here are some components you can use to build your data tables. This is from the [Tasks](/examples/tasks) demo.
### Column header
Make any column header sortable and hideable.
```vue:line-numbers
{{ table.getFilteredSelectedRowModel().rows.length }} of
{{ table.getFilteredRowModel().rows.length }} row(s) selected.
Rows per page
Page {{ table.getState().pagination.pageIndex + 1 }} of
{{ table.getPageCount() }}
```
```vue
```
### Column toggle
A component to toggle column visibility.
```vue:line-numbers
Toggle columns column.toggleVisibility(!!value)"
>
{{ column.id }}
```
```vue
```
---
---
url: /docs/components/date-picker.md
description: A date picker component with range and presets.
---
## Installation
The Date Picker is built using a composition of the `` and either the `` or `` components.
See installations instructions for the [Popover](/docs/components/popover), [Calendar](/docs/components/calendar), and [Range Calendar](/docs/components/range-calendar) components.
## Examples
### Date Picker
### Date Range Picker
### Date Range Picker with Independent Months
### With Presets
### Form
---
---
url: /docs/components/dialog.md
description: >-
A window overlaid on either the primary window or another dialog window,
rendering the content underneath inert.
---
## Installation
```bash
npx shadcn-vue@latest add dialog
```
## Usage
```vue
```
## Examples
### Custom close button
### Scroll body
### Scroll overlay
### Form
## Notes
To activate the `Dialog` component from within a `Context Menu` or `Dropdown Menu`, you must encase the `Context Menu` or `Dropdown Menu` component in the `Dialog` component. For more information, refer to the linked issue [here](https://github.com/radix-ui/primitives/issues/1836).
```js:line-numbers showLineNumber{14-25}
```
---
---
url: /docs/charts/donut.md
description: >-
A line chart visually represents data in a circular form, similar to a pie
chart but with a central void, emphasizing proportions within categories.
---
## Installation
Only works with Vue >3.3
### Run the following command
```bash
npx shadcn-vue@latest add chart-donut
```
### Setup
Follow the [guide](/docs/charts.html#installation) to complete the setup.
## API
## Example
### Pie Chart
If you want to render pie chart instead, pass `type` as `pie`.
### Color
We generate colors automatically based on the primary and secondary color and assigned them accordingly. Feel free to pass in your own array of colors.
### Custom Tooltip
If you want to render custom tooltip, you can easily pass in a custom component. Refer to prop definition [here](/docs/charts.html#custom-tooltip).
---
---
url: /docs/components/drawer.md
description: A drawer component for vue.
---
## About
Drawer is built on top of [Vaul Vue](https://github.com/unovue/vaul-vue).
## Installation
```bash
npx shadcn-vue@latest add drawer
```
## Usage
```vue showLineNumbers
OpenAre you absolutely sure?This action cannot be undone.
```
### Scale Background
If you want the background to have a zoom effect, you need to add the `vaul-drawer-wrapper` attribute to the root component.
```html
```
## Examples
### Responsive Dialog
You can combine the `Dialog` and `Drawer` components to create a responsive dialog. This renders a `Dialog` component on desktop and a `Drawer` on mobile.
---
---
url: /docs/components/dropdown-menu.md
description: >-
Displays a menu to the user — such as a set of actions or functions —
triggered by a button.
---
## Installation
```bash
npx shadcn-vue@latest add dropdown-menu
```
## Usage
```vue
OpenMy AccountProfileBillingTeamSubscription
```
## Examples
### Checkboxes
### Radio Group
---
---
url: /docs/registry/examples.md
description: 'Examples of registry items: styles, components, css vars, etc.'
---
## registry:style
### Custom style that extends shadcn-vue
The following registry item is a custom style that extends shadcn-vue. On `npx shadcn-vue init`, it will:
- Install `@iconify/vue` as a dependency.
- Add the `Login01` block and `calendar` component to the project.
- Add the `editor` from a remote registry.
- Set the `font-sans` variable to `Inter, sans-serif`.
- Install a `brand` color in light and dark mode.
```json:line-numbers title="example-style.json"
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json",
"name": "example-style",
"type": "registry:style",
"dependencies": ["@iconify/vue"],
"registryDependencies": [
"Login01",
"calendar",
"https://example.com/r/editor.json"
],
"cssVars": {
"theme": {
"font-sans": "Inter, sans-serif"
},
"light": {
"brand": "20 14.3% 4.1%"
},
"dark": {
"brand": "20 14.3% 4.1%"
}
}
}
```
### Custom style from scratch
The following registry item is a custom style that doesn't extend shadcn-vue. See the `extends: none` field.
It can be used to create a new style from scratch i.e custom components, css vars, dependencies, etc.
On `npx shadcn-vue add`, the following will:
- Install `tailwind-merge` and `clsx` as dependencies.
- Add the `utils` registry item from the shadcn-vue registry.
- Add the `button`, `input`, `label`, and `select` components from a remote registry.
- Install new css vars: `main`, `bg`, `border`, `text`, `ring`.
```json:line-numbers title="example-style.json"
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json",
"extends": "none",
"name": "new-style",
"type": "registry:style",
"dependencies": ["tailwind-merge", "clsx"],
"registryDependencies": [
"utils",
"https://example.com/r/button.json",
"https://example.com/r/input.json",
"https://example.com/r/label.json",
"https://example.com/r/select.json"
],
"cssVars": {
"theme": {
"font-sans": "Inter, sans-serif",
}
"light": {
"main": "#88aaee",
"bg": "#dfe5f2",
"border": "#000",
"text": "#000",
"ring": "#000",
},
"dark": {
"main": "#88aaee",
"bg": "#272933",
"border": "#000",
"text": "#e6e6e6",
"ring": "#fff",
}
}
}
```
## registry:theme
### Custom theme
```json:line-numbers title="example-theme.json"
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json",
"name": "custom-theme",
"type": "registry:theme",
"cssVars": {
"light": {
"background": "oklch(1 0 0)",
"foreground": "oklch(0.141 0.005 285.823)",
"primary": "oklch(0.546 0.245 262.881)",
"primary-foreground": "oklch(0.97 0.014 254.604)",
"ring": "oklch(0.746 0.16 232.661)",
"sidebar-primary": "oklch(0.546 0.245 262.881)",
"sidebar-primary-foreground": "oklch(0.97 0.014 254.604)",
"sidebar-ring": "oklch(0.746 0.16 232.661)"
},
"dark": {
"background": "oklch(1 0 0)",
"foreground": "oklch(0.141 0.005 285.823)",
"primary": "oklch(0.707 0.165 254.624)",
"primary-foreground": "oklch(0.97 0.014 254.604)",
"ring": "oklch(0.707 0.165 254.624)",
"sidebar-primary": "oklch(0.707 0.165 254.624)",
"sidebar-primary-foreground": "oklch(0.97 0.014 254.604)",
"sidebar-ring": "oklch(0.707 0.165 254.624)"
}
}
}
```
### Custom colors
The following style will init using shadcn-vue defaults and then add a custom `brand` color.
```json:line-numbers title="example-style.json"
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json",
"name": "custom-style",
"type": "registry:style",
"cssVars": {
"light": {
"brand": "oklch(0.99 0.00 0)"
},
"dark": {
"brand": "oklch(0.14 0.00 286)"
}
}
}
```
## registry:block
### Custom block
This blocks installs the `Login01` block from the shadcn-vue registry.
```json:line-numbers title="Login01.json"
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json",
"name": "Login01",
"type": "registry:block",
"description": "A simple login form.",
"registryDependencies": ["button", "card", "input", "label"],
"files": [
{
"path": "blocks/Login01/page.vue",
"content": "import { LoginForm } ...",
"type": "registry:page",
"target": "pages/login/index.vue"
},
{
"path": "blocks/Login01/components/LoginForm.vue",
"content": "...",
"type": "registry:component"
}
]
}
```
### Install a block and override primitives
You can install a block fromt the shadcn-vue registry and override the primitives using your custom ones.
On `npx shadcn-vue add`, the following will:
- Add the `Login01` block from the shadcn-vue registry.
- Override the `button`, `input`, and `label` primitives with the ones from the remote registry.
```json:line-numbers title="example-style.json"
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json",
"name": "custom-login",
"type": "registry:block",
"registryDependencies": [
"Login01",
"https://example.com/r/button.json",
"https://example.com/r/input.json",
"https://example.com/r/label.json"
]
}
```
## CSS Variables
### Custom Theme Variables
Add custom theme variables to the `theme` object.
```json:line-numbers title="example-theme.json"
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json",
"name": "custom-theme",
"type": "registry:theme",
"cssVars": {
"theme": {
"font-heading": "Inter, sans-serif",
"shadow-card": "0 0 0 1px rgba(0, 0, 0, 0.1)"
}
}
}
```
### Override Tailwind CSS variables
```json:line-numbers title="example-theme.json"
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json",
"name": "custom-theme",
"type": "registry:theme",
"cssVars": {
"theme": {
"spacing": "0.2rem",
"breakpoint-sm": "640px",
"breakpoint-md": "768px",
"breakpoint-lg": "1024px",
"breakpoint-xl": "1280px",
"breakpoint-2xl": "1536px"
}
}
}
```
## Add custom CSS
### Base styles
```json:line-numbers title="example-base.json"
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json",
"name": "custom-style",
"type": "registry:style",
"css": {
"@layer base": {
"h1": {
"font-size": "var(--text-2xl)"
},
"h2": {
"font-size": "var(--text-xl)"
}
}
}
}
```
### Components
```json:line-numbers title="example-card.json"
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json",
"name": "custom-card",
"type": "registry:component",
"css": {
"@layer components": {
"card": {
"background-color": "var(--color-white)",
"border-radius": "var(--rounded-lg)",
"padding": "var(--spacing-6)",
"box-shadow": "var(--shadow-xl)"
}
}
}
}
```
## Add custom utilities
### Simple utility
```json:line-numbers title="example-component.json"
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json",
"name": "custom-component",
"type": "registry:component",
"css": {
"@utility content-auto": {
"content-visibility": "auto"
}
}
}
```
### Complex utility
```json:line-numbers title="example-utility.json"
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json",
"name": "custom-component",
"type": "registry:component",
"css": {
"@utility scrollbar-hidden": {
"scrollbar-hidden": {
"&::-webkit-scrollbar": {
"display": "none"
}
}
}
}
}
```
### Functional utilities
```json:line-numbers title="example-functional.json"
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json",
"name": "custom-component",
"type": "registry:component",
"css": {
"@utility tab-*": {
"tab-size": "var(--tab-size-*)"
}
}
}
```
## Add custom animations
Note: you need to define both `@keyframes` in css and `theme` in cssVars to use animations.
```json:line-numbers title="example-component.json"
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json",
"name": "custom-component",
"type": "registry:component",
"cssVars": {
"theme": {
"--animate-wiggle": "wiggle 1s ease-in-out infinite"
}
},
"css": {
"@keyframes wiggle": {
"0%, 100%": {
"transform": "rotate(-3deg)"
},
"50%": {
"transform": "rotate(3deg)"
}
}
}
}
```
---
---
url: /docs/registry/faq.md
description: Frequently asked questions about running a registry.
---
## Frequently asked questions
### What does a complex component look like?
Here's an example of a complex component that installs a page, two components, a composable, a format date utils and a config file.
```json:line-numbers
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json",
"name": "hello-world",
"title": "Hello World",
"type": "registry:block",
"description": "A complex hello world component",
"files": [
{
"path": "registry/new-york/HelloWorld/page.vue",
"type": "registry:page",
"target": "pages/hello/index.vue"
},
{
"path": "registry/new-york/HelloWorld/components/HelloWorld.vue",
"type": "registry:component"
},
{
"path": "registry/new-york/HelloWorld/components/FormattedMessage.vue",
"type": "registry:component"
},
{
"path": "registry/new-york/HelloWorld/composables/useHello.ts",
"type": "registry:hook"
},
{
"path": "registry/new-york/HelloWorld/lib/formatDate.ts",
"type": "registry:utils"
},
{
"path": "registry/new-york/HelloWorld/hello.config.ts",
"type": "registry:file",
"target": "~/hello.config.ts"
}
]
}
```
### How do I add a new Tailwind color?
To add a new color you need to add it to `cssVars` and `tailwind.config.theme.extend.colors`.
```json:line-numbers {10-19} {24-29}
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json",
"name": "hello-world",
"title": "Hello World",
"type": "registry:block",
"description": "A complex hello world component",
"files": [
// ...
],
"cssVars": {
"light": {
"brand-background": "20 14.3% 4.1%",
"brand-accent": "20 14.3% 4.1%"
},
"dark": {
"brand-background": "20 14.3% 4.1%",
"brand-accent": "20 14.3% 4.1%"
}
},
"tailwind": {
"config": {
"theme": {
"extend": {
"colors": {
"brand": {
"DEFAULT": "hsl(var(--brand-background))",
"accent": "hsl(var(--brand-accent))"
}
}
}
}
}
}
}
```
The CLI will update the project CSS file and tailwind.config.js file. Once updated, the new colors will be available to be used as utility classes: `bg-brand` and `text-brand-accent`.
### How do I add a Tailwind animation?
To add a new animation you add it to `tailwind.config.theme.extend.animation` and `tailwind.config.theme.extend.keyframes`.
```json:line-numbers {14-22}
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json",
"name": "hello-world",
"title": "Hello World",
"type": "registry:block",
"description": "A complex hello world component",
"files": [
// ...
],
"tailwind": {
"config": {
"theme": {
"extend": {
"keyframes": {
"wiggle": {
"0%, 100%": { "transform": "rotate(-3deg)" },
"50%": { "transform": "rotate(3deg)" }
}
},
"animation": {
"wiggle": "wiggle 1s ease-in-out infinite"
}
}
}
}
}
}
```
---
---
url: /docs/figma.md
description: >-
Every component recreated in Figma. With customizable props, typography and
icons.
---
The Figma UI Kit is open sourced by [Pietro Schirano](https://twitter.com/skirano).
## Grab a copy
---
---
url: /docs/registry/getting-started.md
description: Learn how to get setup and run your own component registry.
---
This guide will walk you through the process of setting up your own component registry.
It assumes you already have a project with components and would like to turn it into a registry.
## registry.json
The `registry.json` file is only required if you're using the `shadcn-vue` CLI to build your registry.
If you're using a different build system, you can skip this step as long as your build system produces valid JSON files that conform to the [registry-item schema specification](/docs/registry/registry-item-json).
### Add a registry.json file
Create a `registry.json` file in the root of your project. Your project can be a Nuxt, Vite, or any other project that supports Vue.
```json:line-numbers title="registry.json"
{
"$schema": "https://shadcn-vue.com/schema/registry.json",
"name": "acme",
"homepage": "https://acme.com",
"items": [
// ...
]
}
```
This `registry.json` file must conform to the [registry schema specification](/docs/registry/registry-json).
## Add a registry item
### Create your component
Add your first component. Here's an example of a simple `` component:
```vue:line-numbers title="registry/new-york/HelloWorld/HelloWorld.vue"
```
**Note:** This example places the component in the `registry/new-york`
directory. You can place it anywhere in your project as long as you set the
correct path in the `registry.json` file and you follow the `registry/[NAME]`
directory structure.
```txt
registry
└── new-york
└── HelloWorld
└── HelloWorld.vue
```
**Important:** If you're placing your component in a custom directory, make
sure it is configured in your `tailwind.config.ts` file.
```ts:line-numbers
// tailwind.config.ts
export default {
content: ["./registry/**/*.{js,ts,jsx,tsx,vue}"],
}
```
### Add your component to the registry
To add your component to the registry, you need to add your component definition to `registry.json`.
```json:line-numbers title="registry.json" {6-17}
{
"$schema": "https://shadcn-vue.com/schema/registry.json",
"name": "acme",
"homepage": "https://acme.com",
"items": [
{
"name": "hello-world",
"type": "registry:block",
"title": "Hello World",
"description": "A simple hello world component.",
"files": [
{
"path": "registry/new-york/HelloWorld/HelloWorld.vue",
"type": "registry:component"
}
]
}
]
}
```
You define your registry item by adding a `name`, `type`, `title`, `description` and `files`.
For every file you add, you must specify the `path` and `type` of the file. The `path` is the relative path to the file from the root of your project. The `type` is the type of the file.
You can read more about the registry item schema and file types in the [registry item schema docs](/docs/registry/registry-item-json).
## Build your registry
### Install the shadcn-vue CLI
Note: the `build` command is currently only available in the `shadcn-vue@canary` version of the CLI.
```bash
npm install shadcn-vue@latest
```
### Add a build script
Add a `registry:build` script to your `package.json` file.
```json:line-numbers title="package.json"
{
"scripts": {
"registry:build": "shadcn-vue build"
}
}
```
### Run the build script
Run the build script to generate the registry JSON files.
```bash
npm run registry:build
```
**Note:** By default, the build script will generate the registry JSON files in `public/r` e.g `public/r/hello-world.json`.
You can change the output directory by passing the `--output` option. See the [shadcn build command](/docs/cli#build) for more information.
## Serve your registry
If you're running your registry on Nuxt, you can now serve your registry by running the `nuxt` server. The command might differ for other frameworks.
```bash
npm run dev
```
Your files will now be served at `http://localhost:3000/r/[NAME].json` eg. `http://localhost:3000/r/hello-world.json`.
## Publish your registry
To make your registry available to other developers, you can publish it by deploying your project to a public URL.
## Adding Auth
The `shadcn-vue` CLI does not offer a built-in way to add auth to your registry. We recommend handling authorization on your registry server.
A common simple approach is to use a `token` query parameter to authenticate requests to your registry. e.g. `http://localhost:3000/r/hello-world.json?token=[SECURE_TOKEN_HERE]`.
Use the secure token to authenticate requests and return a 401 Unauthorized response if the token is invalid. Both the `shadcn` CLI and `Open in v0` will handle the 401 response and display a message to the user.
**Note:** Make sure to encrypt and expire tokens.
## Guidelines
Here are some guidelines to follow when building components for a registry.
- Place your registry item in the `registry/[STYLE]/[NAME]` directory. I'm using `new-york` as an example. It can be anything you want as long as it's nested under the `registry` directory.
- The following properties are required for the block definition: `name`, `description`, `type` and `files`.
- Make sure to list all registry dependencies in `registryDependencies`. A registry dependency is the name of the component in the registry eg. `input`, `button`, `card`, etc or a URL to a registry item eg. `http://localhost:3000/r/editor.json`.
- Make sure to list all dependencies in `dependencies`. A dependency is the name of the package in the registry eg. `zod`, `sonner`, etc. To set a version, you can use the `name@version` format eg. `zod@^3.20.0`.
- **Imports should always use the `@/registry` path.** eg. `import { HelloWorld } from "@/registry/new-york/hello-world/hello-world"`
- Ideally, place your files within a registry item in `components`, `hooks`, `lib` directories.
## Install using the CLI
To install a registry item using the `shadcn-vue` CLI, use the `add` command followed by the URL of the registry item.
```bash
npx shadcn-vue@latest add http://localhost:3000/r/hello-world.json
```
---
---
url: /docs/components/hover-card.md
description: For sighted users to preview content available behind a link.
---
## Installation
```bash
npx shadcn-vue@latest add hover-card
```
## Usage
```vue
Hover
The Vue Framework – created and maintained by @vuejs.
```
---
---
url: /docs/components/input.md
description: Displays a form input field or a component that looks like an input field.
---
## Installation
```bash
npx shadcn-vue@latest add input
```
### Copy and paste the following code into your project:
<<< @/registry/default/ui/input/Input.vue
## Usage
```vue
```
## Examples
### Default
### File
### Disabled
### With Label
### With Button
### With Icon
### Form
---
---
url: /docs/installation.md
description: How to install dependencies and structure your app.
---
## Frameworks
Vite
Nuxt
Astro
Laravel
Manual
## TypeScript
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 `typescript` flag in your `components.json` file.
```json {9} title="components.json"
{
"style": "default",
"tailwind": {
"config": "tailwind.config.js",
"css": "src/app/globals.css",
"baseColor": "zinc",
"cssVariables": true
},
"typescript": false,
"aliases": {
"utils": "~/lib/utils",
"components": "~/components"
}
}
```
To configure import aliases, you can use the following `jsconfig.json`:
```json {4} title="jsconfig.json"
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}
```
## VSCode extension
Install the [shadcn-vue](https://marketplace.visualstudio.com/items?itemName=Selemondev.shadcn-vue) extension by [@selemondev](https://github.com/selemondev) in Visual Studio Code to easily add Shadcn Vue components to your project.
This extension offers a range of features:
- Ability to initialize the Shadcn Vue CLI
- Install components
- Open documentation
- Navigate to a specific component's documentation page directly from your IDE.
- Handy snippets for quick and straightforward component imports and markup.
---
---
url: /docs/introduction.md
description: 'Re-usable components built with Radix Vue, and Tailwind CSS.'
---
An unofficial, community-led [Vue](https://vuejs.org/) port of [shadcn/ui](https://ui.shadcn.com). We are not affiliated with [shadcn](https://twitter.com/shadcn), but we did get his blessing before creating a Vue version of his work. This project was born out of the need for a similar project for the Vue ecosystem.
This is **NOT** a component library. It's a collection of re-usable components that you can copy and paste or use the CLI to add to your apps.
**What do you mean not a component library?**
It means you do not install it as a dependency. It is not available or distributed via npm, with no plans to publish it.
Pick the components you need. Use the CLI to automatically add the components, or copy and paste the code into your project and customize to your needs. The code is yours.
_Use this as a reference to build your own component libraries._
## FAQ
Why not packaged as a dependency?
The idea behind this is to give you ownership and control over the code, allowing you to decide how the components are built and styled.
Start with some sensible defaults, then customize the components to your needs.
One of the drawback of packaging the components in an npm package is that the style is coupled with the implementation. _The design of your components should be separate from their implementation._
Which frameworks are supported?
This port is built to be used with Vue/Nuxt.
Can I use this in my project?
Yes. Free to use for personal and commercial projects. No attribution required.
But let us know if you do use it. We'd love to see what you build with it.
---
---
url: /docs/components/label.md
description: Renders an accessible label associated with controls.
---
## Installation
```bash
npx shadcn-vue@latest add label
```
### Install the following dependency:
```bash
npm install reka-ui
```
### Copy and paste the following code into your project:
<<< @/registry/default/ui/label/Label.vue
## Usage
```vue
```
---
---
url: /docs/installation/laravel.md
description: Install and configure Laravel with Inertia
---
**Note:** The following guide is for Tailwind v4. If you are using Tailwind
v3, use `shadcn-vue@1.0.3`.
### Create project
Start by creating a new Laravel project with Inertia and Vue using the laravel installer `laravel new my-app`:
```bash
laravel new my-app --vue
```
### Add Components
You can now start adding components to your project.
```bash
npx shadcn-vue@latest add switch
```
The command above will add the `Switch` component to `resources/js/components/ui/switch`. You can then import it like this:
```vue {2,7}
```
---
---
url: /docs/charts/line.md
description: >-
A line chart visually displays data points connected by straight lines,
illustrating trends or relationships over a continuous axis.
---
## Installation
Only works with Vue >3.3
### Run the following command
```bash
npx shadcn-vue@latest add chart-line
```
### Setup
Follow the [guide](/docs/charts.html#installation) to complete the setup.
## API
## Example
### Sparkline
We can turn the chart into sparkline chart by hiding axis, gridline and legends.
### Custom Tooltip
If you want to render custom tooltip, you can easily pass in a custom component. Refer to prop definition [here](/docs/charts.html#custom-tooltip).
---
---
url: /docs/installation/manual.md
description: Add dependencies to your project manually.
---
### Add Tailwind CSS
Components are styled using Tailwind CSS. You need to install Tailwind CSS in your project.
[Follow the Tailwind CSS installation instructions to get started.](https://tailwindcss.com/docs/installation)
### Add dependencies
Add the following dependencies to your project:
```bash
npm install class-variance-authority clsx tailwind-merge lucide-vue-next tw-animate-css
```
### Configure path aliases
Configure the path aliases in your `tsconfig.json` file.
```json:line-numbers {3-6} title="tsconfig.json"
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./*"]
}
}
}
```
The `@` alias is a preference. You can use other aliases if you want.
### Configure styles
Add the following to your styles/globals.css file. You can learn more about using CSS variables for theming in the [theming section](/docs/theming).
```css:line-numbers title="src/styles/globals.css"
@import "tailwindcss";
@import "tw-animate-css";
@custom-variant dark (&:is(.dark *));
:root {
--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);
--destructive-foreground: 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);
--radius: 0.625rem;
--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.145 0 0);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.145 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.985 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.396 0.141 25.723);
--destructive-foreground: oklch(0.637 0.237 25.331);
--border: oklch(0.269 0 0);
--input: oklch(0.269 0 0);
--ring: oklch(0.439 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(0.269 0 0);
--sidebar-ring: oklch(0.439 0 0);
}
@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-destructive-foreground: var(--destructive-foreground);
--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);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--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);
--animate-accordion-down: accordion-down 0.2s ease-out;
--animate-accordion-up: accordion-up 0.2s ease-out;
@keyframes accordion-down {
from {
height: 0;
}
to {
height: var(--reka-accordion-content-height);
}
}
@keyframes accordion-up {
from {
height: var(--reka-accordion-content-height);
}
to {
height: 0;
}
}
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
}
```
### Add a cn helper
```ts:line-numbers title="lib/utils.ts"
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
```
### Create a `components.json` file
Create a `components.json` file in the root of your project.
```json:line-numbers title="components.json"
{
"$schema": "https://shadcn-vue.com/schema.json",
"style": "new-york",
"typescript": true,
"tailwind": {
"config": "",
"css": "src/styles/globals.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"composables": "@/composables",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
},
"iconLibrary": "lucide"
}
```
### That's it
You can now start adding components to your project.
---
---
url: /docs/components/menubar.md
description: >-
A visually persistent menu common in desktop applications that provides quick
access to a consistent set of commands.
---
## Installation
```bash
npx shadcn-vue@latest add menubar
```
## Usage
```vue
File
New Tab ⌘TNew WindowSharePrint
```
---
---
url: /docs/components/navigation-menu.md
description: A collection of links for navigating websites.
---
## Installation
```bash
npx shadcn-vue@latest add navigation-menu
```
## Usage
```vue
Item OneLink
```
## Examples
### Link Component
When using the Nuxt `` component, you can use `navigationMenuTriggerStyle()` to apply the correct styles to the trigger.
```ts
import { navigationMenuTriggerStyle } from '@/components/ui/navigation-menu'
```
```vue
Documentation
```
---
---
url: /docs/components/number-field.md
description: >-
A number field allows a user to enter a number and increment or decrement the
value using stepper buttons.
---
## Installation
```bash
npx shadcn-vue@latest add number-field
```
## Usage
```vue
```
## Examples
### Default
### Disabled
### Decimal
### Percentage
### Currency
### Form
---
---
url: /docs/dark-mode/nuxt.md
description: Adding dark mode to your nuxt app.
---
## Dark mode
### Install Dependencies
```bash
npm install -D @nuxtjs/color-mode
```
Then, add `@nuxtjs/color-mode` to the modules section of your `nuxt.config.ts`
```ts
export default defineNuxtConfig({
modules: [
'@nuxtjs/tailwindcss',
'@nuxtjs/color-mode'
],
colorMode: {
classSuffix: ''
}
})
```
### Add a mode toggle
Place a mode toggle on your site to toggle between light and dark mode.
We're using [`useColorMode`](https://color-mode.nuxtjs.org/#usage) from [`Nuxt Color Mode`](https://color-mode.nuxtjs.org/).
Optional, to include icons for theme button.
```bash
npm install -D @iconify/vue @iconify-json/radix-icons
```
```vue
Light
Dark
System
```
---
---
url: /docs/installation/nuxt.md
description: Install and configure Nuxt.
---
**Note:** The following guide is for Tailwind v4. If you are using Tailwind
v3, use `shadcn-vue@1.0.3`.
### Create project
Start by creating a new Nuxt project using `create-nuxt-app`:
```bash
npm create nuxt@latest
```
If you encounter the error `ERROR: Cannot read properties of undefined (reading 'sys') (x4)`, please proceed to install TypeScript as a dependency, as advised in this [issue](https://github.com/nuxt/nuxt/issues/20936)
```bash
npm install -D typescript
```
### Add Tailwind CSS
```bash
npm install tailwindcss @tailwindcss/vite
```
Replace everything in `assets/css/tailwind.css` with the following:
```css title="assets/css/tailwind.css"
@import "tailwindcss";
```
Update `nuxt.config.ts` with the following:
```ts
import tailwindcss from '@tailwindcss/vite'
export default defineNuxtConfig({
// ...
css: ['~/assets/css/tailwind.css'],
vite: {
plugins: [
tailwindcss(),
],
},
})
```
### Add `Nuxt` module
Due to Nuxt auto-import feature, if you skip this step you will observe many warning in console.
Install the package below.
```bash
npx nuxi@latest module add shadcn-nuxt
```
Add the following code to `modules/shadcn.ts`.
```bash
import {
defineNuxtModule,
addComponent,
addComponentsDir,
tryResolveModule,
} from 'nuxt/kit';
export interface ShadcnVueOptions {
/**
* Prefix for all the imported component
*/
prefix: string;
/**
* Directory that the component lives in.
* @default "~/components/ui"
*/
componentDir: string;
}
export default defineNuxtModule({
defaults: {
prefix: 'Ui',
componentDir: '~/components/ui',
},
meta: {
name: 'ShadcnVue',
configKey: 'shadcn',
version: '0.0.1',
compatibility: {
nuxt: '>=3.9.0',
bridge: false,
},
},
async setup({ componentDir, prefix }) {
const veeValidate = await tryResolveModule('vee-validate');
const vaulVue = await tryResolveModule('vaul-vue');
addComponentsDir(
{
path: componentDir,
extensions: ['.vue'],
prefix,
pathPrefix: false,
},
{
prepend: true,
}
);
if (veeValidate !== undefined) {
addComponent({
filePath: 'vee-validate',
export: 'Form',
name: `${prefix}Form`,
priority: 999,
});
addComponent({
filePath: 'vee-validate',
export: 'Field',
name: `${prefix}FormField`,
priority: 999,
});
}
if(vaulVue !== undefined) {
['DrawerPortal', 'DrawerTrigger', 'DrawerClose'].forEach((item) => {
addComponent({
filePath: 'vaul-vue',
export: item,
name: prefix + item,
priority: 999,
});
})
}
addComponent({
filePath: 'reka-ui',
export: 'PaginationRoot',
name: `${prefix}Pagination`,
priority: 999,
});
addComponent({
filePath: 'reka-ui',
export: 'PaginationList',
name: `${prefix}PaginationList`,
priority: 999,
});
addComponent({
filePath: 'reka-ui',
export: 'PaginationListItem',
name: `${prefix}PaginationListItem`,
priority: 999,
});
},
});
declare module '@nuxt/schema' {
interface NuxtConfig {
shadcn?: ShadcnVueOptions;
}
interface NuxtOptions {
shadcn?: ShadcnVueOptions;
}
}
```
### Configure `nuxt.config.ts`
```ts
export default defineNuxtConfig({
// ...
modules: ['shadcn-nuxt'],
shadcn: {
/**
* Prefix for all the imported component
*/
prefix: '',
/**
* Directory that the component lives in.
* @default "./components/ui"
*/
componentDir: './components/ui'
}
})
```
### Run Nuxt Prepare
If you are initiating a new project, you need to run the command so that Nuxt generates the necessary `.nuxt` folder:
```bash
npx nuxi prepare
```
### Run the CLI
Run the `shadcn-vue` init command to setup your project:
```bash
npx shadcn-vue@latest init
```
You will be asked a few questions to configure `components.json`.
```txt
Which color would you like to use as base color? › Neutral
```
### Add Components
You can now start adding components to your project.
```bash
npx shadcn-vue@latest add button
```
The command above will add the `Button` component to your project. Nuxt autoImport will handle importing the components, you can just use it as such:
```vue {3}
```
---
---
url: /docs/components/pagination.md
description: Displays data in paged format and provides navigation between pages.
---
## Installation
```bash
npx shadcn-vue@latest add pagination
```
## Usage
```vue
```
---
---
url: /docs/components/pin-input.md
description: Allows users to input a sequence of one-character alphanumeric inputs.
---
## Installation
```bash
npx shadcn-vue@latest add pin-input
```
## Usage
### Controlled
### Disabled
### Separator
### Form
---
---
url: /docs/components/popover.md
description: 'Displays rich content in a portal, triggered by a button.'
---
## Installation
```bash
npx shadcn-vue@latest add popover
```
## Usage
```vue
Open popover
Some popover content
```
---
---
url: /docs/components/progress.md
description: >-
Displays an indicator showing the completion progress of a task, typically
displayed as a progress bar.
---
## Installation
```bash
npx shadcn-vue@latest add progress
```
### Install the following dependency:
```bash
npm install reka-ui
```
### Copy and paste the following code into your project:
<<< @/registry/default/ui/progress/Progress.vue
## Usage
```vue
```
---
---
url: /docs/components/radio-group.md
description: >-
A set of checkable buttons—known as radio buttons—where no more than one of
the buttons can be checked at a time.
---
## Installation
```bash
npx shadcn-vue@latest add radio-group
```
## Usage
```vue
```
## Examples
### Form
Please first read `vee-validate` section for [Checkbox and Radio Inputs](https://vee-validate.logaretm.com/v4/examples/checkboxes-and-radio/)
---
---
url: /docs/components/range-calendar.md
description: A calendar component that allows users to select a range of dates.
---
## About
The `` component is built on top of the [RadixVue Range Calendar](https://www.reka-ui.com/docs/components/date-range-picker.html) component, which uses the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package to handle dates.
## Installation
```bash
npx shadcn-vue@latest add range-calendar
```
---
---
url: /docs/registry/index.md
description: Run your own component registry.
---
**Note:** This feature is currently experimental. Help us improve it by
testing it out and sending feedback. If you have any questions, please [reach
out to us](https://github.com/unovue/shadcn-vue/discussions).
You can use the `shadcn-vue` CLI to run your own component registry. Running your own registry allows you to distribute your custom components, hooks, pages, and other files to any Vue project.
Registry items are automatically compatible with the `shadcn-vue` CLI.
## Requirements
You are free to design and host your custom registry as you see fit. The only requirement is that your registry items must be valid JSON files that conform to the [registry-item schema specification](/docs/registry/registry-item-json).
---
---
url: /docs/registry/registry-item-json.md
description: Specification for registry items.
---
The `registry-item.json` schema is used to define your custom registry items.
```json:line-numbers title="registry-item.json"
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json",
"name": "hello-world",
"type": "registry:block",
"title": "Hello World",
"description": "A simple hello world component.",
"files": [
{
"path": "registry/new-york/HelloWorld/HelloWorld.vue",
"type": "registry:component"
},
{
"path": "registry/new-york/HelloWorld/useHelloWorld.ts",
"type": "registry:hook"
}
]
}
```
## Definitions
You can see the JSON Schema for `registry-item.json` [here](https://shadcn-vue.com/schema/registry-item.json).
### $schema
The `$schema` property is used to specify the schema for the `registry-item.json` file.
```json:line-numbers title="registry-item.json"
{
"$schema": "https://shadcn-vue.com/schema/registry-item.json"
}
```
### name
The `name` property is used to specify the name of your registry item.
```json:line-numbers title="registry-item.json"
{
"name": "hello-world"
}
```
### title
A human-readable title for your registry item. Keep it short and descriptive.
```json:line-numbers title="registry-item.json"
{
"title": "Hello World"
}
```
### description
A description of your registry item. This can be longer and more detailed than the `title`.
```json:line-numbers title="registry-item.json"
{
"description": "A simple hello world component."
}
```
### type
The `type` property is used to specify the type of your registry item.
```json:line-numbers title="registry-item.json"
{
"type": "registry:block"
}
```
The following types are supported:
| Type | Description |
| -------------------- | ------------------------------------------------ |
| `registry:block` | Use for complex components with multiple files. |
| `registry:component` | Use for simple components. |
| `registry:lib` | Use for lib and utils. |
| `registry:hook` | Use for composables (hooks). |
| `registry:ui` | Use for UI components and single-file primitives |
| `registry:page` | Use for page or file-based routes. |
| `registry:file` | Use for miscellaneous files. |
### author
The `author` property is used to specify the author of the registry item.
It can be unique to the registry item or the same as the author of the registry.
```json:line-numbers title="registry-item.json"
{
"author": "John Doe "
}
```
### dependencies
The `dependencies` property is used to specify the dependencies of your registry item. This is for `npm` packages.
Use `@version` to specify the version of your registry item.
```json:line-numbers title="registry-item.json"
{
"dependencies": [
"reka-ui",
"zod",
"lucide-vue-next",
"name@1.0.2"
]
}
```
### registryDependencies
Used for registry dependencies. Can be names or URLs.
- For `shadcn/ui` registry items such as `button`, `input`, `select`, etc use the name eg. `['button', 'input', 'select']`.
- For custom registry items use the URL of the registry item eg. `['https://example.com/r/hello-world.json']`.
```json:line-numbers title="registry-item.json"
{
"registryDependencies": [
"button",
"input",
"select",
"https://example.com/r/editor.json"
]
}
```
Note: The CLI will automatically resolve remote registry dependencies.
### files
The `files` property is used to specify the files of your registry item. Each file has a `path`, `type` and `target` (optional) property.
**The `target` property is required for `registry:page` and `registry:file` types.**
```json:line-numbers title="registry-item.json"
{
"files": [
{
"path": "registry/new-york/HelloWorld/page.vue",
"type": "registry:page",
"target": "pages/hello/index.vue"
},
{
"path": "registry/new-york/HelloWorld/HelloWorld.vue",
"type": "registry:component"
},
{
"path": "registry/new-york/HelloWorld/useHelloWorld.ts",
"type": "registry:hook"
},
{
"path": "registry/new-york/HelloWorld/.env",
"type": "registry:file",
"target": "~/.env"
}
]
}
```
#### path
The `path` property is used to specify the path to the file in your registry. This path is used by the build script to parse, transform and build the registry JSON payload.
#### type
The `type` property is used to specify the type of the file. See the [type](#type) section for more information.
#### target
The `target` property is used to indicate where the file should be placed in a project. This is optional and only required for `registry:page` and `registry:file` types.
By default, the `shadcn-vue` cli will read a project's `components.json` file to determine the target path. For some files, such as routes or config you can specify the target path manually.
Use `~` to refer to the root of the project e.g `~/foo.config.js`.
### tailwind
**DEPRECATED:** Use `cssVars.theme` instead for Tailwind v4 projects.
The `tailwind` property is used for tailwind configuration such as `theme`, `plugins` and `content`.
You can use the `tailwind.config` property to add colors, animations and plugins to your registry item.
```json:line-numbers title="registry-item.json"
{
"tailwind": {
"config": {
"theme": {
"extend": {
"colors": {
"brand": "hsl(var(--brand))"
},
"keyframes": {
"wiggle": {
"0%, 100%": { "transform": "rotate(-3deg)" },
"50%": { "transform": "rotate(3deg)" }
}
},
"animation": {
"wiggle": "wiggle 1s ease-in-out infinite"
}
}
}
}
}
}
```
### cssVars
Use to define CSS variables for your registry item.
```json:line-numbers title="registry-item.json"
{
"cssVars": {
"light": {
"brand": "20 14.3% 4.1%",
"radius": "0.5rem"
},
"dark": {
"brand": "20 14.3% 4.1%"
}
}
}
```
### css
Use `css` to add new rules to the project's CSS file eg. `@layer base`, `@layer components`, `@utility`, `@keyframes`, etc.
```json:line-numbers title="registry-item.json"
{
"css": {
"@layer base": {
"body": {
"font-size": "var(--text-base)",
"line-height": "1.5"
}
},
"@layer components": {
"button": {
"background-color": "var(--color-primary)",
"color": "var(--color-white)"
}
},
"@utility text-magic": {
"font-size": "var(--text-base)",
"line-height": "1.5"
},
"@keyframes wiggle": {
"0%, 100%": {
"transform": "rotate(-3deg)"
},
"50%": {
"transform": "rotate(3deg)"
}
}
}
}
```
### docs
Use `docs` to show custom documentation or message when installing your registry item via the CLI.
```json:line-numbers title="registry-item.json"
{
"docs": "Remember to add the FOO_BAR environment variable to your .env file."
}
```
### categories
Use `categories` to organize your registry item.
```json:line-numbers title="registry-item.json"
{
"categories": ["sidebar", "dashboard"]
}
```
### meta
Use `meta` to add additional metadata to your registry item. You can add any key/value pair that you want to be available to the registry item.
```json:line-numbers title="registry-item.json"
{
"meta": { "foo": "bar" }
}
```
---
---
url: /docs/registry/registry-json.md
description: Schema for running your own component registry.
---
The `registry.json` schema is used to define your custom component registry.
```json:line-numbers title="registry.json"
{
"$schema": "https://shadcn-vue.com/schema/registry.json",
"name": "shadcn",
"homepage": "https://shadcn-vue.com",
"items": [
{
"name": "hello-world",
"type": "registry:block",
"title": "Hello World",
"description": "A simple hello world component.",
"files": [
{
"path": "registry/new-york/HelloWorld/HelloWorld.vue",
"type": "registry:component"
}
]
}
]
}
```
## Definitions
You can see the JSON Schema for `registry.json` [here](https://shadcn-vue.com/schema/registry.json).
### $schema
The `$schema` property is used to specify the schema for the `registry.json` file.
```json:line-numbers title="registry.json"
{
"$schema": "https://shadcn-vue.com/schema/registry.json"
}
```
### name
The `name` property is used to specify the name of your registry. This is used for data attributes and other metadata.
```json:line-numbers title="registry.json"
{
"name": "acme"
}
```
### homepage
The homepage of your registry. This is used for data attributes and other metadata.
```json:line-numbers title="registry.json"
{
"homepage": "https://acme.com"
}
```
### items
The `items` in your registry. Each item must implement the [registry-item schema specification](https://shadcn-vue.com/schema/registry-item.json).
```json:line-numbers title="registry.json"
{
"items": [
{
"name": "hello-world",
"type": "registry:block",
"title": "Hello World",
"description": "A simple hello world component.",
"files": [
{
"path": "registry/new-york/HelloWorld/HelloWorld.vue",
"type": "registry:component"
}
]
}
]
}
```
See the [registry-item schema documentation](/docs/registry/registry-item-json) for more information.
---
---
url: /docs/components/resizable.md
description: Accessible resizable panel groups and layouts with keyboard support.
---
## Installation
```bash
npx shadcn-vue@latest add resizable
```
### Install the following dependency:
```bash
npm install reka-ui
```
### Copy and paste the following code into your project:
`index.ts`
<<< @/registry/default/ui/resizable/index.ts
`ResizablePanelGroup.vue`
<<< @/registry/default/ui/resizable/ResizablePanelGroup.vue
`ResizableHandle.vue`
<<< @/registry/default/ui/resizable/ResizableHandle.vue
## Usage
```vue
OneTwo
```
## Examples
### Vertical
Use the direction prop to set the direction of the resizable panels.
```vue:line-numbers {10}
OneTwo
```
### Handle
You can set or hide the handle by using the withHandle prop on the ResizableHandle component.
```vue:line-numbers {12}
OneTwo
```
---
---
url: /docs/components/scroll-area.md
description: 'Augments native scroll functionality for custom, cross-browser styling.'
---
## Installation
```bash
npx shadcn-vue@latest add scroll-area
```
## Usage
```vue
Jokester began sneaking into the castle in the middle of the night and leaving
jokes all over the place: under the king's pillow, in his soup, even in the
royal toilet. The king was furious, but he couldn't seem to stop Jokester. And
then, one day, the people of the kingdom discovered that the jokes left by
Jokester were so funny that they couldn't help but laugh. And once they
started laughing, they couldn't stop.
```
## Examples
### Horizontal Scrolling
---
---
url: /docs/components/select.md
description: Displays a list of options for the user to pick from—triggered by a button.
---
## Installation
```bash
npx shadcn-vue@latest add select
```
## Usage
```vue
```
## Examples
### Scrollable
### Form
---
---
url: /docs/components/separator.md
description: Visually or semantically separates content.
---
## Installation
```bash
npx shadcn-vue@latest add separator
```
### Install the following dependency
```bash
npm install reka-ui
```
### Copy and paste the following code into your project
<<< @/registry/default/ui/separator/Separator.vue
## Usage
```vue
```
---
---
url: /docs/components/sheet.md
description: >-
Extends the Dialog component to display content that complements the main
content of the screen.
---
## Installation
```bash
npx shadcn-vue@latest add sheet
```
## Usage
```vue
OpenAre you absolutely sure?
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
```
## Examples
### Side
Use the `side` property to `` to indicate the edge of the screen where the component will appear. The values can be `top`, `right`, `bottom` or `left`.
### Size
You can adjust the size of the sheet using CSS classes:
```vue:line-numbers {4}
OpenAre you absolutely sure?
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
```
---
---
url: /docs/components/sidebar.md
description: 'A composable, themeable and customizable sidebar component.'
---
A sidebar that collapses to icons.
Sidebars are one of the most complex components to build. They are central
to any application and often contain a lot of moving parts.
I don't like building sidebars. So I built 30+ of them. All kinds of
configurations. Then I extracted the core components into `Sidebar*.vue`.
We now have a solid foundation to build on top of. Composable. Themeable.
Customizable.
[Browse the Blocks Library](/blocks).
## Installation
### install this component
```bash
npx shadcn-vue@latest add sidebar
```
### Add the following colors to your CSS file
The command above should install the colors for you. If not, copy and paste the following in your CSS file.
```css
@layer base {
:root {
--sidebar-background: 0 0% 98%;
--sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 240 4.8% 95.9%;
--sidebar-accent-foreground: 240 5.9% 10%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
.dark {
--sidebar-background: 240 5.9% 10%;
--sidebar-foreground: 240 4.8% 95.9%;
--sidebar-primary: 224.3 76.3% 48%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 240 3.7% 15.9%;
--sidebar-accent-foreground: 240 4.8% 95.9%;
--sidebar-border: 240 3.7% 15.9%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
}
```
## Structure
A `Sidebar` component is composed of the following parts:
- `SidebarProvider` - Handles collapsible state.
- `Sidebar` - The sidebar container.
- `SidebarHeader` and SidebarFooter - Sticky at the top and bottom of the sidebar
- `SidebarContent` - Scrollable content.
- `SidebarGroup` - Section within the SidebarContent.
- `SidebarTrigger` - Trigger for the Sidebar
## Usage
```vue:line-numbers title="App.vue"
```
```vue:line-numbers title="@/components/AppSidebar.vue"
```
## Your First Sidebar
Let's start with the most basic sidebar A collapsible sidebar with a menu.
### Add a `SidebarProvider` and `SidebarTrigger` at the root of your application.
```vue:line-numbers title="src/pages/index.vue"
```
### Create a new sidebar component at `@/components/AppSidebar.vue`.
```vue:line-numbers title="@/components/AppSidebar.vue"
```
### Now, let's add a `SidebarMenu` to the sidebar
We'll use the `SidebarMenu` component in a `SidebarGroup`.
```vue:line-numbers title="@/components/AppSidebar.vue"
Application{{item.title}}
```
### You've created your first sidebar
Your first sidebar
## Components
The components in the `Sidebar*.vue` files are built to be composable i.e you build your sidebar by putting the provided components together. They also compose well with other shadcn-vue components such as `DropdownMenu`, `Collapsible`, `Dialog`, etc.
**If you need to change the code in the `Sidebar*.vue` files, you are encourage to do so. The code is yours. Use the provided components as a starting point to build your own**
In the next sections, we'll go over each component and how to use them.
## SidebarProvider
The `SidebarProvider` component is used to provide the sidebar context to the `Sidebar` component. You should always wrap your application in a `SidebarProvider` component.
### Props
| Name | Type | Description |
| -------------- | ------------------------- | -------------------------------------------- |
| `defaultOpen` | `boolean` | Default open state of the sidebar. |
| `open` | `boolean` | Open state of the sidebar (controlled). |
| `onOpenChange` | `(open: boolean) => void` | Sets open state of the sidebar (controlled). |
### Width
If you have a single sidebar in your application, you can use the `SIDEBAR_WIDTH` and `SIDEBAR_WIDTH_MOBILE` constants in `@/components/ui/sidebar/utils.ts` to set the width of the sidebar
```ts:line-numbers title="@/components/ui/sidebar/utils.ts"
export const SIDEBAR_WIDTH = "16rem";
export const SIDEBAR_WIDTH_MOBILE = "18rem";
```
For multiple sidebars in your application, you can use the `style` prop to set the width of the sidebar
To set the width of the sidebar, you can use the `--sidebar-width` and `--sidebar-width-mobile` CSS variables in the `style` prop.
```vue:line-numbers
```
This will not only handle the width of the sidebar but also the layout spacing.
### Keyboard Shortcut
The `SIDEBAR_KEYBOARD_SHORTCUT` variable in `@/components/ui/sidebar/utils.ts` is used to set the keyboard shortcut used to open and close the sidebar
To trigger the sidebar, you use the `cmd+b` keyboard shortcut on Mac and `ctrl+b` on Windows.
You can change the keyboard shortcut by changing the value of the `SIDEBAR_KEYBOARD_SHORTCUT` variable.
```ts:line-numbers title="@/components/ui/sidebar/utils.ts"
export const SIDEBAR_KEYBOARD_SHORTCUT = "b";
```
### Persisted State
The `SidebarProvider` supports persisting the sidebar state across page reloads and server-side rendering. It uses cookies to store the current state of the sidebar. When the sidebar state changes, a default cookie named `sidebar_state` is set with the current open/closed state. This cookie is then read on subsequent page loads to restore the sidebar state.
To persist sidebar state in SSR, set up your `SidebarProvider` in `App.vue` like this:
```vue:line-numbers title="App.vue"
```
You can change the name of the cookie by updating the `SIDEBAR_COOKIE_NAME` variable in `sidebar/utils.ts`.
```ts:line-numbers title="@/components/ui/sidebar/utils.ts"
export const SIDEBAR_COOKIE_NAME = "sidebar_state"
```
## Sidebar
The main `Sidebar` component used to render a collapsible sidebar
```vue:line-numbers
```
### Props
| Property | Type | Description |
| ------------- | --------------------------------- | --------------------------------- |
| `side` | `left` or `right` | The side of the sidebar |
| `variant` | `sidebar`, `floating`, or `inset` | The variant of the sidebar |
| `collapsible` | `offcanvas`, `icon`, or `none` | Collapsible state of the sidebar |
### side
Use the `side` prop to change the side of the sidebar
Available options are `left` and `right`.
```vue:line-numbers
```
### variant
Use the `variant` prop to change the variant of the sidebar
Available options are `sidebar`, `floating` and `inset`.
```vue:line-numbers
```
**Note:** If you use the `inset` variant, remember to wrap your main content
in a `SidebarInset` component.
```vue:line-numbers
```
### collapsible
Use the `collapsible` prop to make the sidebar collapsible
Available options are `offcanvas`, `icon` and `none`.
```vue:line-numbers
```
| Prop | Description |
| ----------- | ------------------------------------------------------------ |
| `offcanvas` | A collapsible sidebar that slides in from the left or right. |
| `icon` | A sidebar that collapses to icons. |
| `none` | A non-collapsible sidebar |
## useSidebar
The `useSidebar` composable is used to control the sidebar.
```vue:line-numbers
```
| Property | Type | Description |
| --------------- | ------------------------- | --------------------------------------------- |
| `state` | `expanded` or `collapsed` | The current state of the sidebar. |
| `open` | `boolean` | Whether the sidebar is open. |
| `setOpen` | `(open: boolean) => void` | Sets the open state of the sidebar. |
| `openMobile` | `boolean` | Whether the sidebar is open on mobile. |
| `setOpenMobile` | `(open: boolean) => void` | Sets the open state of the sidebar on mobile. |
| `isMobile` | `boolean` | Whether the sidebar is on mobile. |
| `toggleSidebar` | `() => void` | Toggles the sidebar. Desktop and mobile. |
## SidebarHeader
Use the `SidebarHeader` component to add a sticky header to the sidebar
The following example adds a `` to the `SidebarHeader`.
A sidebar header with a dropdown menu.
```vue:line-numbers title="@/components/AppSidebar.vue"
Select Workspace
Acme IncAcme Corp.
```
## SidebarFooter
Use the `SidebarFooter` component to add a sticky footer to the sidebar
The following example adds a `` to the `SidebarFooter`.
A sidebar footer with a dropdown menu.
```vue:line-numbers title="@/components/AppSidebar.vue"
Username
AccountBillingSign out
```
## SidebarContent
The `SidebarContent` component is used to wrap the content of the sidebar This is where you add your `SidebarGroup` components. It is scrollable.
```vue:line-numbers
```
## SidebarGroup
Use the `SidebarGroup` component to create a section within the sidebar
A `SidebarGroup` has a `SidebarGroupLabel`, a `SidebarGroupContent` and an optional `SidebarGroupAction`.
A sidebar group.
```vue:line-numbers
ApplicationAdd Project
```
## Collapsible SidebarGroup
To make a `SidebarGroup` collapsible, wrap it in a `Collapsible`.
A collapsible sidebar group.
```vue:line-numbers
Help
```
**Note:** We wrap the `CollapsibleTrigger` in a `SidebarGroupLabel` to render
a button.
## SidebarGroupAction
Use the `SidebarGroupAction` component to add an action to a `SidebarGroup`.
```vue:line-numbers {4-6}
ProjectsAdd Project
```
A sidebar group with an action button.
## SidebarMenu
The `SidebarMenu` component is used for building a menu within a `SidebarGroup`.
A `SidebarMenu` is composed of `SidebarMenuItem`, `SidebarMenuButton`, `SidebarMenuAction`, and `SidebarMenuSub` components.
Here's an example of a `SidebarMenu` component rendering a list of projects.
A sidebar menu with a list of projects.
```vue:line-numbers
Projects{{project.name}}
```
## SidebarMenuButton
The `SidebarMenuButton` component is used to render a menu button within a `SidebarMenuItem`.
### Link or Anchor
By default, the `SidebarMenuButton` renders a button, but you can use the `asChild` prop to render a different component such as an `` tag.
```vue:line-numbers
Home
```
### Icon and Label
You can render an icon and a truncated label inside the button. Remember to wrap the label in a `` tag.
```vue:line-numbers
Home
```
### isActive
Use the `isActive` prop to mark a menu item as active.
```vue:line-numbers
Home
```
## SidebarMenuAction
The `SidebarMenuAction` component is used to render a menu action within a `SidebarMenuItem`.
This button works independently of the `SidebarMenuButton` i.e. you can have the `SidebarMenuButton` as a clickable link and the `SidebarMenuAction` as a button.
```vue:line-numbers
HomeAdd Project
```
### DropdownMenu
Here's an example of a `SidebarMenuAction` component rendering a `DropdownMenu`.
A sidebar menu action with a dropdown menu.
```vue:line-numbers
HomeEdit ProjectDelete Project
```
## SidebarMenuSub
The `SidebarMenuSub` component is used to render a submenu within a `SidebarMenu`.
Use `SidebarMenuSubItem` and `SidebarMenuSubButton` to render a submenu item.
A sidebar menu sub.
```vue:line-numbers
```
## Collapsible SidebarMenu
To make a `SidebarMenu` component collapsible, wrap it and the `SidebarMenuSub` components in a `Collapsible`.
A collapsible sidebar menu.
```vue:line-numbers
```
## SidebarMenuBadge
The `SidebarMenuBadge` component is used to render a badge within a `SidebarMenuItem`.
A sidebar menu badge.
```vue:line-numbers
24
```
## SidebarMenuSkeleton
The `SidebarMenuSkeleton` component is used to render a skeleton within a `SidebarMenu`. You can use this to show a loading state while waiting for data to load.
```vue:line-numbers
```
## SidebarSeparator
The `SidebarSeparator` component is used to render a separator within a `Sidebar`.
```vue:line-numbers
```
## SidebarTrigger
Use the `SidebarTrigger` component to render a button that toggles the sidebar.
The `SidebarTrigger` component must be used within a `SidebarProvider`.
```vue:line-numbers
```
## Custom Trigger
To create a custom trigger, you can use the `useSidebar` composable.
```vue:line-numbers
```
## SidebarRail
The `SidebarRail` component is used to render a rail within a `Sidebar`. This rail can be used to toggle the sidebar
```vue:line-numbers
```
## Controlled Sidebar
Use the `open` prop and `@update:open` emit (or `v-model:open`) to control the sidebar state.
A controlled sidebar.
```vue:line-numbers
```
## Theming
We use the following CSS variables to theme the sidebar
```css
@layer base {
:root {
--sidebar-background: 0 0% 98%;
--sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 240 4.8% 95.9%;
--sidebar-accent-foreground: 240 5.9% 10%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
.dark {
--sidebar-background: 240 5.9% 10%;
--sidebar-foreground: 240 4.8% 95.9%;
--sidebar-primary: 0 0% 98%;
--sidebar-primary-foreground: 240 5.9% 10%;
--sidebar-accent: 240 3.7% 15.9%;
--sidebar-accent-foreground: 240 4.8% 95.9%;
--sidebar-border: 240 3.7% 15.9%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
}
```
**We intentionally use different variables for the sidebar and the rest of the application** to make it easy to have a sidebar that is styled differently from the rest of the application. Think a sidebar with a darker shade from the main application.
## Styling
Here are some tips for styling the sidebar based on different states.
- **Styling an element based on the sidebar collapsible state.** The following will hide the `SidebarGroup` when the sidebar is in `icon` mode.
```vue
```
- **Styling a menu action based on the menu button active state.** The following will force the menu action to be visible when the menu button is active.
```vue
```
You can find more tips on using states for styling in this [Twitter thread](https://x.com/shadcn/status/1842329158879420864).
---
---
url: /docs/components/skeleton.md
description: Use to show a placeholder while content is loading.
---
## Installation
```bash
npx shadcn-vue@latest add skeleton
```
### Copy and paste the following code into your project
<<< @/registry/default/ui/skeleton/Skeleton.vue
## Usage
```vue
```
## Examples
### Card
---
---
url: /docs/components/slider.md
description: An input where the user selects a value from within a given range.
---
## Installation
```bash
npx shadcn-vue@latest add slider
```
## Usage
```vue
```
## Examples
### Form
---
---
url: /docs/components/sonner.md
description: An opinionated toast component for Vue.
---
## About
The Sonner component is provided by [vue-sonner](https://vue-sonner.vercel.app/), which is a Vue port of Sonner, originally created by [Emil Kowalski](https://twitter.com/emilkowalski_) for React.
## Installation
### Run the following command
```bash
npx shadcn-vue@latest add sonner
```
### Add the Toaster component
Add the following `Toaster` component to your `App.vue` file:
```vue title="App.vue" {2,6}
```
## Usage
```vue
```
## Examples
### Sonner with Dialog
Related issue https://github.com/unovue/shadcn-vue/issues/462
Add `pointer-events-auto` class to Toaster component in your `App.vue` file:
```vue {6}
```
---
---
url: /docs/components/stepper.md
description: >-
A set of steps that are used to indicate progress through a multi-step
process.
---
## Installation
```bash
npx shadcn-vue@latest add stepper
```
## Usage
```vue
1Step 1This is the first step2Step 2This is the second step
```
## Examples
### Horizontal
### Vertical
### Form
---
---
url: /docs/components/switch.md
description: A control that allows the user to toggle between checked and not checked.
---
## Installation
```bash
npx shadcn-vue@latest add switch
```
### Install the following dependency:
```bash
npm install reka-ui
```
### Copy and paste the following code into your project
<<< @/registry/default/ui/switch/Switch.vue
## Usage
```vue
```
# Add icon inside switch thumb
```vue
```
## Examples
### Form
---
---
url: /docs/components/table.md
description: A responsive table component.
---
## Installation
```bash
npx shadcn-vue@latest add table
```
## Usage
```vue
A list of your recent invoices.
Invoice
StatusMethod
Amount
INV001
PaidCredit Card
$250.00
```
## Data Table
You can use the `
` component to build more complex data tables. Combine it with [@tanstack/vue-table](https://tanstack.com/table/v8) to create tables with sorting, filtering and pagination.
See the [Data Table](/docs/components/data-table) documentation for more information.
You can also see an example of a data table in the [Tasks](/examples/tasks) demo.
---
---
url: /docs/components/tabs.md
description: >-
A set of layered sections of content—known as tab panels—that are displayed
one at a time.
---
## Installation
```bash
npx shadcn-vue@latest add tabs
```
## Usage
```vue
Account
Password
Make changes to your account here.
Change your password here.
```
## Examples
### Vertical
---
---
url: /docs/components/tags-input.md
description: 'Tag inputs render tags inside an input, followed by an actual text input.'
---
## Installation
```bash
npx shadcn-vue@latest add tags-input
```
## Usage
### Tags with Combobox
### Form
---
---
url: /docs/tailwind-v4.md
description: How to use shadcn-vue with Tailwind v4.
---
It's here! Tailwind v4. 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.
- 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 will still work. When you add new components, they'll still be in v3 until you upgrade. Only new projects start with Tailwind v4.**
## See it Live
I put together a demo with all the updated components here: https://v4.shadcn-vue.com
Take a look and test the components. If you find any bugs, please let me know on [GitHub](https://github.com/unovue/shadcn-vue).
## Try It Out
See the framework specific guides below for how to get started.
Vite
Nuxt
Astro
Laravel
Manual
## Upgrade Your Project
**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.
One of the major advantages of using `shadcn-vue` 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:line-numbers
@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:line-numbers
: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 for eg. using color values in JavaScript.
### 3. 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
```
### 4. Install and Update your dependencies
```bash
pnpm i tw-animate-css
pnpm up reka-ui lucide-vue-next tailwind-merge clsx --latest
```
---
---
url: /docs/components/textarea.md
description: Displays a form textarea or a component that looks like a textarea.
---
## Installation
```bash
npx shadcn-vue@latest add textarea
```
### Install the following dependency:
```bash
npm install reka-ui
```
### Copy and paste the following code into your project
<<< @/registry/default/ui/textarea/Textarea.vue
## Usage
```vue
```
## Examples
### Default
### Disabled
### With Label
### With Text
### With Button
### Form
---
---
url: /docs/theming.md
description: Use CSS Variables to customize the look and feel of your application.
---
You can choose between using CSS variables or Tailwind CSS utility classes for theming.
## Utility classes
```html /bg-zinc-950/ /text-zinc-50/ /dark:bg-white/ /dark:text-zinc-950/
```
To use utility classes for theming set `tailwind.cssVariables` to `false` in your `components.json` file.
```json {7} title="components.json"
{
"style": "default",
"tailwind": {
"config": "tailwind.config.js",
"css": "app/globals.css",
"baseColor": "slate",
"cssVariables": false
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}
```
## CSS Variables
```html /bg-background/ /text-foreground/
```
To use CSS variables for theming set `tailwind.cssVariables` to `true` in your `components.json` file.
```json {7} title="components.json"
{
"style": "default",
"tailwind": {
"config": "tailwind.config.js",
"css": "app/globals.css",
"baseColor": "slate",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}
```
### Convention
We use a simple `background` and `foreground` convention for colors. The `background` variable is used for the background color of the component and the `foreground` variable is used for the text color.
The `background` suffix is omitted when the variable is used for the background color of the component.
Given the following CSS variables:
```css
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
```
The `background` color of the following component will be `hsl(var(--primary))` and the `foreground` color will be `hsl(var(--primary-foreground))`.
```html
Hello
```
**CSS variables must be defined without color space function**. See the [Tailwind CSS documentation](https://tailwindcss.com/docs/customizing-colors#using-css-variables) for more information.
### List of variables
Here's the list of variables available for customization:
```css
/* Default background color of ...etc */
--background: 0 0% 100%;
--foreground: 222.2 47.4% 11.2%;
```
```css
/* Muted backgrounds such as , and */
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
```
```css
/* Background color for */
--card: 0 0% 100%;
--card-foreground: 222.2 47.4% 11.2%;
```
```css
/* Background color for popovers such as , , */
--popover: 0 0% 100%;
--popover-foreground: 222.2 47.4% 11.2%;
```
```css
/* Default border color */
--border: 214.3 31.8% 91.4%;
```
```css
/* Border color for inputs such as , , */
--input: 214.3 31.8% 91.4%;
```
```css
/* Primary colors for */
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
```
```css
/* Secondary colors for */
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
```
```css
/* Used for accents such as hover effects on , ...etc */
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
```
```css
/* Used for destructive actions such as