diff --git a/apps/v4/app/(app)/docs/[[...slug]]/page.tsx b/apps/v4/app/(app)/docs/[[...slug]]/page.tsx
index f700a3c5b7..fad2c5bd2a 100644
--- a/apps/v4/app/(app)/docs/[[...slug]]/page.tsx
+++ b/apps/v4/app/(app)/docs/[[...slug]]/page.tsx
@@ -12,6 +12,7 @@ import z from "zod"
import { source } from "@/lib/source"
import { absoluteUrl } from "@/lib/utils"
+import { DocsBaseSwitcher } from "@/components/docs-base-switcher"
import { DocsCopyPage } from "@/components/docs-copy-page"
import { DocsTableOfContents } from "@/components/docs-toc"
import { OpenInV0Cta } from "@/components/open-in-v0-cta"
@@ -147,6 +148,10 @@ export default async function Page(props: {
)}
+ {params.slug?.[0] === "components" &&
+ (params.slug?.[1] === "radix" || params.slug?.[1] === "base") && (
+
{links?.doc && (
diff --git a/apps/v4/components/component-preview.tsx b/apps/v4/components/component-preview.tsx
index a207dcb80f..5dbcf413c3 100644
--- a/apps/v4/components/component-preview.tsx
+++ b/apps/v4/components/component-preview.tsx
@@ -1,9 +1,8 @@
import Image from "next/image"
+import { getRegistryComponent } from "@/lib/registry"
import { ComponentPreviewTabs } from "@/components/component-preview-tabs"
import { ComponentSource } from "@/components/component-source"
-import { Index } from "@/registry/__index__"
-import { type Style } from "@/registry/_legacy-styles"
export function ComponentPreview({
name,
@@ -16,14 +15,14 @@ export function ComponentPreview({
...props
}: React.ComponentProps<"div"> & {
name: string
- styleName?: Style["name"]
+ styleName?: string
align?: "center" | "start" | "end"
description?: string
hideCode?: boolean
type?: "block" | "component" | "example"
chromeLessOnMobile?: boolean
}) {
- const Component = Index[styleName]?.[name]?.component
+ const Component = getRegistryComponent(name, styleName)
if (!Component) {
return (
diff --git a/apps/v4/components/component-source.tsx b/apps/v4/components/component-source.tsx
index 55bf3acca3..b108b3f22f 100644
--- a/apps/v4/components/component-source.tsx
+++ b/apps/v4/components/component-source.tsx
@@ -8,7 +8,6 @@ import { cn } from "@/lib/utils"
import { CodeCollapsibleWrapper } from "@/components/code-collapsible-wrapper"
import { CopyButton } from "@/components/copy-button"
import { getIconForLanguageExtension } from "@/components/icons"
-import { type Style } from "@/registry/_legacy-styles"
export async function ComponentSource({
name,
@@ -24,7 +23,7 @@ export async function ComponentSource({
title?: string
language?: string
collapsible?: boolean
- styleName?: Style["name"]
+ styleName?: string
}) {
if (!name && !src) {
return null
diff --git a/apps/v4/components/docs-base-switcher.tsx b/apps/v4/components/docs-base-switcher.tsx
new file mode 100644
index 0000000000..b3e5d3ee71
--- /dev/null
+++ b/apps/v4/components/docs-base-switcher.tsx
@@ -0,0 +1,40 @@
+"use client"
+
+import Link from "next/link"
+import { usePathname } from "next/navigation"
+
+import { cn } from "@/lib/utils"
+
+const BASES = [
+ { name: "radix", label: "Radix UI" },
+ { name: "base", label: "Base UI" },
+]
+
+export function DocsBaseSwitcher() {
+ const pathname = usePathname()
+
+ // Extract base and component from /docs/components/{base}/{component}.
+ const match = pathname.match(/\/docs\/components\/(radix|base)\/(.+)/)
+ if (!match) return null
+
+ const [, currentBase, component] = match
+
+ return (
+
+ {BASES.map((base) => (
+
+ {base.label}
+
+ ))}
+
+ )
+}
diff --git a/apps/v4/components/docs-sidebar.tsx b/apps/v4/components/docs-sidebar.tsx
index 79dce7005d..458180dfe3 100644
--- a/apps/v4/components/docs-sidebar.tsx
+++ b/apps/v4/components/docs-sidebar.tsx
@@ -17,6 +17,10 @@ import {
SidebarMenuItem,
} from "@/registry/new-york-v4/ui/sidebar"
+type PageTreeNode = (typeof source.pageTree)["children"][number]
+type PageTreeFolder = Extract
+type PageTreePage = Extract
+
const TOP_LEVEL_SECTIONS = [
{ name: "Get Started", href: "/docs" },
{
@@ -43,12 +47,67 @@ const TOP_LEVEL_SECTIONS = [
const EXCLUDED_SECTIONS = ["installation", "dark-mode"]
const EXCLUDED_PAGES = ["/docs", "/docs/changelog"]
+// Recursively find all pages in a folder tree.
+function getAllPagesFromFolder(folder: PageTreeFolder): PageTreePage[] {
+ const pages: PageTreePage[] = []
+
+ for (const child of folder.children) {
+ if (child.type === "page") {
+ pages.push(child)
+ } else if (child.type === "folder") {
+ pages.push(...getAllPagesFromFolder(child))
+ }
+ }
+
+ return pages
+}
+
+// Get the pages from a folder, handling nested base folders (radix/base).
+function getPagesFromFolder(
+ folder: PageTreeFolder,
+ currentBase: string
+): PageTreePage[] {
+ // For the components folder, find the base subfolder.
+ if (folder.$id === "components" || folder.name === "Components") {
+ for (const child of folder.children) {
+ if (child.type === "folder") {
+ // Match by $id or by name.
+ const isRadix = child.$id === "radix" || child.name === "Radix UI"
+ const isBase = child.$id === "base" || child.name === "Base UI"
+
+ if (
+ (currentBase === "radix" && isRadix) ||
+ (currentBase === "base" && isBase)
+ ) {
+ return child.children.filter(
+ (c): c is PageTreePage => c.type === "page"
+ )
+ }
+ }
+ }
+
+ // Fallback: return all pages from nested folders.
+ return getAllPagesFromFolder(folder).filter(
+ (page) => !page.url.endsWith("/components")
+ )
+ }
+
+ // For other folders, return direct page children.
+ return folder.children.filter(
+ (child): child is PageTreePage => child.type === "page"
+ )
+}
+
export function DocsSidebar({
tree,
...props
}: React.ComponentProps & { tree: typeof source.pageTree }) {
const pathname = usePathname()
+ // Detect current base from URL (radix or base).
+ const baseMatch = pathname.match(/\/docs\/components\/(radix|base)\//)
+ const currentBase = baseMatch ? baseMatch[1] : "radix" // Default to radix.
+
return (
{item.type === "folder" && (
- {item.children.map((item) => {
- if (
- !showMcpDocs &&
- item.type === "page" &&
- item.url?.includes("/mcp")
- ) {
+ {getPagesFromFolder(item, currentBase).map((page) => {
+ if (!showMcpDocs && page.url.includes("/mcp")) {
+ return null
+ }
+
+ if (EXCLUDED_PAGES.includes(page.url)) {
return null
}
return (
- item.type === "page" &&
- !EXCLUDED_PAGES.includes(item.url) && (
-
-
-
-
- {item.name}
- {PAGES_NEW.includes(item.url) && (
-
- )}
-
-
-
- )
+
+
+
+
+ {page.name}
+ {PAGES_NEW.includes(page.url) && (
+
+ )}
+
+
+
)
})}
diff --git a/apps/v4/content/docs/components/accordion.mdx b/apps/v4/content/docs/components/base/accordion.mdx
similarity index 91%
rename from apps/v4/content/docs/components/accordion.mdx
rename to apps/v4/content/docs/components/base/accordion.mdx
index fb5cd44281..dba2d460c9 100644
--- a/apps/v4/content/docs/components/accordion.mdx
+++ b/apps/v4/content/docs/components/base/accordion.mdx
@@ -1,6 +1,7 @@
---
title: Accordion
description: A vertically stacked set of interactive headings that each reveal a section of content.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/accordion
@@ -8,6 +9,7 @@ links:
---
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/alert-dialog.mdx b/apps/v4/content/docs/components/base/alert-dialog.mdx
similarity index 93%
rename from apps/v4/content/docs/components/alert-dialog.mdx
rename to apps/v4/content/docs/components/base/alert-dialog.mdx
index d85d30f057..56ef5541a5 100644
--- a/apps/v4/content/docs/components/alert-dialog.mdx
+++ b/apps/v4/content/docs/components/base/alert-dialog.mdx
@@ -2,6 +2,7 @@
title: Alert Dialog
description: A modal dialog that interrupts the user with important content and expects a response.
featured: true
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/alert-dialog
@@ -9,6 +10,7 @@ links:
---
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/alert.mdx b/apps/v4/content/docs/components/base/alert.mdx
similarity index 90%
rename from apps/v4/content/docs/components/alert.mdx
rename to apps/v4/content/docs/components/base/alert.mdx
index ec3d6f2d42..98df719adb 100644
--- a/apps/v4/content/docs/components/alert.mdx
+++ b/apps/v4/content/docs/components/base/alert.mdx
@@ -1,10 +1,12 @@
---
title: Alert
description: Displays a callout for user attention.
+base: base
component: true
---
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/aspect-ratio.mdx b/apps/v4/content/docs/components/base/aspect-ratio.mdx
similarity index 89%
rename from apps/v4/content/docs/components/aspect-ratio.mdx
rename to apps/v4/content/docs/components/base/aspect-ratio.mdx
index 958f6d054a..cb5ffd7399 100644
--- a/apps/v4/content/docs/components/aspect-ratio.mdx
+++ b/apps/v4/content/docs/components/base/aspect-ratio.mdx
@@ -1,6 +1,7 @@
---
title: Aspect Ratio
description: Displays content within a desired ratio.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/aspect-ratio
@@ -8,6 +9,7 @@ links:
---
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/avatar.mdx b/apps/v4/content/docs/components/base/avatar.mdx
similarity index 90%
rename from apps/v4/content/docs/components/avatar.mdx
rename to apps/v4/content/docs/components/base/avatar.mdx
index a20c1259a9..88d9cc100f 100644
--- a/apps/v4/content/docs/components/avatar.mdx
+++ b/apps/v4/content/docs/components/base/avatar.mdx
@@ -1,6 +1,7 @@
---
title: Avatar
description: An image element with a fallback for representing the user.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/avatar
@@ -8,6 +9,7 @@ links:
---
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/badge.mdx b/apps/v4/content/docs/components/base/badge.mdx
similarity index 90%
rename from apps/v4/content/docs/components/badge.mdx
rename to apps/v4/content/docs/components/base/badge.mdx
index 6f4abdb0cb..810115edd8 100644
--- a/apps/v4/content/docs/components/badge.mdx
+++ b/apps/v4/content/docs/components/base/badge.mdx
@@ -1,10 +1,12 @@
---
title: Badge
description: Displays a badge or a component that looks like a badge.
+base: base
component: true
---
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/breadcrumb.mdx b/apps/v4/content/docs/components/base/breadcrumb.mdx
similarity index 94%
rename from apps/v4/content/docs/components/breadcrumb.mdx
rename to apps/v4/content/docs/components/base/breadcrumb.mdx
index 91c0ccbe1c..656a4d669e 100644
--- a/apps/v4/content/docs/components/breadcrumb.mdx
+++ b/apps/v4/content/docs/components/base/breadcrumb.mdx
@@ -1,10 +1,12 @@
---
title: Breadcrumb
description: Displays the path to the current resource using a hierarchy of links.
+base: base
component: true
---
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -80,6 +86,7 @@ import {
Use a custom component as `children` for ` ` to create a custom separator.
@@ -111,6 +118,7 @@ import { SlashIcon } from "lucide-react"
You can compose ` ` with a ` ` to create a dropdown in the breadcrumb.
` component to show a collapsed state when the breadcrumb is too long.
`.
@@ -205,6 +215,7 @@ Here's an example of a responsive breadcrumb that composes ` `
It displays a dropdown on desktop and a drawer on mobile.
+
## Installation
@@ -34,7 +35,11 @@ npm install @radix-ui/react-slot
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -85,19 +90,19 @@ import {
Set the `orientation` prop to change the button group layout.
-
+
### Size
Control the size of buttons using the `size` prop on individual buttons.
-
+
### Nested
Nest `` components to create button groups with spacing.
-
+
### Separator
@@ -105,43 +110,43 @@ The `ButtonGroupSeparator` component visually divides buttons within a group.
Buttons with variant `outline` do not need a separator since they have a border. For other variants, a separator is recommended to improve the visual hierarchy.
-
+
### Split
Create a split button group by adding two buttons separated by a `ButtonGroupSeparator`.
-
+
### Input
Wrap an `Input` component with buttons.
-
+
### Input Group
Wrap an `InputGroup` component to create complex input layouts.
-
+
### Dropdown Menu
Create a split button group with a `DropdownMenu` component.
-
+
### Select
Pair with a `Select` component.
-
+
### Popover
Use with a `Popover` component.
-
+
## API Reference
diff --git a/apps/v4/content/docs/components/base/button.mdx b/apps/v4/content/docs/components/base/button.mdx
new file mode 100644
index 0000000000..4943f9b98b
--- /dev/null
+++ b/apps/v4/content/docs/components/base/button.mdx
@@ -0,0 +1,350 @@
+---
+title: Button
+description: Displays a button or a component that looks like a button.
+featured: true
+base: base
+component: true
+---
+
+import { InfoIcon } from "lucide-react"
+
+ }>
+**Updated:** We have updated the button component to add new sizes: `icon-sm` and `icon-lg`. See the
+[changelog](/docs/components/button#changelog) for more details. Follow the
+instructions to update your project.
+
+
+
+
+
+```tsx showLineNumbers
+Button
+
+
+
+```
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add button
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-slot
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx
+import { Button } from "@/components/ui/button"
+```
+
+```tsx
+Button
+```
+
+## Cursor
+
+Tailwind v4 [switched](https://tailwindcss.com/docs/upgrade-guide#buttons-use-the-default-cursor) from `cursor: pointer` to `cursor: default` for the button component.
+
+If you want to keep the `cursor: pointer` behavior, add the following code to your CSS file:
+
+```css showLineNumbers title="globals.css"
+@layer base {
+ button:not(:disabled),
+ [role="button"]:not(:disabled) {
+ cursor: pointer;
+ }
+}
+```
+
+## Examples
+
+### Size
+
+
+
+```tsx
+// Small
+Small
+
+
+
+
+// Medium
+Default
+
+
+
+
+// Large
+Large
+
+
+
+```
+
+### Default
+
+
+
+```tsx
+Button
+```
+
+### Outline
+
+
+
+```tsx
+Outline
+```
+
+### Secondary
+
+
+
+```tsx
+Secondary
+```
+
+### Ghost
+
+
+
+```tsx
+Ghost
+```
+
+### Destructive
+
+
+
+```tsx
+Destructive
+```
+
+### Link
+
+
+
+```tsx
+Link
+```
+
+### Icon
+
+
+
+```tsx showLineNumbers
+
+
+
+```
+
+### With Icon
+
+The spacing between the icon and the text is automatically adjusted
+based on the size of the button. You do not need any margin on the icon.
+
+
+
+```tsx
+
+ New Branch
+
+```
+
+### Rounded
+
+Use the `rounded-full` class to make the button rounded.
+
+
+
+```tsx
+
+
+
+```
+
+### Spinner
+
+
+
+```tsx showLineNumbers
+
+
+ Submit
+
+```
+
+### Button Group
+
+To create a button group, use the `ButtonGroup` component. See the [Button Group](/docs/components/button-group) documentation for more details.
+
+
+
+```tsx showLineNumbers
+
+
+
+
+
+
+
+ Archive
+ Report
+
+
+ Snooze
+
+
+
+
+
+
+
+
+
+
+```
+
+### Link
+
+You can use the `asChild` prop to make another component look like a button. Here's an example of a link that looks like a button.
+
+```tsx showLineNumbers
+import Link from "next/link"
+
+import { Button } from "@/components/ui/button"
+
+export function LinkAsButton() {
+ return (
+
+ Login
+
+ )
+}
+```
+
+## API Reference
+
+### Button
+
+The `Button` component is a wrapper around the `button` element that adds a variety of styles and functionality.
+
+| Prop | Type | Default |
+| --------- | ----------------------------------------------------------------------------- | ----------- |
+| `variant` | `"default" \| "outline" \| "ghost" \| "destructive" \| "secondary" \| "link"` | `"default"` |
+| `size` | `"default" \| "sm" \| "lg" \| "icon" \| "icon-sm" \| "icon-lg"` | `"default"` |
+| `asChild` | `boolean` | `false` |
+
+## Changelog
+
+### 2025-09-24 New sizes
+
+We have added two new sizes to the button component: `icon-sm` and `icon-lg`. These sizes are used to create icon buttons. To add them, edit `button.tsx` and add the following code under `size` in `buttonVariants`:
+
+```tsx showLineNumbers title="components/ui/button.tsx"
+const buttonVariants = cva("...", {
+ variants: {
+ size: {
+ // ...
+ "icon-sm": "size-8",
+ "icon-lg": "size-10",
+ // ...
+ },
+ },
+})
+```
diff --git a/apps/v4/content/docs/components/calendar.mdx b/apps/v4/content/docs/components/base/calendar.mdx
similarity index 96%
rename from apps/v4/content/docs/components/calendar.mdx
rename to apps/v4/content/docs/components/base/calendar.mdx
index 5ecf2dfcc5..4400811163 100644
--- a/apps/v4/content/docs/components/calendar.mdx
+++ b/apps/v4/content/docs/components/base/calendar.mdx
@@ -1,12 +1,14 @@
---
title: Calendar
description: A date field component that allows users to enter and edit date.
+base: base
component: true
links:
doc: https://react-day-picker.js.org
---
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -103,6 +109,7 @@ To use the Persian calendar, edit `components/ui/calendar.tsx` and replace `reac
```
span]:text-xs [&>span]:opacity-70",
+ "data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 flex aspect-square h-auto w-full min-w-[--cell-size] flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] data-[range-end=true]:rounded-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md [&>span]:text-xs [&>span]:opacity-70",
defaultClassNames.day,
className
)}
diff --git a/apps/v4/content/docs/components/card.mdx b/apps/v4/content/docs/components/base/card.mdx
similarity index 83%
rename from apps/v4/content/docs/components/card.mdx
rename to apps/v4/content/docs/components/base/card.mdx
index c5b2633b34..58530977d3 100644
--- a/apps/v4/content/docs/components/card.mdx
+++ b/apps/v4/content/docs/components/base/card.mdx
@@ -1,10 +1,15 @@
---
title: Card
description: Displays a card with header, content, and footer.
+base: base
component: true
---
-
+
## Installation
@@ -28,7 +33,11 @@ npx shadcn@latest add card
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/carousel.mdx b/apps/v4/content/docs/components/base/carousel.mdx
similarity index 96%
rename from apps/v4/content/docs/components/carousel.mdx
rename to apps/v4/content/docs/components/base/carousel.mdx
index 73461ccc8c..02e51d9fe3 100644
--- a/apps/v4/content/docs/components/carousel.mdx
+++ b/apps/v4/content/docs/components/base/carousel.mdx
@@ -1,6 +1,7 @@
---
title: Carousel
description: A carousel with motion and swipe built using Embla.
+base: base
component: true
links:
doc: https://www.embla-carousel.com/get-started/react
@@ -8,6 +9,7 @@ links:
---
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -87,6 +93,7 @@ import {
To set the size of the items, you can use the `basis` utility class on the ` `.
Copy and paste the following code into `components/ui/chart.tsx`.
-
+
Add the following colors to your CSS file
@@ -197,9 +203,14 @@ You can now build your chart using Recharts components.
-
+
@@ -231,6 +242,7 @@ import { Bar, BarChart, CartesianGrid } from "recharts"
```
@@ -269,6 +281,7 @@ import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"
```
@@ -310,6 +323,7 @@ import { ChartTooltip, ChartTooltipContent } from "@/components/ui/chart"
```
@@ -352,6 +366,7 @@ import { ChartLegend, ChartLegendContent } from "@/components/ui/chart"
```
@@ -476,6 +491,7 @@ const chartData = [
A chart tooltip contains a label, name, indicator and value. You can use a combination of these to customize your tooltip.
+
## Installation
@@ -37,7 +42,11 @@ npm install @radix-ui/react-checkbox
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/collapsible.mdx b/apps/v4/content/docs/components/base/collapsible.mdx
similarity index 90%
rename from apps/v4/content/docs/components/collapsible.mdx
rename to apps/v4/content/docs/components/base/collapsible.mdx
index d3b18f7bcd..aa5daa519e 100644
--- a/apps/v4/content/docs/components/collapsible.mdx
+++ b/apps/v4/content/docs/components/base/collapsible.mdx
@@ -1,6 +1,7 @@
---
title: Collapsible
description: An interactive component which expands/collapses a panel.
+base: base
component: true
featured: true
links:
@@ -9,6 +10,7 @@ links:
---
@@ -41,7 +43,11 @@ npm install @radix-ui/react-collapsible
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/combobox.mdx b/apps/v4/content/docs/components/base/combobox.mdx
similarity index 93%
rename from apps/v4/content/docs/components/combobox.mdx
rename to apps/v4/content/docs/components/base/combobox.mdx
index a8788f7f24..61c5b18d72 100644
--- a/apps/v4/content/docs/components/combobox.mdx
+++ b/apps/v4/content/docs/components/base/combobox.mdx
@@ -1,10 +1,12 @@
---
title: Combobox
description: Autocomplete input and command palette with a list of suggestions.
+base: base
component: true
---
@@ -123,17 +125,19 @@ export function ExampleCombobox() {
### Combobox
### Popover
-
+
### Dropdown menu
@@ -142,4 +146,4 @@ export function ExampleCombobox() {
You can create a responsive combobox by using the ` ` on desktop and the ` ` components on mobile.
-
+
diff --git a/apps/v4/content/docs/components/command.mdx b/apps/v4/content/docs/components/base/command.mdx
similarity index 95%
rename from apps/v4/content/docs/components/command.mdx
rename to apps/v4/content/docs/components/base/command.mdx
index 7784dae9ee..62ba9db88d 100644
--- a/apps/v4/content/docs/components/command.mdx
+++ b/apps/v4/content/docs/components/base/command.mdx
@@ -1,12 +1,14 @@
---
title: Command
description: Fast, composable, unstyled command menu for React.
+base: base
component: true
links:
doc: https://cmdk.paco.me
---
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -96,6 +102,7 @@ import {
### Dialog
diff --git a/apps/v4/content/docs/components/context-menu.mdx b/apps/v4/content/docs/components/base/context-menu.mdx
similarity index 91%
rename from apps/v4/content/docs/components/context-menu.mdx
rename to apps/v4/content/docs/components/base/context-menu.mdx
index 81c599d69e..92ff5dbd6e 100644
--- a/apps/v4/content/docs/components/context-menu.mdx
+++ b/apps/v4/content/docs/components/base/context-menu.mdx
@@ -1,6 +1,7 @@
---
title: Context Menu
description: Displays a menu to the user — such as a set of actions or functions — triggered by a button.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/context-menu
@@ -8,6 +9,7 @@ links:
---
@@ -40,7 +42,11 @@ npm install @radix-ui/react-context-menu
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/data-table.mdx b/apps/v4/content/docs/components/base/data-table.mdx
similarity index 98%
rename from apps/v4/content/docs/components/data-table.mdx
rename to apps/v4/content/docs/components/base/data-table.mdx
index b66f08572a..738ed06234 100644
--- a/apps/v4/content/docs/components/data-table.mdx
+++ b/apps/v4/content/docs/components/base/data-table.mdx
@@ -1,12 +1,17 @@
---
title: Data Table
description: Powerful table and datagrids built using TanStack Table.
+base: base
component: true
links:
doc: https://tanstack.com/table/v8/docs/introduction
---
-
+
## Introduction
@@ -856,7 +861,10 @@ export const columns = [
Add pagination controls to your table including page size and selection count.
-
+
```tsx
@@ -866,7 +874,10 @@ Add pagination controls to your table including page size and selection count.
A component to toggle column visibility.
-
+
```tsx
diff --git a/apps/v4/content/docs/components/date-picker.mdx b/apps/v4/content/docs/components/base/date-picker.mdx
similarity index 94%
rename from apps/v4/content/docs/components/date-picker.mdx
rename to apps/v4/content/docs/components/base/date-picker.mdx
index 24ca640ef0..b7dee5ed78 100644
--- a/apps/v4/content/docs/components/date-picker.mdx
+++ b/apps/v4/content/docs/components/base/date-picker.mdx
@@ -1,10 +1,12 @@
---
title: Date Picker
description: A date picker component with range and presets.
+base: base
component: true
---
@@ -41,7 +43,11 @@ npm install @radix-ui/react-dialog
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -83,7 +89,7 @@ import {
### Custom close button
-
+
## Notes
diff --git a/apps/v4/content/docs/components/drawer.mdx b/apps/v4/content/docs/components/base/drawer.mdx
similarity index 86%
rename from apps/v4/content/docs/components/drawer.mdx
rename to apps/v4/content/docs/components/base/drawer.mdx
index 7314414862..af179960d9 100644
--- a/apps/v4/content/docs/components/drawer.mdx
+++ b/apps/v4/content/docs/components/base/drawer.mdx
@@ -1,12 +1,17 @@
---
title: Drawer
description: A drawer component for React.
+base: base
component: true
links:
doc: https://vaul.emilkowal.ski/getting-started
---
-
+
## About
@@ -40,7 +45,11 @@ npm install vaul
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -89,4 +98,4 @@ import {
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.
-
+
diff --git a/apps/v4/content/docs/components/dropdown-menu.mdx b/apps/v4/content/docs/components/base/dropdown-menu.mdx
similarity index 89%
rename from apps/v4/content/docs/components/dropdown-menu.mdx
rename to apps/v4/content/docs/components/base/dropdown-menu.mdx
index 39af9d2b3f..489f6350ce 100644
--- a/apps/v4/content/docs/components/dropdown-menu.mdx
+++ b/apps/v4/content/docs/components/base/dropdown-menu.mdx
@@ -2,6 +2,7 @@
title: Dropdown Menu
description: Displays a menu to the user — such as a set of actions or functions — triggered by a button.
featured: true
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/dropdown-menu
@@ -9,6 +10,7 @@ links:
---
@@ -41,7 +43,11 @@ npm install @radix-ui/react-dropdown-menu
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -83,6 +89,7 @@ import {
### Checkboxes
@@ -90,6 +97,7 @@ import {
### Radio Group
@@ -108,4 +116,4 @@ Use `modal={false}` on the `DropdownMenu` component.
```
-
+
diff --git a/apps/v4/content/docs/components/empty.mdx b/apps/v4/content/docs/components/base/empty.mdx
similarity index 85%
rename from apps/v4/content/docs/components/empty.mdx
rename to apps/v4/content/docs/components/base/empty.mdx
index a14e61ddfb..f29bdfec7c 100644
--- a/apps/v4/content/docs/components/empty.mdx
+++ b/apps/v4/content/docs/components/base/empty.mdx
@@ -1,10 +1,15 @@
---
title: Empty
description: Use the Empty component to display an empty state.
+base: base
component: true
---
-
+
## Installation
@@ -28,7 +33,11 @@ npx shadcn@latest add empty
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -73,6 +82,7 @@ import {
Use the `border` utility class to create an outline empty state.
@@ -81,25 +91,41 @@ Use the `border` utility class to create an outline empty state.
Use the `bg-*` and `bg-gradient-*` utilities to add a background to the empty state.
-
+
### Avatar
Use the `EmptyMedia` component to display an avatar in the empty state.
-
+
### Avatar Group
Use the `EmptyMedia` component to display an avatar group in the empty state.
-
+
### InputGroup
You can add an `InputGroup` component to the `EmptyContent` component.
-
+
## API Reference
diff --git a/apps/v4/content/docs/components/field.mdx b/apps/v4/content/docs/components/base/field.mdx
similarity index 88%
rename from apps/v4/content/docs/components/field.mdx
rename to apps/v4/content/docs/components/base/field.mdx
index 72ea66badc..8f96e26cb2 100644
--- a/apps/v4/content/docs/components/field.mdx
+++ b/apps/v4/content/docs/components/base/field.mdx
@@ -1,10 +1,12 @@
---
title: Field
description: Combine labels, controls, and help text to compose accessible form fields and grouped inputs.
+base: base
component: true
---
@@ -31,7 +33,11 @@ npx shadcn@latest add field
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -106,47 +112,87 @@ See the [Form](/docs/forms) documentation for building forms with the `Field` co
### Input
-
+
### Textarea
-
+
### Select
-
+
### Slider
-
+
### Fieldset
-
+
### Checkbox
-
+
### Radio
-
+
### Switch
-
+
### Choice Card
Wrap `Field` components inside `FieldLabel` to create selectable field groups. This works with `RadioItem`, `Checkbox` and `Switch` components.
-
+
### Field Group
Stack `Field` components with `FieldGroup`. Add `FieldSeparator` to divide them.
-
+
## Responsive Layout
@@ -155,6 +201,7 @@ Stack `Field` components with `FieldGroup`. Add `FieldSeparator` to divide them.
- **Responsive fields:** Set `orientation="responsive"` for automatic column layouts inside container-aware parents. Apply `@container/field-group` classes on `FieldGroup` to switch orientations at specific breakpoints.
diff --git a/apps/v4/content/docs/components/form.mdx b/apps/v4/content/docs/components/base/form.mdx
similarity index 98%
rename from apps/v4/content/docs/components/form.mdx
rename to apps/v4/content/docs/components/base/form.mdx
index 8a89d57de4..3a8d903e7c 100644
--- a/apps/v4/content/docs/components/form.mdx
+++ b/apps/v4/content/docs/components/base/form.mdx
@@ -115,7 +115,11 @@ npm install @radix-ui/react-label @radix-ui/react-slot react-hook-form @hookform
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/hover-card.mdx b/apps/v4/content/docs/components/base/hover-card.mdx
similarity index 84%
rename from apps/v4/content/docs/components/hover-card.mdx
rename to apps/v4/content/docs/components/base/hover-card.mdx
index 8dacd7e557..448c49e760 100644
--- a/apps/v4/content/docs/components/hover-card.mdx
+++ b/apps/v4/content/docs/components/base/hover-card.mdx
@@ -1,13 +1,18 @@
---
title: Hover Card
description: For sighted users to preview content available behind a link.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/hover-card
api: https://www.radix-ui.com/docs/primitives/components/hover-card#api-reference
---
-
+
## Installation
@@ -37,7 +42,11 @@ npm install @radix-ui/react-hover-card
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/input-group.mdx b/apps/v4/content/docs/components/base/input-group.mdx
similarity index 85%
rename from apps/v4/content/docs/components/input-group.mdx
rename to apps/v4/content/docs/components/base/input-group.mdx
index e46960e8a0..28e2eba954 100644
--- a/apps/v4/content/docs/components/input-group.mdx
+++ b/apps/v4/content/docs/components/base/input-group.mdx
@@ -1,12 +1,17 @@
---
title: Input Group
description: Display additional information or actions to an input or textarea.
+base: base
component: true
---
import { IconInfoCircle } from "@tabler/icons-react"
-
+
## Installation
@@ -30,7 +35,11 @@ npx shadcn@latest add input-group
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -69,55 +78,88 @@ import {
### Icon
-
+
### Text
Display additional text information alongside inputs.
-
+
### Button
Add buttons to perform actions within the input group.
-
+
### Tooltip
Add tooltips to provide additional context or help.
-
+
### Textarea
Input groups also work with textarea components. Use `block-start` or `block-end` for alignment.
-
+
### Spinner
Show loading indicators while processing input.
-
+
### Label
Add labels within input groups to improve accessibility.
-
+
### Dropdown
Pair input groups with dropdown menus for complex interactions.
-
+
### Button Group
Wrap input groups with button groups to create prefixes and suffixes.
@@ -129,6 +171,7 @@ Add the `data-slot="input-group-control"` attribute to your custom input for aut
No style is applied to the custom input. Apply your own styles using the `className` prop.
diff --git a/apps/v4/content/docs/components/input-otp.mdx b/apps/v4/content/docs/components/base/input-otp.mdx
similarity index 92%
rename from apps/v4/content/docs/components/input-otp.mdx
rename to apps/v4/content/docs/components/base/input-otp.mdx
index 9c56f18be3..c2897c683f 100644
--- a/apps/v4/content/docs/components/input-otp.mdx
+++ b/apps/v4/content/docs/components/base/input-otp.mdx
@@ -1,12 +1,17 @@
---
title: Input OTP
description: Accessible one-time password component with copy paste functionality.
+base: base
component: true
links:
doc: https://input-otp.rodz.dev
---
-
+
## About
@@ -46,7 +51,11 @@ npm install input-otp
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -90,6 +99,7 @@ import {
Use the `pattern` prop to define a custom pattern for the OTP input.
@@ -115,6 +125,7 @@ import { REGEXP_ONLY_DIGITS_AND_CHARS } from "input-otp"
You can use the ` ` component to add a separator between the input groups.
@@ -146,11 +157,11 @@ import {
You can use the `value` and `onChange` props to control the input value.
-
+
### Form
-
+
## Changelog
diff --git a/apps/v4/content/docs/components/input.mdx b/apps/v4/content/docs/components/base/input.mdx
similarity index 86%
rename from apps/v4/content/docs/components/input.mdx
rename to apps/v4/content/docs/components/base/input.mdx
index c4638ca6b1..5ff77703cc 100644
--- a/apps/v4/content/docs/components/input.mdx
+++ b/apps/v4/content/docs/components/base/input.mdx
@@ -1,10 +1,12 @@
---
title: Input
description: Displays a form input field or a component that looks like an input field.
+base: base
component: true
---
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -57,6 +63,7 @@ import { Input } from "@/components/ui/input"
### Default
+
## Installation
@@ -32,7 +37,11 @@ npx shadcn@latest add item
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -80,39 +89,71 @@ If you only need to display content such as a title, description, and actions, u
### Variants
-
+
### Size
The `Item` component has different sizes for different use cases. For example, you can use the `sm` size for a compact item or the `default` size for a standard item.
-
+
### Icon
-
+
### Avatar
-
+
### Image
-
+
### Group
-
+
### Header
-
+
### Link
To render an item as a link, use the `asChild` prop. The hover and focus states will be applied to the anchor element.
-
+
```tsx showLineNumbers
-
@@ -129,7 +170,11 @@ To render an item as a link, use the `asChild` prop. The hover and focus states
### Dropdown
-
+
## API Reference
diff --git a/apps/v4/content/docs/components/kbd.mdx b/apps/v4/content/docs/components/base/kbd.mdx
similarity index 79%
rename from apps/v4/content/docs/components/kbd.mdx
rename to apps/v4/content/docs/components/base/kbd.mdx
index 47e934eca1..b8cd804137 100644
--- a/apps/v4/content/docs/components/kbd.mdx
+++ b/apps/v4/content/docs/components/base/kbd.mdx
@@ -1,10 +1,11 @@
---
title: Kbd
description: Used to display textual user input from keyboard.
+base: base
component: true
---
-
+
## Installation
@@ -28,7 +29,11 @@ npx shadcn@latest add kbd
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -54,25 +59,25 @@ import { Kbd } from "@/components/ui/kbd"
Use the `KbdGroup` component to group keyboard keys together.
-
+
### Button
Use the `Kbd` component inside a `Button` component to display a keyboard key inside a button.
-
+
### Tooltip
You can use the `Kbd` component inside a `Tooltip` component to display a tooltip with a keyboard key.
-
+
### Input Group
You can use the `Kbd` component inside a `InputGroupAddon` component to display a keyboard key inside an input group.
-
+
## API Reference
diff --git a/apps/v4/content/docs/components/label.mdx b/apps/v4/content/docs/components/base/label.mdx
similarity index 82%
rename from apps/v4/content/docs/components/label.mdx
rename to apps/v4/content/docs/components/base/label.mdx
index f2f60e9282..de83018cff 100644
--- a/apps/v4/content/docs/components/label.mdx
+++ b/apps/v4/content/docs/components/base/label.mdx
@@ -1,13 +1,18 @@
---
title: Label
description: Renders an accessible label associated with controls.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/label
api: https://www.radix-ui.com/docs/primitives/components/label#api-reference
---
-
+
## Installation
@@ -37,7 +42,11 @@ npm install @radix-ui/react-label
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/menubar.mdx b/apps/v4/content/docs/components/base/menubar.mdx
similarity index 87%
rename from apps/v4/content/docs/components/menubar.mdx
rename to apps/v4/content/docs/components/base/menubar.mdx
index a96439dad8..aab7a7fb18 100644
--- a/apps/v4/content/docs/components/menubar.mdx
+++ b/apps/v4/content/docs/components/base/menubar.mdx
@@ -1,13 +1,18 @@
---
title: Menubar
description: A visually persistent menu common in desktop applications that provides quick access to a consistent set of commands.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/menubar
api: https://www.radix-ui.com/docs/primitives/components/menubar#api-reference
---
-
+
## Installation
@@ -37,7 +42,11 @@ npm install @radix-ui/react-menubar
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/base/meta.json b/apps/v4/content/docs/components/base/meta.json
new file mode 100644
index 0000000000..876c74b3f0
--- /dev/null
+++ b/apps/v4/content/docs/components/base/meta.json
@@ -0,0 +1,64 @@
+{
+ "title": "Base UI",
+ "pages": [
+ "accordion",
+ "alert",
+ "alert-dialog",
+ "aspect-ratio",
+ "avatar",
+ "badge",
+ "breadcrumb",
+ "button",
+ "button-group",
+ "calendar",
+ "card",
+ "carousel",
+ "chart",
+ "checkbox",
+ "collapsible",
+ "combobox",
+ "command",
+ "context-menu",
+ "data-table",
+ "date-picker",
+ "dialog",
+ "drawer",
+ "dropdown-menu",
+ "empty",
+ "field",
+ "form",
+ "hover-card",
+ "input",
+ "input-group",
+ "input-otp",
+ "item",
+ "kbd",
+ "label",
+ "menubar",
+ "native-select",
+ "navigation-menu",
+ "pagination",
+ "popover",
+ "progress",
+ "radio-group",
+ "resizable",
+ "scroll-area",
+ "select",
+ "separator",
+ "sheet",
+ "sidebar",
+ "skeleton",
+ "slider",
+ "sonner",
+ "spinner",
+ "switch",
+ "table",
+ "tabs",
+ "textarea",
+ "toast",
+ "toggle",
+ "toggle-group",
+ "tooltip",
+ "typography"
+ ]
+}
diff --git a/apps/v4/content/docs/components/native-select.mdx b/apps/v4/content/docs/components/base/native-select.mdx
similarity index 90%
rename from apps/v4/content/docs/components/native-select.mdx
rename to apps/v4/content/docs/components/base/native-select.mdx
index 77e4d11b1c..2a4204cf97 100644
--- a/apps/v4/content/docs/components/native-select.mdx
+++ b/apps/v4/content/docs/components/base/native-select.mdx
@@ -1,6 +1,7 @@
---
title: Native Select
description: A styled native HTML select element with consistent design system integration.
+base: base
component: true
---
@@ -11,7 +12,7 @@ import { InfoIcon } from "lucide-react"
component.
-
+
## Installation
@@ -35,7 +36,11 @@ npx shadcn@latest add native-select
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -74,7 +79,7 @@ import {
Organize options using `NativeSelectOptGroup` for better categorization.
-
+
```tsx showLineNumbers
@@ -96,13 +101,13 @@ Organize options using `NativeSelectOptGroup` for better categorization.
Disable individual options or the entire select component.
-
+
### Invalid State
Show validation errors with the `aria-invalid` attribute and error styling.
-
+
```tsx showLineNumbers
@@ -117,13 +122,13 @@ Show validation errors with the `aria-invalid` attribute and error styling.
Use with form libraries like React Hook Form for controlled components.
-
+
### Input Group Integration
Combine with `InputGroup` for complex input layouts.
-
+
## Native Select vs Select
diff --git a/apps/v4/content/docs/components/navigation-menu.mdx b/apps/v4/content/docs/components/base/navigation-menu.mdx
similarity index 98%
rename from apps/v4/content/docs/components/navigation-menu.mdx
rename to apps/v4/content/docs/components/base/navigation-menu.mdx
index 582d634b6c..affd8d0b2b 100644
--- a/apps/v4/content/docs/components/navigation-menu.mdx
+++ b/apps/v4/content/docs/components/base/navigation-menu.mdx
@@ -1,6 +1,7 @@
---
title: Navigation Menu
description: A collection of links for navigating websites.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/navigation-menu
@@ -8,6 +9,7 @@ links:
---
diff --git a/apps/v4/content/docs/components/pagination.mdx b/apps/v4/content/docs/components/base/pagination.mdx
similarity index 93%
rename from apps/v4/content/docs/components/pagination.mdx
rename to apps/v4/content/docs/components/base/pagination.mdx
index a1e79dd892..e6139ffe82 100644
--- a/apps/v4/content/docs/components/pagination.mdx
+++ b/apps/v4/content/docs/components/base/pagination.mdx
@@ -1,10 +1,12 @@
---
title: Pagination
description: Pagination with page navigation, next and previous links.
+base: base
component: true
---
@@ -31,7 +33,11 @@ npx shadcn@latest add pagination
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/popover.mdx b/apps/v4/content/docs/components/base/popover.mdx
similarity index 90%
rename from apps/v4/content/docs/components/popover.mdx
rename to apps/v4/content/docs/components/base/popover.mdx
index 53e1e933bf..67ad1b1da1 100644
--- a/apps/v4/content/docs/components/popover.mdx
+++ b/apps/v4/content/docs/components/base/popover.mdx
@@ -1,6 +1,7 @@
---
title: Popover
description: Displays rich content in a portal, triggered by a button.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/popover
@@ -8,6 +9,7 @@ links:
---
@@ -40,7 +42,11 @@ npm install @radix-ui/react-popover
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/progress.mdx b/apps/v4/content/docs/components/base/progress.mdx
similarity index 89%
rename from apps/v4/content/docs/components/progress.mdx
rename to apps/v4/content/docs/components/base/progress.mdx
index fba7eb68e7..df3ede6f93 100644
--- a/apps/v4/content/docs/components/progress.mdx
+++ b/apps/v4/content/docs/components/base/progress.mdx
@@ -1,6 +1,7 @@
---
title: Progress
description: Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/progress
@@ -8,6 +9,7 @@ links:
---
@@ -40,7 +42,11 @@ npm install @radix-ui/react-progress
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/radio-group.mdx b/apps/v4/content/docs/components/base/radio-group.mdx
similarity index 91%
rename from apps/v4/content/docs/components/radio-group.mdx
rename to apps/v4/content/docs/components/base/radio-group.mdx
index 0b571c8354..3043cbe58f 100644
--- a/apps/v4/content/docs/components/radio-group.mdx
+++ b/apps/v4/content/docs/components/base/radio-group.mdx
@@ -1,6 +1,7 @@
---
title: Radio Group
description: A set of checkable buttons—known as radio buttons—where no more than one of the buttons can be checked at a time.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/radio-group
@@ -8,6 +9,7 @@ links:
---
@@ -40,7 +42,11 @@ npm install @radix-ui/react-radio-group
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/resizable.mdx b/apps/v4/content/docs/components/base/resizable.mdx
similarity index 93%
rename from apps/v4/content/docs/components/resizable.mdx
rename to apps/v4/content/docs/components/base/resizable.mdx
index bda70158a6..f180db53d3 100644
--- a/apps/v4/content/docs/components/resizable.mdx
+++ b/apps/v4/content/docs/components/base/resizable.mdx
@@ -1,6 +1,7 @@
---
title: Resizable
description: Accessible resizable panel groups and layouts with keyboard support.
+base: base
component: true
links:
doc: https://github.com/bvaughn/react-resizable-panels
@@ -8,6 +9,7 @@ links:
---
@@ -44,7 +46,11 @@ npm install react-resizable-panels
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -79,6 +85,7 @@ import {
Use the `direction` prop to set the direction of the resizable panels.
@@ -106,6 +113,7 @@ export default function Example() {
You can set or hide the handle by using the `withHandle` prop on the `ResizableHandle` component.
diff --git a/apps/v4/content/docs/components/scroll-area.mdx b/apps/v4/content/docs/components/base/scroll-area.mdx
similarity index 88%
rename from apps/v4/content/docs/components/scroll-area.mdx
rename to apps/v4/content/docs/components/base/scroll-area.mdx
index c5c33a4e85..449e342214 100644
--- a/apps/v4/content/docs/components/scroll-area.mdx
+++ b/apps/v4/content/docs/components/base/scroll-area.mdx
@@ -1,6 +1,7 @@
---
title: Scroll Area
description: Augments native scroll functionality for custom, cross-browser styling.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/scroll-area
@@ -8,6 +9,7 @@ links:
---
@@ -40,7 +42,11 @@ npm install @radix-ui/react-scroll-area
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -71,4 +77,4 @@ import { ScrollArea } from "@/components/ui/scroll-area"
### Horizontal Scrolling
-
+
diff --git a/apps/v4/content/docs/components/select.mdx b/apps/v4/content/docs/components/base/select.mdx
similarity index 91%
rename from apps/v4/content/docs/components/select.mdx
rename to apps/v4/content/docs/components/base/select.mdx
index 96e6f3bc7e..9fb1ce004d 100644
--- a/apps/v4/content/docs/components/select.mdx
+++ b/apps/v4/content/docs/components/base/select.mdx
@@ -1,6 +1,7 @@
---
title: Select
description: Displays a list of options for the user to pick from—triggered by a button.
+base: base
component: true
featured: true
links:
@@ -9,6 +10,7 @@ links:
---
@@ -41,7 +43,11 @@ npm install @radix-ui/react-select
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -81,6 +87,7 @@ import {
### Scrollable
diff --git a/apps/v4/content/docs/components/separator.mdx b/apps/v4/content/docs/components/base/separator.mdx
similarity index 81%
rename from apps/v4/content/docs/components/separator.mdx
rename to apps/v4/content/docs/components/base/separator.mdx
index ae264acb2f..ee0696d80f 100644
--- a/apps/v4/content/docs/components/separator.mdx
+++ b/apps/v4/content/docs/components/base/separator.mdx
@@ -1,13 +1,18 @@
---
title: Separator
description: Visually or semantically separates content.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/separator
api: https://www.radix-ui.com/docs/primitives/components/separator#api-reference
---
-
+
## Installation
@@ -36,7 +41,11 @@ npm install @radix-ui/react-separator
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/sheet.mdx b/apps/v4/content/docs/components/base/sheet.mdx
similarity index 91%
rename from apps/v4/content/docs/components/sheet.mdx
rename to apps/v4/content/docs/components/base/sheet.mdx
index a3c5a88d18..27eef4199b 100644
--- a/apps/v4/content/docs/components/sheet.mdx
+++ b/apps/v4/content/docs/components/base/sheet.mdx
@@ -1,13 +1,18 @@
---
title: Sheet
description: Extends the Dialog component to display content that complements the main content of the screen.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/dialog
api: https://www.radix-ui.com/docs/primitives/components/dialog#api-reference
---
-
+
## Installation
@@ -37,7 +42,11 @@ npm install @radix-ui/react-dialog
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/sidebar.mdx b/apps/v4/content/docs/components/base/sidebar.mdx
similarity index 98%
rename from apps/v4/content/docs/components/sidebar.mdx
rename to apps/v4/content/docs/components/base/sidebar.mdx
index ca0e8da886..c96de9c47b 100644
--- a/apps/v4/content/docs/components/sidebar.mdx
+++ b/apps/v4/content/docs/components/base/sidebar.mdx
@@ -1,11 +1,13 @@
---
title: Sidebar
description: A composable, themeable and customizable sidebar component.
+base: base
component: true
---
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -317,6 +323,7 @@ You should see something like this:
` to the `SidebarHeader`.
` to the `SidebarFooter`.
` and ` ` to render a submenu
+
## Installation
@@ -28,7 +33,11 @@ npx shadcn@latest add skeleton
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -53,6 +62,7 @@ import { Skeleton } from "@/components/ui/skeleton"
### Card
diff --git a/apps/v4/content/docs/components/slider.mdx b/apps/v4/content/docs/components/base/slider.mdx
similarity index 82%
rename from apps/v4/content/docs/components/slider.mdx
rename to apps/v4/content/docs/components/base/slider.mdx
index e4aaf8e3fc..32bb336ecb 100644
--- a/apps/v4/content/docs/components/slider.mdx
+++ b/apps/v4/content/docs/components/base/slider.mdx
@@ -1,13 +1,18 @@
---
title: Slider
description: An input where the user selects a value from within a given range.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/slider
api: https://www.radix-ui.com/docs/primitives/components/slider#api-reference
---
-
+
## Installation
@@ -37,7 +42,11 @@ npm install @radix-ui/react-slider
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/sonner.mdx b/apps/v4/content/docs/components/base/sonner.mdx
similarity index 92%
rename from apps/v4/content/docs/components/sonner.mdx
rename to apps/v4/content/docs/components/base/sonner.mdx
index 2b87452e14..71239fb04d 100644
--- a/apps/v4/content/docs/components/sonner.mdx
+++ b/apps/v4/content/docs/components/base/sonner.mdx
@@ -1,12 +1,13 @@
---
title: Sonner
description: An opinionated toast component for React.
+base: base
component: true
links:
doc: https://sonner.emilkowal.ski
---
-
+
## About
@@ -64,7 +65,11 @@ npm install sonner next-themes
Copy and paste the following code into your project.
-
+
Add the Toaster component
@@ -102,7 +107,7 @@ toast("Event has been created.")
## Examples
-
+
## Changelog
diff --git a/apps/v4/content/docs/components/spinner.mdx b/apps/v4/content/docs/components/base/spinner.mdx
similarity index 72%
rename from apps/v4/content/docs/components/spinner.mdx
rename to apps/v4/content/docs/components/base/spinner.mdx
index b4c2159b21..57dc12ad5b 100644
--- a/apps/v4/content/docs/components/spinner.mdx
+++ b/apps/v4/content/docs/components/base/spinner.mdx
@@ -1,10 +1,15 @@
---
title: Spinner
description: An indicator that can be used to show a loading state.
+base: base
component: true
---
-
+
## Installation
@@ -28,7 +33,11 @@ npx shadcn@latest add spinner
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -52,7 +61,7 @@ import { Spinner } from "@/components/ui/spinner"
You can replace the default spinner icon with any other icon by editing the `Spinner` component.
-
+
```tsx showLineNumbers title="components/ui/spinner.tsx"
import { LoaderIcon } from "lucide-react"
@@ -79,41 +88,41 @@ export { Spinner }
Use the `size-*` utility class to change the size of the spinner.
-
+
### Color
Use the `text-` utility class to change the color of the spinner.
-
+
### Button
Add a spinner to a button to indicate a loading state. The ` ` will handle the spacing between the spinner and the text.
-
+
### Badge
You can also use a spinner inside a badge.
-
+
### Input Group
Input Group can have spinners inside ``.
-
+
### Empty
-
+
### Item
Use the spinner inside `` to indicate a loading state.
-
+
## API Reference
diff --git a/apps/v4/content/docs/components/switch.mdx b/apps/v4/content/docs/components/base/switch.mdx
similarity index 81%
rename from apps/v4/content/docs/components/switch.mdx
rename to apps/v4/content/docs/components/base/switch.mdx
index 2c7bae254c..b78eed1af2 100644
--- a/apps/v4/content/docs/components/switch.mdx
+++ b/apps/v4/content/docs/components/base/switch.mdx
@@ -1,13 +1,18 @@
---
title: Switch
description: A control that allows the user to toggle between checked and not checked.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/switch
api: https://www.radix-ui.com/docs/primitives/components/switch#api-reference
---
-
+
## Installation
@@ -37,7 +42,11 @@ npm install @radix-ui/react-switch
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/table.mdx b/apps/v4/content/docs/components/base/table.mdx
similarity index 89%
rename from apps/v4/content/docs/components/table.mdx
rename to apps/v4/content/docs/components/base/table.mdx
index 9ded734a91..8be9ebd62c 100644
--- a/apps/v4/content/docs/components/table.mdx
+++ b/apps/v4/content/docs/components/base/table.mdx
@@ -1,10 +1,15 @@
---
title: Table
description: A responsive table component.
+base: base
component: true
---
-
+
## Installation
@@ -28,7 +33,11 @@ npx shadcn@latest add table
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/tabs.mdx b/apps/v4/content/docs/components/base/tabs.mdx
similarity index 91%
rename from apps/v4/content/docs/components/tabs.mdx
rename to apps/v4/content/docs/components/base/tabs.mdx
index 90a0323293..d3d95f6e52 100644
--- a/apps/v4/content/docs/components/tabs.mdx
+++ b/apps/v4/content/docs/components/base/tabs.mdx
@@ -1,6 +1,7 @@
---
title: Tabs
description: A set of layered sections of content—known as tab panels—that are displayed one at a time.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/tabs
@@ -8,6 +9,7 @@ links:
---
@@ -40,7 +42,11 @@ npm install @radix-ui/react-tabs
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/textarea.mdx b/apps/v4/content/docs/components/base/textarea.mdx
similarity index 69%
rename from apps/v4/content/docs/components/textarea.mdx
rename to apps/v4/content/docs/components/base/textarea.mdx
index c8175f73e9..c80d19ab01 100644
--- a/apps/v4/content/docs/components/textarea.mdx
+++ b/apps/v4/content/docs/components/base/textarea.mdx
@@ -1,10 +1,15 @@
---
title: Textarea
description: Displays a form textarea or a component that looks like a textarea.
+base: base
component: true
---
-
+
## Installation
@@ -28,7 +33,11 @@ npx shadcn@latest add textarea
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -52,15 +61,24 @@ import { Textarea } from "@/components/ui/textarea"
### Default
-
+
### Disabled
-
+
### With Label
@@ -76,6 +95,7 @@ import { Textarea } from "@/components/ui/textarea"
### With Button
diff --git a/apps/v4/content/docs/components/toast.mdx b/apps/v4/content/docs/components/base/toast.mdx
similarity index 98%
rename from apps/v4/content/docs/components/toast.mdx
rename to apps/v4/content/docs/components/base/toast.mdx
index 9069d926c7..57b07f3bb8 100644
--- a/apps/v4/content/docs/components/toast.mdx
+++ b/apps/v4/content/docs/components/base/toast.mdx
@@ -1,6 +1,7 @@
---
title: Toast
description: A succinct message that is displayed temporarily.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/toast
diff --git a/apps/v4/content/docs/components/toggle-group.mdx b/apps/v4/content/docs/components/base/toggle-group.mdx
similarity index 89%
rename from apps/v4/content/docs/components/toggle-group.mdx
rename to apps/v4/content/docs/components/base/toggle-group.mdx
index 856b46bd5f..3ebff1df5d 100644
--- a/apps/v4/content/docs/components/toggle-group.mdx
+++ b/apps/v4/content/docs/components/base/toggle-group.mdx
@@ -1,13 +1,14 @@
---
title: Toggle Group
description: A set of two-state buttons that can be toggled on or off.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/toggle-group
api: https://www.radix-ui.com/docs/primitives/components/toggle-group#api-reference
---
-
+
## Installation
@@ -37,7 +38,11 @@ npm install @radix-ui/react-toggle-group
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -66,6 +71,7 @@ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
### Outline
@@ -73,6 +79,7 @@ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
### Single
@@ -80,6 +87,7 @@ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
### Small
@@ -87,6 +95,7 @@ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
### Large
@@ -94,6 +103,7 @@ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
### Disabled
@@ -103,6 +113,7 @@ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
Use `spacing={2}` to add spacing between toggle group items.
diff --git a/apps/v4/content/docs/components/toggle.mdx b/apps/v4/content/docs/components/base/toggle.mdx
similarity index 68%
rename from apps/v4/content/docs/components/toggle.mdx
rename to apps/v4/content/docs/components/base/toggle.mdx
index e826256df8..0a4915bd26 100644
--- a/apps/v4/content/docs/components/toggle.mdx
+++ b/apps/v4/content/docs/components/base/toggle.mdx
@@ -1,13 +1,18 @@
---
title: Toggle
description: A two-state button that can be either on or off.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/toggle
api: https://www.radix-ui.com/docs/primitives/components/toggle#api-reference
---
-
+
## Installation
@@ -37,7 +42,11 @@ npm install @radix-ui/react-toggle
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -61,11 +70,16 @@ import { Toggle } from "@/components/ui/toggle"
### Default
-
+
### Outline
@@ -73,21 +87,31 @@ import { Toggle } from "@/components/ui/toggle"
### With Text
### Small
-
+
### Large
-
+
### Disabled
diff --git a/apps/v4/content/docs/components/tooltip.mdx b/apps/v4/content/docs/components/base/tooltip.mdx
similarity index 87%
rename from apps/v4/content/docs/components/tooltip.mdx
rename to apps/v4/content/docs/components/base/tooltip.mdx
index f87036bfa2..17b4b43899 100644
--- a/apps/v4/content/docs/components/tooltip.mdx
+++ b/apps/v4/content/docs/components/base/tooltip.mdx
@@ -1,13 +1,18 @@
---
title: Tooltip
description: A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.
+base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/tooltip
api: https://www.radix-ui.com/docs/primitives/components/tooltip#api-reference
---
-
+
## Installation
@@ -37,7 +42,11 @@ npm install @radix-ui/react-tooltip
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
diff --git a/apps/v4/content/docs/components/base/typography.mdx b/apps/v4/content/docs/components/base/typography.mdx
new file mode 100644
index 0000000000..8efacfde15
--- /dev/null
+++ b/apps/v4/content/docs/components/base/typography.mdx
@@ -0,0 +1,68 @@
+---
+title: Typography
+description: Styles for headings, paragraphs, lists...etc
+base: base
+component: true
+---
+
+We do not ship any typography styles by default. This page is an example of how you can use utility classes to style your text.
+
+
+
+## h1
+
+
+
+## h2
+
+
+
+## h3
+
+
+
+## h4
+
+
+
+## p
+
+
+
+## blockquote
+
+
+
+## table
+
+
+
+## list
+
+
+
+## Inline code
+
+
+
+## Lead
+
+
+
+## Large
+
+
+
+## Small
+
+
+
+## Muted
+
+
diff --git a/apps/v4/content/docs/components/meta.json b/apps/v4/content/docs/components/meta.json
new file mode 100644
index 0000000000..b366d3b02b
--- /dev/null
+++ b/apps/v4/content/docs/components/meta.json
@@ -0,0 +1,4 @@
+{
+ "title": "Components",
+ "pages": ["..."]
+}
diff --git a/apps/v4/content/docs/components/radix/accordion.mdx b/apps/v4/content/docs/components/radix/accordion.mdx
new file mode 100644
index 0000000000..f2f4bfac00
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/accordion.mdx
@@ -0,0 +1,82 @@
+---
+title: Accordion
+description: A vertically stacked set of interactive headings that each reveal a section of content.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/accordion
+ api: https://www.radix-ui.com/docs/primitives/components/accordion#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+
+```bash
+npx shadcn@latest add accordion
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-accordion
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ Accordion,
+ AccordionContent,
+ AccordionItem,
+ AccordionTrigger,
+} from "@/components/ui/accordion"
+```
+
+```tsx showLineNumbers
+
+
+ Is it accessible?
+
+ Yes. It adheres to the WAI-ARIA design pattern.
+
+
+
+```
diff --git a/apps/v4/content/docs/components/radix/alert-dialog.mdx b/apps/v4/content/docs/components/radix/alert-dialog.mdx
new file mode 100644
index 0000000000..5b8aec504c
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/alert-dialog.mdx
@@ -0,0 +1,94 @@
+---
+title: Alert Dialog
+description: A modal dialog that interrupts the user with important content and expects a response.
+featured: true
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/alert-dialog
+ api: https://www.radix-ui.com/docs/primitives/components/alert-dialog#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add alert-dialog
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-alert-dialog
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+ AlertDialogTrigger,
+} from "@/components/ui/alert-dialog"
+```
+
+```tsx showLineNumbers
+
+ Open
+
+
+ Are you absolutely sure?
+
+ This action cannot be undone. This will permanently delete your account
+ and remove your data from our servers.
+
+
+
+ Cancel
+ Continue
+
+
+
+```
diff --git a/apps/v4/content/docs/components/radix/alert.mdx b/apps/v4/content/docs/components/radix/alert.mdx
new file mode 100644
index 0000000000..d8f7e4e1d8
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/alert.mdx
@@ -0,0 +1,65 @@
+---
+title: Alert
+description: Displays a callout for user attention.
+base: radix
+component: true
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add alert
+```
+
+
+
+
+
+
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
+```
+
+```tsx showLineNumbers
+
+
+ Heads up!
+
+ You can add components and dependencies to your app using the cli.
+
+
+```
diff --git a/apps/v4/content/docs/components/radix/aspect-ratio.mdx b/apps/v4/content/docs/components/radix/aspect-ratio.mdx
new file mode 100644
index 0000000000..a246d3a9f2
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/aspect-ratio.mdx
@@ -0,0 +1,70 @@
+---
+title: Aspect Ratio
+description: Displays content within a desired ratio.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/aspect-ratio
+ api: https://www.radix-ui.com/docs/primitives/components/aspect-ratio#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add aspect-ratio
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-aspect-ratio
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import { AspectRatio } from "@/components/ui/aspect-ratio"
+```
+
+```tsx showLineNumbers
+
+
+
+```
diff --git a/apps/v4/content/docs/components/radix/avatar.mdx b/apps/v4/content/docs/components/radix/avatar.mdx
new file mode 100644
index 0000000000..10e3f25be6
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/avatar.mdx
@@ -0,0 +1,71 @@
+---
+title: Avatar
+description: An image element with a fallback for representing the user.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/avatar
+ api: https://www.radix-ui.com/docs/primitives/components/avatar#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add avatar
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-avatar
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
+```
+
+```tsx showLineNumbers
+
+
+ CN
+
+```
diff --git a/apps/v4/content/docs/components/radix/badge.mdx b/apps/v4/content/docs/components/radix/badge.mdx
new file mode 100644
index 0000000000..3ec855bec1
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/badge.mdx
@@ -0,0 +1,77 @@
+---
+title: Badge
+description: Displays a badge or a component that looks like a badge.
+base: radix
+component: true
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add badge
+```
+
+
+
+
+
+
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx
+import { Badge } from "@/components/ui/badge"
+```
+
+```tsx
+Badge
+```
+
+### Link
+
+You can use the `asChild` prop to make another component look like a badge. Here's an example of a link that looks like a badge.
+
+```tsx showLineNumbers
+import Link from "next/link"
+
+import { Badge } from "@/components/ui/badge"
+
+export function LinkAsBadge() {
+ return (
+
+ Badge
+
+ )
+}
+```
diff --git a/apps/v4/content/docs/components/radix/breadcrumb.mdx b/apps/v4/content/docs/components/radix/breadcrumb.mdx
new file mode 100644
index 0000000000..92303a19ae
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/breadcrumb.mdx
@@ -0,0 +1,222 @@
+---
+title: Breadcrumb
+description: Displays the path to the current resource using a hierarchy of links.
+base: radix
+component: true
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add breadcrumb
+```
+
+
+
+
+
+
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ Breadcrumb,
+ BreadcrumbItem,
+ BreadcrumbLink,
+ BreadcrumbList,
+ BreadcrumbPage,
+ BreadcrumbSeparator,
+} from "@/components/ui/breadcrumb"
+```
+
+```tsx showLineNumbers
+
+
+
+ Home
+
+
+
+ Components
+
+
+
+ Breadcrumb
+
+
+
+```
+
+## Examples
+
+### Custom separator
+
+Use a custom component as `children` for ` ` to create a custom separator.
+
+
+
+```tsx showLineNumbers {1,10-12}
+import { SlashIcon } from "lucide-react"
+
+...
+
+
+
+
+ Home
+
+
+
+
+
+ Components
+
+
+
+```
+
+---
+
+### Dropdown
+
+You can compose ` ` with a ` ` to create a dropdown in the breadcrumb.
+
+
+
+```tsx showLineNumbers {1-6,11-21}
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu"
+
+...
+
+
+
+
+ Components
+
+
+ Documentation
+ Themes
+ GitHub
+
+
+
+```
+
+---
+
+### Collapsed
+
+We provide a ` ` component to show a collapsed state when the breadcrumb is too long.
+
+
+
+```tsx showLineNumbers {1,9}
+import { BreadcrumbEllipsis } from "@/components/ui/breadcrumb"
+
+...
+
+
+
+ {/* ... */}
+
+
+
+ {/* ... */}
+
+
+```
+
+---
+
+### Link component
+
+To use a custom link component from your routing library, you can use the `asChild` prop on ` `.
+
+
+
+```tsx showLineNumbers {1,8-10}
+import Link from "next/link"
+
+...
+
+
+
+
+
+ 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.
+
+
diff --git a/apps/v4/content/docs/components/radix/button-group.mdx b/apps/v4/content/docs/components/radix/button-group.mdx
new file mode 100644
index 0000000000..ab1c40e575
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/button-group.mdx
@@ -0,0 +1,224 @@
+---
+title: Button Group
+description: A container that groups related buttons together with consistent styling.
+base: radix
+component: true
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add button-group
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-slot
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx
+import {
+ ButtonGroup,
+ ButtonGroupSeparator,
+ ButtonGroupText,
+} from "@/components/ui/button-group"
+```
+
+```tsx
+
+ Button 1
+ Button 2
+
+```
+
+## Accessibility
+
+- The `ButtonGroup` component has the `role` attribute set to `group`.
+- Use Tab to navigate between the buttons in the group.
+- Use `aria-label` or `aria-labelledby` to label the button group.
+
+```tsx showLineNumbers
+
+ Button 1
+ Button 2
+
+```
+
+## ButtonGroup vs ToggleGroup
+
+- Use the `ButtonGroup` component when you want to group buttons that perform an action.
+- Use the `ToggleGroup` component when you want to group buttons that toggle a state.
+
+## Examples
+
+### Orientation
+
+Set the `orientation` prop to change the button group layout.
+
+
+
+### Size
+
+Control the size of buttons using the `size` prop on individual buttons.
+
+
+
+### Nested
+
+Nest `` components to create button groups with spacing.
+
+
+
+### Separator
+
+The `ButtonGroupSeparator` component visually divides buttons within a group.
+
+Buttons with variant `outline` do not need a separator since they have a border. For other variants, a separator is recommended to improve the visual hierarchy.
+
+
+
+### Split
+
+Create a split button group by adding two buttons separated by a `ButtonGroupSeparator`.
+
+
+
+### Input
+
+Wrap an `Input` component with buttons.
+
+
+
+### Input Group
+
+Wrap an `InputGroup` component to create complex input layouts.
+
+
+
+### Dropdown Menu
+
+Create a split button group with a `DropdownMenu` component.
+
+
+
+### Select
+
+Pair with a `Select` component.
+
+
+
+### Popover
+
+Use with a `Popover` component.
+
+
+
+## API Reference
+
+### ButtonGroup
+
+The `ButtonGroup` component is a container that groups related buttons together with consistent styling.
+
+| Prop | Type | Default |
+| ------------- | ---------------------------- | -------------- |
+| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` |
+
+```tsx
+
+ Button 1
+ Button 2
+
+```
+
+Nest multiple button groups to create complex layouts with spacing. See the [nested](#nested) example for more details.
+
+```tsx
+
+
+
+
+```
+
+### ButtonGroupSeparator
+
+The `ButtonGroupSeparator` component visually divides buttons within a group.
+
+| Prop | Type | Default |
+| ------------- | ---------------------------- | ------------ |
+| `orientation` | `"horizontal" \| "vertical"` | `"vertical"` |
+
+```tsx
+
+ Button 1
+
+ Button 2
+
+```
+
+### ButtonGroupText
+
+Use this component to display text within a button group.
+
+| Prop | Type | Default |
+| --------- | --------- | ------- |
+| `asChild` | `boolean` | `false` |
+
+```tsx
+
+ Text
+ Button
+
+```
+
+Use the `asChild` prop to render a custom component as the text, for example a label.
+
+```tsx showLineNumbers
+import { ButtonGroupText } from "@/components/ui/button-group"
+import { Label } from "@/components/ui/label"
+
+export function ButtonGroupTextDemo() {
+ return (
+
+
+ Text
+
+
+
+ )
+}
+```
diff --git a/apps/v4/content/docs/components/button.mdx b/apps/v4/content/docs/components/radix/button.mdx
similarity index 90%
rename from apps/v4/content/docs/components/button.mdx
rename to apps/v4/content/docs/components/radix/button.mdx
index 73bb53644c..191a826abc 100644
--- a/apps/v4/content/docs/components/button.mdx
+++ b/apps/v4/content/docs/components/radix/button.mdx
@@ -2,6 +2,7 @@
title: Button
description: Displays a button or a component that looks like a button.
featured: true
+base: radix
component: true
---
@@ -14,7 +15,12 @@ instructions to update your project.
-
+
```tsx showLineNumbers
Button
@@ -51,7 +57,11 @@ npm install @radix-ui/react-slot
Copy and paste the following code into your project.
-
+
Update the import paths to match your project setup.
@@ -90,7 +100,7 @@ If you want to keep the `cursor: pointer` behavior, add the following code to yo
### Size
-
+
```tsx
// Small
@@ -115,6 +125,7 @@ If you want to keep the `cursor: pointer` behavior, add the following code to yo
### Default
+
```tsx
@@ -230,6 +252,7 @@ Use the `rounded-full` class to make the button rounded.
### Spinner
+
```tsx showLineNumbers
diff --git a/apps/v4/content/docs/components/radix/calendar.mdx b/apps/v4/content/docs/components/radix/calendar.mdx
new file mode 100644
index 0000000000..781b01d3eb
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/calendar.mdx
@@ -0,0 +1,512 @@
+---
+title: Calendar
+description: A date field component that allows users to enter and edit date.
+base: radix
+component: true
+links:
+ doc: https://react-day-picker.js.org
+---
+
+
+
+## Blocks
+
+We have built a collection of 30+ calendar blocks that you can use to build your own calendar components.
+
+See all calendar blocks in the [Blocks Library](/blocks/calendar) page.
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add calendar
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install react-day-picker date-fns
+```
+
+Add the `Button` component to your project.
+
+The `Calendar` component uses the `Button` component. Make sure you have it installed in your project.
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import { Calendar } from "@/components/ui/calendar"
+```
+
+```tsx showLineNumbers
+const [date, setDate] = React.useState(new Date())
+
+return (
+
+)
+```
+
+See the [React DayPicker](https://react-day-picker.js.org) documentation for more information.
+
+## About
+
+The `Calendar` component is built on top of [React DayPicker](https://react-day-picker.js.org).
+
+## Customization
+
+See the [React DayPicker](https://react-day-picker.js.org/docs/customization) documentation for more information on how to customize the `Calendar` component.
+
+## Date Picker
+
+You can use the `` component to build a date picker. See the [Date Picker](/docs/components/date-picker) page for more information.
+
+## Persian / Hijri / Jalali Calendar
+
+To use the Persian calendar, edit `components/ui/calendar.tsx` and replace `react-day-picker` with `react-day-picker/persian`.
+
+```diff
+- import { DayPicker } from "react-day-picker"
++ import { DayPicker } from "react-day-picker/persian"
+```
+
+
+
+## Selected Date (With TimeZone)
+
+The Calendar component accepts a `timeZone` prop to ensure dates are displayed and selected in the user's local timezone.
+
+```tsx showLineNumbers
+export function CalendarWithTimezone() {
+ const [date, setDate] = React.useState(undefined)
+ const [timeZone, setTimeZone] = React.useState(undefined)
+
+ React.useEffect(() => {
+ setTimeZone(Intl.DateTimeFormat().resolvedOptions().timeZone)
+ }, [])
+
+ return (
+
+ )
+}
+```
+
+**Note:** If you notice a selected date offset (for example, selecting the 20th highlights the 19th), make sure the `timeZone` prop is set to the user's local timezone.
+
+**Why client-side?** The timezone is detected using `Intl.DateTimeFormat().resolvedOptions().timeZone` inside a `useEffect` to ensure compatibility with server-side rendering. Detecting the timezone during render would cause hydration mismatches, as the server and client may be in different timezones.
+
+## Examples
+
+### Range Calendar
+
+
+
+### Month and Year Selector
+
+
+
+### Date of Birth Picker
+
+
+
+### Date and Time Picker
+
+
+
+### Natural Language Picker
+
+This component uses the `chrono-node` library to parse natural language dates.
+
+
+
+### Custom Cell Size
+
+
+
+You can customize the size of calendar cells using the `--cell-size` CSS variable. You can also make it responsive by using breakpoint-specific values:
+
+```tsx showLineNumbers
+
+```
+
+Or use fixed values:
+
+```tsx showLineNumbers
+
+```
+
+## Upgrade Guide
+
+### Tailwind v4
+
+If you're already using Tailwind v4, you can upgrade to the latest version of the `Calendar` component by running the following command:
+
+```bash
+npx shadcn@latest add calendar
+```
+
+When you're prompted to overwrite the existing `Calendar` component, select `Yes`. **If you have made any changes to the `Calendar` component, you will need to merge your changes with the new version.**
+
+This will update the `Calendar` component and `react-day-picker` to the latest version.
+
+Next, follow the [React DayPicker](https://daypicker.dev/upgrading) upgrade guide to upgrade your existing components to the latest version.
+
+#### Installing Blocks
+
+After upgrading the `Calendar` component, you can install the new blocks by running the `shadcn@latest add` command.
+
+```bash
+npx shadcn@latest add calendar-02
+```
+
+This will install the latest version of the calendar blocks.
+
+### Tailwind v3
+
+If you're using Tailwind v3, you can upgrade to the latest version of the `Calendar` by copying the following code to your `calendar.tsx` file.
+
+
+
+```tsx showLineNumbers title="components/ui/calendar.tsx"
+"use client"
+
+import * as React from "react"
+import {
+ ChevronDownIcon,
+ ChevronLeftIcon,
+ ChevronRightIcon,
+} from "lucide-react"
+import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker"
+
+import { cn } from "@/lib/utils"
+import { Button, buttonVariants } from "@/components/ui/button"
+
+function Calendar({
+ className,
+ classNames,
+ showOutsideDays = true,
+ captionLayout = "label",
+ buttonVariant = "ghost",
+ formatters,
+ components,
+ ...props
+}: React.ComponentProps & {
+ buttonVariant?: React.ComponentProps["variant"]
+}) {
+ const defaultClassNames = getDefaultClassNames()
+
+ return (
+ svg]:rotate-180`,
+ String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
+ className
+ )}
+ captionLayout={captionLayout}
+ formatters={{
+ formatMonthDropdown: (date) =>
+ date.toLocaleString("default", { month: "short" }),
+ ...formatters,
+ }}
+ classNames={{
+ root: cn("w-fit", defaultClassNames.root),
+ months: cn(
+ "relative flex flex-col gap-4 md:flex-row",
+ defaultClassNames.months
+ ),
+ month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
+ nav: cn(
+ "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
+ defaultClassNames.nav
+ ),
+ button_previous: cn(
+ buttonVariants({ variant: buttonVariant }),
+ "h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50",
+ defaultClassNames.button_previous
+ ),
+ button_next: cn(
+ buttonVariants({ variant: buttonVariant }),
+ "h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50",
+ defaultClassNames.button_next
+ ),
+ month_caption: cn(
+ "flex h-[--cell-size] w-full items-center justify-center px-[--cell-size]",
+ defaultClassNames.month_caption
+ ),
+ dropdowns: cn(
+ "flex h-[--cell-size] w-full items-center justify-center gap-1.5 text-sm font-medium",
+ defaultClassNames.dropdowns
+ ),
+ dropdown_root: cn(
+ "has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md border",
+ defaultClassNames.dropdown_root
+ ),
+ dropdown: cn("absolute inset-0 opacity-0", defaultClassNames.dropdown),
+ caption_label: cn(
+ "select-none font-medium",
+ captionLayout === "label"
+ ? "text-sm"
+ : "[&>svg]:text-muted-foreground flex h-8 items-center gap-1 rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5",
+ defaultClassNames.caption_label
+ ),
+ table: "w-full border-collapse",
+ weekdays: cn("flex", defaultClassNames.weekdays),
+ weekday: cn(
+ "text-muted-foreground flex-1 select-none rounded-md text-[0.8rem] font-normal",
+ defaultClassNames.weekday
+ ),
+ week: cn("mt-2 flex w-full", defaultClassNames.week),
+ week_number_header: cn(
+ "w-[--cell-size] select-none",
+ defaultClassNames.week_number_header
+ ),
+ week_number: cn(
+ "text-muted-foreground select-none text-[0.8rem]",
+ defaultClassNames.week_number
+ ),
+ day: cn(
+ "relative w-full h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none",
+ props.showWeekNumber
+ ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-md"
+ : "[&:first-child[data-selected=true]_button]:rounded-l-md",
+ defaultClassNames.day
+ ),
+ range_start: cn(
+ "bg-accent rounded-l-md",
+ defaultClassNames.range_start
+ ),
+ range_middle: cn("rounded-none", defaultClassNames.range_middle),
+ range_end: cn("bg-accent rounded-r-md", defaultClassNames.range_end),
+ today: cn(
+ "bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none",
+ defaultClassNames.today
+ ),
+ outside: cn(
+ "text-muted-foreground aria-selected:text-muted-foreground",
+ defaultClassNames.outside
+ ),
+ disabled: cn(
+ "text-muted-foreground opacity-50",
+ defaultClassNames.disabled
+ ),
+ hidden: cn("invisible", defaultClassNames.hidden),
+ ...classNames,
+ }}
+ components={{
+ Root: ({ className, rootRef, ...props }) => {
+ return (
+
+ )
+ },
+ Chevron: ({ className, orientation, ...props }) => {
+ if (orientation === "left") {
+ return (
+
+ )
+ }
+
+ if (orientation === "right") {
+ return (
+
+ )
+ }
+
+ return (
+
+ )
+ },
+ DayButton: CalendarDayButton,
+ WeekNumber: ({ children, ...props }) => {
+ return (
+
+
+ {children}
+
+
+ )
+ },
+ ...components,
+ }}
+ {...props}
+ />
+ )
+}
+
+function CalendarDayButton({
+ className,
+ day,
+ modifiers,
+ ...props
+}: React.ComponentProps) {
+ const defaultClassNames = getDefaultClassNames()
+
+ const ref = React.useRef(null)
+ React.useEffect(() => {
+ if (modifiers.focused) ref.current?.focus()
+ }, [modifiers.focused])
+
+ return (
+ span]:text-xs [&>span]:opacity-70",
+ defaultClassNames.day,
+ className
+ )}
+ {...props}
+ />
+ )
+}
+
+export { Calendar, CalendarDayButton }
+```
+
+
+
+**If you have made any changes to the `Calendar` component, you will need to merge your changes with the new version.**
+
+Then follow the [React DayPicker](https://daypicker.dev/upgrading) upgrade guide to upgrade your dependencies and existing components to the latest version.
+
+#### Installing Blocks
+
+After upgrading the `Calendar` component, you can install the new blocks by running the `shadcn@latest add` command.
+
+```bash
+npx shadcn@latest add calendar-02
+```
+
+This will install the latest version of the calendar blocks.
+
+## Changelog
+
+### 2025-10-26 Fixed day radius with week numbers
+
+We have fixed an issue where the selected day's left border radius was not applied correctly when week numbers were displayed. The fix ensures that when `showWeekNumber` is enabled, the first day (which is the second child due to the week number column) correctly receives the rounded left border.
+
+To apply this fix, edit `components/ui/calendar.tsx` and update the `day` class in `classNames`:
+
+```tsx showLineNumbers title="components/ui/calendar.tsx" {5-7}
+classNames={{
+ // ... other classNames
+ day: cn(
+ "relative w-full h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none",
+ props.showWeekNumber
+ ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-md"
+ : "[&:first-child[data-selected=true]_button]:rounded-l-md",
+ defaultClassNames.day
+ ),
+ // ... other classNames
+}}
+```
diff --git a/apps/v4/content/docs/components/radix/card.mdx b/apps/v4/content/docs/components/radix/card.mdx
new file mode 100644
index 0000000000..295f7beca2
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/card.mdx
@@ -0,0 +1,78 @@
+---
+title: Card
+description: Displays a card with header, content, and footer.
+base: radix
+component: true
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add card
+```
+
+
+
+
+
+
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ Card,
+ CardAction,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card"
+```
+
+```tsx showLineNumbers
+
+
+ Card Title
+ Card Description
+ Card Action
+
+
+ Card Content
+
+
+ Card Footer
+
+
+```
diff --git a/apps/v4/content/docs/components/radix/carousel.mdx b/apps/v4/content/docs/components/radix/carousel.mdx
new file mode 100644
index 0000000000..f82a9a632b
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/carousel.mdx
@@ -0,0 +1,312 @@
+---
+title: Carousel
+description: A carousel with motion and swipe built using Embla.
+base: radix
+component: true
+links:
+ doc: https://www.embla-carousel.com/get-started/react
+ api: https://www.embla-carousel.com/api
+---
+
+
+
+## About
+
+The carousel component is built using the [Embla Carousel](https://www.embla-carousel.com/) library.
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+
+```bash
+npx shadcn@latest add carousel
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install embla-carousel-react
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ Carousel,
+ CarouselContent,
+ CarouselItem,
+ CarouselNext,
+ CarouselPrevious,
+} from "@/components/ui/carousel"
+```
+
+```tsx showLineNumbers
+
+
+ ...
+ ...
+ ...
+
+
+
+
+```
+
+## Examples
+
+### Sizes
+
+To set the size of the items, you can use the `basis` utility class on the ` `.
+
+
+
+```tsx showLineNumbers {4-6}
+// 33% of the carousel width.
+
+
+ ...
+ ...
+ ...
+
+
+```
+
+```tsx showLineNumbers {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 `
+ ` 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.
+
+
+
+
+
+```tsx showLineNumbers /-ml-4/ /pl-4/
+
+
+ ...
+ ...
+ ...
+
+
+```
+
+```tsx showLineNumbers /-ml-2/ /pl-2/ /md:-ml-4/ /md:pl-4/
+
+
+ ...
+ ...
+ ...
+
+
+```
+
+### Orientation
+
+Use the `orientation` prop to set the orientation of the carousel.
+
+
+
+```tsx showLineNumbers /vertical | horizontal/
+
+
+ ...
+ ...
+ ...
+
+
+```
+
+## 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.
+
+```tsx showLineNumbers {2-5}
+
+
+ ...
+ ...
+ ...
+
+
+```
+
+## API
+
+Use a state and the `setApi` props to get an instance of the carousel API.
+
+
+
+```tsx showLineNumbers {1,4,22}
+import { type CarouselApi } from "@/components/ui/carousel"
+
+export function Example() {
+ const [api, setApi] = React.useState()
+ const [current, setCurrent] = React.useState(0)
+ const [count, setCount] = React.useState(0)
+
+ React.useEffect(() => {
+ if (!api) {
+ return
+ }
+
+ setCount(api.scrollSnapList().length)
+ setCurrent(api.selectedScrollSnap() + 1)
+
+ api.on("select", () => {
+ setCurrent(api.selectedScrollSnap() + 1)
+ })
+ }, [api])
+
+ return (
+
+
+ ...
+ ...
+ ...
+
+
+ )
+}
+```
+
+## Events
+
+You can listen to events using the api instance from `setApi`.
+
+```tsx showLineNumbers {1,4-14,16}
+import { type CarouselApi } from "@/components/ui/carousel"
+
+export function Example() {
+ const [api, setApi] = React.useState()
+
+ React.useEffect(() => {
+ if (!api) {
+ return
+ }
+
+ api.on("select", () => {
+ // Do something on select.
+ })
+ }, [api])
+
+ return (
+
+
+ ...
+ ...
+ ...
+
+
+ )
+}
+```
+
+See the [Embla Carousel docs](https://www.embla-carousel.com/api/events/) for more information on using events.
+
+## Plugins
+
+You can use the `plugins` prop to add plugins to the carousel.
+
+```ts showLineNumbers {1,6-10}
+import Autoplay from "embla-carousel-autoplay"
+
+export function Example() {
+ return (
+
+ // ...
+
+ )
+}
+```
+
+
+
+See the [Embla Carousel docs](https://www.embla-carousel.com/api/plugins/) for more information on using plugins.
diff --git a/apps/v4/content/docs/components/radix/chart.mdx b/apps/v4/content/docs/components/radix/chart.mdx
new file mode 100644
index 0000000000..501684bba8
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/chart.mdx
@@ -0,0 +1,615 @@
+---
+title: Chart
+description: Beautiful charts. Built using Recharts. Copy and paste into your apps.
+base: radix
+component: true
+---
+
+
+
+**Note:** We're working on upgrading to Recharts v3. In the meantime, if you'd like to start testing v3, see the code in the comment [here](https://github.com/shadcn-ui/ui/issues/7669#issuecomment-2998299159). We'll have an official release soon.
+
+
+
+
+
+Introducing **Charts**. A collection of chart components that you can copy and paste into your apps.
+
+Charts are designed to look great out of the box. They work well with the other components and are fully customizable to fit your project.
+
+[Browse the Charts Library](/charts).
+
+## Component
+
+We use [Recharts](https://recharts.org/) under the hood.
+
+We designed the `chart` component with composition in mind. **You build your charts using Recharts components and only bring in custom components, such as `ChartTooltip`, when and where you need it**.
+
+```tsx showLineNumbers /ChartContainer/ /ChartTooltipContent/
+import { Bar, BarChart } from "recharts"
+
+import { ChartContainer, ChartTooltipContent } from "@/components/ui/chart"
+
+export function MyChart() {
+ return (
+
+
+
+ } />
+
+
+ )
+}
+```
+
+We do not wrap Recharts. This means you're not locked into an abstraction. When a new Recharts version is released, you can follow the official upgrade path to upgrade your charts.
+
+**The components are yours**.
+
+## Installation
+
+
+
+**Note:** If you are using charts with **React 19** or the **Next.js 15**, see the note [here](/docs/react-19#recharts).
+
+
+
+
+
+
+ CLI
+ Manual
+
+
+
+
+
+Run the following command to install `chart.tsx`
+
+```bash
+npx shadcn@latest add chart
+```
+
+Add the following colors to your CSS file
+
+```css title="app/globals.css" showLineNumbers
+@layer base {
+ :root {
+ --chart-1: oklch(0.646 0.222 41.116);
+ --chart-2: oklch(0.6 0.118 184.704);
+ --chart-3: oklch(0.398 0.07 227.392);
+ --chart-4: oklch(0.828 0.189 84.429);
+ --chart-5: oklch(0.769 0.188 70.08);
+ }
+
+ .dark {
+ --chart-1: oklch(0.488 0.243 264.376);
+ --chart-2: oklch(0.696 0.17 162.48);
+ --chart-3: oklch(0.769 0.188 70.08);
+ --chart-4: oklch(0.627 0.265 303.9);
+ --chart-5: oklch(0.645 0.246 16.439);
+ }
+}
+```
+
+
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install recharts
+```
+
+Copy and paste the following code into `components/ui/chart.tsx`.
+
+
+
+Add the following colors to your CSS file
+
+```css title="app/globals.css" showLineNumbers
+@layer base {
+ :root {
+ --chart-1: oklch(0.646 0.222 41.116);
+ --chart-2: oklch(0.6 0.118 184.704);
+ --chart-3: oklch(0.398 0.07 227.392);
+ --chart-4: oklch(0.828 0.189 84.429);
+ --chart-5: oklch(0.769 0.188 70.08);
+ }
+
+ .dark {
+ --chart-1: oklch(0.488 0.243 264.376);
+ --chart-2: oklch(0.696 0.17 162.48);
+ --chart-3: oklch(0.769 0.188 70.08);
+ --chart-4: oklch(0.627 0.265 303.9);
+ --chart-5: oklch(0.645 0.246 16.439);
+ }
+}
+```
+
+
+
+
+
+
+
+## Your First Chart
+
+Let's build your first chart. We'll build a bar chart, add a grid, axis, tooltip and legend.
+
+
+
+Start by defining your data
+
+The following data represents the number of desktop and mobile users for each month.
+
+
+
+**Note:** Your data can be in any shape. You are not limited to the shape of the data below. Use the `dataKey` prop to map your data to the chart.
+
+
+
+```tsx title="components/example-chart.tsx" showLineNumbers
+const chartData = [
+ { month: "January", desktop: 186, mobile: 80 },
+ { month: "February", desktop: 305, mobile: 200 },
+ { month: "March", desktop: 237, mobile: 120 },
+ { month: "April", desktop: 73, mobile: 190 },
+ { month: "May", desktop: 209, mobile: 130 },
+ { month: "June", desktop: 214, mobile: 140 },
+]
+```
+
+Define your chart config
+
+The chart config holds configuration for the chart. This is where you place human-readable strings, such as labels, icons and color tokens for theming.
+
+```tsx title="components/example-chart.tsx" showLineNumbers
+import { type ChartConfig } from "@/components/ui/chart"
+
+const chartConfig = {
+ desktop: {
+ label: "Desktop",
+ color: "#2563eb",
+ },
+ mobile: {
+ label: "Mobile",
+ color: "#60a5fa",
+ },
+} satisfies ChartConfig
+```
+
+Build your chart
+
+You can now build your chart using Recharts components.
+
+
+
+**Important:** Remember to set a `min-h-[VALUE]` on the `ChartContainer` component. This is required for the chart to be responsive.
+
+
+
+
+
+
+
+
+
+### Add a Grid
+
+Let's add a grid to the chart.
+
+
+
+Import the `CartesianGrid` component.
+
+```tsx /CartesianGrid/
+import { Bar, BarChart, CartesianGrid } from "recharts"
+```
+
+Add the `CartesianGrid` component to your chart.
+
+```tsx showLineNumbers {3}
+
+
+
+
+
+
+
+```
+
+
+
+
+
+### Add an Axis
+
+To add an x-axis to the chart, we'll use the `XAxis` component.
+
+
+
+Import the `XAxis` component.
+
+```tsx /XAxis/
+import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"
+```
+
+Add the `XAxis` component to your chart.
+
+```tsx showLineNumbers {4-10}
+
+
+
+ value.slice(0, 3)}
+ />
+
+
+
+
+```
+
+
+
+
+
+### Add Tooltip
+
+So far we've only used components from Recharts. They look great out of the box thanks to some customization in the `chart` component.
+
+To add a tooltip, we'll use the custom `ChartTooltip` and `ChartTooltipContent` components from `chart`.
+
+
+
+Import the `ChartTooltip` and `ChartTooltipContent` components.
+
+```tsx
+import { ChartTooltip, ChartTooltipContent } from "@/components/ui/chart"
+```
+
+Add the components to your chart.
+
+```tsx showLineNumbers {11}
+
+
+
+ value.slice(0, 3)}
+ />
+ } />
+
+
+
+
+```
+
+
+
+Hover to see the tooltips. Easy, right? Two components, and we've got a beautiful tooltip.
+
+
+
+### Add Legend
+
+We'll do the same for the legend. We'll use the `ChartLegend` and `ChartLegendContent` components from `chart`.
+
+
+
+Import the `ChartLegend` and `ChartLegendContent` components.
+
+```tsx
+import { ChartLegend, ChartLegendContent } from "@/components/ui/chart"
+```
+
+Add the components to your chart.
+
+```tsx showLineNumbers {12}
+
+
+
+ value.slice(0, 3)}
+ />
+ } />
+ } />
+
+
+
+
+```
+
+
+
+
+
+Done. You've built your first chart! What's next?
+
+- [Themes and Colors](/docs/components/chart#theming)
+- [Tooltip](/docs/components/chart#tooltip)
+- [Legend](/docs/components/chart#legend)
+
+## Chart Config
+
+The chart config is where you define the labels, icons and colors for a chart.
+
+It is intentionally decoupled from chart data.
+
+This allows you to share config and color tokens between charts. It can also work independently for cases where your data or color tokens live remotely or in a different format.
+
+```tsx showLineNumbers /ChartConfig/
+import { Monitor } from "lucide-react"
+
+import { type ChartConfig } from "@/components/ui/chart"
+
+const chartConfig = {
+ desktop: {
+ label: "Desktop",
+ icon: Monitor,
+ // A color like 'hsl(220, 98%, 61%)' or 'var(--color-name)'
+ color: "#2563eb",
+ // OR a theme object with 'light' and 'dark' keys
+ theme: {
+ light: "#2563eb",
+ dark: "#dc2626",
+ },
+ },
+} satisfies ChartConfig
+```
+
+## Theming
+
+Charts have built-in support for theming. You can use css variables (recommended) or color values in any color format, such as hex, hsl or oklch.
+
+### CSS Variables
+
+
+
+Define your colors in your css file
+
+```css {6-7,14-15} title="app/globals.css" showLineNumbers
+@layer base {
+ :root {
+ --chart-1: oklch(0.646 0.222 41.116);
+ --chart-2: oklch(0.6 0.118 184.704);
+ }
+
+ .dark: {
+ --chart-1: oklch(0.488 0.243 264.376);
+ --chart-2: oklch(0.696 0.17 162.48);
+ }
+}
+```
+
+Add the color to your `chartConfig`
+
+```tsx {4,8} showLineNumbers
+const chartConfig = {
+ desktop: {
+ label: "Desktop",
+ color: "var(--chart-1)",
+ },
+ mobile: {
+ label: "Mobile",
+ color: "var(--chart-2)",
+ },
+} satisfies ChartConfig
+```
+
+
+
+### hex, hsl or oklch
+
+You can also define your colors directly in the chart config. Use the color format you prefer.
+
+```tsx showLineNumbers
+const chartConfig = {
+ desktop: {
+ label: "Desktop",
+ color: "#2563eb",
+ },
+} satisfies ChartConfig
+```
+
+### Using Colors
+
+To use the theme colors in your chart, reference the colors using the format `var(--color-KEY)`.
+
+#### Components
+
+```tsx
+
+```
+
+#### Chart Data
+
+```tsx showLineNumbers
+const chartData = [
+ { browser: "chrome", visitors: 275, fill: "var(--color-chrome)" },
+ { browser: "safari", visitors: 200, fill: "var(--color-safari)" },
+]
+```
+
+#### Tailwind
+
+```tsx
+
+```
+
+## Tooltip
+
+A chart tooltip contains a label, name, indicator and value. You can use a combination of these to customize your tooltip.
+
+
+
+You can turn on/off any of these using the `hideLabel`, `hideIndicator` props and customize the indicator style using the `indicator` prop.
+
+Use `labelKey` and `nameKey` to use a custom key for the tooltip label and name.
+
+Chart comes with the `` and `` components. You can use these two components to add custom tooltips to your chart.
+
+```tsx
+import { ChartTooltip, ChartTooltipContent } from "@/components/ui/chart"
+```
+
+```tsx
+ } />
+```
+
+### Props
+
+Use the following props to customize the tooltip.
+
+| Prop | Type | Description |
+| :-------------- | :----------------------- | :------------------------------------------- |
+| `labelKey` | string | The config or data key to use for the label. |
+| `nameKey` | string | The config or data key to use for the name. |
+| `indicator` | `dot` `line` or `dashed` | The indicator style for the tooltip. |
+| `hideLabel` | boolean | Whether to hide the label. |
+| `hideIndicator` | boolean | Whether to hide the indicator. |
+
+### Colors
+
+Colors are automatically referenced from the chart config.
+
+### Custom
+
+To use a custom key for tooltip label and names, use the `labelKey` and `nameKey` props.
+
+```tsx showLineNumbers /browser/
+const chartData = [
+ { browser: "chrome", visitors: 187, fill: "var(--color-chrome)" },
+ { browser: "safari", visitors: 200, fill: "var(--color-safari)" },
+]
+
+const chartConfig = {
+ visitors: {
+ label: "Total Visitors",
+ },
+ chrome: {
+ label: "Chrome",
+ color: "hsl(var(--chart-1))",
+ },
+ safari: {
+ label: "Safari",
+ color: "hsl(var(--chart-2))",
+ },
+} satisfies ChartConfig
+```
+
+```tsx
+ }
+/>
+```
+
+This will use `Total Visitors` for label and `Chrome` and `Safari` for the tooltip names.
+
+## Legend
+
+You can use the custom `` and `` components to add a legend to your chart.
+
+```tsx
+import { ChartLegend, ChartLegendContent } from "@/components/ui/chart"
+```
+
+```tsx
+ } />
+```
+
+### Colors
+
+Colors are automatically referenced from the chart config.
+
+### Custom
+
+To use a custom key for legend names, use the `nameKey` prop.
+
+```tsx showLineNumbers /browser/
+const chartData = [
+ { browser: "chrome", visitors: 187, fill: "var(--color-chrome)" },
+ { browser: "safari", visitors: 200, fill: "var(--color-safari)" },
+]
+
+const chartConfig = {
+ chrome: {
+ label: "Chrome",
+ color: "hsl(var(--chart-1))",
+ },
+ safari: {
+ label: "Safari",
+ color: "hsl(var(--chart-2))",
+ },
+} satisfies ChartConfig
+```
+
+```tsx
+ } />
+```
+
+This will use `Chrome` and `Safari` for the legend names.
+
+## Accessibility
+
+You can turn on the `accessibilityLayer` prop to add an accessible layer to your chart.
+
+This prop adds keyboard access and screen reader support to your charts.
+
+```tsx
+
+```
diff --git a/apps/v4/content/docs/components/radix/checkbox.mdx b/apps/v4/content/docs/components/radix/checkbox.mdx
new file mode 100644
index 0000000000..86fcbf7541
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/checkbox.mdx
@@ -0,0 +1,67 @@
+---
+title: Checkbox
+description: A control that allows the user to toggle between checked and not checked.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/checkbox
+ api: https://www.radix-ui.com/docs/primitives/components/checkbox#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add checkbox
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-checkbox
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx
+import { Checkbox } from "@/components/ui/checkbox"
+```
+
+```tsx
+
+```
diff --git a/apps/v4/content/docs/components/radix/collapsible.mdx b/apps/v4/content/docs/components/radix/collapsible.mdx
new file mode 100644
index 0000000000..3aa45b5e6d
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/collapsible.mdx
@@ -0,0 +1,78 @@
+---
+title: Collapsible
+description: An interactive component which expands/collapses a panel.
+base: radix
+component: true
+featured: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/collapsible
+ api: https://www.radix-ui.com/docs/primitives/components/collapsible#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add collapsible
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-collapsible
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ Collapsible,
+ CollapsibleContent,
+ CollapsibleTrigger,
+} from "@/components/ui/collapsible"
+```
+
+```tsx showLineNumbers
+
+ Can I use this in my project?
+
+ Yes. Free to use for personal and commercial projects. No attribution
+ required.
+
+
+```
diff --git a/apps/v4/content/docs/components/radix/combobox.mdx b/apps/v4/content/docs/components/radix/combobox.mdx
new file mode 100644
index 0000000000..828ad21de2
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/combobox.mdx
@@ -0,0 +1,149 @@
+---
+title: Combobox
+description: Autocomplete input and command palette with a list of suggestions.
+base: radix
+component: true
+---
+
+
+
+## Installation
+
+The Combobox is built using a composition of the ` ` and the ` ` components.
+
+See installation instructions for the [Popover](/docs/components/popover#installation) and the [Command](/docs/components/command#installation) components.
+
+## Usage
+
+
+
+```tsx showLineNumbers title="components/example-combobox.tsx"
+"use client"
+
+import * as React from "react"
+import { CheckIcon, ChevronsUpDownIcon } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+import { Button } from "@/components/ui/button"
+import {
+ Command,
+ CommandEmpty,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+ CommandList,
+} from "@/components/ui/command"
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/components/ui/popover"
+
+const frameworks = [
+ {
+ value: "next.js",
+ label: "Next.js",
+ },
+ {
+ value: "sveltekit",
+ label: "SvelteKit",
+ },
+ {
+ value: "nuxt.js",
+ label: "Nuxt.js",
+ },
+ {
+ value: "remix",
+ label: "Remix",
+ },
+ {
+ value: "astro",
+ label: "Astro",
+ },
+]
+
+export function ExampleCombobox() {
+ const [open, setOpen] = React.useState(false)
+ const [value, setValue] = React.useState("")
+
+ return (
+
+
+
+ {value
+ ? frameworks.find((framework) => framework.value === value)?.label
+ : "Select framework..."}
+
+
+
+
+
+
+
+ No framework found.
+
+ {frameworks.map((framework) => (
+ {
+ setValue(currentValue === value ? "" : currentValue)
+ setOpen(false)
+ }}
+ >
+
+ {framework.label}
+
+ ))}
+
+
+
+
+
+ )
+}
+```
+
+
+
+## Examples
+
+### Combobox
+
+
+
+### Popover
+
+
+
+### Dropdown menu
+
+
+
+### Responsive
+
+You can create a responsive combobox by using the ` ` on desktop and the ` ` components on mobile.
+
+
diff --git a/apps/v4/content/docs/components/radix/command.mdx b/apps/v4/content/docs/components/radix/command.mdx
new file mode 100644
index 0000000000..88278f9987
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/command.mdx
@@ -0,0 +1,145 @@
+---
+title: Command
+description: Fast, composable, unstyled command menu for React.
+base: radix
+component: true
+links:
+ doc: https://cmdk.paco.me
+---
+
+
+
+## About
+
+The ` ` component uses the [`cmdk`](https://cmdk.paco.me) component by [pacocoursey](https://twitter.com/pacocoursey).
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add command
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install cmdk
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ Command,
+ CommandDialog,
+ CommandEmpty,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+ CommandList,
+ CommandSeparator,
+ CommandShortcut,
+} from "@/components/ui/command"
+```
+
+```tsx showLineNumbers
+
+
+
+ No results found.
+
+ Calendar
+ Search Emoji
+ Calculator
+
+
+
+ Profile
+ Billing
+ Settings
+
+
+
+```
+
+## Examples
+
+### Dialog
+
+
+
+To show the command menu in a dialog, use the ` ` component.
+
+```tsx showLineNumbers title="components/example-command-menu.tsx"
+export function CommandMenu() {
+ const [open, setOpen] = React.useState(false)
+
+ React.useEffect(() => {
+ const down = (e: KeyboardEvent) => {
+ if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
+ e.preventDefault()
+ setOpen((open) => !open)
+ }
+ }
+ document.addEventListener("keydown", down)
+ return () => document.removeEventListener("keydown", down)
+ }, [])
+
+ return (
+
+
+
+ No results found.
+
+ Calendar
+ Search Emoji
+ Calculator
+
+
+
+ )
+}
+```
+
+### Combobox
+
+You can use the ` ` component as a combobox. See the [Combobox](/docs/components/combobox) page for more information.
diff --git a/apps/v4/content/docs/components/radix/context-menu.mdx b/apps/v4/content/docs/components/radix/context-menu.mdx
new file mode 100644
index 0000000000..1fd2b478cb
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/context-menu.mdx
@@ -0,0 +1,80 @@
+---
+title: Context Menu
+description: Displays a menu to the user — such as a set of actions or functions — triggered by a button.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/context-menu
+ api: https://www.radix-ui.com/docs/primitives/components/context-menu#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add context-menu
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-context-menu
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ ContextMenu,
+ ContextMenuContent,
+ ContextMenuItem,
+ ContextMenuTrigger,
+} from "@/components/ui/context-menu"
+```
+
+```tsx showLineNumbers
+
+ Right click
+
+ Profile
+ Billing
+ Team
+ Subscription
+
+
+```
diff --git a/apps/v4/content/docs/components/radix/data-table.mdx b/apps/v4/content/docs/components/radix/data-table.mdx
new file mode 100644
index 0000000000..2d5a5698bd
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/data-table.mdx
@@ -0,0 +1,884 @@
+---
+title: Data Table
+description: Powerful table and datagrids built using TanStack Table.
+base: radix
+component: true
+links:
+ doc: https://tanstack.com/table/v8/docs/introduction
+---
+
+
+
+## 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/v8/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) 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@latest add table
+```
+
+2. Add `tanstack/react-table` dependency:
+
+```bash
+npm install @tanstack/react-table
+```
+
+## Prerequisites
+
+We are going to build a table to show recent payments. Here's what our data looks like:
+
+```tsx showLineNumbers
+type Payment = {
+ id: string
+ amount: number
+ status: "pending" | "processing" | "success" | "failed"
+ email: string
+}
+
+export const payments: Payment[] = [
+ {
+ id: "728ed52f",
+ amount: 100,
+ status: "pending",
+ email: "m@example.com",
+ },
+ {
+ id: "489e1d42",
+ amount: 125,
+ status: "processing",
+ email: "example@gmail.com",
+ },
+ // ...
+]
+```
+
+## Project Structure
+
+Start by creating the following file structure:
+
+```txt
+app
+└── payments
+ ├── columns.tsx
+ ├── data-table.tsx
+ └── page.tsx
+```
+
+I'm using a Next.js example here but this works for any other React framework.
+
+- `columns.tsx` (client component) will contain our column definitions.
+- `data-table.tsx` (client component) will contain our ` ` component.
+- `page.tsx` (server component) 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.
+
+```tsx showLineNumbers title="app/payments/columns.tsx" {3,14-27}
+"use client"
+
+import { ColumnDef } from "@tanstack/react-table"
+
+// This type is used to define the shape of our data.
+// You can use a Zod schema here if you want.
+export type Payment = {
+ id: string
+ amount: number
+ status: "pending" | "processing" | "success" | "failed"
+ email: string
+}
+
+export const columns: ColumnDef[] = [
+ {
+ accessorKey: "status",
+ header: "Status",
+ },
+ {
+ accessorKey: "email",
+ header: "Email",
+ },
+ {
+ accessorKey: "amount",
+ header: "Amount",
+ },
+]
+```
+
+
+
+**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.
+
+```tsx showLineNumbers title="app/payments/data-table.tsx"
+"use client"
+
+import {
+ ColumnDef,
+ flexRender,
+ getCoreRowModel,
+ useReactTable,
+} from "@tanstack/react-table"
+
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/components/ui/table"
+
+interface DataTableProps {
+ columns: ColumnDef[]
+ data: TData[]
+}
+
+export function DataTable({
+ columns,
+ data,
+}: DataTableProps) {
+ const table = useReactTable({
+ data,
+ columns,
+ getCoreRowModel: getCoreRowModel(),
+ })
+
+ return (
+
+
+
+ {table.getHeaderGroups().map((headerGroup) => (
+
+ {headerGroup.headers.map((header) => {
+ return (
+
+ {header.isPlaceholder
+ ? null
+ : flexRender(
+ header.column.columnDef.header,
+ header.getContext()
+ )}
+
+ )
+ })}
+
+ ))}
+
+
+ {table.getRowModel().rows?.length ? (
+ table.getRowModel().rows.map((row) => (
+
+ {row.getVisibleCells().map((cell) => (
+
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
+
+ ))}
+
+ ))
+ ) : (
+
+
+ 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.tsx`.
+
+` `
+
+
+
+### Render the table
+
+Finally, we'll render our table in our page component.
+
+```tsx showLineNumbers title="app/payments/page.tsx" {22}
+import { columns, Payment } from "./columns"
+import { DataTable } from "./data-table"
+
+async function getData(): Promise {
+ // Fetch data from your API here.
+ return [
+ {
+ id: "728ed52f",
+ amount: 100,
+ status: "pending",
+ email: "m@example.com",
+ },
+ // ...
+ ]
+}
+
+export default async function DemoPage() {
+ const data = await getData()
+
+ return (
+
+
+
+ )
+}
+```
+
+
+
+## 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:
+
+```tsx showLineNumbers title="app/payments/columns.tsx" {4-15}
+export const columns: ColumnDef[] = [
+ {
+ accessorKey: "amount",
+ header: () => Amount
,
+ cell: ({ row }) => {
+ const amount = parseFloat(row.getValue("amount"))
+ const formatted = new Intl.NumberFormat("en-US", {
+ style: "currency",
+ currency: "USD",
+ }).format(amount)
+
+ return {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.
+
+
+
+### Update columns definition
+
+Update our columns definition to add a new `actions` column. The `actions` cell returns a ` ` component.
+
+```tsx showLineNumbers title="app/payments/columns.tsx" {4,6-14,18-45}
+"use client"
+
+import { ColumnDef } from "@tanstack/react-table"
+import { MoreHorizontal } from "lucide-react"
+
+import { Button } from "@/components/ui/button"
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu"
+
+export const columns: ColumnDef[] = [
+ // ...
+ {
+ id: "actions",
+ cell: ({ row }) => {
+ const payment = row.original
+
+ return (
+
+
+
+ Open menu
+
+
+
+
+ Actions
+ navigator.clipboard.writeText(payment.id)}
+ >
+ Copy payment ID
+
+
+ View customer
+ View payment details
+
+
+ )
+ },
+ },
+ // ...
+]
+```
+
+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 ``
+
+```tsx showLineNumbers title="app/payments/data-table.tsx" {5,17}
+import {
+ ColumnDef,
+ flexRender,
+ getCoreRowModel,
+ getPaginationRowModel,
+ useReactTable,
+} from "@tanstack/react-table"
+
+export function DataTable({
+ columns,
+ data,
+}: DataTableProps) {
+ const table = useReactTable({
+ data,
+ 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.
+
+```tsx showLineNumbers title="app/payments/data-table.tsx" {1,15,21-39}
+import { Button } from "@/components/ui/button"
+
+export function DataTable({
+ columns,
+ data,
+}: DataTableProps) {
+ const table = useReactTable({
+ data,
+ columns,
+ getCoreRowModel: getCoreRowModel(),
+ getPaginationRowModel: getPaginationRowModel(),
+ })
+
+ return (
+
+
+
+ table.previousPage()}
+ disabled={!table.getCanPreviousPage()}
+ >
+ Previous
+
+ table.nextPage()}
+ disabled={!table.getCanNextPage()}
+ >
+ Next
+
+
+
+ )
+}
+```
+
+See [Reusable Components](#reusable-components) section for a more advanced pagination component.
+
+
+
+## Sorting
+
+Let's make the email column sortable.
+
+
+
+### Update ``
+
+```tsx showLineNumbers title="app/payments/data-table.tsx" showLineNumbers {3,6,10,18,25-28}
+"use client"
+
+import * as React from "react"
+import {
+ ColumnDef,
+ SortingState,
+ flexRender,
+ getCoreRowModel,
+ getPaginationRowModel,
+ getSortedRowModel,
+ useReactTable,
+} from "@tanstack/react-table"
+
+export function DataTable({
+ columns,
+ data,
+}: DataTableProps) {
+ const [sorting, setSorting] = React.useState([])
+
+ const table = useReactTable({
+ data,
+ columns,
+ getCoreRowModel: getCoreRowModel(),
+ getPaginationRowModel: getPaginationRowModel(),
+ onSortingChange: setSorting,
+ getSortedRowModel: getSortedRowModel(),
+ state: {
+ sorting,
+ },
+ })
+
+ return (
+
+ )
+}
+```
+
+### Make header cell sortable
+
+We can now update the `email` header cell to add sorting controls.
+
+```tsx showLineNumbers title="app/payments/columns.tsx" {4,9-19}
+"use client"
+
+import { ColumnDef } from "@tanstack/react-table"
+import { ArrowUpDown } from "lucide-react"
+
+export const columns: ColumnDef[] = [
+ {
+ accessorKey: "email",
+ header: ({ column }) => {
+ return (
+ column.toggleSorting(column.getIsSorted() === "asc")}
+ >
+ 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 ``
+
+```tsx showLineNumbers title="app/payments/data-table.tsx" {6,10,17,24-26,35-36,39,45-54}
+"use client"
+
+import * as React from "react"
+import {
+ ColumnDef,
+ ColumnFiltersState,
+ SortingState,
+ flexRender,
+ getCoreRowModel,
+ getFilteredRowModel,
+ getPaginationRowModel,
+ getSortedRowModel,
+ useReactTable,
+} from "@tanstack/react-table"
+
+import { Button } from "@/components/ui/button"
+import { Input } from "@/components/ui/input"
+
+export function DataTable({
+ columns,
+ data,
+}: DataTableProps) {
+ const [sorting, setSorting] = React.useState([])
+ const [columnFilters, setColumnFilters] = React.useState(
+ []
+ )
+
+ const table = useReactTable({
+ data,
+ columns,
+ onSortingChange: setSorting,
+ getCoreRowModel: getCoreRowModel(),
+ getPaginationRowModel: getPaginationRowModel(),
+ getSortedRowModel: getSortedRowModel(),
+ onColumnFiltersChange: setColumnFilters,
+ getFilteredRowModel: getFilteredRowModel(),
+ state: {
+ sorting,
+ columnFilters,
+ },
+ })
+
+ return (
+
+
+
+ table.getColumn("email")?.setFilterValue(event.target.value)
+ }
+ className="max-w-sm"
+ />
+
+
+
+ )
+}
+```
+
+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/react-table` visibility API.
+
+
+
+### Update ``
+
+```tsx showLineNumbers title="app/payments/data-table.tsx" {8,18-23,33-34,45,49,64-91}
+"use client"
+
+import * as React from "react"
+import {
+ ColumnDef,
+ ColumnFiltersState,
+ SortingState,
+ VisibilityState,
+ flexRender,
+ getCoreRowModel,
+ getFilteredRowModel,
+ getPaginationRowModel,
+ getSortedRowModel,
+ useReactTable,
+} from "@tanstack/react-table"
+
+import { Button } from "@/components/ui/button"
+import {
+ DropdownMenu,
+ DropdownMenuCheckboxItem,
+ DropdownMenuContent,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu"
+
+export function DataTable({
+ columns,
+ data,
+}: DataTableProps) {
+ const [sorting, setSorting] = React.useState([])
+ const [columnFilters, setColumnFilters] = React.useState(
+ []
+ )
+ const [columnVisibility, setColumnVisibility] =
+ React.useState({})
+
+ const table = useReactTable({
+ data,
+ columns,
+ onSortingChange: setSorting,
+ onColumnFiltersChange: setColumnFilters,
+ getCoreRowModel: getCoreRowModel(),
+ getPaginationRowModel: getPaginationRowModel(),
+ getSortedRowModel: getSortedRowModel(),
+ getFilteredRowModel: getFilteredRowModel(),
+ onColumnVisibilityChange: setColumnVisibility,
+ state: {
+ sorting,
+ columnFilters,
+ columnVisibility,
+ },
+ })
+
+ return (
+
+
+
+ table.getColumn("email")?.setFilterValue(event.target.value)
+ }
+ className="max-w-sm"
+ />
+
+
+
+ Columns
+
+
+
+ {table
+ .getAllColumns()
+ .filter(
+ (column) => column.getCanHide()
+ )
+ .map((column) => {
+ return (
+
+ column.toggleVisibility(!!value)
+ }
+ >
+ {column.id}
+
+ )
+ })}
+
+
+
+
+
+ )
+}
+```
+
+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
+
+```tsx showLineNumbers title="app/payments/columns.tsx" {6,9-27}
+"use client"
+
+import { ColumnDef } from "@tanstack/react-table"
+
+import { Badge } from "@/components/ui/badge"
+import { Checkbox } from "@/components/ui/checkbox"
+
+export const columns: ColumnDef[] = [
+ {
+ id: "select",
+ header: ({ table }) => (
+ table.toggleAllPageRowsSelected(!!value)}
+ aria-label="Select all"
+ />
+ ),
+ cell: ({ row }) => (
+ row.toggleSelected(!!value)}
+ aria-label="Select row"
+ />
+ ),
+ enableSorting: false,
+ enableHiding: false,
+ },
+]
+```
+
+### Update ``
+
+```tsx showLineNumbers title="app/payments/data-table.tsx" {11,23,28}
+export function DataTable({
+ columns,
+ data,
+}: DataTableProps) {
+ const [sorting, setSorting] = React.useState([])
+ const [columnFilters, setColumnFilters] = React.useState(
+ []
+ )
+ const [columnVisibility, setColumnVisibility] =
+ React.useState({})
+ const [rowSelection, setRowSelection] = React.useState({})
+
+ const table = useReactTable({
+ data,
+ columns,
+ onSortingChange: setSorting,
+ onColumnFiltersChange: setColumnFilters,
+ getCoreRowModel: getCoreRowModel(),
+ getPaginationRowModel: getPaginationRowModel(),
+ getSortedRowModel: getSortedRowModel(),
+ getFilteredRowModel: getFilteredRowModel(),
+ onColumnVisibilityChange: setColumnVisibility,
+ onRowSelectionChange: setRowSelection,
+ state: {
+ sorting,
+ columnFilters,
+ columnVisibility,
+ rowSelection,
+ },
+ })
+
+ return (
+
+ )
+}
+```
+
+This adds a checkbox to each row and a checkbox in the header to select all rows.
+
+### Show selected rows
+
+You can show the number of selected rows using the `table.getFilteredSelectedRowModel()` API.
+
+```tsx
+
+ {table.getFilteredSelectedRowModel().rows.length} of{" "}
+ {table.getFilteredRowModel().rows.length} row(s) selected.
+
+```
+
+
+
+## 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.
+
+
+
+```tsx showLineNumbers {5}
+export const columns = [
+ {
+ accessorKey: "email",
+ header: ({ column }) => (
+
+ ),
+ },
+]
+```
+
+### Pagination
+
+Add pagination controls to your table including page size and selection count.
+
+
+
+```tsx
+
+```
+
+### Column toggle
+
+A component to toggle column visibility.
+
+
+
+```tsx
+
+```
diff --git a/apps/v4/content/docs/components/radix/date-picker.mdx b/apps/v4/content/docs/components/radix/date-picker.mdx
new file mode 100644
index 0000000000..be5e2b4877
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/date-picker.mdx
@@ -0,0 +1,102 @@
+---
+title: Date Picker
+description: A date picker component with range and presets.
+base: radix
+component: true
+---
+
+
+
+## Installation
+
+The Date Picker is built using a composition of the ` ` and the ` ` components.
+
+See installation instructions for the [Popover](/docs/components/popover#installation) and the [Calendar](/docs/components/calendar#installation) components.
+
+## Usage
+
+```tsx showLineNumbers title="components/example-date-picker.tsx"
+"use client"
+
+import * as React from "react"
+import { format } from "date-fns"
+import { Calendar as CalendarIcon } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+import { Button } from "@/components/ui/button"
+import { Calendar } from "@/components/ui/calendar"
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/components/ui/popover"
+
+export function DatePickerDemo() {
+ const [date, setDate] = React.useState()
+
+ return (
+
+
+
+
+ {date ? format(date, "PPP") : Pick a date }
+
+
+
+
+
+
+ )
+}
+```
+
+See the [React DayPicker](https://react-day-picker.js.org) documentation for more information.
+
+## Examples
+
+### Date of Birth Picker
+
+
+
+### Picker with Input
+
+
+
+### Date and Time Picker
+
+
+
+### Natural Language Picker
+
+This component uses the `chrono-node` library to parse natural language dates.
+
+
diff --git a/apps/v4/content/docs/components/radix/dialog.mdx b/apps/v4/content/docs/components/radix/dialog.mdx
new file mode 100644
index 0000000000..118297eaf8
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/dialog.mdx
@@ -0,0 +1,126 @@
+---
+title: Dialog
+description: A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.
+featured: true
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/dialog
+ api: https://www.radix-ui.com/docs/primitives/components/dialog#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add dialog
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-dialog
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogHeader,
+ DialogTitle,
+ DialogTrigger,
+} from "@/components/ui/dialog"
+```
+
+```tsx showLineNumbers
+
+ Open
+
+
+ Are you absolutely sure?
+
+ This action cannot be undone. This will permanently delete your account
+ and remove your data from our servers.
+
+
+
+
+```
+
+## Examples
+
+### Custom close button
+
+
+
+## Notes
+
+To use 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.
+
+```tsx showLineNumbers title="components/example-dialog-context-menu.tsx" {1, 26}
+
+
+ Right click
+
+ Open
+ Download
+
+
+ Delete
+
+
+
+
+
+
+ Are you absolutely sure?
+
+ This action cannot be undone. Are you sure you want to permanently
+ delete this file from our servers?
+
+
+
+ Confirm
+
+
+
+```
diff --git a/apps/v4/content/docs/components/radix/drawer.mdx b/apps/v4/content/docs/components/radix/drawer.mdx
new file mode 100644
index 0000000000..72f61872d3
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/drawer.mdx
@@ -0,0 +1,101 @@
+---
+title: Drawer
+description: A drawer component for React.
+base: radix
+component: true
+links:
+ doc: https://vaul.emilkowal.ski/getting-started
+---
+
+
+
+## About
+
+Drawer is built on top of [Vaul](https://github.com/emilkowalski/vaul) by [emilkowalski](https://twitter.com/emilkowalski).
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add drawer
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install vaul
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ Drawer,
+ DrawerClose,
+ DrawerContent,
+ DrawerDescription,
+ DrawerFooter,
+ DrawerHeader,
+ DrawerTitle,
+ DrawerTrigger,
+} from "@/components/ui/drawer"
+```
+
+```tsx showLineNumbers
+
+ Open
+
+
+ Are you absolutely sure?
+ This action cannot be undone.
+
+
+ Submit
+
+ Cancel
+
+
+
+
+```
+
+## 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.
+
+
diff --git a/apps/v4/content/docs/components/radix/dropdown-menu.mdx b/apps/v4/content/docs/components/radix/dropdown-menu.mdx
new file mode 100644
index 0000000000..dfc656ee8b
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/dropdown-menu.mdx
@@ -0,0 +1,119 @@
+---
+title: Dropdown Menu
+description: Displays a menu to the user — such as a set of actions or functions — triggered by a button.
+featured: true
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/dropdown-menu
+ api: https://www.radix-ui.com/docs/primitives/components/dropdown-menu#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add dropdown-menu
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-dropdown-menu
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu"
+```
+
+```tsx showLineNumbers
+
+ Open
+
+ My Account
+
+ Profile
+ Billing
+ Team
+ Subscription
+
+
+```
+
+## Examples
+
+### Checkboxes
+
+
+
+### Radio Group
+
+
+
+### Dialog
+
+This example shows how to open a dialog from a dropdown menu.
+
+Use `modal={false}` on the `DropdownMenu` component.
+
+```tsx showLineNumbers
+
+
+ Actions
+
+
+```
+
+
diff --git a/apps/v4/content/docs/components/radix/empty.mdx b/apps/v4/content/docs/components/radix/empty.mdx
new file mode 100644
index 0000000000..4807196495
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/empty.mdx
@@ -0,0 +1,223 @@
+---
+title: Empty
+description: Use the Empty component to display an empty state.
+base: radix
+component: true
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add empty
+```
+
+
+
+
+
+
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx
+import {
+ Empty,
+ EmptyContent,
+ EmptyDescription,
+ EmptyHeader,
+ EmptyMedia,
+ EmptyTitle,
+} from "@/components/ui/empty"
+```
+
+```tsx
+
+
+
+
+
+ No data
+ No data found
+
+
+ Add data
+
+
+```
+
+## Examples
+
+### Outline
+
+Use the `border` utility class to create an outline empty state.
+
+
+
+### Background
+
+Use the `bg-*` and `bg-gradient-*` utilities to add a background to the empty state.
+
+
+
+### Avatar
+
+Use the `EmptyMedia` component to display an avatar in the empty state.
+
+
+
+### Avatar Group
+
+Use the `EmptyMedia` component to display an avatar group in the empty state.
+
+
+
+### InputGroup
+
+You can add an `InputGroup` component to the `EmptyContent` component.
+
+
+
+## API Reference
+
+### Empty
+
+The main component of the empty state. Wraps the `EmptyHeader` and `EmptyContent` components.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+
+
+
+
+```
+
+### EmptyHeader
+
+The `EmptyHeader` component wraps the empty media, title, and description.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+
+
+
+
+
+```
+
+### EmptyMedia
+
+Use the `EmptyMedia` component to display the media of the empty state such as an icon or an image. You can also use it to display other components such as an avatar.
+
+| Prop | Type | Default |
+| ----------- | --------------------- | --------- |
+| `variant` | `"default" \| "icon"` | `default` |
+| `className` | `string` | |
+
+```tsx
+
+
+
+```
+
+```tsx
+
+
+
+ CN
+
+
+```
+
+### EmptyTitle
+
+Use the `EmptyTitle` component to display the title of the empty state.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+No data
+```
+
+### EmptyDescription
+
+Use the `EmptyDescription` component to display the description of the empty state.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+You do not have any notifications.
+```
+
+### EmptyContent
+
+Use the `EmptyContent` component to display the content of the empty state such as a button, input or a link.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+
+ Add Project
+
+```
diff --git a/apps/v4/content/docs/components/radix/field.mdx b/apps/v4/content/docs/components/radix/field.mdx
new file mode 100644
index 0000000000..d3de9f2a88
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/field.mdx
@@ -0,0 +1,378 @@
+---
+title: Field
+description: Combine labels, controls, and help text to compose accessible form fields and grouped inputs.
+base: radix
+component: true
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add field
+```
+
+
+
+
+
+
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ Field,
+ FieldContent,
+ FieldDescription,
+ FieldError,
+ FieldGroup,
+ FieldLabel,
+ FieldLegend,
+ FieldSeparator,
+ FieldSet,
+ FieldTitle,
+} from "@/components/ui/field"
+```
+
+```tsx showLineNumbers
+
+ Profile
+ This appears on invoices and emails.
+
+
+ Full name
+
+ This appears on invoices and emails.
+
+
+ Username
+
+ Choose another username.
+
+
+
+ Subscribe to the newsletter
+
+
+
+```
+
+## Anatomy
+
+The `Field` family is designed for composing accessible forms. A typical field is structured as follows:
+
+```tsx showLineNumbers
+
+ Label
+ {/* Input, Select, Switch, etc. */}
+ Optional helper text.
+ Validation message.
+
+```
+
+- `Field` is the core wrapper for a single field.
+- `FieldContent` is a flex column that groups label and description. Not required if you have no description.
+- Wrap related fields with `FieldGroup`, and use `FieldSet` with `FieldLegend` for semantic grouping.
+
+## Form
+
+See the [Form](/docs/forms) documentation for building forms with the `Field` component and [React Hook Form](/docs/forms/react-hook-form) or [Tanstack Form](/docs/forms/tanstack-form).
+
+## Examples
+
+### Input
+
+
+
+### Textarea
+
+
+
+### Select
+
+
+
+### Slider
+
+
+
+### Fieldset
+
+
+
+### Checkbox
+
+
+
+### Radio
+
+
+
+### Switch
+
+
+
+### Choice Card
+
+Wrap `Field` components inside `FieldLabel` to create selectable field groups. This works with `RadioItem`, `Checkbox` and `Switch` components.
+
+
+
+### Field Group
+
+Stack `Field` components with `FieldGroup`. Add `FieldSeparator` to divide them.
+
+
+
+## Responsive Layout
+
+- **Vertical fields:** Default orientation stacks label, control, and helper text—ideal for mobile-first layouts.
+- **Horizontal fields:** Set `orientation="horizontal"` on `Field` to align the label and control side-by-side. Pair with `FieldContent` to keep descriptions aligned.
+- **Responsive fields:** Set `orientation="responsive"` for automatic column layouts inside container-aware parents. Apply `@container/field-group` classes on `FieldGroup` to switch orientations at specific breakpoints.
+
+
+
+## Validation and Errors
+
+- Add `data-invalid` to `Field` to switch the entire block into an error state.
+- Add `aria-invalid` on the input itself for assistive technologies.
+- Render `FieldError` immediately after the control or inside `FieldContent` to keep error messages aligned with the field.
+
+```tsx showLineNumbers /data-invalid/ /aria-invalid/
+
+ Email
+
+ Enter a valid email address.
+
+```
+
+## Accessibility
+
+- `FieldSet` and `FieldLegend` keep related controls grouped for keyboard and assistive tech users.
+- `Field` outputs `role="group"` so nested controls inherit labeling from `FieldLabel` and `FieldLegend` when combined.
+- Apply `FieldSeparator` sparingly to ensure screen readers encounter clear section boundaries.
+
+## API Reference
+
+### FieldSet
+
+Container that renders a semantic `fieldset` with spacing presets.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+
+ Delivery
+ {/* Fields */}
+
+```
+
+### FieldLegend
+
+Legend element for a `FieldSet`. Switch to the `label` variant to align with label sizing.
+
+| Prop | Type | Default |
+| ----------- | --------------------- | ---------- |
+| `variant` | `"legend" \| "label"` | `"legend"` |
+| `className` | `string` | |
+
+```tsx
+Notification Preferences
+```
+
+The `FieldLegend` has two variants: `legend` and `label`. The `label` variant applies label sizing and alignment. Handy if you have nested `FieldSet`.
+
+### FieldGroup
+
+Layout wrapper that stacks `Field` components and enables container queries for responsive orientations.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+
+ {/* ... */}
+ {/* ... */}
+
+```
+
+### Field
+
+The core wrapper for a single field. Provides orientation control, invalid state styling, and spacing.
+
+| Prop | Type | Default |
+| -------------- | -------------------------------------------- | ------------ |
+| `orientation` | `"vertical" \| "horizontal" \| "responsive"` | `"vertical"` |
+| `className` | `string` | |
+| `data-invalid` | `boolean` | |
+
+```tsx
+
+ Remember me
+
+
+```
+
+### FieldContent
+
+Flex column that groups control and descriptions when the label sits beside the control. Not required if you have no description.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+
+
+
+ Notifications
+ Email, SMS, and push options.
+
+
+```
+
+### FieldLabel
+
+Label styled for both direct inputs and nested `Field` children.
+
+| Prop | Type | Default |
+| ----------- | --------- | ------- |
+| `className` | `string` | |
+| `asChild` | `boolean` | `false` |
+
+```tsx
+Email
+```
+
+### FieldTitle
+
+Renders a title with label styling inside `FieldContent`.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+
+ Enable Touch ID
+ Unlock your device faster.
+
+```
+
+### FieldDescription
+
+Helper text slot that automatically balances long lines in horizontal layouts.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+We never share your email with anyone.
+```
+
+### FieldSeparator
+
+Visual divider to separate sections inside a `FieldGroup`. Accepts optional inline content.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+Or continue with
+```
+
+### FieldError
+
+Accessible error container that accepts children or an `errors` array (e.g., from `react-hook-form`).
+
+| Prop | Type | Default |
+| ----------- | ------------------------------------------ | ------- |
+| `errors` | `Array<{ message?: string } \| undefined>` | |
+| `className` | `string` | |
+
+```tsx
+
+```
+
+When the `errors` array contains multiple messages, the component renders a list automatically.
+
+`FieldError` also accepts issues produced by any validator that implements [Standard Schema](https://standardschema.dev/), including Zod, Valibot, and ArkType. Pass the `issues` array from the schema result directly to render a unified error list across libraries.
diff --git a/apps/v4/content/docs/components/radix/form.mdx b/apps/v4/content/docs/components/radix/form.mdx
new file mode 100644
index 0000000000..9209a2803e
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/form.mdx
@@ -0,0 +1,245 @@
+---
+title: Form
+description: Building forms with React Hook Form and Zod.
+links:
+ doc: https://react-hook-form.com
+---
+
+import { InfoIcon } from "lucide-react"
+
+ } title="We are not actively developing this component anymore.">
+
+The Form component is an abstraction over the `react-hook-form` library. Going forward, we recommend using the [` `](/docs/components/field) component to build forms. See the [Form](/docs/forms) documentation for more information.
+
+
+
+Forms are tricky. They are one of the most common things you'll build in a web application, but also one of the most complex.
+
+Well-designed HTML forms are:
+
+- Well-structured and semantically correct.
+- Easy to use and navigate (keyboard).
+- Accessible with ARIA attributes and proper labels.
+- Has support for client and server side validation.
+- Well-styled and consistent with the rest of the application.
+
+In this guide, we will take a look at building forms with [`react-hook-form`](https://react-hook-form.com/) and [`zod`](https://zod.dev). We're going to use a `` component to compose accessible forms using Radix UI components.
+
+## Features
+
+The `` component is a wrapper around the `react-hook-form` library. It provides a few things:
+
+- Composable components for building forms.
+- A ` ` component for building controlled form fields.
+- Form validation using `zod`.
+- Handles accessibility and error messages.
+- Uses `React.useId()` for generating unique IDs.
+- Applies the correct `aria` attributes to form fields based on states.
+- Built to work with all Radix UI components.
+- Bring your own schema library. We use `zod` but you can use anything you want.
+- **You have full control over the markup and styling.**
+
+## Anatomy
+
+```tsx showLineNumbers
+
+```
+
+## Example
+
+```tsx showLineNumbers
+const form = useForm()
+
+ (
+
+ Username
+
+
+
+ This is your public display name.
+
+
+ )}
+/>
+```
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+
+
+### Command
+
+```bash
+npx shadcn@latest add form
+```
+
+
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-label @radix-ui/react-slot react-hook-form @hookform/resolvers zod
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+### Create a form schema
+
+Define the shape of your form using a Zod schema. You can read more about using Zod in the [Zod documentation](https://zod.dev).
+
+```tsx showLineNumbers title="components/example-form.tsx" {3,5-7}
+"use client"
+
+import { z } from "zod"
+
+const formSchema = z.object({
+ username: z.string().min(2).max(50),
+})
+```
+
+### Define a form
+
+Use the `useForm` hook from `react-hook-form` to create a form.
+
+```tsx showLineNumbers title="components/example-form.tsx" {3-4,14-20,22-27}
+"use client"
+
+import { zodResolver } from "@hookform/resolvers/zod"
+import { useForm } from "react-hook-form"
+import { z } from "zod"
+
+const formSchema = z.object({
+ username: z.string().min(2, {
+ message: "Username must be at least 2 characters.",
+ }),
+})
+
+export function ProfileForm() {
+ // 1. Define your form.
+ const form = useForm>({
+ resolver: zodResolver(formSchema),
+ defaultValues: {
+ username: "",
+ },
+ })
+
+ // 2. Define a submit handler.
+ function onSubmit(values: z.infer) {
+ // Do something with the form values.
+ // ✅ This will be type-safe and validated.
+ console.log(values)
+ }
+}
+```
+
+Since `FormField` is using a controlled component, you need to provide a default value for the field. See the [React Hook Form docs](https://react-hook-form.com/docs/usecontroller) to learn more about controlled components.
+
+### Build your form
+
+We can now use the `` components to build our form.
+
+```tsx showLineNumbers title="components/example-form.tsx" {7-17,28-50}
+"use client"
+
+import { zodResolver } from "@hookform/resolvers/zod"
+import { useForm } from "react-hook-form"
+import { z } from "zod"
+
+import { Button } from "@/components/ui/button"
+import {
+ Form,
+ FormControl,
+ FormDescription,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormMessage,
+} from "@/components/ui/form"
+import { Input } from "@/components/ui/input"
+
+const formSchema = z.object({
+ username: z.string().min(2, {
+ message: "Username must be at least 2 characters.",
+ }),
+})
+
+export function ProfileForm() {
+ // ...
+
+ return (
+
+
+ )
+}
+```
+
+### Done
+
+That's it. You now have a fully accessible form that is type-safe with client-side validation.
diff --git a/apps/v4/content/docs/components/radix/hover-card.mdx b/apps/v4/content/docs/components/radix/hover-card.mdx
new file mode 100644
index 0000000000..fb49de8e53
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/hover-card.mdx
@@ -0,0 +1,76 @@
+---
+title: Hover Card
+description: For sighted users to preview content available behind a link.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/hover-card
+ api: https://www.radix-ui.com/docs/primitives/components/hover-card#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add hover-card
+```
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-hover-card
+```
+
+
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ HoverCard,
+ HoverCardContent,
+ HoverCardTrigger,
+} from "@/components/ui/hover-card"
+```
+
+```tsx showLineNumbers
+
+ Hover
+
+ The React Framework – created and maintained by @vercel.
+
+
+```
diff --git a/apps/v4/content/docs/components/radix/input-group.mdx b/apps/v4/content/docs/components/radix/input-group.mdx
new file mode 100644
index 0000000000..91329d8df3
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/input-group.mdx
@@ -0,0 +1,304 @@
+---
+title: Input Group
+description: Display additional information or actions to an input or textarea.
+base: radix
+component: true
+---
+
+import { IconInfoCircle } from "@tabler/icons-react"
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add input-group
+```
+
+
+
+
+
+
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ InputGroup,
+ InputGroupAddon,
+ InputGroupButton,
+ InputGroupInput,
+ InputGroupText,
+ InputGroupTextarea,
+} from "@/components/ui/input-group"
+```
+
+```tsx showLineNumbers
+
+
+
+
+
+
+ Search
+
+
+```
+
+## Examples
+
+### Icon
+
+
+
+### Text
+
+Display additional text information alongside inputs.
+
+
+
+### Button
+
+Add buttons to perform actions within the input group.
+
+
+
+### Tooltip
+
+Add tooltips to provide additional context or help.
+
+
+
+### Textarea
+
+Input groups also work with textarea components. Use `block-start` or `block-end` for alignment.
+
+
+
+### Spinner
+
+Show loading indicators while processing input.
+
+
+
+### Label
+
+Add labels within input groups to improve accessibility.
+
+
+
+### Dropdown
+
+Pair input groups with dropdown menus for complex interactions.
+
+
+
+### Button Group
+
+Wrap input groups with button groups to create prefixes and suffixes.
+
+
+
+### Custom Input
+
+Add the `data-slot="input-group-control"` attribute to your custom input for automatic behavior and focus state handling.
+
+No style is applied to the custom input. Apply your own styles using the `className` prop.
+
+
+
+```tsx showLineNumbers
+import { InputGroup, InputGroupAddon } from "@/component/ui/input-group"
+import TextareaAutosize from "react-textarea-autosize"
+
+export function InputGroupCustom() {
+ return (
+
+
+ how
+
+ )
+}
+```
+
+## API Reference
+
+### InputGroup
+
+The main component that wraps inputs and addons.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+
+
+
+
+```
+
+### InputGroupAddon
+
+Displays icons, text, buttons, or other content alongside inputs.
+
+ } title="Focus Navigation">
+ For proper focus navigation, the `InputGroupAddon` component should be placed
+ after the input. Set the `align` prop to position the addon.
+
+
+| Prop | Type | Default |
+| ----------- | ---------------------------------------------------------------- | ---------------- |
+| `align` | `"inline-start" \| "inline-end" \| "block-start" \| "block-end"` | `"inline-start"` |
+| `className` | `string` | |
+
+```tsx
+
+
+
+```
+
+**For ` `, use the `inline-start` or `inline-end` alignment. For ` `, use the `block-start` or `block-end` alignment.**
+
+The `InputGroupAddon` component can have multiple `InputGroupButton` components and icons.
+
+```tsx
+
+ Button
+ Button
+
+```
+
+### InputGroupButton
+
+Displays buttons within input groups.
+
+| Prop | Type | Default |
+| ----------- | ----------------------------------------------------------------------------- | --------- |
+| `size` | `"xs" \| "icon-xs" \| "sm" \| "icon-sm"` | `"xs"` |
+| `variant` | `"default" \| "destructive" \| "outline" \| "secondary" \| "ghost" \| "link"` | `"ghost"` |
+| `className` | `string` | |
+
+```tsx
+Button
+
+
+
+```
+
+### InputGroupInput
+
+Replacement for ` ` when building input groups. This component has the input group styles pre-applied and uses the unified `data-slot="input-group-control"` for focus state handling.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+All other props are passed through to the underlying ` ` component.
+
+```tsx
+
+
+
+
+
+
+```
+
+### InputGroupTextarea
+
+Replacement for `` when building input groups. This component has the textarea group styles pre-applied and uses the unified `data-slot="input-group-control"` for focus state handling.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+All other props are passed through to the underlying `` component.
+
+```tsx
+
+
+
+ Send
+
+
+```
+
+## Changelog
+
+### 2025-10-06 `InputGroup`
+
+Add the `min-w-0` class to the `InputGroup` component. See [diff](https://github.com/shadcn-ui/ui/pull/8341/files#diff-0e2ee95d0050ca4c5d82339df86c54e14a6739dc4638fdda0eec8f73aebc2da9).
diff --git a/apps/v4/content/docs/components/radix/input-otp.mdx b/apps/v4/content/docs/components/radix/input-otp.mdx
new file mode 100644
index 0000000000..7b7fe9b299
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/input-otp.mdx
@@ -0,0 +1,241 @@
+---
+title: Input OTP
+description: Accessible one-time password component with copy paste functionality.
+base: radix
+component: true
+links:
+ doc: https://input-otp.rodz.dev
+---
+
+
+
+## About
+
+Input OTP is built on top of [input-otp](https://github.com/guilhermerodz/input-otp) by [@guilherme_rodz](https://twitter.com/guilherme_rodz).
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+
+
+Run the following command:
+
+```bash
+npx shadcn@latest add input-otp
+```
+
+
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install input-otp
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ InputOTP,
+ InputOTPGroup,
+ InputOTPSeparator,
+ InputOTPSlot,
+} from "@/components/ui/input-otp"
+```
+
+```tsx showLineNumbers
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+## Examples
+
+### Pattern
+
+Use the `pattern` prop to define a custom pattern for the OTP input.
+
+
+
+```tsx showLineNumbers {1,7}
+import { REGEXP_ONLY_DIGITS_AND_CHARS } from "input-otp"
+
+...
+
+
+
+
+ {/* ... */}
+
+
+```
+
+### Separator
+
+You can use the ` ` component to add a separator between the input groups.
+
+
+
+```tsx showLineNumbers {4,15}
+import {
+ InputOTP,
+ InputOTPGroup,
+ InputOTPSeparator,
+ InputOTPSlot,
+} from "@/components/ui/input-otp"
+
+...
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### Controlled
+
+You can use the `value` and `onChange` props to control the input value.
+
+
+
+### Form
+
+
+
+## Changelog
+
+### 2024-03-19 Composition
+
+We've made some updates and replaced the render props pattern with composition. Here's how to update your code if you prefer the composition pattern.
+
+
+ **Note:** You are not required to update your code if you are using the
+ `render` prop. It is still supported.
+
+
+
+
+Update to the latest version of `input-otp`.
+
+```bash
+npm install input-otp@latest
+```
+
+Update `input-otp.tsx`
+
+```diff showLineNumbers title="input-otp.tsx" {2,8-11}
+- import { OTPInput, SlotProps } from "input-otp"
++ import { OTPInput, OTPInputContext } from "input-otp"
+
+ const InputOTPSlot = React.forwardRef<
+ React.ElementRef<"div">,
+- SlotProps & React.ComponentPropsWithoutRef<"div">
+- >(({ char, hasFakeCaret, isActive, className, ...props }, ref) => {
++ React.ComponentPropsWithoutRef<"div"> & { index: number }
++ >(({ index, className, ...props }, ref) => {
++ const inputOTPContext = React.useContext(OTPInputContext)
++ const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index]
+```
+
+Then replace the `render` prop in your code.
+
+```diff showLineNumbers {2-12}
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+### 2024-03-19 Disabled
+
+To add a disabled state to the input, update ` ` as follows:
+
+```tsx showLineNumbers title="input-otp.tsx" {4,7-11}
+const InputOTP = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, containerClassName, ...props }, ref) => (
+
+))
+InputOTP.displayName = "InputOTP"
+```
diff --git a/apps/v4/content/docs/components/radix/input.mdx b/apps/v4/content/docs/components/radix/input.mdx
new file mode 100644
index 0000000000..e793f4bb94
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/input.mdx
@@ -0,0 +1,112 @@
+---
+title: Input
+description: Displays a form input field or a component that looks like an input field.
+base: radix
+component: true
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add input
+```
+
+
+
+
+
+
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx
+import { Input } from "@/components/ui/input"
+```
+
+```tsx
+
+```
+
+## Examples
+
+### Default
+
+
+
+### File
+
+
+
+### Disabled
+
+
+
+### With Label
+
+
+
+### With Button
+
+
+
+## Changelog
+
+### 2025-09-18 Remove `flex` class
+
+Edit `input.tsx` and remove the `flex` class from the input component. This is no longer needed.
diff --git a/apps/v4/content/docs/components/radix/item.mdx b/apps/v4/content/docs/components/radix/item.mdx
new file mode 100644
index 0000000000..87d5fd4e4a
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/item.mdx
@@ -0,0 +1,362 @@
+---
+title: Item
+description: A versatile component that you can use to display any content.
+base: radix
+component: true
+---
+
+The `Item` component is a straightforward flex container that can house nearly any type of content. Use it to display a title, description, and actions. Group it with the `ItemGroup` component to create a list of items.
+
+You can pretty much achieve the same result with the `div` element and some classes, but **I've built this so many times** that I decided to create a component for it. Now I use it all the time.
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add item
+```
+
+
+
+
+
+
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemDescription,
+ ItemFooter,
+ ItemHeader,
+ ItemMedia,
+ ItemTitle,
+} from "@/components/ui/item"
+```
+
+```tsx showLineNumbers
+-
+
Item Header
+
+
+ Item
+ Item
+
+
+ Item Footer
+
+```
+
+## Item vs Field
+
+Use `Field` if you need to display a form input such as a checkbox, input, radio, or select.
+
+If you only need to display content such as a title, description, and actions, use `Item`.
+
+## Examples
+
+### Variants
+
+
+
+### Size
+
+The `Item` component has different sizes for different use cases. For example, you can use the `sm` size for a compact item or the `default` size for a standard item.
+
+
+
+### Icon
+
+
+
+### Avatar
+
+
+
+### Image
+
+
+
+### Group
+
+
+
+### Header
+
+
+
+### Link
+
+To render an item as a link, use the `asChild` prop. The hover and focus states will be applied to the anchor element.
+
+
+
+```tsx showLineNumbers
+-
+
+
+
+ Dashboard
+ Overview of your account and activity.
+
+
+
+
+```
+
+### Dropdown
+
+
+
+## API Reference
+
+### Item
+
+The main component for displaying content with media, title, description, and actions.
+
+| Prop | Type | Default |
+| --------- | ----------------------------------- | ----------- |
+| `variant` | `"default" \| "outline" \| "muted"` | `"default"` |
+| `size` | `"default" \| "sm"` | `"default"` |
+| `asChild` | `boolean` | `false` |
+
+```tsx
+-
+
+
+ Item
+ Item
+
+
+
+```
+
+You can use the `asChild` prop to render a custom component as the item, for example a link. The hover and focus states will be applied to the custom component.
+
+```tsx showLineNumbers
+import {
+ Item,
+ ItemContent,
+ ItemDescription,
+ ItemMedia,
+ ItemTitle,
+} from "@/components/ui/item"
+
+export function ItemLink() {
+ return (
+ -
+
+
+
+
+
+ Dashboard
+
+ Overview of your account and activity.
+
+
+
+
+ )
+}
+```
+
+### ItemGroup
+
+The `ItemGroup` component is a container that groups related items together with consistent styling.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+
+
+
+
+```
+
+### ItemSeparator
+
+The `ItemSeparator` component is a separator that separates items in the item group.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+
+
+
+
+
+```
+
+### ItemMedia
+
+Use the `ItemMedia` component to display media content such as icons, images, or avatars.
+
+| Prop | Type | Default |
+| ----------- | -------------------------------- | ----------- |
+| `variant` | `"default" \| "icon" \| "image"` | `"default"` |
+| `className` | `string` | |
+
+```tsx
+
+
+
+```
+
+```tsx
+
+
+
+```
+
+### ItemContent
+
+The `ItemContent` component wraps the title and description of the item.
+
+You can skip `ItemContent` if you only need a title.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+
+ Item
+ Item
+
+```
+
+### ItemTitle
+
+Use the `ItemTitle` component to display the title of the item.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+Item Title
+```
+
+### ItemDescription
+
+Use the `ItemDescription` component to display the description of the item.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+Item description
+```
+
+### ItemActions
+
+Use the `ItemActions` component to display action buttons or other interactive elements.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+
+ Action
+ Action
+
+```
+
+### ItemHeader
+
+Use the `ItemHeader` component to display a header in the item.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+Item Header
+```
+
+### ItemFooter
+
+Use the `ItemFooter` component to display a footer in the item.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+```tsx
+Item Footer
+```
diff --git a/apps/v4/content/docs/components/radix/kbd.mdx b/apps/v4/content/docs/components/radix/kbd.mdx
new file mode 100644
index 0000000000..f5e5476864
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/kbd.mdx
@@ -0,0 +1,109 @@
+---
+title: Kbd
+description: Used to display textual user input from keyboard.
+base: radix
+component: true
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add kbd
+```
+
+
+
+
+
+
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx
+import { Kbd } from "@/components/ui/kbd"
+```
+
+```tsx
+Ctrl
+```
+
+## Examples
+
+### Group
+
+Use the `KbdGroup` component to group keyboard keys together.
+
+
+
+### Button
+
+Use the `Kbd` component inside a `Button` component to display a keyboard key inside a button.
+
+
+
+### Tooltip
+
+You can use the `Kbd` component inside a `Tooltip` component to display a tooltip with a keyboard key.
+
+
+
+### Input Group
+
+You can use the `Kbd` component inside a `InputGroupAddon` component to display a keyboard key inside an input group.
+
+
+
+## API Reference
+
+### Kbd
+
+Use the `Kbd` component to display a keyboard key.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | `` |
+
+```tsx
+Ctrl
+```
+
+### KbdGroup
+
+Use the `KbdGroup` component to group `Kbd` components together.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | `` |
+
+```tsx
+
+ Ctrl
+ B
+
+```
diff --git a/apps/v4/content/docs/components/radix/label.mdx b/apps/v4/content/docs/components/radix/label.mdx
new file mode 100644
index 0000000000..e57e21a6ed
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/label.mdx
@@ -0,0 +1,67 @@
+---
+title: Label
+description: Renders an accessible label associated with controls.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/label
+ api: https://www.radix-ui.com/docs/primitives/components/label#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add label
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-label
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx
+import { Label } from "@/components/ui/label"
+```
+
+```tsx
+Your email address
+```
diff --git a/apps/v4/content/docs/components/radix/menubar.mdx b/apps/v4/content/docs/components/radix/menubar.mdx
new file mode 100644
index 0000000000..6ac6d15f57
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/menubar.mdx
@@ -0,0 +1,89 @@
+---
+title: Menubar
+description: A visually persistent menu common in desktop applications that provides quick access to a consistent set of commands.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/menubar
+ api: https://www.radix-ui.com/docs/primitives/components/menubar#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add menubar
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-menubar
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ Menubar,
+ MenubarContent,
+ MenubarItem,
+ MenubarMenu,
+ MenubarSeparator,
+ MenubarShortcut,
+ MenubarTrigger,
+} from "@/components/ui/menubar"
+```
+
+```tsx showLineNumbers
+
+
+ File
+
+
+ New Tab ⌘T
+
+ New Window
+
+ Share
+
+ Print
+
+
+
+```
diff --git a/apps/v4/content/docs/components/radix/meta.json b/apps/v4/content/docs/components/radix/meta.json
new file mode 100644
index 0000000000..1e71ba5d95
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/meta.json
@@ -0,0 +1,64 @@
+{
+ "title": "Radix UI",
+ "pages": [
+ "accordion",
+ "alert",
+ "alert-dialog",
+ "aspect-ratio",
+ "avatar",
+ "badge",
+ "breadcrumb",
+ "button",
+ "button-group",
+ "calendar",
+ "card",
+ "carousel",
+ "chart",
+ "checkbox",
+ "collapsible",
+ "combobox",
+ "command",
+ "context-menu",
+ "data-table",
+ "date-picker",
+ "dialog",
+ "drawer",
+ "dropdown-menu",
+ "empty",
+ "field",
+ "form",
+ "hover-card",
+ "input",
+ "input-group",
+ "input-otp",
+ "item",
+ "kbd",
+ "label",
+ "menubar",
+ "native-select",
+ "navigation-menu",
+ "pagination",
+ "popover",
+ "progress",
+ "radio-group",
+ "resizable",
+ "scroll-area",
+ "select",
+ "separator",
+ "sheet",
+ "sidebar",
+ "skeleton",
+ "slider",
+ "sonner",
+ "spinner",
+ "switch",
+ "table",
+ "tabs",
+ "textarea",
+ "toast",
+ "toggle",
+ "toggle-group",
+ "tooltip",
+ "typography"
+ ]
+}
diff --git a/apps/v4/content/docs/components/radix/native-select.mdx b/apps/v4/content/docs/components/radix/native-select.mdx
new file mode 100644
index 0000000000..4bf8ebfe91
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/native-select.mdx
@@ -0,0 +1,210 @@
+---
+title: Native Select
+description: A styled native HTML select element with consistent design system integration.
+base: radix
+component: true
+---
+
+import { InfoIcon } from "lucide-react"
+
+ }>
+ For a styled select component, see the [Select](/docs/components/select)
+ component.
+
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add native-select
+```
+
+
+
+
+
+
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ NativeSelect,
+ NativeSelectOptGroup,
+ NativeSelectOption,
+} from "@/components/ui/native-select"
+```
+
+```tsx showLineNumbers
+
+ Select a fruit
+ Apple
+ Banana
+ Blueberry
+
+ Grapes
+
+ Pineapple
+
+```
+
+## Examples
+
+### With Groups
+
+Organize options using `NativeSelectOptGroup` for better categorization.
+
+
+
+```tsx showLineNumbers
+
+ Select a food
+
+ Apple
+ Banana
+ Blueberry
+
+
+ Carrot
+ Broccoli
+ Spinach
+
+
+```
+
+### Disabled State
+
+Disable individual options or the entire select component.
+
+
+
+### Invalid State
+
+Show validation errors with the `aria-invalid` attribute and error styling.
+
+
+
+```tsx showLineNumbers
+
+ Select a country
+ United States
+ United Kingdom
+ Canada
+
+```
+
+### Form Integration
+
+Use with form libraries like React Hook Form for controlled components.
+
+
+
+### Input Group Integration
+
+Combine with `InputGroup` for complex input layouts.
+
+
+
+## Native Select vs Select
+
+- Use `NativeSelect` when you need native browser behavior, better performance, or mobile-optimized dropdowns.
+- Use `Select` when you need custom styling, animations, or complex interactions.
+
+The `NativeSelect` component provides native HTML select functionality with consistent styling that matches your design system.
+
+## Accessibility
+
+- The component maintains all native HTML select accessibility features.
+- Screen readers can navigate through options using arrow keys.
+- The chevron icon is marked as `aria-hidden="true"` to avoid duplication.
+- Use `aria-label` or `aria-labelledby` for additional context when needed.
+
+```tsx showLineNumbers
+
+ English
+ Spanish
+ French
+
+```
+
+## API Reference
+
+### NativeSelect
+
+The main select component that wraps the native HTML select element.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | |
+
+All other props are passed through to the underlying `` element.
+
+```tsx
+
+ Option 1
+ Option 2
+
+```
+
+### NativeSelectOption
+
+Represents an individual option within the select.
+
+| Prop | Type | Default |
+| ----------- | --------- | ------- |
+| `value` | `string` | |
+| `disabled` | `boolean` | `false` |
+| `className` | `string` | |
+
+All other props are passed through to the underlying `` element.
+
+```tsx
+Apple
+
+ Banana
+
+```
+
+### NativeSelectOptGroup
+
+Groups related options together for better organization.
+
+| Prop | Type | Default |
+| ----------- | --------- | ------- |
+| `label` | `string` | |
+| `disabled` | `boolean` | `false` |
+| `className` | `string` | |
+
+All other props are passed through to the underlying ` ` element.
+
+```tsx
+
+ Apple
+ Banana
+
+```
diff --git a/apps/v4/content/docs/components/radix/navigation-menu.mdx b/apps/v4/content/docs/components/radix/navigation-menu.mdx
new file mode 100644
index 0000000000..7855b5338b
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/navigation-menu.mdx
@@ -0,0 +1,102 @@
+---
+title: Navigation Menu
+description: A collection of links for navigating websites.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/navigation-menu
+ api: https://www.radix-ui.com/docs/primitives/components/navigation-menu#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add navigation-menu
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-navigation-menu
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ NavigationMenu,
+ NavigationMenuContent,
+ NavigationMenuIndicator,
+ NavigationMenuItem,
+ NavigationMenuLink,
+ NavigationMenuList,
+ NavigationMenuTrigger,
+ NavigationMenuViewport,
+} from "@/components/ui/navigation-menu"
+```
+
+```tsx showLineNumbers
+
+
+
+ Item One
+
+ Link
+
+
+
+
+```
+
+## Link
+
+You can use the `asChild` prop to make another component look like a navigation menu trigger. Here's an example of a link that looks like a navigation menu trigger.
+
+```tsx showLineNumbers title="components/example-navigation-menu.tsx"
+import Link from "next/link"
+
+export function NavigationMenuDemo() {
+ return (
+
+
+ Documentation
+
+
+ )
+}
+```
diff --git a/apps/v4/content/docs/components/radix/pagination.mdx b/apps/v4/content/docs/components/radix/pagination.mdx
new file mode 100644
index 0000000000..84675f1365
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/pagination.mdx
@@ -0,0 +1,111 @@
+---
+title: Pagination
+description: Pagination with page navigation, next and previous links.
+base: radix
+component: true
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add pagination
+```
+
+
+
+
+
+
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ Pagination,
+ PaginationContent,
+ PaginationEllipsis,
+ PaginationItem,
+ PaginationLink,
+ PaginationNext,
+ PaginationPrevious,
+} from "@/components/ui/pagination"
+```
+
+```tsx showLineNumbers
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+```
+
+### Next.js
+
+By default the ` ` component will render an ` ` tag.
+
+To use the Next.js ` ` component, make the following updates to `pagination.tsx`.
+
+```diff showLineNumbers /typeof Link/ {1}
++ import Link from "next/link"
+
+- type PaginationLinkProps = ... & React.ComponentProps<"a">
++ type PaginationLinkProps = ... & React.ComponentProps
+
+const PaginationLink = ({...props }: ) => (
+
+-
++
+ // ...
+-
++
+
+)
+
+```
+
+
+
+**Note:** We are making updates to the cli to automatically do this for you.
+
+
diff --git a/apps/v4/content/docs/components/radix/popover.mdx b/apps/v4/content/docs/components/radix/popover.mdx
new file mode 100644
index 0000000000..95a933c054
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/popover.mdx
@@ -0,0 +1,74 @@
+---
+title: Popover
+description: Displays rich content in a portal, triggered by a button.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/popover
+ api: https://www.radix-ui.com/docs/primitives/components/popover#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add popover
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-popover
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/components/ui/popover"
+```
+
+```tsx showLineNumbers
+
+ Open
+ Place content for the popover here.
+
+```
diff --git a/apps/v4/content/docs/components/radix/progress.mdx b/apps/v4/content/docs/components/radix/progress.mdx
new file mode 100644
index 0000000000..f68f7292b4
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/progress.mdx
@@ -0,0 +1,67 @@
+---
+title: Progress
+description: Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/progress
+ api: https://www.radix-ui.com/docs/primitives/components/progress#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add progress
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-progress
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import { Progress } from "@/components/ui/progress"
+```
+
+```tsx showLineNumbers
+
+```
diff --git a/apps/v4/content/docs/components/radix/radio-group.mdx b/apps/v4/content/docs/components/radix/radio-group.mdx
new file mode 100644
index 0000000000..dcc7ebca5e
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/radio-group.mdx
@@ -0,0 +1,77 @@
+---
+title: Radio Group
+description: A set of checkable buttons—known as radio buttons—where no more than one of the buttons can be checked at a time.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/radio-group
+ api: https://www.radix-ui.com/docs/primitives/components/radio-group#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add radio-group
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-radio-group
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import { Label } from "@/components/ui/label"
+import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
+```
+
+```tsx showLineNumbers
+
+
+
+ Option One
+
+
+
+ Option Two
+
+
+```
diff --git a/apps/v4/content/docs/components/radix/resizable.mdx b/apps/v4/content/docs/components/radix/resizable.mdx
new file mode 100644
index 0000000000..feecf09efb
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/resizable.mdx
@@ -0,0 +1,137 @@
+---
+title: Resizable
+description: Accessible resizable panel groups and layouts with keyboard support.
+base: radix
+component: true
+links:
+ doc: https://github.com/bvaughn/react-resizable-panels
+ api: https://github.com/bvaughn/react-resizable-panels/tree/main/packages/react-resizable-panels
+---
+
+
+
+## About
+
+The `Resizable` component is built on top of [react-resizable-panels](https://github.com/bvaughn/react-resizable-panels) by [bvaughn](https://github.com/bvaughn).
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add resizable
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install react-resizable-panels
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ ResizableHandle,
+ ResizablePanel,
+ ResizablePanelGroup,
+} from "@/components/ui/resizable"
+```
+
+```tsx showLineNumbers
+
+ One
+
+ Two
+
+```
+
+## Examples
+
+### Vertical
+
+Use the `direction` prop to set the direction of the resizable panels.
+
+
+
+```tsx showLineNumbers {9}
+import {
+ ResizableHandle,
+ ResizablePanel,
+ ResizablePanelGroup,
+} from "@/components/ui/resizable"
+
+export default function Example() {
+ return (
+
+ One
+
+ Two
+
+ )
+}
+```
+
+### Handle
+
+You can set or hide the handle by using the `withHandle` prop on the `ResizableHandle` component.
+
+
+
+```tsx showLineNumbers {11}
+import {
+ ResizableHandle,
+ ResizablePanel,
+ ResizablePanelGroup,
+} from "@/components/ui/resizable"
+
+export default function Example() {
+ return (
+
+ One
+
+ Two
+
+ )
+}
+```
diff --git a/apps/v4/content/docs/components/radix/scroll-area.mdx b/apps/v4/content/docs/components/radix/scroll-area.mdx
new file mode 100644
index 0000000000..8c0069aba0
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/scroll-area.mdx
@@ -0,0 +1,80 @@
+---
+title: Scroll Area
+description: Augments native scroll functionality for custom, cross-browser styling.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/scroll-area
+ api: https://www.radix-ui.com/docs/primitives/components/scroll-area#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add scroll-area
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-scroll-area
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import { ScrollArea } from "@/components/ui/scroll-area"
+```
+
+```tsx showLineNumbers
+
+ 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
+
+
diff --git a/apps/v4/content/docs/components/radix/select.mdx b/apps/v4/content/docs/components/radix/select.mdx
new file mode 100644
index 0000000000..b17a159791
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/select.mdx
@@ -0,0 +1,93 @@
+---
+title: Select
+description: Displays a list of options for the user to pick from—triggered by a button.
+base: radix
+component: true
+featured: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/select
+ api: https://www.radix-ui.com/docs/primitives/components/select#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add select
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-select
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/components/ui/select"
+```
+
+```tsx showLineNumbers
+
+
+
+
+
+ Light
+ Dark
+ System
+
+
+```
+
+## Examples
+
+### Scrollable
+
+
diff --git a/apps/v4/content/docs/components/radix/separator.mdx b/apps/v4/content/docs/components/radix/separator.mdx
new file mode 100644
index 0000000000..b590f8cbd3
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/separator.mdx
@@ -0,0 +1,66 @@
+---
+title: Separator
+description: Visually or semantically separates content.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/separator
+ api: https://www.radix-ui.com/docs/primitives/components/separator#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add separator
+```
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-separator
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import { Separator } from "@/components/ui/separator"
+```
+
+```tsx showLineNumbers
+
+```
diff --git a/apps/v4/content/docs/components/radix/sheet.mdx b/apps/v4/content/docs/components/radix/sheet.mdx
new file mode 100644
index 0000000000..b9796f0dc7
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/sheet.mdx
@@ -0,0 +1,110 @@
+---
+title: Sheet
+description: Extends the Dialog component to display content that complements the main content of the screen.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/dialog
+ api: https://www.radix-ui.com/docs/primitives/components/dialog#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add sheet
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-dialog
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+### Usage
+
+```tsx showLineNumbers
+import {
+ Sheet,
+ SheetContent,
+ SheetDescription,
+ SheetHeader,
+ SheetTitle,
+ SheetTrigger,
+} from "@/components/ui/sheet"
+```
+
+```tsx showLineNumbers
+
+ Open
+
+
+ Are 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:
+
+```tsx showLineNumbers {3}
+
+ Open
+
+
+ Are you absolutely sure?
+
+ This action cannot be undone. This will permanently delete your account
+ and remove your data from our servers.
+
+
+
+
+```
diff --git a/apps/v4/content/docs/components/radix/sidebar.mdx b/apps/v4/content/docs/components/radix/sidebar.mdx
new file mode 100644
index 0000000000..193daa7429
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/sidebar.mdx
@@ -0,0 +1,1395 @@
+---
+title: Sidebar
+description: A composable, themeable and customizable sidebar component.
+base: radix
+component: true
+---
+
+
+
+
+ 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.tsx`.
+
+We now have a solid foundation to build on top of. Composable. Themeable.
+Customizable.
+
+[Browse the Blocks Library](/blocks).
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+
+
+Run the following command to install `sidebar.tsx`
+
+```bash
+npx shadcn@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.
+
+We'll go over the colors later in the [theming section](/docs/components/sidebar#theming).
+
+```css showLineNumbers title="app/globals.css"
+@layer base {
+ :root {
+ --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 {
+ --sidebar: oklch(0.205 0 0);
+ --sidebar-foreground: oklch(0.985 0 0);
+ --sidebar-primary: oklch(0.488 0.243 264.376);
+ --sidebar-primary-foreground: oklch(0.985 0 0);
+ --sidebar-accent: oklch(0.269 0 0);
+ --sidebar-accent-foreground: oklch(0.985 0 0);
+ --sidebar-border: oklch(1 0 0 / 10%);
+ --sidebar-ring: oklch(0.439 0 0);
+ }
+}
+```
+
+
+
+
+
+
+
+
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+Add the following colors to your CSS file
+
+We'll go over the colors later in the [theming section](/docs/components/sidebar#theming).
+
+```css showLineNumbers title="app/globals.css"
+@layer base {
+ :root {
+ --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 {
+ --sidebar: oklch(0.205 0 0);
+ --sidebar-foreground: oklch(0.985 0 0);
+ --sidebar-primary: oklch(0.488 0.243 264.376);
+ --sidebar-primary-foreground: oklch(0.985 0 0);
+ --sidebar-accent: oklch(0.269 0 0);
+ --sidebar-accent-foreground: oklch(0.985 0 0);
+ --sidebar-border: oklch(1 0 0 / 10%);
+ --sidebar-ring: oklch(0.439 0 0);
+ }
+}
+```
+
+
+
+
+
+
+
+## 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
+
+```tsx showLineNumbers title="app/layout.tsx"
+import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
+import { AppSidebar } from "@/components/app-sidebar"
+
+export default function Layout({ children }: { children: React.ReactNode }) {
+ return (
+
+
+
+
+ {children}
+
+
+ )
+}
+```
+
+```tsx showLineNumbers title="components/app-sidebar.tsx"
+import {
+ Sidebar,
+ SidebarContent,
+ SidebarFooter,
+ SidebarGroup,
+ SidebarHeader,
+} from "@/components/ui/sidebar"
+
+export function AppSidebar() {
+ return (
+
+
+
+
+
+
+
+
+ )
+}
+```
+
+## 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.
+
+
+```tsx showLineNumbers title="app/layout.tsx"
+import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
+import { AppSidebar } from "@/components/app-sidebar"
+
+export default function Layout({ children }: { children: React.ReactNode }) {
+ return (
+
+
+
+
+ {children}
+
+
+ )
+}
+```
+
+Create a new sidebar component at `components/app-sidebar.tsx`.
+
+```tsx showLineNumbers title="components/app-sidebar.tsx"
+import { Sidebar, SidebarContent } from "@/components/ui/sidebar"
+
+export function AppSidebar() {
+ return (
+
+
+
+ )
+}
+```
+
+Now, let's add a `SidebarMenu` to the sidebar.
+
+We'll use the `SidebarMenu` component in a `SidebarGroup`.
+
+```tsx showLineNumbers title="components/app-sidebar.tsx"
+import { Calendar, Home, Inbox, Search, Settings } from "lucide-react"
+
+import {
+ Sidebar,
+ SidebarContent,
+ SidebarGroup,
+ SidebarGroupContent,
+ SidebarGroupLabel,
+ SidebarMenu,
+ SidebarMenuButton,
+ SidebarMenuItem,
+} from "@/components/ui/sidebar"
+
+// Menu items.
+const items = [
+ {
+ title: "Home",
+ url: "#",
+ icon: Home,
+ },
+ {
+ title: "Inbox",
+ url: "#",
+ icon: Inbox,
+ },
+ {
+ title: "Calendar",
+ url: "#",
+ icon: Calendar,
+ },
+ {
+ title: "Search",
+ url: "#",
+ icon: Search,
+ },
+ {
+ title: "Settings",
+ url: "#",
+ icon: Settings,
+ },
+]
+
+export function AppSidebar() {
+ return (
+
+
+
+ Application
+
+
+ {items.map((item) => (
+
+
+
+
+ {item.title}
+
+
+
+ ))}
+
+
+
+
+
+ )
+}
+```
+
+You've created your first sidebar.
+
+You should see something like this:
+
+
+
+
+ Your first sidebar.
+
+
+
+
+
+## Components
+
+The components in `sidebar.tsx` are built to be composable i.e you build your sidebar by putting the provided components together. They also compose well with other shadcn/ui components such as `DropdownMenu`, `Collapsible` or `Dialog` etc.
+
+**If you need to change the code in `sidebar.tsx`, you are encouraged to do so. The code is yours. Use `sidebar.tsx` as a starting point and 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` variables in `sidebar.tsx` to set the width of the sidebar.
+
+```tsx showLineNumbers title="components/ui/sidebar.tsx"
+const SIDEBAR_WIDTH = "16rem"
+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.
+
+```tsx showLineNumbers title="components/ui/sidebar.tsx"
+
+
+
+```
+
+This will handle the width of the sidebar but also the layout spacing.
+
+### Keyboard Shortcut
+
+The `SIDEBAR_KEYBOARD_SHORTCUT` variable 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 updating the `SIDEBAR_KEYBOARD_SHORTCUT` variable.
+
+```tsx showLineNumbers title="components/ui/sidebar.tsx"
+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 Next.js, set up your `SidebarProvider` in `app/layout.tsx` like this:
+
+```tsx showLineNumbers title="app/layout.tsx"
+import { cookies } from "next/headers"
+
+import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
+import { AppSidebar } from "@/components/app-sidebar"
+
+export async function Layout({ children }: { children: React.ReactNode }) {
+ const cookieStore = await cookies()
+ const defaultOpen = cookieStore.get("sidebar_state")?.value === "true"
+
+ return (
+
+
+
+
+ {children}
+
+
+ )
+}
+```
+
+You can change the name of the cookie by updating the `SIDEBAR_COOKIE_NAME` variable in `sidebar.tsx`.
+
+```tsx showLineNumbers title="components/ui/sidebar.tsx"
+const SIDEBAR_COOKIE_NAME = "sidebar_state"
+```
+
+## Sidebar
+
+The main `Sidebar` component used to render a collapsible sidebar.
+
+```tsx showLineNumbers
+import { Sidebar } from "@/components/ui/sidebar"
+
+export function AppSidebar() {
+ return
+}
+```
+
+### 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`.
+
+```tsx showLineNumbers
+import { Sidebar } from "@/components/ui/sidebar"
+
+export function AppSidebar() {
+ return
+}
+```
+
+### variant
+
+Use the `variant` prop to change the variant of the sidebar.
+
+Available options are `sidebar`, `floating` and `inset`.
+
+```tsx showLineNumbers
+import { Sidebar } from "@/components/ui/sidebar"
+
+export function AppSidebar() {
+ return
+}
+```
+
+
+ **Note:** If you use the `inset` variant, remember to wrap your main content
+ in a `SidebarInset` component.
+
+
+```tsx showLineNumbers
+
+
+
+ {children}
+
+
+```
+
+### collapsible
+
+Use the `collapsible` prop to make the sidebar collapsible.
+
+Available options are `offcanvas`, `icon` and `none`.
+
+```tsx showLineNumbers
+import { Sidebar } from "@/components/ui/sidebar"
+
+export function AppSidebar() {
+ return
+}
+```
+
+| 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` hook is used to control the sidebar.
+
+```tsx showLineNumbers
+import { useSidebar } from "@/components/ui/sidebar"
+
+export function AppSidebar() {
+ const {
+ state,
+ open,
+ setOpen,
+ openMobile,
+ setOpenMobile,
+ isMobile,
+ toggleSidebar,
+ } = useSidebar()
+}
+```
+
+| 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.
+
+
+
+```tsx showLineNumbers title="components/app-sidebar.tsx"
+
+
+
+
+
+
+
+ Select Workspace
+
+
+
+
+
+ Acme Inc
+
+
+ Acme 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.
+
+
+
+```tsx showLineNumbers title="components/app-sidebar.tsx"
+export function AppSidebar() {
+ return (
+
+
+
+
+
+
+
+
+
+
+ Username
+
+
+
+
+
+ Account
+
+
+ Billing
+
+
+ Sign 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.
+
+```tsx showLineNumbers
+import { Sidebar, SidebarContent } from "@/components/ui/sidebar"
+
+export function AppSidebar() {
+ return (
+
+
+
+
+
+
+ )
+}
+```
+
+## 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.
+
+
+
+```tsx showLineNumbers
+import { Sidebar, SidebarContent, SidebarGroup } from "@/components/ui/sidebar"
+
+export function AppSidebar() {
+ return (
+
+
+
+ Application
+
+ Add Project
+
+
+
+
+
+ )
+}
+```
+
+## Collapsible SidebarGroup
+
+To make a `SidebarGroup` collapsible, wrap it in a `Collapsible`.
+
+
+
+
+ A collapsible sidebar group.
+
+
+
+```tsx showLineNumbers
+export function AppSidebar() {
+ return (
+
+
+
+
+ Help
+
+
+
+
+
+
+
+
+ )
+}
+```
+
+
+ **Note:** We wrap the `CollapsibleTrigger` in a `SidebarGroupLabel` to render
+ a button.
+
+
+## SidebarGroupAction
+
+Use the `SidebarGroupAction` component to add an action button to the `SidebarGroup`.
+
+
+
+
+ A sidebar group with an action button.
+
+
+
+```tsx showLineNumbers {5-7}
+export function AppSidebar() {
+ return (
+
+ Projects
+
+ Add Project
+
+
+
+ )
+}
+```
+
+## SidebarMenu
+
+The `SidebarMenu` component is used for building a menu within a `SidebarGroup`.
+
+A `SidebarMenu` component is composed of `SidebarMenuItem`, `SidebarMenuButton`, ` ` and ` ` components.
+
+
+
+
+Here's an example of a `SidebarMenu` component rendering a list of projects.
+
+
+
+
+ A sidebar menu with a list of projects.
+
+
+
+```tsx showLineNumbers
+
+
+
+ Projects
+
+
+ {projects.map((project) => (
+
+
+
+
+ {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 a `Link` or an `a` tag.
+
+```tsx showLineNumbers
+
+ Home
+
+```
+
+### Icon and Label
+
+You can render an icon and a truncated label inside the button. Remember to wrap the label in a ``.
+
+```tsx showLineNumbers
+
+
+
+ Home
+
+
+```
+
+### isActive
+
+Use the `isActive` prop to mark a menu item as active.
+
+```tsx showLineNumbers
+
+ 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 ` ` as a clickable link and the ` ` as a button.
+
+```tsx showLineNumbers
+
+
+
+
+ Home
+
+
+
+ Add Project
+
+
+```
+
+### DropdownMenu
+
+Here's an example of a `SidebarMenuAction` component rendering a `DropdownMenu`.
+
+
+
+
+ A sidebar menu action with a dropdown menu.
+
+
+
+```tsx showLineNumbers
+
+
+
+
+ Home
+
+
+
+
+
+
+
+
+
+
+ Edit Project
+
+
+ Delete Project
+
+
+
+
+```
+
+## SidebarMenuSub
+
+The `SidebarMenuSub` component is used to render a submenu within a `SidebarMenu`.
+
+Use ` ` and ` ` to render a submenu item.
+
+
+
+
+ A sidebar menu with a submenu.
+
+
+
+```tsx showLineNumbers
+
+
+
+
+
+
+
+
+
+
+
+```
+
+## Collapsible SidebarMenu
+
+To make a `SidebarMenu` component collapsible, wrap it and the `SidebarMenuSub` components in a `Collapsible`.
+
+
+
+
+ A collapsible sidebar menu.
+
+
+
+```tsx showLineNumbers
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+## SidebarMenuBadge
+
+The `SidebarMenuBadge` component is used to render a badge within a `SidebarMenuItem`.
+
+
+
+
+ A sidebar menu with a badge.
+
+
+
+```tsx showLineNumbers
+
+
+ 24
+
+```
+
+## SidebarMenuSkeleton
+
+The `SidebarMenuSkeleton` component is used to render a skeleton for a `SidebarMenu`. You can use this to show a loading state when using React Server Components, SWR or react-query.
+
+```tsx showLineNumbers
+function NavProjectsSkeleton() {
+ return (
+
+ {Array.from({ length: 5 }).map((_, index) => (
+
+
+
+ ))}
+
+ )
+}
+```
+
+## SidebarSeparator
+
+The `SidebarSeparator` component is used to render a separator within a `Sidebar`.
+
+```tsx showLineNumbers
+
+
+
+
+
+
+
+
+
+```
+
+## SidebarTrigger
+
+Use the `SidebarTrigger` component to render a button that toggles the sidebar.
+
+The `SidebarTrigger` component must be used within a `SidebarProvider`.
+
+```tsx showLineNumbers
+
+
+
+
+
+
+```
+
+### Custom Trigger
+
+To create a custom trigger, you can use the `useSidebar` hook.
+
+```tsx showLineNumbers
+import { useSidebar } from "@/components/ui/sidebar"
+
+export function CustomTrigger() {
+ const { toggleSidebar } = useSidebar()
+
+ return Toggle Sidebar
+}
+```
+
+## SidebarRail
+
+The `SidebarRail` component is used to render a rail within a `Sidebar`. This rail can be used to toggle the sidebar.
+
+```tsx showLineNumbers
+
+
+
+
+
+
+
+
+```
+
+## Data Fetching
+
+### React Server Components
+
+Here's an example of a `SidebarMenu` component rendering a list of projects using React Server Components.
+
+
+
+
+ A sidebar menu using React Server Components.
+
+
+
+```tsx showLineNumbers {6} title="Skeleton to show loading state."
+function NavProjectsSkeleton() {
+ return (
+
+ {Array.from({ length: 5 }).map((_, index) => (
+
+
+
+ ))}
+
+ )
+}
+```
+
+```tsx showLineNumbers {2} title="Server component fetching data."
+async function NavProjects() {
+ const projects = await fetchProjects()
+
+ return (
+
+ {projects.map((project) => (
+
+
+
+
+ {project.name}
+
+
+
+ ))}
+
+ )
+}
+```
+
+```tsx showLineNumbers {8-10} title="Usage with React Suspense."
+function AppSidebar() {
+ return (
+
+
+
+ Projects
+
+ }>
+
+
+
+
+
+
+ )
+}
+```
+
+### SWR and React Query
+
+You can use the same approach with [SWR](https://swr.vercel.app/) or [react-query](https://tanstack.com/query/latest/docs/framework/react/overview).
+
+```tsx showLineNumbers title="SWR"
+function NavProjects() {
+ const { data, isLoading } = useSWR("/api/projects", fetcher)
+
+ if (isLoading) {
+ return (
+
+ {Array.from({ length: 5 }).map((_, index) => (
+
+
+
+ ))}
+
+ )
+ }
+
+ if (!data) {
+ return ...
+ }
+
+ return (
+
+ {data.map((project) => (
+
+
+
+
+ {project.name}
+
+
+
+ ))}
+
+ )
+}
+```
+
+```tsx showLineNumbers title="React Query"
+function NavProjects() {
+ const { data, isLoading } = useQuery()
+
+ if (isLoading) {
+ return (
+
+ {Array.from({ length: 5 }).map((_, index) => (
+
+
+
+ ))}
+
+ )
+ }
+
+ if (!data) {
+ return ...
+ }
+
+ return (
+
+ {data.map((project) => (
+
+
+
+
+ {project.name}
+
+
+
+ ))}
+
+ )
+}
+```
+
+## Controlled Sidebar
+
+Use the `open` and `onOpenChange` props to control the sidebar.
+
+
+
+
+ A controlled sidebar.
+
+
+
+```tsx showLineNumbers
+export function AppSidebar() {
+ const [open, setOpen] = React.useState(false)
+
+ return (
+
+
+
+ )
+}
+```
+
+## 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.
+
+```tsx
+
+
+
+
+
+```
+
+- **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.
+
+```tsx
+
+
+
+
+```
+
+You can find more tips on using states for styling in this [Twitter thread](https://x.com/shadcn/status/1842329158879420864).
+
+## Changelog
+
+### 2024-10-30 Cookie handling in setOpen
+
+- [#5593](https://github.com/shadcn-ui/ui/pull/5593) - Improved setOpen callback logic in ``.
+
+Update the `setOpen` callback in `` as follows:
+
+```tsx showLineNumbers
+const setOpen = React.useCallback(
+ (value: boolean | ((value: boolean) => boolean)) => {
+ const openState = typeof value === "function" ? value(open) : value
+ if (setOpenProp) {
+ setOpenProp(openState)
+ } else {
+ _setOpen(openState)
+ }
+
+ // This sets the cookie to keep the sidebar state.
+ document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
+ },
+ [setOpenProp, open]
+)
+```
+
+### 2024-10-21 Fixed `text-sidebar-foreground`
+
+- [#5491](https://github.com/shadcn-ui/ui/pull/5491) - Moved `text-sidebar-foreground` from `` to `` component.
+
+### 2024-10-20 Typo in `useSidebar` hook.
+
+Fixed typo in `useSidebar` hook.
+
+```diff showLineNumbers title="sidebar.tsx"
+- throw new Error("useSidebar must be used within a Sidebar.")
++ throw new Error("useSidebar must be used within a SidebarProvider.")
+```
diff --git a/apps/v4/content/docs/components/radix/skeleton.mdx b/apps/v4/content/docs/components/radix/skeleton.mdx
new file mode 100644
index 0000000000..c2779a9535
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/skeleton.mdx
@@ -0,0 +1,68 @@
+---
+title: Skeleton
+description: Use to show a placeholder while content is loading.
+base: radix
+component: true
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add skeleton
+```
+
+
+
+
+
+
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx
+import { Skeleton } from "@/components/ui/skeleton"
+```
+
+```tsx
+
+```
+
+## Examples
+
+### Card
+
+
diff --git a/apps/v4/content/docs/components/radix/slider.mdx b/apps/v4/content/docs/components/radix/slider.mdx
new file mode 100644
index 0000000000..3e10784f03
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/slider.mdx
@@ -0,0 +1,67 @@
+---
+title: Slider
+description: An input where the user selects a value from within a given range.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/slider
+ api: https://www.radix-ui.com/docs/primitives/components/slider#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add slider
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-slider
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx
+import { Slider } from "@/components/ui/slider"
+```
+
+```tsx
+
+```
diff --git a/apps/v4/content/docs/components/radix/sonner.mdx b/apps/v4/content/docs/components/radix/sonner.mdx
new file mode 100644
index 0000000000..42bf72fc42
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/sonner.mdx
@@ -0,0 +1,159 @@
+---
+title: Sonner
+description: An opinionated toast component for React.
+base: radix
+component: true
+links:
+ doc: https://sonner.emilkowal.ski
+---
+
+
+
+## About
+
+Sonner is built and maintained by [emilkowalski](https://twitter.com/emilkowalski).
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+
+
+Run the following command:
+
+```bash
+npx shadcn@latest add sonner
+```
+
+Add the Toaster component
+
+```tsx title="app/layout.tsx" {1,9}
+import { Toaster } from "@/components/ui/sonner"
+
+export default function RootLayout({ children }) {
+ return (
+
+
+
+ {children}
+
+
+
+ )
+}
+```
+
+
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install sonner next-themes
+```
+
+Copy and paste the following code into your project.
+
+
+
+Add the Toaster component
+
+```tsx showLineNumbers title="app/layout.tsx" {1,8}
+import { Toaster } from "@/components/ui/sonner"
+
+export default function RootLayout({ children }) {
+ return (
+
+
+
+
+ {children}
+
+
+ )
+}
+```
+
+
+
+
+
+
+
+## Usage
+
+```tsx
+import { toast } from "sonner"
+```
+
+```tsx
+toast("Event has been created.")
+```
+
+## Examples
+
+
+
+## Changelog
+
+### 2025-10-13 Icons
+
+We've updated the Sonner component to use icons from `lucide`. Update your `sonner.tsx` file to use the new icons.
+
+```tsx showLineNumbers title="components/ui/sonner.tsx" {3-9,20-26}
+"use client"
+
+import {
+ CircleCheckIcon,
+ InfoIcon,
+ Loader2Icon,
+ OctagonXIcon,
+ TriangleAlertIcon,
+} from "lucide-react"
+import { useTheme } from "next-themes"
+import { Toaster as Sonner, ToasterProps } from "sonner"
+
+const Toaster = ({ ...props }: ToasterProps) => {
+ const { theme = "system" } = useTheme()
+
+ return (
+ ,
+ info: ,
+ warning: ,
+ error: ,
+ loading: ,
+ }}
+ style={
+ {
+ "--normal-bg": "var(--popover)",
+ "--normal-text": "var(--popover-foreground)",
+ "--normal-border": "var(--border)",
+ "--border-radius": "var(--radius)",
+ } as React.CSSProperties
+ }
+ {...props}
+ />
+ )
+}
+
+export { Toaster }
+```
diff --git a/apps/v4/content/docs/components/radix/spinner.mdx b/apps/v4/content/docs/components/radix/spinner.mdx
new file mode 100644
index 0000000000..4271569f96
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/spinner.mdx
@@ -0,0 +1,139 @@
+---
+title: Spinner
+description: An indicator that can be used to show a loading state.
+base: radix
+component: true
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add spinner
+```
+
+
+
+
+
+
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx
+import { Spinner } from "@/components/ui/spinner"
+```
+
+```tsx
+
+```
+
+## Customization
+
+You can replace the default spinner icon with any other icon by editing the `Spinner` component.
+
+
+
+```tsx showLineNumbers title="components/ui/spinner.tsx"
+import { LoaderIcon } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+
+function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
+ return (
+
+ )
+}
+
+export { Spinner }
+```
+
+## Examples
+
+### Size
+
+Use the `size-*` utility class to change the size of the spinner.
+
+
+
+### Color
+
+Use the `text-` utility class to change the color of the spinner.
+
+
+
+### Button
+
+Add a spinner to a button to indicate a loading state. The ` ` will handle the spacing between the spinner and the text.
+
+
+
+### Badge
+
+You can also use a spinner inside a badge.
+
+
+
+### Input Group
+
+Input Group can have spinners inside ``.
+
+
+
+### Empty
+
+
+
+### Item
+
+Use the spinner inside `` to indicate a loading state.
+
+
+
+## API Reference
+
+### Spinner
+
+Use the `Spinner` component to display a spinner.
+
+| Prop | Type | Default |
+| ----------- | -------- | ------- |
+| `className` | `string` | `` |
+
+```tsx
+
+```
diff --git a/apps/v4/content/docs/components/radix/switch.mdx b/apps/v4/content/docs/components/radix/switch.mdx
new file mode 100644
index 0000000000..fdd33c728f
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/switch.mdx
@@ -0,0 +1,67 @@
+---
+title: Switch
+description: A control that allows the user to toggle between checked and not checked.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/switch
+ api: https://www.radix-ui.com/docs/primitives/components/switch#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add switch
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-switch
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx
+import { Switch } from "@/components/ui/switch"
+```
+
+```tsx
+
+```
diff --git a/apps/v4/content/docs/components/radix/table.mdx b/apps/v4/content/docs/components/radix/table.mdx
new file mode 100644
index 0000000000..430588aca8
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/table.mdx
@@ -0,0 +1,92 @@
+---
+title: Table
+description: A responsive table component.
+base: radix
+component: true
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add table
+```
+
+
+
+
+
+
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ Table,
+ TableBody,
+ TableCaption,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/components/ui/table"
+```
+
+```tsx showLineNumbers
+
+ A list of your recent invoices.
+
+
+ Invoice
+ Status
+ Method
+ Amount
+
+
+
+
+ INV001
+ Paid
+ Credit Card
+ $250.00
+
+
+
+```
+
+## Data Table
+
+You can use the `` component to build more complex data tables. Combine it with [@tanstack/react-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.
diff --git a/apps/v4/content/docs/components/radix/tabs.mdx b/apps/v4/content/docs/components/radix/tabs.mdx
new file mode 100644
index 0000000000..ee9988cf48
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/tabs.mdx
@@ -0,0 +1,74 @@
+---
+title: Tabs
+description: A set of layered sections of content—known as tab panels—that are displayed one at a time.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/tabs
+ api: https://www.radix-ui.com/docs/primitives/components/tabs#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add tabs
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-tabs
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
+```
+
+```tsx showLineNumbers
+
+
+ Account
+ Password
+
+ Make changes to your account here.
+ Change your password here.
+
+```
diff --git a/apps/v4/content/docs/components/radix/textarea.mdx b/apps/v4/content/docs/components/radix/textarea.mdx
new file mode 100644
index 0000000000..bcf23b7088
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/textarea.mdx
@@ -0,0 +1,101 @@
+---
+title: Textarea
+description: Displays a form textarea or a component that looks like a textarea.
+base: radix
+component: true
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add textarea
+```
+
+
+
+
+
+
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx
+import { Textarea } from "@/components/ui/textarea"
+```
+
+```tsx
+
+```
+
+## Examples
+
+### Default
+
+
+
+### Disabled
+
+
+
+### With Label
+
+
+
+### With Text
+
+
+
+### With Button
+
+
diff --git a/apps/v4/content/docs/components/radix/toast.mdx b/apps/v4/content/docs/components/radix/toast.mdx
new file mode 100644
index 0000000000..213016d9d3
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/toast.mdx
@@ -0,0 +1,15 @@
+---
+title: Toast
+description: A succinct message that is displayed temporarily.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/toast
+ api: https://www.radix-ui.com/docs/primitives/components/toast#api-reference
+---
+
+
+ See the [sonner](/docs/components/sonner) documentation for more information.
+
+
+If you're looking for the old toast component, see the [old docs](https://v3.shadcn.com/docs/components/toast) for more information.
diff --git a/apps/v4/content/docs/components/radix/toggle-group.mdx b/apps/v4/content/docs/components/radix/toggle-group.mdx
new file mode 100644
index 0000000000..28819d62f7
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/toggle-group.mdx
@@ -0,0 +1,149 @@
+---
+title: Toggle Group
+description: A set of two-state buttons that can be toggled on or off.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/toggle-group
+ api: https://www.radix-ui.com/docs/primitives/components/toggle-group#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add toggle-group
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-toggle-group
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx
+import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
+```
+
+```tsx
+
+ A
+ B
+ C
+
+```
+
+## Examples
+
+### Outline
+
+
+
+### Single
+
+
+
+### Small
+
+
+
+### Large
+
+
+
+### Disabled
+
+
+
+### Spacing
+
+Use `spacing={2}` to add spacing between toggle group items.
+
+
+
+## API Reference
+
+### ToggleGroup
+
+The main component that wraps toggle group items.
+
+| Prop | Type | Default |
+| ----------- | --------------------------- | ----------- |
+| `type` | `"single" \| "multiple"` | `"single"` |
+| `variant` | `"default" \| "outline"` | `"default"` |
+| `size` | `"default" \| "sm" \| "lg"` | `"default"` |
+| `spacing` | `number` | `0` |
+| `className` | `string` | |
+
+```tsx
+
+ A
+ B
+
+```
+
+### ToggleGroupItem
+
+Individual toggle items within a toggle group. Remember to add an `aria-label` to each item for accessibility.
+
+| Prop | Type | Default |
+| ----------- | -------- | -------- |
+| `value` | `string` | Required |
+| `className` | `string` | |
diff --git a/apps/v4/content/docs/components/radix/toggle.mdx b/apps/v4/content/docs/components/radix/toggle.mdx
new file mode 100644
index 0000000000..32b6848530
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/toggle.mdx
@@ -0,0 +1,117 @@
+---
+title: Toggle
+description: A two-state button that can be either on or off.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/toggle
+ api: https://www.radix-ui.com/docs/primitives/components/toggle#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add toggle
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-toggle
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx
+import { Toggle } from "@/components/ui/toggle"
+```
+
+```tsx
+Toggle
+```
+
+## Examples
+
+### Default
+
+
+
+### Outline
+
+
+
+### With Text
+
+
+
+### Small
+
+
+
+### Large
+
+
+
+### Disabled
+
+
diff --git a/apps/v4/content/docs/components/radix/tooltip.mdx b/apps/v4/content/docs/components/radix/tooltip.mdx
new file mode 100644
index 0000000000..b391f250af
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/tooltip.mdx
@@ -0,0 +1,86 @@
+---
+title: Tooltip
+description: A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/docs/primitives/components/tooltip
+ api: https://www.radix-ui.com/docs/primitives/components/tooltip#api-reference
+---
+
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+```bash
+npx shadcn@latest add tooltip
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @radix-ui/react-tooltip
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from "@/components/ui/tooltip"
+```
+
+```tsx showLineNumbers
+
+ Hover
+
+ Add to library
+
+
+```
+
+---
+
+## Changelog
+
+### 2025-09-22 Update tooltip colors
+
+We've updated the tooltip colors to use the foreground color for the background and the background color for the foreground.
+
+Replace `bg-primary text-primary-foreground` with `bg-foreground text-background` for both ` ` and ` `.
diff --git a/apps/v4/content/docs/components/radix/typography.mdx b/apps/v4/content/docs/components/radix/typography.mdx
new file mode 100644
index 0000000000..750e6cfd8c
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/typography.mdx
@@ -0,0 +1,68 @@
+---
+title: Typography
+description: Styles for headings, paragraphs, lists...etc
+base: radix
+component: true
+---
+
+We do not ship any typography styles by default. This page is an example of how you can use utility classes to style your text.
+
+
+
+## h1
+
+
+
+## h2
+
+
+
+## h3
+
+
+
+## h4
+
+
+
+## p
+
+
+
+## blockquote
+
+
+
+## table
+
+
+
+## list
+
+
+
+## Inline code
+
+
+
+## Lead
+
+
+
+## Large
+
+
+
+## Small
+
+
+
+## Muted
+
+
diff --git a/apps/v4/content/docs/components/typography.mdx b/apps/v4/content/docs/components/typography.mdx
deleted file mode 100644
index f51f4e0b92..0000000000
--- a/apps/v4/content/docs/components/typography.mdx
+++ /dev/null
@@ -1,66 +0,0 @@
----
-title: Typography
-description: Styles for headings, paragraphs, lists...etc
-component: true
----
-
-We do not ship any typography styles by default. This page is an example of how you can use utility classes to style your text.
-
-
-
-## h1
-
-
-
-## h2
-
-
-
-## h3
-
-
-
-## h4
-
-
-
-## p
-
-
-
-## blockquote
-
-
-
-## table
-
-
-
-## list
-
-
-
-## Inline code
-
-
-
-## Lead
-
-
-
-## Large
-
-
-
-## Small
-
-
-
-## Muted
-
-
diff --git a/apps/v4/lib/registry.ts b/apps/v4/lib/registry.ts
index 9c0808b102..6c4d1b67b8 100644
--- a/apps/v4/lib/registry.ts
+++ b/apps/v4/lib/registry.ts
@@ -5,18 +5,31 @@ import { registryItemSchema, type registryItemFileSchema } from "shadcn/schema"
import { Project, ScriptKind } from "ts-morph"
import { type z } from "zod"
-import { Index } from "@/registry/__index__"
-import { type Style } from "@/registry/_legacy-styles"
+import { Index as StylesIndex } from "@/registry/__index__"
+import { Index as BasesIndex } from "@/registry/bases/__index__"
-export function getRegistryComponent(name: string, styleName: Style["name"]) {
- return Index[styleName]?.[name]?.component
+// Map style names to their corresponding index and key.
+function getIndexForStyle(styleName: string) {
+ if (styleName.startsWith("radix-")) {
+ return { index: BasesIndex, key: "radix" }
+ }
+ if (styleName.startsWith("base-")) {
+ return { index: BasesIndex, key: "base" }
+ }
+ return { index: StylesIndex, key: styleName }
+}
+
+export function getRegistryComponent(name: string, styleName: string) {
+ const { index, key } = getIndexForStyle(styleName)
+ return index[key]?.[name]?.component
}
export async function getRegistryItems(
- styleName: Style["name"],
+ styleName: string,
filter?: (item: z.infer) => boolean
) {
- const styleIndex = Index[styleName]
+ const { index, key } = getIndexForStyle(styleName)
+ const styleIndex = index[key]
if (!styleIndex) {
return []
@@ -34,8 +47,9 @@ export async function getRegistryItems(
).then((results) => results.filter(Boolean))
}
-export async function getRegistryItem(name: string, styleName: Style["name"]) {
- const item = Index[styleName]?.[name]
+export async function getRegistryItem(name: string, styleName: string) {
+ const { index, key } = getIndexForStyle(styleName)
+ const item = index[key]?.[name]
if (!item) {
return null
diff --git a/apps/v4/lib/rehype.ts b/apps/v4/lib/rehype.ts
index 2b2c70dd10..175989cc5d 100644
--- a/apps/v4/lib/rehype.ts
+++ b/apps/v4/lib/rehype.ts
@@ -3,8 +3,20 @@ import path from "path"
import { u } from "unist-builder"
import { visit } from "unist-util-visit"
-import { Index } from "@/registry/__index__"
+import { Index as StylesIndex } from "@/registry/__index__"
import { getActiveStyle } from "@/registry/_legacy-styles"
+import { Index as BasesIndex } from "@/registry/bases/__index__"
+
+// Map style names to their corresponding index and key.
+function getIndexForStyle(styleName: string) {
+ if (styleName.startsWith("radix-")) {
+ return { index: BasesIndex, key: "radix" }
+ }
+ if (styleName.startsWith("base-")) {
+ return { index: BasesIndex, key: "base" }
+ }
+ return { index: StylesIndex, key: styleName }
+}
interface UnistNode {
type: string
@@ -43,6 +55,9 @@ export function rehypeComponent() {
const fileName = getNodeAttributeByName(node, "fileName")?.value as
| string
| undefined
+ const styleName =
+ (getNodeAttributeByName(node, "styleName")?.value as string) ||
+ activeStyle.name
if (!name && !srcPath) {
return null
@@ -54,7 +69,8 @@ export function rehypeComponent() {
if (srcPath) {
src = path.join(process.cwd(), srcPath)
} else {
- const component = Index[name]
+ const { index, key } = getIndexForStyle(styleName)
+ const component = index[key]?.[name]
src = fileName
? component.files.find((file: unknown) => {
if (typeof file === "string") {
@@ -75,7 +91,12 @@ export function rehypeComponent() {
// Replace imports.
// TODO: Use @swc/core and a visitor to replace this.
// For now a simple regex should do.
- source = source.replaceAll(`@/registry/new-york-v4/`, "@/components/")
+ source = source.replaceAll(
+ `@/registry/${styleName}/`,
+ "@/components/"
+ )
+ source = source.replaceAll(`@/registry/bases/radix/`, "@/components/")
+ source = source.replaceAll(`@/registry/bases/base/`, "@/components/")
source = source.replaceAll("export default", "export")
// Add code as children so that rehype can take over at build time.
@@ -108,13 +129,17 @@ export function rehypeComponent() {
if (node.name === "ComponentPreview") {
const name = getNodeAttributeByName(node, "name")?.value as string
+ const styleName =
+ (getNodeAttributeByName(node, "styleName")?.value as string) ||
+ activeStyle.name
if (!name) {
return null
}
try {
- const component = Index[activeStyle.name]?.[name]
+ const { index, key } = getIndexForStyle(styleName)
+ const component = index[key]?.[name]
const src = component.files[0]?.path
// Read the source file.
@@ -124,7 +149,12 @@ export function rehypeComponent() {
// Replace imports.
// TODO: Use @swc/core and a visitor to replace this.
// For now a simple regex should do.
- source = source.replaceAll(`@/registry/new-york-v4/`, "@/components/")
+ source = source.replaceAll(
+ `@/registry/${styleName}/`,
+ "@/components/"
+ )
+ source = source.replaceAll(`@/registry/bases/radix/`, "@/components/")
+ source = source.replaceAll(`@/registry/bases/base/`, "@/components/")
source = source.replaceAll("export default", "export")
// Add code as children so that rehype can take over at build time.
diff --git a/apps/v4/middleware.ts b/apps/v4/middleware.ts
new file mode 100644
index 0000000000..973604f2c0
--- /dev/null
+++ b/apps/v4/middleware.ts
@@ -0,0 +1,89 @@
+import { NextResponse } from "next/server"
+import type { NextRequest } from "next/server"
+
+// List of all component names.
+const COMPONENT_NAMES = [
+ "accordion",
+ "alert",
+ "alert-dialog",
+ "aspect-ratio",
+ "avatar",
+ "badge",
+ "breadcrumb",
+ "button",
+ "button-group",
+ "calendar",
+ "card",
+ "carousel",
+ "chart",
+ "checkbox",
+ "collapsible",
+ "combobox",
+ "command",
+ "context-menu",
+ "data-table",
+ "date-picker",
+ "dialog",
+ "drawer",
+ "dropdown-menu",
+ "empty",
+ "field",
+ "form",
+ "hover-card",
+ "input",
+ "input-group",
+ "input-otp",
+ "item",
+ "kbd",
+ "label",
+ "menubar",
+ "native-select",
+ "navigation-menu",
+ "pagination",
+ "popover",
+ "progress",
+ "radio-group",
+ "resizable",
+ "scroll-area",
+ "select",
+ "separator",
+ "sheet",
+ "sidebar",
+ "skeleton",
+ "slider",
+ "sonner",
+ "spinner",
+ "switch",
+ "table",
+ "tabs",
+ "textarea",
+ "toast",
+ "toggle",
+ "toggle-group",
+ "tooltip",
+ "typography",
+]
+
+export function middleware(request: NextRequest) {
+ const { pathname } = request.nextUrl
+
+ // Match /docs/components/:component (not /docs/components/radix/:component or /docs/components/base/:component).
+ const match = pathname.match(/^\/docs\/components\/([^/]+)$/)
+
+ if (match) {
+ const segment = match[1]
+ // Redirect component pages to radix version (default).
+ if (COMPONENT_NAMES.includes(segment)) {
+ return NextResponse.redirect(
+ new URL(`/docs/components/radix/${segment}`, request.url),
+ 301
+ )
+ }
+ }
+
+ return NextResponse.next()
+}
+
+export const config = {
+ matcher: "/docs/components/:path*",
+}