feat: add base and radix docs

This commit is contained in:
shadcn
2026-01-06 16:43:01 +04:00
parent 8fcfc563a9
commit eb098f87d2
130 changed files with 11820 additions and 271 deletions

View File

@@ -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: {
</p>
)}
</div>
{params.slug?.[0] === "components" &&
(params.slug?.[1] === "radix" || params.slug?.[1] === "base") && (
<DocsBaseSwitcher />
)}
{links ? (
<div className="flex items-center gap-2 pt-4">
{links?.doc && (

View File

@@ -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 (

View File

@@ -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

View File

@@ -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 (
<div className="flex gap-1 rounded-md border p-1">
{BASES.map((base) => (
<Link
key={base.name}
href={`/docs/components/${base.name}/${component}`}
className={cn(
"rounded px-3 py-1 text-sm transition-colors",
currentBase === base.name
? "bg-primary text-primary-foreground"
: "hover:bg-muted"
)}
>
{base.label}
</Link>
))}
</div>
)
}

View File

@@ -17,6 +17,10 @@ import {
SidebarMenuItem,
} from "@/registry/new-york-v4/ui/sidebar"
type PageTreeNode = (typeof source.pageTree)["children"][number]
type PageTreeFolder = Extract<PageTreeNode, { type: "folder" }>
type PageTreePage = Extract<PageTreeNode, { type: "page" }>
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<typeof Sidebar> & { 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 (
<Sidebar
className="sticky top-[calc(var(--header-height)+1px)] z-30 hidden h-[calc(100svh-var(--footer-height)-4rem)] overscroll-none bg-transparent lg:flex"
@@ -102,37 +161,34 @@ export function DocsSidebar({
<SidebarGroupContent>
{item.type === "folder" && (
<SidebarMenu className="gap-0.5">
{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) && (
<SidebarMenuItem key={item.url}>
<SidebarMenuButton
asChild
isActive={item.url === pathname}
className="data-[active=true]:bg-accent data-[active=true]:border-accent 3xl:fixed:w-full 3xl:fixed:max-w-48 relative h-[30px] w-fit overflow-visible border border-transparent text-[0.8rem] font-medium after:absolute after:inset-x-0 after:-inset-y-1 after:z-0 after:rounded-md"
>
<Link href={item.url}>
<span className="absolute inset-0 flex w-(--sidebar-width) bg-transparent" />
{item.name}
{PAGES_NEW.includes(item.url) && (
<span
className="flex size-2 rounded-full bg-blue-500"
title="New"
/>
)}
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
)
<SidebarMenuItem key={page.url}>
<SidebarMenuButton
asChild
isActive={page.url === pathname}
className="data-[active=true]:bg-accent data-[active=true]:border-accent 3xl:fixed:w-full 3xl:fixed:max-w-48 relative h-[30px] w-fit overflow-visible border border-transparent text-[0.8rem] font-medium after:absolute after:inset-x-0 after:-inset-y-1 after:z-0 after:rounded-md"
>
<Link href={page.url}>
<span className="absolute inset-0 flex w-(--sidebar-width) bg-transparent" />
{page.name}
{PAGES_NEW.includes(page.url) && (
<span
className="flex size-2 rounded-full bg-blue-500"
title="New"
/>
)}
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
)
})}
</SidebarMenu>

View File

@@ -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:
---
<ComponentPreview
styleName="base-nova"
name="accordion-demo"
className="[&_.preview>[data-orientation=vertical]]:sm:max-w-[80%] **:[.preview]:min-h-[400px]"
description="An accordion with three items"
@@ -43,7 +45,11 @@ npm install @radix-ui/react-accordion
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="accordion" title="components/ui/accordion.tsx" />
<ComponentSource
name="accordion"
title="components/ui/accordion.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -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:
---
<ComponentPreview
styleName="base-nova"
name="alert-dialog-demo"
title="An alert dialog with cancel and continue buttons."
description="An alert dialog with cancel and continue buttons."
@@ -42,7 +44,11 @@ npm install @radix-ui/react-alert-dialog
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="alert-dialog" title="components/ui/alert-dialog.tsx" />
<ComponentSource
name="alert-dialog"
title="components/ui/alert-dialog.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -1,10 +1,12 @@
---
title: Alert
description: Displays a callout for user attention.
base: base
component: true
---
<ComponentPreview
styleName="base-nova"
name="alert-demo"
title="An alert with an icon, title and description."
description="An alert with an icon, title and description. The title says 'Heads up!' and the description is 'You can add components to your app using the cli.'."
@@ -32,7 +34,11 @@ npx shadcn@latest add alert
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="alert" title="components/ui/alert.tsx" />
<ComponentSource
name="alert"
title="components/ui/alert.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -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:
---
<ComponentPreview
styleName="base-nova"
name="aspect-ratio-demo"
title="Aspect Ratio"
description="A component that displays an image with a 16:9 aspect ratio."
@@ -41,7 +43,11 @@ npm install @radix-ui/react-aspect-ratio
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="aspect-ratio" title="components/ui/aspect-ratio.tsx" />
<ComponentSource
name="aspect-ratio"
title="components/ui/aspect-ratio.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -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:
---
<ComponentPreview
styleName="base-nova"
name="avatar-demo"
title="Avatar"
description="An avatar with a fallback."
@@ -41,7 +43,11 @@ npm install @radix-ui/react-avatar
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="avatar" title="components/ui/avatar.tsx" />
<ComponentSource
name="avatar"
title="components/ui/avatar.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -1,10 +1,12 @@
---
title: Badge
description: Displays a badge or a component that looks like a badge.
base: base
component: true
---
<ComponentPreview
styleName="base-nova"
name="badge-demo"
title="Badge"
description="A default badge"
@@ -32,7 +34,11 @@ npx shadcn@latest add badge
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="badge" title="components/ui/badge.tsx" />
<ComponentSource
name="badge"
title="components/ui/badge.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -1,10 +1,12 @@
---
title: Breadcrumb
description: Displays the path to the current resource using a hierarchy of links.
base: base
component: true
---
<ComponentPreview
styleName="base-nova"
name="breadcrumb-demo"
className="[&_.preview]:p-2"
description="A breadcrumb with a collapsible dropdown."
@@ -32,7 +34,11 @@ npx shadcn@latest add breadcrumb
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="breadcrumb" title="components/ui/breadcrumb.tsx" />
<ComponentSource
name="breadcrumb"
title="components/ui/breadcrumb.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -80,6 +86,7 @@ import {
Use a custom component as `children` for `<BreadcrumbSeparator />` to create a custom separator.
<ComponentPreview
styleName="base-nova"
name="breadcrumb-separator"
description="A breadcrumb with a custom separator"
/>
@@ -111,6 +118,7 @@ import { SlashIcon } from "lucide-react"
You can compose `<BreadcrumbItem />` with a `<DropdownMenu />` to create a dropdown in the breadcrumb.
<ComponentPreview
styleName="base-nova"
name="breadcrumb-dropdown"
className="[&_.preview]:p-2"
description="A breadcrumb with a dropdown."
@@ -147,6 +155,7 @@ import {
We provide a `<BreadcrumbEllipsis />` component to show a collapsed state when the breadcrumb is too long.
<ComponentPreview
styleName="base-nova"
name="breadcrumb-ellipsis"
className="[&_.preview]:p-2"
description="A breadcrumb showing a collapsed state."
@@ -175,6 +184,7 @@ import { BreadcrumbEllipsis } from "@/components/ui/breadcrumb"
To use a custom link component from your routing library, you can use the `asChild` prop on `<BreadcrumbLink />`.
<ComponentPreview
styleName="base-nova"
name="breadcrumb-link"
description="A breadcrumb with a custom Link component"
/>
@@ -205,6 +215,7 @@ Here's an example of a responsive breadcrumb that composes `<BreadcrumbItem />`
It displays a dropdown on desktop and a drawer on mobile.
<ComponentPreview
styleName="base-nova"
name="breadcrumb-responsive"
className="[&_.preview]:p-2"
description="A responsive breadcrumb. It displays a dropdown on desktop and a drawer on mobile."

View File

@@ -1,10 +1,11 @@
---
title: Button Group
description: A container that groups related buttons together with consistent styling.
base: base
component: true
---
<ComponentPreview name="button-group-demo" />
<ComponentPreview styleName="base-nova" name="button-group-demo" />
## Installation
@@ -34,7 +35,11 @@ npm install @radix-ui/react-slot
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="button-group" title="components/ui/button-group.tsx" />
<ComponentSource
name="button-group"
title="components/ui/button-group.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -85,19 +90,19 @@ import {
Set the `orientation` prop to change the button group layout.
<ComponentPreview name="button-group-orientation" />
<ComponentPreview styleName="base-nova" name="button-group-orientation" />
### Size
Control the size of buttons using the `size` prop on individual buttons.
<ComponentPreview name="button-group-size" />
<ComponentPreview styleName="base-nova" name="button-group-size" />
### Nested
Nest `<ButtonGroup>` components to create button groups with spacing.
<ComponentPreview name="button-group-nested" />
<ComponentPreview styleName="base-nova" name="button-group-nested" />
### 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.
<ComponentPreview name="button-group-separator" />
<ComponentPreview styleName="base-nova" name="button-group-separator" />
### Split
Create a split button group by adding two buttons separated by a `ButtonGroupSeparator`.
<ComponentPreview name="button-group-split" />
<ComponentPreview styleName="base-nova" name="button-group-split" />
### Input
Wrap an `Input` component with buttons.
<ComponentPreview name="button-group-input" />
<ComponentPreview styleName="base-nova" name="button-group-input" />
### Input Group
Wrap an `InputGroup` component to create complex input layouts.
<ComponentPreview name="button-group-input-group" />
<ComponentPreview styleName="base-nova" name="button-group-input-group" />
### Dropdown Menu
Create a split button group with a `DropdownMenu` component.
<ComponentPreview name="button-group-dropdown" />
<ComponentPreview styleName="base-nova" name="button-group-dropdown" />
### Select
Pair with a `Select` component.
<ComponentPreview name="button-group-select" />
<ComponentPreview styleName="base-nova" name="button-group-select" />
### Popover
Use with a `Popover` component.
<ComponentPreview name="button-group-popover" />
<ComponentPreview styleName="base-nova" name="button-group-popover" />
## API Reference

View File

@@ -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"
<Callout variant="info" icon={<InfoIcon />}>
**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.
</Callout>
<ComponentPreview
styleName="base-nova"
name="button-demo"
description="A button"
className="mb-4"
/>
```tsx showLineNumbers
<Button variant="outline">Button</Button>
<Button variant="outline" size="icon" aria-label="Submit">
<ArrowUpIcon />
</Button>
```
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add button
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-slot
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="button"
title="components/ui/button.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import { Button } from "@/components/ui/button"
```
```tsx
<Button variant="outline">Button</Button>
```
## Cursor
Tailwind v4 [switched](https://tailwindcss.com/docs/upgrade-guide#buttons-use-the-default-cursor) from `cursor: pointer` to `cursor: default` for the button component.
If you want to keep the `cursor: pointer` behavior, add the following code to your CSS file:
```css showLineNumbers title="globals.css"
@layer base {
button:not(:disabled),
[role="button"]:not(:disabled) {
cursor: pointer;
}
}
```
## Examples
### Size
<ComponentPreview styleName="base-nova" name="button-size" className="mb-4" />
```tsx
// Small
<Button size="sm" variant="outline">Small</Button>
<Button size="icon-sm" aria-label="Submit" variant="outline">
<ArrowUpRightIcon />
</Button>
// Medium
<Button variant="outline">Default</Button>
<Button size="icon" aria-label="Submit" variant="outline">
<ArrowUpRightIcon />
</Button>
// Large
<Button size="lg" variant="outline">Large</Button>
<Button size="icon-lg" aria-label="Submit" variant="outline">
<ArrowUpRightIcon />
</Button>
```
### Default
<ComponentPreview
styleName="base-nova"
name="button-default"
description="A primary button"
className="mb-4"
/>
```tsx
<Button>Button</Button>
```
### Outline
<ComponentPreview
styleName="base-nova"
name="button-outline"
description="A button using the outline variant."
className="mb-4"
/>
```tsx
<Button variant="outline">Outline</Button>
```
### Secondary
<ComponentPreview
styleName="base-nova"
name="button-secondary"
description="A secondary button"
className="mb-4"
/>
```tsx
<Button variant="secondary">Secondary</Button>
```
### Ghost
<ComponentPreview
styleName="base-nova"
name="button-ghost"
description="A button using the ghost variant"
className="mb-4"
/>
```tsx
<Button variant="ghost">Ghost</Button>
```
### Destructive
<ComponentPreview
styleName="base-nova"
name="button-destructive"
description="A destructive button"
className="mb-4"
/>
```tsx
<Button variant="destructive">Destructive</Button>
```
### Link
<ComponentPreview
styleName="base-nova"
name="button-link"
description="A button using the link variant."
className="mb-4"
/>
```tsx
<Button variant="link">Link</Button>
```
### Icon
<ComponentPreview
styleName="base-nova"
name="button-icon"
description="An icon button"
className="mb-4"
/>
```tsx showLineNumbers
<Button variant="outline" size="icon" aria-label="Submit">
<CircleFadingArrowUpIcon />
</Button>
```
### 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.
<ComponentPreview
styleName="base-nova"
name="button-with-icon"
description="A button with an icon"
className="mb-4"
/>
```tsx
<Button variant="outline" size="sm">
<IconGitBranch /> New Branch
</Button>
```
### Rounded
Use the `rounded-full` class to make the button rounded.
<ComponentPreview
styleName="base-nova"
name="button-rounded"
className="mb-4"
/>
```tsx
<Button variant="outline" size="icon" className="rounded-full">
<ArrowUpRightIcon />
</Button>
```
### Spinner
<ComponentPreview
styleName="base-nova"
name="button-loading"
description="A button with a loading state."
className="mb-4"
/>
```tsx showLineNumbers
<Button size="sm" variant="outline" disabled>
<Spinner />
Submit
</Button>
```
### Button Group
To create a button group, use the `ButtonGroup` component. See the [Button Group](/docs/components/button-group) documentation for more details.
<ComponentPreview
styleName="base-nova"
name="button-group-demo"
className="mb-4"
/>
```tsx showLineNumbers
<ButtonGroup>
<ButtonGroup>
<Button variant="outline" size="icon" aria-label="Go Back">
<ArrowLeftIcon />
</Button>
</ButtonGroup>
<ButtonGroup>
<Button variant="outline">Archive</Button>
<Button variant="outline">Report</Button>
</ButtonGroup>
<ButtonGroup>
<Button variant="outline">Snooze</Button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" size="icon" aria-label="More Options">
<MoreHorizontalIcon />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent />
</DropdownMenu>
</ButtonGroup>
</ButtonGroup>
```
### 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 (
<Button asChild>
<Link href="/login">Login</Link>
</Button>
)
}
```
## 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",
// ...
},
},
})
```

View File

@@ -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
---
<ComponentPreview
styleName="base-nova"
name="calendar-demo"
title="Calendar"
description="A calendar showing the current date."
@@ -50,7 +52,11 @@ The `Calendar` component uses the `Button` component. Make sure you have it inst
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="calendar" title="components/ui/calendar.tsx" />
<ComponentSource
name="calendar"
title="components/ui/calendar.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -103,6 +109,7 @@ To use the Persian calendar, edit `components/ui/calendar.tsx` and replace `reac
```
<ComponentPreview
styleName="base-nova"
name="calendar-hijri"
title="Persian / Hijri / Jalali Calendar"
description="A Persian calendar."
@@ -141,6 +148,7 @@ export function CalendarWithTimezone() {
### Range Calendar
<ComponentPreview
styleName="base-nova"
name="calendar-05"
title="Range Calendar"
description="A calendar showing the current date and range selection."
@@ -150,6 +158,7 @@ export function CalendarWithTimezone() {
### Month and Year Selector
<ComponentPreview
styleName="base-nova"
name="calendar-13"
title="Month and Year Selector"
description="A calendar with month and year dropdowns."
@@ -158,6 +167,7 @@ export function CalendarWithTimezone() {
### Date of Birth Picker
<ComponentPreview
styleName="base-nova"
name="calendar-22"
title="Date of Birth Picker"
description="A calendar with date of birth picker."
@@ -166,6 +176,7 @@ export function CalendarWithTimezone() {
### Date and Time Picker
<ComponentPreview
styleName="base-nova"
name="calendar-24"
title="Date and Time Picker"
description="A calendar with date and time picker."
@@ -176,6 +187,7 @@ export function CalendarWithTimezone() {
This component uses the `chrono-node` library to parse natural language dates.
<ComponentPreview
styleName="base-nova"
name="calendar-29"
title="Natural Language Picker"
description="A calendar with natural language picker."
@@ -184,6 +196,7 @@ This component uses the `chrono-node` library to parse natural language dates.
### Custom Cell Size
<ComponentPreview
styleName="base-nova"
name="calendar-18"
title="Custom Cell Size"
description="A calendar with custom cell size that's responsive."
@@ -448,7 +461,7 @@ function CalendarDayButton({
data-range-end={modifiers.range_end}
data-range-middle={modifiers.range_middle}
className={cn(
"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 font-normal leading-none data-[range-end=true]:rounded-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] [&>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
)}

View File

@@ -1,10 +1,15 @@
---
title: Card
description: Displays a card with header, content, and footer.
base: base
component: true
---
<ComponentPreview name="card-demo" description="A card with a form" />
<ComponentPreview
styleName="base-nova"
name="card-demo"
description="A card with a form"
/>
## Installation
@@ -28,7 +33,11 @@ npx shadcn@latest add card
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="card" title="components/ui/card.tsx" />
<ComponentSource
name="card"
title="components/ui/card.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -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:
---
<ComponentPreview
styleName="base-nova"
name="carousel-demo"
title="Carousel"
description="A carousel with 5 items and a previous and next button."
@@ -46,7 +48,11 @@ npm install embla-carousel-react
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="carousel" title="components/ui/carousel.tsx" />
<ComponentSource
name="carousel"
title="components/ui/carousel.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -87,6 +93,7 @@ import {
To set the size of the items, you can use the `basis` utility class on the `<CarouselItem />`.
<ComponentPreview
styleName="base-nova"
name="carousel-size"
title="Carousel"
description="A carousel with 3 active items of equal size."
@@ -129,6 +136,7 @@ You can always adjust this in your own project if you need to.
</Callout>
<ComponentPreview
styleName="base-nova"
name="carousel-spacing"
title="Carousel"
description="A carousel with 3 items with a spacing of 1rem."
@@ -159,6 +167,7 @@ You can always adjust this in your own project if you need to.
Use the `orientation` prop to set the orientation of the carousel.
<ComponentPreview
styleName="base-nova"
name="carousel-orientation"
title="Carousel"
description="A vertical carousel."
@@ -198,6 +207,7 @@ You can pass options to the carousel using the `opts` prop. See the [Embla Carou
Use a state and the `setApi` props to get an instance of the carousel API.
<ComponentPreview
styleName="base-nova"
name="carousel-api"
title="Carousel"
description="A carousel with a slide counter."
@@ -293,6 +303,7 @@ export function Example() {
```
<ComponentPreview
styleName="base-nova"
name="carousel-plugin"
title="Carousel"
description="A carousel with the autoplay plugin."

View File

@@ -1,6 +1,7 @@
---
title: Chart
description: Beautiful charts. Built using Recharts. Copy and paste into your apps.
base: base
component: true
---
@@ -11,6 +12,7 @@ component: true
</Callout>
<ComponentPreview
styleName="base-nova"
name="chart-bar-interactive"
className="theme-blue [&_.preview]:h-auto [&_.preview]:p-0 [&_.preview]:lg:min-h-[404px] [&_.preview>div]:w-full [&_.preview>div]:border-none [&_.preview>div]:shadow-none"
hideCode
@@ -111,7 +113,11 @@ npm install recharts
<Step>Copy and paste the following code into `components/ui/chart.tsx`.</Step>
<ComponentSource name="chart" title="components/ui/chart.tsx" />
<ComponentSource
name="chart"
title="components/ui/chart.tsx"
styleName="base-nova"
/>
<Step>Add the following colors to your CSS file</Step>
@@ -197,9 +203,14 @@ You can now build your chart using Recharts components.
</Callout>
<ComponentSource name="chart-bar-demo" title="components/example-chart.tsx" />
<ComponentSource
name="chart-bar-demo"
title="components/example-chart.tsx"
styleName="base-nova"
/>
<ComponentPreview
styleName="base-nova"
name="chart-bar-demo"
className="[&_.preview]:min-h-[250px] [&_.preview]:p-4"
/>
@@ -231,6 +242,7 @@ import { Bar, BarChart, CartesianGrid } from "recharts"
```
<ComponentPreview
styleName="base-nova"
name="chart-bar-demo-grid"
className="[&_.preview]:min-h-[250px] [&_.preview]:p-4"
/>
@@ -269,6 +281,7 @@ import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"
```
<ComponentPreview
styleName="base-nova"
name="chart-bar-demo-axis"
className="[&_.preview]:min-h-[250px] [&_.preview]:p-4"
/>
@@ -310,6 +323,7 @@ import { ChartTooltip, ChartTooltipContent } from "@/components/ui/chart"
```
<ComponentPreview
styleName="base-nova"
name="chart-bar-demo-tooltip"
className="[&_.preview]:min-h-[250px] [&_.preview]:p-4"
/>
@@ -352,6 +366,7 @@ import { ChartLegend, ChartLegendContent } from "@/components/ui/chart"
```
<ComponentPreview
styleName="base-nova"
name="chart-bar-demo-legend"
className="[&_.preview]:min-h-[250px] [&_.preview]:p-4"
/>
@@ -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.
<ComponentPreview
styleName="base-nova"
name="chart-tooltip-demo"
className="[&_.preview]:py-0"
hideCode

View File

@@ -1,13 +1,18 @@
---
title: Checkbox
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/checkbox
api: https://www.radix-ui.com/docs/primitives/components/checkbox#api-reference
---
<ComponentPreview name="checkbox-demo" description="A checkbox" />
<ComponentPreview
styleName="base-nova"
name="checkbox-demo"
description="A checkbox"
/>
## Installation
@@ -37,7 +42,11 @@ npm install @radix-ui/react-checkbox
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="checkbox" title="components/ui/checkbox.tsx" />
<ComponentSource
name="checkbox"
title="components/ui/checkbox.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -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:
---
<ComponentPreview
styleName="base-nova"
name="collapsible-demo"
description="A collapsible component."
/>
@@ -41,7 +43,11 @@ npm install @radix-ui/react-collapsible
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="collapsible" title="components/ui/collapsible.tsx" />
<ComponentSource
name="collapsible"
title="components/ui/collapsible.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -1,10 +1,12 @@
---
title: Combobox
description: Autocomplete input and command palette with a list of suggestions.
base: base
component: true
---
<ComponentPreview
styleName="base-nova"
name="combobox-demo"
description="A combobox with a list of frameworks."
/>
@@ -123,17 +125,19 @@ export function ExampleCombobox() {
### Combobox
<ComponentPreview
styleName="base-nova"
name="combobox-demo"
description="A combobox with a list of frameworks."
/>
### Popover
<ComponentPreview name="combobox-popover" />
<ComponentPreview styleName="base-nova" name="combobox-popover" />
### Dropdown menu
<ComponentPreview
styleName="base-nova"
name="combobox-dropdown-menu"
description="A combobox in a dropdown menu"
/>
@@ -142,4 +146,4 @@ export function ExampleCombobox() {
You can create a responsive combobox by using the `<Popover />` on desktop and the `<Drawer />` components on mobile.
<ComponentPreview name="combobox-responsive" />
<ComponentPreview styleName="base-nova" name="combobox-responsive" />

View File

@@ -1,12 +1,14 @@
---
title: Command
description: Fast, composable, unstyled command menu for React.
base: base
component: true
links:
doc: https://cmdk.paco.me
---
<ComponentPreview
styleName="base-nova"
name="command-demo"
align="start"
className="[&_.preview>div]:max-w-[450px]"
@@ -45,7 +47,11 @@ npm install cmdk
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="command" title="components/ui/command.tsx" />
<ComponentSource
name="command"
title="components/ui/command.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -96,6 +102,7 @@ import {
### Dialog
<ComponentPreview
styleName="base-nova"
name="command-dialog"
description="A command menu in a dialog"
/>

View File

@@ -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:
---
<ComponentPreview
styleName="base-nova"
name="context-menu-demo"
description="A context menu with sub menu items."
/>
@@ -40,7 +42,11 @@ npm install @radix-ui/react-context-menu
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="context-menu" title="components/ui/context-menu.tsx" />
<ComponentSource
name="context-menu"
title="components/ui/context-menu.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -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
---
<ComponentPreview name="data-table-demo" className="[&_.preview]:items-start" />
<ComponentPreview
styleName="base-nova"
name="data-table-demo"
className="[&_.preview]:items-start"
/>
## Introduction
@@ -856,7 +861,10 @@ export const columns = [
Add pagination controls to your table including page size and selection count.
<ComponentSource src="/app/(app)/examples/tasks/components/data-table-pagination.tsx" />
<ComponentSource
src="/app/(app)/examples/tasks/components/data-table-pagination.tsx"
styleName="base-nova"
/>
```tsx
<DataTablePagination table={table} />
@@ -866,7 +874,10 @@ Add pagination controls to your table including page size and selection count.
A component to toggle column visibility.
<ComponentSource src="/app/(app)/examples/tasks/components/data-table-view-options.tsx" />
<ComponentSource
src="/app/(app)/examples/tasks/components/data-table-view-options.tsx"
styleName="base-nova"
/>
```tsx
<DataTableViewOptions table={table} />

View File

@@ -1,10 +1,12 @@
---
title: Date Picker
description: A date picker component with range and presets.
base: base
component: true
---
<ComponentPreview
styleName="base-nova"
name="calendar-22"
title="Date of Birth Picker"
description="A calendar with date of birth picker."
@@ -64,6 +66,7 @@ See the [React DayPicker](https://react-day-picker.js.org) documentation for mor
### Date of Birth Picker
<ComponentPreview
styleName="base-nova"
name="calendar-22"
title="Date of Birth Picker"
description="A calendar with date of birth picker."
@@ -72,6 +75,7 @@ See the [React DayPicker](https://react-day-picker.js.org) documentation for mor
### Picker with Input
<ComponentPreview
styleName="base-nova"
name="calendar-28"
title="Picker with Input"
description="A calendar with input and picker."
@@ -80,6 +84,7 @@ See the [React DayPicker](https://react-day-picker.js.org) documentation for mor
### Date and Time Picker
<ComponentPreview
styleName="base-nova"
name="calendar-24"
title="Date and Time Picker"
description="A calendar with date and time picker."
@@ -90,6 +95,7 @@ See the [React DayPicker](https://react-day-picker.js.org) documentation for mor
This component uses the `chrono-node` library to parse natural language dates.
<ComponentPreview
styleName="base-nova"
name="calendar-29"
title="Natural Language Picker"
description="A calendar with natural language picker."

View File

@@ -2,6 +2,7 @@
title: Dialog
description: A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.
featured: true
base: base
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/dialog
@@ -9,6 +10,7 @@ links:
---
<ComponentPreview
styleName="base-nova"
name="dialog-demo"
description="A dialog for editing profile details."
/>
@@ -41,7 +43,11 @@ npm install @radix-ui/react-dialog
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="dialog" title="components/ui/dialog.tsx" />
<ComponentSource
name="dialog"
title="components/ui/dialog.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -83,7 +89,7 @@ import {
### Custom close button
<ComponentPreview name="dialog-close-button" />
<ComponentPreview styleName="base-nova" name="dialog-close-button" />
## Notes

View File

@@ -1,12 +1,17 @@
---
title: Drawer
description: A drawer component for React.
base: base
component: true
links:
doc: https://vaul.emilkowal.ski/getting-started
---
<ComponentPreview name="drawer-demo" description="A drawer component." />
<ComponentPreview
styleName="base-nova"
name="drawer-demo"
description="A drawer component."
/>
## About
@@ -40,7 +45,11 @@ npm install vaul
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="drawer" title="components/ui/drawer.tsx" />
<ComponentSource
name="drawer"
title="components/ui/drawer.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -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.
<ComponentPreview name="drawer-dialog" />
<ComponentPreview styleName="base-nova" name="drawer-dialog" />

View File

@@ -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:
---
<ComponentPreview
styleName="base-nova"
name="dropdown-menu-demo"
description="A dropdown menu with icons, shortcuts and sub menu items."
/>
@@ -41,7 +43,11 @@ npm install @radix-ui/react-dropdown-menu
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="dropdown-menu" title="components/ui/dropdown-menu.tsx" />
<ComponentSource
name="dropdown-menu"
title="components/ui/dropdown-menu.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -83,6 +89,7 @@ import {
### Checkboxes
<ComponentPreview
styleName="base-nova"
name="dropdown-menu-checkboxes"
description="A dropdown menu with checkboxes."
/>
@@ -90,6 +97,7 @@ import {
### Radio Group
<ComponentPreview
styleName="base-nova"
name="dropdown-menu-radio-group"
description="A dropdown menu with radio items."
/>
@@ -108,4 +116,4 @@ Use `modal={false}` on the `DropdownMenu` component.
</DropdownMenu>
```
<ComponentPreview name="dropdown-menu-dialog" />
<ComponentPreview styleName="base-nova" name="dropdown-menu-dialog" />

View File

@@ -1,10 +1,15 @@
---
title: Empty
description: Use the Empty component to display an empty state.
base: base
component: true
---
<ComponentPreview name="empty-demo" className="[&_.preview]:p-0" />
<ComponentPreview
styleName="base-nova"
name="empty-demo"
className="[&_.preview]:p-0"
/>
## Installation
@@ -28,7 +33,11 @@ npx shadcn@latest add empty
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="empty" title="components/ui/empty.tsx" />
<ComponentSource
name="empty"
title="components/ui/empty.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -73,6 +82,7 @@ import {
Use the `border` utility class to create an outline empty state.
<ComponentPreview
styleName="base-nova"
name="empty-outline"
className="[&_.preview]:p-6 md:[&_.preview]:p-10"
/>
@@ -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.
<ComponentPreview name="empty-background" className="[&_.preview]:p-0" />
<ComponentPreview
styleName="base-nova"
name="empty-background"
className="[&_.preview]:p-0"
/>
### Avatar
Use the `EmptyMedia` component to display an avatar in the empty state.
<ComponentPreview name="empty-avatar" className="[&_.preview]:p-0" />
<ComponentPreview
styleName="base-nova"
name="empty-avatar"
className="[&_.preview]:p-0"
/>
### Avatar Group
Use the `EmptyMedia` component to display an avatar group in the empty state.
<ComponentPreview name="empty-avatar-group" className="[&_.preview]:p-0" />
<ComponentPreview
styleName="base-nova"
name="empty-avatar-group"
className="[&_.preview]:p-0"
/>
### InputGroup
You can add an `InputGroup` component to the `EmptyContent` component.
<ComponentPreview name="empty-input-group" className="[&_.preview]:p-0" />
<ComponentPreview
styleName="base-nova"
name="empty-input-group"
className="[&_.preview]:p-0"
/>
## API Reference

View File

@@ -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
---
<ComponentPreview
styleName="base-nova"
name="field-demo"
className="[&_.preview]:h-[800px] [&_.preview]:p-6 md:[&_.preview]:h-[850px]"
/>
@@ -31,7 +33,11 @@ npx shadcn@latest add field
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="field" title="components/ui/field.tsx" />
<ComponentSource
name="field"
title="components/ui/field.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -106,47 +112,87 @@ See the [Form](/docs/forms) documentation for building forms with the `Field` co
### Input
<ComponentPreview name="field-input" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview
styleName="base-nova"
name="field-input"
className="!mb-4 [&_.preview]:p-6"
/>
### Textarea
<ComponentPreview name="field-textarea" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview
styleName="base-nova"
name="field-textarea"
className="!mb-4 [&_.preview]:p-6"
/>
### Select
<ComponentPreview name="field-select" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview
styleName="base-nova"
name="field-select"
className="!mb-4 [&_.preview]:p-6"
/>
### Slider
<ComponentPreview name="field-slider" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview
styleName="base-nova"
name="field-slider"
className="!mb-4 [&_.preview]:p-6"
/>
### Fieldset
<ComponentPreview name="field-fieldset" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview
styleName="base-nova"
name="field-fieldset"
className="!mb-4 [&_.preview]:p-6"
/>
### Checkbox
<ComponentPreview name="field-checkbox" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview
styleName="base-nova"
name="field-checkbox"
className="!mb-4 [&_.preview]:p-6"
/>
### Radio
<ComponentPreview name="field-radio" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview
styleName="base-nova"
name="field-radio"
className="!mb-4 [&_.preview]:p-6"
/>
### Switch
<ComponentPreview name="field-switch" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview
styleName="base-nova"
name="field-switch"
className="!mb-4 [&_.preview]:p-6"
/>
### Choice Card
Wrap `Field` components inside `FieldLabel` to create selectable field groups. This works with `RadioItem`, `Checkbox` and `Switch` components.
<ComponentPreview name="field-choice-card" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview
styleName="base-nova"
name="field-choice-card"
className="!mb-4 [&_.preview]:p-6"
/>
### Field Group
Stack `Field` components with `FieldGroup`. Add `FieldSeparator` to divide them.
<ComponentPreview name="field-group" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview
styleName="base-nova"
name="field-group"
className="!mb-4 [&_.preview]:p-6"
/>
## 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.
<ComponentPreview
styleName="base-nova"
name="field-responsive"
className="!mb-4 [&_.preview]:h-[650px] [&_.preview]:p-6 [&_.preview]:md:h-[500px] [&_.preview]:md:p-10"
/>

View File

@@ -115,7 +115,11 @@ npm install @radix-ui/react-label @radix-ui/react-slot react-hook-form @hookform
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="form" title="components/ui/form.tsx" />
<ComponentSource
name="form"
title="components/ui/form.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -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
---
<ComponentPreview name="hover-card-demo" description="A hover card component" />
<ComponentPreview
styleName="base-nova"
name="hover-card-demo"
description="A hover card component"
/>
## Installation
@@ -37,7 +42,11 @@ npm install @radix-ui/react-hover-card
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="hover-card" title="components/ui/hover-card.tsx" />
<ComponentSource
name="hover-card"
title="components/ui/hover-card.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -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"
<ComponentPreview name="input-group-demo" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="input-group-demo"
className="[&_.preview]:p-4"
/>
## Installation
@@ -30,7 +35,11 @@ npx shadcn@latest add input-group
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="input-group" title="components/ui/input-group.tsx" />
<ComponentSource
name="input-group"
title="components/ui/input-group.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -69,55 +78,88 @@ import {
### Icon
<ComponentPreview name="input-group-icon" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="input-group-icon"
className="[&_.preview]:p-4"
/>
### Text
Display additional text information alongside inputs.
<ComponentPreview name="input-group-text" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="input-group-text"
className="[&_.preview]:p-4"
/>
### Button
Add buttons to perform actions within the input group.
<ComponentPreview name="input-group-button" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="input-group-button"
className="[&_.preview]:p-4"
/>
### Tooltip
Add tooltips to provide additional context or help.
<ComponentPreview name="input-group-tooltip" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="input-group-tooltip"
className="[&_.preview]:p-4"
/>
### Textarea
Input groups also work with textarea components. Use `block-start` or `block-end` for alignment.
<ComponentPreview name="input-group-textarea" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="input-group-textarea"
className="[&_.preview]:p-4"
/>
### Spinner
Show loading indicators while processing input.
<ComponentPreview name="input-group-spinner" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="input-group-spinner"
className="[&_.preview]:p-4"
/>
### Label
Add labels within input groups to improve accessibility.
<ComponentPreview name="input-group-label" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="input-group-label"
className="[&_.preview]:p-4"
/>
### Dropdown
Pair input groups with dropdown menus for complex interactions.
<ComponentPreview name="input-group-dropdown" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="input-group-dropdown"
className="[&_.preview]:p-4"
/>
### Button Group
Wrap input groups with button groups to create prefixes and suffixes.
<ComponentPreview
styleName="base-nova"
name="input-group-button-group"
className="[&_.preview]:p-4"
/>
@@ -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.
<ComponentPreview
styleName="base-nova"
name="input-group-custom"
className="!mb-4 [&_.preview]:p-4"
/>

View File

@@ -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
---
<ComponentPreview name="input-otp-demo" description="An 6 digits input OTP." />
<ComponentPreview
styleName="base-nova"
name="input-otp-demo"
description="An 6 digits input OTP."
/>
## About
@@ -46,7 +51,11 @@ npm install input-otp
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="input-otp" title="components/ui/input-otp.tsx" />
<ComponentSource
name="input-otp"
title="components/ui/input-otp.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -90,6 +99,7 @@ import {
Use the `pattern` prop to define a custom pattern for the OTP input.
<ComponentPreview
styleName="base-nova"
name="input-otp-pattern"
description="An input OTP with alphanumeric pattern."
/>
@@ -115,6 +125,7 @@ import { REGEXP_ONLY_DIGITS_AND_CHARS } from "input-otp"
You can use the `<InputOTPSeparator />` component to add a separator between the input groups.
<ComponentPreview
styleName="base-nova"
name="input-otp-separator"
description="An input OTP with custom separator."
/>
@@ -146,11 +157,11 @@ import {
You can use the `value` and `onChange` props to control the input value.
<ComponentPreview name="input-otp-controlled" />
<ComponentPreview styleName="base-nova" name="input-otp-controlled" />
### Form
<ComponentPreview name="input-otp-form" />
<ComponentPreview styleName="base-nova" name="input-otp-form" />
## Changelog

View File

@@ -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
---
<ComponentPreview
styleName="base-nova"
name="input-demo"
className="[&_input]:max-w-xs"
description="A form input component."
@@ -32,7 +34,11 @@ npx shadcn@latest add input
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="input" title="components/ui/input.tsx" />
<ComponentSource
name="input"
title="components/ui/input.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -57,6 +63,7 @@ import { Input } from "@/components/ui/input"
### Default
<ComponentPreview
styleName="base-nova"
name="input-demo"
className="[&_input]:max-w-xs"
description="A form input component."
@@ -65,6 +72,7 @@ import { Input } from "@/components/ui/input"
### File
<ComponentPreview
styleName="base-nova"
name="input-file"
className="[&_input]:max-w-xs"
description="A file input component."
@@ -73,6 +81,7 @@ import { Input } from "@/components/ui/input"
### Disabled
<ComponentPreview
styleName="base-nova"
name="input-disabled"
className="[&_input]:max-w-xs"
description="A disabled input component."
@@ -81,6 +90,7 @@ import { Input } from "@/components/ui/input"
### With Label
<ComponentPreview
styleName="base-nova"
name="input-with-label"
className="[&_input]:max-w-xs"
description="An input component with a label."
@@ -89,6 +99,7 @@ import { Input } from "@/components/ui/input"
### With Button
<ComponentPreview
styleName="base-nova"
name="input-with-button"
className="[&_input]:max-w-xs"
description="An input component with a button."

View File

@@ -1,6 +1,7 @@
---
title: Item
description: A versatile component that you can use to display any content.
base: base
component: true
---
@@ -8,7 +9,11 @@ The `Item` component is a straightforward flex container that can house nearly a
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.
<ComponentPreview name="item-demo" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="item-demo"
className="[&_.preview]:p-4"
/>
## Installation
@@ -32,7 +37,11 @@ npx shadcn@latest add item
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="item" title="components/ui/item.tsx" />
<ComponentSource
name="item"
title="components/ui/item.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -80,39 +89,71 @@ If you only need to display content such as a title, description, and actions, u
### Variants
<ComponentPreview name="item-variant" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="item-variant"
className="[&_.preview]:p-4"
/>
### 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.
<ComponentPreview name="item-size" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="item-size"
className="[&_.preview]:p-4"
/>
### Icon
<ComponentPreview name="item-icon" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="item-icon"
className="[&_.preview]:p-4"
/>
### Avatar
<ComponentPreview name="item-avatar" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="item-avatar"
className="[&_.preview]:p-4"
/>
### Image
<ComponentPreview name="item-image" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="item-image"
className="[&_.preview]:p-4"
/>
### Group
<ComponentPreview name="item-group" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="item-group"
className="[&_.preview]:p-4"
/>
### Header
<ComponentPreview name="item-header" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="item-header"
className="[&_.preview]:p-4"
/>
### Link
To render an item as a link, use the `asChild` prop. The hover and focus states will be applied to the anchor element.
<ComponentPreview name="item-link" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="item-link"
className="[&_.preview]:p-4"
/>
```tsx showLineNumbers
<Item asChild>
@@ -129,7 +170,11 @@ To render an item as a link, use the `asChild` prop. The hover and focus states
### Dropdown
<ComponentPreview name="item-dropdown" className="[&_.preview]:p-4" />
<ComponentPreview
styleName="base-nova"
name="item-dropdown"
className="[&_.preview]:p-4"
/>
## API Reference

View File

@@ -1,10 +1,11 @@
---
title: Kbd
description: Used to display textual user input from keyboard.
base: base
component: true
---
<ComponentPreview name="kbd-demo" />
<ComponentPreview styleName="base-nova" name="kbd-demo" />
## Installation
@@ -28,7 +29,11 @@ npx shadcn@latest add kbd
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="kbd" title="components/ui/kbd.tsx" />
<ComponentSource
name="kbd"
title="components/ui/kbd.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -54,25 +59,25 @@ import { Kbd } from "@/components/ui/kbd"
Use the `KbdGroup` component to group keyboard keys together.
<ComponentPreview name="kbd-group" />
<ComponentPreview styleName="base-nova" name="kbd-group" />
### Button
Use the `Kbd` component inside a `Button` component to display a keyboard key inside a button.
<ComponentPreview name="kbd-button" />
<ComponentPreview styleName="base-nova" name="kbd-button" />
### Tooltip
You can use the `Kbd` component inside a `Tooltip` component to display a tooltip with a keyboard key.
<ComponentPreview name="kbd-tooltip" />
<ComponentPreview styleName="base-nova" name="kbd-tooltip" />
### Input Group
You can use the `Kbd` component inside a `InputGroupAddon` component to display a keyboard key inside an input group.
<ComponentPreview name="kbd-input-group" />
<ComponentPreview styleName="base-nova" name="kbd-input-group" />
## API Reference

View File

@@ -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
---
<ComponentPreview name="label-demo" description="A label" />
<ComponentPreview
styleName="base-nova"
name="label-demo"
description="A label"
/>
## Installation
@@ -37,7 +42,11 @@ npm install @radix-ui/react-label
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="label" title="components/ui/label.tsx" />
<ComponentSource
name="label"
title="components/ui/label.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -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
---
<ComponentPreview name="menubar-demo" description="A menubar component." />
<ComponentPreview
styleName="base-nova"
name="menubar-demo"
description="A menubar component."
/>
## Installation
@@ -37,7 +42,11 @@ npm install @radix-ui/react-menubar
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="menubar" title="components/ui/menubar.tsx" />
<ComponentSource
name="menubar"
title="components/ui/menubar.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -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"
]
}

View File

@@ -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.
</Callout>
<ComponentPreview name="native-select-demo" />
<ComponentPreview styleName="base-nova" name="native-select-demo" />
## Installation
@@ -35,7 +36,11 @@ npx shadcn@latest add native-select
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="native-select" title="components/ui/native-select.tsx" />
<ComponentSource
name="native-select"
title="components/ui/native-select.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -74,7 +79,7 @@ import {
Organize options using `NativeSelectOptGroup` for better categorization.
<ComponentPreview name="native-select-groups" />
<ComponentPreview styleName="base-nova" name="native-select-groups" />
```tsx showLineNumbers
<NativeSelect>
@@ -96,13 +101,13 @@ Organize options using `NativeSelectOptGroup` for better categorization.
Disable individual options or the entire select component.
<ComponentPreview name="native-select-disabled" />
<ComponentPreview styleName="base-nova" name="native-select-disabled" />
### Invalid State
Show validation errors with the `aria-invalid` attribute and error styling.
<ComponentPreview name="native-select-invalid" />
<ComponentPreview styleName="base-nova" name="native-select-invalid" />
```tsx showLineNumbers
<NativeSelect aria-invalid="true">
@@ -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.
<ComponentPreview name="native-select-form" />
<ComponentPreview styleName="base-nova" name="native-select-form" />
### Input Group Integration
Combine with `InputGroup` for complex input layouts.
<ComponentPreview name="native-select-input-group" />
<ComponentPreview styleName="base-nova" name="native-select-input-group" />
## Native Select vs Select

View File

@@ -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:
---
<ComponentPreview
styleName="base-nova"
name="navigation-menu-demo"
className="[&_.preview]:!items-start [&_.preview]:p-4 [&_.preview]:pt-8 md:[&_.preview]:pt-16"
/>

View File

@@ -1,10 +1,12 @@
---
title: Pagination
description: Pagination with page navigation, next and previous links.
base: base
component: true
---
<ComponentPreview
styleName="base-nova"
name="pagination-demo"
description="A pagination with previous and next links."
/>
@@ -31,7 +33,11 @@ npx shadcn@latest add pagination
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="pagination" title="components/ui/pagination.tsx" />
<ComponentSource
name="pagination"
title="components/ui/pagination.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -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:
---
<ComponentPreview
styleName="base-nova"
name="popover-demo"
description="A popover component with a form."
/>
@@ -40,7 +42,11 @@ npm install @radix-ui/react-popover
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="popover" title="components/ui/popover.tsx" />
<ComponentSource
name="popover"
title="components/ui/popover.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -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:
---
<ComponentPreview
styleName="base-nova"
name="progress-demo"
description="A progress bar component."
/>
@@ -40,7 +42,11 @@ npm install @radix-ui/react-progress
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="progress" title="components/ui/progress.tsx" />
<ComponentSource
name="progress"
title="components/ui/progress.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -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:
---
<ComponentPreview
styleName="base-nova"
name="radio-group-demo"
description="A radio group with 3 items."
/>
@@ -40,7 +42,11 @@ npm install @radix-ui/react-radio-group
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="radio-group" title="components/ui/radio-group.tsx" />
<ComponentSource
name="radio-group"
title="components/ui/radio-group.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -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:
---
<ComponentPreview
styleName="base-nova"
name="resizable-demo"
description="A group of resizable horizontal and vertical panels."
/>
@@ -44,7 +46,11 @@ npm install react-resizable-panels
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="resizable" title="components/ui/resizable.tsx" />
<ComponentSource
name="resizable"
title="components/ui/resizable.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -79,6 +85,7 @@ import {
Use the `direction` prop to set the direction of the resizable panels.
<ComponentPreview
styleName="base-nova"
name="resizable-vertical"
description="A group of resizable vertical 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.
<ComponentPreview
styleName="base-nova"
name="resizable-handle"
description="A group of resizable panels with a handle."
/>

View File

@@ -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:
---
<ComponentPreview
styleName="base-nova"
name="scroll-area-demo"
description="A scroll area component."
/>
@@ -40,7 +42,11 @@ npm install @radix-ui/react-scroll-area
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="scroll-area" title="components/ui/scroll-area.tsx" />
<ComponentSource
name="scroll-area"
title="components/ui/scroll-area.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -71,4 +77,4 @@ import { ScrollArea } from "@/components/ui/scroll-area"
### Horizontal Scrolling
<ComponentPreview name="scroll-area-horizontal-demo" />
<ComponentPreview styleName="base-nova" name="scroll-area-horizontal-demo" />

View File

@@ -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:
---
<ComponentPreview
styleName="base-nova"
name="select-demo"
description="A select component with a list of options."
/>
@@ -41,7 +43,11 @@ npm install @radix-ui/react-select
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="select" title="components/ui/select.tsx" />
<ComponentSource
name="select"
title="components/ui/select.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -81,6 +87,7 @@ import {
### Scrollable
<ComponentPreview
styleName="base-nova"
name="select-scrollable"
description="A select component with a scrollable list of options."
/>

View File

@@ -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
---
<ComponentPreview name="separator-demo" description="A separator component." />
<ComponentPreview
styleName="base-nova"
name="separator-demo"
description="A separator component."
/>
## Installation
@@ -36,7 +41,11 @@ npm install @radix-ui/react-separator
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="separator" title="components/ui/separator.tsx" />
<ComponentSource
name="separator"
title="components/ui/separator.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -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
---
<ComponentPreview name="sheet-demo" description="A sheet component." />
<ComponentPreview
styleName="base-nova"
name="sheet-demo"
description="A sheet component."
/>
## Installation
@@ -37,7 +42,11 @@ npm install @radix-ui/react-dialog
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="sheet" title="components/ui/sheet.tsx" />
<ComponentSource
name="sheet"
title="components/ui/sheet.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -1,11 +1,13 @@
---
title: Sidebar
description: A composable, themeable and customizable sidebar component.
base: base
component: true
---
<figure className="flex flex-col gap-4">
<ComponentPreview
styleName="base-nova"
name="sidebar-07"
title="Sidebar"
type="block"
@@ -88,7 +90,11 @@ We'll go over the colors later in the [theming section](/docs/components/sidebar
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="sidebar" title="components/ui/sidebar.tsx" />
<ComponentSource
name="sidebar"
title="components/ui/sidebar.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -317,6 +323,7 @@ You should see something like this:
<figure className="flex flex-col gap-4">
<ComponentPreview
styleName="base-nova"
name="sidebar-demo"
title="Sidebar"
type="block"
@@ -542,6 +549,7 @@ The following example adds a `<DropdownMenu>` to the `SidebarHeader`.
<figure className="mt-6 flex flex-col gap-4">
<ComponentPreview
styleName="base-nova"
name="sidebar-header"
title="Sidebar"
type="block"
@@ -588,6 +596,7 @@ The following example adds a `<DropdownMenu>` to the `SidebarFooter`.
<figure className="mt-6 flex flex-col gap-4">
<ComponentPreview
styleName="base-nova"
name="sidebar-footer"
title="Sidebar"
type="block"
@@ -667,6 +676,7 @@ A `SidebarGroup` has a `SidebarGroupLabel`, a `SidebarGroupContent` and an optio
<figure className="mt-6 flex flex-col gap-4">
<ComponentPreview
styleName="base-nova"
name="sidebar-group"
title="Sidebar Group"
type="block"
@@ -704,6 +714,7 @@ To make a `SidebarGroup` collapsible, wrap it in a `Collapsible`.
<figure className="mt-6 flex flex-col gap-4">
<ComponentPreview
styleName="base-nova"
name="sidebar-group-collapsible"
title="Sidebar Group"
type="block"
@@ -746,6 +757,7 @@ Use the `SidebarGroupAction` component to add an action button to the `SidebarGr
<figure className="flex flex-col gap-4">
<ComponentPreview
styleName="base-nova"
name="sidebar-group-action"
title="Sidebar Group"
type="block"
@@ -796,6 +808,7 @@ Here's an example of a `SidebarMenu` component rendering a list of projects.
<figure className="mt-6 flex flex-col gap-4">
<ComponentPreview
styleName="base-nova"
name="sidebar-menu"
title="Sidebar Menu"
type="block"
@@ -894,6 +907,7 @@ Here's an example of a `SidebarMenuAction` component rendering a `DropdownMenu`.
<figure className="mt-6 flex flex-col gap-4">
<ComponentPreview
styleName="base-nova"
name="sidebar-menu-action"
title="Sidebar Menu Action"
type="block"
@@ -939,6 +953,7 @@ Use `<SidebarMenuSubItem />` and `<SidebarMenuSubButton />` to render a submenu
<figure className="mt-6 flex flex-col gap-4">
<ComponentPreview
styleName="base-nova"
name="sidebar-menu-sub"
title="Sidebar Menu Sub"
type="block"
@@ -970,6 +985,7 @@ To make a `SidebarMenu` component collapsible, wrap it and the `SidebarMenuSub`
<figure className="mt-6 flex flex-col gap-4">
<ComponentPreview
styleName="base-nova"
name="sidebar-menu-collapsible"
title="Sidebar Menu"
type="block"
@@ -1004,6 +1020,7 @@ The `SidebarMenuBadge` component is used to render a badge within a `SidebarMenu
<figure className="mt-6 flex flex-col gap-4">
<ComponentPreview
styleName="base-nova"
name="sidebar-menu-badge"
title="Sidebar Menu Badge"
type="block"
@@ -1108,6 +1125,7 @@ Here's an example of a `SidebarMenu` component rendering a list of projects usin
<figure className="mt-6 flex flex-col gap-4">
<ComponentPreview
styleName="base-nova"
name="sidebar-rsc"
title="Sidebar Menu RSC"
type="block"
@@ -1257,6 +1275,7 @@ Use the `open` and `onOpenChange` props to control the sidebar.
<figure className="mt-6 flex flex-col gap-4">
<ComponentPreview
styleName="base-nova"
name="sidebar-controlled"
title="Sidebar Controlled"
type="block"

View File

@@ -1,10 +1,15 @@
---
title: Skeleton
description: Use to show a placeholder while content is loading.
base: base
component: true
---
<ComponentPreview name="skeleton-demo" description="A skeleton component." />
<ComponentPreview
styleName="base-nova"
name="skeleton-demo"
description="A skeleton component."
/>
## Installation
@@ -28,7 +33,11 @@ npx shadcn@latest add skeleton
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="skeleton" title="components/ui/skeleton.tsx" />
<ComponentSource
name="skeleton"
title="components/ui/skeleton.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -53,6 +62,7 @@ import { Skeleton } from "@/components/ui/skeleton"
### Card
<ComponentPreview
styleName="base-nova"
name="skeleton-card"
description="A card with skeleton showing a loading state."
/>

View File

@@ -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
---
<ComponentPreview name="slider-demo" description="A slider component." />
<ComponentPreview
styleName="base-nova"
name="slider-demo"
description="A slider component."
/>
## Installation
@@ -37,7 +42,11 @@ npm install @radix-ui/react-slider
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="slider" title="components/ui/slider.tsx" />
<ComponentSource
name="slider"
title="components/ui/slider.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -1,12 +1,13 @@
---
title: Sonner
description: An opinionated toast component for React.
base: base
component: true
links:
doc: https://sonner.emilkowal.ski
---
<ComponentPreview name="sonner-demo" />
<ComponentPreview styleName="base-nova" name="sonner-demo" />
## About
@@ -64,7 +65,11 @@ npm install sonner next-themes
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="sonner" title="components/ui/sonner.tsx" />
<ComponentSource
name="sonner"
title="components/ui/sonner.tsx"
styleName="base-nova"
/>
<Step>Add the Toaster component</Step>
@@ -102,7 +107,7 @@ toast("Event has been created.")
## Examples
<ComponentPreview name="sonner-types" />
<ComponentPreview styleName="base-nova" name="sonner-types" />
## Changelog

View File

@@ -1,10 +1,15 @@
---
title: Spinner
description: An indicator that can be used to show a loading state.
base: base
component: true
---
<ComponentPreview name="spinner-demo" className="[&_.preview]:p-6" />
<ComponentPreview
styleName="base-nova"
name="spinner-demo"
className="[&_.preview]:p-6"
/>
## Installation
@@ -28,7 +33,11 @@ npx shadcn@latest add spinner
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="spinner" title="components/ui/spinner.tsx" />
<ComponentSource
name="spinner"
title="components/ui/spinner.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -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.
<ComponentPreview name="spinner-custom" />
<ComponentPreview styleName="base-nova" name="spinner-custom" />
```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.
<ComponentPreview name="spinner-size" />
<ComponentPreview styleName="base-nova" name="spinner-size" />
### Color
Use the `text-` utility class to change the color of the spinner.
<ComponentPreview name="spinner-color" />
<ComponentPreview styleName="base-nova" name="spinner-color" />
### Button
Add a spinner to a button to indicate a loading state. The `<Button />` will handle the spacing between the spinner and the text.
<ComponentPreview name="spinner-button" />
<ComponentPreview styleName="base-nova" name="spinner-button" />
### Badge
You can also use a spinner inside a badge.
<ComponentPreview name="spinner-badge" />
<ComponentPreview styleName="base-nova" name="spinner-badge" />
### Input Group
Input Group can have spinners inside `<InputGroupAddon>`.
<ComponentPreview name="spinner-input-group" />
<ComponentPreview styleName="base-nova" name="spinner-input-group" />
### Empty
<ComponentPreview name="spinner-empty" />
<ComponentPreview styleName="base-nova" name="spinner-empty" />
### Item
Use the spinner inside `<ItemMedia>` to indicate a loading state.
<ComponentPreview name="spinner-item" />
<ComponentPreview styleName="base-nova" name="spinner-item" />
## API Reference

View File

@@ -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
---
<ComponentPreview name="switch-demo" description="A switch component." />
<ComponentPreview
styleName="base-nova"
name="switch-demo"
description="A switch component."
/>
## Installation
@@ -37,7 +42,11 @@ npm install @radix-ui/react-switch
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="switch" title="components/ui/switch.tsx" />
<ComponentSource
name="switch"
title="components/ui/switch.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -1,10 +1,15 @@
---
title: Table
description: A responsive table component.
base: base
component: true
---
<ComponentPreview name="table-demo" description="A table component." />
<ComponentPreview
styleName="base-nova"
name="table-demo"
description="A table component."
/>
## Installation
@@ -28,7 +33,11 @@ npx shadcn@latest add table
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="table" title="components/ui/table.tsx" />
<ComponentSource
name="table"
title="components/ui/table.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -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:
---
<ComponentPreview
styleName="base-nova"
name="tabs-demo"
description="A tabs component with two forms."
/>
@@ -40,7 +42,11 @@ npm install @radix-ui/react-tabs
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="tabs" title="components/ui/tabs.tsx" />
<ComponentSource
name="tabs"
title="components/ui/tabs.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -1,10 +1,15 @@
---
title: Textarea
description: Displays a form textarea or a component that looks like a textarea.
base: base
component: true
---
<ComponentPreview name="textarea-demo" description="A textarea" />
<ComponentPreview
styleName="base-nova"
name="textarea-demo"
description="A textarea"
/>
## Installation
@@ -28,7 +33,11 @@ npx shadcn@latest add textarea
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="textarea" title="components/ui/textarea.tsx" />
<ComponentSource
name="textarea"
title="components/ui/textarea.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -52,15 +61,24 @@ import { Textarea } from "@/components/ui/textarea"
### Default
<ComponentPreview name="textarea-demo" description="A textarea" />
<ComponentPreview
styleName="base-nova"
name="textarea-demo"
description="A textarea"
/>
### Disabled
<ComponentPreview name="textarea-disabled" description="A disabled textarea" />
<ComponentPreview
styleName="base-nova"
name="textarea-disabled"
description="A disabled textarea"
/>
### With Label
<ComponentPreview
styleName="base-nova"
name="textarea-with-label"
className="[&_div.grid]:w-full"
description="A textarea with a label"
@@ -69,6 +87,7 @@ import { Textarea } from "@/components/ui/textarea"
### With Text
<ComponentPreview
styleName="base-nova"
name="textarea-with-text"
description="A textarea with text"
/>
@@ -76,6 +95,7 @@ import { Textarea } from "@/components/ui/textarea"
### With Button
<ComponentPreview
styleName="base-nova"
name="textarea-with-button"
description="A textarea with a button"
/>

View File

@@ -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

View File

@@ -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
---
<ComponentPreview name="toggle-group-spacing" />
<ComponentPreview styleName="base-nova" name="toggle-group-spacing" />
## Installation
@@ -37,7 +38,11 @@ npm install @radix-ui/react-toggle-group
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="toggle-group" title="components/ui/toggle-group.tsx" />
<ComponentSource
name="toggle-group"
title="components/ui/toggle-group.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -66,6 +71,7 @@ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
### Outline
<ComponentPreview
styleName="base-nova"
name="toggle-group-outline"
description="A toggle group using the outline variant."
/>
@@ -73,6 +79,7 @@ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
### Single
<ComponentPreview
styleName="base-nova"
name="toggle-group-single"
description="A toggle group with single selection."
/>
@@ -80,6 +87,7 @@ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
### Small
<ComponentPreview
styleName="base-nova"
name="toggle-group-sm"
description="A toggle group using the small size."
/>
@@ -87,6 +95,7 @@ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
### Large
<ComponentPreview
styleName="base-nova"
name="toggle-group-lg"
description="A toggle group using the large size."
/>
@@ -94,6 +103,7 @@ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
### Disabled
<ComponentPreview
styleName="base-nova"
name="toggle-group-disabled"
description="A disabled toggle group."
/>
@@ -103,6 +113,7 @@ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
Use `spacing={2}` to add spacing between toggle group items.
<ComponentPreview
styleName="base-nova"
name="toggle-group-spacing"
description="A toggle group with spacing."
/>

View File

@@ -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
---
<ComponentPreview name="toggle-demo" description="A toggle component." />
<ComponentPreview
styleName="base-nova"
name="toggle-demo"
description="A toggle component."
/>
## Installation
@@ -37,7 +42,11 @@ npm install @radix-ui/react-toggle
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="toggle" title="components/ui/toggle.tsx" />
<ComponentSource
name="toggle"
title="components/ui/toggle.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -61,11 +70,16 @@ import { Toggle } from "@/components/ui/toggle"
### Default
<ComponentPreview name="toggle-demo" description="A toggle component." />
<ComponentPreview
styleName="base-nova"
name="toggle-demo"
description="A toggle component."
/>
### Outline
<ComponentPreview
styleName="base-nova"
name="toggle-outline"
description="A toggle component using the outline variant."
/>
@@ -73,21 +87,31 @@ import { Toggle } from "@/components/ui/toggle"
### With Text
<ComponentPreview
styleName="base-nova"
name="toggle-with-text"
description="A toggle component with text."
/>
### Small
<ComponentPreview name="toggle-sm" description="A small toggle component." />
<ComponentPreview
styleName="base-nova"
name="toggle-sm"
description="A small toggle component."
/>
### Large
<ComponentPreview name="toggle-lg" description="A large toggle component." />
<ComponentPreview
styleName="base-nova"
name="toggle-lg"
description="A large toggle component."
/>
### Disabled
<ComponentPreview
styleName="base-nova"
name="toggle-disabled"
description="A disabled toggle component."
/>

View File

@@ -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
---
<ComponentPreview name="tooltip-demo" description="A tooltip component." />
<ComponentPreview
styleName="base-nova"
name="tooltip-demo"
description="A tooltip component."
/>
## Installation
@@ -37,7 +42,11 @@ npm install @radix-ui/react-tooltip
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="tooltip" title="components/ui/tooltip.tsx" />
<ComponentSource
name="tooltip"
title="components/ui/tooltip.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>

View File

@@ -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.
<ComponentPreview
styleName="base-nova"
name="typography-demo"
description="A collection of typographic elements."
className="[&_.preview]:!h-auto"
hideCode
/>
## h1
<ComponentPreview styleName="base-nova" name="typography-h1" />
## h2
<ComponentPreview styleName="base-nova" name="typography-h2" />
## h3
<ComponentPreview styleName="base-nova" name="typography-h3" />
## h4
<ComponentPreview styleName="base-nova" name="typography-h4" />
## p
<ComponentPreview styleName="base-nova" name="typography-p" />
## blockquote
<ComponentPreview styleName="base-nova" name="typography-blockquote" />
## table
<ComponentPreview styleName="base-nova" name="typography-table" />
## list
<ComponentPreview styleName="base-nova" name="typography-list" />
## Inline code
<ComponentPreview styleName="base-nova" name="typography-inline-code" />
## Lead
<ComponentPreview styleName="base-nova" name="typography-lead" />
## Large
<ComponentPreview styleName="base-nova" name="typography-large" />
## Small
<ComponentPreview styleName="base-nova" name="typography-small" />
## Muted
<ComponentPreview styleName="base-nova" name="typography-muted" />

View File

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

View File

@@ -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
---
<ComponentPreview
styleName="radix-nova"
name="accordion-demo"
className="[&_.preview>[data-orientation=vertical]]:sm:max-w-[80%] **:[.preview]:min-h-[400px]"
description="An accordion with three items"
align="start"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add accordion
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-accordion
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="accordion"
title="components/ui/accordion.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion"
```
```tsx showLineNumbers
<Accordion type="single" collapsible>
<AccordionItem value="item-1">
<AccordionTrigger>Is it accessible?</AccordionTrigger>
<AccordionContent>
Yes. It adheres to the WAI-ARIA design pattern.
</AccordionContent>
</AccordionItem>
</Accordion>
```

View File

@@ -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
---
<ComponentPreview
styleName="radix-nova"
name="alert-dialog-demo"
title="An alert dialog with cancel and continue buttons."
description="An alert dialog with cancel and continue buttons."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add alert-dialog
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-alert-dialog
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="alert-dialog"
title="components/ui/alert-dialog.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog"
```
```tsx showLineNumbers
<AlertDialog>
<AlertDialogTrigger>Open</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
<AlertDialogDescription>
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction>Continue</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
```

View File

@@ -0,0 +1,65 @@
---
title: Alert
description: Displays a callout for user attention.
base: radix
component: true
---
<ComponentPreview
styleName="radix-nova"
name="alert-demo"
title="An alert with an icon, title and description."
description="An alert with an icon, title and description. The title says 'Heads up!' and the description is 'You can add components to your app using the cli.'."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add alert
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="alert"
title="components/ui/alert.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
```
```tsx showLineNumbers
<Alert variant="default | destructive">
<Terminal />
<AlertTitle>Heads up!</AlertTitle>
<AlertDescription>
You can add components and dependencies to your app using the cli.
</AlertDescription>
</Alert>
```

View File

@@ -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
---
<ComponentPreview
styleName="radix-nova"
name="aspect-ratio-demo"
title="Aspect Ratio"
description="A component that displays an image with a 16:9 aspect ratio."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add aspect-ratio
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-aspect-ratio
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="aspect-ratio"
title="components/ui/aspect-ratio.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { AspectRatio } from "@/components/ui/aspect-ratio"
```
```tsx showLineNumbers
<AspectRatio ratio={16 / 9}>
<Image src="..." alt="Image" className="rounded-md object-cover" />
</AspectRatio>
```

View File

@@ -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
---
<ComponentPreview
styleName="radix-nova"
name="avatar-demo"
title="Avatar"
description="An avatar with a fallback."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add avatar
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-avatar
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="avatar"
title="components/ui/avatar.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
```
```tsx showLineNumbers
<Avatar>
<AvatarImage src="https://github.com/shadcn.png" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
```

View File

@@ -0,0 +1,77 @@
---
title: Badge
description: Displays a badge or a component that looks like a badge.
base: radix
component: true
---
<ComponentPreview
styleName="radix-nova"
name="badge-demo"
title="Badge"
description="A default badge"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add badge
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="badge"
title="components/ui/badge.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import { Badge } from "@/components/ui/badge"
```
```tsx
<Badge variant="default | outline | secondary | destructive">Badge</Badge>
```
### 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 asChild>
<Link href="/">Badge</Link>
</Badge>
)
}
```

View File

@@ -0,0 +1,222 @@
---
title: Breadcrumb
description: Displays the path to the current resource using a hierarchy of links.
base: radix
component: true
---
<ComponentPreview
styleName="radix-nova"
name="breadcrumb-demo"
className="[&_.preview]:p-2"
description="A breadcrumb with a collapsible dropdown."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add breadcrumb
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="breadcrumb"
title="components/ui/breadcrumb.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
```
```tsx showLineNumbers
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="/components">Components</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
```
## Examples
### Custom separator
Use a custom component as `children` for `<BreadcrumbSeparator />` to create a custom separator.
<ComponentPreview
styleName="radix-nova"
name="breadcrumb-separator"
description="A breadcrumb with a custom separator"
/>
```tsx showLineNumbers {1,10-12}
import { SlashIcon } from "lucide-react"
...
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<SlashIcon />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbLink href="/components">Components</BreadcrumbLink>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
```
---
### Dropdown
You can compose `<BreadcrumbItem />` with a `<DropdownMenu />` to create a dropdown in the breadcrumb.
<ComponentPreview
styleName="radix-nova"
name="breadcrumb-dropdown"
className="[&_.preview]:p-2"
description="A breadcrumb with a dropdown."
/>
```tsx showLineNumbers {1-6,11-21}
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
...
<BreadcrumbItem>
<DropdownMenu>
<DropdownMenuTrigger>
Components
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem>Documentation</DropdownMenuItem>
<DropdownMenuItem>Themes</DropdownMenuItem>
<DropdownMenuItem>GitHub</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbItem>
```
---
### Collapsed
We provide a `<BreadcrumbEllipsis />` component to show a collapsed state when the breadcrumb is too long.
<ComponentPreview
styleName="radix-nova"
name="breadcrumb-ellipsis"
className="[&_.preview]:p-2"
description="A breadcrumb showing a collapsed state."
/>
```tsx showLineNumbers {1,9}
import { BreadcrumbEllipsis } from "@/components/ui/breadcrumb"
...
<Breadcrumb>
<BreadcrumbList>
{/* ... */}
<BreadcrumbItem>
<BreadcrumbEllipsis />
</BreadcrumbItem>
{/* ... */}
</BreadcrumbList>
</Breadcrumb>
```
---
### Link component
To use a custom link component from your routing library, you can use the `asChild` prop on `<BreadcrumbLink />`.
<ComponentPreview
styleName="radix-nova"
name="breadcrumb-link"
description="A breadcrumb with a custom Link component"
/>
```tsx showLineNumbers {1,8-10}
import Link from "next/link"
...
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink asChild>
<Link href="/">Home</Link>
</BreadcrumbLink>
</BreadcrumbItem>
{/* ... */}
</BreadcrumbList>
</Breadcrumb>
```
---
### Responsive
Here's an example of a responsive breadcrumb that composes `<BreadcrumbItem />` with `<BreadcrumbEllipsis />`, `<DropdownMenu />`, and `<Drawer />`.
It displays a dropdown on desktop and a drawer on mobile.
<ComponentPreview
styleName="radix-nova"
name="breadcrumb-responsive"
className="[&_.preview]:p-2"
description="A responsive breadcrumb. It displays a dropdown on desktop and a drawer on mobile."
/>

View File

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

View File

@@ -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.
</Callout>
<ComponentPreview name="button-demo" description="A button" className="mb-4" />
<ComponentPreview
styleName="radix-nova"
name="button-demo"
description="A button"
className="mb-4"
/>
```tsx showLineNumbers
<Button variant="outline">Button</Button>
@@ -51,7 +57,11 @@ npm install @radix-ui/react-slot
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="button" title="components/ui/button.tsx" />
<ComponentSource
name="button"
title="components/ui/button.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -90,7 +100,7 @@ If you want to keep the `cursor: pointer` behavior, add the following code to yo
### Size
<ComponentPreview name="button-size" className="mb-4" />
<ComponentPreview styleName="radix-nova" name="button-size" className="mb-4" />
```tsx
// Small
@@ -115,6 +125,7 @@ If you want to keep the `cursor: pointer` behavior, add the following code to yo
### Default
<ComponentPreview
styleName="radix-nova"
name="button-default"
description="A primary button"
className="mb-4"
@@ -127,6 +138,7 @@ If you want to keep the `cursor: pointer` behavior, add the following code to yo
### Outline
<ComponentPreview
styleName="radix-nova"
name="button-outline"
description="A button using the outline variant."
className="mb-4"
@@ -139,6 +151,7 @@ If you want to keep the `cursor: pointer` behavior, add the following code to yo
### Secondary
<ComponentPreview
styleName="radix-nova"
name="button-secondary"
description="A secondary button"
className="mb-4"
@@ -151,6 +164,7 @@ If you want to keep the `cursor: pointer` behavior, add the following code to yo
### Ghost
<ComponentPreview
styleName="radix-nova"
name="button-ghost"
description="A button using the ghost variant"
className="mb-4"
@@ -163,6 +177,7 @@ If you want to keep the `cursor: pointer` behavior, add the following code to yo
### Destructive
<ComponentPreview
styleName="radix-nova"
name="button-destructive"
description="A destructive button"
className="mb-4"
@@ -175,6 +190,7 @@ If you want to keep the `cursor: pointer` behavior, add the following code to yo
### Link
<ComponentPreview
styleName="radix-nova"
name="button-link"
description="A button using the link variant."
className="mb-4"
@@ -187,6 +203,7 @@ If you want to keep the `cursor: pointer` behavior, add the following code to yo
### Icon
<ComponentPreview
styleName="radix-nova"
name="button-icon"
description="An icon button"
className="mb-4"
@@ -204,6 +221,7 @@ 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.
<ComponentPreview
styleName="radix-nova"
name="button-with-icon"
description="A button with an icon"
className="mb-4"
@@ -219,7 +237,11 @@ based on the size of the button. You do not need any margin on the icon.
Use the `rounded-full` class to make the button rounded.
<ComponentPreview name="button-rounded" className="mb-4" />
<ComponentPreview
styleName="radix-nova"
name="button-rounded"
className="mb-4"
/>
```tsx
<Button variant="outline" size="icon" className="rounded-full">
@@ -230,6 +252,7 @@ Use the `rounded-full` class to make the button rounded.
### Spinner
<ComponentPreview
styleName="radix-nova"
name="button-loading"
description="A button with a loading state."
className="mb-4"
@@ -246,7 +269,11 @@ Use the `rounded-full` class to make the button rounded.
To create a button group, use the `ButtonGroup` component. See the [Button Group](/docs/components/button-group) documentation for more details.
<ComponentPreview name="button-group-demo" className="mb-4" />
<ComponentPreview
styleName="radix-nova"
name="button-group-demo"
className="mb-4"
/>
```tsx showLineNumbers
<ButtonGroup>

View File

@@ -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
---
<ComponentPreview
styleName="radix-nova"
name="calendar-demo"
title="Calendar"
description="A calendar showing the current date."
/>
## 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
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add calendar
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install react-day-picker date-fns
```
<Step>Add the `Button` component to your project.</Step>
The `Calendar` component uses the `Button` component. Make sure you have it installed in your project.
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="calendar"
title="components/ui/calendar.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { Calendar } from "@/components/ui/calendar"
```
```tsx showLineNumbers
const [date, setDate] = React.useState<Date | undefined>(new Date())
return (
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="rounded-lg border"
/>
)
```
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 `<Calendar>` 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"
```
<ComponentPreview
styleName="radix-nova"
name="calendar-hijri"
title="Persian / Hijri / Jalali Calendar"
description="A Persian calendar."
/>
## 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<Date | undefined>(undefined)
const [timeZone, setTimeZone] = React.useState<string | undefined>(undefined)
React.useEffect(() => {
setTimeZone(Intl.DateTimeFormat().resolvedOptions().timeZone)
}, [])
return (
<Calendar
mode="single"
selected={date}
onSelect={setDate}
timeZone={timeZone}
/>
)
}
```
**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
<ComponentPreview
styleName="radix-nova"
name="calendar-05"
title="Range Calendar"
description="A calendar showing the current date and range selection."
className="**:[.preview]:h-auto lg:**:[.preview]:h-[450px]"
/>
### Month and Year Selector
<ComponentPreview
styleName="radix-nova"
name="calendar-13"
title="Month and Year Selector"
description="A calendar with month and year dropdowns."
/>
### Date of Birth Picker
<ComponentPreview
styleName="radix-nova"
name="calendar-22"
title="Date of Birth Picker"
description="A calendar with date of birth picker."
/>
### Date and Time Picker
<ComponentPreview
styleName="radix-nova"
name="calendar-24"
title="Date and Time Picker"
description="A calendar with date and time picker."
/>
### Natural Language Picker
This component uses the `chrono-node` library to parse natural language dates.
<ComponentPreview
styleName="radix-nova"
name="calendar-29"
title="Natural Language Picker"
description="A calendar with natural language picker."
/>
### Custom Cell Size
<ComponentPreview
styleName="radix-nova"
name="calendar-18"
title="Custom Cell Size"
description="A calendar with custom cell size that's responsive."
className="**:[.preview]:h-[560px]"
/>
You can customize the size of calendar cells using the `--cell-size` CSS variable. You can also make it responsive by using breakpoint-specific values:
```tsx showLineNumbers
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="rounded-lg border [--cell-size:--spacing(11)] md:[--cell-size:--spacing(12)]"
/>
```
Or use fixed values:
```tsx showLineNumbers
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="rounded-lg border [--cell-size:2.75rem] md:[--cell-size:3rem]"
/>
```
## 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.
<CodeCollapsibleWrapper>
```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<typeof DayPicker> & {
buttonVariant?: React.ComponentProps<typeof Button>["variant"]
}) {
const defaultClassNames = getDefaultClassNames()
return (
<DayPicker
showOutsideDays={showOutsideDays}
className={cn(
"bg-background group/calendar p-3 [--cell-size:2rem] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
String.raw`rtl:**:[.rdp-button\_next>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 (
<div
data-slot="calendar"
ref={rootRef}
className={cn(className)}
{...props}
/>
)
},
Chevron: ({ className, orientation, ...props }) => {
if (orientation === "left") {
return (
<ChevronLeftIcon className={cn("size-4", className)} {...props} />
)
}
if (orientation === "right") {
return (
<ChevronRightIcon
className={cn("size-4", className)}
{...props}
/>
)
}
return (
<ChevronDownIcon className={cn("size-4", className)} {...props} />
)
},
DayButton: CalendarDayButton,
WeekNumber: ({ children, ...props }) => {
return (
<td {...props}>
<div className="flex size-[--cell-size] items-center justify-center text-center">
{children}
</div>
</td>
)
},
...components,
}}
{...props}
/>
)
}
function CalendarDayButton({
className,
day,
modifiers,
...props
}: React.ComponentProps<typeof DayButton>) {
const defaultClassNames = getDefaultClassNames()
const ref = React.useRef<HTMLButtonElement>(null)
React.useEffect(() => {
if (modifiers.focused) ref.current?.focus()
}, [modifiers.focused])
return (
<Button
ref={ref}
variant="ghost"
size="icon"
data-day={day.date.toLocaleDateString()}
data-selected-single={
modifiers.selected &&
!modifiers.range_start &&
!modifiers.range_end &&
!modifiers.range_middle
}
data-range-start={modifiers.range_start}
data-range-end={modifiers.range_end}
data-range-middle={modifiers.range_middle}
className={cn(
"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
)}
{...props}
/>
)
}
export { Calendar, CalendarDayButton }
```
</CodeCollapsibleWrapper>
**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
}}
```

View File

@@ -0,0 +1,78 @@
---
title: Card
description: Displays a card with header, content, and footer.
base: radix
component: true
---
<ComponentPreview
styleName="radix-nova"
name="card-demo"
description="A card with a form"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add card
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="card"
title="components/ui/card.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Card,
CardAction,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card"
```
```tsx showLineNumbers
<Card>
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card Description</CardDescription>
<CardAction>Card Action</CardAction>
</CardHeader>
<CardContent>
<p>Card Content</p>
</CardContent>
<CardFooter>
<p>Card Footer</p>
</CardFooter>
</Card>
```

View File

@@ -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
---
<ComponentPreview
styleName="radix-nova"
name="carousel-demo"
title="Carousel"
description="A carousel with 5 items and a previous and next button."
/>
## About
The carousel component is built using the [Embla Carousel](https://www.embla-carousel.com/) library.
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add carousel
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install embla-carousel-react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="carousel"
title="components/ui/carousel.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@/components/ui/carousel"
```
```tsx showLineNumbers
<Carousel>
<CarouselContent>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
```
## Examples
### Sizes
To set the size of the items, you can use the `basis` utility class on the `<CarouselItem />`.
<ComponentPreview
styleName="radix-nova"
name="carousel-size"
title="Carousel"
description="A carousel with 3 active items of equal size."
/>
```tsx showLineNumbers {4-6}
// 33% of the carousel width.
<Carousel>
<CarouselContent>
<CarouselItem className="basis-1/3">...</CarouselItem>
<CarouselItem className="basis-1/3">...</CarouselItem>
<CarouselItem className="basis-1/3">...</CarouselItem>
</CarouselContent>
</Carousel>
```
```tsx showLineNumbers {4-6}
// 50% on small screens and 33% on larger screens.
<Carousel>
<CarouselContent>
<CarouselItem className="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
<CarouselItem className="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
<CarouselItem className="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
</CarouselContent>
</Carousel>
```
### Spacing
To set the spacing between the items, we use a `pl-[VALUE]` utility on the `<CarouselItem />` and a negative `-ml-[VALUE]` on the `<CarouselContent />`.
<Callout className="mt-6">
**Why:** I tried to use the `gap` property or a `grid` layout on the `
<CarouselContent />` but it required a lot of math and mental effort to get the
spacing right. I found `pl-[VALUE]` and `-ml-[VALUE]` utilities much easier to
use.
You can always adjust this in your own project if you need to.
</Callout>
<ComponentPreview
styleName="radix-nova"
name="carousel-spacing"
title="Carousel"
description="A carousel with 3 items with a spacing of 1rem."
/>
```tsx showLineNumbers /-ml-4/ /pl-4/
<Carousel>
<CarouselContent className="-ml-4">
<CarouselItem className="pl-4">...</CarouselItem>
<CarouselItem className="pl-4">...</CarouselItem>
<CarouselItem className="pl-4">...</CarouselItem>
</CarouselContent>
</Carousel>
```
```tsx showLineNumbers /-ml-2/ /pl-2/ /md:-ml-4/ /md:pl-4/
<Carousel>
<CarouselContent className="-ml-2 md:-ml-4">
<CarouselItem className="pl-2 md:pl-4">...</CarouselItem>
<CarouselItem className="pl-2 md:pl-4">...</CarouselItem>
<CarouselItem className="pl-2 md:pl-4">...</CarouselItem>
</CarouselContent>
</Carousel>
```
### Orientation
Use the `orientation` prop to set the orientation of the carousel.
<ComponentPreview
styleName="radix-nova"
name="carousel-orientation"
title="Carousel"
description="A vertical carousel."
/>
```tsx showLineNumbers /vertical | horizontal/
<Carousel orientation="vertical | horizontal">
<CarouselContent>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
</CarouselContent>
</Carousel>
```
## Options
You can pass options to the carousel using the `opts` prop. See the [Embla Carousel docs](https://www.embla-carousel.com/api/options/) for more information.
```tsx showLineNumbers {2-5}
<Carousel
opts={{
align: "start",
loop: true,
}}
>
<CarouselContent>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
</CarouselContent>
</Carousel>
```
## API
Use a state and the `setApi` props to get an instance of the carousel API.
<ComponentPreview
styleName="radix-nova"
name="carousel-api"
title="Carousel"
description="A carousel with a slide counter."
/>
```tsx showLineNumbers {1,4,22}
import { type CarouselApi } from "@/components/ui/carousel"
export function Example() {
const [api, setApi] = React.useState<CarouselApi>()
const [current, setCurrent] = React.useState(0)
const [count, setCount] = React.useState(0)
React.useEffect(() => {
if (!api) {
return
}
setCount(api.scrollSnapList().length)
setCurrent(api.selectedScrollSnap() + 1)
api.on("select", () => {
setCurrent(api.selectedScrollSnap() + 1)
})
}, [api])
return (
<Carousel setApi={setApi}>
<CarouselContent>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
</CarouselContent>
</Carousel>
)
}
```
## Events
You can listen to events using the api instance from `setApi`.
```tsx showLineNumbers {1,4-14,16}
import { type CarouselApi } from "@/components/ui/carousel"
export function Example() {
const [api, setApi] = React.useState<CarouselApi>()
React.useEffect(() => {
if (!api) {
return
}
api.on("select", () => {
// Do something on select.
})
}, [api])
return (
<Carousel setApi={setApi}>
<CarouselContent>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
</CarouselContent>
</Carousel>
)
}
```
See the [Embla Carousel docs](https://www.embla-carousel.com/api/events/) for more information on using events.
## Plugins
You can use the `plugins` prop to add plugins to the carousel.
```ts showLineNumbers {1,6-10}
import Autoplay from "embla-carousel-autoplay"
export function Example() {
return (
<Carousel
plugins={[
Autoplay({
delay: 2000,
}),
]}
>
// ...
</Carousel>
)
}
```
<ComponentPreview
styleName="radix-nova"
name="carousel-plugin"
title="Carousel"
description="A carousel with the autoplay plugin."
/>
See the [Embla Carousel docs](https://www.embla-carousel.com/api/plugins/) for more information on using plugins.

View File

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

View File

@@ -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
---
<ComponentPreview
styleName="radix-nova"
name="checkbox-demo"
description="A checkbox"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add checkbox
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-checkbox
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="checkbox"
title="components/ui/checkbox.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import { Checkbox } from "@/components/ui/checkbox"
```
```tsx
<Checkbox />
```

View File

@@ -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
---
<ComponentPreview
styleName="radix-nova"
name="collapsible-demo"
description="A collapsible component."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add collapsible
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-collapsible
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="collapsible"
title="components/ui/collapsible.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible"
```
```tsx showLineNumbers
<Collapsible>
<CollapsibleTrigger>Can I use this in my project?</CollapsibleTrigger>
<CollapsibleContent>
Yes. Free to use for personal and commercial projects. No attribution
required.
</CollapsibleContent>
</Collapsible>
```

View File

@@ -0,0 +1,149 @@
---
title: Combobox
description: Autocomplete input and command palette with a list of suggestions.
base: radix
component: true
---
<ComponentPreview
styleName="radix-nova"
name="combobox-demo"
description="A combobox with a list of frameworks."
/>
## Installation
The Combobox is built using a composition of the `<Popover />` and the `<Command />` components.
See installation instructions for the [Popover](/docs/components/popover#installation) and the [Command](/docs/components/command#installation) components.
## Usage
<CodeCollapsibleWrapper>
```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 (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={open}
className="w-[200px] justify-between"
>
{value
? frameworks.find((framework) => framework.value === value)?.label
: "Select framework..."}
<ChevronsUpDownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0">
<Command>
<CommandInput placeholder="Search framework..." />
<CommandList>
<CommandEmpty>No framework found.</CommandEmpty>
<CommandGroup>
{frameworks.map((framework) => (
<CommandItem
key={framework.value}
value={framework.value}
onSelect={(currentValue) => {
setValue(currentValue === value ? "" : currentValue)
setOpen(false)
}}
>
<CheckIcon
className={cn(
"mr-2 h-4 w-4",
value === framework.value ? "opacity-100" : "opacity-0"
)}
/>
{framework.label}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
)
}
```
</CodeCollapsibleWrapper>
## Examples
### Combobox
<ComponentPreview
styleName="radix-nova"
name="combobox-demo"
description="A combobox with a list of frameworks."
/>
### Popover
<ComponentPreview styleName="radix-nova" name="combobox-popover" />
### Dropdown menu
<ComponentPreview
styleName="radix-nova"
name="combobox-dropdown-menu"
description="A combobox in a dropdown menu"
/>
### Responsive
You can create a responsive combobox by using the `<Popover />` on desktop and the `<Drawer />` components on mobile.
<ComponentPreview styleName="radix-nova" name="combobox-responsive" />

View File

@@ -0,0 +1,145 @@
---
title: Command
description: Fast, composable, unstyled command menu for React.
base: radix
component: true
links:
doc: https://cmdk.paco.me
---
<ComponentPreview
styleName="radix-nova"
name="command-demo"
align="start"
className="[&_.preview>div]:max-w-[450px]"
description="A command menu"
/>
## About
The `<Command />` component uses the [`cmdk`](https://cmdk.paco.me) component by [pacocoursey](https://twitter.com/pacocoursey).
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add command
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install cmdk
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="command"
title="components/ui/command.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Command,
CommandDialog,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
CommandShortcut,
} from "@/components/ui/command"
```
```tsx showLineNumbers
<Command>
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem>Calendar</CommandItem>
<CommandItem>Search Emoji</CommandItem>
<CommandItem>Calculator</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Settings">
<CommandItem>Profile</CommandItem>
<CommandItem>Billing</CommandItem>
<CommandItem>Settings</CommandItem>
</CommandGroup>
</CommandList>
</Command>
```
## Examples
### Dialog
<ComponentPreview
styleName="radix-nova"
name="command-dialog"
description="A command menu in a dialog"
/>
To show the command menu in a dialog, use the `<CommandDialog />` 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 (
<CommandDialog open={open} onOpenChange={setOpen}>
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem>Calendar</CommandItem>
<CommandItem>Search Emoji</CommandItem>
<CommandItem>Calculator</CommandItem>
</CommandGroup>
</CommandList>
</CommandDialog>
)
}
```
### Combobox
You can use the `<Command />` component as a combobox. See the [Combobox](/docs/components/combobox) page for more information.

View File

@@ -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
---
<ComponentPreview
styleName="radix-nova"
name="context-menu-demo"
description="A context menu with sub menu items."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add context-menu
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-context-menu
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="context-menu"
title="components/ui/context-menu.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
ContextMenu,
ContextMenuContent,
ContextMenuItem,
ContextMenuTrigger,
} from "@/components/ui/context-menu"
```
```tsx showLineNumbers
<ContextMenu>
<ContextMenuTrigger>Right click</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem>Profile</ContextMenuItem>
<ContextMenuItem>Billing</ContextMenuItem>
<ContextMenuItem>Team</ContextMenuItem>
<ContextMenuItem>Subscription</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
```

View File

@@ -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
---
<ComponentPreview
styleName="radix-nova"
name="data-table-demo"
className="[&_.preview]:items-start"
/>
## 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 `<Table />` component and build a complex data table from scratch.
<Callout className="mt-4">
**Tip:** If you find yourself using the same table in multiple places in your app, you can always extract it into a reusable component.
</Callout>
## Table of Contents
This guide will show you how to use [TanStack Table](https://tanstack.com/table) and the `<Table />` component to build your own custom data table. We'll cover the following topics:
- [Basic Table](#basic-table)
- [Row Actions](#row-actions)
- [Pagination](#pagination)
- [Sorting](#sorting)
- [Filtering](#filtering)
- [Visibility](#visibility)
- [Row Selection](#row-selection)
- [Reusable Components](#reusable-components)
## Installation
1. Add the `<Table />` component to your project:
```bash
npx shadcn@latest add table
```
2. Add `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 `<DataTable />` 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.
<Steps>
### 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<Payment>[] = [
{
accessorKey: "status",
header: "Status",
},
{
accessorKey: "email",
header: "Email",
},
{
accessorKey: "amount",
header: "Amount",
},
]
```
<Callout className="mt-4">
**Note:** Columns are where you define the core of what your table
will look like. They define the data that will be displayed, how it will be
formatted, sorted and filtered.
</Callout>
### `<DataTable />` component
Next, we'll create a `<DataTable />` component to render our table.
```tsx showLineNumbers title="app/payments/data-table.tsx"
"use client"
import {
ColumnDef,
flexRender,
getCoreRowModel,
useReactTable,
} from "@tanstack/react-table"
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table"
interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[]
data: TData[]
}
export function DataTable<TData, TValue>({
columns,
data,
}: DataTableProps<TData, TValue>) {
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
})
return (
<div className="overflow-hidden rounded-md border">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
)
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={columns.length} className="h-24 text-center">
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
)
}
```
<Callout>
**Tip**: If you find yourself using `<DataTable />` in multiple places, this is the component you could make reusable by extracting it to `components/ui/data-table.tsx`.
`<DataTable columns={columns} data={data} />`
</Callout>
### Render the table
Finally, we'll render our table in our page component.
```tsx showLineNumbers title="app/payments/page.tsx" {22}
import { columns, Payment } from "./columns"
import { DataTable } from "./data-table"
async function getData(): Promise<Payment[]> {
// Fetch data from your API here.
return [
{
id: "728ed52f",
amount: 100,
status: "pending",
email: "m@example.com",
},
// ...
]
}
export default async function DemoPage() {
const data = await getData()
return (
<div className="container mx-auto py-10">
<DataTable columns={columns} data={data} />
</div>
)
}
```
</Steps>
## Cell Formatting
Let's format the amount cell to display the dollar amount. We'll also align the cell to the right.
<Steps>
### 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<Payment>[] = [
{
accessorKey: "amount",
header: () => <div className="text-right">Amount</div>,
cell: ({ row }) => {
const amount = parseFloat(row.getValue("amount"))
const formatted = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
}).format(amount)
return <div className="text-right font-medium">{formatted}</div>
},
},
]
```
You can use the same approach to format other cells and headers.
</Steps>
## Row Actions
Let's add row actions to our table. We'll use a `<Dropdown />` component for this.
<Steps>
### Update columns definition
Update our columns definition to add a new `actions` column. The `actions` cell returns a `<Dropdown />` component.
```tsx showLineNumbers title="app/payments/columns.tsx" {4,6-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<Payment>[] = [
// ...
{
id: "actions",
cell: ({ row }) => {
const payment = row.original
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="h-8 w-8 p-0">
<span className="sr-only">Open menu</span>
<MoreHorizontal className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuItem
onClick={() => navigator.clipboard.writeText(payment.id)}
>
Copy payment ID
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>View customer</DropdownMenuItem>
<DropdownMenuItem>View payment details</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
},
},
// ...
]
```
You can access the row data using `row.original` in the `cell` function. Use this to handle actions for your row eg. use the `id` to make a DELETE call to your API.
</Steps>
## Pagination
Next, we'll add pagination to our table.
<Steps>
### Update `<DataTable>`
```tsx showLineNumbers title="app/payments/data-table.tsx" {5,17}
import {
ColumnDef,
flexRender,
getCoreRowModel,
getPaginationRowModel,
useReactTable,
} from "@tanstack/react-table"
export function DataTable<TData, TValue>({
columns,
data,
}: DataTableProps<TData, TValue>) {
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 `<Button />` 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<TData, TValue>({
columns,
data,
}: DataTableProps<TData, TValue>) {
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
})
return (
<div>
<div className="overflow-hidden rounded-md border">
<Table>
{ // .... }
</Table>
</div>
<div className="flex items-center justify-end space-x-2 py-4">
<Button
variant="outline"
size="sm"
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
>
Previous
</Button>
<Button
variant="outline"
size="sm"
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
>
Next
</Button>
</div>
</div>
)
}
```
See [Reusable Components](#reusable-components) section for a more advanced pagination component.
</Steps>
## Sorting
Let's make the email column sortable.
<Steps>
### Update `<DataTable>`
```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<TData, TValue>({
columns,
data,
}: DataTableProps<TData, TValue>) {
const [sorting, setSorting] = React.useState<SortingState>([])
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
onSortingChange: setSorting,
getSortedRowModel: getSortedRowModel(),
state: {
sorting,
},
})
return (
<div>
<div className="overflow-hidden rounded-md border">
<Table>{ ... }</Table>
</div>
</div>
)
}
```
### Make header cell sortable
We can now update the `email` header cell to add sorting controls.
```tsx showLineNumbers title="app/payments/columns.tsx" {4,9-19}
"use client"
import { ColumnDef } from "@tanstack/react-table"
import { ArrowUpDown } from "lucide-react"
export const columns: ColumnDef<Payment>[] = [
{
accessorKey: "email",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Email
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
)
},
},
]
```
This will automatically sort the table (asc and desc) when the user toggles on the header cell.
</Steps>
## Filtering
Let's add a search input to filter emails in our table.
<Steps>
### Update `<DataTable>`
```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<TData, TValue>({
columns,
data,
}: DataTableProps<TData, TValue>) {
const [sorting, setSorting] = React.useState<SortingState>([])
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
)
const table = useReactTable({
data,
columns,
onSortingChange: setSorting,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
onColumnFiltersChange: setColumnFilters,
getFilteredRowModel: getFilteredRowModel(),
state: {
sorting,
columnFilters,
},
})
return (
<div>
<div className="flex items-center py-4">
<Input
placeholder="Filter emails..."
value={(table.getColumn("email")?.getFilterValue() as string) ?? ""}
onChange={(event) =>
table.getColumn("email")?.setFilterValue(event.target.value)
}
className="max-w-sm"
/>
</div>
<div className="overflow-hidden rounded-md border">
<Table>{ ... }</Table>
</div>
</div>
)
}
```
Filtering is now enabled for the `email` column. You can add filters to other columns as well. See the [filtering docs](https://tanstack.com/table/v8/docs/guide/filters) for more information on customizing filters.
</Steps>
## Visibility
Adding column visibility is fairly simple using `@tanstack/react-table` visibility API.
<Steps>
### Update `<DataTable>`
```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<TData, TValue>({
columns,
data,
}: DataTableProps<TData, TValue>) {
const [sorting, setSorting] = React.useState<SortingState>([])
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
)
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({})
const table = useReactTable({
data,
columns,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onColumnVisibilityChange: setColumnVisibility,
state: {
sorting,
columnFilters,
columnVisibility,
},
})
return (
<div>
<div className="flex items-center py-4">
<Input
placeholder="Filter emails..."
value={table.getColumn("email")?.getFilterValue() as string}
onChange={(event) =>
table.getColumn("email")?.setFilterValue(event.target.value)
}
className="max-w-sm"
/>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" className="ml-auto">
Columns
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{table
.getAllColumns()
.filter(
(column) => column.getCanHide()
)
.map((column) => {
return (
<DropdownMenuCheckboxItem
key={column.id}
className="capitalize"
checked={column.getIsVisible()}
onCheckedChange={(value) =>
column.toggleVisibility(!!value)
}
>
{column.id}
</DropdownMenuCheckboxItem>
)
})}
</DropdownMenuContent>
</DropdownMenu>
</div>
<div className="overflow-hidden rounded-md border">
<Table>{ ... }</Table>
</div>
</div>
)
}
```
This adds a dropdown menu that you can use to toggle column visibility.
</Steps>
## Row Selection
Next, we're going to add row selection to our table.
<Steps>
### 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<Payment>[] = [
{
id: "select",
header: ({ table }) => (
<Checkbox
checked={
table.getIsAllPageRowsSelected() ||
(table.getIsSomePageRowsSelected() && "indeterminate")
}
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
aria-label="Select all"
/>
),
cell: ({ row }) => (
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value) => row.toggleSelected(!!value)}
aria-label="Select row"
/>
),
enableSorting: false,
enableHiding: false,
},
]
```
### Update `<DataTable>`
```tsx showLineNumbers title="app/payments/data-table.tsx" {11,23,28}
export function DataTable<TData, TValue>({
columns,
data,
}: DataTableProps<TData, TValue>) {
const [sorting, setSorting] = React.useState<SortingState>([])
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
)
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({})
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 (
<div>
<div className="overflow-hidden rounded-md border">
<Table />
</div>
</div>
)
}
```
This adds a checkbox to each row and a checkbox in the header to select all rows.
### Show selected rows
You can show the number of selected rows using the `table.getFilteredSelectedRowModel()` API.
```tsx
<div className="text-muted-foreground flex-1 text-sm">
{table.getFilteredSelectedRowModel().rows.length} of{" "}
{table.getFilteredRowModel().rows.length} row(s) selected.
</div>
```
</Steps>
## Reusable Components
Here are some components you can use to build your data tables. This is from the [Tasks](/examples/tasks) demo.
### Column header
Make any column header sortable and hideable.
<ComponentSource
src="/app/(app)/examples/tasks/components/data-table-column-header.tsx"
title="components/data-table-column-header.tsx"
/>
```tsx showLineNumbers {5}
export const columns = [
{
accessorKey: "email",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Email" />
),
},
]
```
### Pagination
Add pagination controls to your table including page size and selection count.
<ComponentSource
src="/app/(app)/examples/tasks/components/data-table-pagination.tsx"
styleName="radix-nova"
/>
```tsx
<DataTablePagination table={table} />
```
### Column toggle
A component to toggle column visibility.
<ComponentSource
src="/app/(app)/examples/tasks/components/data-table-view-options.tsx"
styleName="radix-nova"
/>
```tsx
<DataTableViewOptions table={table} />
```

View File

@@ -0,0 +1,102 @@
---
title: Date Picker
description: A date picker component with range and presets.
base: radix
component: true
---
<ComponentPreview
styleName="radix-nova"
name="calendar-22"
title="Date of Birth Picker"
description="A calendar with date of birth picker."
/>
## Installation
The Date Picker is built using a composition of the `<Popover />` and the `<Calendar />` 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<Date>()
return (
<Popover>
<PopoverTrigger asChild>
<Button
variant="outline"
data-empty={!date}
className="data-[empty=true]:text-muted-foreground w-[280px] justify-start text-left font-normal"
>
<CalendarIcon />
{date ? format(date, "PPP") : <span>Pick a date</span>}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar mode="single" selected={date} onSelect={setDate} />
</PopoverContent>
</Popover>
)
}
```
See the [React DayPicker](https://react-day-picker.js.org) documentation for more information.
## Examples
### Date of Birth Picker
<ComponentPreview
styleName="radix-nova"
name="calendar-22"
title="Date of Birth Picker"
description="A calendar with date of birth picker."
/>
### Picker with Input
<ComponentPreview
styleName="radix-nova"
name="calendar-28"
title="Picker with Input"
description="A calendar with input and picker."
/>
### Date and Time Picker
<ComponentPreview
styleName="radix-nova"
name="calendar-24"
title="Date and Time Picker"
description="A calendar with date and time picker."
/>
### Natural Language Picker
This component uses the `chrono-node` library to parse natural language dates.
<ComponentPreview
styleName="radix-nova"
name="calendar-29"
title="Natural Language Picker"
description="A calendar with natural language picker."
/>

View File

@@ -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
---
<ComponentPreview
styleName="radix-nova"
name="dialog-demo"
description="A dialog for editing profile details."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add dialog
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-dialog
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="dialog"
title="components/ui/dialog.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
```
```tsx showLineNumbers
<Dialog>
<DialogTrigger>Open</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Are you absolutely sure?</DialogTitle>
<DialogDescription>
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog>
```
## Examples
### Custom close button
<ComponentPreview styleName="radix-nova" name="dialog-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}
<Dialog>
<ContextMenu>
<ContextMenuTrigger>Right click</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem>Open</ContextMenuItem>
<ContextMenuItem>Download</ContextMenuItem>
<DialogTrigger asChild>
<ContextMenuItem>
<span>Delete</span>
</ContextMenuItem>
</DialogTrigger>
</ContextMenuContent>
</ContextMenu>
<DialogContent>
<DialogHeader>
<DialogTitle>Are you absolutely sure?</DialogTitle>
<DialogDescription>
This action cannot be undone. Are you sure you want to permanently
delete this file from our servers?
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button type="submit">Confirm</Button>
</DialogFooter>
</DialogContent>
</Dialog>
```

View File

@@ -0,0 +1,101 @@
---
title: Drawer
description: A drawer component for React.
base: radix
component: true
links:
doc: https://vaul.emilkowal.ski/getting-started
---
<ComponentPreview
styleName="radix-nova"
name="drawer-demo"
description="A drawer component."
/>
## About
Drawer is built on top of [Vaul](https://github.com/emilkowalski/vaul) by [emilkowalski](https://twitter.com/emilkowalski).
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add drawer
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install vaul
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="drawer"
title="components/ui/drawer.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from "@/components/ui/drawer"
```
```tsx showLineNumbers
<Drawer>
<DrawerTrigger>Open</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Are you absolutely sure?</DrawerTitle>
<DrawerDescription>This action cannot be undone.</DrawerDescription>
</DrawerHeader>
<DrawerFooter>
<Button>Submit</Button>
<DrawerClose>
<Button variant="outline">Cancel</Button>
</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>
```
## 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.
<ComponentPreview styleName="radix-nova" name="drawer-dialog" />

View File

@@ -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
---
<ComponentPreview
styleName="radix-nova"
name="dropdown-menu-demo"
description="A dropdown menu with icons, shortcuts and sub menu items."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add dropdown-menu
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-dropdown-menu
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="dropdown-menu"
title="components/ui/dropdown-menu.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
```
```tsx showLineNumbers
<DropdownMenu>
<DropdownMenuTrigger>Open</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem>Profile</DropdownMenuItem>
<DropdownMenuItem>Billing</DropdownMenuItem>
<DropdownMenuItem>Team</DropdownMenuItem>
<DropdownMenuItem>Subscription</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
```
## Examples
### Checkboxes
<ComponentPreview
styleName="radix-nova"
name="dropdown-menu-checkboxes"
description="A dropdown menu with checkboxes."
/>
### Radio Group
<ComponentPreview
styleName="radix-nova"
name="dropdown-menu-radio-group"
description="A dropdown menu with radio items."
/>
### Dialog
This example shows how to open a dialog from a dropdown menu.
Use `modal={false}` on the `DropdownMenu` component.
```tsx showLineNumbers
<DropdownMenu modal={false}>
<DropdownMenuTrigger asChild>
<Button variant="outline">Actions</Button>
</DropdownMenuTrigger>
</DropdownMenu>
```
<ComponentPreview styleName="radix-nova" name="dropdown-menu-dialog" />

View File

@@ -0,0 +1,223 @@
---
title: Empty
description: Use the Empty component to display an empty state.
base: radix
component: true
---
<ComponentPreview
styleName="radix-nova"
name="empty-demo"
className="[&_.preview]:p-0"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add empty
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="empty"
title="components/ui/empty.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import {
Empty,
EmptyContent,
EmptyDescription,
EmptyHeader,
EmptyMedia,
EmptyTitle,
} from "@/components/ui/empty"
```
```tsx
<Empty>
<EmptyHeader>
<EmptyMedia variant="icon">
<Icon />
</EmptyMedia>
<EmptyTitle>No data</EmptyTitle>
<EmptyDescription>No data found</EmptyDescription>
</EmptyHeader>
<EmptyContent>
<Button>Add data</Button>
</EmptyContent>
</Empty>
```
## Examples
### Outline
Use the `border` utility class to create an outline empty state.
<ComponentPreview
styleName="radix-nova"
name="empty-outline"
className="[&_.preview]:p-6 md:[&_.preview]:p-10"
/>
### Background
Use the `bg-*` and `bg-gradient-*` utilities to add a background to the empty state.
<ComponentPreview
styleName="radix-nova"
name="empty-background"
className="[&_.preview]:p-0"
/>
### Avatar
Use the `EmptyMedia` component to display an avatar in the empty state.
<ComponentPreview
styleName="radix-nova"
name="empty-avatar"
className="[&_.preview]:p-0"
/>
### Avatar Group
Use the `EmptyMedia` component to display an avatar group in the empty state.
<ComponentPreview
styleName="radix-nova"
name="empty-avatar-group"
className="[&_.preview]:p-0"
/>
### InputGroup
You can add an `InputGroup` component to the `EmptyContent` component.
<ComponentPreview
styleName="radix-nova"
name="empty-input-group"
className="[&_.preview]:p-0"
/>
## API Reference
### Empty
The main component of the empty state. Wraps the `EmptyHeader` and `EmptyContent` components.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | |
```tsx
<Empty>
<EmptyHeader />
<EmptyContent />
</Empty>
```
### EmptyHeader
The `EmptyHeader` component wraps the empty media, title, and description.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | |
```tsx
<EmptyHeader>
<EmptyMedia />
<EmptyTitle />
<EmptyDescription />
</EmptyHeader>
```
### 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
<EmptyMedia variant="icon">
<Icon />
</EmptyMedia>
```
```tsx
<EmptyMedia>
<Avatar>
<AvatarImage src="..." />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
</EmptyMedia>
```
### EmptyTitle
Use the `EmptyTitle` component to display the title of the empty state.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | |
```tsx
<EmptyTitle>No data</EmptyTitle>
```
### EmptyDescription
Use the `EmptyDescription` component to display the description of the empty state.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | |
```tsx
<EmptyDescription>You do not have any notifications.</EmptyDescription>
```
### 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
<EmptyContent>
<Button>Add Project</Button>
</EmptyContent>
```

View File

@@ -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
---
<ComponentPreview
styleName="radix-nova"
name="field-demo"
className="[&_.preview]:h-[800px] [&_.preview]:p-6 md:[&_.preview]:h-[850px]"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add field
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="field"
title="components/ui/field.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Field,
FieldContent,
FieldDescription,
FieldError,
FieldGroup,
FieldLabel,
FieldLegend,
FieldSeparator,
FieldSet,
FieldTitle,
} from "@/components/ui/field"
```
```tsx showLineNumbers
<FieldSet>
<FieldLegend>Profile</FieldLegend>
<FieldDescription>This appears on invoices and emails.</FieldDescription>
<FieldGroup>
<Field>
<FieldLabel htmlFor="name">Full name</FieldLabel>
<Input id="name" autoComplete="off" placeholder="Evil Rabbit" />
<FieldDescription>This appears on invoices and emails.</FieldDescription>
</Field>
<Field>
<FieldLabel htmlFor="username">Username</FieldLabel>
<Input id="username" autoComplete="off" aria-invalid />
<FieldError>Choose another username.</FieldError>
</Field>
<Field orientation="horizontal">
<Switch id="newsletter" />
<FieldLabel htmlFor="newsletter">Subscribe to the newsletter</FieldLabel>
</Field>
</FieldGroup>
</FieldSet>
```
## Anatomy
The `Field` family is designed for composing accessible forms. A typical field is structured as follows:
```tsx showLineNumbers
<Field>
<FieldLabel htmlFor="input-id">Label</FieldLabel>
{/* Input, Select, Switch, etc. */}
<FieldDescription>Optional helper text.</FieldDescription>
<FieldError>Validation message.</FieldError>
</Field>
```
- `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
<ComponentPreview
styleName="radix-nova"
name="field-input"
className="!mb-4 [&_.preview]:p-6"
/>
### Textarea
<ComponentPreview
styleName="radix-nova"
name="field-textarea"
className="!mb-4 [&_.preview]:p-6"
/>
### Select
<ComponentPreview
styleName="radix-nova"
name="field-select"
className="!mb-4 [&_.preview]:p-6"
/>
### Slider
<ComponentPreview
styleName="radix-nova"
name="field-slider"
className="!mb-4 [&_.preview]:p-6"
/>
### Fieldset
<ComponentPreview
styleName="radix-nova"
name="field-fieldset"
className="!mb-4 [&_.preview]:p-6"
/>
### Checkbox
<ComponentPreview
styleName="radix-nova"
name="field-checkbox"
className="!mb-4 [&_.preview]:p-6"
/>
### Radio
<ComponentPreview
styleName="radix-nova"
name="field-radio"
className="!mb-4 [&_.preview]:p-6"
/>
### Switch
<ComponentPreview
styleName="radix-nova"
name="field-switch"
className="!mb-4 [&_.preview]:p-6"
/>
### Choice Card
Wrap `Field` components inside `FieldLabel` to create selectable field groups. This works with `RadioItem`, `Checkbox` and `Switch` components.
<ComponentPreview
styleName="radix-nova"
name="field-choice-card"
className="!mb-4 [&_.preview]:p-6"
/>
### Field Group
Stack `Field` components with `FieldGroup`. Add `FieldSeparator` to divide them.
<ComponentPreview
styleName="radix-nova"
name="field-group"
className="!mb-4 [&_.preview]:p-6"
/>
## 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.
<ComponentPreview
styleName="radix-nova"
name="field-responsive"
className="!mb-4 [&_.preview]:h-[650px] [&_.preview]:p-6 [&_.preview]:md:h-[500px] [&_.preview]:md:p-10"
/>
## 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/
<Field data-invalid>
<FieldLabel htmlFor="email">Email</FieldLabel>
<Input id="email" type="email" aria-invalid />
<FieldError>Enter a valid email address.</FieldError>
</Field>
```
## 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
<FieldSet>
<FieldLegend>Delivery</FieldLegend>
<FieldGroup>{/* Fields */}</FieldGroup>
</FieldSet>
```
### 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
<FieldLegend variant="label">Notification Preferences</FieldLegend>
```
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
<FieldGroup className="@container/field-group flex flex-col gap-6">
<Field>{/* ... */}</Field>
<Field>{/* ... */}</Field>
</FieldGroup>
```
### 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
<Field orientation="horizontal">
<FieldLabel htmlFor="remember">Remember me</FieldLabel>
<Switch id="remember" />
</Field>
```
### 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
<Field>
<Checkbox id="notifications" />
<FieldContent>
<FieldLabel htmlFor="notifications">Notifications</FieldLabel>
<FieldDescription>Email, SMS, and push options.</FieldDescription>
</FieldContent>
</Field>
```
### FieldLabel
Label styled for both direct inputs and nested `Field` children.
| Prop | Type | Default |
| ----------- | --------- | ------- |
| `className` | `string` | |
| `asChild` | `boolean` | `false` |
```tsx
<FieldLabel htmlFor="email">Email</FieldLabel>
```
### FieldTitle
Renders a title with label styling inside `FieldContent`.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | |
```tsx
<FieldContent>
<FieldTitle>Enable Touch ID</FieldTitle>
<FieldDescription>Unlock your device faster.</FieldDescription>
</FieldContent>
```
### FieldDescription
Helper text slot that automatically balances long lines in horizontal layouts.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | |
```tsx
<FieldDescription>We never share your email with anyone.</FieldDescription>
```
### FieldSeparator
Visual divider to separate sections inside a `FieldGroup`. Accepts optional inline content.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | |
```tsx
<FieldSeparator>Or continue with</FieldSeparator>
```
### 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
<FieldError errors={errors.username} />
```
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.

View File

@@ -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"
<Callout icon={<InfoIcon />} 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 [`<Field />`](/docs/components/field) component to build forms. See the [Form](/docs/forms) documentation for more information.
</Callout>
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 `<FormField>` component to compose accessible forms using Radix UI components.
## Features
The `<Form />` component is a wrapper around the `react-hook-form` library. It provides a few things:
- Composable components for building forms.
- A `<FormField />` 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
<Form>
<FormField
control={...}
name="..."
render={() => (
<FormItem>
<FormLabel />
<FormControl>
{ /* Your form field */}
</FormControl>
<FormDescription />
<FormMessage />
</FormItem>
)}
/>
</Form>
```
## Example
```tsx showLineNumbers
const form = useForm()
<FormField
control={form.control}
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="shadcn" {...field} />
</FormControl>
<FormDescription>This is your public display name.</FormDescription>
<FormMessage />
</FormItem>
)}
/>
```
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
<Steps>
### Command
```bash
npx shadcn@latest add form
```
</Steps>
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-label @radix-ui/react-slot react-hook-form @hookform/resolvers zod
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="form"
title="components/ui/form.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## 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<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
username: "",
},
})
// 2. Define a submit handler.
function onSubmit(values: z.infer<typeof formSchema>) {
// 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 `<Form />` 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 (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="shadcn" {...field} />
</FormControl>
<FormDescription>
This is your public display name.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
)
}
```
### Done
That's it. You now have a fully accessible form that is type-safe with client-side validation.

View File

@@ -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
---
<ComponentPreview
styleName="radix-nova"
name="hover-card-demo"
description="A hover card component"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add hover-card
```
</TabsContent>
<TabsContent value="manual">
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-hover-card
```
<Steps>
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="hover-card"
title="components/ui/hover-card.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from "@/components/ui/hover-card"
```
```tsx showLineNumbers
<HoverCard>
<HoverCardTrigger>Hover</HoverCardTrigger>
<HoverCardContent>
The React Framework created and maintained by @vercel.
</HoverCardContent>
</HoverCard>
```

View File

@@ -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"
<ComponentPreview
styleName="radix-nova"
name="input-group-demo"
className="[&_.preview]:p-4"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add input-group
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="input-group"
title="components/ui/input-group.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupInput,
InputGroupText,
InputGroupTextarea,
} from "@/components/ui/input-group"
```
```tsx showLineNumbers
<InputGroup>
<InputGroupInput placeholder="Search..." />
<InputGroupAddon>
<SearchIcon />
</InputGroupAddon>
<InputGroupAddon align="inline-end">
<InputGroupButton>Search</InputGroupButton>
</InputGroupAddon>
</InputGroup>
```
## Examples
### Icon
<ComponentPreview
styleName="radix-nova"
name="input-group-icon"
className="[&_.preview]:p-4"
/>
### Text
Display additional text information alongside inputs.
<ComponentPreview
styleName="radix-nova"
name="input-group-text"
className="[&_.preview]:p-4"
/>
### Button
Add buttons to perform actions within the input group.
<ComponentPreview
styleName="radix-nova"
name="input-group-button"
className="[&_.preview]:p-4"
/>
### Tooltip
Add tooltips to provide additional context or help.
<ComponentPreview
styleName="radix-nova"
name="input-group-tooltip"
className="[&_.preview]:p-4"
/>
### Textarea
Input groups also work with textarea components. Use `block-start` or `block-end` for alignment.
<ComponentPreview
styleName="radix-nova"
name="input-group-textarea"
className="[&_.preview]:p-4"
/>
### Spinner
Show loading indicators while processing input.
<ComponentPreview
styleName="radix-nova"
name="input-group-spinner"
className="[&_.preview]:p-4"
/>
### Label
Add labels within input groups to improve accessibility.
<ComponentPreview
styleName="radix-nova"
name="input-group-label"
className="[&_.preview]:p-4"
/>
### Dropdown
Pair input groups with dropdown menus for complex interactions.
<ComponentPreview
styleName="radix-nova"
name="input-group-dropdown"
className="[&_.preview]:p-4"
/>
### Button Group
Wrap input groups with button groups to create prefixes and suffixes.
<ComponentPreview
styleName="radix-nova"
name="input-group-button-group"
className="[&_.preview]:p-4"
/>
### 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.
<ComponentPreview
styleName="radix-nova"
name="input-group-custom"
className="!mb-4 [&_.preview]:p-4"
/>
```tsx showLineNumbers
import { InputGroup, InputGroupAddon } from "@/component/ui/input-group"
import TextareaAutosize from "react-textarea-autosize"
export function InputGroupCustom() {
return (
<InputGroup>
<TextareaAutosize
data-slot="input-group-control"
className="dark:bg-input/30 flex field-sizing-content min-h-16 w-full resize-none rounded-md bg-transparent px-3 py-2 text-base transition-[color,box-shadow] outline-none"
placeholder="Autoresize textarea..."
/>
<InputGroupAddon align="block-end">how</InputGroupAddon>
</InputGroup>
)
}
```
## API Reference
### InputGroup
The main component that wraps inputs and addons.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | |
```tsx
<InputGroup>
<InputGroupInput />
<InputGroupAddon />
</InputGroup>
```
### InputGroupAddon
Displays icons, text, buttons, or other content alongside inputs.
<Callout icon={<IconInfoCircle />} title="Focus Navigation">
For proper focus navigation, the `InputGroupAddon` component should be placed
after the input. Set the `align` prop to position the addon.
</Callout>
| Prop | Type | Default |
| ----------- | ---------------------------------------------------------------- | ---------------- |
| `align` | `"inline-start" \| "inline-end" \| "block-start" \| "block-end"` | `"inline-start"` |
| `className` | `string` | |
```tsx
<InputGroupAddon align="inline-end">
<SearchIcon />
</InputGroupAddon>
```
**For `<InputGroupInput />`, use the `inline-start` or `inline-end` alignment. For `<InputGroupTextarea />`, use the `block-start` or `block-end` alignment.**
The `InputGroupAddon` component can have multiple `InputGroupButton` components and icons.
```tsx
<InputGroupAddon>
<InputGroupButton>Button</InputGroupButton>
<InputGroupButton>Button</InputGroupButton>
</InputGroupAddon>
```
### 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
<InputGroupButton>Button</InputGroupButton>
<InputGroupButton size="icon-xs" aria-label="Copy">
<CopyIcon />
</InputGroupButton>
```
### InputGroupInput
Replacement for `<Input />` 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 `<Input />` component.
```tsx
<InputGroup>
<InputGroupInput placeholder="Enter text..." />
<InputGroupAddon>
<SearchIcon />
</InputGroupAddon>
</InputGroup>
```
### InputGroupTextarea
Replacement for `<Textarea />` 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 `<Textarea />` component.
```tsx
<InputGroup>
<InputGroupTextarea placeholder="Enter message..." />
<InputGroupAddon align="block-end">
<InputGroupButton>Send</InputGroupButton>
</InputGroupAddon>
</InputGroup>
```
## 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).

View File

@@ -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
---
<ComponentPreview
styleName="radix-nova"
name="input-otp-demo"
description="An 6 digits input OTP."
/>
## 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
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
<Steps>
<Step>Run the following command:</Step>
```bash
npx shadcn@latest add input-otp
```
</Steps>
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install input-otp
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="input-otp"
title="components/ui/input-otp.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
InputOTP,
InputOTPGroup,
InputOTPSeparator,
InputOTPSlot,
} from "@/components/ui/input-otp"
```
```tsx showLineNumbers
<InputOTP maxLength={6}>
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
<InputOTPSlot index={2} />
</InputOTPGroup>
<InputOTPSeparator />
<InputOTPGroup>
<InputOTPSlot index={3} />
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
</InputOTPGroup>
</InputOTP>
```
## Examples
### Pattern
Use the `pattern` prop to define a custom pattern for the OTP input.
<ComponentPreview
styleName="radix-nova"
name="input-otp-pattern"
description="An input OTP with alphanumeric pattern."
/>
```tsx showLineNumbers {1,7}
import { REGEXP_ONLY_DIGITS_AND_CHARS } from "input-otp"
...
<InputOTP
maxLength={6}
pattern={REGEXP_ONLY_DIGITS_AND_CHARS}
>
<InputOTPGroup>
<InputOTPSlot index={0} />
{/* ... */}
</InputOTPGroup>
</InputOTP>
```
### Separator
You can use the `<InputOTPSeparator />` component to add a separator between the input groups.
<ComponentPreview
styleName="radix-nova"
name="input-otp-separator"
description="An input OTP with custom separator."
/>
```tsx showLineNumbers {4,15}
import {
InputOTP,
InputOTPGroup,
InputOTPSeparator,
InputOTPSlot,
} from "@/components/ui/input-otp"
...
<InputOTP maxLength={4}>
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
</InputOTPGroup>
<InputOTPSeparator />
<InputOTPGroup>
<InputOTPSlot index={2} />
<InputOTPSlot index={3} />
</InputOTPGroup>
</InputOTP>
```
### Controlled
You can use the `value` and `onChange` props to control the input value.
<ComponentPreview styleName="radix-nova" name="input-otp-controlled" />
### Form
<ComponentPreview styleName="radix-nova" name="input-otp-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.
<Callout className="mt-6">
**Note:** You are not required to update your code if you are using the
`render` prop. It is still supported.
</Callout>
<Steps>
<Step>Update to the latest version of `input-otp`.</Step>
```bash
npm install input-otp@latest
```
<Step>Update `input-otp.tsx`</Step>
```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]
```
<Step>Then replace the `render` prop in your code.</Step>
```diff showLineNumbers {2-12}
<InputOTP maxLength={6}>
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
<InputOTPSlot index={2} />
</InputOTPGroup>
<InputOTPSeparator />
<InputOTPGroup>
<InputOTPSlot index={3} />
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
</InputOTPGroup>
</InputOTP>
```
</Steps>
### 2024-03-19 Disabled
To add a disabled state to the input, update `<InputOTP />` as follows:
```tsx showLineNumbers title="input-otp.tsx" {4,7-11}
const InputOTP = React.forwardRef<
React.ElementRef<typeof OTPInput>,
React.ComponentPropsWithoutRef<typeof OTPInput>
>(({ className, containerClassName, ...props }, ref) => (
<OTPInput
ref={ref}
containerClassName={cn(
"flex items-center gap-2 has-[:disabled]:opacity-50",
containerClassName
)}
className={cn("disabled:cursor-not-allowed", className)}
{...props}
/>
))
InputOTP.displayName = "InputOTP"
```

View File

@@ -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
---
<ComponentPreview
styleName="radix-nova"
name="input-demo"
className="[&_input]:max-w-xs"
description="A form input component."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add input
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="input"
title="components/ui/input.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import { Input } from "@/components/ui/input"
```
```tsx
<Input />
```
## Examples
### Default
<ComponentPreview
styleName="radix-nova"
name="input-demo"
className="[&_input]:max-w-xs"
description="A form input component."
/>
### File
<ComponentPreview
styleName="radix-nova"
name="input-file"
className="[&_input]:max-w-xs"
description="A file input component."
/>
### Disabled
<ComponentPreview
styleName="radix-nova"
name="input-disabled"
className="[&_input]:max-w-xs"
description="A disabled input component."
/>
### With Label
<ComponentPreview
styleName="radix-nova"
name="input-with-label"
className="[&_input]:max-w-xs"
description="An input component with a label."
/>
### With Button
<ComponentPreview
styleName="radix-nova"
name="input-with-button"
className="[&_input]:max-w-xs"
description="An input component with a 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.

View File

@@ -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.
<ComponentPreview
styleName="radix-nova"
name="item-demo"
className="[&_.preview]:p-4"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add item
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="item"
title="components/ui/item.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Item,
ItemActions,
ItemContent,
ItemDescription,
ItemFooter,
ItemHeader,
ItemMedia,
ItemTitle,
} from "@/components/ui/item"
```
```tsx showLineNumbers
<Item>
<ItemHeader>Item Header</ItemHeader>
<ItemMedia />
<ItemContent>
<ItemTitle>Item</ItemTitle>
<ItemDescription>Item</ItemDescription>
</ItemContent>
<ItemActions />
<ItemFooter>Item Footer</ItemFooter>
</Item>
```
## 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
<ComponentPreview
styleName="radix-nova"
name="item-variant"
className="[&_.preview]:p-4"
/>
### 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.
<ComponentPreview
styleName="radix-nova"
name="item-size"
className="[&_.preview]:p-4"
/>
### Icon
<ComponentPreview
styleName="radix-nova"
name="item-icon"
className="[&_.preview]:p-4"
/>
### Avatar
<ComponentPreview
styleName="radix-nova"
name="item-avatar"
className="[&_.preview]:p-4"
/>
### Image
<ComponentPreview
styleName="radix-nova"
name="item-image"
className="[&_.preview]:p-4"
/>
### Group
<ComponentPreview
styleName="radix-nova"
name="item-group"
className="[&_.preview]:p-4"
/>
### Header
<ComponentPreview
styleName="radix-nova"
name="item-header"
className="[&_.preview]:p-4"
/>
### Link
To render an item as a link, use the `asChild` prop. The hover and focus states will be applied to the anchor element.
<ComponentPreview
styleName="radix-nova"
name="item-link"
className="[&_.preview]:p-4"
/>
```tsx showLineNumbers
<Item asChild>
<a href="/dashboard">
<ItemMedia />
<ItemContent>
<ItemTitle>Dashboard</ItemTitle>
<ItemDescription>Overview of your account and activity.</ItemDescription>
</ItemContent>
<ItemActions />
</a>
</Item>
```
### Dropdown
<ComponentPreview
styleName="radix-nova"
name="item-dropdown"
className="[&_.preview]:p-4"
/>
## 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 size="" variant="">
<ItemMedia />
<ItemContent>
<ItemTitle>Item</ItemTitle>
<ItemDescription>Item</ItemDescription>
</ItemContent>
<ItemActions />
</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 (
<Item asChild>
<a href="/dashboard">
<ItemMedia variant="icon">
<Home />
</ItemMedia>
<ItemContent>
<ItemTitle>Dashboard</ItemTitle>
<ItemDescription>
Overview of your account and activity.
</ItemDescription>
</ItemContent>
</a>
</Item>
)
}
```
### ItemGroup
The `ItemGroup` component is a container that groups related items together with consistent styling.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | |
```tsx
<ItemGroup>
<Item />
<Item />
</ItemGroup>
```
### ItemSeparator
The `ItemSeparator` component is a separator that separates items in the item group.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | |
```tsx
<ItemGroup>
<Item />
<ItemSeparator />
<Item />
</ItemGroup>
```
### 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
<ItemMedia variant="icon">
<Icon />
</ItemMedia>
```
```tsx
<ItemMedia variant="image">
<img src="..." alt="..." />
</ItemMedia>
```
### 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
<ItemContent>
<ItemTitle>Item</ItemTitle>
<ItemDescription>Item</ItemDescription>
</ItemContent>
```
### ItemTitle
Use the `ItemTitle` component to display the title of the item.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | |
```tsx
<ItemTitle>Item Title</ItemTitle>
```
### ItemDescription
Use the `ItemDescription` component to display the description of the item.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | |
```tsx
<ItemDescription>Item description</ItemDescription>
```
### ItemActions
Use the `ItemActions` component to display action buttons or other interactive elements.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | |
```tsx
<ItemActions>
<Button>Action</Button>
<Button>Action</Button>
</ItemActions>
```
### ItemHeader
Use the `ItemHeader` component to display a header in the item.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | |
```tsx
<ItemHeader>Item Header</ItemHeader>
```
### ItemFooter
Use the `ItemFooter` component to display a footer in the item.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | |
```tsx
<ItemFooter>Item Footer</ItemFooter>
```

View File

@@ -0,0 +1,109 @@
---
title: Kbd
description: Used to display textual user input from keyboard.
base: radix
component: true
---
<ComponentPreview styleName="radix-nova" name="kbd-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add kbd
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="kbd"
title="components/ui/kbd.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import { Kbd } from "@/components/ui/kbd"
```
```tsx
<Kbd>Ctrl</Kbd>
```
## Examples
### Group
Use the `KbdGroup` component to group keyboard keys together.
<ComponentPreview styleName="radix-nova" name="kbd-group" />
### Button
Use the `Kbd` component inside a `Button` component to display a keyboard key inside a button.
<ComponentPreview styleName="radix-nova" name="kbd-button" />
### Tooltip
You can use the `Kbd` component inside a `Tooltip` component to display a tooltip with a keyboard key.
<ComponentPreview styleName="radix-nova" name="kbd-tooltip" />
### Input Group
You can use the `Kbd` component inside a `InputGroupAddon` component to display a keyboard key inside an input group.
<ComponentPreview styleName="radix-nova" name="kbd-input-group" />
## API Reference
### Kbd
Use the `Kbd` component to display a keyboard key.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | `` |
```tsx
<Kbd>Ctrl</Kbd>
```
### KbdGroup
Use the `KbdGroup` component to group `Kbd` components together.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | `` |
```tsx
<KbdGroup>
<Kbd>Ctrl</Kbd>
<Kbd>B</Kbd>
</KbdGroup>
```

View File

@@ -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
---
<ComponentPreview
styleName="radix-nova"
name="label-demo"
description="A label"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add label
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-label
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="label"
title="components/ui/label.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import { Label } from "@/components/ui/label"
```
```tsx
<Label htmlFor="email">Your email address</Label>
```

View File

@@ -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
---
<ComponentPreview
styleName="radix-nova"
name="menubar-demo"
description="A menubar component."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add menubar
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-menubar
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="menubar"
title="components/ui/menubar.tsx"
styleName="radix-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Menubar,
MenubarContent,
MenubarItem,
MenubarMenu,
MenubarSeparator,
MenubarShortcut,
MenubarTrigger,
} from "@/components/ui/menubar"
```
```tsx showLineNumbers
<Menubar>
<MenubarMenu>
<MenubarTrigger>File</MenubarTrigger>
<MenubarContent>
<MenubarItem>
New Tab <MenubarShortcut>⌘T</MenubarShortcut>
</MenubarItem>
<MenubarItem>New Window</MenubarItem>
<MenubarSeparator />
<MenubarItem>Share</MenubarItem>
<MenubarSeparator />
<MenubarItem>Print</MenubarItem>
</MenubarContent>
</MenubarMenu>
</Menubar>
```

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