mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-06-28 07:04:20 +00:00
feat: add base and radix docs
This commit is contained in:
@@ -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 && (
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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
|
||||
|
||||
40
apps/v4/components/docs-base-switcher.tsx
Normal file
40
apps/v4/components/docs-base-switcher.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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."
|
||||
@@ -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
|
||||
|
||||
350
apps/v4/content/docs/components/base/button.mdx
Normal file
350
apps/v4/content/docs/components/base/button.mdx
Normal 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",
|
||||
// ...
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
@@ -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
|
||||
)}
|
||||
@@ -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>
|
||||
|
||||
@@ -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."
|
||||
@@ -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
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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" />
|
||||
@@ -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"
|
||||
/>
|
||||
@@ -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>
|
||||
|
||||
@@ -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} />
|
||||
@@ -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."
|
||||
@@ -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
|
||||
|
||||
@@ -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" />
|
||||
@@ -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" />
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
/>
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
/>
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
64
apps/v4/content/docs/components/base/meta.json
Normal file
64
apps/v4/content/docs/components/base/meta.json
Normal 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"
|
||||
]
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
/>
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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."
|
||||
/>
|
||||
@@ -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" />
|
||||
@@ -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."
|
||||
/>
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
@@ -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."
|
||||
/>
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
/>
|
||||
@@ -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
|
||||
@@ -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."
|
||||
/>
|
||||
@@ -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."
|
||||
/>
|
||||
@@ -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>
|
||||
|
||||
68
apps/v4/content/docs/components/base/typography.mdx
Normal file
68
apps/v4/content/docs/components/base/typography.mdx
Normal 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" />
|
||||
4
apps/v4/content/docs/components/meta.json
Normal file
4
apps/v4/content/docs/components/meta.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"title": "Components",
|
||||
"pages": ["..."]
|
||||
}
|
||||
82
apps/v4/content/docs/components/radix/accordion.mdx
Normal file
82
apps/v4/content/docs/components/radix/accordion.mdx
Normal 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>
|
||||
```
|
||||
94
apps/v4/content/docs/components/radix/alert-dialog.mdx
Normal file
94
apps/v4/content/docs/components/radix/alert-dialog.mdx
Normal 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>
|
||||
```
|
||||
65
apps/v4/content/docs/components/radix/alert.mdx
Normal file
65
apps/v4/content/docs/components/radix/alert.mdx
Normal 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>
|
||||
```
|
||||
70
apps/v4/content/docs/components/radix/aspect-ratio.mdx
Normal file
70
apps/v4/content/docs/components/radix/aspect-ratio.mdx
Normal 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>
|
||||
```
|
||||
71
apps/v4/content/docs/components/radix/avatar.mdx
Normal file
71
apps/v4/content/docs/components/radix/avatar.mdx
Normal 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>
|
||||
```
|
||||
77
apps/v4/content/docs/components/radix/badge.mdx
Normal file
77
apps/v4/content/docs/components/radix/badge.mdx
Normal 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>
|
||||
)
|
||||
}
|
||||
```
|
||||
222
apps/v4/content/docs/components/radix/breadcrumb.mdx
Normal file
222
apps/v4/content/docs/components/radix/breadcrumb.mdx
Normal 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."
|
||||
/>
|
||||
224
apps/v4/content/docs/components/radix/button-group.mdx
Normal file
224
apps/v4/content/docs/components/radix/button-group.mdx
Normal 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>
|
||||
)
|
||||
}
|
||||
```
|
||||
@@ -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>
|
||||
512
apps/v4/content/docs/components/radix/calendar.mdx
Normal file
512
apps/v4/content/docs/components/radix/calendar.mdx
Normal 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
|
||||
}}
|
||||
```
|
||||
78
apps/v4/content/docs/components/radix/card.mdx
Normal file
78
apps/v4/content/docs/components/radix/card.mdx
Normal 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>
|
||||
```
|
||||
312
apps/v4/content/docs/components/radix/carousel.mdx
Normal file
312
apps/v4/content/docs/components/radix/carousel.mdx
Normal 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.
|
||||
615
apps/v4/content/docs/components/radix/chart.mdx
Normal file
615
apps/v4/content/docs/components/radix/chart.mdx
Normal 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 />
|
||||
```
|
||||
67
apps/v4/content/docs/components/radix/checkbox.mdx
Normal file
67
apps/v4/content/docs/components/radix/checkbox.mdx
Normal 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 />
|
||||
```
|
||||
78
apps/v4/content/docs/components/radix/collapsible.mdx
Normal file
78
apps/v4/content/docs/components/radix/collapsible.mdx
Normal 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>
|
||||
```
|
||||
149
apps/v4/content/docs/components/radix/combobox.mdx
Normal file
149
apps/v4/content/docs/components/radix/combobox.mdx
Normal 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" />
|
||||
145
apps/v4/content/docs/components/radix/command.mdx
Normal file
145
apps/v4/content/docs/components/radix/command.mdx
Normal 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.
|
||||
80
apps/v4/content/docs/components/radix/context-menu.mdx
Normal file
80
apps/v4/content/docs/components/radix/context-menu.mdx
Normal 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>
|
||||
```
|
||||
884
apps/v4/content/docs/components/radix/data-table.mdx
Normal file
884
apps/v4/content/docs/components/radix/data-table.mdx
Normal 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} />
|
||||
```
|
||||
102
apps/v4/content/docs/components/radix/date-picker.mdx
Normal file
102
apps/v4/content/docs/components/radix/date-picker.mdx
Normal 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."
|
||||
/>
|
||||
126
apps/v4/content/docs/components/radix/dialog.mdx
Normal file
126
apps/v4/content/docs/components/radix/dialog.mdx
Normal 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>
|
||||
```
|
||||
101
apps/v4/content/docs/components/radix/drawer.mdx
Normal file
101
apps/v4/content/docs/components/radix/drawer.mdx
Normal 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" />
|
||||
119
apps/v4/content/docs/components/radix/dropdown-menu.mdx
Normal file
119
apps/v4/content/docs/components/radix/dropdown-menu.mdx
Normal 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" />
|
||||
223
apps/v4/content/docs/components/radix/empty.mdx
Normal file
223
apps/v4/content/docs/components/radix/empty.mdx
Normal 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>
|
||||
```
|
||||
378
apps/v4/content/docs/components/radix/field.mdx
Normal file
378
apps/v4/content/docs/components/radix/field.mdx
Normal 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.
|
||||
245
apps/v4/content/docs/components/radix/form.mdx
Normal file
245
apps/v4/content/docs/components/radix/form.mdx
Normal 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.
|
||||
76
apps/v4/content/docs/components/radix/hover-card.mdx
Normal file
76
apps/v4/content/docs/components/radix/hover-card.mdx
Normal 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>
|
||||
```
|
||||
304
apps/v4/content/docs/components/radix/input-group.mdx
Normal file
304
apps/v4/content/docs/components/radix/input-group.mdx
Normal 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).
|
||||
241
apps/v4/content/docs/components/radix/input-otp.mdx
Normal file
241
apps/v4/content/docs/components/radix/input-otp.mdx
Normal 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"
|
||||
```
|
||||
112
apps/v4/content/docs/components/radix/input.mdx
Normal file
112
apps/v4/content/docs/components/radix/input.mdx
Normal 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.
|
||||
362
apps/v4/content/docs/components/radix/item.mdx
Normal file
362
apps/v4/content/docs/components/radix/item.mdx
Normal 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>
|
||||
```
|
||||
109
apps/v4/content/docs/components/radix/kbd.mdx
Normal file
109
apps/v4/content/docs/components/radix/kbd.mdx
Normal 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>
|
||||
```
|
||||
67
apps/v4/content/docs/components/radix/label.mdx
Normal file
67
apps/v4/content/docs/components/radix/label.mdx
Normal 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>
|
||||
```
|
||||
89
apps/v4/content/docs/components/radix/menubar.mdx
Normal file
89
apps/v4/content/docs/components/radix/menubar.mdx
Normal 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
Reference in New Issue
Block a user