diff --git a/apps/v4/app/(app)/docs/[[...slug]]/page.tsx b/apps/v4/app/(app)/docs/[[...slug]]/page.tsx index f700a3c5b7..fad2c5bd2a 100644 --- a/apps/v4/app/(app)/docs/[[...slug]]/page.tsx +++ b/apps/v4/app/(app)/docs/[[...slug]]/page.tsx @@ -12,6 +12,7 @@ import z from "zod" import { source } from "@/lib/source" import { absoluteUrl } from "@/lib/utils" +import { DocsBaseSwitcher } from "@/components/docs-base-switcher" import { DocsCopyPage } from "@/components/docs-copy-page" import { DocsTableOfContents } from "@/components/docs-toc" import { OpenInV0Cta } from "@/components/open-in-v0-cta" @@ -147,6 +148,10 @@ export default async function Page(props: {

)} + {params.slug?.[0] === "components" && + (params.slug?.[1] === "radix" || params.slug?.[1] === "base") && ( + + )} {links ? (
{links?.doc && ( diff --git a/apps/v4/components/component-preview.tsx b/apps/v4/components/component-preview.tsx index a207dcb80f..5dbcf413c3 100644 --- a/apps/v4/components/component-preview.tsx +++ b/apps/v4/components/component-preview.tsx @@ -1,9 +1,8 @@ import Image from "next/image" +import { getRegistryComponent } from "@/lib/registry" import { ComponentPreviewTabs } from "@/components/component-preview-tabs" import { ComponentSource } from "@/components/component-source" -import { Index } from "@/registry/__index__" -import { type Style } from "@/registry/_legacy-styles" export function ComponentPreview({ name, @@ -16,14 +15,14 @@ export function ComponentPreview({ ...props }: React.ComponentProps<"div"> & { name: string - styleName?: Style["name"] + styleName?: string align?: "center" | "start" | "end" description?: string hideCode?: boolean type?: "block" | "component" | "example" chromeLessOnMobile?: boolean }) { - const Component = Index[styleName]?.[name]?.component + const Component = getRegistryComponent(name, styleName) if (!Component) { return ( diff --git a/apps/v4/components/component-source.tsx b/apps/v4/components/component-source.tsx index 55bf3acca3..b108b3f22f 100644 --- a/apps/v4/components/component-source.tsx +++ b/apps/v4/components/component-source.tsx @@ -8,7 +8,6 @@ import { cn } from "@/lib/utils" import { CodeCollapsibleWrapper } from "@/components/code-collapsible-wrapper" import { CopyButton } from "@/components/copy-button" import { getIconForLanguageExtension } from "@/components/icons" -import { type Style } from "@/registry/_legacy-styles" export async function ComponentSource({ name, @@ -24,7 +23,7 @@ export async function ComponentSource({ title?: string language?: string collapsible?: boolean - styleName?: Style["name"] + styleName?: string }) { if (!name && !src) { return null diff --git a/apps/v4/components/docs-base-switcher.tsx b/apps/v4/components/docs-base-switcher.tsx new file mode 100644 index 0000000000..b3e5d3ee71 --- /dev/null +++ b/apps/v4/components/docs-base-switcher.tsx @@ -0,0 +1,40 @@ +"use client" + +import Link from "next/link" +import { usePathname } from "next/navigation" + +import { cn } from "@/lib/utils" + +const BASES = [ + { name: "radix", label: "Radix UI" }, + { name: "base", label: "Base UI" }, +] + +export function DocsBaseSwitcher() { + const pathname = usePathname() + + // Extract base and component from /docs/components/{base}/{component}. + const match = pathname.match(/\/docs\/components\/(radix|base)\/(.+)/) + if (!match) return null + + const [, currentBase, component] = match + + return ( +
+ {BASES.map((base) => ( + + {base.label} + + ))} +
+ ) +} diff --git a/apps/v4/components/docs-sidebar.tsx b/apps/v4/components/docs-sidebar.tsx index 79dce7005d..458180dfe3 100644 --- a/apps/v4/components/docs-sidebar.tsx +++ b/apps/v4/components/docs-sidebar.tsx @@ -17,6 +17,10 @@ import { SidebarMenuItem, } from "@/registry/new-york-v4/ui/sidebar" +type PageTreeNode = (typeof source.pageTree)["children"][number] +type PageTreeFolder = Extract +type PageTreePage = Extract + const TOP_LEVEL_SECTIONS = [ { name: "Get Started", href: "/docs" }, { @@ -43,12 +47,67 @@ const TOP_LEVEL_SECTIONS = [ const EXCLUDED_SECTIONS = ["installation", "dark-mode"] const EXCLUDED_PAGES = ["/docs", "/docs/changelog"] +// Recursively find all pages in a folder tree. +function getAllPagesFromFolder(folder: PageTreeFolder): PageTreePage[] { + const pages: PageTreePage[] = [] + + for (const child of folder.children) { + if (child.type === "page") { + pages.push(child) + } else if (child.type === "folder") { + pages.push(...getAllPagesFromFolder(child)) + } + } + + return pages +} + +// Get the pages from a folder, handling nested base folders (radix/base). +function getPagesFromFolder( + folder: PageTreeFolder, + currentBase: string +): PageTreePage[] { + // For the components folder, find the base subfolder. + if (folder.$id === "components" || folder.name === "Components") { + for (const child of folder.children) { + if (child.type === "folder") { + // Match by $id or by name. + const isRadix = child.$id === "radix" || child.name === "Radix UI" + const isBase = child.$id === "base" || child.name === "Base UI" + + if ( + (currentBase === "radix" && isRadix) || + (currentBase === "base" && isBase) + ) { + return child.children.filter( + (c): c is PageTreePage => c.type === "page" + ) + } + } + } + + // Fallback: return all pages from nested folders. + return getAllPagesFromFolder(folder).filter( + (page) => !page.url.endsWith("/components") + ) + } + + // For other folders, return direct page children. + return folder.children.filter( + (child): child is PageTreePage => child.type === "page" + ) +} + export function DocsSidebar({ tree, ...props }: React.ComponentProps & { tree: typeof source.pageTree }) { const pathname = usePathname() + // Detect current base from URL (radix or base). + const baseMatch = pathname.match(/\/docs\/components\/(radix|base)\//) + const currentBase = baseMatch ? baseMatch[1] : "radix" // Default to radix. + return ( {item.type === "folder" && ( - {item.children.map((item) => { - if ( - !showMcpDocs && - item.type === "page" && - item.url?.includes("/mcp") - ) { + {getPagesFromFolder(item, currentBase).map((page) => { + if (!showMcpDocs && page.url.includes("/mcp")) { + return null + } + + if (EXCLUDED_PAGES.includes(page.url)) { return null } return ( - item.type === "page" && - !EXCLUDED_PAGES.includes(item.url) && ( - - - - - {item.name} - {PAGES_NEW.includes(item.url) && ( - - )} - - - - ) + + + + + {page.name} + {PAGES_NEW.includes(page.url) && ( + + )} + + + ) })} diff --git a/apps/v4/content/docs/components/accordion.mdx b/apps/v4/content/docs/components/base/accordion.mdx similarity index 91% rename from apps/v4/content/docs/components/accordion.mdx rename to apps/v4/content/docs/components/base/accordion.mdx index fb5cd44281..dba2d460c9 100644 --- a/apps/v4/content/docs/components/accordion.mdx +++ b/apps/v4/content/docs/components/base/accordion.mdx @@ -1,6 +1,7 @@ --- title: Accordion description: A vertically stacked set of interactive headings that each reveal a section of content. +base: base component: true links: doc: https://www.radix-ui.com/docs/primitives/components/accordion @@ -8,6 +9,7 @@ links: --- Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/alert-dialog.mdx b/apps/v4/content/docs/components/base/alert-dialog.mdx similarity index 93% rename from apps/v4/content/docs/components/alert-dialog.mdx rename to apps/v4/content/docs/components/base/alert-dialog.mdx index d85d30f057..56ef5541a5 100644 --- a/apps/v4/content/docs/components/alert-dialog.mdx +++ b/apps/v4/content/docs/components/base/alert-dialog.mdx @@ -2,6 +2,7 @@ title: Alert Dialog description: A modal dialog that interrupts the user with important content and expects a response. featured: true +base: base component: true links: doc: https://www.radix-ui.com/docs/primitives/components/alert-dialog @@ -9,6 +10,7 @@ links: --- Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/alert.mdx b/apps/v4/content/docs/components/base/alert.mdx similarity index 90% rename from apps/v4/content/docs/components/alert.mdx rename to apps/v4/content/docs/components/base/alert.mdx index ec3d6f2d42..98df719adb 100644 --- a/apps/v4/content/docs/components/alert.mdx +++ b/apps/v4/content/docs/components/base/alert.mdx @@ -1,10 +1,12 @@ --- title: Alert description: Displays a callout for user attention. +base: base component: true --- Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/aspect-ratio.mdx b/apps/v4/content/docs/components/base/aspect-ratio.mdx similarity index 89% rename from apps/v4/content/docs/components/aspect-ratio.mdx rename to apps/v4/content/docs/components/base/aspect-ratio.mdx index 958f6d054a..cb5ffd7399 100644 --- a/apps/v4/content/docs/components/aspect-ratio.mdx +++ b/apps/v4/content/docs/components/base/aspect-ratio.mdx @@ -1,6 +1,7 @@ --- title: Aspect Ratio description: Displays content within a desired ratio. +base: base component: true links: doc: https://www.radix-ui.com/docs/primitives/components/aspect-ratio @@ -8,6 +9,7 @@ links: --- Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/avatar.mdx b/apps/v4/content/docs/components/base/avatar.mdx similarity index 90% rename from apps/v4/content/docs/components/avatar.mdx rename to apps/v4/content/docs/components/base/avatar.mdx index a20c1259a9..88d9cc100f 100644 --- a/apps/v4/content/docs/components/avatar.mdx +++ b/apps/v4/content/docs/components/base/avatar.mdx @@ -1,6 +1,7 @@ --- title: Avatar description: An image element with a fallback for representing the user. +base: base component: true links: doc: https://www.radix-ui.com/docs/primitives/components/avatar @@ -8,6 +9,7 @@ links: --- Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/badge.mdx b/apps/v4/content/docs/components/base/badge.mdx similarity index 90% rename from apps/v4/content/docs/components/badge.mdx rename to apps/v4/content/docs/components/base/badge.mdx index 6f4abdb0cb..810115edd8 100644 --- a/apps/v4/content/docs/components/badge.mdx +++ b/apps/v4/content/docs/components/base/badge.mdx @@ -1,10 +1,12 @@ --- title: Badge description: Displays a badge or a component that looks like a badge. +base: base component: true --- Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/breadcrumb.mdx b/apps/v4/content/docs/components/base/breadcrumb.mdx similarity index 94% rename from apps/v4/content/docs/components/breadcrumb.mdx rename to apps/v4/content/docs/components/base/breadcrumb.mdx index 91c0ccbe1c..656a4d669e 100644 --- a/apps/v4/content/docs/components/breadcrumb.mdx +++ b/apps/v4/content/docs/components/base/breadcrumb.mdx @@ -1,10 +1,12 @@ --- title: Breadcrumb description: Displays the path to the current resource using a hierarchy of links. +base: base component: true --- Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -80,6 +86,7 @@ import { Use a custom component as `children` for `` to create a custom separator. @@ -111,6 +118,7 @@ import { SlashIcon } from "lucide-react" You can compose `` with a `` to create a dropdown in the breadcrumb. ` component to show a collapsed state when the breadcrumb is too long. `. @@ -205,6 +215,7 @@ Here's an example of a responsive breadcrumb that composes `` It displays a dropdown on desktop and a drawer on mobile. + ## Installation @@ -34,7 +35,11 @@ npm install @radix-ui/react-slot Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -85,19 +90,19 @@ import { Set the `orientation` prop to change the button group layout. - + ### Size Control the size of buttons using the `size` prop on individual buttons. - + ### Nested Nest `` components to create button groups with spacing. - + ### Separator @@ -105,43 +110,43 @@ The `ButtonGroupSeparator` component visually divides buttons within a group. Buttons with variant `outline` do not need a separator since they have a border. For other variants, a separator is recommended to improve the visual hierarchy. - + ### Split Create a split button group by adding two buttons separated by a `ButtonGroupSeparator`. - + ### Input Wrap an `Input` component with buttons. - + ### Input Group Wrap an `InputGroup` component to create complex input layouts. - + ### Dropdown Menu Create a split button group with a `DropdownMenu` component. - + ### Select Pair with a `Select` component. - + ### Popover Use with a `Popover` component. - + ## API Reference diff --git a/apps/v4/content/docs/components/base/button.mdx b/apps/v4/content/docs/components/base/button.mdx new file mode 100644 index 0000000000..4943f9b98b --- /dev/null +++ b/apps/v4/content/docs/components/base/button.mdx @@ -0,0 +1,350 @@ +--- +title: Button +description: Displays a button or a component that looks like a button. +featured: true +base: base +component: true +--- + +import { InfoIcon } from "lucide-react" + +}> +**Updated:** We have updated the button component to add new sizes: `icon-sm` and `icon-lg`. See the +[changelog](/docs/components/button#changelog) for more details. Follow the +instructions to update your project. + + + + + +```tsx showLineNumbers + + +``` + +## Installation + + + + + CLI + Manual + + + +```bash +npx shadcn@latest add button +``` + + + + + + + +Install the following dependencies: + +```bash +npm install @radix-ui/react-slot +``` + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { Button } from "@/components/ui/button" +``` + +```tsx + +``` + +## Cursor + +Tailwind v4 [switched](https://tailwindcss.com/docs/upgrade-guide#buttons-use-the-default-cursor) from `cursor: pointer` to `cursor: default` for the button component. + +If you want to keep the `cursor: pointer` behavior, add the following code to your CSS file: + +```css showLineNumbers title="globals.css" +@layer base { + button:not(:disabled), + [role="button"]:not(:disabled) { + cursor: pointer; + } +} +``` + +## Examples + +### Size + + + +```tsx +// Small + + + +// Medium + + + +// Large + + +``` + +### Default + + + +```tsx + +``` + +### Outline + + + +```tsx + +``` + +### Secondary + + + +```tsx + +``` + +### Ghost + + + +```tsx + +``` + +### Destructive + + + +```tsx + +``` + +### Link + + + +```tsx + +``` + +### Icon + + + +```tsx showLineNumbers + +``` + +### With Icon + +The spacing between the icon and the text is automatically adjusted +based on the size of the button. You do not need any margin on the icon. + + + +```tsx + +``` + +### Rounded + +Use the `rounded-full` class to make the button rounded. + + + +```tsx + +``` + +### Spinner + + + +```tsx showLineNumbers + +``` + +### Button Group + +To create a button group, use the `ButtonGroup` component. See the [Button Group](/docs/components/button-group) documentation for more details. + + + +```tsx showLineNumbers + + + + + + + + + + + + + + + + + + +``` + +### 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 ( + + ) +} +``` + +## API Reference + +### Button + +The `Button` component is a wrapper around the `button` element that adds a variety of styles and functionality. + +| Prop | Type | Default | +| --------- | ----------------------------------------------------------------------------- | ----------- | +| `variant` | `"default" \| "outline" \| "ghost" \| "destructive" \| "secondary" \| "link"` | `"default"` | +| `size` | `"default" \| "sm" \| "lg" \| "icon" \| "icon-sm" \| "icon-lg"` | `"default"` | +| `asChild` | `boolean` | `false` | + +## Changelog + +### 2025-09-24 New sizes + +We have added two new sizes to the button component: `icon-sm` and `icon-lg`. These sizes are used to create icon buttons. To add them, edit `button.tsx` and add the following code under `size` in `buttonVariants`: + +```tsx showLineNumbers title="components/ui/button.tsx" +const buttonVariants = cva("...", { + variants: { + size: { + // ... + "icon-sm": "size-8", + "icon-lg": "size-10", + // ... + }, + }, +}) +``` diff --git a/apps/v4/content/docs/components/calendar.mdx b/apps/v4/content/docs/components/base/calendar.mdx similarity index 96% rename from apps/v4/content/docs/components/calendar.mdx rename to apps/v4/content/docs/components/base/calendar.mdx index 5ecf2dfcc5..4400811163 100644 --- a/apps/v4/content/docs/components/calendar.mdx +++ b/apps/v4/content/docs/components/base/calendar.mdx @@ -1,12 +1,14 @@ --- title: Calendar description: A date field component that allows users to enter and edit date. +base: base component: true links: doc: https://react-day-picker.js.org --- Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -103,6 +109,7 @@ To use the Persian calendar, edit `components/ui/calendar.tsx` and replace `reac ``` span]:text-xs [&>span]:opacity-70", + "data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 flex aspect-square h-auto w-full min-w-[--cell-size] flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] data-[range-end=true]:rounded-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md [&>span]:text-xs [&>span]:opacity-70", defaultClassNames.day, className )} diff --git a/apps/v4/content/docs/components/card.mdx b/apps/v4/content/docs/components/base/card.mdx similarity index 83% rename from apps/v4/content/docs/components/card.mdx rename to apps/v4/content/docs/components/base/card.mdx index c5b2633b34..58530977d3 100644 --- a/apps/v4/content/docs/components/card.mdx +++ b/apps/v4/content/docs/components/base/card.mdx @@ -1,10 +1,15 @@ --- title: Card description: Displays a card with header, content, and footer. +base: base component: true --- - + ## Installation @@ -28,7 +33,11 @@ npx shadcn@latest add card Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/carousel.mdx b/apps/v4/content/docs/components/base/carousel.mdx similarity index 96% rename from apps/v4/content/docs/components/carousel.mdx rename to apps/v4/content/docs/components/base/carousel.mdx index 73461ccc8c..02e51d9fe3 100644 --- a/apps/v4/content/docs/components/carousel.mdx +++ b/apps/v4/content/docs/components/base/carousel.mdx @@ -1,6 +1,7 @@ --- title: Carousel description: A carousel with motion and swipe built using Embla. +base: base component: true links: doc: https://www.embla-carousel.com/get-started/react @@ -8,6 +9,7 @@ links: --- Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -87,6 +93,7 @@ import { To set the size of the items, you can use the `basis` utility class on the ``. Copy and paste the following code into `components/ui/chart.tsx`. - + Add the following colors to your CSS file @@ -197,9 +203,14 @@ You can now build your chart using Recharts components. - + @@ -231,6 +242,7 @@ import { Bar, BarChart, CartesianGrid } from "recharts" ``` @@ -269,6 +281,7 @@ import { Bar, BarChart, CartesianGrid, XAxis } from "recharts" ``` @@ -310,6 +323,7 @@ import { ChartTooltip, ChartTooltipContent } from "@/components/ui/chart" ``` @@ -352,6 +366,7 @@ import { ChartLegend, ChartLegendContent } from "@/components/ui/chart" ``` @@ -476,6 +491,7 @@ const chartData = [ A chart tooltip contains a label, name, indicator and value. You can use a combination of these to customize your tooltip. + ## Installation @@ -37,7 +42,11 @@ npm install @radix-ui/react-checkbox Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/collapsible.mdx b/apps/v4/content/docs/components/base/collapsible.mdx similarity index 90% rename from apps/v4/content/docs/components/collapsible.mdx rename to apps/v4/content/docs/components/base/collapsible.mdx index d3b18f7bcd..aa5daa519e 100644 --- a/apps/v4/content/docs/components/collapsible.mdx +++ b/apps/v4/content/docs/components/base/collapsible.mdx @@ -1,6 +1,7 @@ --- title: Collapsible description: An interactive component which expands/collapses a panel. +base: base component: true featured: true links: @@ -9,6 +10,7 @@ links: --- @@ -41,7 +43,11 @@ npm install @radix-ui/react-collapsible Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/combobox.mdx b/apps/v4/content/docs/components/base/combobox.mdx similarity index 93% rename from apps/v4/content/docs/components/combobox.mdx rename to apps/v4/content/docs/components/base/combobox.mdx index a8788f7f24..61c5b18d72 100644 --- a/apps/v4/content/docs/components/combobox.mdx +++ b/apps/v4/content/docs/components/base/combobox.mdx @@ -1,10 +1,12 @@ --- title: Combobox description: Autocomplete input and command palette with a list of suggestions. +base: base component: true --- @@ -123,17 +125,19 @@ export function ExampleCombobox() { ### Combobox ### Popover - + ### Dropdown menu @@ -142,4 +146,4 @@ export function ExampleCombobox() { You can create a responsive combobox by using the `` on desktop and the `` components on mobile. - + diff --git a/apps/v4/content/docs/components/command.mdx b/apps/v4/content/docs/components/base/command.mdx similarity index 95% rename from apps/v4/content/docs/components/command.mdx rename to apps/v4/content/docs/components/base/command.mdx index 7784dae9ee..62ba9db88d 100644 --- a/apps/v4/content/docs/components/command.mdx +++ b/apps/v4/content/docs/components/base/command.mdx @@ -1,12 +1,14 @@ --- title: Command description: Fast, composable, unstyled command menu for React. +base: base component: true links: doc: https://cmdk.paco.me --- Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -96,6 +102,7 @@ import { ### Dialog diff --git a/apps/v4/content/docs/components/context-menu.mdx b/apps/v4/content/docs/components/base/context-menu.mdx similarity index 91% rename from apps/v4/content/docs/components/context-menu.mdx rename to apps/v4/content/docs/components/base/context-menu.mdx index 81c599d69e..92ff5dbd6e 100644 --- a/apps/v4/content/docs/components/context-menu.mdx +++ b/apps/v4/content/docs/components/base/context-menu.mdx @@ -1,6 +1,7 @@ --- title: Context Menu description: Displays a menu to the user — such as a set of actions or functions — triggered by a button. +base: base component: true links: doc: https://www.radix-ui.com/docs/primitives/components/context-menu @@ -8,6 +9,7 @@ links: --- @@ -40,7 +42,11 @@ npm install @radix-ui/react-context-menu Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/data-table.mdx b/apps/v4/content/docs/components/base/data-table.mdx similarity index 98% rename from apps/v4/content/docs/components/data-table.mdx rename to apps/v4/content/docs/components/base/data-table.mdx index b66f08572a..738ed06234 100644 --- a/apps/v4/content/docs/components/data-table.mdx +++ b/apps/v4/content/docs/components/base/data-table.mdx @@ -1,12 +1,17 @@ --- title: Data Table description: Powerful table and datagrids built using TanStack Table. +base: base component: true links: doc: https://tanstack.com/table/v8/docs/introduction --- - + ## Introduction @@ -856,7 +861,10 @@ export const columns = [ Add pagination controls to your table including page size and selection count. - + ```tsx @@ -866,7 +874,10 @@ Add pagination controls to your table including page size and selection count. A component to toggle column visibility. - + ```tsx diff --git a/apps/v4/content/docs/components/date-picker.mdx b/apps/v4/content/docs/components/base/date-picker.mdx similarity index 94% rename from apps/v4/content/docs/components/date-picker.mdx rename to apps/v4/content/docs/components/base/date-picker.mdx index 24ca640ef0..b7dee5ed78 100644 --- a/apps/v4/content/docs/components/date-picker.mdx +++ b/apps/v4/content/docs/components/base/date-picker.mdx @@ -1,10 +1,12 @@ --- title: Date Picker description: A date picker component with range and presets. +base: base component: true --- @@ -41,7 +43,11 @@ npm install @radix-ui/react-dialog Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -83,7 +89,7 @@ import { ### Custom close button - + ## Notes diff --git a/apps/v4/content/docs/components/drawer.mdx b/apps/v4/content/docs/components/base/drawer.mdx similarity index 86% rename from apps/v4/content/docs/components/drawer.mdx rename to apps/v4/content/docs/components/base/drawer.mdx index 7314414862..af179960d9 100644 --- a/apps/v4/content/docs/components/drawer.mdx +++ b/apps/v4/content/docs/components/base/drawer.mdx @@ -1,12 +1,17 @@ --- title: Drawer description: A drawer component for React. +base: base component: true links: doc: https://vaul.emilkowal.ski/getting-started --- - + ## About @@ -40,7 +45,11 @@ npm install vaul Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -89,4 +98,4 @@ import { You can combine the `Dialog` and `Drawer` components to create a responsive dialog. This renders a `Dialog` component on desktop and a `Drawer` on mobile. - + diff --git a/apps/v4/content/docs/components/dropdown-menu.mdx b/apps/v4/content/docs/components/base/dropdown-menu.mdx similarity index 89% rename from apps/v4/content/docs/components/dropdown-menu.mdx rename to apps/v4/content/docs/components/base/dropdown-menu.mdx index 39af9d2b3f..489f6350ce 100644 --- a/apps/v4/content/docs/components/dropdown-menu.mdx +++ b/apps/v4/content/docs/components/base/dropdown-menu.mdx @@ -2,6 +2,7 @@ title: Dropdown Menu description: Displays a menu to the user — such as a set of actions or functions — triggered by a button. featured: true +base: base component: true links: doc: https://www.radix-ui.com/docs/primitives/components/dropdown-menu @@ -9,6 +10,7 @@ links: --- @@ -41,7 +43,11 @@ npm install @radix-ui/react-dropdown-menu Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -83,6 +89,7 @@ import { ### Checkboxes @@ -90,6 +97,7 @@ import { ### Radio Group @@ -108,4 +116,4 @@ Use `modal={false}` on the `DropdownMenu` component. ``` - + diff --git a/apps/v4/content/docs/components/empty.mdx b/apps/v4/content/docs/components/base/empty.mdx similarity index 85% rename from apps/v4/content/docs/components/empty.mdx rename to apps/v4/content/docs/components/base/empty.mdx index a14e61ddfb..f29bdfec7c 100644 --- a/apps/v4/content/docs/components/empty.mdx +++ b/apps/v4/content/docs/components/base/empty.mdx @@ -1,10 +1,15 @@ --- title: Empty description: Use the Empty component to display an empty state. +base: base component: true --- - + ## Installation @@ -28,7 +33,11 @@ npx shadcn@latest add empty Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -73,6 +82,7 @@ import { Use the `border` utility class to create an outline empty state. @@ -81,25 +91,41 @@ Use the `border` utility class to create an outline empty state. Use the `bg-*` and `bg-gradient-*` utilities to add a background to the empty state. - + ### Avatar Use the `EmptyMedia` component to display an avatar in the empty state. - + ### Avatar Group Use the `EmptyMedia` component to display an avatar group in the empty state. - + ### InputGroup You can add an `InputGroup` component to the `EmptyContent` component. - + ## API Reference diff --git a/apps/v4/content/docs/components/field.mdx b/apps/v4/content/docs/components/base/field.mdx similarity index 88% rename from apps/v4/content/docs/components/field.mdx rename to apps/v4/content/docs/components/base/field.mdx index 72ea66badc..8f96e26cb2 100644 --- a/apps/v4/content/docs/components/field.mdx +++ b/apps/v4/content/docs/components/base/field.mdx @@ -1,10 +1,12 @@ --- title: Field description: Combine labels, controls, and help text to compose accessible form fields and grouped inputs. +base: base component: true --- @@ -31,7 +33,11 @@ npx shadcn@latest add field Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -106,47 +112,87 @@ See the [Form](/docs/forms) documentation for building forms with the `Field` co ### Input - + ### Textarea - + ### Select - + ### Slider - + ### Fieldset - + ### Checkbox - + ### Radio - + ### Switch - + ### Choice Card Wrap `Field` components inside `FieldLabel` to create selectable field groups. This works with `RadioItem`, `Checkbox` and `Switch` components. - + ### Field Group Stack `Field` components with `FieldGroup`. Add `FieldSeparator` to divide them. - + ## Responsive Layout @@ -155,6 +201,7 @@ Stack `Field` components with `FieldGroup`. Add `FieldSeparator` to divide them. - **Responsive fields:** Set `orientation="responsive"` for automatic column layouts inside container-aware parents. Apply `@container/field-group` classes on `FieldGroup` to switch orientations at specific breakpoints. diff --git a/apps/v4/content/docs/components/form.mdx b/apps/v4/content/docs/components/base/form.mdx similarity index 98% rename from apps/v4/content/docs/components/form.mdx rename to apps/v4/content/docs/components/base/form.mdx index 8a89d57de4..3a8d903e7c 100644 --- a/apps/v4/content/docs/components/form.mdx +++ b/apps/v4/content/docs/components/base/form.mdx @@ -115,7 +115,11 @@ npm install @radix-ui/react-label @radix-ui/react-slot react-hook-form @hookform Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/hover-card.mdx b/apps/v4/content/docs/components/base/hover-card.mdx similarity index 84% rename from apps/v4/content/docs/components/hover-card.mdx rename to apps/v4/content/docs/components/base/hover-card.mdx index 8dacd7e557..448c49e760 100644 --- a/apps/v4/content/docs/components/hover-card.mdx +++ b/apps/v4/content/docs/components/base/hover-card.mdx @@ -1,13 +1,18 @@ --- title: Hover Card description: For sighted users to preview content available behind a link. +base: base component: true links: doc: https://www.radix-ui.com/docs/primitives/components/hover-card api: https://www.radix-ui.com/docs/primitives/components/hover-card#api-reference --- - + ## Installation @@ -37,7 +42,11 @@ npm install @radix-ui/react-hover-card Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/input-group.mdx b/apps/v4/content/docs/components/base/input-group.mdx similarity index 85% rename from apps/v4/content/docs/components/input-group.mdx rename to apps/v4/content/docs/components/base/input-group.mdx index e46960e8a0..28e2eba954 100644 --- a/apps/v4/content/docs/components/input-group.mdx +++ b/apps/v4/content/docs/components/base/input-group.mdx @@ -1,12 +1,17 @@ --- title: Input Group description: Display additional information or actions to an input or textarea. +base: base component: true --- import { IconInfoCircle } from "@tabler/icons-react" - + ## Installation @@ -30,7 +35,11 @@ npx shadcn@latest add input-group Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -69,55 +78,88 @@ import { ### Icon - + ### Text Display additional text information alongside inputs. - + ### Button Add buttons to perform actions within the input group. - + ### Tooltip Add tooltips to provide additional context or help. - + ### Textarea Input groups also work with textarea components. Use `block-start` or `block-end` for alignment. - + ### Spinner Show loading indicators while processing input. - + ### Label Add labels within input groups to improve accessibility. - + ### Dropdown Pair input groups with dropdown menus for complex interactions. - + ### Button Group Wrap input groups with button groups to create prefixes and suffixes. @@ -129,6 +171,7 @@ Add the `data-slot="input-group-control"` attribute to your custom input for aut No style is applied to the custom input. Apply your own styles using the `className` prop. diff --git a/apps/v4/content/docs/components/input-otp.mdx b/apps/v4/content/docs/components/base/input-otp.mdx similarity index 92% rename from apps/v4/content/docs/components/input-otp.mdx rename to apps/v4/content/docs/components/base/input-otp.mdx index 9c56f18be3..c2897c683f 100644 --- a/apps/v4/content/docs/components/input-otp.mdx +++ b/apps/v4/content/docs/components/base/input-otp.mdx @@ -1,12 +1,17 @@ --- title: Input OTP description: Accessible one-time password component with copy paste functionality. +base: base component: true links: doc: https://input-otp.rodz.dev --- - + ## About @@ -46,7 +51,11 @@ npm install input-otp Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -90,6 +99,7 @@ import { Use the `pattern` prop to define a custom pattern for the OTP input. @@ -115,6 +125,7 @@ import { REGEXP_ONLY_DIGITS_AND_CHARS } from "input-otp" You can use the `` component to add a separator between the input groups. @@ -146,11 +157,11 @@ import { You can use the `value` and `onChange` props to control the input value. - + ### Form - + ## Changelog diff --git a/apps/v4/content/docs/components/input.mdx b/apps/v4/content/docs/components/base/input.mdx similarity index 86% rename from apps/v4/content/docs/components/input.mdx rename to apps/v4/content/docs/components/base/input.mdx index c4638ca6b1..5ff77703cc 100644 --- a/apps/v4/content/docs/components/input.mdx +++ b/apps/v4/content/docs/components/base/input.mdx @@ -1,10 +1,12 @@ --- title: Input description: Displays a form input field or a component that looks like an input field. +base: base component: true --- Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -57,6 +63,7 @@ import { Input } from "@/components/ui/input" ### Default + ## Installation @@ -32,7 +37,11 @@ npx shadcn@latest add item Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -80,39 +89,71 @@ If you only need to display content such as a title, description, and actions, u ### Variants - + ### Size The `Item` component has different sizes for different use cases. For example, you can use the `sm` size for a compact item or the `default` size for a standard item. - + ### Icon - + ### Avatar - + ### Image - + ### Group - + ### Header - + ### Link To render an item as a link, use the `asChild` prop. The hover and focus states will be applied to the anchor element. - + ```tsx showLineNumbers @@ -129,7 +170,11 @@ To render an item as a link, use the `asChild` prop. The hover and focus states ### Dropdown - + ## API Reference diff --git a/apps/v4/content/docs/components/kbd.mdx b/apps/v4/content/docs/components/base/kbd.mdx similarity index 79% rename from apps/v4/content/docs/components/kbd.mdx rename to apps/v4/content/docs/components/base/kbd.mdx index 47e934eca1..b8cd804137 100644 --- a/apps/v4/content/docs/components/kbd.mdx +++ b/apps/v4/content/docs/components/base/kbd.mdx @@ -1,10 +1,11 @@ --- title: Kbd description: Used to display textual user input from keyboard. +base: base component: true --- - + ## Installation @@ -28,7 +29,11 @@ npx shadcn@latest add kbd Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -54,25 +59,25 @@ import { Kbd } from "@/components/ui/kbd" Use the `KbdGroup` component to group keyboard keys together. - + ### Button Use the `Kbd` component inside a `Button` component to display a keyboard key inside a button. - + ### Tooltip You can use the `Kbd` component inside a `Tooltip` component to display a tooltip with a keyboard key. - + ### Input Group You can use the `Kbd` component inside a `InputGroupAddon` component to display a keyboard key inside an input group. - + ## API Reference diff --git a/apps/v4/content/docs/components/label.mdx b/apps/v4/content/docs/components/base/label.mdx similarity index 82% rename from apps/v4/content/docs/components/label.mdx rename to apps/v4/content/docs/components/base/label.mdx index f2f60e9282..de83018cff 100644 --- a/apps/v4/content/docs/components/label.mdx +++ b/apps/v4/content/docs/components/base/label.mdx @@ -1,13 +1,18 @@ --- title: Label description: Renders an accessible label associated with controls. +base: base component: true links: doc: https://www.radix-ui.com/docs/primitives/components/label api: https://www.radix-ui.com/docs/primitives/components/label#api-reference --- - + ## Installation @@ -37,7 +42,11 @@ npm install @radix-ui/react-label Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/menubar.mdx b/apps/v4/content/docs/components/base/menubar.mdx similarity index 87% rename from apps/v4/content/docs/components/menubar.mdx rename to apps/v4/content/docs/components/base/menubar.mdx index a96439dad8..aab7a7fb18 100644 --- a/apps/v4/content/docs/components/menubar.mdx +++ b/apps/v4/content/docs/components/base/menubar.mdx @@ -1,13 +1,18 @@ --- title: Menubar description: A visually persistent menu common in desktop applications that provides quick access to a consistent set of commands. +base: base component: true links: doc: https://www.radix-ui.com/docs/primitives/components/menubar api: https://www.radix-ui.com/docs/primitives/components/menubar#api-reference --- - + ## Installation @@ -37,7 +42,11 @@ npm install @radix-ui/react-menubar Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/base/meta.json b/apps/v4/content/docs/components/base/meta.json new file mode 100644 index 0000000000..876c74b3f0 --- /dev/null +++ b/apps/v4/content/docs/components/base/meta.json @@ -0,0 +1,64 @@ +{ + "title": "Base UI", + "pages": [ + "accordion", + "alert", + "alert-dialog", + "aspect-ratio", + "avatar", + "badge", + "breadcrumb", + "button", + "button-group", + "calendar", + "card", + "carousel", + "chart", + "checkbox", + "collapsible", + "combobox", + "command", + "context-menu", + "data-table", + "date-picker", + "dialog", + "drawer", + "dropdown-menu", + "empty", + "field", + "form", + "hover-card", + "input", + "input-group", + "input-otp", + "item", + "kbd", + "label", + "menubar", + "native-select", + "navigation-menu", + "pagination", + "popover", + "progress", + "radio-group", + "resizable", + "scroll-area", + "select", + "separator", + "sheet", + "sidebar", + "skeleton", + "slider", + "sonner", + "spinner", + "switch", + "table", + "tabs", + "textarea", + "toast", + "toggle", + "toggle-group", + "tooltip", + "typography" + ] +} diff --git a/apps/v4/content/docs/components/native-select.mdx b/apps/v4/content/docs/components/base/native-select.mdx similarity index 90% rename from apps/v4/content/docs/components/native-select.mdx rename to apps/v4/content/docs/components/base/native-select.mdx index 77e4d11b1c..2a4204cf97 100644 --- a/apps/v4/content/docs/components/native-select.mdx +++ b/apps/v4/content/docs/components/base/native-select.mdx @@ -1,6 +1,7 @@ --- title: Native Select description: A styled native HTML select element with consistent design system integration. +base: base component: true --- @@ -11,7 +12,7 @@ import { InfoIcon } from "lucide-react" component. - + ## Installation @@ -35,7 +36,11 @@ npx shadcn@latest add native-select Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -74,7 +79,7 @@ import { Organize options using `NativeSelectOptGroup` for better categorization. - + ```tsx showLineNumbers @@ -96,13 +101,13 @@ Organize options using `NativeSelectOptGroup` for better categorization. Disable individual options or the entire select component. - + ### Invalid State Show validation errors with the `aria-invalid` attribute and error styling. - + ```tsx showLineNumbers @@ -117,13 +122,13 @@ Show validation errors with the `aria-invalid` attribute and error styling. Use with form libraries like React Hook Form for controlled components. - + ### Input Group Integration Combine with `InputGroup` for complex input layouts. - + ## Native Select vs Select diff --git a/apps/v4/content/docs/components/navigation-menu.mdx b/apps/v4/content/docs/components/base/navigation-menu.mdx similarity index 98% rename from apps/v4/content/docs/components/navigation-menu.mdx rename to apps/v4/content/docs/components/base/navigation-menu.mdx index 582d634b6c..affd8d0b2b 100644 --- a/apps/v4/content/docs/components/navigation-menu.mdx +++ b/apps/v4/content/docs/components/base/navigation-menu.mdx @@ -1,6 +1,7 @@ --- title: Navigation Menu description: A collection of links for navigating websites. +base: base component: true links: doc: https://www.radix-ui.com/docs/primitives/components/navigation-menu @@ -8,6 +9,7 @@ links: --- diff --git a/apps/v4/content/docs/components/pagination.mdx b/apps/v4/content/docs/components/base/pagination.mdx similarity index 93% rename from apps/v4/content/docs/components/pagination.mdx rename to apps/v4/content/docs/components/base/pagination.mdx index a1e79dd892..e6139ffe82 100644 --- a/apps/v4/content/docs/components/pagination.mdx +++ b/apps/v4/content/docs/components/base/pagination.mdx @@ -1,10 +1,12 @@ --- title: Pagination description: Pagination with page navigation, next and previous links. +base: base component: true --- @@ -31,7 +33,11 @@ npx shadcn@latest add pagination Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/popover.mdx b/apps/v4/content/docs/components/base/popover.mdx similarity index 90% rename from apps/v4/content/docs/components/popover.mdx rename to apps/v4/content/docs/components/base/popover.mdx index 53e1e933bf..67ad1b1da1 100644 --- a/apps/v4/content/docs/components/popover.mdx +++ b/apps/v4/content/docs/components/base/popover.mdx @@ -1,6 +1,7 @@ --- title: Popover description: Displays rich content in a portal, triggered by a button. +base: base component: true links: doc: https://www.radix-ui.com/docs/primitives/components/popover @@ -8,6 +9,7 @@ links: --- @@ -40,7 +42,11 @@ npm install @radix-ui/react-popover Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/progress.mdx b/apps/v4/content/docs/components/base/progress.mdx similarity index 89% rename from apps/v4/content/docs/components/progress.mdx rename to apps/v4/content/docs/components/base/progress.mdx index fba7eb68e7..df3ede6f93 100644 --- a/apps/v4/content/docs/components/progress.mdx +++ b/apps/v4/content/docs/components/base/progress.mdx @@ -1,6 +1,7 @@ --- title: Progress description: Displays an indicator showing the completion progress of a task, typically displayed as a progress bar. +base: base component: true links: doc: https://www.radix-ui.com/docs/primitives/components/progress @@ -8,6 +9,7 @@ links: --- @@ -40,7 +42,11 @@ npm install @radix-ui/react-progress Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/radio-group.mdx b/apps/v4/content/docs/components/base/radio-group.mdx similarity index 91% rename from apps/v4/content/docs/components/radio-group.mdx rename to apps/v4/content/docs/components/base/radio-group.mdx index 0b571c8354..3043cbe58f 100644 --- a/apps/v4/content/docs/components/radio-group.mdx +++ b/apps/v4/content/docs/components/base/radio-group.mdx @@ -1,6 +1,7 @@ --- title: Radio Group description: A set of checkable buttons—known as radio buttons—where no more than one of the buttons can be checked at a time. +base: base component: true links: doc: https://www.radix-ui.com/docs/primitives/components/radio-group @@ -8,6 +9,7 @@ links: --- @@ -40,7 +42,11 @@ npm install @radix-ui/react-radio-group Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/resizable.mdx b/apps/v4/content/docs/components/base/resizable.mdx similarity index 93% rename from apps/v4/content/docs/components/resizable.mdx rename to apps/v4/content/docs/components/base/resizable.mdx index bda70158a6..f180db53d3 100644 --- a/apps/v4/content/docs/components/resizable.mdx +++ b/apps/v4/content/docs/components/base/resizable.mdx @@ -1,6 +1,7 @@ --- title: Resizable description: Accessible resizable panel groups and layouts with keyboard support. +base: base component: true links: doc: https://github.com/bvaughn/react-resizable-panels @@ -8,6 +9,7 @@ links: --- @@ -44,7 +46,11 @@ npm install react-resizable-panels Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -79,6 +85,7 @@ import { Use the `direction` prop to set the direction of the resizable panels. @@ -106,6 +113,7 @@ export default function Example() { You can set or hide the handle by using the `withHandle` prop on the `ResizableHandle` component. diff --git a/apps/v4/content/docs/components/scroll-area.mdx b/apps/v4/content/docs/components/base/scroll-area.mdx similarity index 88% rename from apps/v4/content/docs/components/scroll-area.mdx rename to apps/v4/content/docs/components/base/scroll-area.mdx index c5c33a4e85..449e342214 100644 --- a/apps/v4/content/docs/components/scroll-area.mdx +++ b/apps/v4/content/docs/components/base/scroll-area.mdx @@ -1,6 +1,7 @@ --- title: Scroll Area description: Augments native scroll functionality for custom, cross-browser styling. +base: base component: true links: doc: https://www.radix-ui.com/docs/primitives/components/scroll-area @@ -8,6 +9,7 @@ links: --- @@ -40,7 +42,11 @@ npm install @radix-ui/react-scroll-area Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -71,4 +77,4 @@ import { ScrollArea } from "@/components/ui/scroll-area" ### Horizontal Scrolling - + diff --git a/apps/v4/content/docs/components/select.mdx b/apps/v4/content/docs/components/base/select.mdx similarity index 91% rename from apps/v4/content/docs/components/select.mdx rename to apps/v4/content/docs/components/base/select.mdx index 96e6f3bc7e..9fb1ce004d 100644 --- a/apps/v4/content/docs/components/select.mdx +++ b/apps/v4/content/docs/components/base/select.mdx @@ -1,6 +1,7 @@ --- title: Select description: Displays a list of options for the user to pick from—triggered by a button. +base: base component: true featured: true links: @@ -9,6 +10,7 @@ links: --- @@ -41,7 +43,11 @@ npm install @radix-ui/react-select Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -81,6 +87,7 @@ import { ### Scrollable diff --git a/apps/v4/content/docs/components/separator.mdx b/apps/v4/content/docs/components/base/separator.mdx similarity index 81% rename from apps/v4/content/docs/components/separator.mdx rename to apps/v4/content/docs/components/base/separator.mdx index ae264acb2f..ee0696d80f 100644 --- a/apps/v4/content/docs/components/separator.mdx +++ b/apps/v4/content/docs/components/base/separator.mdx @@ -1,13 +1,18 @@ --- title: Separator description: Visually or semantically separates content. +base: base component: true links: doc: https://www.radix-ui.com/docs/primitives/components/separator api: https://www.radix-ui.com/docs/primitives/components/separator#api-reference --- - + ## Installation @@ -36,7 +41,11 @@ npm install @radix-ui/react-separator Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/sheet.mdx b/apps/v4/content/docs/components/base/sheet.mdx similarity index 91% rename from apps/v4/content/docs/components/sheet.mdx rename to apps/v4/content/docs/components/base/sheet.mdx index a3c5a88d18..27eef4199b 100644 --- a/apps/v4/content/docs/components/sheet.mdx +++ b/apps/v4/content/docs/components/base/sheet.mdx @@ -1,13 +1,18 @@ --- title: Sheet description: Extends the Dialog component to display content that complements the main content of the screen. +base: base component: true links: doc: https://www.radix-ui.com/docs/primitives/components/dialog api: https://www.radix-ui.com/docs/primitives/components/dialog#api-reference --- - + ## Installation @@ -37,7 +42,11 @@ npm install @radix-ui/react-dialog Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/sidebar.mdx b/apps/v4/content/docs/components/base/sidebar.mdx similarity index 98% rename from apps/v4/content/docs/components/sidebar.mdx rename to apps/v4/content/docs/components/base/sidebar.mdx index ca0e8da886..c96de9c47b 100644 --- a/apps/v4/content/docs/components/sidebar.mdx +++ b/apps/v4/content/docs/components/base/sidebar.mdx @@ -1,11 +1,13 @@ --- title: Sidebar description: A composable, themeable and customizable sidebar component. +base: base component: true ---
Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -317,6 +323,7 @@ You should see something like this:
` to the `SidebarHeader`.
` to the `SidebarFooter`.
` and `` to render a submenu
+ ## Installation @@ -28,7 +33,11 @@ npx shadcn@latest add skeleton Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -53,6 +62,7 @@ import { Skeleton } from "@/components/ui/skeleton" ### Card diff --git a/apps/v4/content/docs/components/slider.mdx b/apps/v4/content/docs/components/base/slider.mdx similarity index 82% rename from apps/v4/content/docs/components/slider.mdx rename to apps/v4/content/docs/components/base/slider.mdx index e4aaf8e3fc..32bb336ecb 100644 --- a/apps/v4/content/docs/components/slider.mdx +++ b/apps/v4/content/docs/components/base/slider.mdx @@ -1,13 +1,18 @@ --- title: Slider description: An input where the user selects a value from within a given range. +base: base component: true links: doc: https://www.radix-ui.com/docs/primitives/components/slider api: https://www.radix-ui.com/docs/primitives/components/slider#api-reference --- - + ## Installation @@ -37,7 +42,11 @@ npm install @radix-ui/react-slider Copy and paste the following code into your project. - + Update the import paths to match your project setup. diff --git a/apps/v4/content/docs/components/sonner.mdx b/apps/v4/content/docs/components/base/sonner.mdx similarity index 92% rename from apps/v4/content/docs/components/sonner.mdx rename to apps/v4/content/docs/components/base/sonner.mdx index 2b87452e14..71239fb04d 100644 --- a/apps/v4/content/docs/components/sonner.mdx +++ b/apps/v4/content/docs/components/base/sonner.mdx @@ -1,12 +1,13 @@ --- title: Sonner description: An opinionated toast component for React. +base: base component: true links: doc: https://sonner.emilkowal.ski --- - + ## About @@ -64,7 +65,11 @@ npm install sonner next-themes Copy and paste the following code into your project. - + Add the Toaster component @@ -102,7 +107,7 @@ toast("Event has been created.") ## Examples - + ## Changelog diff --git a/apps/v4/content/docs/components/spinner.mdx b/apps/v4/content/docs/components/base/spinner.mdx similarity index 72% rename from apps/v4/content/docs/components/spinner.mdx rename to apps/v4/content/docs/components/base/spinner.mdx index b4c2159b21..57dc12ad5b 100644 --- a/apps/v4/content/docs/components/spinner.mdx +++ b/apps/v4/content/docs/components/base/spinner.mdx @@ -1,10 +1,15 @@ --- title: Spinner description: An indicator that can be used to show a loading state. +base: base component: true --- - + ## Installation @@ -28,7 +33,11 @@ npx shadcn@latest add spinner Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -52,7 +61,7 @@ import { Spinner } from "@/components/ui/spinner" You can replace the default spinner icon with any other icon by editing the `Spinner` component. - + ```tsx showLineNumbers title="components/ui/spinner.tsx" import { LoaderIcon } from "lucide-react" @@ -79,41 +88,41 @@ export { Spinner } Use the `size-*` utility class to change the size of the spinner. - + ### Color Use the `text-` utility class to change the color of the spinner. - + ### Button Add a spinner to a button to indicate a loading state. The ` + + +``` + +## Accessibility + +- The `ButtonGroup` component has the `role` attribute set to `group`. +- Use Tab to navigate between the buttons in the group. +- Use `aria-label` or `aria-labelledby` to label the button group. + +```tsx showLineNumbers + + + + +``` + +## ButtonGroup vs ToggleGroup + +- Use the `ButtonGroup` component when you want to group buttons that perform an action. +- Use the `ToggleGroup` component when you want to group buttons that toggle a state. + +## Examples + +### Orientation + +Set the `orientation` prop to change the button group layout. + + + +### Size + +Control the size of buttons using the `size` prop on individual buttons. + + + +### Nested + +Nest `` components to create button groups with spacing. + + + +### Separator + +The `ButtonGroupSeparator` component visually divides buttons within a group. + +Buttons with variant `outline` do not need a separator since they have a border. For other variants, a separator is recommended to improve the visual hierarchy. + + + +### Split + +Create a split button group by adding two buttons separated by a `ButtonGroupSeparator`. + + + +### Input + +Wrap an `Input` component with buttons. + + + +### Input Group + +Wrap an `InputGroup` component to create complex input layouts. + + + +### Dropdown Menu + +Create a split button group with a `DropdownMenu` component. + + + +### Select + +Pair with a `Select` component. + + + +### Popover + +Use with a `Popover` component. + + + +## API Reference + +### ButtonGroup + +The `ButtonGroup` component is a container that groups related buttons together with consistent styling. + +| Prop | Type | Default | +| ------------- | ---------------------------- | -------------- | +| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | + +```tsx + + + + +``` + +Nest multiple button groups to create complex layouts with spacing. See the [nested](#nested) example for more details. + +```tsx + + + + +``` + +### ButtonGroupSeparator + +The `ButtonGroupSeparator` component visually divides buttons within a group. + +| Prop | Type | Default | +| ------------- | ---------------------------- | ------------ | +| `orientation` | `"horizontal" \| "vertical"` | `"vertical"` | + +```tsx + + + + + +``` + +### ButtonGroupText + +Use this component to display text within a button group. + +| Prop | Type | Default | +| --------- | --------- | ------- | +| `asChild` | `boolean` | `false` | + +```tsx + + Text + + +``` + +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 ( + + + + + + + ) +} +``` diff --git a/apps/v4/content/docs/components/button.mdx b/apps/v4/content/docs/components/radix/button.mdx similarity index 90% rename from apps/v4/content/docs/components/button.mdx rename to apps/v4/content/docs/components/radix/button.mdx index 73bb53644c..191a826abc 100644 --- a/apps/v4/content/docs/components/button.mdx +++ b/apps/v4/content/docs/components/radix/button.mdx @@ -2,6 +2,7 @@ title: Button description: Displays a button or a component that looks like a button. featured: true +base: radix component: true --- @@ -14,7 +15,12 @@ instructions to update your project. - + ```tsx showLineNumbers @@ -51,7 +57,11 @@ npm install @radix-ui/react-slot Copy and paste the following code into your project. - + Update the import paths to match your project setup. @@ -90,7 +100,7 @@ If you want to keep the `cursor: pointer` behavior, add the following code to yo ### Size - + ```tsx // Small @@ -115,6 +125,7 @@ If you want to keep the `cursor: pointer` behavior, add the following code to yo ### Default + ```tsx + + + + + + No framework found. + + {frameworks.map((framework) => ( + { + setValue(currentValue === value ? "" : currentValue) + setOpen(false) + }} + > + + {framework.label} + + ))} + + + + + + ) +} +``` + + + +## Examples + +### Combobox + + + +### Popover + + + +### Dropdown menu + + + +### Responsive + +You can create a responsive combobox by using the `` on desktop and the `` components on mobile. + + diff --git a/apps/v4/content/docs/components/radix/command.mdx b/apps/v4/content/docs/components/radix/command.mdx new file mode 100644 index 0000000000..88278f9987 --- /dev/null +++ b/apps/v4/content/docs/components/radix/command.mdx @@ -0,0 +1,145 @@ +--- +title: Command +description: Fast, composable, unstyled command menu for React. +base: radix +component: true +links: + doc: https://cmdk.paco.me +--- + + + +## About + +The `` component uses the [`cmdk`](https://cmdk.paco.me) component by [pacocoursey](https://twitter.com/pacocoursey). + +## Installation + + + + + CLI + Manual + + + +```bash +npx shadcn@latest add command +``` + + + + + + + +Install the following dependencies: + +```bash +npm install cmdk +``` + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx showLineNumbers +import { + Command, + CommandDialog, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, + CommandSeparator, + CommandShortcut, +} from "@/components/ui/command" +``` + +```tsx showLineNumbers + + + + No results found. + + Calendar + Search Emoji + Calculator + + + + Profile + Billing + Settings + + + +``` + +## Examples + +### Dialog + + + +To show the command menu in a dialog, use the `` component. + +```tsx showLineNumbers title="components/example-command-menu.tsx" +export function CommandMenu() { + const [open, setOpen] = React.useState(false) + + React.useEffect(() => { + const down = (e: KeyboardEvent) => { + if (e.key === "k" && (e.metaKey || e.ctrlKey)) { + e.preventDefault() + setOpen((open) => !open) + } + } + document.addEventListener("keydown", down) + return () => document.removeEventListener("keydown", down) + }, []) + + return ( + + + + No results found. + + Calendar + Search Emoji + Calculator + + + + ) +} +``` + +### Combobox + +You can use the `` component as a combobox. See the [Combobox](/docs/components/combobox) page for more information. diff --git a/apps/v4/content/docs/components/radix/context-menu.mdx b/apps/v4/content/docs/components/radix/context-menu.mdx new file mode 100644 index 0000000000..1fd2b478cb --- /dev/null +++ b/apps/v4/content/docs/components/radix/context-menu.mdx @@ -0,0 +1,80 @@ +--- +title: Context Menu +description: Displays a menu to the user — such as a set of actions or functions — triggered by a button. +base: radix +component: true +links: + doc: https://www.radix-ui.com/docs/primitives/components/context-menu + api: https://www.radix-ui.com/docs/primitives/components/context-menu#api-reference +--- + + + +## Installation + + + + + CLI + Manual + + + +```bash +npx shadcn@latest add context-menu +``` + + + + + + + +Install the following dependencies: + +```bash +npm install @radix-ui/react-context-menu +``` + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx showLineNumbers +import { + ContextMenu, + ContextMenuContent, + ContextMenuItem, + ContextMenuTrigger, +} from "@/components/ui/context-menu" +``` + +```tsx showLineNumbers + + Right click + + Profile + Billing + Team + Subscription + + +``` diff --git a/apps/v4/content/docs/components/radix/data-table.mdx b/apps/v4/content/docs/components/radix/data-table.mdx new file mode 100644 index 0000000000..2d5a5698bd --- /dev/null +++ b/apps/v4/content/docs/components/radix/data-table.mdx @@ -0,0 +1,884 @@ +--- +title: Data Table +description: Powerful table and datagrids built using TanStack Table. +base: radix +component: true +links: + doc: https://tanstack.com/table/v8/docs/introduction +--- + + + +## Introduction + +Every data table or datagrid I've created has been unique. They all behave differently, have specific sorting and filtering requirements, and work with different data sources. + +It doesn't make sense to combine all of these variations into a single component. If we do that, we'll lose the flexibility that [headless UI](https://tanstack.com/table/v8/docs/introduction#what-is-headless-ui) provides. + +So instead of a data-table component, I thought it would be more helpful to provide a guide on how to build your own. + +We'll start with the basic `` component and build a complex data table from scratch. + + + +**Tip:** If you find yourself using the same table in multiple places in your app, you can always extract it into a reusable component. + + + +## Table of Contents + +This guide will show you how to use [TanStack Table](https://tanstack.com/table) and the `
` component to build your own custom data table. We'll cover the following topics: + +- [Basic Table](#basic-table) +- [Row Actions](#row-actions) +- [Pagination](#pagination) +- [Sorting](#sorting) +- [Filtering](#filtering) +- [Visibility](#visibility) +- [Row Selection](#row-selection) +- [Reusable Components](#reusable-components) + +## Installation + +1. Add the `
` component to your project: + +```bash +npx shadcn@latest add table +``` + +2. Add `tanstack/react-table` dependency: + +```bash +npm install @tanstack/react-table +``` + +## Prerequisites + +We are going to build a table to show recent payments. Here's what our data looks like: + +```tsx showLineNumbers +type Payment = { + id: string + amount: number + status: "pending" | "processing" | "success" | "failed" + email: string +} + +export const payments: Payment[] = [ + { + id: "728ed52f", + amount: 100, + status: "pending", + email: "m@example.com", + }, + { + id: "489e1d42", + amount: 125, + status: "processing", + email: "example@gmail.com", + }, + // ... +] +``` + +## Project Structure + +Start by creating the following file structure: + +```txt +app +└── payments + ├── columns.tsx + ├── data-table.tsx + └── page.tsx +``` + +I'm using a Next.js example here but this works for any other React framework. + +- `columns.tsx` (client component) will contain our column definitions. +- `data-table.tsx` (client component) will contain our `` component. +- `page.tsx` (server component) is where we'll fetch data and render our table. + +## Basic Table + +Let's start by building a basic table. + + + +### Column Definitions + +First, we'll define our columns. + +```tsx showLineNumbers title="app/payments/columns.tsx" {3,14-27} +"use client" + +import { ColumnDef } from "@tanstack/react-table" + +// This type is used to define the shape of our data. +// You can use a Zod schema here if you want. +export type Payment = { + id: string + amount: number + status: "pending" | "processing" | "success" | "failed" + email: string +} + +export const columns: ColumnDef[] = [ + { + accessorKey: "status", + header: "Status", + }, + { + accessorKey: "email", + header: "Email", + }, + { + accessorKey: "amount", + header: "Amount", + }, +] +``` + + + +**Note:** Columns are where you define the core of what your table +will look like. They define the data that will be displayed, how it will be +formatted, sorted and filtered. + + + +### `` component + +Next, we'll create a `` component to render our table. + +```tsx showLineNumbers title="app/payments/data-table.tsx" +"use client" + +import { + ColumnDef, + flexRender, + getCoreRowModel, + useReactTable, +} from "@tanstack/react-table" + +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table" + +interface DataTableProps { + columns: ColumnDef[] + data: TData[] +} + +export function DataTable({ + columns, + data, +}: DataTableProps) { + const table = useReactTable({ + data, + columns, + getCoreRowModel: getCoreRowModel(), + }) + + return ( +
+
+ + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => { + return ( + + {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef.header, + header.getContext() + )} + + ) + })} + + ))} + + + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + + ))} + + )) + ) : ( + + + No results. + + + )} + +
+
+ ) +} +``` + + + +**Tip**: If you find yourself using `` in multiple places, this is the component you could make reusable by extracting it to `components/ui/data-table.tsx`. + +`` + + + +### Render the table + +Finally, we'll render our table in our page component. + +```tsx showLineNumbers title="app/payments/page.tsx" {22} +import { columns, Payment } from "./columns" +import { DataTable } from "./data-table" + +async function getData(): Promise { + // Fetch data from your API here. + return [ + { + id: "728ed52f", + amount: 100, + status: "pending", + email: "m@example.com", + }, + // ... + ] +} + +export default async function DemoPage() { + const data = await getData() + + return ( +
+ +
+ ) +} +``` + + + +## Cell Formatting + +Let's format the amount cell to display the dollar amount. We'll also align the cell to the right. + + + +### Update columns definition + +Update the `header` and `cell` definitions for amount as follows: + +```tsx showLineNumbers title="app/payments/columns.tsx" {4-15} +export const columns: ColumnDef[] = [ + { + accessorKey: "amount", + header: () =>
Amount
, + cell: ({ row }) => { + const amount = parseFloat(row.getValue("amount")) + const formatted = new Intl.NumberFormat("en-US", { + style: "currency", + currency: "USD", + }).format(amount) + + return
{formatted}
+ }, + }, +] +``` + +You can use the same approach to format other cells and headers. + +
+ +## Row Actions + +Let's add row actions to our table. We'll use a `` component for this. + + + +### Update columns definition + +Update our columns definition to add a new `actions` column. The `actions` cell returns a `` component. + +```tsx showLineNumbers title="app/payments/columns.tsx" {4,6-14,18-45} +"use client" + +import { ColumnDef } from "@tanstack/react-table" +import { MoreHorizontal } from "lucide-react" + +import { Button } from "@/components/ui/button" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" + +export const columns: ColumnDef[] = [ + // ... + { + id: "actions", + cell: ({ row }) => { + const payment = row.original + + return ( + + + + + + Actions + navigator.clipboard.writeText(payment.id)} + > + Copy payment ID + + + View customer + View payment details + + + ) + }, + }, + // ... +] +``` + +You can access the row data using `row.original` in the `cell` function. Use this to handle actions for your row eg. use the `id` to make a DELETE call to your API. + + + +## Pagination + +Next, we'll add pagination to our table. + + + +### Update `` + +```tsx showLineNumbers title="app/payments/data-table.tsx" {5,17} +import { + ColumnDef, + flexRender, + getCoreRowModel, + getPaginationRowModel, + useReactTable, +} from "@tanstack/react-table" + +export function DataTable({ + columns, + data, +}: DataTableProps) { + const table = useReactTable({ + data, + columns, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + }) + + // ... +} +``` + +This will automatically paginate your rows into pages of 10. See the [pagination docs](https://tanstack.com/table/v8/docs/api/features/pagination) for more information on customizing page size and implementing manual pagination. + +### Add pagination controls + +We can add pagination controls to our table using the ` + + + + ) +} +``` + +See [Reusable Components](#reusable-components) section for a more advanced pagination component. + + + +## Sorting + +Let's make the email column sortable. + + + +### Update `` + +```tsx showLineNumbers title="app/payments/data-table.tsx" showLineNumbers {3,6,10,18,25-28} +"use client" + +import * as React from "react" +import { + ColumnDef, + SortingState, + flexRender, + getCoreRowModel, + getPaginationRowModel, + getSortedRowModel, + useReactTable, +} from "@tanstack/react-table" + +export function DataTable({ + columns, + data, +}: DataTableProps) { + const [sorting, setSorting] = React.useState([]) + + const table = useReactTable({ + data, + columns, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + onSortingChange: setSorting, + getSortedRowModel: getSortedRowModel(), + state: { + sorting, + }, + }) + + return ( +
+
+ { ... }
+
+
+ ) +} +``` + +### Make header cell sortable + +We can now update the `email` header cell to add sorting controls. + +```tsx showLineNumbers title="app/payments/columns.tsx" {4,9-19} +"use client" + +import { ColumnDef } from "@tanstack/react-table" +import { ArrowUpDown } from "lucide-react" + +export const columns: ColumnDef[] = [ + { + accessorKey: "email", + header: ({ column }) => { + return ( + + ) + }, + }, +] +``` + +This will automatically sort the table (asc and desc) when the user toggles on the header cell. + +
+ +## Filtering + +Let's add a search input to filter emails in our table. + + + +### Update `` + +```tsx showLineNumbers title="app/payments/data-table.tsx" {6,10,17,24-26,35-36,39,45-54} +"use client" + +import * as React from "react" +import { + ColumnDef, + ColumnFiltersState, + SortingState, + flexRender, + getCoreRowModel, + getFilteredRowModel, + getPaginationRowModel, + getSortedRowModel, + useReactTable, +} from "@tanstack/react-table" + +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" + +export function DataTable({ + columns, + data, +}: DataTableProps) { + const [sorting, setSorting] = React.useState([]) + const [columnFilters, setColumnFilters] = React.useState( + [] + ) + + const table = useReactTable({ + data, + columns, + onSortingChange: setSorting, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + getSortedRowModel: getSortedRowModel(), + onColumnFiltersChange: setColumnFilters, + getFilteredRowModel: getFilteredRowModel(), + state: { + sorting, + columnFilters, + }, + }) + + return ( +
+
+ + table.getColumn("email")?.setFilterValue(event.target.value) + } + className="max-w-sm" + /> +
+
+ { ... }
+
+
+ ) +} +``` + +Filtering is now enabled for the `email` column. You can add filters to other columns as well. See the [filtering docs](https://tanstack.com/table/v8/docs/guide/filters) for more information on customizing filters. + +
+ +## Visibility + +Adding column visibility is fairly simple using `@tanstack/react-table` visibility API. + + + +### Update `` + +```tsx showLineNumbers title="app/payments/data-table.tsx" {8,18-23,33-34,45,49,64-91} +"use client" + +import * as React from "react" +import { + ColumnDef, + ColumnFiltersState, + SortingState, + VisibilityState, + flexRender, + getCoreRowModel, + getFilteredRowModel, + getPaginationRowModel, + getSortedRowModel, + useReactTable, +} from "@tanstack/react-table" + +import { Button } from "@/components/ui/button" +import { + DropdownMenu, + DropdownMenuCheckboxItem, + DropdownMenuContent, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" + +export function DataTable({ + columns, + data, +}: DataTableProps) { + const [sorting, setSorting] = React.useState([]) + const [columnFilters, setColumnFilters] = React.useState( + [] + ) + const [columnVisibility, setColumnVisibility] = + React.useState({}) + + const table = useReactTable({ + data, + columns, + onSortingChange: setSorting, + onColumnFiltersChange: setColumnFilters, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + getSortedRowModel: getSortedRowModel(), + getFilteredRowModel: getFilteredRowModel(), + onColumnVisibilityChange: setColumnVisibility, + state: { + sorting, + columnFilters, + columnVisibility, + }, + }) + + return ( +
+
+ + table.getColumn("email")?.setFilterValue(event.target.value) + } + className="max-w-sm" + /> + + + + + + {table + .getAllColumns() + .filter( + (column) => column.getCanHide() + ) + .map((column) => { + return ( + + column.toggleVisibility(!!value) + } + > + {column.id} + + ) + })} + + +
+
+ { ... }
+
+
+ ) +} +``` + +This adds a dropdown menu that you can use to toggle column visibility. + +
+ +## Row Selection + +Next, we're going to add row selection to our table. + + + +### Update column definitions + +```tsx showLineNumbers title="app/payments/columns.tsx" {6,9-27} +"use client" + +import { ColumnDef } from "@tanstack/react-table" + +import { Badge } from "@/components/ui/badge" +import { Checkbox } from "@/components/ui/checkbox" + +export const columns: ColumnDef[] = [ + { + id: "select", + header: ({ table }) => ( + table.toggleAllPageRowsSelected(!!value)} + aria-label="Select all" + /> + ), + cell: ({ row }) => ( + row.toggleSelected(!!value)} + aria-label="Select row" + /> + ), + enableSorting: false, + enableHiding: false, + }, +] +``` + +### Update `` + +```tsx showLineNumbers title="app/payments/data-table.tsx" {11,23,28} +export function DataTable({ + columns, + data, +}: DataTableProps) { + const [sorting, setSorting] = React.useState([]) + const [columnFilters, setColumnFilters] = React.useState( + [] + ) + const [columnVisibility, setColumnVisibility] = + React.useState({}) + const [rowSelection, setRowSelection] = React.useState({}) + + const table = useReactTable({ + data, + columns, + onSortingChange: setSorting, + onColumnFiltersChange: setColumnFilters, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + getSortedRowModel: getSortedRowModel(), + getFilteredRowModel: getFilteredRowModel(), + onColumnVisibilityChange: setColumnVisibility, + onRowSelectionChange: setRowSelection, + state: { + sorting, + columnFilters, + columnVisibility, + rowSelection, + }, + }) + + return ( +
+
+ + + + ) +} +``` + +This adds a checkbox to each row and a checkbox in the header to select all rows. + +### Show selected rows + +You can show the number of selected rows using the `table.getFilteredSelectedRowModel()` API. + +```tsx +
+ {table.getFilteredSelectedRowModel().rows.length} of{" "} + {table.getFilteredRowModel().rows.length} row(s) selected. +
+``` + + + +## Reusable Components + +Here are some components you can use to build your data tables. This is from the [Tasks](/examples/tasks) demo. + +### Column header + +Make any column header sortable and hideable. + + + +```tsx showLineNumbers {5} +export const columns = [ + { + accessorKey: "email", + header: ({ column }) => ( + + ), + }, +] +``` + +### Pagination + +Add pagination controls to your table including page size and selection count. + + + +```tsx + +``` + +### Column toggle + +A component to toggle column visibility. + + + +```tsx + +``` diff --git a/apps/v4/content/docs/components/radix/date-picker.mdx b/apps/v4/content/docs/components/radix/date-picker.mdx new file mode 100644 index 0000000000..be5e2b4877 --- /dev/null +++ b/apps/v4/content/docs/components/radix/date-picker.mdx @@ -0,0 +1,102 @@ +--- +title: Date Picker +description: A date picker component with range and presets. +base: radix +component: true +--- + + + +## Installation + +The Date Picker is built using a composition of the `` and the `` components. + +See installation instructions for the [Popover](/docs/components/popover#installation) and the [Calendar](/docs/components/calendar#installation) components. + +## Usage + +```tsx showLineNumbers title="components/example-date-picker.tsx" +"use client" + +import * as React from "react" +import { format } from "date-fns" +import { Calendar as CalendarIcon } from "lucide-react" + +import { cn } from "@/lib/utils" +import { Button } from "@/components/ui/button" +import { Calendar } from "@/components/ui/calendar" +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover" + +export function DatePickerDemo() { + const [date, setDate] = React.useState() + + return ( + + + + + + + + + ) +} +``` + +See the [React DayPicker](https://react-day-picker.js.org) documentation for more information. + +## Examples + +### Date of Birth Picker + + + +### Picker with Input + + + +### Date and Time Picker + + + +### Natural Language Picker + +This component uses the `chrono-node` library to parse natural language dates. + + diff --git a/apps/v4/content/docs/components/radix/dialog.mdx b/apps/v4/content/docs/components/radix/dialog.mdx new file mode 100644 index 0000000000..118297eaf8 --- /dev/null +++ b/apps/v4/content/docs/components/radix/dialog.mdx @@ -0,0 +1,126 @@ +--- +title: Dialog +description: A window overlaid on either the primary window or another dialog window, rendering the content underneath inert. +featured: true +base: radix +component: true +links: + doc: https://www.radix-ui.com/docs/primitives/components/dialog + api: https://www.radix-ui.com/docs/primitives/components/dialog#api-reference +--- + + + +## Installation + + + + + CLI + Manual + + + +```bash +npx shadcn@latest add dialog +``` + + + + + + + +Install the following dependencies: + +```bash +npm install @radix-ui/react-dialog +``` + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx showLineNumbers +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog" +``` + +```tsx showLineNumbers + + Open + + + Are you absolutely sure? + + This action cannot be undone. This will permanently delete your account + and remove your data from our servers. + + + + +``` + +## Examples + +### Custom close button + + + +## Notes + +To use the `Dialog` component from within a `Context Menu` or `Dropdown Menu`, you must encase the `Context Menu` or +`Dropdown Menu` component in the `Dialog` component. + +```tsx showLineNumbers title="components/example-dialog-context-menu.tsx" {1, 26} + + + Right click + + Open + Download + + + Delete + + + + + + + Are you absolutely sure? + + This action cannot be undone. Are you sure you want to permanently + delete this file from our servers? + + + + + + + +``` diff --git a/apps/v4/content/docs/components/radix/drawer.mdx b/apps/v4/content/docs/components/radix/drawer.mdx new file mode 100644 index 0000000000..72f61872d3 --- /dev/null +++ b/apps/v4/content/docs/components/radix/drawer.mdx @@ -0,0 +1,101 @@ +--- +title: Drawer +description: A drawer component for React. +base: radix +component: true +links: + doc: https://vaul.emilkowal.ski/getting-started +--- + + + +## About + +Drawer is built on top of [Vaul](https://github.com/emilkowalski/vaul) by [emilkowalski](https://twitter.com/emilkowalski). + +## Installation + + + + + CLI + Manual + + + +```bash +npx shadcn@latest add drawer +``` + + + + + + + +Install the following dependencies: + +```bash +npm install vaul +``` + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx showLineNumbers +import { + Drawer, + DrawerClose, + DrawerContent, + DrawerDescription, + DrawerFooter, + DrawerHeader, + DrawerTitle, + DrawerTrigger, +} from "@/components/ui/drawer" +``` + +```tsx showLineNumbers + + Open + + + Are you absolutely sure? + This action cannot be undone. + + + + + + + + + +``` + +## Examples + +### Responsive Dialog + +You can combine the `Dialog` and `Drawer` components to create a responsive dialog. This renders a `Dialog` component on desktop and a `Drawer` on mobile. + + diff --git a/apps/v4/content/docs/components/radix/dropdown-menu.mdx b/apps/v4/content/docs/components/radix/dropdown-menu.mdx new file mode 100644 index 0000000000..dfc656ee8b --- /dev/null +++ b/apps/v4/content/docs/components/radix/dropdown-menu.mdx @@ -0,0 +1,119 @@ +--- +title: Dropdown Menu +description: Displays a menu to the user — such as a set of actions or functions — triggered by a button. +featured: true +base: radix +component: true +links: + doc: https://www.radix-ui.com/docs/primitives/components/dropdown-menu + api: https://www.radix-ui.com/docs/primitives/components/dropdown-menu#api-reference +--- + + + +## Installation + + + + + CLI + Manual + + + +```bash +npx shadcn@latest add dropdown-menu +``` + + + + + + + +Install the following dependencies: + +```bash +npm install @radix-ui/react-dropdown-menu +``` + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx showLineNumbers +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +``` + +```tsx showLineNumbers + + Open + + My Account + + Profile + Billing + Team + Subscription + + +``` + +## Examples + +### Checkboxes + + + +### Radio Group + + + +### Dialog + +This example shows how to open a dialog from a dropdown menu. + +Use `modal={false}` on the `DropdownMenu` component. + +```tsx showLineNumbers + + + + + +``` + + diff --git a/apps/v4/content/docs/components/radix/empty.mdx b/apps/v4/content/docs/components/radix/empty.mdx new file mode 100644 index 0000000000..4807196495 --- /dev/null +++ b/apps/v4/content/docs/components/radix/empty.mdx @@ -0,0 +1,223 @@ +--- +title: Empty +description: Use the Empty component to display an empty state. +base: radix +component: true +--- + + + +## Installation + + + + + CLI + Manual + + + +```bash +npx shadcn@latest add empty +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { + Empty, + EmptyContent, + EmptyDescription, + EmptyHeader, + EmptyMedia, + EmptyTitle, +} from "@/components/ui/empty" +``` + +```tsx + + + + + + No data + No data found + + + + + +``` + +## Examples + +### Outline + +Use the `border` utility class to create an outline empty state. + + + +### Background + +Use the `bg-*` and `bg-gradient-*` utilities to add a background to the empty state. + + + +### Avatar + +Use the `EmptyMedia` component to display an avatar in the empty state. + + + +### Avatar Group + +Use the `EmptyMedia` component to display an avatar group in the empty state. + + + +### InputGroup + +You can add an `InputGroup` component to the `EmptyContent` component. + + + +## API Reference + +### Empty + +The main component of the empty state. Wraps the `EmptyHeader` and `EmptyContent` components. + +| Prop | Type | Default | +| ----------- | -------- | ------- | +| `className` | `string` | | + +```tsx + + + + +``` + +### EmptyHeader + +The `EmptyHeader` component wraps the empty media, title, and description. + +| Prop | Type | Default | +| ----------- | -------- | ------- | +| `className` | `string` | | + +```tsx + + + + + +``` + +### EmptyMedia + +Use the `EmptyMedia` component to display the media of the empty state such as an icon or an image. You can also use it to display other components such as an avatar. + +| Prop | Type | Default | +| ----------- | --------------------- | --------- | +| `variant` | `"default" \| "icon"` | `default` | +| `className` | `string` | | + +```tsx + + + +``` + +```tsx + + + + CN + + +``` + +### EmptyTitle + +Use the `EmptyTitle` component to display the title of the empty state. + +| Prop | Type | Default | +| ----------- | -------- | ------- | +| `className` | `string` | | + +```tsx +No data +``` + +### EmptyDescription + +Use the `EmptyDescription` component to display the description of the empty state. + +| Prop | Type | Default | +| ----------- | -------- | ------- | +| `className` | `string` | | + +```tsx +You do not have any notifications. +``` + +### EmptyContent + +Use the `EmptyContent` component to display the content of the empty state such as a button, input or a link. + +| Prop | Type | Default | +| ----------- | -------- | ------- | +| `className` | `string` | | + +```tsx + + + +``` diff --git a/apps/v4/content/docs/components/radix/field.mdx b/apps/v4/content/docs/components/radix/field.mdx new file mode 100644 index 0000000000..d3de9f2a88 --- /dev/null +++ b/apps/v4/content/docs/components/radix/field.mdx @@ -0,0 +1,378 @@ +--- +title: Field +description: Combine labels, controls, and help text to compose accessible form fields and grouped inputs. +base: radix +component: true +--- + + + +## Installation + + + + + CLI + Manual + + + +```bash +npx shadcn@latest add field +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx showLineNumbers +import { + Field, + FieldContent, + FieldDescription, + FieldError, + FieldGroup, + FieldLabel, + FieldLegend, + FieldSeparator, + FieldSet, + FieldTitle, +} from "@/components/ui/field" +``` + +```tsx showLineNumbers +
+ Profile + This appears on invoices and emails. + + + Full name + + This appears on invoices and emails. + + + Username + + Choose another username. + + + + Subscribe to the newsletter + + +
+``` + +## Anatomy + +The `Field` family is designed for composing accessible forms. A typical field is structured as follows: + +```tsx showLineNumbers + + Label + {/* Input, Select, Switch, etc. */} + Optional helper text. + Validation message. + +``` + +- `Field` is the core wrapper for a single field. +- `FieldContent` is a flex column that groups label and description. Not required if you have no description. +- Wrap related fields with `FieldGroup`, and use `FieldSet` with `FieldLegend` for semantic grouping. + +## Form + +See the [Form](/docs/forms) documentation for building forms with the `Field` component and [React Hook Form](/docs/forms/react-hook-form) or [Tanstack Form](/docs/forms/tanstack-form). + +## Examples + +### Input + + + +### Textarea + + + +### Select + + + +### Slider + + + +### Fieldset + + + +### Checkbox + + + +### Radio + + + +### Switch + + + +### Choice Card + +Wrap `Field` components inside `FieldLabel` to create selectable field groups. This works with `RadioItem`, `Checkbox` and `Switch` components. + + + +### Field Group + +Stack `Field` components with `FieldGroup`. Add `FieldSeparator` to divide them. + + + +## Responsive Layout + +- **Vertical fields:** Default orientation stacks label, control, and helper text—ideal for mobile-first layouts. +- **Horizontal fields:** Set `orientation="horizontal"` on `Field` to align the label and control side-by-side. Pair with `FieldContent` to keep descriptions aligned. +- **Responsive fields:** Set `orientation="responsive"` for automatic column layouts inside container-aware parents. Apply `@container/field-group` classes on `FieldGroup` to switch orientations at specific breakpoints. + + + +## Validation and Errors + +- Add `data-invalid` to `Field` to switch the entire block into an error state. +- Add `aria-invalid` on the input itself for assistive technologies. +- Render `FieldError` immediately after the control or inside `FieldContent` to keep error messages aligned with the field. + +```tsx showLineNumbers /data-invalid/ /aria-invalid/ + + Email + + Enter a valid email address. + +``` + +## Accessibility + +- `FieldSet` and `FieldLegend` keep related controls grouped for keyboard and assistive tech users. +- `Field` outputs `role="group"` so nested controls inherit labeling from `FieldLabel` and `FieldLegend` when combined. +- Apply `FieldSeparator` sparingly to ensure screen readers encounter clear section boundaries. + +## API Reference + +### FieldSet + +Container that renders a semantic `fieldset` with spacing presets. + +| Prop | Type | Default | +| ----------- | -------- | ------- | +| `className` | `string` | | + +```tsx +
+ Delivery + {/* Fields */} +
+``` + +### FieldLegend + +Legend element for a `FieldSet`. Switch to the `label` variant to align with label sizing. + +| Prop | Type | Default | +| ----------- | --------------------- | ---------- | +| `variant` | `"legend" \| "label"` | `"legend"` | +| `className` | `string` | | + +```tsx +Notification Preferences +``` + +The `FieldLegend` has two variants: `legend` and `label`. The `label` variant applies label sizing and alignment. Handy if you have nested `FieldSet`. + +### FieldGroup + +Layout wrapper that stacks `Field` components and enables container queries for responsive orientations. + +| Prop | Type | Default | +| ----------- | -------- | ------- | +| `className` | `string` | | + +```tsx + + {/* ... */} + {/* ... */} + +``` + +### Field + +The core wrapper for a single field. Provides orientation control, invalid state styling, and spacing. + +| Prop | Type | Default | +| -------------- | -------------------------------------------- | ------------ | +| `orientation` | `"vertical" \| "horizontal" \| "responsive"` | `"vertical"` | +| `className` | `string` | | +| `data-invalid` | `boolean` | | + +```tsx + + Remember me + + +``` + +### FieldContent + +Flex column that groups control and descriptions when the label sits beside the control. Not required if you have no description. + +| Prop | Type | Default | +| ----------- | -------- | ------- | +| `className` | `string` | | + +```tsx + + + + Notifications + Email, SMS, and push options. + + +``` + +### FieldLabel + +Label styled for both direct inputs and nested `Field` children. + +| Prop | Type | Default | +| ----------- | --------- | ------- | +| `className` | `string` | | +| `asChild` | `boolean` | `false` | + +```tsx +Email +``` + +### FieldTitle + +Renders a title with label styling inside `FieldContent`. + +| Prop | Type | Default | +| ----------- | -------- | ------- | +| `className` | `string` | | + +```tsx + + Enable Touch ID + Unlock your device faster. + +``` + +### FieldDescription + +Helper text slot that automatically balances long lines in horizontal layouts. + +| Prop | Type | Default | +| ----------- | -------- | ------- | +| `className` | `string` | | + +```tsx +We never share your email with anyone. +``` + +### FieldSeparator + +Visual divider to separate sections inside a `FieldGroup`. Accepts optional inline content. + +| Prop | Type | Default | +| ----------- | -------- | ------- | +| `className` | `string` | | + +```tsx +Or continue with +``` + +### FieldError + +Accessible error container that accepts children or an `errors` array (e.g., from `react-hook-form`). + +| Prop | Type | Default | +| ----------- | ------------------------------------------ | ------- | +| `errors` | `Array<{ message?: string } \| undefined>` | | +| `className` | `string` | | + +```tsx + +``` + +When the `errors` array contains multiple messages, the component renders a list automatically. + +`FieldError` also accepts issues produced by any validator that implements [Standard Schema](https://standardschema.dev/), including Zod, Valibot, and ArkType. Pass the `issues` array from the schema result directly to render a unified error list across libraries. diff --git a/apps/v4/content/docs/components/radix/form.mdx b/apps/v4/content/docs/components/radix/form.mdx new file mode 100644 index 0000000000..9209a2803e --- /dev/null +++ b/apps/v4/content/docs/components/radix/form.mdx @@ -0,0 +1,245 @@ +--- +title: Form +description: Building forms with React Hook Form and Zod. +links: + doc: https://react-hook-form.com +--- + +import { InfoIcon } from "lucide-react" + +} title="We are not actively developing this component anymore."> + +The Form component is an abstraction over the `react-hook-form` library. Going forward, we recommend using the [``](/docs/components/field) component to build forms. See the [Form](/docs/forms) documentation for more information. + + + +Forms are tricky. They are one of the most common things you'll build in a web application, but also one of the most complex. + +Well-designed HTML forms are: + +- Well-structured and semantically correct. +- Easy to use and navigate (keyboard). +- Accessible with ARIA attributes and proper labels. +- Has support for client and server side validation. +- Well-styled and consistent with the rest of the application. + +In this guide, we will take a look at building forms with [`react-hook-form`](https://react-hook-form.com/) and [`zod`](https://zod.dev). We're going to use a `` component to compose accessible forms using Radix UI components. + +## Features + +The `
` component is a wrapper around the `react-hook-form` library. It provides a few things: + +- Composable components for building forms. +- A `` component for building controlled form fields. +- Form validation using `zod`. +- Handles accessibility and error messages. +- Uses `React.useId()` for generating unique IDs. +- Applies the correct `aria` attributes to form fields based on states. +- Built to work with all Radix UI components. +- Bring your own schema library. We use `zod` but you can use anything you want. +- **You have full control over the markup and styling.** + +## Anatomy + +```tsx showLineNumbers + + ( + + + + { /* Your form field */} + + + + + )} + /> + +``` + +## Example + +```tsx showLineNumbers +const form = useForm() + + ( + + Username + + + + This is your public display name. + + + )} +/> +``` + +## Installation + + + + + CLI + Manual + + + + + +### Command + +```bash +npx shadcn@latest add form +``` + + + + + + + + + +Install the following dependencies: + +```bash +npm install @radix-ui/react-label @radix-ui/react-slot react-hook-form @hookform/resolvers zod +``` + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +### Create a form schema + +Define the shape of your form using a Zod schema. You can read more about using Zod in the [Zod documentation](https://zod.dev). + +```tsx showLineNumbers title="components/example-form.tsx" {3,5-7} +"use client" + +import { z } from "zod" + +const formSchema = z.object({ + username: z.string().min(2).max(50), +}) +``` + +### Define a form + +Use the `useForm` hook from `react-hook-form` to create a form. + +```tsx showLineNumbers title="components/example-form.tsx" {3-4,14-20,22-27} +"use client" + +import { zodResolver } from "@hookform/resolvers/zod" +import { useForm } from "react-hook-form" +import { z } from "zod" + +const formSchema = z.object({ + username: z.string().min(2, { + message: "Username must be at least 2 characters.", + }), +}) + +export function ProfileForm() { + // 1. Define your form. + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + username: "", + }, + }) + + // 2. Define a submit handler. + function onSubmit(values: z.infer) { + // Do something with the form values. + // ✅ This will be type-safe and validated. + console.log(values) + } +} +``` + +Since `FormField` is using a controlled component, you need to provide a default value for the field. See the [React Hook Form docs](https://react-hook-form.com/docs/usecontroller) to learn more about controlled components. + +### Build your form + +We can now use the `
` components to build our form. + +```tsx showLineNumbers title="components/example-form.tsx" {7-17,28-50} +"use client" + +import { zodResolver } from "@hookform/resolvers/zod" +import { useForm } from "react-hook-form" +import { z } from "zod" + +import { Button } from "@/components/ui/button" +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form" +import { Input } from "@/components/ui/input" + +const formSchema = z.object({ + username: z.string().min(2, { + message: "Username must be at least 2 characters.", + }), +}) + +export function ProfileForm() { + // ... + + return ( + + + ( + + Username + + + + + This is your public display name. + + + + )} + /> + + + + ) +} +``` + +### Done + +That's it. You now have a fully accessible form that is type-safe with client-side validation. diff --git a/apps/v4/content/docs/components/radix/hover-card.mdx b/apps/v4/content/docs/components/radix/hover-card.mdx new file mode 100644 index 0000000000..fb49de8e53 --- /dev/null +++ b/apps/v4/content/docs/components/radix/hover-card.mdx @@ -0,0 +1,76 @@ +--- +title: Hover Card +description: For sighted users to preview content available behind a link. +base: radix +component: true +links: + doc: https://www.radix-ui.com/docs/primitives/components/hover-card + api: https://www.radix-ui.com/docs/primitives/components/hover-card#api-reference +--- + + + +## Installation + + + + + CLI + Manual + + + +```bash +npx shadcn@latest add hover-card +``` + + + + + +Install the following dependencies: + +```bash +npm install @radix-ui/react-hover-card +``` + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx showLineNumbers +import { + HoverCard, + HoverCardContent, + HoverCardTrigger, +} from "@/components/ui/hover-card" +``` + +```tsx showLineNumbers + + Hover + + The React Framework – created and maintained by @vercel. + + +``` diff --git a/apps/v4/content/docs/components/radix/input-group.mdx b/apps/v4/content/docs/components/radix/input-group.mdx new file mode 100644 index 0000000000..91329d8df3 --- /dev/null +++ b/apps/v4/content/docs/components/radix/input-group.mdx @@ -0,0 +1,304 @@ +--- +title: Input Group +description: Display additional information or actions to an input or textarea. +base: radix +component: true +--- + +import { IconInfoCircle } from "@tabler/icons-react" + + + +## Installation + + + + + CLI + Manual + + + +```bash +npx shadcn@latest add input-group +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx showLineNumbers +import { + InputGroup, + InputGroupAddon, + InputGroupButton, + InputGroupInput, + InputGroupText, + InputGroupTextarea, +} from "@/components/ui/input-group" +``` + +```tsx showLineNumbers + + + + + + + Search + + +``` + +## Examples + +### Icon + + + +### Text + +Display additional text information alongside inputs. + + + +### Button + +Add buttons to perform actions within the input group. + + + +### Tooltip + +Add tooltips to provide additional context or help. + + + +### Textarea + +Input groups also work with textarea components. Use `block-start` or `block-end` for alignment. + + + +### Spinner + +Show loading indicators while processing input. + + + +### Label + +Add labels within input groups to improve accessibility. + + + +### Dropdown + +Pair input groups with dropdown menus for complex interactions. + + + +### Button Group + +Wrap input groups with button groups to create prefixes and suffixes. + + + +### Custom Input + +Add the `data-slot="input-group-control"` attribute to your custom input for automatic behavior and focus state handling. + +No style is applied to the custom input. Apply your own styles using the `className` prop. + + + +```tsx showLineNumbers +import { InputGroup, InputGroupAddon } from "@/component/ui/input-group" +import TextareaAutosize from "react-textarea-autosize" + +export function InputGroupCustom() { + return ( + + + how + + ) +} +``` + +## API Reference + +### InputGroup + +The main component that wraps inputs and addons. + +| Prop | Type | Default | +| ----------- | -------- | ------- | +| `className` | `string` | | + +```tsx + + + + +``` + +### InputGroupAddon + +Displays icons, text, buttons, or other content alongside inputs. + +} title="Focus Navigation"> + For proper focus navigation, the `InputGroupAddon` component should be placed + after the input. Set the `align` prop to position the addon. + + +| Prop | Type | Default | +| ----------- | ---------------------------------------------------------------- | ---------------- | +| `align` | `"inline-start" \| "inline-end" \| "block-start" \| "block-end"` | `"inline-start"` | +| `className` | `string` | | + +```tsx + + + +``` + +**For ``, use the `inline-start` or `inline-end` alignment. For ``, use the `block-start` or `block-end` alignment.** + +The `InputGroupAddon` component can have multiple `InputGroupButton` components and icons. + +```tsx + + Button + Button + +``` + +### InputGroupButton + +Displays buttons within input groups. + +| Prop | Type | Default | +| ----------- | ----------------------------------------------------------------------------- | --------- | +| `size` | `"xs" \| "icon-xs" \| "sm" \| "icon-sm"` | `"xs"` | +| `variant` | `"default" \| "destructive" \| "outline" \| "secondary" \| "ghost" \| "link"` | `"ghost"` | +| `className` | `string` | | + +```tsx +Button + + + +``` + +### InputGroupInput + +Replacement for `` when building input groups. This component has the input group styles pre-applied and uses the unified `data-slot="input-group-control"` for focus state handling. + +| Prop | Type | Default | +| ----------- | -------- | ------- | +| `className` | `string` | | + +All other props are passed through to the underlying `` component. + +```tsx + + + + + + +``` + +### InputGroupTextarea + +Replacement for `