-
-
- Subscribe
-
+
+
+ Search
)
}
diff --git a/apps/v4/examples/base/input-with-description.tsx b/apps/v4/examples/base/input-with-description.tsx
new file mode 100644
index 000000000..dbabe6d3a
--- /dev/null
+++ b/apps/v4/examples/base/input-with-description.tsx
@@ -0,0 +1,18 @@
+import { Field, FieldDescription, FieldLabel } from "@/examples/base/ui/field"
+import { Input } from "@/examples/base/ui/input"
+
+export function InputWithDescription() {
+ return (
+
+ Username
+
+
+ Choose a unique username for your account.
+
+
+ )
+}
diff --git a/apps/v4/examples/base/input-with-label.tsx b/apps/v4/examples/base/input-with-label.tsx
index b644273f5..33e2a7dc6 100644
--- a/apps/v4/examples/base/input-with-label.tsx
+++ b/apps/v4/examples/base/input-with-label.tsx
@@ -1,11 +1,15 @@
+import { Field, FieldLabel } from "@/examples/base/ui/field"
import { Input } from "@/examples/base/ui/input"
-import { Label } from "@/examples/base/ui/label"
-export default function InputWithLabel() {
+export function InputWithLabel() {
return (
-
- Email
-
-
+
+ Email
+
+
)
}
diff --git a/apps/v4/examples/base/input-with-native-select.tsx b/apps/v4/examples/base/input-with-native-select.tsx
new file mode 100644
index 000000000..703e0e3e9
--- /dev/null
+++ b/apps/v4/examples/base/input-with-native-select.tsx
@@ -0,0 +1,19 @@
+import { Input } from "@/examples/base/ui/input"
+import {
+ NativeSelect,
+ NativeSelectOption,
+} from "@/examples/base/ui/native-select"
+import { Select } from "@/examples/base/ui/select"
+
+export function InputWithNativeSelect() {
+ return (
+
+
+
+ +1
+ +44
+ +46
+
+
+ )
+}
diff --git a/apps/v4/examples/base/input-with-select.tsx b/apps/v4/examples/base/input-with-select.tsx
new file mode 100644
index 000000000..a84659433
--- /dev/null
+++ b/apps/v4/examples/base/input-with-select.tsx
@@ -0,0 +1,26 @@
+import { Input } from "@/examples/base/ui/input"
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+
+export function InputWithSelect() {
+ return (
+
+
+
+
+
+
+
+ USD
+ EUR
+ GBP
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/item-default-extra-small.tsx b/apps/v4/examples/base/item-default-extra-small.tsx
new file mode 100644
index 000000000..f8ad5e916
--- /dev/null
+++ b/apps/v4/examples/base/item-default-extra-small.tsx
@@ -0,0 +1,112 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemDescription,
+ ItemMedia,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+import { InboxIcon } from "lucide-react"
+
+export function ItemDefaultExtraSmall() {
+ return (
+ <>
+
-
+
+ Title Only
+
+
+
-
+
+ Title + Button
+
+
+
+ Action
+
+
+
+
-
+
+ Title + Description
+
+ This is a description that provides additional context.
+
+
+
+
-
+
+ Title + Description + Button
+
+ This item includes a title, description, and action button.
+
+
+
+
+ Action
+
+
+
+
-
+
+
+
+
+ Media + Title
+
+
+
-
+
+
+
+
+ Media + Title + Button
+
+
+ Action
+
+
+
-
+
+
+
+
+ Media + Title + Description
+
+ This item includes media, title, and description.
+
+
+
+
-
+
+
+
+
+ Media + Title + Description + Button
+
+ Complete item with all components: media, title, description, and
+ button.
+
+
+
+ Action
+
+
+
-
+
+ Multiple Actions
+
+ Item with multiple action buttons in the actions area.
+
+
+
+
+ Cancel
+
+ Confirm
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-default-small.tsx b/apps/v4/examples/base/item-default-small.tsx
new file mode 100644
index 000000000..88045dcdd
--- /dev/null
+++ b/apps/v4/examples/base/item-default-small.tsx
@@ -0,0 +1,112 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemDescription,
+ ItemMedia,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+import { InboxIcon } from "lucide-react"
+
+export function ItemDefaultSmall() {
+ return (
+ <>
+
-
+
+ Title Only
+
+
+
-
+
+ Title + Button
+
+
+
+ Action
+
+
+
+
-
+
+ Title + Description
+
+ This is a description that provides additional context.
+
+
+
+
-
+
+ Title + Description + Button
+
+ This item includes a title, description, and action button.
+
+
+
+
+ Action
+
+
+
+
-
+
+
+
+
+ Media + Title
+
+
+
-
+
+
+
+
+ Media + Title + Button
+
+
+ Action
+
+
+
-
+
+
+
+
+ Media + Title + Description
+
+ This item includes media, title, and description.
+
+
+
+
-
+
+
+
+
+ Media + Title + Description + Button
+
+ Complete item with all components: media, title, description, and
+ button.
+
+
+
+ Action
+
+
+
-
+
+ Multiple Actions
+
+ Item with multiple action buttons in the actions area.
+
+
+
+
+ Cancel
+
+ Confirm
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-default-with-image.tsx b/apps/v4/examples/base/item-default-with-image.tsx
new file mode 100644
index 000000000..76d5da1af
--- /dev/null
+++ b/apps/v4/examples/base/item-default-with-image.tsx
@@ -0,0 +1,74 @@
+import Image from "next/image"
+import { Button } from "@/examples/base/ui/button"
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemDescription,
+ ItemMedia,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+
+export function ItemDefaultWithImage() {
+ return (
+ <>
+
-
+
+
+
+
+ Project Dashboard
+
+ Overview of project settings and configuration.
+
+
+
+
-
+
+
+
+
+ Document
+ A document with metadata displayed.
+
+
+
+ View
+
+
+
+
-
+
+
+
+
+ File Attachment
+
+ Complete file with image, title, description, and action button.
+
+
+
+ Download
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-default.tsx b/apps/v4/examples/base/item-default.tsx
new file mode 100644
index 000000000..7845c5465
--- /dev/null
+++ b/apps/v4/examples/base/item-default.tsx
@@ -0,0 +1,108 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemDescription,
+ ItemMedia,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+import { InboxIcon } from "lucide-react"
+
+export function ItemDefault() {
+ return (
+ <>
+
-
+
+ Title Only
+
+
+
-
+
+ Title + Button
+
+
+ Action
+
+
+
-
+
+ Title + Description
+
+ This is a description that provides additional context.
+
+
+
+
-
+
+ Title + Description + Button
+
+ This item includes a title, description, and action button.
+
+
+
+ Action
+
+
+
-
+
+
+
+
+ Media + Title
+
+
+
-
+
+
+
+
+ Media + Title + Button
+
+
+ Action
+
+
+
-
+
+
+
+
+ Media + Title + Description
+
+ This item includes media, title, and description.
+
+
+
+
-
+
+
+
+
+ Media + Title + Description + Button
+
+ Complete item with all components: media, title, description, and
+ button.
+
+
+
+ Action
+
+
+
-
+
+ Multiple Actions
+
+ Item with multiple action buttons in the actions area.
+
+
+
+
+ Cancel
+
+ Confirm
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-footer-examples.tsx b/apps/v4/examples/base/item-footer-examples.tsx
new file mode 100644
index 000000000..fd1bedb04
--- /dev/null
+++ b/apps/v4/examples/base/item-footer-examples.tsx
@@ -0,0 +1,54 @@
+import {
+ Item,
+ ItemContent,
+ ItemDescription,
+ ItemFooter,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+
+export function ItemFooterExamples() {
+ return (
+ <>
+
-
+
+ Quarterly Report Q4 2024
+
+ Financial overview including revenue, expenses, and growth metrics
+ for the fourth quarter.
+
+
+
+
+ Last updated 2 hours ago
+
+
+
+
-
+
+ User Research Findings
+
+ Insights from interviews and surveys conducted with 50+ users across
+ different demographics.
+
+
+
+
+ Created by Sarah Chen
+
+
+
+
-
+
+ Product Roadmap
+
+ Planned features and improvements scheduled for the next three
+ months.
+
+
+
+ 12 comments
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-header-and-footer-examples.tsx b/apps/v4/examples/base/item-header-and-footer-examples.tsx
new file mode 100644
index 000000000..4726b9370
--- /dev/null
+++ b/apps/v4/examples/base/item-header-and-footer-examples.tsx
@@ -0,0 +1,66 @@
+import {
+ Item,
+ ItemContent,
+ ItemDescription,
+ ItemFooter,
+ ItemHeader,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+
+export function ItemHeaderAndFooterExamples() {
+ return (
+ <>
+
-
+
+ Team Project
+
+
+ Website Redesign
+
+ Complete overhaul of the company website with modern design
+ principles and improved user experience.
+
+
+
+
+ Updated 5 minutes ago
+
+
+
+
-
+
+ Client Work
+
+
+ Mobile App Development
+
+ Building a cross-platform mobile application for iOS and Android
+ with React Native.
+
+
+
+
+ Status: In Progress
+
+
+
+
-
+
+ Documentation
+
+
+ API Integration Guide
+
+ Step-by-step instructions for integrating third-party APIs with
+ authentication and error handling.
+
+
+
+
+ Category: Technical • 3 attachments
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-header-examples.tsx b/apps/v4/examples/base/item-header-examples.tsx
new file mode 100644
index 000000000..72269ba70
--- /dev/null
+++ b/apps/v4/examples/base/item-header-examples.tsx
@@ -0,0 +1,50 @@
+import {
+ Item,
+ ItemContent,
+ ItemDescription,
+ ItemHeader,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+
+export function ItemHeaderExamples() {
+ return (
+ <>
+
-
+
+ Design System
+
+
+ Component Library
+
+ A comprehensive collection of reusable UI components for building
+ consistent interfaces.
+
+
+
+
-
+
+ Marketing
+
+
+ Campaign Analytics
+
+ Track performance metrics and engagement rates across all marketing
+ channels.
+
+
+
+
-
+
+ Engineering
+
+
+ API Documentation
+
+ Complete reference guide for all available endpoints and
+ authentication methods.
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-link-default.tsx b/apps/v4/examples/base/item-link-default.tsx
new file mode 100644
index 000000000..5f2d6a77f
--- /dev/null
+++ b/apps/v4/examples/base/item-link-default.tsx
@@ -0,0 +1,65 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemDescription,
+ ItemGroup,
+ ItemMedia,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+import { InboxIcon } from "lucide-react"
+
+export function ItemLinkDefault() {
+ return (
+ <>
+
+ }>
+
+ Title Only (Link)
+
+
+ }>
+
+ Title + Description (Link)
+
+ Clickable item with title and description.
+
+
+
+ }>
+
+
+
+
+ Media + Title (Link)
+
+
+ }>
+
+
+
+
+ Media + Title + Description (Link)
+
+ Complete link item with media, title, and description.
+
+
+
+ }>
+
+ With Actions (Link)
+
+ Link item that also has action buttons.
+
+
+
+
+ Share
+
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-link-muted.tsx b/apps/v4/examples/base/item-link-muted.tsx
new file mode 100644
index 000000000..dd6a477a1
--- /dev/null
+++ b/apps/v4/examples/base/item-link-muted.tsx
@@ -0,0 +1,65 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemDescription,
+ ItemGroup,
+ ItemMedia,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+import { InboxIcon } from "lucide-react"
+
+export function ItemLinkMuted() {
+ return (
+ <>
+
+ }>
+
+ Title Only (Link)
+
+
+ }>
+
+ Title + Description (Link)
+
+ Clickable item with title and description.
+
+
+
+ }>
+
+
+
+
+ Media + Title (Link)
+
+
+ }>
+
+
+
+
+ Media + Title + Description (Link)
+
+ Complete link item with media, title, and description.
+
+
+
+ }>
+
+ With Actions (Link)
+
+ Link item that also has action buttons.
+
+
+
+
+ Share
+
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-link-outline.tsx b/apps/v4/examples/base/item-link-outline.tsx
new file mode 100644
index 000000000..c1497aa3a
--- /dev/null
+++ b/apps/v4/examples/base/item-link-outline.tsx
@@ -0,0 +1,65 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemDescription,
+ ItemGroup,
+ ItemMedia,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+import { InboxIcon } from "lucide-react"
+
+export function ItemLinkOutline() {
+ return (
+ <>
+
+ }>
+
+ Title Only (Link)
+
+
+ }>
+
+ Title + Description (Link)
+
+ Clickable item with title and description.
+
+
+
+ }>
+
+
+
+
+ Media + Title (Link)
+
+
+ }>
+
+
+
+
+ Media + Title + Description (Link)
+
+ Complete link item with media, title, and description.
+
+
+
+ }>
+
+ With Actions (Link)
+
+ Link item that also has action buttons.
+
+
+
+
+ Share
+
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-muted-extra-small.tsx b/apps/v4/examples/base/item-muted-extra-small.tsx
new file mode 100644
index 000000000..c0b0419a6
--- /dev/null
+++ b/apps/v4/examples/base/item-muted-extra-small.tsx
@@ -0,0 +1,112 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemDescription,
+ ItemMedia,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+import { InboxIcon } from "lucide-react"
+
+export function ItemMutedExtraSmall() {
+ return (
+ <>
+
-
+
+ Title Only
+
+
+
-
+
+ Title + Button
+
+
+
+ Action
+
+
+
+
-
+
+ Title + Description
+
+ This is a description that provides additional context.
+
+
+
+
-
+
+ Title + Description + Button
+
+ This item includes a title, description, and action button.
+
+
+
+
+ Action
+
+
+
+
-
+
+
+
+
+ Media + Title
+
+
+
-
+
+
+
+
+ Media + Title + Button
+
+
+ Action
+
+
+
-
+
+
+
+
+ Media + Title + Description
+
+ This item includes media, title, and description.
+
+
+
+
-
+
+
+
+
+ Media + Title + Description + Button
+
+ Complete item with all components: media, title, description, and
+ button.
+
+
+
+ Action
+
+
+
-
+
+ Multiple Actions
+
+ Item with multiple action buttons in the actions area.
+
+
+
+
+ Cancel
+
+ Confirm
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-muted-small.tsx b/apps/v4/examples/base/item-muted-small.tsx
new file mode 100644
index 000000000..637eb7953
--- /dev/null
+++ b/apps/v4/examples/base/item-muted-small.tsx
@@ -0,0 +1,112 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemDescription,
+ ItemMedia,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+import { InboxIcon } from "lucide-react"
+
+export function ItemMutedSmall() {
+ return (
+ <>
+
-
+
+ Title Only
+
+
+
-
+
+ Title + Button
+
+
+
+ Action
+
+
+
+
-
+
+ Title + Description
+
+ This is a description that provides additional context.
+
+
+
+
-
+
+ Title + Description + Button
+
+ This item includes a title, description, and action button.
+
+
+
+
+ Action
+
+
+
+
-
+
+
+
+
+ Media + Title
+
+
+
-
+
+
+
+
+ Media + Title + Button
+
+
+ Action
+
+
+
-
+
+
+
+
+ Media + Title + Description
+
+ This item includes media, title, and description.
+
+
+
+
-
+
+
+
+
+ Media + Title + Description + Button
+
+ Complete item with all components: media, title, description, and
+ button.
+
+
+
+ Action
+
+
+
-
+
+ Multiple Actions
+
+ Item with multiple action buttons in the actions area.
+
+
+
+
+ Cancel
+
+ Confirm
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-muted-with-image.tsx b/apps/v4/examples/base/item-muted-with-image.tsx
new file mode 100644
index 000000000..02ff5f597
--- /dev/null
+++ b/apps/v4/examples/base/item-muted-with-image.tsx
@@ -0,0 +1,74 @@
+import Image from "next/image"
+import { Button } from "@/examples/base/ui/button"
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemDescription,
+ ItemMedia,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+
+export function ItemMutedWithImage() {
+ return (
+ <>
+
-
+
+
+
+
+ Project Dashboard
+
+ Overview of project settings and configuration.
+
+
+
+
-
+
+
+
+
+ Document
+ A document with metadata displayed.
+
+
+
+ View
+
+
+
+
-
+
+
+
+
+ File Attachment
+
+ Complete file with image, title, description, and action button.
+
+
+
+ Download
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-muted.tsx b/apps/v4/examples/base/item-muted.tsx
new file mode 100644
index 000000000..97ba1e935
--- /dev/null
+++ b/apps/v4/examples/base/item-muted.tsx
@@ -0,0 +1,108 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemDescription,
+ ItemMedia,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+import { InboxIcon } from "lucide-react"
+
+export function MutedVariantItems() {
+ return (
+ <>
+
-
+
+ Title Only
+
+
+
-
+
+ Title + Button
+
+
+ Action
+
+
+
-
+
+ Title + Description
+
+ This is a description that provides additional context.
+
+
+
+
-
+
+ Title + Description + Button
+
+ This item includes a title, description, and action button.
+
+
+
+ Action
+
+
+
-
+
+
+
+
+ Media + Title
+
+
+
-
+
+
+
+
+ Media + Title + Button
+
+
+ Action
+
+
+
-
+
+
+
+
+ Media + Title + Description
+
+ This item includes media, title, and description.
+
+
+
+
-
+
+
+
+
+ Media + Title + Description + Button
+
+ Complete item with all components: media, title, description, and
+ button.
+
+
+
+ Action
+
+
+
-
+
+ Multiple Actions
+
+ Item with multiple action buttons in the actions area.
+
+
+
+
+ Cancel
+
+ Confirm
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-outline-extra-small.tsx b/apps/v4/examples/base/item-outline-extra-small.tsx
new file mode 100644
index 000000000..d318be868
--- /dev/null
+++ b/apps/v4/examples/base/item-outline-extra-small.tsx
@@ -0,0 +1,112 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemDescription,
+ ItemMedia,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+import { InboxIcon } from "lucide-react"
+
+export function ItemOutlineExtraSmall() {
+ return (
+ <>
+
-
+
+ Title Only
+
+
+
-
+
+ Title + Button
+
+
+
+ Action
+
+
+
+
-
+
+ Title + Description
+
+ This is a description that provides additional context.
+
+
+
+
-
+
+ Title + Description + Button
+
+ This item includes a title, description, and action button.
+
+
+
+
+ Action
+
+
+
+
-
+
+
+
+
+ Media + Title
+
+
+
-
+
+
+
+
+ Media + Title + Button
+
+
+ Action
+
+
+
-
+
+
+
+
+ Media + Title + Description
+
+ This item includes media, title, and description.
+
+
+
+
-
+
+
+
+
+ Media + Title + Description + Button
+
+ Complete item with all components: media, title, description, and
+ button.
+
+
+
+ Action
+
+
+
-
+
+ Multiple Actions
+
+ Item with multiple action buttons in the actions area.
+
+
+
+
+ Cancel
+
+ Confirm
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-outline-small.tsx b/apps/v4/examples/base/item-outline-small.tsx
new file mode 100644
index 000000000..50c028828
--- /dev/null
+++ b/apps/v4/examples/base/item-outline-small.tsx
@@ -0,0 +1,112 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemDescription,
+ ItemMedia,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+import { InboxIcon } from "lucide-react"
+
+export function ItemOutlineSmall() {
+ return (
+ <>
+
-
+
+ Title Only
+
+
+
-
+
+ Title + Button
+
+
+
+ Action
+
+
+
+
-
+
+ Title + Description
+
+ This is a description that provides additional context.
+
+
+
+
-
+
+ Title + Description + Button
+
+ This item includes a title, description, and action button.
+
+
+
+
+ Action
+
+
+
+
-
+
+
+
+
+ Media + Title
+
+
+
-
+
+
+
+
+ Media + Title + Button
+
+
+ Action
+
+
+
-
+
+
+
+
+ Media + Title + Description
+
+ This item includes media, title, and description.
+
+
+
+
-
+
+
+
+
+ Media + Title + Description + Button
+
+ Complete item with all components: media, title, description, and
+ button.
+
+
+
+ Action
+
+
+
-
+
+ Multiple Actions
+
+ Item with multiple action buttons in the actions area.
+
+
+
+
+ Cancel
+
+ Confirm
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-outline-with-image-extra-small.tsx b/apps/v4/examples/base/item-outline-with-image-extra-small.tsx
new file mode 100644
index 000000000..8c4ced685
--- /dev/null
+++ b/apps/v4/examples/base/item-outline-with-image-extra-small.tsx
@@ -0,0 +1,66 @@
+import Image from "next/image"
+import { Button } from "@/examples/base/ui/button"
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemMedia,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+
+export function ItemOutlineWithImageExtraSmall() {
+ return (
+ <>
+
-
+
+
+
+
+ Project Dashboard
+
+
+
-
+
+
+
+
+ Document
+
+
+
+ View
+
+
+
+
-
+
+
+
+
+ File Attachment
+
+
+ Download
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-outline-with-image-small.tsx b/apps/v4/examples/base/item-outline-with-image-small.tsx
new file mode 100644
index 000000000..c1cc68755
--- /dev/null
+++ b/apps/v4/examples/base/item-outline-with-image-small.tsx
@@ -0,0 +1,74 @@
+import Image from "next/image"
+import { Button } from "@/examples/base/ui/button"
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemDescription,
+ ItemMedia,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+
+export function ItemOutlineWithImageSmall() {
+ return (
+ <>
+
-
+
+
+
+
+ Project Dashboard
+
+ Overview of project settings and configuration.
+
+
+
+
-
+
+
+
+
+ Document
+ A document with metadata displayed.
+
+
+
+ View
+
+
+
+
-
+
+
+
+
+ File Attachment
+
+ Complete file with image, title, description, and action button.
+
+
+
+ Download
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-outline-with-image.tsx b/apps/v4/examples/base/item-outline-with-image.tsx
new file mode 100644
index 000000000..db47972bb
--- /dev/null
+++ b/apps/v4/examples/base/item-outline-with-image.tsx
@@ -0,0 +1,74 @@
+import Image from "next/image"
+import { Button } from "@/examples/base/ui/button"
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemDescription,
+ ItemMedia,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+
+export function OutlineVariantItemsWithImage() {
+ return (
+ <>
+
-
+
+
+
+
+ Project Dashboard
+
+ Overview of project settings and configuration.
+
+
+
+
-
+
+
+
+
+ Document
+ A document with metadata displayed.
+
+
+
+ View
+
+
+
+
-
+
+
+
+
+ File Attachment
+
+ Complete file with image, title, description, and action button.
+
+
+
+ Download
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-outline.tsx b/apps/v4/examples/base/item-outline.tsx
new file mode 100644
index 000000000..cec7b20d2
--- /dev/null
+++ b/apps/v4/examples/base/item-outline.tsx
@@ -0,0 +1,108 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemDescription,
+ ItemMedia,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+import { InboxIcon } from "lucide-react"
+
+export function OutlineVariantItems() {
+ return (
+ <>
+
-
+
+ Title Only
+
+
+
-
+
+ Title + Button
+
+
+ Action
+
+
+
-
+
+ Title + Description
+
+ This is a description that provides additional context.
+
+
+
+
-
+
+ Title + Description + Button
+
+ This item includes a title, description, and action button.
+
+
+
+ Action
+
+
+
-
+
+
+
+
+ Media + Title
+
+
+
-
+
+
+
+
+ Media + Title + Button
+
+
+ Action
+
+
+
-
+
+
+
+
+ Media + Title + Description
+
+ This item includes media, title, and description.
+
+
+
+
-
+
+
+
+
+ Media + Title + Description + Button
+
+ Complete item with all components: media, title, description, and
+ button.
+
+
+
+ Action
+
+
+
-
+
+ Multiple Actions
+
+ Item with multiple action buttons in the actions area.
+
+
+
+
+ Cancel
+
+ Confirm
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/item-separator-example.tsx b/apps/v4/examples/base/item-separator-example.tsx
new file mode 100644
index 000000000..849ef2955
--- /dev/null
+++ b/apps/v4/examples/base/item-separator-example.tsx
@@ -0,0 +1,56 @@
+import {
+ Item,
+ ItemContent,
+ ItemDescription,
+ ItemGroup,
+ ItemMedia,
+ ItemSeparator,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+import { InboxIcon } from "lucide-react"
+
+export function ItemSeparatorExample() {
+ return (
+
+ -
+
+
+
+
+ Inbox
+ View all incoming messages.
+
+
+
+ -
+
+
+
+
+ Sent
+ View all sent messages.
+
+
+
+ -
+
+
+
+
+ Drafts
+ View all draft messages.
+
+
+
+ -
+
+
+
+
+ Archive
+ View archived messages.
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/kbd-arrow-keys.tsx b/apps/v4/examples/base/kbd-arrow-keys.tsx
new file mode 100644
index 000000000..ef244b555
--- /dev/null
+++ b/apps/v4/examples/base/kbd-arrow-keys.tsx
@@ -0,0 +1,12 @@
+import { Kbd } from "@/examples/base/ui/kbd"
+
+export function KbdArrowKeys() {
+ return (
+
+ ↑
+ ↓
+ ←
+ →
+
+ )
+}
diff --git a/apps/v4/examples/base/kbd-basic.tsx b/apps/v4/examples/base/kbd-basic.tsx
new file mode 100644
index 000000000..346ca291b
--- /dev/null
+++ b/apps/v4/examples/base/kbd-basic.tsx
@@ -0,0 +1,11 @@
+import { Kbd } from "@/examples/base/ui/kbd"
+
+export function KbdBasic() {
+ return (
+
+ Ctrl
+ ⌘K
+ Ctrl + B
+
+ )
+}
diff --git a/apps/v4/examples/base/kbd-group-example.tsx b/apps/v4/examples/base/kbd-group-example.tsx
new file mode 100644
index 000000000..b1b592d92
--- /dev/null
+++ b/apps/v4/examples/base/kbd-group-example.tsx
@@ -0,0 +1,11 @@
+import { Kbd, KbdGroup } from "@/examples/base/ui/kbd"
+
+export function KbdGroupExample() {
+ return (
+
+ Ctrl
+ Shift
+ P
+
+ )
+}
diff --git a/apps/v4/examples/base/kbd-in-input-group.tsx b/apps/v4/examples/base/kbd-in-input-group.tsx
new file mode 100644
index 000000000..69c01db64
--- /dev/null
+++ b/apps/v4/examples/base/kbd-in-input-group.tsx
@@ -0,0 +1,17 @@
+import {
+ InputGroup,
+ InputGroupAddon,
+ InputGroupInput,
+} from "@/examples/base/ui/input-group"
+import { Kbd } from "@/examples/base/ui/kbd"
+
+export function KbdInInputGroup() {
+ return (
+
+
+
+ Space
+
+
+ )
+}
diff --git a/apps/v4/examples/base/kbd-in-tooltip.tsx b/apps/v4/examples/base/kbd-in-tooltip.tsx
new file mode 100644
index 000000000..0229bcbab
--- /dev/null
+++ b/apps/v4/examples/base/kbd-in-tooltip.tsx
@@ -0,0 +1,25 @@
+import { Button } from "@/examples/base/ui/button"
+import { Kbd } from "@/examples/base/ui/kbd"
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from "@/examples/base/ui/tooltip"
+import { SaveIcon } from "lucide-react"
+
+export function KbdInTooltip() {
+ return (
+ <>
+
+ }>
+
+
+
+
+ Save Changes S
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/kbd-modifier-keys.tsx b/apps/v4/examples/base/kbd-modifier-keys.tsx
new file mode 100644
index 000000000..d669c9ff0
--- /dev/null
+++ b/apps/v4/examples/base/kbd-modifier-keys.tsx
@@ -0,0 +1,10 @@
+import { Kbd } from "@/examples/base/ui/kbd"
+
+export function KbdModifierKeys() {
+ return (
+
+ ⌘
+ C
+
+ )
+}
diff --git a/apps/v4/examples/base/kbd-with-icons-and-text.tsx b/apps/v4/examples/base/kbd-with-icons-and-text.tsx
new file mode 100644
index 000000000..3f8ca9a86
--- /dev/null
+++ b/apps/v4/examples/base/kbd-with-icons-and-text.tsx
@@ -0,0 +1,17 @@
+import { Kbd, KbdGroup } from "@/examples/base/ui/kbd"
+import { ArrowLeftIcon, CircleDashedIcon } from "lucide-react"
+
+export function KbdWithIconsAndText() {
+ return (
+
+
+
+ Left
+
+
+
+ Voice Enabled
+
+
+ )
+}
diff --git a/apps/v4/examples/base/kbd-with-icons.tsx b/apps/v4/examples/base/kbd-with-icons.tsx
new file mode 100644
index 000000000..b9405a964
--- /dev/null
+++ b/apps/v4/examples/base/kbd-with-icons.tsx
@@ -0,0 +1,18 @@
+import { Kbd, KbdGroup } from "@/examples/base/ui/kbd"
+import { ArrowLeftIcon, ArrowRightIcon, CircleDashedIcon } from "lucide-react"
+
+export function KbdWithIcons() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/kbd-with-samp.tsx b/apps/v4/examples/base/kbd-with-samp.tsx
new file mode 100644
index 000000000..716e2502d
--- /dev/null
+++ b/apps/v4/examples/base/kbd-with-samp.tsx
@@ -0,0 +1,9 @@
+import { Kbd } from "@/examples/base/ui/kbd"
+
+export function KbdWithSamp() {
+ return (
+
+ File
+
+ )
+}
diff --git a/apps/v4/examples/base/label-disabled.tsx b/apps/v4/examples/base/label-disabled.tsx
new file mode 100644
index 000000000..b58a490a7
--- /dev/null
+++ b/apps/v4/examples/base/label-disabled.tsx
@@ -0,0 +1,12 @@
+import { Field } from "@/examples/base/ui/field"
+import { Input } from "@/examples/base/ui/input"
+import { Label } from "@/examples/base/ui/label"
+
+export function LabelDisabled() {
+ return (
+
+ Disabled
+
+
+ )
+}
diff --git a/apps/v4/examples/base/label-with-checkbox.tsx b/apps/v4/examples/base/label-with-checkbox.tsx
new file mode 100644
index 000000000..372d25344
--- /dev/null
+++ b/apps/v4/examples/base/label-with-checkbox.tsx
@@ -0,0 +1,12 @@
+import { Checkbox } from "@/examples/base/ui/checkbox"
+import { Field } from "@/examples/base/ui/field"
+import { Label } from "@/examples/base/ui/label"
+
+export function LabelWithCheckbox() {
+ return (
+
+
+ Accept terms and conditions
+
+ )
+}
diff --git a/apps/v4/examples/base/label-with-input.tsx b/apps/v4/examples/base/label-with-input.tsx
new file mode 100644
index 000000000..e28077c37
--- /dev/null
+++ b/apps/v4/examples/base/label-with-input.tsx
@@ -0,0 +1,12 @@
+import { Field } from "@/examples/base/ui/field"
+import { Input } from "@/examples/base/ui/input"
+import { Label } from "@/examples/base/ui/label"
+
+export function LabelWithInput() {
+ return (
+
+ Username
+
+
+ )
+}
diff --git a/apps/v4/examples/base/label-with-textarea.tsx b/apps/v4/examples/base/label-with-textarea.tsx
new file mode 100644
index 000000000..455ba2377
--- /dev/null
+++ b/apps/v4/examples/base/label-with-textarea.tsx
@@ -0,0 +1,12 @@
+import { Field } from "@/examples/base/ui/field"
+import { Label } from "@/examples/base/ui/label"
+import { Textarea } from "@/examples/base/ui/textarea"
+
+export function LabelWithTextarea() {
+ return (
+
+ Message
+
+
+ )
+}
diff --git a/apps/v4/examples/base/menubar-basic.tsx b/apps/v4/examples/base/menubar-basic.tsx
new file mode 100644
index 000000000..8b6495cd7
--- /dev/null
+++ b/apps/v4/examples/base/menubar-basic.tsx
@@ -0,0 +1,47 @@
+import {
+ Menubar,
+ MenubarContent,
+ MenubarItem,
+ MenubarMenu,
+ MenubarSeparator,
+ MenubarShortcut,
+ MenubarTrigger,
+} from "@/examples/base/ui/menubar"
+
+export function MenubarBasic() {
+ return (
+
+
+ File
+
+
+ New Tab ⌘T
+
+
+ New Window ⌘N
+
+ New Incognito Window
+
+
+ Print... ⌘P
+
+
+
+
+ Edit
+
+
+ Undo ⌘Z
+
+
+ Redo ⇧⌘Z
+
+
+ Cut
+ Copy
+ Paste
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/menubar-destructive.tsx b/apps/v4/examples/base/menubar-destructive.tsx
new file mode 100644
index 000000000..eb611c30a
--- /dev/null
+++ b/apps/v4/examples/base/menubar-destructive.tsx
@@ -0,0 +1,65 @@
+import {
+ Menubar,
+ MenubarContent,
+ MenubarItem,
+ MenubarMenu,
+ MenubarSeparator,
+ MenubarShortcut,
+ MenubarTrigger,
+} from "@/examples/base/ui/menubar"
+import {
+ FileIcon,
+ FolderIcon,
+ LogOutIcon,
+ SettingsIcon,
+ TrashIcon,
+ UserIcon,
+} from "lucide-react"
+
+export function MenubarDestructive() {
+ return (
+
+
+ File
+
+
+
+ New File ⌘N
+
+
+
+ Open Folder
+
+
+
+
+ Delete File ⌘⌫
+
+
+
+
+ Account
+
+
+
+ Profile
+
+
+
+ Settings
+
+
+
+
+ Sign out
+
+
+
+
+ Delete
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/menubar-format.tsx b/apps/v4/examples/base/menubar-format.tsx
new file mode 100644
index 000000000..189d0f292
--- /dev/null
+++ b/apps/v4/examples/base/menubar-format.tsx
@@ -0,0 +1,48 @@
+import {
+ Menubar,
+ MenubarCheckboxItem,
+ MenubarContent,
+ MenubarItem,
+ MenubarMenu,
+ MenubarSeparator,
+ MenubarShortcut,
+ MenubarTrigger,
+} from "@/examples/base/ui/menubar"
+import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react"
+
+export function MenubarFormat() {
+ return (
+
+
+ Format
+
+
+
+ Bold ⌘B
+
+
+
+ Italic ⌘I
+
+
+
+ Underline ⌘U
+
+
+ Strikethrough
+ Code
+
+
+
+ View
+
+ Show Ruler
+ Show Grid
+
+ Zoom In
+ Zoom Out
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/menubar-in-dialog.tsx b/apps/v4/examples/base/menubar-in-dialog.tsx
new file mode 100644
index 000000000..a86d92580
--- /dev/null
+++ b/apps/v4/examples/base/menubar-in-dialog.tsx
@@ -0,0 +1,93 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogHeader,
+ DialogTitle,
+ DialogTrigger,
+} from "@/examples/base/ui/dialog"
+import {
+ Menubar,
+ MenubarContent,
+ MenubarItem,
+ MenubarMenu,
+ MenubarSeparator,
+ MenubarShortcut,
+ MenubarSub,
+ MenubarSubContent,
+ MenubarSubTrigger,
+ MenubarTrigger,
+} from "@/examples/base/ui/menubar"
+import {
+ ClipboardPasteIcon,
+ CopyIcon,
+ ScissorsIcon,
+ TrashIcon,
+} from "lucide-react"
+
+export function MenubarInDialog() {
+ return (
+ <>
+
+ }>
+ Open Dialog
+
+
+
+ Menubar Example
+
+ Use the menubar below to see the menu options.
+
+
+
+
+ File
+
+
+
+ Copy
+
+
+
+ Cut
+
+
+
+ Paste
+
+
+
+ More Options
+
+ Save Page...
+ Create Shortcut...
+ Name Window...
+
+ Developer Tools
+
+
+
+
+
+ Delete
+
+
+
+
+ Edit
+
+
+ Undo ⌘Z
+
+
+ Redo ⇧⌘Z
+
+
+
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/menubar-insert.tsx b/apps/v4/examples/base/menubar-insert.tsx
new file mode 100644
index 000000000..055ff5bae
--- /dev/null
+++ b/apps/v4/examples/base/menubar-insert.tsx
@@ -0,0 +1,64 @@
+import {
+ Menubar,
+ MenubarContent,
+ MenubarItem,
+ MenubarMenu,
+ MenubarSeparator,
+ MenubarShortcut,
+ MenubarSub,
+ MenubarSubContent,
+ MenubarSubTrigger,
+ MenubarTrigger,
+} from "@/examples/base/ui/menubar"
+import {
+ CheckIcon,
+ ImageIcon,
+ LinkIcon,
+ SearchIcon,
+ TableIcon,
+} from "lucide-react"
+
+export function MenubarInsert() {
+ return (
+
+
+ Insert
+
+
+
+
+ Media
+
+
+ Image
+ Video
+ Audio
+
+
+
+
+
+ Link ⌘K
+
+
+
+ Table
+
+
+
+
+ Tools
+
+
+
+ Find & Replace ⌘F
+
+
+
+ Spell Check
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/menubar-with-checkboxes.tsx b/apps/v4/examples/base/menubar-with-checkboxes.tsx
new file mode 100644
index 000000000..54e94af7c
--- /dev/null
+++ b/apps/v4/examples/base/menubar-with-checkboxes.tsx
@@ -0,0 +1,41 @@
+import {
+ Menubar,
+ MenubarCheckboxItem,
+ MenubarContent,
+ MenubarItem,
+ MenubarMenu,
+ MenubarSeparator,
+ MenubarShortcut,
+ MenubarTrigger,
+} from "@/examples/base/ui/menubar"
+
+export function MenubarWithCheckboxes() {
+ return (
+
+
+ View
+
+ Always Show Bookmarks Bar
+
+ Always Show Full URLs
+
+
+
+ Reload ⌘R
+
+
+ Force Reload ⇧⌘R
+
+
+
+
+ Format
+
+ Strikethrough
+ Code
+ Superscript
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/menubar-with-icons.tsx b/apps/v4/examples/base/menubar-with-icons.tsx
new file mode 100644
index 000000000..4239cc634
--- /dev/null
+++ b/apps/v4/examples/base/menubar-with-icons.tsx
@@ -0,0 +1,56 @@
+import {
+ Menubar,
+ MenubarContent,
+ MenubarGroup,
+ MenubarItem,
+ MenubarMenu,
+ MenubarSeparator,
+ MenubarShortcut,
+ MenubarTrigger,
+} from "@/examples/base/ui/menubar"
+import { CircleDashedIcon, FileIcon, FolderIcon, SaveIcon } from "lucide-react"
+
+export function MenubarWithIcons() {
+ return (
+
+
+ File
+
+
+
+ New File ⌘N
+
+
+
+ Open Folder
+
+
+
+
+ Save ⌘S
+
+
+
+
+ More
+
+
+
+
+ Settings
+
+
+
+ Help
+
+
+
+
+ Delete
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/menubar-with-radio.tsx b/apps/v4/examples/base/menubar-with-radio.tsx
new file mode 100644
index 000000000..564ca4e6e
--- /dev/null
+++ b/apps/v4/examples/base/menubar-with-radio.tsx
@@ -0,0 +1,46 @@
+"use client"
+
+import * as React from "react"
+import {
+ Menubar,
+ MenubarContent,
+ MenubarItem,
+ MenubarMenu,
+ MenubarRadioGroup,
+ MenubarRadioItem,
+ MenubarSeparator,
+ MenubarTrigger,
+} from "@/examples/base/ui/menubar"
+
+export function MenubarWithRadio() {
+ const [user, setUser] = React.useState("benoit")
+ const [theme, setTheme] = React.useState("system")
+
+ return (
+
+
+ Profiles
+
+
+ Andy
+ Benoit
+ Luis
+
+
+ Edit...
+ Add Profile...
+
+
+
+ Theme
+
+
+ Light
+ Dark
+ System
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/menubar-with-shortcuts.tsx b/apps/v4/examples/base/menubar-with-shortcuts.tsx
new file mode 100644
index 000000000..cad511057
--- /dev/null
+++ b/apps/v4/examples/base/menubar-with-shortcuts.tsx
@@ -0,0 +1,51 @@
+import {
+ Menubar,
+ MenubarContent,
+ MenubarItem,
+ MenubarMenu,
+ MenubarSeparator,
+ MenubarShortcut,
+ MenubarTrigger,
+} from "@/examples/base/ui/menubar"
+
+export function MenubarWithShortcuts() {
+ return (
+
+
+ File
+
+
+ New Tab ⌘T
+
+
+ New Window ⌘N
+
+
+ Print... ⌘P
+
+
+
+
+ Edit
+
+
+ Undo ⌘Z
+
+
+ Redo ⇧⌘Z
+
+
+
+ Cut ⌘X
+
+
+ Copy ⌘C
+
+
+ Paste ⌘V
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/menubar-with-submenu.tsx b/apps/v4/examples/base/menubar-with-submenu.tsx
new file mode 100644
index 000000000..14f802dc4
--- /dev/null
+++ b/apps/v4/examples/base/menubar-with-submenu.tsx
@@ -0,0 +1,60 @@
+import {
+ Menubar,
+ MenubarContent,
+ MenubarItem,
+ MenubarMenu,
+ MenubarSeparator,
+ MenubarShortcut,
+ MenubarSub,
+ MenubarSubContent,
+ MenubarSubTrigger,
+ MenubarTrigger,
+} from "@/examples/base/ui/menubar"
+
+export function MenubarWithSubmenu() {
+ return (
+
+
+ File
+
+
+ Share
+
+ Email link
+ Messages
+ Notes
+
+
+
+
+ Print... ⌘P
+
+
+
+
+ Edit
+
+
+ Undo ⌘Z
+
+
+ Redo ⇧⌘Z
+
+
+
+ Find
+
+ Find...
+ Find Next
+ Find Previous
+
+
+
+ Cut
+ Copy
+ Paste
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/muted-item-group.tsx b/apps/v4/examples/base/muted-item-group.tsx
new file mode 100644
index 000000000..8cd94878d
--- /dev/null
+++ b/apps/v4/examples/base/muted-item-group.tsx
@@ -0,0 +1,49 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Item,
+ ItemActions,
+ ItemContent,
+ ItemDescription,
+ ItemGroup,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+
+export function MutedItemGroup() {
+ return (
+
+ -
+
+ Item 1
+ First item in muted group.
+
+
+
+ Action
+
+
+
+ -
+
+ Item 2
+ Second item in muted group.
+
+
+
+ Action
+
+
+
+ -
+
+ Item 3
+ Third item in muted group.
+
+
+
+ Action
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/native-select-basic.tsx b/apps/v4/examples/base/native-select-basic.tsx
new file mode 100644
index 000000000..195e6a7db
--- /dev/null
+++ b/apps/v4/examples/base/native-select-basic.tsx
@@ -0,0 +1,19 @@
+import {
+ NativeSelect,
+ NativeSelectOption,
+} from "@/examples/base/ui/native-select"
+
+export function NativeSelectBasic() {
+ return (
+
+ Select a fruit
+ Apple
+ Banana
+ Blueberry
+
+ Grapes
+
+ Pineapple
+
+ )
+}
diff --git a/apps/v4/examples/base/native-select-disabled.tsx b/apps/v4/examples/base/native-select-disabled.tsx
index 698af00d5..bd1574161 100644
--- a/apps/v4/examples/base/native-select-disabled.tsx
+++ b/apps/v4/examples/base/native-select-disabled.tsx
@@ -3,14 +3,13 @@ import {
NativeSelectOption,
} from "@/examples/base/ui/native-select"
-export default function NativeSelectDisabled() {
+export function NativeSelectDisabled() {
return (
- Select priority
- Low
- Medium
- High
- Critical
+ Disabled
+ Apple
+ Banana
+ Blueberry
)
}
diff --git a/apps/v4/examples/base/native-select-fields.tsx b/apps/v4/examples/base/native-select-fields.tsx
new file mode 100644
index 000000000..83bb6ec2c
--- /dev/null
+++ b/apps/v4/examples/base/native-select-fields.tsx
@@ -0,0 +1,101 @@
+import {
+ Field,
+ FieldDescription,
+ FieldGroup,
+ FieldLabel,
+} from "@/examples/base/ui/field"
+import {
+ NativeSelect,
+ NativeSelectOptGroup,
+ NativeSelectOption,
+} from "@/examples/base/ui/native-select"
+import { Select } from "@/examples/base/ui/select"
+
+export function NativeSelectFields() {
+ return (
+
+
+
+ Basic Native Select
+
+
+ Choose an option
+ Option 1
+ Option 2
+ Option 3
+
+
+
+ Country
+
+ Select your country
+ United States
+ United Kingdom
+ Canada
+
+
+ Select the country where you currently reside.
+
+
+
+ Timezone
+
+ Choose your local timezone for accurate scheduling.
+
+
+ Select timezone
+ UTC
+ Eastern Time
+ Pacific Time
+
+
+
+ Grouped Options
+
+ Select a region
+
+ United States
+ Canada
+ Mexico
+
+
+ United Kingdom
+ France
+ Germany
+
+
+
+ Native select with grouped options using optgroup.
+
+
+
+
+ Invalid Native Select
+
+
+
+ This field has an error
+
+ Option 1
+ Option 2
+ Option 3
+
+
+ This field contains validation errors.
+
+
+
+
+ Disabled Field
+
+
+ Cannot select
+ Option 1
+ Option 2
+ Option 3
+
+ This field is currently disabled.
+
+
+ )
+}
diff --git a/apps/v4/examples/base/native-select-invalid.tsx b/apps/v4/examples/base/native-select-invalid.tsx
index 79741484a..1fe5435a5 100644
--- a/apps/v4/examples/base/native-select-invalid.tsx
+++ b/apps/v4/examples/base/native-select-invalid.tsx
@@ -3,14 +3,13 @@ import {
NativeSelectOption,
} from "@/examples/base/ui/native-select"
-export default function NativeSelectInvalid() {
+export function NativeSelectInvalid() {
return (
- Select role
- Admin
- Editor
- Viewer
- Guest
+ Error state
+ Apple
+ Banana
+ Blueberry
)
}
diff --git a/apps/v4/examples/base/native-select-sizes.tsx b/apps/v4/examples/base/native-select-sizes.tsx
new file mode 100644
index 000000000..4ed3168d5
--- /dev/null
+++ b/apps/v4/examples/base/native-select-sizes.tsx
@@ -0,0 +1,23 @@
+import {
+ NativeSelect,
+ NativeSelectOption,
+} from "@/examples/base/ui/native-select"
+
+export function NativeSelectSizes() {
+ return (
+
+
+ Select a fruit
+ Apple
+ Banana
+ Blueberry
+
+
+ Select a fruit
+ Apple
+ Banana
+ Blueberry
+
+
+ )
+}
diff --git a/apps/v4/examples/base/native-select-with-field.tsx b/apps/v4/examples/base/native-select-with-field.tsx
new file mode 100644
index 000000000..1348d5931
--- /dev/null
+++ b/apps/v4/examples/base/native-select-with-field.tsx
@@ -0,0 +1,21 @@
+import { Field, FieldDescription, FieldLabel } from "@/examples/base/ui/field"
+import {
+ NativeSelect,
+ NativeSelectOption,
+} from "@/examples/base/ui/native-select"
+
+export function NativeSelectWithField() {
+ return (
+
+ Country
+
+ Select a country
+ United States
+ United Kingdom
+ Canada
+ Australia
+
+ Select your country of residence.
+
+ )
+}
diff --git a/apps/v4/examples/base/native-select-with-groups.tsx b/apps/v4/examples/base/native-select-with-groups.tsx
new file mode 100644
index 000000000..3d9006bc9
--- /dev/null
+++ b/apps/v4/examples/base/native-select-with-groups.tsx
@@ -0,0 +1,23 @@
+import {
+ NativeSelect,
+ NativeSelectOptGroup,
+ NativeSelectOption,
+} from "@/examples/base/ui/native-select"
+
+export function NativeSelectWithGroups() {
+ return (
+
+ Select a food
+
+ Apple
+ Banana
+ Blueberry
+
+
+ Carrot
+ Broccoli
+ Spinach
+
+
+ )
+}
diff --git a/apps/v4/examples/base/navigation-menu-basic.tsx b/apps/v4/examples/base/navigation-menu-basic.tsx
new file mode 100644
index 000000000..319bd71e0
--- /dev/null
+++ b/apps/v4/examples/base/navigation-menu-basic.tsx
@@ -0,0 +1,152 @@
+import * as React from "react"
+import Link from "next/link"
+import {
+ NavigationMenu,
+ NavigationMenuContent,
+ NavigationMenuItem,
+ NavigationMenuLink,
+ NavigationMenuList,
+ NavigationMenuTrigger,
+ navigationMenuTriggerStyle,
+} from "@/examples/base/ui/navigation-menu"
+import { CircleAlertIcon } from "lucide-react"
+
+const components: { title: string; href: string; description: string }[] = [
+ {
+ title: "Alert Dialog",
+ href: "/docs/primitives/alert-dialog",
+ description:
+ "A modal dialog that interrupts the user with important content and expects a response.",
+ },
+ {
+ title: "Hover Card",
+ href: "/docs/primitives/hover-card",
+ description:
+ "For sighted users to preview content available behind a link.",
+ },
+ {
+ title: "Progress",
+ href: "/docs/primitives/progress",
+ description:
+ "Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.",
+ },
+ {
+ title: "Scroll-area",
+ href: "/docs/primitives/scroll-area",
+ description: "Visually or semantically separates content.",
+ },
+ {
+ title: "Tabs",
+ href: "/docs/primitives/tabs",
+ description:
+ "A set of layered sections of content—known as tab panels—that are displayed one at a time.",
+ },
+ {
+ title: "Tooltip",
+ href: "/docs/primitives/tooltip",
+ description:
+ "A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.",
+ },
+]
+
+function ListItem({
+ title,
+ children,
+ href,
+ ...props
+}: React.ComponentPropsWithoutRef<"li"> & { href: string }) {
+ return (
+
+ }>
+
+
+
+ )
+}
+
+export function NavigationMenuBasic() {
+ return (
+ <>
+
+
+
+ Getting started
+
+
+
+ Re-usable components built with Tailwind CSS.
+
+
+ How to install dependencies and structure your app.
+
+
+ Styles for headings, paragraphs, lists...etc
+
+
+
+
+
+ Components
+
+
+ {components.map((component) => (
+
+ {component.description}
+
+ ))}
+
+
+
+
+ With Icon
+
+
+
+
+ }
+ >
+
+ Backlog
+
+
+ }
+ >
+
+ To Do
+
+
+ }
+ >
+
+ Done
+
+
+
+
+
+
+ }
+ className={navigationMenuTriggerStyle()}
+ >
+ Documentation
+
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/outline-item-group.tsx b/apps/v4/examples/base/outline-item-group.tsx
new file mode 100644
index 000000000..def2e92f9
--- /dev/null
+++ b/apps/v4/examples/base/outline-item-group.tsx
@@ -0,0 +1,43 @@
+import {
+ Item,
+ ItemContent,
+ ItemDescription,
+ ItemGroup,
+ ItemMedia,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+import { InboxIcon } from "lucide-react"
+
+export function OutlineItemGroup() {
+ return (
+
+ -
+
+
+
+
+ Item 1
+ First item with icon.
+
+
+ -
+
+
+
+
+ Item 2
+ Second item with icon.
+
+
+ -
+
+
+
+
+ Item 3
+ Third item with icon.
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/pagination-basic.tsx b/apps/v4/examples/base/pagination-basic.tsx
new file mode 100644
index 000000000..d2641ffbb
--- /dev/null
+++ b/apps/v4/examples/base/pagination-basic.tsx
@@ -0,0 +1,38 @@
+import {
+ Pagination,
+ PaginationContent,
+ PaginationEllipsis,
+ PaginationItem,
+ PaginationLink,
+ PaginationNext,
+ PaginationPrevious,
+} from "@/examples/base/ui/pagination"
+
+export function PaginationBasic() {
+ return (
+
+
+
+
+
+
+ 1
+
+
+
+ 2
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/pagination-icons-only.tsx b/apps/v4/examples/base/pagination-icons-only.tsx
new file mode 100644
index 000000000..0188e43c7
--- /dev/null
+++ b/apps/v4/examples/base/pagination-icons-only.tsx
@@ -0,0 +1,49 @@
+import { Field, FieldLabel } from "@/examples/base/ui/field"
+import {
+ Pagination,
+ PaginationContent,
+ PaginationItem,
+ PaginationNext,
+ PaginationPrevious,
+} from "@/examples/base/ui/pagination"
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+
+export function PaginationIconsOnly() {
+ return (
+
+
+ Rows per page
+
+
+
+
+
+
+ 10
+ 25
+ 50
+ 100
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/pagination-simple.tsx b/apps/v4/examples/base/pagination-simple.tsx
new file mode 100644
index 000000000..90885621d
--- /dev/null
+++ b/apps/v4/examples/base/pagination-simple.tsx
@@ -0,0 +1,32 @@
+import {
+ Pagination,
+ PaginationContent,
+ PaginationItem,
+ PaginationLink,
+} from "@/examples/base/ui/pagination"
+
+export function PaginationSimple() {
+ return (
+
+
+
+ 1
+
+
+
+ 2
+
+
+
+ 3
+
+
+ 4
+
+
+ 5
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/popover-alignments.tsx b/apps/v4/examples/base/popover-alignments.tsx
new file mode 100644
index 000000000..2270e305d
--- /dev/null
+++ b/apps/v4/examples/base/popover-alignments.tsx
@@ -0,0 +1,39 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/examples/base/ui/popover"
+
+export function PopoverAlignments() {
+ return (
+ <>
+
+
+ }>
+ Start
+
+
+ Aligned to start
+
+
+
+ }>
+ Center
+
+
+ Aligned to center
+
+
+
+ }>
+ End
+
+
+ Aligned to end
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/popover-basic.tsx b/apps/v4/examples/base/popover-basic.tsx
new file mode 100644
index 000000000..21a790f8f
--- /dev/null
+++ b/apps/v4/examples/base/popover-basic.tsx
@@ -0,0 +1,29 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Popover,
+ PopoverContent,
+ PopoverDescription,
+ PopoverHeader,
+ PopoverTitle,
+ PopoverTrigger,
+} from "@/examples/base/ui/popover"
+
+export function PopoverBasic() {
+ return (
+ <>
+
+ }>
+ Open Popover
+
+
+
+ Dimensions
+
+ Set the dimensions for the layer.
+
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/popover-in-dialog.tsx b/apps/v4/examples/base/popover-in-dialog.tsx
new file mode 100644
index 000000000..11cf5ba0e
--- /dev/null
+++ b/apps/v4/examples/base/popover-in-dialog.tsx
@@ -0,0 +1,53 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogHeader,
+ DialogTitle,
+ DialogTrigger,
+} from "@/examples/base/ui/dialog"
+import {
+ Popover,
+ PopoverContent,
+ PopoverDescription,
+ PopoverHeader,
+ PopoverTitle,
+ PopoverTrigger,
+} from "@/examples/base/ui/popover"
+
+export function PopoverInDialog() {
+ return (
+ <>
+
+ }>
+ Open Dialog
+
+
+
+ Popover Example
+
+ Click the button below to see the popover.
+
+
+
+ }
+ >
+ Open Popover
+
+
+
+ Popover in Dialog
+
+ This popover appears inside a dialog. Click the button to open
+ it.
+
+
+
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/popover-with-form.tsx b/apps/v4/examples/base/popover-with-form.tsx
new file mode 100644
index 000000000..db8f86a7f
--- /dev/null
+++ b/apps/v4/examples/base/popover-with-form.tsx
@@ -0,0 +1,45 @@
+import { Button } from "@/examples/base/ui/button"
+import { Field, FieldGroup, FieldLabel } from "@/examples/base/ui/field"
+import { Input } from "@/examples/base/ui/input"
+import {
+ Popover,
+ PopoverContent,
+ PopoverDescription,
+ PopoverHeader,
+ PopoverTitle,
+ PopoverTrigger,
+} from "@/examples/base/ui/popover"
+
+export function PopoverWithForm() {
+ return (
+ <>
+
+ }>
+ Open Popover
+
+
+
+ Dimensions
+
+ Set the dimensions for the layer.
+
+
+
+
+
+ Width
+
+
+
+
+
+ Height
+
+
+
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/progress-controlled.tsx b/apps/v4/examples/base/progress-controlled.tsx
new file mode 100644
index 000000000..32dc14259
--- /dev/null
+++ b/apps/v4/examples/base/progress-controlled.tsx
@@ -0,0 +1,22 @@
+"use client"
+
+import * as React from "react"
+import { Progress } from "@/examples/base/ui/progress"
+import { Slider } from "@/examples/base/ui/slider"
+
+export function ProgressControlled() {
+ const [value, setValue] = React.useState(50)
+
+ return (
+
+
+
setValue(value as number)}
+ min={0}
+ max={100}
+ step={1}
+ />
+
+ )
+}
diff --git a/apps/v4/examples/base/progress-values.tsx b/apps/v4/examples/base/progress-values.tsx
new file mode 100644
index 000000000..8ded71cb1
--- /dev/null
+++ b/apps/v4/examples/base/progress-values.tsx
@@ -0,0 +1,13 @@
+import { Progress } from "@/examples/base/ui/progress"
+
+export function ProgressValues() {
+ return (
+
+ )
+}
diff --git a/apps/v4/examples/base/progress-with-label.tsx b/apps/v4/examples/base/progress-with-label.tsx
new file mode 100644
index 000000000..356558065
--- /dev/null
+++ b/apps/v4/examples/base/progress-with-label.tsx
@@ -0,0 +1,14 @@
+import {
+ Progress,
+ ProgressLabel,
+ ProgressValue,
+} from "@/examples/base/ui/progress"
+
+export function ProgressWithLabel() {
+ return (
+
+ Upload progress
+
+
+ )
+}
diff --git a/apps/v4/examples/base/radio-fields.tsx b/apps/v4/examples/base/radio-fields.tsx
new file mode 100644
index 000000000..793b6ebfe
--- /dev/null
+++ b/apps/v4/examples/base/radio-fields.tsx
@@ -0,0 +1,149 @@
+import {
+ Field,
+ FieldContent,
+ FieldDescription,
+ FieldGroup,
+ FieldLabel,
+ FieldLegend,
+ FieldSet,
+ FieldTitle,
+} from "@/examples/base/ui/field"
+import { RadioGroup, RadioGroupItem } from "@/examples/base/ui/radio-group"
+
+export function RadioFields() {
+ return (
+
+
+ Subscription Plan
+
+
+
+
+ Free Plan
+
+
+
+
+
+ Pro Plan
+
+
+
+
+
+ Enterprise
+
+
+
+
+
+ Battery Level
+
+ Choose your preferred battery level.
+
+
+
+
+ High
+
+
+
+ Medium
+
+
+
+ Low
+
+
+
+
+
+
+
+ Enable Touch ID
+
+ Enable Touch ID to quickly unlock your device.
+
+
+
+
+
+
+
+ Enable Touch ID and Face ID to make it even faster to unlock your
+ device. This is a long label to test the layout.
+
+
+ Enable Touch ID to quickly unlock your device.
+
+
+
+
+
+
+
+
+
+ Enable Touch ID
+
+ Enable Touch ID to quickly unlock your device.
+
+
+
+
+
+
+
+
+
+ Enable Touch ID and Face ID to make it even faster to unlock
+ your device. This is a long label to test the layout.
+
+
+ Enable Touch ID to quickly unlock your device.
+
+
+
+
+
+
+ Invalid Radio Group
+
+
+
+ Invalid Option 1
+
+
+
+ Invalid Option 2
+
+
+
+
+ Disabled Radio Group
+
+
+
+
+ Disabled Option 1
+
+
+
+
+
+ Disabled Option 2
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/radio-group-basic.tsx b/apps/v4/examples/base/radio-group-basic.tsx
new file mode 100644
index 000000000..91e6c1f27
--- /dev/null
+++ b/apps/v4/examples/base/radio-group-basic.tsx
@@ -0,0 +1,27 @@
+import { Field, FieldLabel } from "@/examples/base/ui/field"
+import { RadioGroup, RadioGroupItem } from "@/examples/base/ui/radio-group"
+
+export function RadioGroupBasic() {
+ return (
+
+
+
+
+ Default
+
+
+
+
+
+ Comfortable
+
+
+
+
+
+ Compact
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/radio-group-disabled.tsx b/apps/v4/examples/base/radio-group-disabled.tsx
new file mode 100644
index 000000000..d6217b144
--- /dev/null
+++ b/apps/v4/examples/base/radio-group-disabled.tsx
@@ -0,0 +1,27 @@
+import { Field, FieldLabel } from "@/examples/base/ui/field"
+import { RadioGroup, RadioGroupItem } from "@/examples/base/ui/radio-group"
+
+export function RadioGroupDisabled() {
+ return (
+
+
+
+
+ Option 1
+
+
+
+
+
+ Option 2
+
+
+
+
+
+ Option 3
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/radio-group-grid.tsx b/apps/v4/examples/base/radio-group-grid.tsx
new file mode 100644
index 000000000..d98af9b0e
--- /dev/null
+++ b/apps/v4/examples/base/radio-group-grid.tsx
@@ -0,0 +1,33 @@
+import { Field, FieldLabel } from "@/examples/base/ui/field"
+import { RadioGroup, RadioGroupItem } from "@/examples/base/ui/radio-group"
+
+export function RadioGroupGrid() {
+ return (
+
+
+
+
+ Small
+
+
+
+
+
+ Medium
+
+
+
+
+
+ Large
+
+
+
+
+
+ X-Large
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/radio-group-invalid.tsx b/apps/v4/examples/base/radio-group-invalid.tsx
new file mode 100644
index 000000000..5e87e3c66
--- /dev/null
+++ b/apps/v4/examples/base/radio-group-invalid.tsx
@@ -0,0 +1,39 @@
+import {
+ Field,
+ FieldDescription,
+ FieldLabel,
+ FieldLegend,
+ FieldSet,
+} from "@/examples/base/ui/field"
+import { RadioGroup, RadioGroupItem } from "@/examples/base/ui/radio-group"
+
+export function RadioGroupInvalid() {
+ return (
+
+ Notification Preferences
+
+ Choose how you want to receive notifications.
+
+
+
+
+
+ Email only
+
+
+
+
+
+ SMS only
+
+
+
+
+
+ Both Email & SMS
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/radio-group-with-descriptions.tsx b/apps/v4/examples/base/radio-group-with-descriptions.tsx
new file mode 100644
index 000000000..0f174098a
--- /dev/null
+++ b/apps/v4/examples/base/radio-group-with-descriptions.tsx
@@ -0,0 +1,41 @@
+import {
+ Field,
+ FieldContent,
+ FieldDescription,
+ FieldLabel,
+} from "@/examples/base/ui/field"
+import { RadioGroup, RadioGroupItem } from "@/examples/base/ui/radio-group"
+
+export function RadioGroupWithDescriptions() {
+ return (
+
+
+
+
+ Plus
+ For individuals and small teams
+
+
+
+
+
+
+
+ Pro
+ For growing businesses
+
+
+
+
+
+
+
+ Enterprise
+ For large teams and enterprises
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/radio-group-with-field-set.tsx b/apps/v4/examples/base/radio-group-with-field-set.tsx
new file mode 100644
index 000000000..e4a9ff447
--- /dev/null
+++ b/apps/v4/examples/base/radio-group-with-field-set.tsx
@@ -0,0 +1,37 @@
+import {
+ Field,
+ FieldDescription,
+ FieldLabel,
+ FieldLegend,
+ FieldSet,
+} from "@/examples/base/ui/field"
+import { RadioGroup, RadioGroupItem } from "@/examples/base/ui/radio-group"
+
+export function RadioGroupWithFieldSet() {
+ return (
+
+ Battery Level
+ Choose your preferred battery level.
+
+
+
+
+ High
+
+
+
+
+
+ Medium
+
+
+
+
+
+ Low
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/resizable-controlled.tsx b/apps/v4/examples/base/resizable-controlled.tsx
new file mode 100644
index 000000000..d6e00a3b7
--- /dev/null
+++ b/apps/v4/examples/base/resizable-controlled.tsx
@@ -0,0 +1,34 @@
+"use client"
+
+import * as React from "react"
+import {
+ ResizableHandle,
+ ResizablePanel,
+ ResizablePanelGroup,
+} from "@/examples/base/ui/resizable"
+
+export function ResizableControlled() {
+ const [sizes, setSizes] = React.useState([30, 70])
+
+ return (
+
{
+ setSizes(newSizes)
+ }}
+ >
+
+
+ {Math.round(sizes[0] ?? 30)}%
+
+
+
+
+
+ {Math.round(sizes[1] ?? 70)}%
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/resizable-horizontal.tsx b/apps/v4/examples/base/resizable-horizontal.tsx
new file mode 100644
index 000000000..ffd716a13
--- /dev/null
+++ b/apps/v4/examples/base/resizable-horizontal.tsx
@@ -0,0 +1,26 @@
+import {
+ ResizableHandle,
+ ResizablePanel,
+ ResizablePanelGroup,
+} from "@/examples/base/ui/resizable"
+
+export function ResizableHorizontal() {
+ return (
+
+
+
+ Sidebar
+
+
+
+
+
+ Content
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/resizable-nested.tsx b/apps/v4/examples/base/resizable-nested.tsx
new file mode 100644
index 000000000..602fa4444
--- /dev/null
+++ b/apps/v4/examples/base/resizable-nested.tsx
@@ -0,0 +1,33 @@
+import {
+ ResizableHandle,
+ ResizablePanel,
+ ResizablePanelGroup,
+} from "@/examples/base/ui/resizable"
+
+export function ResizableNested() {
+ return (
+
+
+
+ One
+
+
+
+
+
+
+
+ Two
+
+
+
+
+
+ Three
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/resizable-vertical.tsx b/apps/v4/examples/base/resizable-vertical.tsx
index d02c19c45..b77929b40 100644
--- a/apps/v4/examples/base/resizable-vertical.tsx
+++ b/apps/v4/examples/base/resizable-vertical.tsx
@@ -4,11 +4,11 @@ import {
ResizablePanelGroup,
} from "@/examples/base/ui/resizable"
-export default function ResizableDemo() {
+export function ResizableVertical() {
return (
diff --git a/apps/v4/examples/base/resizable-with-handle.tsx b/apps/v4/examples/base/resizable-with-handle.tsx
new file mode 100644
index 000000000..da92bf86e
--- /dev/null
+++ b/apps/v4/examples/base/resizable-with-handle.tsx
@@ -0,0 +1,26 @@
+import {
+ ResizableHandle,
+ ResizablePanel,
+ ResizablePanelGroup,
+} from "@/examples/base/ui/resizable"
+
+export function ResizableWithHandle() {
+ return (
+
+
+
+ Sidebar
+
+
+
+
+
+ Content
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/scroll-area-horizontal.tsx b/apps/v4/examples/base/scroll-area-horizontal.tsx
new file mode 100644
index 000000000..d7b6cf7e4
--- /dev/null
+++ b/apps/v4/examples/base/scroll-area-horizontal.tsx
@@ -0,0 +1,46 @@
+import Image from "next/image"
+import { ScrollArea, ScrollBar } from "@/examples/base/ui/scroll-area"
+
+const works = [
+ {
+ artist: "Ornella Binni",
+ art: "https://images.unsplash.com/photo-1465869185982-5a1a7522cbcb?auto=format&fit=crop&w=300&q=80",
+ },
+ {
+ artist: "Tom Byrom",
+ art: "https://images.unsplash.com/photo-1548516173-3cabfa4607e9?auto=format&fit=crop&w=300&q=80",
+ },
+ {
+ artist: "Vladimir Malyav",
+ art: "https://images.unsplash.com/photo-1494337480532-3725c85fd2ab?auto=format&fit=crop&w=300&q=80",
+ },
+] as const
+
+export function ScrollAreaHorizontal() {
+ return (
+
+
+ {works.map((artwork) => (
+
+
+
+
+
+ Photo by{" "}
+
+ {artwork.artist}
+
+
+
+ ))}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/scroll-area-vertical.tsx b/apps/v4/examples/base/scroll-area-vertical.tsx
new file mode 100644
index 000000000..c39c37817
--- /dev/null
+++ b/apps/v4/examples/base/scroll-area-vertical.tsx
@@ -0,0 +1,23 @@
+import * as React from "react"
+import { ScrollArea } from "@/examples/base/ui/scroll-area"
+import { Separator } from "@/examples/base/ui/separator"
+
+const tags = Array.from({ length: 50 }).map(
+ (_, i, a) => `v1.2.0-beta.${a.length - i}`
+)
+
+export function ScrollAreaVertical() {
+ return (
+
+
+
Tags
+ {tags.map((tag) => (
+
+ {tag}
+
+
+ ))}
+
+
+ )
+}
diff --git a/apps/v4/examples/base/select-basic.tsx b/apps/v4/examples/base/select-basic.tsx
new file mode 100644
index 000000000..8adfcce56
--- /dev/null
+++ b/apps/v4/examples/base/select-basic.tsx
@@ -0,0 +1,35 @@
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+
+export function SelectBasic() {
+ const items = [
+ { label: "Select a fruit", value: null },
+ { label: "Apple", value: "apple" },
+ { label: "Banana", value: "banana" },
+ { label: "Blueberry", value: "blueberry" },
+ { label: "Grapes", value: "grapes" },
+ { label: "Pineapple", value: "pineapple" },
+ ]
+ return (
+
+
+
+
+
+
+ {items.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/select-disabled.tsx b/apps/v4/examples/base/select-disabled.tsx
new file mode 100644
index 000000000..ad67781c4
--- /dev/null
+++ b/apps/v4/examples/base/select-disabled.tsx
@@ -0,0 +1,39 @@
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+
+export function SelectDisabled() {
+ const items = [
+ { label: "Select a fruit", value: null },
+ { label: "Apple", value: "apple" },
+ { label: "Banana", value: "banana" },
+ { label: "Blueberry", value: "blueberry" },
+ { label: "Grapes", value: "grapes", disabled: true },
+ { label: "Pineapple", value: "pineapple" },
+ ]
+ return (
+
+
+
+
+
+
+ {items.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/select-fields.tsx b/apps/v4/examples/base/select-fields.tsx
new file mode 100644
index 000000000..01d178785
--- /dev/null
+++ b/apps/v4/examples/base/select-fields.tsx
@@ -0,0 +1,147 @@
+import {
+ Field,
+ FieldDescription,
+ FieldGroup,
+ FieldLabel,
+} from "@/examples/base/ui/field"
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+
+export function SelectFields() {
+ const basicItems = [
+ { label: "Choose an option", value: null },
+ { label: "Option 1", value: "option1" },
+ { label: "Option 2", value: "option2" },
+ { label: "Option 3", value: "option3" },
+ ]
+ const countryItems = [
+ { label: "Select your country", value: null },
+ { label: "United States", value: "us" },
+ { label: "United Kingdom", value: "uk" },
+ { label: "Canada", value: "ca" },
+ ]
+ const timezoneItems = [
+ { label: "Select timezone", value: null },
+ { label: "UTC", value: "utc" },
+ { label: "Eastern Time", value: "est" },
+ { label: "Pacific Time", value: "pst" },
+ ]
+ const invalidItems = [
+ { label: "This field has an error", value: null },
+ { label: "Option 1", value: "option1" },
+ { label: "Option 2", value: "option2" },
+ { label: "Option 3", value: "option3" },
+ ]
+ const disabledItems = [
+ { label: "Cannot select", value: null },
+ { label: "Option 1", value: "option1" },
+ { label: "Option 2", value: "option2" },
+ { label: "Option 3", value: "option3" },
+ ]
+
+ return (
+
+
+ Basic Select
+
+
+
+
+
+
+ {basicItems.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+
+
+ Country
+
+
+
+
+
+
+ {countryItems.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+
+ Select the country where you currently reside.
+
+
+
+ Timezone
+
+ Choose your local timezone for accurate scheduling.
+
+
+
+
+
+
+
+ {timezoneItems.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+
+
+ Invalid Select
+
+
+
+
+
+
+ {invalidItems.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+
+ This field contains validation errors.
+
+
+
+ Disabled Field
+
+
+
+
+
+
+ {disabledItems.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+ This field is currently disabled.
+
+
+ )
+}
diff --git a/apps/v4/examples/base/select-in-dialog.tsx b/apps/v4/examples/base/select-in-dialog.tsx
new file mode 100644
index 000000000..c1d73477e
--- /dev/null
+++ b/apps/v4/examples/base/select-in-dialog.tsx
@@ -0,0 +1,59 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogHeader,
+ DialogTitle,
+ DialogTrigger,
+} from "@/examples/base/ui/dialog"
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+
+export function SelectInDialog() {
+ const items = [
+ { label: "Select a fruit", value: null },
+ { label: "Apple", value: "apple" },
+ { label: "Banana", value: "banana" },
+ { label: "Blueberry", value: "blueberry" },
+ { label: "Grapes", value: "grapes" },
+ { label: "Pineapple", value: "pineapple" },
+ ]
+ return (
+ <>
+
+ }>
+ Open Dialog
+
+
+
+ Select Example
+
+ Use the select below to choose a fruit.
+
+
+
+
+
+
+
+
+ {items.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/select-inline.tsx b/apps/v4/examples/base/select-inline.tsx
new file mode 100644
index 000000000..18e613daf
--- /dev/null
+++ b/apps/v4/examples/base/select-inline.tsx
@@ -0,0 +1,47 @@
+import { Input } from "@/examples/base/ui/input"
+import {
+ NativeSelect,
+ NativeSelectOption,
+} from "@/examples/base/ui/native-select"
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+
+export function SelectInline() {
+ const items = [
+ { label: "Filter", value: null },
+ { label: "All", value: "all" },
+ { label: "Active", value: "active" },
+ { label: "Inactive", value: "inactive" },
+ ]
+ return (
+
+
+
+
+
+
+
+
+ {items.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+
+ Sort by
+ Name
+ Date
+ Status
+
+
+ )
+}
diff --git a/apps/v4/examples/base/select-invalid.tsx b/apps/v4/examples/base/select-invalid.tsx
new file mode 100644
index 000000000..6cdf368d3
--- /dev/null
+++ b/apps/v4/examples/base/select-invalid.tsx
@@ -0,0 +1,56 @@
+import { Field, FieldError, FieldLabel } from "@/examples/base/ui/field"
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+
+export function SelectInvalid() {
+ const items = [
+ { label: "Select a fruit", value: null },
+ { label: "Apple", value: "apple" },
+ { label: "Banana", value: "banana" },
+ { label: "Blueberry", value: "blueberry" },
+ { label: "Grapes", value: "grapes" },
+ { label: "Pineapple", value: "pineapple" },
+ ]
+ return (
+
+
+
+
+
+
+
+ {items.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+
+ Favorite Fruit
+
+
+
+
+
+
+ {items.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/select-item-aligned.tsx b/apps/v4/examples/base/select-item-aligned.tsx
new file mode 100644
index 000000000..d551c00e5
--- /dev/null
+++ b/apps/v4/examples/base/select-item-aligned.tsx
@@ -0,0 +1,40 @@
+import { Item } from "@/examples/base/ui/item"
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+
+export function SelectItemAligned() {
+ const items = [
+ { label: "Select a fruit", value: null },
+ { label: "Apple", value: "apple" },
+ { label: "Banana", value: "banana" },
+ { label: "Blueberry", value: "blueberry" },
+ { label: "Grapes", value: "grapes", disabled: true },
+ { label: "Pineapple", value: "pineapple" },
+ ]
+ return (
+
+
+
+
+
+
+ {items.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/select-large-list.tsx b/apps/v4/examples/base/select-large-list.tsx
new file mode 100644
index 000000000..fa8ad12bb
--- /dev/null
+++ b/apps/v4/examples/base/select-large-list.tsx
@@ -0,0 +1,35 @@
+import { Item } from "@/examples/base/ui/item"
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+
+export function SelectLargeList() {
+ const items = [
+ { label: "Select an item", value: null },
+ ...Array.from({ length: 100 }).map((_, i) => ({
+ label: `Item ${i}`,
+ value: `item-${i}`,
+ })),
+ ]
+ return (
+
+
+
+
+
+
+ {items.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/select-multiple.tsx b/apps/v4/examples/base/select-multiple.tsx
new file mode 100644
index 000000000..2f6d1227e
--- /dev/null
+++ b/apps/v4/examples/base/select-multiple.tsx
@@ -0,0 +1,46 @@
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+
+export function SelectMultiple() {
+ const items = [
+ { label: "Apple", value: "apple" },
+ { label: "Banana", value: "banana" },
+ { label: "Blueberry", value: "blueberry" },
+ { label: "Grapes", value: "grapes" },
+ { label: "Pineapple", value: "pineapple" },
+ { label: "Strawberry", value: "strawberry" },
+ { label: "Watermelon", value: "watermelon" },
+ ]
+ return (
+
+
+
+ {(value: string[]) => {
+ if (value.length === 0) {
+ return "Select fruits"
+ }
+ if (value.length === 1) {
+ return items.find((item) => item.value === value[0])?.label
+ }
+ return `${value.length} fruits selected`
+ }}
+
+
+
+
+ {items.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/select-plan.tsx b/apps/v4/examples/base/select-plan.tsx
new file mode 100644
index 000000000..77b3421d3
--- /dev/null
+++ b/apps/v4/examples/base/select-plan.tsx
@@ -0,0 +1,66 @@
+import {
+ Item,
+ ItemContent,
+ ItemDescription,
+ ItemTitle,
+} from "@/examples/base/ui/item"
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+
+const plans = [
+ {
+ name: "Starter",
+ description: "Perfect for individuals getting started.",
+ },
+ {
+ name: "Professional",
+ description: "Ideal for growing teams and businesses.",
+ },
+ {
+ name: "Enterprise",
+ description: "Advanced features for large organizations.",
+ },
+]
+
+function SelectPlanItem({ plan }: { plan: (typeof plans)[number] }) {
+ return (
+
-
+
+ {plan.name}
+
+ {plan.description}
+
+
+
+ )
+}
+
+export function SelectPlan() {
+ return (
+
plan.name}
+ >
+
+
+ {(value: (typeof plans)[number]) => }
+
+
+
+
+ {plans.map((plan) => (
+
+
+
+ ))}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/select-sizes.tsx b/apps/v4/examples/base/select-sizes.tsx
new file mode 100644
index 000000000..37d340dfb
--- /dev/null
+++ b/apps/v4/examples/base/select-sizes.tsx
@@ -0,0 +1,49 @@
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+
+export function SelectSizes() {
+ const items = [
+ { label: "Select a fruit", value: null },
+ { label: "Apple", value: "apple" },
+ { label: "Banana", value: "banana" },
+ { label: "Blueberry", value: "blueberry" },
+ ]
+ return (
+
+
+
+
+
+
+
+ {items.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+
+
+
+
+
+
+ {items.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/select-with-button.tsx b/apps/v4/examples/base/select-with-button.tsx
new file mode 100644
index 000000000..56fb3b7e4
--- /dev/null
+++ b/apps/v4/examples/base/select-with-button.tsx
@@ -0,0 +1,58 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+
+export function SelectWithButton() {
+ const items = [
+ { label: "Select a fruit", value: null },
+ { label: "Apple", value: "apple" },
+ { label: "Banana", value: "banana" },
+ { label: "Blueberry", value: "blueberry" },
+ ]
+ return (
+
+
+
+
+
+
+
+
+ {items.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+
+ Submit
+
+
+
+
+
+
+
+
+
+ {items.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+ Submit
+
+
+ )
+}
diff --git a/apps/v4/examples/base/select-with-field.tsx b/apps/v4/examples/base/select-with-field.tsx
new file mode 100644
index 000000000..c350fac7e
--- /dev/null
+++ b/apps/v4/examples/base/select-with-field.tsx
@@ -0,0 +1,42 @@
+import { Field, FieldDescription, FieldLabel } from "@/examples/base/ui/field"
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+
+export function SelectWithField() {
+ const items = [
+ { label: "Select a fruit", value: null },
+ { label: "Apple", value: "apple" },
+ { label: "Banana", value: "banana" },
+ { label: "Blueberry", value: "blueberry" },
+ { label: "Grapes", value: "grapes" },
+ { label: "Pineapple", value: "pineapple" },
+ ]
+ return (
+
+ Favorite Fruit
+
+
+
+
+
+
+ {items.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+
+ Choose your favorite fruit from the list.
+
+
+ )
+}
diff --git a/apps/v4/examples/base/select-with-groups.tsx b/apps/v4/examples/base/select-with-groups.tsx
new file mode 100644
index 000000000..7b515c30a
--- /dev/null
+++ b/apps/v4/examples/base/select-with-groups.tsx
@@ -0,0 +1,54 @@
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectLabel,
+ SelectSeparator,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+
+export function SelectWithGroups() {
+ const fruits = [
+ { label: "Apple", value: "apple" },
+ { label: "Banana", value: "banana" },
+ { label: "Blueberry", value: "blueberry" },
+ ]
+ const vegetables = [
+ { label: "Carrot", value: "carrot" },
+ { label: "Broccoli", value: "broccoli" },
+ { label: "Spinach", value: "spinach" },
+ ]
+ const allItems = [
+ { label: "Select a fruit", value: null },
+ ...fruits,
+ ...vegetables,
+ ]
+ return (
+
+
+
+
+
+
+ Fruits
+ {fruits.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+ Vegetables
+ {vegetables.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/select-with-icons.tsx b/apps/v4/examples/base/select-with-icons.tsx
new file mode 100644
index 000000000..70d985527
--- /dev/null
+++ b/apps/v4/examples/base/select-with-icons.tsx
@@ -0,0 +1,82 @@
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+import { ChartBarIcon, ChartLineIcon, ChartPieIcon } from "lucide-react"
+
+export function SelectWithIcons() {
+ const items = [
+ {
+ label: (
+ <>
+
+ Chart Type
+ >
+ ),
+ value: null,
+ },
+ {
+ label: (
+ <>
+
+ Line
+ >
+ ),
+ value: "line",
+ },
+ {
+ label: (
+ <>
+
+ Bar
+ >
+ ),
+ value: "bar",
+ },
+ {
+ label: (
+ <>
+
+ Pie
+ >
+ ),
+ value: "pie",
+ },
+ ]
+ return (
+
+
+
+
+
+
+
+ {items.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+
+
+
+
+
+
+ {items.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/separator-horizontal.tsx b/apps/v4/examples/base/separator-horizontal.tsx
new file mode 100644
index 000000000..37c99f3b0
--- /dev/null
+++ b/apps/v4/examples/base/separator-horizontal.tsx
@@ -0,0 +1,19 @@
+import { Separator } from "@/examples/base/ui/separator"
+
+export function SeparatorHorizontal() {
+ return (
+
+
+
shadcn/ui
+
+ The Foundation for your Design System
+
+
+
+
+ A set of beautifully designed components that you can customize, extend,
+ and build on.
+
+
+ )
+}
diff --git a/apps/v4/examples/base/separator-in-list.tsx b/apps/v4/examples/base/separator-in-list.tsx
new file mode 100644
index 000000000..9a7c0ba6b
--- /dev/null
+++ b/apps/v4/examples/base/separator-in-list.tsx
@@ -0,0 +1,22 @@
+import { Separator } from "@/examples/base/ui/separator"
+
+export function SeparatorInList() {
+ return (
+
+
+ Item 1
+ Value 1
+
+
+
+ Item 2
+ Value 2
+
+
+
+ Item 3
+ Value 3
+
+
+ )
+}
diff --git a/apps/v4/examples/base/separator-vertical-menu.tsx b/apps/v4/examples/base/separator-vertical-menu.tsx
new file mode 100644
index 000000000..9651a9763
--- /dev/null
+++ b/apps/v4/examples/base/separator-vertical-menu.tsx
@@ -0,0 +1,26 @@
+import { Separator } from "@/examples/base/ui/separator"
+
+export function SeparatorVerticalMenu() {
+ return (
+
+
+ Settings
+
+ Manage preferences
+
+
+
+
+ Account
+
+ Profile & security
+
+
+
+
+ Help
+ Support & docs
+
+
+ )
+}
diff --git a/apps/v4/examples/base/separator-vertical.tsx b/apps/v4/examples/base/separator-vertical.tsx
new file mode 100644
index 000000000..a015025c8
--- /dev/null
+++ b/apps/v4/examples/base/separator-vertical.tsx
@@ -0,0 +1,13 @@
+import { Separator } from "@/examples/base/ui/separator"
+
+export function SeparatorVertical() {
+ return (
+
+
Blog
+
+
Docs
+
+
Source
+
+ )
+}
diff --git a/apps/v4/examples/base/sheet-no-close-button.tsx b/apps/v4/examples/base/sheet-no-close-button.tsx
new file mode 100644
index 000000000..f07428e4e
--- /dev/null
+++ b/apps/v4/examples/base/sheet-no-close-button.tsx
@@ -0,0 +1,30 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Sheet,
+ SheetContent,
+ SheetDescription,
+ SheetHeader,
+ SheetTitle,
+ SheetTrigger,
+} from "@/examples/base/ui/sheet"
+
+export function SheetNoCloseButton() {
+ return (
+ <>
+
+ }>
+ No Close Button
+
+
+
+ No Close Button
+
+ This sheet doesn't have a close button in the top-right
+ corner. You can only close it using the button below.
+
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/sheet-with-form.tsx b/apps/v4/examples/base/sheet-with-form.tsx
new file mode 100644
index 000000000..853572fac
--- /dev/null
+++ b/apps/v4/examples/base/sheet-with-form.tsx
@@ -0,0 +1,48 @@
+import { Button } from "@/examples/base/ui/button"
+import { Field, FieldGroup, FieldLabel } from "@/examples/base/ui/field"
+import { Input } from "@/examples/base/ui/input"
+import {
+ Sheet,
+ SheetClose,
+ SheetContent,
+ SheetDescription,
+ SheetFooter,
+ SheetHeader,
+ SheetTitle,
+ SheetTrigger,
+} from "@/examples/base/ui/sheet"
+
+export function SheetWithForm() {
+ return (
+ <>
+
+ }>Open
+
+
+ Edit profile
+
+ Make changes to your profile here. Click save when you're
+ done.
+
+
+
+
+
+ Name
+
+
+
+ Username
+
+
+
+
+
+ Save changes
+ }>Close
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/sheet-with-sides.tsx b/apps/v4/examples/base/sheet-with-sides.tsx
new file mode 100644
index 000000000..5e5b12836
--- /dev/null
+++ b/apps/v4/examples/base/sheet-with-sides.tsx
@@ -0,0 +1,64 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Sheet,
+ SheetClose,
+ SheetContent,
+ SheetDescription,
+ SheetFooter,
+ SheetHeader,
+ SheetTitle,
+ SheetTrigger,
+} from "@/examples/base/ui/sheet"
+
+const SHEET_SIDES = ["top", "right", "bottom", "left"] as const
+
+export function SheetWithSides() {
+ return (
+
+ {SHEET_SIDES.map((side) => (
+
+ }
+ >
+ {side}
+
+
+
+ Edit profile
+
+ Make changes to your profile here. Click save when you're
+ done.
+
+
+
+ {Array.from({ length: 10 }).map((_, index) => (
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed
+ do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+ Ut enim ad minim veniam, quis nostrud exercitation ullamco
+ laboris nisi ut aliquip ex ea commodo consequat. Duis aute
+ irure dolor in reprehenderit in voluptate velit esse cillum
+ dolore eu fugiat nulla pariatur. Excepteur sint occaecat
+ cupidatat non proident, sunt in culpa qui officia deserunt
+ mollit anim id est laborum.
+
+ ))}
+
+
+ Save changes
+ }>
+ Cancel
+
+
+
+
+ ))}
+
+ )
+}
diff --git a/apps/v4/examples/base/skeleton-avatar.tsx b/apps/v4/examples/base/skeleton-avatar.tsx
new file mode 100644
index 000000000..ba6441498
--- /dev/null
+++ b/apps/v4/examples/base/skeleton-avatar.tsx
@@ -0,0 +1,13 @@
+import { Skeleton } from "@/examples/base/ui/skeleton"
+
+export function SkeletonAvatar() {
+ return (
+
+ )
+}
diff --git a/apps/v4/examples/base/skeleton-card.tsx b/apps/v4/examples/base/skeleton-card.tsx
index 6f605157d..68cdbbd30 100644
--- a/apps/v4/examples/base/skeleton-card.tsx
+++ b/apps/v4/examples/base/skeleton-card.tsx
@@ -1,13 +1,16 @@
+import { Card, CardContent, CardHeader } from "@/examples/base/ui/card"
import { Skeleton } from "@/examples/base/ui/skeleton"
export function SkeletonCard() {
return (
-
+
+
+
+
+
+
+
+
+
)
}
diff --git a/apps/v4/examples/base/skeleton-form.tsx b/apps/v4/examples/base/skeleton-form.tsx
new file mode 100644
index 000000000..11c37f11d
--- /dev/null
+++ b/apps/v4/examples/base/skeleton-form.tsx
@@ -0,0 +1,17 @@
+import { Skeleton } from "@/examples/base/ui/skeleton"
+
+export function SkeletonForm() {
+ return (
+
+ )
+}
diff --git a/apps/v4/examples/base/skeleton-table.tsx b/apps/v4/examples/base/skeleton-table.tsx
new file mode 100644
index 000000000..d5b093d60
--- /dev/null
+++ b/apps/v4/examples/base/skeleton-table.tsx
@@ -0,0 +1,23 @@
+import { Skeleton } from "@/examples/base/ui/skeleton"
+
+export function SkeletonTable() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/skeleton-text.tsx b/apps/v4/examples/base/skeleton-text.tsx
new file mode 100644
index 000000000..556af4b37
--- /dev/null
+++ b/apps/v4/examples/base/skeleton-text.tsx
@@ -0,0 +1,11 @@
+import { Skeleton } from "@/examples/base/ui/skeleton"
+
+export function SkeletonText() {
+ return (
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/slider-basic.tsx b/apps/v4/examples/base/slider-basic.tsx
new file mode 100644
index 000000000..d6bef3219
--- /dev/null
+++ b/apps/v4/examples/base/slider-basic.tsx
@@ -0,0 +1,5 @@
+import { Slider } from "@/examples/base/ui/slider"
+
+export function SliderBasic() {
+ return
+}
diff --git a/apps/v4/examples/base/slider-controlled.tsx b/apps/v4/examples/base/slider-controlled.tsx
new file mode 100644
index 000000000..ea5f10acc
--- /dev/null
+++ b/apps/v4/examples/base/slider-controlled.tsx
@@ -0,0 +1,28 @@
+"use client"
+
+import * as React from "react"
+import { Label } from "@/examples/base/ui/label"
+import { Slider } from "@/examples/base/ui/slider"
+
+export function SliderControlled() {
+ const [value, setValue] = React.useState([0.3, 0.7])
+
+ return (
+
+
+ Temperature
+
+ {value.join(", ")}
+
+
+
setValue(value as number[])}
+ min={0}
+ max={1}
+ step={0.1}
+ />
+
+ )
+}
diff --git a/apps/v4/examples/base/slider-disabled.tsx b/apps/v4/examples/base/slider-disabled.tsx
new file mode 100644
index 000000000..357db50a8
--- /dev/null
+++ b/apps/v4/examples/base/slider-disabled.tsx
@@ -0,0 +1,5 @@
+import { Slider } from "@/examples/base/ui/slider"
+
+export function SliderDisabled() {
+ return
+}
diff --git a/apps/v4/examples/base/slider-fields.tsx b/apps/v4/examples/base/slider-fields.tsx
new file mode 100644
index 000000000..98e44aaf9
--- /dev/null
+++ b/apps/v4/examples/base/slider-fields.tsx
@@ -0,0 +1,119 @@
+"use client"
+
+import * as React from "react"
+import { useState } from "react"
+import {
+ Field,
+ FieldDescription,
+ FieldGroup,
+ FieldLabel,
+} from "@/examples/base/ui/field"
+import { Slider } from "@/examples/base/ui/slider"
+
+export function SliderFields() {
+ const [volume, setVolume] = useState([50])
+ const [brightness, setBrightness] = useState([75])
+ const [temperature, setTemperature] = useState([0.3, 0.7])
+ const [priceRange, setPriceRange] = useState([25, 75])
+ const [colorBalance, setColorBalance] = useState([10, 20, 70])
+
+ return (
+
+
+ Volume
+ setVolume(value as number[])}
+ max={100}
+ step={1}
+ />
+
+
+ Screen Brightness
+ setBrightness(value as number[])}
+ max={100}
+ step={5}
+ />
+
+ Current brightness: {brightness[0]}%
+
+
+
+ Video Quality
+ Higher quality uses more bandwidth.
+
+
+
+ Temperature Range
+ setTemperature(value as number[])}
+ min={0}
+ max={1}
+ step={0.1}
+ />
+
+ Range: {temperature[0].toFixed(1)} - {temperature[1].toFixed(1)}
+
+
+
+ Price Range
+ setPriceRange(value as number[])}
+ max={100}
+ step={5}
+ />
+
+ ${priceRange[0]} - ${priceRange[1]}
+
+
+
+ Color Balance
+ setColorBalance(value as number[])}
+ max={100}
+ step={10}
+ />
+
+ Red: {colorBalance[0]}%, Green: {colorBalance[1]}%, Blue:{" "}
+ {colorBalance[2]}%
+
+
+
+ Invalid Slider
+
+ This slider has validation errors.
+
+
+ Disabled Slider
+
+ This slider is currently disabled.
+
+
+ )
+}
diff --git a/apps/v4/examples/base/slider-multiple.tsx b/apps/v4/examples/base/slider-multiple.tsx
new file mode 100644
index 000000000..4d5cd1819
--- /dev/null
+++ b/apps/v4/examples/base/slider-multiple.tsx
@@ -0,0 +1,5 @@
+import { Slider } from "@/examples/base/ui/slider"
+
+export function SliderMultiple() {
+ return
+}
diff --git a/apps/v4/examples/base/slider-range.tsx b/apps/v4/examples/base/slider-range.tsx
new file mode 100644
index 000000000..332d69ca2
--- /dev/null
+++ b/apps/v4/examples/base/slider-range.tsx
@@ -0,0 +1,5 @@
+import { Slider } from "@/examples/base/ui/slider"
+
+export function SliderRange() {
+ return
+}
diff --git a/apps/v4/examples/base/slider-vertical.tsx b/apps/v4/examples/base/slider-vertical.tsx
new file mode 100644
index 000000000..6eec36e8b
--- /dev/null
+++ b/apps/v4/examples/base/slider-vertical.tsx
@@ -0,0 +1,22 @@
+import { Slider } from "@/examples/base/ui/slider"
+
+export function SliderVertical() {
+ return (
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/sonner-basic.tsx b/apps/v4/examples/base/sonner-basic.tsx
new file mode 100644
index 000000000..e225f578f
--- /dev/null
+++ b/apps/v4/examples/base/sonner-basic.tsx
@@ -0,0 +1,14 @@
+import { Button } from "@/examples/base/ui/button"
+import { toast } from "sonner"
+
+export function SonnerBasic() {
+ return (
+
toast("Event has been created")}
+ variant="outline"
+ className="w-fit"
+ >
+ Show Toast
+
+ )
+}
diff --git a/apps/v4/examples/base/sonner-with-description.tsx b/apps/v4/examples/base/sonner-with-description.tsx
new file mode 100644
index 000000000..f6e13508e
--- /dev/null
+++ b/apps/v4/examples/base/sonner-with-description.tsx
@@ -0,0 +1,18 @@
+import { Button } from "@/examples/base/ui/button"
+import { toast } from "sonner"
+
+export function SonnerWithDescription() {
+ return (
+
+ toast("Event has been created", {
+ description: "Monday, January 3rd at 6:00pm",
+ })
+ }
+ variant="outline"
+ className="w-fit"
+ >
+ Show Toast
+
+ )
+}
diff --git a/apps/v4/examples/base/spinner-basic.tsx b/apps/v4/examples/base/spinner-basic.tsx
index e4fce2620..196ca3f30 100644
--- a/apps/v4/examples/base/spinner-basic.tsx
+++ b/apps/v4/examples/base/spinner-basic.tsx
@@ -2,8 +2,9 @@ import { Spinner } from "@/examples/base/ui/spinner"
export function SpinnerBasic() {
return (
-
+
+
)
}
diff --git a/apps/v4/examples/base/spinner-in-badges.tsx b/apps/v4/examples/base/spinner-in-badges.tsx
new file mode 100644
index 000000000..d83fbac31
--- /dev/null
+++ b/apps/v4/examples/base/spinner-in-badges.tsx
@@ -0,0 +1,25 @@
+import { Badge } from "@/examples/base/ui/badge"
+import { Spinner } from "@/examples/base/ui/spinner"
+
+export function SpinnerInBadges() {
+ return (
+
+
+
+ Badge
+
+
+
+ Badge
+
+
+
+ Badge
+
+
+
+ Badge
+
+
+ )
+}
diff --git a/apps/v4/examples/base/spinner-in-buttons.tsx b/apps/v4/examples/base/spinner-in-buttons.tsx
new file mode 100644
index 000000000..d3029050f
--- /dev/null
+++ b/apps/v4/examples/base/spinner-in-buttons.tsx
@@ -0,0 +1,22 @@
+import { Button } from "@/examples/base/ui/button"
+import { Spinner } from "@/examples/base/ui/spinner"
+
+export function SpinnerInButtons() {
+ return (
+
+
+ Submit
+
+
+ Disabled
+
+
+ Outline
+
+
+
+ Loading...
+
+
+ )
+}
diff --git a/apps/v4/examples/base/spinner-in-empty.tsx b/apps/v4/examples/base/spinner-in-empty.tsx
new file mode 100644
index 000000000..95ae548e9
--- /dev/null
+++ b/apps/v4/examples/base/spinner-in-empty.tsx
@@ -0,0 +1,44 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Empty,
+ EmptyContent,
+ EmptyDescription,
+ EmptyHeader,
+ EmptyMedia,
+ EmptyTitle,
+} from "@/examples/base/ui/empty"
+import { Spinner } from "@/examples/base/ui/spinner"
+import { ArrowRightIcon } from "lucide-react"
+
+export function SpinnerInEmpty() {
+ return (
+
+
+
+
+
+ No projects yet
+
+ You haven't created any projects yet. Get started by creating
+ your first project.
+
+
+
+
+ } nativeButton={false}>
+ Create project
+
+ Import project
+
+ }
+ nativeButton={false}
+ className="text-muted-foreground"
+ >
+ Learn more
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/spinner-in-input-group.tsx b/apps/v4/examples/base/spinner-in-input-group.tsx
new file mode 100644
index 000000000..3f9c5460f
--- /dev/null
+++ b/apps/v4/examples/base/spinner-in-input-group.tsx
@@ -0,0 +1,21 @@
+import { Field, FieldLabel } from "@/examples/base/ui/field"
+import {
+ InputGroup,
+ InputGroupAddon,
+ InputGroupInput,
+} from "@/examples/base/ui/input-group"
+import { Spinner } from "@/examples/base/ui/spinner"
+
+export function SpinnerInInputGroup() {
+ return (
+
+ Input Group
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/switch-basic.tsx b/apps/v4/examples/base/switch-basic.tsx
new file mode 100644
index 000000000..25422d832
--- /dev/null
+++ b/apps/v4/examples/base/switch-basic.tsx
@@ -0,0 +1,11 @@
+import { Field, FieldLabel } from "@/examples/base/ui/field"
+import { Switch } from "@/examples/base/ui/switch"
+
+export function SwitchBasic() {
+ return (
+
+
+ Airplane Mode
+
+ )
+}
diff --git a/apps/v4/examples/base/switch-disabled.tsx b/apps/v4/examples/base/switch-disabled.tsx
new file mode 100644
index 000000000..f55124510
--- /dev/null
+++ b/apps/v4/examples/base/switch-disabled.tsx
@@ -0,0 +1,17 @@
+import { Label } from "@/examples/base/ui/label"
+import { Switch } from "@/examples/base/ui/switch"
+
+export function SwitchDisabled() {
+ return (
+
+
+
+ Disabled (Unchecked)
+
+
+
+ Disabled (Checked)
+
+
+ )
+}
diff --git a/apps/v4/examples/base/switch-fields.tsx b/apps/v4/examples/base/switch-fields.tsx
new file mode 100644
index 000000000..6239a9410
--- /dev/null
+++ b/apps/v4/examples/base/switch-fields.tsx
@@ -0,0 +1,77 @@
+import {
+ Field,
+ FieldContent,
+ FieldDescription,
+ FieldGroup,
+ FieldLabel,
+} from "@/examples/base/ui/field"
+import { Switch } from "@/examples/base/ui/switch"
+
+export function SwitchFields() {
+ return (
+
+
+
+ Airplane Mode
+
+ Turn on airplane mode to disable all connections.
+
+
+
+
+
+ Dark Mode
+
+
+
+
+
+ Marketing Emails
+
+ Receive emails about new products, features, and more.
+
+
+
+
+ Privacy Settings
+ Manage your privacy preferences.
+
+
+
+
+ Make profile visible to others
+
+
+
+
+
+
+
+ Show email on profile
+
+
+
+
+
+
+ Invalid Switch
+
+ This switch has validation errors.
+
+
+
+
+
+
+
+ Disabled Switch
+
+
+ This switch is currently disabled.
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/switch-sizes.tsx b/apps/v4/examples/base/switch-sizes.tsx
new file mode 100644
index 000000000..57c7a1187
--- /dev/null
+++ b/apps/v4/examples/base/switch-sizes.tsx
@@ -0,0 +1,17 @@
+import { Label } from "@/examples/base/ui/label"
+import { Switch } from "@/examples/base/ui/switch"
+
+export function SwitchSizes() {
+ return (
+
+
+
+ Small
+
+
+
+ Default
+
+
+ )
+}
diff --git a/apps/v4/examples/base/switch-with-description.tsx b/apps/v4/examples/base/switch-with-description.tsx
new file mode 100644
index 000000000..313557673
--- /dev/null
+++ b/apps/v4/examples/base/switch-with-description.tsx
@@ -0,0 +1,25 @@
+import {
+ Field,
+ FieldContent,
+ FieldDescription,
+ FieldLabel,
+ FieldTitle,
+} from "@/examples/base/ui/field"
+import { Switch } from "@/examples/base/ui/switch"
+
+export function SwitchWithDescription() {
+ return (
+
+
+
+ Share across devices
+
+ Focus is shared across devices, and turns off when you leave the
+ app.
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/switch-with-label.tsx b/apps/v4/examples/base/switch-with-label.tsx
new file mode 100644
index 000000000..db019bc5f
--- /dev/null
+++ b/apps/v4/examples/base/switch-with-label.tsx
@@ -0,0 +1,11 @@
+import { Label } from "@/examples/base/ui/label"
+import { Switch } from "@/examples/base/ui/switch"
+
+export function SwitchWithLabel() {
+ return (
+
+
+ Bluetooth
+
+ )
+}
diff --git a/apps/v4/examples/base/table-basic.tsx b/apps/v4/examples/base/table-basic.tsx
new file mode 100644
index 000000000..84052e178
--- /dev/null
+++ b/apps/v4/examples/base/table-basic.tsx
@@ -0,0 +1,80 @@
+import {
+ Table,
+ TableBody,
+ TableCaption,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/examples/base/ui/table"
+
+const invoices = [
+ {
+ invoice: "INV001",
+ paymentStatus: "Paid",
+ totalAmount: "$250.00",
+ paymentMethod: "Credit Card",
+ },
+ {
+ invoice: "INV002",
+ paymentStatus: "Pending",
+ totalAmount: "$150.00",
+ paymentMethod: "PayPal",
+ },
+ {
+ invoice: "INV003",
+ paymentStatus: "Unpaid",
+ totalAmount: "$350.00",
+ paymentMethod: "Bank Transfer",
+ },
+ {
+ invoice: "INV004",
+ paymentStatus: "Paid",
+ totalAmount: "$450.00",
+ paymentMethod: "Credit Card",
+ },
+ {
+ invoice: "INV005",
+ paymentStatus: "Paid",
+ totalAmount: "$550.00",
+ paymentMethod: "PayPal",
+ },
+ {
+ invoice: "INV006",
+ paymentStatus: "Pending",
+ totalAmount: "$200.00",
+ paymentMethod: "Bank Transfer",
+ },
+ {
+ invoice: "INV007",
+ paymentStatus: "Unpaid",
+ totalAmount: "$300.00",
+ paymentMethod: "Credit Card",
+ },
+]
+
+export function TableBasic() {
+ return (
+
+ A list of your recent invoices.
+
+
+ Invoice
+ Status
+ Method
+ Amount
+
+
+
+ {invoices.slice(0, 3).map((invoice) => (
+
+ {invoice.invoice}
+ {invoice.paymentStatus}
+ {invoice.paymentMethod}
+ {invoice.totalAmount}
+
+ ))}
+
+
+ )
+}
diff --git a/apps/v4/examples/base/table-simple.tsx b/apps/v4/examples/base/table-simple.tsx
new file mode 100644
index 000000000..2559e8a36
--- /dev/null
+++ b/apps/v4/examples/base/table-simple.tsx
@@ -0,0 +1,39 @@
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/examples/base/ui/table"
+
+export function TableSimple() {
+ return (
+
+
+
+ Name
+ Email
+ Role
+
+
+
+
+ Sarah Chen
+ sarah.chen@acme.com
+ Admin
+
+
+ Marc Rodriguez
+ marcus.rodriguez@acme.com
+ User
+
+
+ Emily Watson
+ emily.watson@acme.com
+ User
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/table-with-actions.tsx b/apps/v4/examples/base/table-with-actions.tsx
new file mode 100644
index 000000000..c24bfda7d
--- /dev/null
+++ b/apps/v4/examples/base/table-with-actions.tsx
@@ -0,0 +1,107 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger,
+} from "@/examples/base/ui/dropdown-menu"
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/examples/base/ui/table"
+import { MoreHorizontalIcon } from "lucide-react"
+
+export function TableWithActions() {
+ return (
+ <>
+
+
+
+ Product
+ Price
+ Actions
+
+
+
+
+ Wireless Mouse
+ $29.99
+
+
+
+ }
+ >
+
+ Open menu
+
+
+ Edit
+ Duplicate
+
+
+ Delete
+
+
+
+
+
+
+ Mechanical Keyboard
+ $129.99
+
+
+
+ }
+ >
+
+ Open menu
+
+
+ Edit
+ Duplicate
+
+
+ Delete
+
+
+
+
+
+
+ USB-C Hub
+ $49.99
+
+
+
+ }
+ >
+
+ Open menu
+
+
+ Edit
+ Duplicate
+
+
+ Delete
+
+
+
+
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/table-with-badges.tsx b/apps/v4/examples/base/table-with-badges.tsx
new file mode 100644
index 000000000..df98a12db
--- /dev/null
+++ b/apps/v4/examples/base/table-with-badges.tsx
@@ -0,0 +1,63 @@
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/examples/base/ui/table"
+
+export function TableWithBadges() {
+ return (
+
+
+
+ Task
+ Status
+ Priority
+
+
+
+
+ Design homepage
+
+
+ Completed
+
+
+
+
+ High
+
+
+
+
+ Implement API
+
+
+ In Progress
+
+
+
+
+ Medium
+
+
+
+
+ Write tests
+
+
+ Pending
+
+
+
+
+ Low
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/table-with-footer.tsx b/apps/v4/examples/base/table-with-footer.tsx
new file mode 100644
index 000000000..368e0b1d4
--- /dev/null
+++ b/apps/v4/examples/base/table-with-footer.tsx
@@ -0,0 +1,87 @@
+import {
+ Table,
+ TableBody,
+ TableCaption,
+ TableCell,
+ TableFooter,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/examples/base/ui/table"
+
+const invoices = [
+ {
+ invoice: "INV001",
+ paymentStatus: "Paid",
+ totalAmount: "$250.00",
+ paymentMethod: "Credit Card",
+ },
+ {
+ invoice: "INV002",
+ paymentStatus: "Pending",
+ totalAmount: "$150.00",
+ paymentMethod: "PayPal",
+ },
+ {
+ invoice: "INV003",
+ paymentStatus: "Unpaid",
+ totalAmount: "$350.00",
+ paymentMethod: "Bank Transfer",
+ },
+ {
+ invoice: "INV004",
+ paymentStatus: "Paid",
+ totalAmount: "$450.00",
+ paymentMethod: "Credit Card",
+ },
+ {
+ invoice: "INV005",
+ paymentStatus: "Paid",
+ totalAmount: "$550.00",
+ paymentMethod: "PayPal",
+ },
+ {
+ invoice: "INV006",
+ paymentStatus: "Pending",
+ totalAmount: "$200.00",
+ paymentMethod: "Bank Transfer",
+ },
+ {
+ invoice: "INV007",
+ paymentStatus: "Unpaid",
+ totalAmount: "$300.00",
+ paymentMethod: "Credit Card",
+ },
+]
+
+export function TableWithFooter() {
+ return (
+
+ A list of your recent invoices.
+
+
+ Invoice
+ Status
+ Method
+ Amount
+
+
+
+ {invoices.slice(0, 3).map((invoice) => (
+
+ {invoice.invoice}
+ {invoice.paymentStatus}
+ {invoice.paymentMethod}
+ {invoice.totalAmount}
+
+ ))}
+
+
+
+ Total
+ $2,500.00
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/table-with-input.tsx b/apps/v4/examples/base/table-with-input.tsx
new file mode 100644
index 000000000..01c361de2
--- /dev/null
+++ b/apps/v4/examples/base/table-with-input.tsx
@@ -0,0 +1,61 @@
+import { Input } from "@/examples/base/ui/input"
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/examples/base/ui/table"
+
+export function TableWithInput() {
+ return (
+
+ )
+}
diff --git a/apps/v4/examples/base/table-with-select.tsx b/apps/v4/examples/base/table-with-select.tsx
new file mode 100644
index 000000000..e89ecff32
--- /dev/null
+++ b/apps/v4/examples/base/table-with-select.tsx
@@ -0,0 +1,87 @@
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/examples/base/ui/table"
+
+const people = [
+ { value: "sarah", label: "Sarah Chen" },
+ { value: "marcus", label: "Marc Rodriguez" },
+ { value: "emily", label: "Emily Watson" },
+ { value: "david", label: "David Kim" },
+]
+
+const tasks = [
+ {
+ task: "Design homepage",
+ assignee: "sarah",
+ status: "In Progress",
+ },
+ {
+ task: "Implement API",
+ assignee: "marcus",
+ status: "Pending",
+ },
+ {
+ task: "Write tests",
+ assignee: "emily",
+ status: "Not Started",
+ },
+]
+
+export function TableWithSelect() {
+ return (
+
+
+
+ Task
+ Assignee
+ Status
+
+
+
+ {tasks.map((item) => (
+
+ {item.task}
+
+ person.value === item.assignee
+ )}
+ itemToStringValue={(item) => {
+ return item.value
+ }}
+ >
+
+
+
+
+
+ {people.map((person) => (
+
+ {person.label}
+
+ ))}
+
+
+
+
+ {item.status}
+
+ ))}
+
+
+ )
+}
diff --git a/apps/v4/examples/base/tabs-basic.tsx b/apps/v4/examples/base/tabs-basic.tsx
new file mode 100644
index 000000000..ccf4d9644
--- /dev/null
+++ b/apps/v4/examples/base/tabs-basic.tsx
@@ -0,0 +1,12 @@
+import { Tabs, TabsList, TabsTrigger } from "@/examples/base/ui/tabs"
+
+export function TabsBasic() {
+ return (
+
+
+ Home
+ Settings
+
+
+ )
+}
diff --git a/apps/v4/examples/base/tabs-disabled.tsx b/apps/v4/examples/base/tabs-disabled.tsx
new file mode 100644
index 000000000..eed3f4476
--- /dev/null
+++ b/apps/v4/examples/base/tabs-disabled.tsx
@@ -0,0 +1,14 @@
+import { Tabs, TabsList, TabsTrigger } from "@/examples/base/ui/tabs"
+
+export function TabsDisabled() {
+ return (
+
+
+ Home
+
+ Disabled
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/tabs-icon-only.tsx b/apps/v4/examples/base/tabs-icon-only.tsx
new file mode 100644
index 000000000..762a26a23
--- /dev/null
+++ b/apps/v4/examples/base/tabs-icon-only.tsx
@@ -0,0 +1,20 @@
+import { Tabs, TabsList, TabsTrigger } from "@/examples/base/ui/tabs"
+import { HomeIcon, SearchIcon, SettingsIcon } from "lucide-react"
+
+export function TabsIconOnly() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/tabs-line-disabled.tsx b/apps/v4/examples/base/tabs-line-disabled.tsx
new file mode 100644
index 000000000..6ee3604a7
--- /dev/null
+++ b/apps/v4/examples/base/tabs-line-disabled.tsx
@@ -0,0 +1,15 @@
+import { Tabs, TabsList, TabsTrigger } from "@/examples/base/ui/tabs"
+
+export function TabsLineDisabled() {
+ return (
+
+
+ Overview
+ Analytics
+
+ Reports
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/tabs-line-with-content.tsx b/apps/v4/examples/base/tabs-line-with-content.tsx
new file mode 100644
index 000000000..7de07fe49
--- /dev/null
+++ b/apps/v4/examples/base/tabs-line-with-content.tsx
@@ -0,0 +1,29 @@
+import {
+ Tabs,
+ TabsContent,
+ TabsList,
+ TabsTrigger,
+} from "@/examples/base/ui/tabs"
+
+export function TabsLineWithContent() {
+ return (
+
+
+ Account
+ Password
+ Notifications
+
+
+
+ Manage your account preferences and profile information.
+
+
+ Update your password to keep your account secure.
+
+
+ Configure how you receive notifications and alerts.
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/tabs-line.tsx b/apps/v4/examples/base/tabs-line.tsx
new file mode 100644
index 000000000..34326e166
--- /dev/null
+++ b/apps/v4/examples/base/tabs-line.tsx
@@ -0,0 +1,13 @@
+import { Tabs, TabsList, TabsTrigger } from "@/examples/base/ui/tabs"
+
+export function TabsLine() {
+ return (
+
+
+ Overview
+ Analytics
+ Reports
+
+
+ )
+}
diff --git a/apps/v4/examples/base/tabs-multiple.tsx b/apps/v4/examples/base/tabs-multiple.tsx
new file mode 100644
index 000000000..5a42eb39d
--- /dev/null
+++ b/apps/v4/examples/base/tabs-multiple.tsx
@@ -0,0 +1,14 @@
+import { Tabs, TabsList, TabsTrigger } from "@/examples/base/ui/tabs"
+
+export function TabsMultiple() {
+ return (
+
+
+ Overview
+ Analytics
+ Reports
+ Settings
+
+
+ )
+}
diff --git a/apps/v4/examples/base/tabs-variants-comparison.tsx b/apps/v4/examples/base/tabs-variants-comparison.tsx
new file mode 100644
index 000000000..8d81c3b26
--- /dev/null
+++ b/apps/v4/examples/base/tabs-variants-comparison.tsx
@@ -0,0 +1,20 @@
+import { Tabs, TabsList, TabsTrigger } from "@/examples/base/ui/tabs"
+
+export function TabsVariantsComparison() {
+ return (
+
+
+
+ Overview
+ Analytics
+
+
+
+
+ Overview
+ Analytics
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/tabs-vertical.tsx b/apps/v4/examples/base/tabs-vertical.tsx
new file mode 100644
index 000000000..81043f658
--- /dev/null
+++ b/apps/v4/examples/base/tabs-vertical.tsx
@@ -0,0 +1,31 @@
+import {
+ Tabs,
+ TabsContent,
+ TabsList,
+ TabsTrigger,
+} from "@/examples/base/ui/tabs"
+
+export function TabsVertical() {
+ return (
+
+
+ Account
+ Password
+ Notifications
+
+
+
+ Manage your account preferences and profile information.
+
+
+ Update your password to keep your account secure. Use a strong
+ password with a mix of letters, numbers, and symbols.
+
+
+ Configure how you receive notifications and alerts. Choose which types
+ of notifications you want to receive and how you want to receive them.
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/tabs-with-content.tsx b/apps/v4/examples/base/tabs-with-content.tsx
new file mode 100644
index 000000000..3b0706e81
--- /dev/null
+++ b/apps/v4/examples/base/tabs-with-content.tsx
@@ -0,0 +1,29 @@
+import {
+ Tabs,
+ TabsContent,
+ TabsList,
+ TabsTrigger,
+} from "@/examples/base/ui/tabs"
+
+export function TabsWithContent() {
+ return (
+
+
+ Account
+ Password
+ Notifications
+
+
+
+ Manage your account preferences and profile information.
+
+
+ Update your password to keep your account secure.
+
+
+ Configure how you receive notifications and alerts.
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/tabs-with-dropdown.tsx b/apps/v4/examples/base/tabs-with-dropdown.tsx
new file mode 100644
index 000000000..bdcd6440b
--- /dev/null
+++ b/apps/v4/examples/base/tabs-with-dropdown.tsx
@@ -0,0 +1,57 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger,
+} from "@/examples/base/ui/dropdown-menu"
+import {
+ Tabs,
+ TabsContent,
+ TabsList,
+ TabsTrigger,
+} from "@/examples/base/ui/tabs"
+import { MoreHorizontalIcon } from "lucide-react"
+
+export function TabsWithDropdown() {
+ return (
+ <>
+
+
+
+ Overview
+ Analytics
+ Reports
+
+
+ }
+ >
+
+ More options
+
+
+ Settings
+ Export
+
+ Archive
+
+
+
+
+
+
+ View your dashboard metrics and key performance indicators.
+
+
+ Detailed analytics and insights about your data.
+
+
+ Generate and view custom reports.
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/tabs-with-icons.tsx b/apps/v4/examples/base/tabs-with-icons.tsx
new file mode 100644
index 000000000..9da4b0f6f
--- /dev/null
+++ b/apps/v4/examples/base/tabs-with-icons.tsx
@@ -0,0 +1,19 @@
+import { Tabs, TabsList, TabsTrigger } from "@/examples/base/ui/tabs"
+import { AppWindowIcon, CodeIcon } from "lucide-react"
+
+export function TabsWithIcons() {
+ return (
+
+
+
+
+ Preview
+
+
+
+ Code
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/tabs-with-input-and-button.tsx b/apps/v4/examples/base/tabs-with-input-and-button.tsx
new file mode 100644
index 000000000..a49e7cc9f
--- /dev/null
+++ b/apps/v4/examples/base/tabs-with-input-and-button.tsx
@@ -0,0 +1,36 @@
+import { Button } from "@/examples/base/ui/button"
+import { Input } from "@/examples/base/ui/input"
+import {
+ Tabs,
+ TabsContent,
+ TabsList,
+ TabsTrigger,
+} from "@/examples/base/ui/tabs"
+
+export function TabsWithInputAndButton() {
+ return (
+
+
+
+ Overview
+ Analytics
+
+
+
+ Action
+
+
+
+
+ View your dashboard metrics and key performance indicators.
+
+
+ Detailed analytics and insights about your data.
+
+
+ Generate and view custom reports.
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/textarea-basic.tsx b/apps/v4/examples/base/textarea-basic.tsx
new file mode 100644
index 000000000..2be4d6b3e
--- /dev/null
+++ b/apps/v4/examples/base/textarea-basic.tsx
@@ -0,0 +1,5 @@
+import { Textarea } from "@/examples/base/ui/textarea"
+
+export function TextareaBasic() {
+ return
+}
diff --git a/apps/v4/examples/base/textarea-disabled.tsx b/apps/v4/examples/base/textarea-disabled.tsx
index 4ae0b44ed..613046c43 100644
--- a/apps/v4/examples/base/textarea-disabled.tsx
+++ b/apps/v4/examples/base/textarea-disabled.tsx
@@ -1,5 +1,15 @@
+import { Field, FieldLabel } from "@/examples/base/ui/field"
import { Textarea } from "@/examples/base/ui/textarea"
-export default function TextareaDisabled() {
- return
+export function TextareaDisabled() {
+ return (
+
+ Message
+
+
+ )
}
diff --git a/apps/v4/examples/base/textarea-fields.tsx b/apps/v4/examples/base/textarea-fields.tsx
new file mode 100644
index 000000000..931a1e2d6
--- /dev/null
+++ b/apps/v4/examples/base/textarea-fields.tsx
@@ -0,0 +1,67 @@
+import {
+ Field,
+ FieldDescription,
+ FieldGroup,
+ FieldLabel,
+} from "@/examples/base/ui/field"
+import { Textarea } from "@/examples/base/ui/textarea"
+
+export function TextareaFields() {
+ return (
+
+
+ Basic Textarea
+
+
+
+ Comments
+
+ Maximum 500 characters allowed.
+
+
+ Bio
+
+ Tell us about yourself in a few sentences.
+
+
+
+
+ Message
+
+
+ Enter your message so it is long enough to test the layout.
+
+
+
+ Invalid Textarea
+
+
+ This field contains validation errors.
+
+
+
+
+ Disabled Field
+
+
+ This field is currently disabled.
+
+
+ )
+}
diff --git a/apps/v4/examples/base/textarea-invalid.tsx b/apps/v4/examples/base/textarea-invalid.tsx
new file mode 100644
index 000000000..f4dd9f203
--- /dev/null
+++ b/apps/v4/examples/base/textarea-invalid.tsx
@@ -0,0 +1,5 @@
+import { Textarea } from "@/examples/base/ui/textarea"
+
+export function TextareaInvalid() {
+ return
+}
diff --git a/apps/v4/examples/base/textarea-with-description.tsx b/apps/v4/examples/base/textarea-with-description.tsx
new file mode 100644
index 000000000..bd534637d
--- /dev/null
+++ b/apps/v4/examples/base/textarea-with-description.tsx
@@ -0,0 +1,18 @@
+import { Field, FieldDescription, FieldLabel } from "@/examples/base/ui/field"
+import { Textarea } from "@/examples/base/ui/textarea"
+
+export function TextareaWithDescription() {
+ return (
+
+ Message
+
+
+ Type your message and press enter to send.
+
+
+ )
+}
diff --git a/apps/v4/examples/base/textarea-with-label.tsx b/apps/v4/examples/base/textarea-with-label.tsx
index a49765040..124f28ee1 100644
--- a/apps/v4/examples/base/textarea-with-label.tsx
+++ b/apps/v4/examples/base/textarea-with-label.tsx
@@ -1,11 +1,15 @@
-import { Label } from "@/examples/base/ui/label"
+import { Field, FieldLabel } from "@/examples/base/ui/field"
import { Textarea } from "@/examples/base/ui/textarea"
-export default function TextareaWithLabel() {
+export function TextareaWithLabel() {
return (
-
- Your message
-
-
+
+ Message
+
+
)
}
diff --git a/apps/v4/examples/base/toggle-basic.tsx b/apps/v4/examples/base/toggle-basic.tsx
new file mode 100644
index 000000000..6fd00737e
--- /dev/null
+++ b/apps/v4/examples/base/toggle-basic.tsx
@@ -0,0 +1,18 @@
+import { Toggle } from "@/examples/base/ui/toggle"
+import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react"
+
+export function ToggleBasic() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/toggle-disabled.tsx b/apps/v4/examples/base/toggle-disabled.tsx
index 3cba27b69..e1cbc9d92 100644
--- a/apps/v4/examples/base/toggle-disabled.tsx
+++ b/apps/v4/examples/base/toggle-disabled.tsx
@@ -1,10 +1,14 @@
import { Toggle } from "@/examples/base/ui/toggle"
-import { Underline } from "lucide-react"
export function ToggleDisabled() {
return (
-
-
-
+
+
+ Disabled
+
+
+ Disabled
+
+
)
}
diff --git a/apps/v4/examples/base/toggle-group-basic.tsx b/apps/v4/examples/base/toggle-group-basic.tsx
new file mode 100644
index 000000000..e8cb11939
--- /dev/null
+++ b/apps/v4/examples/base/toggle-group-basic.tsx
@@ -0,0 +1,18 @@
+import { ToggleGroup, ToggleGroupItem } from "@/examples/base/ui/toggle-group"
+import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react"
+
+export function ToggleGroupBasic() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/toggle-group-date-range.tsx b/apps/v4/examples/base/toggle-group-date-range.tsx
new file mode 100644
index 000000000..b74d0419b
--- /dev/null
+++ b/apps/v4/examples/base/toggle-group-date-range.tsx
@@ -0,0 +1,25 @@
+import { ToggleGroup, ToggleGroupItem } from "@/examples/base/ui/toggle-group"
+
+export function ToggleGroupDateRange() {
+ return (
+
+
+ Today
+
+
+ This Week
+
+
+ This Month
+
+
+ This Year
+
+
+ )
+}
diff --git a/apps/v4/examples/base/toggle-group-filter.tsx b/apps/v4/examples/base/toggle-group-filter.tsx
new file mode 100644
index 000000000..9dc7b34ca
--- /dev/null
+++ b/apps/v4/examples/base/toggle-group-filter.tsx
@@ -0,0 +1,20 @@
+import { ToggleGroup, ToggleGroupItem } from "@/examples/base/ui/toggle-group"
+
+export function ToggleGroupFilter() {
+ return (
+
+
+ All
+
+
+ Active
+
+
+ Completed
+
+
+ Archived
+
+
+ )
+}
diff --git a/apps/v4/examples/base/toggle-group-outline-with-icons.tsx b/apps/v4/examples/base/toggle-group-outline-with-icons.tsx
new file mode 100644
index 000000000..9ecdf2745
--- /dev/null
+++ b/apps/v4/examples/base/toggle-group-outline-with-icons.tsx
@@ -0,0 +1,18 @@
+import { ToggleGroup, ToggleGroupItem } from "@/examples/base/ui/toggle-group"
+import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react"
+
+export function ToggleGroupOutlineWithIcons() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/toggle-group-outline.tsx b/apps/v4/examples/base/toggle-group-outline.tsx
index 009c353a8..bcf64437a 100644
--- a/apps/v4/examples/base/toggle-group-outline.tsx
+++ b/apps/v4/examples/base/toggle-group-outline.tsx
@@ -1,17 +1,13 @@
import { ToggleGroup, ToggleGroupItem } from "@/examples/base/ui/toggle-group"
-import { Bold, Italic, Underline } from "lucide-react"
export function ToggleGroupOutline() {
return (
-
-
-
+
+
+ All
-
-
-
-
-
+
+ Missed
)
diff --git a/apps/v4/examples/base/toggle-group-sizes.tsx b/apps/v4/examples/base/toggle-group-sizes.tsx
new file mode 100644
index 000000000..62038c2d3
--- /dev/null
+++ b/apps/v4/examples/base/toggle-group-sizes.tsx
@@ -0,0 +1,36 @@
+import { ToggleGroup, ToggleGroupItem } from "@/examples/base/ui/toggle-group"
+
+export function ToggleGroupSizes() {
+ return (
+
+
+
+ Top
+
+
+ Bottom
+
+
+ Left
+
+
+ Right
+
+
+
+
+ Top
+
+
+ Bottom
+
+
+ Left
+
+
+ Right
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/toggle-group-sort.tsx b/apps/v4/examples/base/toggle-group-sort.tsx
new file mode 100644
index 000000000..d4fc0f2eb
--- /dev/null
+++ b/apps/v4/examples/base/toggle-group-sort.tsx
@@ -0,0 +1,21 @@
+import { ToggleGroup, ToggleGroupItem } from "@/examples/base/ui/toggle-group"
+import { ArrowDownIcon, ArrowUpIcon, TrendingUpIcon } from "lucide-react"
+
+export function ToggleGroupSort() {
+ return (
+
+
+
+ Newest
+
+
+
+ Oldest
+
+
+
+ Popular
+
+
+ )
+}
diff --git a/apps/v4/examples/base/toggle-group-spacing.tsx b/apps/v4/examples/base/toggle-group-spacing.tsx
index 8b8020d54..fd9c8437f 100644
--- a/apps/v4/examples/base/toggle-group-spacing.tsx
+++ b/apps/v4/examples/base/toggle-group-spacing.tsx
@@ -1,32 +1,19 @@
import { ToggleGroup, ToggleGroupItem } from "@/examples/base/ui/toggle-group"
-import { BookmarkIcon, HeartIcon, StarIcon } from "lucide-react"
export function ToggleGroupSpacing() {
return (
-
-
-
- Star
+
+
+ Top
-
-
- Heart
+
+ Bottom
-
-
- Bookmark
+
+ Left
+
+
+ Right
)
diff --git a/apps/v4/examples/base/toggle-group-vertical-outline-with-icons.tsx b/apps/v4/examples/base/toggle-group-vertical-outline-with-icons.tsx
new file mode 100644
index 000000000..2da47a993
--- /dev/null
+++ b/apps/v4/examples/base/toggle-group-vertical-outline-with-icons.tsx
@@ -0,0 +1,18 @@
+import { ToggleGroup, ToggleGroupItem } from "@/examples/base/ui/toggle-group"
+import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react"
+
+export function ToggleGroupVerticalOutlineWithIcons() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/toggle-group-vertical-outline.tsx b/apps/v4/examples/base/toggle-group-vertical-outline.tsx
new file mode 100644
index 000000000..c5603fcc8
--- /dev/null
+++ b/apps/v4/examples/base/toggle-group-vertical-outline.tsx
@@ -0,0 +1,25 @@
+import { ToggleGroup, ToggleGroupItem } from "@/examples/base/ui/toggle-group"
+
+export function ToggleGroupVerticalOutline() {
+ return (
+
+
+ All
+
+
+ Active
+
+
+ Completed
+
+
+ Archived
+
+
+ )
+}
diff --git a/apps/v4/examples/base/toggle-group-vertical-with-spacing.tsx b/apps/v4/examples/base/toggle-group-vertical-with-spacing.tsx
new file mode 100644
index 000000000..df421e075
--- /dev/null
+++ b/apps/v4/examples/base/toggle-group-vertical-with-spacing.tsx
@@ -0,0 +1,26 @@
+import { ToggleGroup, ToggleGroupItem } from "@/examples/base/ui/toggle-group"
+
+export function ToggleGroupVerticalWithSpacing() {
+ return (
+
+
+ Top
+
+
+ Bottom
+
+
+ Left
+
+
+ Right
+
+
+ )
+}
diff --git a/apps/v4/examples/base/toggle-group-vertical.tsx b/apps/v4/examples/base/toggle-group-vertical.tsx
new file mode 100644
index 000000000..272b9870b
--- /dev/null
+++ b/apps/v4/examples/base/toggle-group-vertical.tsx
@@ -0,0 +1,18 @@
+import { ToggleGroup, ToggleGroupItem } from "@/examples/base/ui/toggle-group"
+import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react"
+
+export function ToggleGroupVertical() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/toggle-group-with-icons.tsx b/apps/v4/examples/base/toggle-group-with-icons.tsx
new file mode 100644
index 000000000..60ed12701
--- /dev/null
+++ b/apps/v4/examples/base/toggle-group-with-icons.tsx
@@ -0,0 +1,33 @@
+import { ToggleGroup, ToggleGroupItem } from "@/examples/base/ui/toggle-group"
+import { BookmarkIcon, HeartIcon, StarIcon } from "lucide-react"
+
+export function ToggleGroupWithIcons() {
+ return (
+
+
+
+ Star
+
+
+
+ Heart
+
+
+
+ Bookmark
+
+
+ )
+}
diff --git a/apps/v4/examples/base/toggle-group-with-input-and-select.tsx b/apps/v4/examples/base/toggle-group-with-input-and-select.tsx
new file mode 100644
index 000000000..dae6ff614
--- /dev/null
+++ b/apps/v4/examples/base/toggle-group-with-input-and-select.tsx
@@ -0,0 +1,45 @@
+import { Input } from "@/examples/base/ui/input"
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/base/ui/select"
+import { ToggleGroup, ToggleGroupItem } from "@/examples/base/ui/toggle-group"
+
+export function ToggleGroupWithInputAndSelect() {
+ const items = [
+ { label: "All", value: "all" },
+ { label: "Active", value: "active" },
+ { label: "Archived", value: "archived" },
+ ]
+ return (
+
+
+
+
+
+
+
+
+ {items.map((item) => (
+
+ {item.label}
+
+ ))}
+
+
+
+
+
+ Grid
+
+
+ List
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/toggle-outline.tsx b/apps/v4/examples/base/toggle-outline.tsx
index 9a7d253ae..62b424d46 100644
--- a/apps/v4/examples/base/toggle-outline.tsx
+++ b/apps/v4/examples/base/toggle-outline.tsx
@@ -1,10 +1,17 @@
import { Toggle } from "@/examples/base/ui/toggle"
-import { Italic } from "lucide-react"
+import { BoldIcon, ItalicIcon } from "lucide-react"
export function ToggleOutline() {
return (
-
-
-
+
+
+
+ Italic
+
+
+
+ Bold
+
+
)
}
diff --git a/apps/v4/examples/base/toggle-sizes.tsx b/apps/v4/examples/base/toggle-sizes.tsx
new file mode 100644
index 000000000..b25b77b9d
--- /dev/null
+++ b/apps/v4/examples/base/toggle-sizes.tsx
@@ -0,0 +1,17 @@
+import { Toggle } from "@/examples/base/ui/toggle"
+
+export function ToggleSizes() {
+ return (
+
+
+ Small
+
+
+ Default
+
+
+ Large
+
+
+ )
+}
diff --git a/apps/v4/examples/base/toggle-with-button-icon-text.tsx b/apps/v4/examples/base/toggle-with-button-icon-text.tsx
new file mode 100644
index 000000000..44904c4e0
--- /dev/null
+++ b/apps/v4/examples/base/toggle-with-button-icon-text.tsx
@@ -0,0 +1,44 @@
+import { Button } from "@/examples/base/ui/button"
+import { Toggle } from "@/examples/base/ui/toggle"
+import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react"
+
+export function ToggleWithButtonIconText() {
+ return (
+
+
+
+
+ Button
+
+
+
+ Toggle
+
+
+
+
+
+ Button
+
+
+
+ Toggle
+
+
+
+
+
+ Button
+
+
+
+ Toggle
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/toggle-with-button-icon.tsx b/apps/v4/examples/base/toggle-with-button-icon.tsx
new file mode 100644
index 000000000..eb70b865d
--- /dev/null
+++ b/apps/v4/examples/base/toggle-with-button-icon.tsx
@@ -0,0 +1,38 @@
+import { Button } from "@/examples/base/ui/button"
+import { Toggle } from "@/examples/base/ui/toggle"
+import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react"
+
+export function ToggleWithButtonIcon() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/toggle-with-button-text.tsx b/apps/v4/examples/base/toggle-with-button-text.tsx
new file mode 100644
index 000000000..73425c263
--- /dev/null
+++ b/apps/v4/examples/base/toggle-with-button-text.tsx
@@ -0,0 +1,33 @@
+import { Button } from "@/examples/base/ui/button"
+import { Toggle } from "@/examples/base/ui/toggle"
+
+export function ToggleWithButtonText() {
+ return (
+
+
+
+ Button
+
+
+ Toggle
+
+
+
+
+ Button
+
+
+ Toggle
+
+
+
+
+ Button
+
+
+ Toggle
+
+
+
+ )
+}
diff --git a/apps/v4/examples/base/toggle-with-icon.tsx b/apps/v4/examples/base/toggle-with-icon.tsx
new file mode 100644
index 000000000..77d434f03
--- /dev/null
+++ b/apps/v4/examples/base/toggle-with-icon.tsx
@@ -0,0 +1,16 @@
+import { Toggle } from "@/examples/base/ui/toggle"
+import { BookmarkIcon } from "lucide-react"
+
+export function ToggleWithIcon() {
+ return (
+
+
+
+
+
+
+ Bookmark
+
+
+ )
+}
diff --git a/apps/v4/examples/base/tooltip-basic.tsx b/apps/v4/examples/base/tooltip-basic.tsx
new file mode 100644
index 000000000..3ebf484df
--- /dev/null
+++ b/apps/v4/examples/base/tooltip-basic.tsx
@@ -0,0 +1,21 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from "@/examples/base/ui/tooltip"
+
+export function TooltipBasic() {
+ return (
+ <>
+
+ }>
+ Show Tooltip
+
+
+ Add to library
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/tooltip-disabled.tsx b/apps/v4/examples/base/tooltip-disabled.tsx
new file mode 100644
index 000000000..58deed037
--- /dev/null
+++ b/apps/v4/examples/base/tooltip-disabled.tsx
@@ -0,0 +1,23 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from "@/examples/base/ui/tooltip"
+
+export function TooltipDisabled() {
+ return (
+ <>
+
+ }>
+
+ Disabled
+
+
+
+ This feature is currently unavailable
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/tooltip-formatted.tsx b/apps/v4/examples/base/tooltip-formatted.tsx
new file mode 100644
index 000000000..03b5394d6
--- /dev/null
+++ b/apps/v4/examples/base/tooltip-formatted.tsx
@@ -0,0 +1,24 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from "@/examples/base/ui/tooltip"
+
+export function TooltipFormatted() {
+ return (
+ <>
+
+ }>
+ Status
+
+
+
+
Active
+
Last updated 2 hours ago
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/tooltip-long-content.tsx b/apps/v4/examples/base/tooltip-long-content.tsx
new file mode 100644
index 000000000..84b0195e4
--- /dev/null
+++ b/apps/v4/examples/base/tooltip-long-content.tsx
@@ -0,0 +1,22 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from "@/examples/base/ui/tooltip"
+
+export function TooltipLongContent() {
+ return (
+ <>
+
+ }>
+ Show Tooltip
+
+
+ To learn more about how this works, check out the docs. If you have
+ any questions, please reach out to us.
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/tooltip-on-link.tsx b/apps/v4/examples/base/tooltip-on-link.tsx
new file mode 100644
index 000000000..5eacf163d
--- /dev/null
+++ b/apps/v4/examples/base/tooltip-on-link.tsx
@@ -0,0 +1,26 @@
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from "@/examples/base/ui/tooltip"
+
+export function TooltipOnLink() {
+ return (
+
+ e.preventDefault()}
+ />
+ }
+ >
+ Learn more
+
+
+ Click to read the documentation
+
+
+ )
+}
diff --git a/apps/v4/examples/base/tooltip-sides.tsx b/apps/v4/examples/base/tooltip-sides.tsx
new file mode 100644
index 000000000..edcfe6d12
--- /dev/null
+++ b/apps/v4/examples/base/tooltip-sides.tsx
@@ -0,0 +1,25 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from "@/examples/base/ui/tooltip"
+
+export function TooltipSides() {
+ return (
+
+ {(["top", "right", "bottom", "left"] as const).map((side) => (
+
+ }
+ >
+ {side}
+
+
+ Add to library
+
+
+ ))}
+
+ )
+}
diff --git a/apps/v4/examples/base/tooltip-with-icon.tsx b/apps/v4/examples/base/tooltip-with-icon.tsx
new file mode 100644
index 000000000..10d52d375
--- /dev/null
+++ b/apps/v4/examples/base/tooltip-with-icon.tsx
@@ -0,0 +1,23 @@
+import { Button } from "@/examples/base/ui/button"
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from "@/examples/base/ui/tooltip"
+import { InfoIcon } from "lucide-react"
+
+export function TooltipWithIcon() {
+ return (
+ <>
+
+ }>
+
+ Info
+
+
+ Additional information
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/base/tooltip-with-keyboard.tsx b/apps/v4/examples/base/tooltip-with-keyboard.tsx
new file mode 100644
index 000000000..8dc9868f8
--- /dev/null
+++ b/apps/v4/examples/base/tooltip-with-keyboard.tsx
@@ -0,0 +1,25 @@
+import { Button } from "@/examples/base/ui/button"
+import { Kbd } from "@/examples/base/ui/kbd"
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from "@/examples/base/ui/tooltip"
+import { SaveIcon } from "lucide-react"
+
+export function TooltipWithKeyboard() {
+ return (
+ <>
+
+ }>
+
+
+
+
+ Save Changes S
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/radix/accordion-basic.tsx b/apps/v4/examples/radix/accordion-basic.tsx
new file mode 100644
index 000000000..eb0d0fe22
--- /dev/null
+++ b/apps/v4/examples/radix/accordion-basic.tsx
@@ -0,0 +1,39 @@
+import {
+ Accordion,
+ AccordionContent,
+ AccordionItem,
+ AccordionTrigger,
+} from "@/examples/radix/ui/accordion"
+
+export function AccordionBasic() {
+ const items = [
+ {
+ value: "item-1",
+ trigger: "Is it accessible?",
+ content: "Yes. It adheres to the WAI-ARIA design pattern.",
+ },
+ {
+ value: "item-2",
+ trigger: "Is it styled?",
+ content:
+ "Yes. It comes with default styles that matches the other components' aesthetic.",
+ },
+ {
+ value: "item-3",
+ trigger: "Is it animated?",
+ content:
+ "Yes. It's animated by default, but you can disable it if you prefer.",
+ },
+ ]
+
+ return (
+
+ {items.map((item) => (
+
+ {item.trigger}
+ {item.content}
+
+ ))}
+
+ )
+}
diff --git a/apps/v4/examples/radix/accordion-in-card.tsx b/apps/v4/examples/radix/accordion-in-card.tsx
new file mode 100644
index 000000000..d8705b404
--- /dev/null
+++ b/apps/v4/examples/radix/accordion-in-card.tsx
@@ -0,0 +1,143 @@
+import {
+ Accordion,
+ AccordionContent,
+ AccordionItem,
+ AccordionTrigger,
+} from "@/examples/radix/ui/accordion"
+import { Button } from "@/examples/radix/ui/button"
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@/examples/radix/ui/card"
+import { ArrowUpRightIcon } from "lucide-react"
+
+export function AccordionInCard() {
+ const items = [
+ {
+ value: "plans",
+ trigger: "What subscription plans do you offer?",
+ content: (
+ <>
+
+ We offer three subscription tiers: Starter ($9/month), Professional
+ ($29/month), and Enterprise ($99/month). Each plan includes
+ increasing storage limits, API access, priority support, and team
+ collaboration features.
+
+
+ Annual billing is available with a 20% discount. All
+ plans include a 14-day free trial with no credit card required.
+
+
+ View plans
+
+
+ >
+ ),
+ },
+ {
+ value: "billing",
+ trigger: "How does billing work?",
+ content: (
+ <>
+
+ Billing occurs automatically at the start of each billing cycle. We
+ accept all major credit cards, PayPal, and ACH transfers for
+ enterprise customers.
+
+
+ You'll receive an invoice via email after each payment. You can
+ update your payment method or billing information anytime in your
+ account settings. Failed payments will trigger automated retry
+ attempts and email notifications.
+
+ >
+ ),
+ },
+ {
+ value: "upgrade",
+ trigger: "Can I upgrade or downgrade my plan?",
+ content: (
+ <>
+
+ Yes, you can change your plan at any time. When upgrading,
+ you'll be charged a prorated amount for the remainder of your
+ billing cycle and immediately gain access to new features.
+
+
+ When downgrading, the change takes effect at the end of your current
+ billing period, and you'll retain access to premium features
+ until then. No refunds are provided for downgrades.
+
+ >
+ ),
+ },
+ {
+ value: "cancel",
+ trigger: "How do I cancel my subscription?",
+ content: (
+ <>
+
+ You can cancel your subscription anytime from your account settings.
+ There are no cancellation fees or penalties. Your access will
+ continue until the end of your current billing period.
+
+
+ After cancellation, your data is retained for 30 days in case you
+ want to reactivate. You can export all your data before or after
+ canceling. We'd love to hear your feedback about why
+ you're leaving.
+
+ >
+ ),
+ },
+ {
+ value: "refund",
+ trigger: "What is your refund policy?",
+ content: (
+ <>
+
+ We offer a 30-day money-back guarantee for new subscriptions. If
+ you're not satisfied within the first 30 days, contact our
+ support team for a full refund.
+
+
+ After 30 days, we don't provide refunds for partial billing
+ periods, but you can cancel anytime to avoid future charges.
+ Enterprise customers have custom refund terms outlined in their
+ contracts.
+
+ >
+ ),
+ },
+ ]
+
+ return (
+
+
+ Subscription & Billing
+
+ Common questions about your account, plans, and payments
+
+
+
+
+ {items.map((item) => (
+
+ {item.trigger}
+ {item.content}
+
+ ))}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/accordion-multiple.tsx b/apps/v4/examples/radix/accordion-multiple.tsx
index b6746bf82..442350033 100644
--- a/apps/v4/examples/radix/accordion-multiple.tsx
+++ b/apps/v4/examples/radix/accordion-multiple.tsx
@@ -5,42 +5,32 @@ import {
AccordionTrigger,
} from "@/examples/radix/ui/accordion"
-export default function AccordionMultiple() {
+export function AccordionMultiple() {
+ const items = [
+ {
+ value: "item-1",
+ trigger:
+ "What are the key considerations when implementing a comprehensive enterprise-level authentication system?",
+ content:
+ "Implementing a robust enterprise authentication system requires careful consideration of multiple factors. This includes secure password hashing and storage, multi-factor authentication (MFA) implementation, session management, OAuth2 and SSO integration, regular security audits, rate limiting to prevent brute force attacks, and maintaining detailed audit logs. Additionally, you'll need to consider scalability, performance impact, and compliance with relevant data protection regulations such as GDPR or HIPAA.",
+ },
+ {
+ value: "item-2",
+ trigger:
+ "How does modern distributed system architecture handle eventual consistency and data synchronization across multiple regions?",
+ content:
+ "Modern distributed systems employ various strategies to maintain data consistency across regions. This often involves using techniques like CRDT (Conflict-Free Replicated Data Types), vector clocks, and gossip protocols. Systems might implement event sourcing patterns, utilize message queues for asynchronous updates, and employ sophisticated conflict resolution strategies. Popular solutions like Amazon's DynamoDB and Google's Spanner demonstrate different approaches to solving these challenges, balancing between consistency, availability, and partition tolerance as described in the CAP theorem.",
+ },
+ ]
+
return (
-
-
-
- What are the key considerations when implementing a comprehensive
- enterprise-level authentication system?
-
-
- Implementing a robust enterprise authentication system requires
- careful consideration of multiple factors. This includes secure
- password hashing and storage, multi-factor authentication (MFA)
- implementation, session management, OAuth2 and SSO integration,
- regular security audits, rate limiting to prevent brute force attacks,
- and maintaining detailed audit logs. Additionally, you'll need to
- consider scalability, performance impact, and compliance with relevant
- data protection regulations such as GDPR or HIPAA.
-
-
-
-
- How does modern distributed system architecture handle eventual
- consistency and data synchronization across multiple regions?
-
-
- Modern distributed systems employ various strategies to maintain data
- consistency across regions. This often involves using techniques like
- CRDT (Conflict-Free Replicated Data Types), vector clocks, and gossip
- protocols. Systems might implement event sourcing patterns, utilize
- message queues for asynchronous updates, and employ sophisticated
- conflict resolution strategies. Popular solutions like Amazon's
- DynamoDB and Google's Spanner demonstrate different approaches to
- solving these challenges, balancing between consistency, availability,
- and partition tolerance as described in the CAP theorem.
-
-
+
+ {items.map((item) => (
+
+ {item.trigger}
+ {item.content}
+
+ ))}
)
}
diff --git a/apps/v4/examples/radix/accordion-with-borders.tsx b/apps/v4/examples/radix/accordion-with-borders.tsx
new file mode 100644
index 000000000..0789dd39c
--- /dev/null
+++ b/apps/v4/examples/radix/accordion-with-borders.tsx
@@ -0,0 +1,63 @@
+import {
+ Accordion,
+ AccordionContent,
+ AccordionItem,
+ AccordionTrigger,
+} from "@/examples/radix/ui/accordion"
+
+export function AccordionWithBorders() {
+ const items = [
+ {
+ value: "billing",
+ trigger: "How does billing work?",
+ content:
+ "We offer monthly and annual subscription plans. Billing is charged at the beginning of each cycle, and you can cancel anytime. All plans include automatic backups, 24/7 support, and unlimited team members. There are no hidden fees or setup costs.",
+ },
+ {
+ value: "security",
+ trigger: "Is my data secure?",
+ content:
+ "Yes. We use end-to-end encryption, SOC 2 Type II compliance, and regular third-party security audits. All data is encrypted at rest and in transit using industry-standard protocols. We also offer optional two-factor authentication and single sign-on for enterprise customers.",
+ },
+ {
+ value: "integration",
+ trigger: "What integrations do you support?",
+ content: (
+ <>
+
+ We integrate with 500+ popular tools including Slack, Zapier,
+ Salesforce, HubSpot, and more. You can also build custom
+ integrations using our REST API and webhooks.{" "}
+
+
+ Our API documentation includes code examples in 10+ programming
+ languages.
+
+ >
+ ),
+ },
+ ]
+
+ return (
+
+ {items.map((item) => (
+
+
+ {item.trigger}
+
+
+ {item.content}
+
+
+ ))}
+
+ )
+}
diff --git a/apps/v4/examples/radix/accordion-with-disabled.tsx b/apps/v4/examples/radix/accordion-with-disabled.tsx
new file mode 100644
index 000000000..f6079ffc9
--- /dev/null
+++ b/apps/v4/examples/radix/accordion-with-disabled.tsx
@@ -0,0 +1,56 @@
+import {
+ Accordion,
+ AccordionContent,
+ AccordionItem,
+ AccordionTrigger,
+} from "@/examples/radix/ui/accordion"
+
+export function AccordionWithDisabled() {
+ const items = [
+ {
+ value: "item-1",
+ trigger: "Can I access my account history?",
+ content:
+ "Yes, you can view your complete account history including all transactions, plan changes, and support tickets in the Account History section of your dashboard.",
+ disabled: false,
+ },
+ {
+ value: "item-2",
+ trigger: "Premium feature information",
+ content:
+ "This section contains information about premium features. Upgrade your plan to access this content.",
+ disabled: true,
+ },
+ {
+ value: "item-3",
+ trigger: "How do I update my email address?",
+ content:
+ "You can update your email address in your account settings. You'll receive a verification email at your new address to confirm the change.",
+ disabled: false,
+ },
+ ]
+
+ return (
+
+ {items.map((item) => (
+
+
+ {item.trigger}
+
+
+ {item.content}
+
+
+ ))}
+
+ )
+}
diff --git a/apps/v4/examples/radix/alert-dialog-basic.tsx b/apps/v4/examples/radix/alert-dialog-basic.tsx
new file mode 100644
index 000000000..73bed568f
--- /dev/null
+++ b/apps/v4/examples/radix/alert-dialog-basic.tsx
@@ -0,0 +1,35 @@
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+ AlertDialogTrigger,
+} from "@/examples/radix/ui/alert-dialog"
+import { Button } from "@/examples/radix/ui/button"
+
+export function AlertDialogBasic() {
+ return (
+
+
+ Default
+
+
+
+ Are you absolutely sure?
+
+ This action cannot be undone. This will permanently delete your
+ account and remove your data from our servers.
+
+
+
+ Cancel
+ Continue
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/alert-dialog-destructive.tsx b/apps/v4/examples/radix/alert-dialog-destructive.tsx
new file mode 100644
index 000000000..a317ed20a
--- /dev/null
+++ b/apps/v4/examples/radix/alert-dialog-destructive.tsx
@@ -0,0 +1,40 @@
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogMedia,
+ AlertDialogTitle,
+ AlertDialogTrigger,
+} from "@/examples/radix/ui/alert-dialog"
+import { Button } from "@/examples/radix/ui/button"
+import { Trash2Icon } from "lucide-react"
+
+export function AlertDialogDestructive() {
+ return (
+
+
+ Delete Chat
+
+
+
+
+
+
+ Delete chat?
+
+ This will permanently delete this chat conversation. View{" "}
+ Settings delete any memories saved during this chat.
+
+
+
+ Cancel
+ Delete
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/alert-dialog-in-dialog.tsx b/apps/v4/examples/radix/alert-dialog-in-dialog.tsx
new file mode 100644
index 000000000..0ab94cbd0
--- /dev/null
+++ b/apps/v4/examples/radix/alert-dialog-in-dialog.tsx
@@ -0,0 +1,59 @@
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+ AlertDialogTrigger,
+} from "@/examples/radix/ui/alert-dialog"
+import { Button } from "@/examples/radix/ui/button"
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+ DialogTrigger,
+} from "@/examples/radix/ui/dialog"
+
+export function AlertDialogInDialog() {
+ return (
+
+
+ Open Dialog
+
+
+
+ Alert Dialog Example
+
+ Click the button below to open an alert dialog.
+
+
+
+
+
+ Open Alert Dialog
+
+
+
+ Are you absolutely sure?
+
+ This action cannot be undone. This will permanently delete
+ your account and remove your data from our servers.
+
+
+
+ Cancel
+ Continue
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/alert-dialog-small-with-media.tsx b/apps/v4/examples/radix/alert-dialog-small-with-media.tsx
new file mode 100644
index 000000000..894c5f340
--- /dev/null
+++ b/apps/v4/examples/radix/alert-dialog-small-with-media.tsx
@@ -0,0 +1,39 @@
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogMedia,
+ AlertDialogTitle,
+ AlertDialogTrigger,
+} from "@/examples/radix/ui/alert-dialog"
+import { Button } from "@/examples/radix/ui/button"
+import { BluetoothIcon } from "lucide-react"
+
+export function AlertDialogSmallWithMedia() {
+ return (
+
+
+ Small (Media)
+
+
+
+
+
+
+ Allow accessory to connect?
+
+ Do you want to allow the USB accessory to connect to this device?
+
+
+
+ Don't allow
+ Allow
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/alert-dialog-small.tsx b/apps/v4/examples/radix/alert-dialog-small.tsx
new file mode 100644
index 000000000..481d24e39
--- /dev/null
+++ b/apps/v4/examples/radix/alert-dialog-small.tsx
@@ -0,0 +1,34 @@
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+ AlertDialogTrigger,
+} from "@/examples/radix/ui/alert-dialog"
+import { Button } from "@/examples/radix/ui/button"
+
+export function AlertDialogSmall() {
+ return (
+
+
+ Small
+
+
+
+ Allow accessory to connect?
+
+ Do you want to allow the USB accessory to connect to this device?
+
+
+
+ Don't allow
+ Allow
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/alert-dialog-with-media.tsx b/apps/v4/examples/radix/alert-dialog-with-media.tsx
new file mode 100644
index 000000000..ad9496cf6
--- /dev/null
+++ b/apps/v4/examples/radix/alert-dialog-with-media.tsx
@@ -0,0 +1,40 @@
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogMedia,
+ AlertDialogTitle,
+ AlertDialogTrigger,
+} from "@/examples/radix/ui/alert-dialog"
+import { Button } from "@/examples/radix/ui/button"
+import { BluetoothIcon } from "lucide-react"
+
+export function AlertDialogWithMedia() {
+ return (
+
+
+ Default (Media)
+
+
+
+
+
+
+ Are you absolutely sure?
+
+ This will permanently delete your account and remove your data from
+ our servers.
+
+
+
+ Cancel
+ Continue
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/alert-example1.tsx b/apps/v4/examples/radix/alert-example1.tsx
new file mode 100644
index 000000000..d991c1ab5
--- /dev/null
+++ b/apps/v4/examples/radix/alert-example1.tsx
@@ -0,0 +1,22 @@
+import { Alert, AlertDescription, AlertTitle } from "@/examples/radix/ui/alert"
+
+export function AlertExample1() {
+ return (
+
+
+ Success! Your changes have been saved.
+
+
+ Success! Your changes have been saved.
+
+ This is an alert with title and description.
+
+
+
+
+ This one has a description only. No title. No icon.
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/alert-example2.tsx b/apps/v4/examples/radix/alert-example2.tsx
new file mode 100644
index 000000000..105b176a5
--- /dev/null
+++ b/apps/v4/examples/radix/alert-example2.tsx
@@ -0,0 +1,62 @@
+import { Alert, AlertDescription, AlertTitle } from "@/examples/radix/ui/alert"
+import { CircleAlertIcon } from "lucide-react"
+
+export function AlertExample2() {
+ return (
+
+
+
+
+ Let's try one with icon, title and a link .
+
+
+
+
+
+ This one has an icon and a description only. No title.{" "}
+ But it has a link and a second link .
+
+
+
+
+
+ Success! Your changes have been saved
+
+ This is an alert with icon, title and description.
+
+
+
+
+
+ This is a very long alert title that demonstrates how the component
+ handles extended text content and potentially wraps across multiple
+ lines
+
+
+
+
+
+ This is a very long alert description that demonstrates how the
+ component handles extended text content and potentially wraps across
+ multiple lines
+
+
+
+
+
+ This is an extremely long alert title that spans multiple lines to
+ demonstrate how the component handles very lengthy headings while
+ maintaining readability and proper text wrapping behavior
+
+
+ This is an equally long description that contains detailed information
+ about the alert. It shows how the component can accommodate extensive
+ content while preserving proper spacing, alignment, and readability
+ across different screen sizes and viewport widths. This helps ensure
+ the user experience remains consistent regardless of the content
+ length.
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/alert-example3.tsx b/apps/v4/examples/radix/alert-example3.tsx
new file mode 100644
index 000000000..c47e5fae4
--- /dev/null
+++ b/apps/v4/examples/radix/alert-example3.tsx
@@ -0,0 +1,31 @@
+import { Alert, AlertDescription, AlertTitle } from "@/examples/radix/ui/alert"
+import { CircleAlertIcon } from "lucide-react"
+
+export function AlertExample3() {
+ return (
+
+
+
+ Something went wrong!
+
+ Your session has expired. Please log in again.
+
+
+
+
+ Unable to process your payment.
+
+
+ Please verify your billing information and try
+ again.
+
+
+ Check your card details
+ Ensure sufficient funds
+ Verify billing address
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/alert-example4.tsx b/apps/v4/examples/radix/alert-example4.tsx
new file mode 100644
index 000000000..015bdc77b
--- /dev/null
+++ b/apps/v4/examples/radix/alert-example4.tsx
@@ -0,0 +1,34 @@
+import {
+ Alert,
+ AlertAction,
+ AlertDescription,
+ AlertTitle,
+} from "@/examples/radix/ui/alert"
+import { Badge } from "@/examples/radix/ui/badge"
+import { Button } from "@/examples/radix/ui/button"
+import { CircleAlertIcon } from "lucide-react"
+
+export function AlertExample4() {
+ return (
+
+
+
+ The selected emails have been marked as spam.
+
+ Undo
+
+
+
+
+ The selected emails have been marked as spam.
+
+ This is a very long alert title that demonstrates how the component
+ handles extended text content.
+
+
+ Badge
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/aspect-ratio16x9.tsx b/apps/v4/examples/radix/aspect-ratio16x9.tsx
new file mode 100644
index 000000000..7b17d4f4b
--- /dev/null
+++ b/apps/v4/examples/radix/aspect-ratio16x9.tsx
@@ -0,0 +1,15 @@
+import Image from "next/image"
+import { AspectRatio } from "@/examples/radix/ui/aspect-ratio"
+
+export function AspectRatio16x9() {
+ return (
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/aspect-ratio1x1.tsx b/apps/v4/examples/radix/aspect-ratio1x1.tsx
new file mode 100644
index 000000000..a44fc609f
--- /dev/null
+++ b/apps/v4/examples/radix/aspect-ratio1x1.tsx
@@ -0,0 +1,15 @@
+import Image from "next/image"
+import { AspectRatio } from "@/examples/radix/ui/aspect-ratio"
+
+export function AspectRatio1x1() {
+ return (
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/aspect-ratio21x9.tsx b/apps/v4/examples/radix/aspect-ratio21x9.tsx
new file mode 100644
index 000000000..6d6c868c5
--- /dev/null
+++ b/apps/v4/examples/radix/aspect-ratio21x9.tsx
@@ -0,0 +1,15 @@
+import Image from "next/image"
+import { AspectRatio } from "@/examples/radix/ui/aspect-ratio"
+
+export function AspectRatio21x9() {
+ return (
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/aspect-ratio9x16.tsx b/apps/v4/examples/radix/aspect-ratio9x16.tsx
new file mode 100644
index 000000000..9ba781dd5
--- /dev/null
+++ b/apps/v4/examples/radix/aspect-ratio9x16.tsx
@@ -0,0 +1,15 @@
+import Image from "next/image"
+import { AspectRatio } from "@/examples/radix/ui/aspect-ratio"
+
+export function AspectRatio9x16() {
+ return (
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/avatar-group-example.tsx b/apps/v4/examples/radix/avatar-group-example.tsx
new file mode 100644
index 000000000..0f176d018
--- /dev/null
+++ b/apps/v4/examples/radix/avatar-group-example.tsx
@@ -0,0 +1,73 @@
+import {
+ Avatar,
+ AvatarFallback,
+ AvatarGroup,
+ AvatarImage,
+} from "@/examples/radix/ui/avatar"
+
+export function AvatarGroupExample() {
+ return (
+ <>
+
+
+
+ CN
+
+
+
+ LR
+
+
+
+ ER
+
+
+
+
+
+ CN
+
+
+
+ LR
+
+
+
+ ER
+
+
+
+
+
+ CN
+
+
+
+ LR
+
+
+
+ ER
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/radix/avatar-group-with-count.tsx b/apps/v4/examples/radix/avatar-group-with-count.tsx
new file mode 100644
index 000000000..ad9189ebf
--- /dev/null
+++ b/apps/v4/examples/radix/avatar-group-with-count.tsx
@@ -0,0 +1,77 @@
+import {
+ Avatar,
+ AvatarFallback,
+ AvatarGroup,
+ AvatarGroupCount,
+ AvatarImage,
+} from "@/examples/radix/ui/avatar"
+
+export function AvatarGroupWithCount() {
+ return (
+ <>
+
+
+
+ CN
+
+
+
+ LR
+
+
+
+ ER
+
+ +3
+
+
+
+
+ CN
+
+
+
+ LR
+
+
+
+ ER
+
+ +3
+
+
+
+
+ CN
+
+
+
+ LR
+
+
+
+ ER
+
+ +3
+
+ >
+ )
+}
diff --git a/apps/v4/examples/radix/avatar-group-with-icon-count.tsx b/apps/v4/examples/radix/avatar-group-with-icon-count.tsx
new file mode 100644
index 000000000..06f2c63b7
--- /dev/null
+++ b/apps/v4/examples/radix/avatar-group-with-icon-count.tsx
@@ -0,0 +1,90 @@
+import {
+ Avatar,
+ AvatarFallback,
+ AvatarGroup,
+ AvatarGroupCount,
+ AvatarImage,
+} from "@/examples/radix/ui/avatar"
+import { PlusIcon } from "lucide-react"
+
+export function AvatarGroupWithIconCount() {
+ return (
+ <>
+
+
+
+ CN
+
+
+
+ LR
+
+
+
+ ER
+
+
+
+
+
+
+
+
+ CN
+
+
+
+ LR
+
+
+
+ ER
+
+
+
+
+
+
+
+
+ CN
+
+
+
+ LR
+
+
+
+ ER
+
+
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/radix/avatar-in-empty.tsx b/apps/v4/examples/radix/avatar-in-empty.tsx
new file mode 100644
index 000000000..9a0c32215
--- /dev/null
+++ b/apps/v4/examples/radix/avatar-in-empty.tsx
@@ -0,0 +1,67 @@
+import {
+ Avatar,
+ AvatarFallback,
+ AvatarGroup,
+ AvatarGroupCount,
+ AvatarImage,
+} from "@/examples/radix/ui/avatar"
+import { Button } from "@/examples/radix/ui/button"
+import {
+ Empty,
+ EmptyContent,
+ EmptyDescription,
+ EmptyHeader,
+ EmptyMedia,
+ EmptyTitle,
+} from "@/examples/radix/ui/empty"
+import { PlusIcon } from "lucide-react"
+
+export function AvatarInEmpty() {
+ return (
+
+
+
+
+
+
+ CN
+
+
+
+ LR
+
+
+
+ ER
+
+
+
+
+
+
+ No Team Members
+
+ Invite your team to collaborate on this project.
+
+
+
+
+
+ Invite Members
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/avatar-sizes.tsx b/apps/v4/examples/radix/avatar-sizes.tsx
new file mode 100644
index 000000000..462e5b913
--- /dev/null
+++ b/apps/v4/examples/radix/avatar-sizes.tsx
@@ -0,0 +1,33 @@
+import { Avatar, AvatarFallback, AvatarImage } from "@/examples/radix/ui/avatar"
+
+export function AvatarSizes() {
+ return (
+ <>
+
+
+
+ CN
+
+
+
+ CN
+
+
+
+ CN
+
+
+
+
+ CN
+
+
+ CN
+
+
+ CN
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/radix/avatar-with-badge-icon.tsx b/apps/v4/examples/radix/avatar-with-badge-icon.tsx
new file mode 100644
index 000000000..c87b28c33
--- /dev/null
+++ b/apps/v4/examples/radix/avatar-with-badge-icon.tsx
@@ -0,0 +1,66 @@
+import {
+ Avatar,
+ AvatarBadge,
+ AvatarFallback,
+ AvatarImage,
+} from "@/examples/radix/ui/avatar"
+import { CheckIcon, PlusIcon } from "lucide-react"
+
+export function AvatarWithBadgeIcon() {
+ return (
+ <>
+
+
+
+ PP
+
+
+
+
+
+
+ PP
+
+
+
+
+
+
+ PP
+
+
+
+
+
+
+
+ PP
+
+
+
+
+
+ PP
+
+
+
+
+
+ PP
+
+
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/radix/avatar-with-badge.tsx b/apps/v4/examples/radix/avatar-with-badge.tsx
new file mode 100644
index 000000000..6c50e870b
--- /dev/null
+++ b/apps/v4/examples/radix/avatar-with-badge.tsx
@@ -0,0 +1,53 @@
+import {
+ Avatar,
+ AvatarBadge,
+ AvatarFallback,
+ AvatarImage,
+} from "@/examples/radix/ui/avatar"
+
+export function AvatarWithBadge() {
+ return (
+ <>
+
+
+
+ JZ
+
+
+
+
+ JZ
+
+
+
+
+ JZ
+
+
+
+
+
+ JZ
+
+
+
+ JZ
+
+
+
+ JZ
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/radix/badge-as-link.tsx b/apps/v4/examples/radix/badge-as-link.tsx
new file mode 100644
index 000000000..63f98e02c
--- /dev/null
+++ b/apps/v4/examples/radix/badge-as-link.tsx
@@ -0,0 +1,39 @@
+import { Badge } from "@/examples/radix/ui/badge"
+import { ArrowUpRightIcon } from "lucide-react"
+
+export function BadgeAsLink() {
+ return (
+
+ )
+}
diff --git a/apps/v4/examples/radix/badge-custom-colors.tsx b/apps/v4/examples/radix/badge-custom-colors.tsx
new file mode 100644
index 000000000..f90c4b096
--- /dev/null
+++ b/apps/v4/examples/radix/badge-custom-colors.tsx
@@ -0,0 +1,35 @@
+import { Badge } from "@/examples/radix/ui/badge"
+
+export function BadgeCustomColors() {
+ return (
+
+
+ Blue
+
+
+ Green
+
+
+ Sky
+
+
+ Purple
+
+
+ Blue
+
+
+ Green
+
+
+ Sky
+
+
+ Purple
+
+
+ Red
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/badge-long-text.tsx b/apps/v4/examples/radix/badge-long-text.tsx
new file mode 100644
index 000000000..c5a1be7be
--- /dev/null
+++ b/apps/v4/examples/radix/badge-long-text.tsx
@@ -0,0 +1,11 @@
+import { Badge } from "@/examples/radix/ui/badge"
+
+export function BadgeLongText() {
+ return (
+
+
+ A badge with a lot of text to see how it wraps
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/badge-variants.tsx b/apps/v4/examples/radix/badge-variants.tsx
new file mode 100644
index 000000000..576b5c51f
--- /dev/null
+++ b/apps/v4/examples/radix/badge-variants.tsx
@@ -0,0 +1,14 @@
+import { Badge } from "@/examples/radix/ui/badge"
+
+export function BadgeVariants() {
+ return (
+
+ Default
+ Secondary
+ Destructive
+ Outline
+ Ghost
+ Link
+
+ )
+}
diff --git a/apps/v4/examples/radix/badge-with-icon-left.tsx b/apps/v4/examples/radix/badge-with-icon-left.tsx
new file mode 100644
index 000000000..e09915cb0
--- /dev/null
+++ b/apps/v4/examples/radix/badge-with-icon-left.tsx
@@ -0,0 +1,33 @@
+import { Badge } from "@/examples/radix/ui/badge"
+import { BadgeCheck } from "lucide-react"
+
+export function BadgeWithIconLeft() {
+ return (
+
+
+
+ Default
+
+
+
+ Secondary
+
+
+
+ Destructive
+
+
+
+ Outline
+
+
+
+ Ghost
+
+
+
+ Link
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/badge-with-icon-right.tsx b/apps/v4/examples/radix/badge-with-icon-right.tsx
new file mode 100644
index 000000000..318f631c6
--- /dev/null
+++ b/apps/v4/examples/radix/badge-with-icon-right.tsx
@@ -0,0 +1,33 @@
+import { Badge } from "@/examples/radix/ui/badge"
+import { ArrowRightIcon } from "lucide-react"
+
+export function BadgeWithIconRight() {
+ return (
+
+
+ Default
+
+
+
+ Secondary
+
+
+
+ Destructive
+
+
+
+ Outline
+
+
+
+ Ghost
+
+
+
+ Link
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/badge-with-spinner.tsx b/apps/v4/examples/radix/badge-with-spinner.tsx
new file mode 100644
index 000000000..c50761111
--- /dev/null
+++ b/apps/v4/examples/radix/badge-with-spinner.tsx
@@ -0,0 +1,33 @@
+import { Badge } from "@/examples/radix/ui/badge"
+import { Spinner } from "@/examples/radix/ui/spinner"
+
+export function BadgeWithSpinner() {
+ return (
+
+
+
+ Default
+
+
+
+ Secondary
+
+
+
+ Destructive
+
+
+
+ Outline
+
+
+
+ Ghost
+
+
+
+ Link
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/breadcrumb-basic.tsx b/apps/v4/examples/radix/breadcrumb-basic.tsx
new file mode 100644
index 000000000..fed5de94e
--- /dev/null
+++ b/apps/v4/examples/radix/breadcrumb-basic.tsx
@@ -0,0 +1,28 @@
+import {
+ Breadcrumb,
+ BreadcrumbItem,
+ BreadcrumbLink,
+ BreadcrumbList,
+ BreadcrumbPage,
+ BreadcrumbSeparator,
+} from "@/examples/radix/ui/breadcrumb"
+
+export function BreadcrumbBasic() {
+ return (
+
+
+
+ Home
+
+
+
+ Components
+
+
+
+ Breadcrumb
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/breadcrumb-with-dropdown.tsx b/apps/v4/examples/radix/breadcrumb-with-dropdown.tsx
new file mode 100644
index 000000000..a35007a8b
--- /dev/null
+++ b/apps/v4/examples/radix/breadcrumb-with-dropdown.tsx
@@ -0,0 +1,52 @@
+import {
+ Breadcrumb,
+ BreadcrumbEllipsis,
+ BreadcrumbItem,
+ BreadcrumbLink,
+ BreadcrumbList,
+ BreadcrumbPage,
+ BreadcrumbSeparator,
+} from "@/examples/radix/ui/breadcrumb"
+import { Button } from "@/examples/radix/ui/button"
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/examples/radix/ui/dropdown-menu"
+
+export function BreadcrumbWithDropdown() {
+ return (
+
+
+
+ Home
+
+
+
+
+
+
+
+ Toggle menu
+
+
+
+ Documentation
+ Themes
+ GitHub
+
+
+
+
+
+ Components
+
+
+
+ Breadcrumb
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/breadcrumb-with-link.tsx b/apps/v4/examples/radix/breadcrumb-with-link.tsx
new file mode 100644
index 000000000..c8b99dc32
--- /dev/null
+++ b/apps/v4/examples/radix/breadcrumb-with-link.tsx
@@ -0,0 +1,38 @@
+import Link from "next/link"
+import {
+ Breadcrumb,
+ BreadcrumbEllipsis,
+ BreadcrumbItem,
+ BreadcrumbLink,
+ BreadcrumbList,
+ BreadcrumbPage,
+ BreadcrumbSeparator,
+} from "@/examples/radix/ui/breadcrumb"
+
+export function BreadcrumbWithLink() {
+ return (
+
+
+
+
+ Home
+
+
+
+
+
+
+
+
+
+ Components
+
+
+
+
+ Breadcrumb
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/button-examples.tsx b/apps/v4/examples/radix/button-examples.tsx
new file mode 100644
index 000000000..087397d82
--- /dev/null
+++ b/apps/v4/examples/radix/button-examples.tsx
@@ -0,0 +1,21 @@
+import { Button } from "@/examples/radix/ui/button"
+import { ArrowRightIcon } from "lucide-react"
+
+export function ButtonExamples() {
+ return (
+
+ )
+}
diff --git a/apps/v4/examples/radix/button-group-basic.tsx b/apps/v4/examples/radix/button-group-basic.tsx
new file mode 100644
index 000000000..d4d9d06f0
--- /dev/null
+++ b/apps/v4/examples/radix/button-group-basic.tsx
@@ -0,0 +1,13 @@
+import { Button } from "@/examples/radix/ui/button"
+import { ButtonGroup } from "@/examples/radix/ui/button-group"
+
+export function ButtonGroupBasic() {
+ return (
+
+
+ Button
+ Another Button
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/button-group-navigation.tsx b/apps/v4/examples/radix/button-group-navigation.tsx
new file mode 100644
index 000000000..142d1705d
--- /dev/null
+++ b/apps/v4/examples/radix/button-group-navigation.tsx
@@ -0,0 +1,23 @@
+import { Button } from "@/examples/radix/ui/button"
+import { ButtonGroup } from "@/examples/radix/ui/button-group"
+import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react"
+
+export function ButtonGroupNavigation() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/button-group-nested.tsx b/apps/v4/examples/radix/button-group-nested.tsx
index a86c3d978..f777c4a6f 100644
--- a/apps/v4/examples/radix/button-group-nested.tsx
+++ b/apps/v4/examples/radix/button-group-nested.tsx
@@ -1,36 +1,38 @@
-"use client"
-
import { Button } from "@/examples/radix/ui/button"
import { ButtonGroup } from "@/examples/radix/ui/button-group"
-import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react"
+import { Input } from "@/examples/radix/ui/input"
+import {
+ InputGroup,
+ InputGroupAddon,
+ InputGroupInput,
+} from "@/examples/radix/ui/input-group"
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from "@/examples/radix/ui/tooltip"
+import { AudioLinesIcon, PlusIcon } from "lucide-react"
-export default function ButtonGroupNested() {
+export function ButtonGroupNested() {
return (
-
- 1
-
-
- 2
-
-
- 3
-
-
- 4
-
-
- 5
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ Voice Mode
+
+
)
diff --git a/apps/v4/examples/radix/button-group-pagination-split.tsx b/apps/v4/examples/radix/button-group-pagination-split.tsx
new file mode 100644
index 000000000..cfacd0d83
--- /dev/null
+++ b/apps/v4/examples/radix/button-group-pagination-split.tsx
@@ -0,0 +1,35 @@
+import { Button } from "@/examples/radix/ui/button"
+import { ButtonGroup } from "@/examples/radix/ui/button-group"
+import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react"
+
+export function ButtonGroupPaginationSplit() {
+ return (
+
+
+
+ 1
+
+
+ 2
+
+
+ 3
+
+
+ 4
+
+
+ 5
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/button-group-pagination.tsx b/apps/v4/examples/radix/button-group-pagination.tsx
new file mode 100644
index 000000000..b8c613e05
--- /dev/null
+++ b/apps/v4/examples/radix/button-group-pagination.tsx
@@ -0,0 +1,33 @@
+import { Button } from "@/examples/radix/ui/button"
+import { ButtonGroup } from "@/examples/radix/ui/button-group"
+import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react"
+
+export function ButtonGroupPagination() {
+ return (
+
+
+
+ Previous
+
+
+ 1
+
+
+ 2
+
+
+ 3
+
+
+ 4
+
+
+ 5
+
+
+ Next
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/button-group-text-alignment.tsx b/apps/v4/examples/radix/button-group-text-alignment.tsx
new file mode 100644
index 000000000..3cb836196
--- /dev/null
+++ b/apps/v4/examples/radix/button-group-text-alignment.tsx
@@ -0,0 +1,26 @@
+import { Button } from "@/examples/radix/ui/button"
+import { ButtonGroup } from "@/examples/radix/ui/button-group"
+import { Field } from "@/examples/radix/ui/field"
+import { Label } from "@/examples/radix/ui/label"
+
+export function ButtonGroupTextAlignment() {
+ return (
+
+ Text Alignment
+
+
+ Left
+
+
+ Center
+
+
+ Right
+
+
+ Justify
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/button-group-vertical-nested.tsx b/apps/v4/examples/radix/button-group-vertical-nested.tsx
new file mode 100644
index 000000000..bb918bd80
--- /dev/null
+++ b/apps/v4/examples/radix/button-group-vertical-nested.tsx
@@ -0,0 +1,45 @@
+import { Button } from "@/examples/radix/ui/button"
+import { ButtonGroup } from "@/examples/radix/ui/button-group"
+import {
+ CopyIcon,
+ FlipHorizontalIcon,
+ FlipVerticalIcon,
+ RotateCwIcon,
+ SearchIcon,
+ ShareIcon,
+ TrashIcon,
+} from "lucide-react"
+
+export function ButtonGroupVerticalNested() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/button-group-vertical.tsx b/apps/v4/examples/radix/button-group-vertical.tsx
new file mode 100644
index 000000000..de2da4908
--- /dev/null
+++ b/apps/v4/examples/radix/button-group-vertical.tsx
@@ -0,0 +1,22 @@
+import { Button } from "@/examples/radix/ui/button"
+import { ButtonGroup } from "@/examples/radix/ui/button-group"
+import { MinusIcon, PlusIcon } from "lucide-react"
+
+export function ButtonGroupVertical() {
+ return (
+
+ )
+}
diff --git a/apps/v4/examples/radix/button-group-with-dropdown.tsx b/apps/v4/examples/radix/button-group-with-dropdown.tsx
new file mode 100644
index 000000000..42c55bd49
--- /dev/null
+++ b/apps/v4/examples/radix/button-group-with-dropdown.tsx
@@ -0,0 +1,86 @@
+import { Button } from "@/examples/radix/ui/button"
+import { ButtonGroup } from "@/examples/radix/ui/button-group"
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuGroup,
+ DropdownMenuItem,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger,
+} from "@/examples/radix/ui/dropdown-menu"
+import {
+ AlertTriangleIcon,
+ CheckIcon,
+ ChevronDownIcon,
+ CopyIcon,
+ ShareIcon,
+ TrashIcon,
+ UserRoundXIcon,
+ VolumeOffIcon,
+} from "lucide-react"
+
+export function ButtonGroupWithDropdown() {
+ return (
+
+
+ Update
+
+
+
+
+
+
+
+ Disable
+ Uninstall
+
+
+
+
+ Follow
+
+
+
+
+
+
+
+
+
+
+ Mute Conversation
+
+
+
+ Mark as Read
+
+
+
+ Report Conversation
+
+
+
+ Block User
+
+
+
+ Share Conversation
+
+
+
+ Copy Conversation
+
+
+
+
+
+
+ Delete Conversation
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/button-group-with-fields.tsx b/apps/v4/examples/radix/button-group-with-fields.tsx
new file mode 100644
index 000000000..2e96618b8
--- /dev/null
+++ b/apps/v4/examples/radix/button-group-with-fields.tsx
@@ -0,0 +1,41 @@
+import { Button } from "@/examples/radix/ui/button"
+import { ButtonGroup } from "@/examples/radix/ui/button-group"
+import { Field, FieldGroup } from "@/examples/radix/ui/field"
+import { Input } from "@/examples/radix/ui/input"
+import {
+ InputGroup,
+ InputGroupAddon,
+ InputGroupInput,
+} from "@/examples/radix/ui/input-group"
+import { Label } from "@/examples/radix/ui/label"
+import { MinusIcon, PlusIcon } from "lucide-react"
+
+export function ButtonGroupWithFields() {
+ return (
+
+
+ Width
+
+
+
+
+ W
+
+
+ px
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/button-group-with-icons.tsx b/apps/v4/examples/radix/button-group-with-icons.tsx
new file mode 100644
index 000000000..45a4f0cd1
--- /dev/null
+++ b/apps/v4/examples/radix/button-group-with-icons.tsx
@@ -0,0 +1,25 @@
+import { Button } from "@/examples/radix/ui/button"
+import { ButtonGroup } from "@/examples/radix/ui/button-group"
+import {
+ FlipHorizontalIcon,
+ FlipVerticalIcon,
+ RotateCwIcon,
+} from "lucide-react"
+
+export function ButtonGroupWithIcons() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/button-group-with-input-group.tsx b/apps/v4/examples/radix/button-group-with-input-group.tsx
new file mode 100644
index 000000000..5f4634e38
--- /dev/null
+++ b/apps/v4/examples/radix/button-group-with-input-group.tsx
@@ -0,0 +1,20 @@
+import { Input } from "@/examples/radix/ui/input"
+import {
+ InputGroup,
+ InputGroupAddon,
+ InputGroupInput,
+} from "@/examples/radix/ui/input-group"
+import { SearchIcon } from "lucide-react"
+
+export function ButtonGroupWithInputGroup() {
+ return (
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/button-group-with-input.tsx b/apps/v4/examples/radix/button-group-with-input.tsx
new file mode 100644
index 000000000..aeeb30fc1
--- /dev/null
+++ b/apps/v4/examples/radix/button-group-with-input.tsx
@@ -0,0 +1,18 @@
+import { Button } from "@/examples/radix/ui/button"
+import { ButtonGroup } from "@/examples/radix/ui/button-group"
+import { Input } from "@/examples/radix/ui/input"
+
+export function ButtonGroupWithInput() {
+ return (
+
+
+ Button
+
+
+
+
+ Button
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/button-group-with-like.tsx b/apps/v4/examples/radix/button-group-with-like.tsx
new file mode 100644
index 000000000..1513ea8ca
--- /dev/null
+++ b/apps/v4/examples/radix/button-group-with-like.tsx
@@ -0,0 +1,16 @@
+import { Button } from "@/examples/radix/ui/button"
+import { ButtonGroup } from "@/examples/radix/ui/button-group"
+import { HeartIcon } from "lucide-react"
+
+export function ButtonGroupWithLike() {
+ return (
+
+
+ Like
+
+
+ 1.2K
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/button-group-with-select-and-input.tsx b/apps/v4/examples/radix/button-group-with-select-and-input.tsx
new file mode 100644
index 000000000..eef70c432
--- /dev/null
+++ b/apps/v4/examples/radix/button-group-with-select-and-input.tsx
@@ -0,0 +1,28 @@
+import { Button } from "@/examples/radix/ui/button"
+import { ButtonGroup } from "@/examples/radix/ui/button-group"
+import { Input } from "@/examples/radix/ui/input"
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/radix/ui/select"
+
+export function ButtonGroupWithSelectAndInput() {
+ return (
+
+
+
+
+
+
+ Hours
+ Days
+ Weeks
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/button-group-with-select.tsx b/apps/v4/examples/radix/button-group-with-select.tsx
new file mode 100644
index 000000000..9be296056
--- /dev/null
+++ b/apps/v4/examples/radix/button-group-with-select.tsx
@@ -0,0 +1,43 @@
+"use client"
+
+import * as React from "react"
+import { useState } from "react"
+import { Button } from "@/examples/radix/ui/button"
+import { ButtonGroup } from "@/examples/radix/ui/button-group"
+import { Field } from "@/examples/radix/ui/field"
+import { Input } from "@/examples/radix/ui/input"
+import { Label } from "@/examples/radix/ui/label"
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/radix/ui/select"
+import { ArrowRightIcon } from "lucide-react"
+
+export function ButtonGroupWithSelect() {
+ const [currency, setCurrency] = useState("$")
+
+ return (
+
+ Amount
+
+
+
+
+
+
+ $
+ €
+ £
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/button-group-with-text.tsx b/apps/v4/examples/radix/button-group-with-text.tsx
new file mode 100644
index 000000000..e5e4a65a8
--- /dev/null
+++ b/apps/v4/examples/radix/button-group-with-text.tsx
@@ -0,0 +1,21 @@
+import { Button } from "@/examples/radix/ui/button"
+import { ButtonGroup, ButtonGroupText } from "@/examples/radix/ui/button-group"
+import { Input } from "@/examples/radix/ui/input"
+import { Label } from "@/examples/radix/ui/label"
+
+export function ButtonGroupWithText() {
+ return (
+
+
+ Text
+ Another Button
+
+
+
+ GPU Size
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/button-icon-left.tsx b/apps/v4/examples/radix/button-icon-left.tsx
new file mode 100644
index 000000000..51ac66306
--- /dev/null
+++ b/apps/v4/examples/radix/button-icon-left.tsx
@@ -0,0 +1,89 @@
+import { Button } from "@/examples/radix/ui/button"
+import { ArrowLeftCircleIcon } from "lucide-react"
+
+export function ButtonIconLeft() {
+ return (
+ <>
+
+
+ Default
+
+
+ Secondary
+
+
+ Outline
+
+
+ Ghost
+
+
+ Destructive
+
+
+ Link
+
+
+
+
+ Default
+
+
+ Secondary
+
+
+ Outline
+
+
+ Ghost
+
+
+ Destructive
+
+
+ Link
+
+
+
+
+ Default
+
+
+ Secondary
+
+
+ Outline
+
+
+ Ghost
+
+
+ Destructive
+
+
+ Link
+
+
+
+
+ Default
+
+
+ Secondary
+
+
+ Outline
+
+
+ Ghost
+
+
+ Destructive
+
+
+ Link
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/radix/button-icon-only.tsx b/apps/v4/examples/radix/button-icon-only.tsx
new file mode 100644
index 000000000..c53e15df9
--- /dev/null
+++ b/apps/v4/examples/radix/button-icon-only.tsx
@@ -0,0 +1,89 @@
+import { Button } from "@/examples/radix/ui/button"
+import { ArrowRightIcon } from "lucide-react"
+
+export function ButtonIconOnly() {
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/radix/button-icon-right.tsx b/apps/v4/examples/radix/button-icon-right.tsx
new file mode 100644
index 000000000..605d1b997
--- /dev/null
+++ b/apps/v4/examples/radix/button-icon-right.tsx
@@ -0,0 +1,90 @@
+import { Button } from "@/examples/radix/ui/button"
+import { ArrowRightIcon } from "lucide-react"
+
+export function ButtonIconRight() {
+ return (
+ <>
+
+
+ Default
+
+
+ Secondary
+
+
+ Outline
+
+
+ Ghost
+
+
+ Destructive
+
+
+ Link
+
+
+
+
+ Default
+
+
+
+ Secondary
+
+
+ Outline
+
+
+ Ghost
+
+
+ Destructive
+
+
+ Link
+
+
+
+
+ Default
+
+
+ Secondary
+
+
+ Outline
+
+
+ Ghost
+
+
+ Destructive
+
+
+ Link
+
+
+
+
+ Default
+
+
+ Secondary
+
+
+ Outline
+
+
+ Ghost
+
+
+ Destructive
+
+
+ Link
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/radix/button-invalid-states.tsx b/apps/v4/examples/radix/button-invalid-states.tsx
new file mode 100644
index 000000000..20cfd29bb
--- /dev/null
+++ b/apps/v4/examples/radix/button-invalid-states.tsx
@@ -0,0 +1,86 @@
+import { Button } from "@/examples/radix/ui/button"
+
+export function ButtonInvalidStates() {
+ return (
+ <>
+
+
+ Default
+
+
+ Secondary
+
+
+ Outline
+
+
+ Ghost
+
+
+ Destructive
+
+
+ Link
+
+
+
+
+ Default
+
+
+ Secondary
+
+
+ Outline
+
+
+ Ghost
+
+
+ Destructive
+
+
+ Link
+
+
+
+ Default
+
+ Secondary
+
+
+ Outline
+
+
+ Ghost
+
+
+ Destructive
+
+
+ Link
+
+
+
+
+ Default
+
+
+ Secondary
+
+
+ Outline
+
+
+ Ghost
+
+
+ Destructive
+
+
+ Link
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/radix/button-variants-and-sizes.tsx b/apps/v4/examples/radix/button-variants-and-sizes.tsx
new file mode 100644
index 000000000..20d65acd2
--- /dev/null
+++ b/apps/v4/examples/radix/button-variants-and-sizes.tsx
@@ -0,0 +1,70 @@
+import { Button } from "@/examples/radix/ui/button"
+
+export function ButtonVariantsAndSizes() {
+ return (
+ <>
+
+ Default
+
+ Secondary
+
+
+ Outline
+
+
+ Ghost
+
+
+ Destructive
+
+
+ Link
+
+
+
+ Default
+
+ Secondary
+
+
+ Outline
+
+
+ Ghost
+
+
+ Destructive
+
+
+ Link
+
+
+
+ Default
+ Secondary
+ Outline
+ Ghost
+ Destructive
+ Link
+
+
+ Default
+
+ Secondary
+
+
+ Outline
+
+
+ Ghost
+
+
+ Destructive
+
+
+ Link
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/radix/calendar-booked-dates.tsx b/apps/v4/examples/radix/calendar-booked-dates.tsx
new file mode 100644
index 000000000..9b2d99640
--- /dev/null
+++ b/apps/v4/examples/radix/calendar-booked-dates.tsx
@@ -0,0 +1,36 @@
+"use client"
+
+import * as React from "react"
+import { Calendar } from "@/examples/radix/ui/calendar"
+import { Card, CardContent } from "@/examples/radix/ui/card"
+import { es } from "react-day-picker/locale"
+
+export function CalendarBookedDates() {
+ const [date, setDate] = React.useState(
+ new Date(new Date().getFullYear(), 1, 3)
+ )
+ const bookedDates = Array.from(
+ { length: 15 },
+ (_, i) => new Date(new Date().getFullYear(), 1, 12 + i)
+ )
+
+ return (
+
+
+ button]:line-through opacity-100",
+ }}
+ />
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/calendar-custom-days.tsx b/apps/v4/examples/radix/calendar-custom-days.tsx
new file mode 100644
index 000000000..dc9c4cc8b
--- /dev/null
+++ b/apps/v4/examples/radix/calendar-custom-days.tsx
@@ -0,0 +1,50 @@
+"use client"
+
+import * as React from "react"
+import { Calendar, CalendarDayButton } from "@/examples/radix/ui/calendar"
+import { Card, CardContent } from "@/examples/radix/ui/card"
+import { addDays } from "date-fns"
+import { type DateRange } from "react-day-picker"
+
+export function CalendarCustomDays() {
+ const [range, setRange] = React.useState({
+ from: new Date(new Date().getFullYear(), 11, 8),
+ to: addDays(new Date(new Date().getFullYear(), 11, 8), 10),
+ })
+
+ return (
+
+
+ {
+ return date.toLocaleString("default", { month: "long" })
+ },
+ }}
+ components={{
+ DayButton: ({ children, modifiers, day, ...props }) => {
+ const isWeekend =
+ day.date.getDay() === 0 || day.date.getDay() === 6
+
+ return (
+
+ {children}
+ {!modifiers.outside && (
+ {isWeekend ? "$120" : "$100"}
+ )}
+
+ )
+ },
+ }}
+ />
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/calendar-multiple.tsx b/apps/v4/examples/radix/calendar-multiple.tsx
new file mode 100644
index 000000000..e2a9773b4
--- /dev/null
+++ b/apps/v4/examples/radix/calendar-multiple.tsx
@@ -0,0 +1,12 @@
+import { Calendar } from "@/examples/radix/ui/calendar"
+import { Card, CardContent } from "@/examples/radix/ui/card"
+
+export function CalendarMultiple() {
+ return (
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/calendar-range-multiple-months.tsx b/apps/v4/examples/radix/calendar-range-multiple-months.tsx
new file mode 100644
index 000000000..50f960fca
--- /dev/null
+++ b/apps/v4/examples/radix/calendar-range-multiple-months.tsx
@@ -0,0 +1,31 @@
+"use client"
+
+import * as React from "react"
+import { Calendar } from "@/examples/radix/ui/calendar"
+import { Card, CardContent } from "@/examples/radix/ui/card"
+import { addDays } from "date-fns"
+import { type DateRange } from "react-day-picker"
+import { es } from "react-day-picker/locale"
+
+export function CalendarRangeMultipleMonths() {
+ const [range, setRange] = React.useState({
+ from: new Date(new Date().getFullYear(), 3, 12),
+ to: addDays(new Date(new Date().getFullYear(), 3, 12), 60),
+ })
+
+ return (
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/calendar-range.tsx b/apps/v4/examples/radix/calendar-range.tsx
new file mode 100644
index 000000000..cb697fcb6
--- /dev/null
+++ b/apps/v4/examples/radix/calendar-range.tsx
@@ -0,0 +1,31 @@
+"use client"
+
+import * as React from "react"
+import { Calendar } from "@/examples/radix/ui/calendar"
+import { Card, CardContent } from "@/examples/radix/ui/card"
+import { addDays } from "date-fns"
+import { type DateRange } from "react-day-picker"
+
+export function CalendarRange() {
+ const [dateRange, setDateRange] = React.useState({
+ from: new Date(new Date().getFullYear(), 0, 12),
+ to: addDays(new Date(new Date().getFullYear(), 0, 12), 30),
+ })
+
+ return (
+
+
+
+ date > new Date() || date < new Date("1900-01-01")
+ }
+ />
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/calendar-single.tsx b/apps/v4/examples/radix/calendar-single.tsx
new file mode 100644
index 000000000..4b1139ce8
--- /dev/null
+++ b/apps/v4/examples/radix/calendar-single.tsx
@@ -0,0 +1,23 @@
+"use client"
+
+import * as React from "react"
+import { Calendar } from "@/examples/radix/ui/calendar"
+import { Card, CardContent } from "@/examples/radix/ui/card"
+
+export function CalendarSingle() {
+ const [date, setDate] = React.useState(
+ new Date(new Date().getFullYear(), new Date().getMonth(), 12)
+ )
+ return (
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/calendar-week-numbers.tsx b/apps/v4/examples/radix/calendar-week-numbers.tsx
new file mode 100644
index 000000000..569cff5dd
--- /dev/null
+++ b/apps/v4/examples/radix/calendar-week-numbers.tsx
@@ -0,0 +1,25 @@
+"use client"
+
+import * as React from "react"
+import { Calendar } from "@/examples/radix/ui/calendar"
+import { Card, CardContent } from "@/examples/radix/ui/card"
+
+export function CalendarWeekNumbers() {
+ const [date, setDate] = React.useState(
+ new Date(new Date().getFullYear(), 1, 3)
+ )
+
+ return (
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/calendar-with-presets.tsx b/apps/v4/examples/radix/calendar-with-presets.tsx
new file mode 100644
index 000000000..30f8ca9ed
--- /dev/null
+++ b/apps/v4/examples/radix/calendar-with-presets.tsx
@@ -0,0 +1,57 @@
+"use client"
+
+import * as React from "react"
+import { Button } from "@/examples/radix/ui/button"
+import { Calendar } from "@/examples/radix/ui/calendar"
+import { Card, CardContent, CardFooter } from "@/examples/radix/ui/card"
+import { addDays } from "date-fns"
+
+export function CalendarWithPresets() {
+ const [date, setDate] = React.useState(
+ new Date(new Date().getFullYear(), 1, 12)
+ )
+ const [currentMonth, setCurrentMonth] = React.useState(
+ new Date(new Date().getFullYear(), new Date().getMonth(), 1)
+ )
+
+ return (
+
+
+
+
+
+ {[
+ { label: "Today", value: 0 },
+ { label: "Tomorrow", value: 1 },
+ { label: "In 3 days", value: 3 },
+ { label: "In a week", value: 7 },
+ { label: "In 2 weeks", value: 14 },
+ ].map((preset) => (
+ {
+ const newDate = addDays(new Date(), preset.value)
+ setDate(newDate)
+ setCurrentMonth(
+ new Date(newDate.getFullYear(), newDate.getMonth(), 1)
+ )
+ }}
+ >
+ {preset.label}
+
+ ))}
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/calendar-with-time.tsx b/apps/v4/examples/radix/calendar-with-time.tsx
new file mode 100644
index 000000000..440304808
--- /dev/null
+++ b/apps/v4/examples/radix/calendar-with-time.tsx
@@ -0,0 +1,65 @@
+"use client"
+
+import * as React from "react"
+import { Calendar } from "@/examples/radix/ui/calendar"
+import { Card, CardContent, CardFooter } from "@/examples/radix/ui/card"
+import { Field, FieldGroup, FieldLabel } from "@/examples/radix/ui/field"
+import {
+ InputGroup,
+ InputGroupAddon,
+ InputGroupInput,
+} from "@/examples/radix/ui/input-group"
+import { Clock2Icon } from "lucide-react"
+
+export function CalendarWithTime() {
+ const [date, setDate] = React.useState(
+ new Date(new Date().getFullYear(), new Date().getMonth(), 12)
+ )
+
+ return (
+
+
+
+
+
+
+
+ Start Time
+
+
+
+
+
+
+
+
+ End Time
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/card-default.tsx b/apps/v4/examples/radix/card-default.tsx
new file mode 100644
index 000000000..a345093bc
--- /dev/null
+++ b/apps/v4/examples/radix/card-default.tsx
@@ -0,0 +1,33 @@
+import { Button } from "@/examples/radix/ui/button"
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "@/examples/radix/ui/card"
+
+export function CardDefault() {
+ return (
+
+
+ Default Card
+
+ This card uses the default size variant.
+
+
+
+
+ The card component supports a size prop that defaults to
+ "default" for standard spacing and sizing.
+
+
+
+
+ Action
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/card-footer-with-border-small.tsx b/apps/v4/examples/radix/card-footer-with-border-small.tsx
new file mode 100644
index 000000000..ce74fdad4
--- /dev/null
+++ b/apps/v4/examples/radix/card-footer-with-border-small.tsx
@@ -0,0 +1,20 @@
+import { Button } from "@/examples/radix/ui/button"
+import { Card, CardContent, CardFooter } from "@/examples/radix/ui/card"
+
+export function CardFooterWithBorderSmall() {
+ return (
+
+
+
+ The footer has a border-t class applied, creating a visual separation
+ between the content and footer sections.
+
+
+
+
+ Footer with Border
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/card-footer-with-border.tsx b/apps/v4/examples/radix/card-footer-with-border.tsx
new file mode 100644
index 000000000..837e3aaa1
--- /dev/null
+++ b/apps/v4/examples/radix/card-footer-with-border.tsx
@@ -0,0 +1,20 @@
+import { Button } from "@/examples/radix/ui/button"
+import { Card, CardContent, CardFooter } from "@/examples/radix/ui/card"
+
+export function CardFooterWithBorder() {
+ return (
+
+
+
+ The footer has a border-t class applied, creating a visual separation
+ between the content and footer sections.
+
+
+
+
+ Footer with Border
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/card-header-with-border-small.tsx b/apps/v4/examples/radix/card-header-with-border-small.tsx
new file mode 100644
index 000000000..adb8d520c
--- /dev/null
+++ b/apps/v4/examples/radix/card-header-with-border-small.tsx
@@ -0,0 +1,26 @@
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@/examples/radix/ui/card"
+
+export function CardHeaderWithBorderSmall() {
+ return (
+
+
+ Header with Border
+
+ This is a small card with a header that has a bottom border.
+
+
+
+
+ The header has a border-b class applied, creating a visual separation
+ between the header and content sections.
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/card-header-with-border.tsx b/apps/v4/examples/radix/card-header-with-border.tsx
new file mode 100644
index 000000000..3d1157e1e
--- /dev/null
+++ b/apps/v4/examples/radix/card-header-with-border.tsx
@@ -0,0 +1,26 @@
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@/examples/radix/ui/card"
+
+export function CardHeaderWithBorder() {
+ return (
+
+
+ Header with Border
+
+ This is a card with a header that has a bottom border.
+
+
+
+
+ The header has a border-b class applied, creating a visual separation
+ between the header and content sections.
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/card-login.tsx b/apps/v4/examples/radix/card-login.tsx
new file mode 100644
index 000000000..490f93f1f
--- /dev/null
+++ b/apps/v4/examples/radix/card-login.tsx
@@ -0,0 +1,65 @@
+import { Button } from "@/examples/radix/ui/button"
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "@/examples/radix/ui/card"
+import { Field, FieldGroup, FieldLabel } from "@/examples/radix/ui/field"
+import { Input } from "@/examples/radix/ui/input"
+
+export function CardLogin() {
+ return (
+
+
+ Login to your account
+
+ Enter your email below to login to your account
+
+
+
+
+
+
+
+ Login
+
+
+ Login with Google
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/card-meeting-notes.tsx b/apps/v4/examples/radix/card-meeting-notes.tsx
new file mode 100644
index 000000000..6c7488cb4
--- /dev/null
+++ b/apps/v4/examples/radix/card-meeting-notes.tsx
@@ -0,0 +1,73 @@
+import {
+ Avatar,
+ AvatarFallback,
+ AvatarGroup,
+ AvatarGroupCount,
+ AvatarImage,
+} from "@/examples/radix/ui/avatar"
+import { Button } from "@/examples/radix/ui/button"
+import {
+ Card,
+ CardAction,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "@/examples/radix/ui/card"
+import { CaptionsIcon } from "lucide-react"
+
+export function CardMeetingNotes() {
+ return (
+
+
+ Meeting Notes
+
+ Transcript from the meeting with the client.
+
+
+
+
+ Transcribe
+
+
+
+
+
+ Client requested dashboard redesign with focus on mobile
+ responsiveness.
+
+
+ New analytics widgets for daily/weekly metrics
+ Simplified navigation menu
+ Dark mode support
+ Timeline: 6 weeks
+ Follow-up meeting scheduled for next Tuesday
+
+
+
+
+
+
+ CN
+
+
+
+ LR
+
+
+
+ ER
+
+ +8
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/card-small.tsx b/apps/v4/examples/radix/card-small.tsx
new file mode 100644
index 000000000..bb5933569
--- /dev/null
+++ b/apps/v4/examples/radix/card-small.tsx
@@ -0,0 +1,33 @@
+import { Button } from "@/examples/radix/ui/button"
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "@/examples/radix/ui/card"
+
+export function CardSmall() {
+ return (
+
+
+ Small Card
+
+ This card uses the small size variant.
+
+
+
+
+ The card component supports a size prop that can be set to
+ "sm" for a more compact appearance.
+
+
+
+
+ Action
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/card-with-image-small.tsx b/apps/v4/examples/radix/card-with-image-small.tsx
new file mode 100644
index 000000000..41886631e
--- /dev/null
+++ b/apps/v4/examples/radix/card-with-image-small.tsx
@@ -0,0 +1,35 @@
+import { Button } from "@/examples/radix/ui/button"
+import {
+ Card,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "@/examples/radix/ui/card"
+import { PlusIcon } from "lucide-react"
+
+export function CardWithImageSmall() {
+ return (
+
+
+
+
+ Beautiful Landscape
+
+ A stunning view that captures the essence of natural beauty.
+
+
+
+
+
+ Button
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/card-with-image.tsx b/apps/v4/examples/radix/card-with-image.tsx
new file mode 100644
index 000000000..9598b8710
--- /dev/null
+++ b/apps/v4/examples/radix/card-with-image.tsx
@@ -0,0 +1,35 @@
+import { Button } from "@/examples/radix/ui/button"
+import {
+ Card,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "@/examples/radix/ui/card"
+import { PlusIcon } from "lucide-react"
+
+export function CardWithImage() {
+ return (
+
+
+
+
+ Beautiful Landscape
+
+ A stunning view that captures the essence of natural beauty.
+
+
+
+
+
+ Button
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/carousel-basic.tsx b/apps/v4/examples/radix/carousel-basic.tsx
new file mode 100644
index 000000000..d42114a86
--- /dev/null
+++ b/apps/v4/examples/radix/carousel-basic.tsx
@@ -0,0 +1,30 @@
+import { Card, CardContent } from "@/examples/radix/ui/card"
+import {
+ Carousel,
+ CarouselContent,
+ CarouselItem,
+ CarouselNext,
+ CarouselPrevious,
+} from "@/examples/radix/ui/carousel"
+
+export function CarouselBasic() {
+ return (
+
+
+ {Array.from({ length: 5 }).map((_, index) => (
+
+
+
+
+ {index + 1}
+
+
+
+
+ ))}
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/carousel-multiple.tsx b/apps/v4/examples/radix/carousel-multiple.tsx
new file mode 100644
index 000000000..931f06b0f
--- /dev/null
+++ b/apps/v4/examples/radix/carousel-multiple.tsx
@@ -0,0 +1,35 @@
+import { Card, CardContent } from "@/examples/radix/ui/card"
+import {
+ Carousel,
+ CarouselContent,
+ CarouselItem,
+ CarouselNext,
+ CarouselPrevious,
+} from "@/examples/radix/ui/carousel"
+
+export function CarouselMultiple() {
+ return (
+
+
+ {Array.from({ length: 5 }).map((_, index) => (
+
+
+
+
+ {index + 1}
+
+
+
+
+ ))}
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/carousel-with-gap.tsx b/apps/v4/examples/radix/carousel-with-gap.tsx
new file mode 100644
index 000000000..bf8e3540b
--- /dev/null
+++ b/apps/v4/examples/radix/carousel-with-gap.tsx
@@ -0,0 +1,30 @@
+import { Card, CardContent } from "@/examples/radix/ui/card"
+import {
+ Carousel,
+ CarouselContent,
+ CarouselItem,
+ CarouselNext,
+ CarouselPrevious,
+} from "@/examples/radix/ui/carousel"
+
+export function CarouselWithGap() {
+ return (
+
+
+ {Array.from({ length: 5 }).map((_, index) => (
+
+
+
+
+ {index + 1}
+
+
+
+
+ ))}
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/chart-area-example.tsx b/apps/v4/examples/radix/chart-area-example.tsx
new file mode 100644
index 000000000..d2aeffc77
--- /dev/null
+++ b/apps/v4/examples/radix/chart-area-example.tsx
@@ -0,0 +1,90 @@
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "@/examples/radix/ui/card"
+import {
+ ChartContainer,
+ ChartTooltip,
+ ChartTooltipContent,
+ type ChartConfig,
+} from "@/examples/radix/ui/chart"
+import { TrendingUpIcon } from "lucide-react"
+import { Area, AreaChart, CartesianGrid, XAxis } from "recharts"
+
+const areaChartData = [
+ { month: "January", desktop: 186 },
+ { month: "February", desktop: 305 },
+ { month: "March", desktop: 237 },
+ { month: "April", desktop: 73 },
+ { month: "May", desktop: 209 },
+ { month: "June", desktop: 214 },
+]
+
+const areaChartConfig = {
+ desktop: {
+ label: "Desktop",
+ color: "var(--chart-1)",
+ },
+} satisfies ChartConfig
+
+export function ChartAreaExample() {
+ return (
+
+
+ Area Chart
+
+ Showing total visitors for the last 6 months
+
+
+
+
+
+
+ value.slice(0, 3)}
+ />
+ }
+ />
+
+
+
+
+
+
+
+
+ Trending up by 5.2% this month{" "}
+
+
+
+ January - June 2024
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/chart-bar-example.tsx b/apps/v4/examples/radix/chart-bar-example.tsx
new file mode 100644
index 000000000..6d7d1e5a1
--- /dev/null
+++ b/apps/v4/examples/radix/chart-bar-example.tsx
@@ -0,0 +1,75 @@
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "@/examples/radix/ui/card"
+import {
+ ChartContainer,
+ ChartTooltip,
+ ChartTooltipContent,
+ type ChartConfig,
+} from "@/examples/radix/ui/chart"
+import { TrendingUpIcon } from "lucide-react"
+import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"
+
+const barChartData = [
+ { month: "January", desktop: 186, mobile: 80 },
+ { month: "February", desktop: 305, mobile: 200 },
+ { month: "March", desktop: 237, mobile: 120 },
+ { month: "April", desktop: 73, mobile: 190 },
+ { month: "May", desktop: 209, mobile: 130 },
+ { month: "June", desktop: 214, mobile: 140 },
+]
+
+const barChartConfig = {
+ desktop: {
+ label: "Desktop",
+ color: "var(--chart-1)",
+ },
+ mobile: {
+ label: "Mobile",
+ color: "var(--chart-2)",
+ },
+} satisfies ChartConfig
+
+export function ChartBarExample() {
+ return (
+
+
+ Bar Chart - Multiple
+ January - June 2024
+
+
+
+
+
+ value.slice(0, 3)}
+ />
+ }
+ />
+
+
+
+
+
+
+
+ Trending up by 5.2% this month
+
+
+ Showing total visitors for the last 6 months
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/chart-line-example.tsx b/apps/v4/examples/radix/chart-line-example.tsx
new file mode 100644
index 000000000..f9e0e66f8
--- /dev/null
+++ b/apps/v4/examples/radix/chart-line-example.tsx
@@ -0,0 +1,96 @@
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "@/examples/radix/ui/card"
+import {
+ ChartContainer,
+ ChartTooltip,
+ ChartTooltipContent,
+ type ChartConfig,
+} from "@/examples/radix/ui/chart"
+import { TrendingUpIcon } from "lucide-react"
+import { CartesianGrid, Line, LineChart, XAxis } from "recharts"
+
+const lineChartData = [
+ { month: "January", desktop: 186, mobile: 80 },
+ { month: "February", desktop: 305, mobile: 200 },
+ { month: "March", desktop: 237, mobile: 120 },
+ { month: "April", desktop: 73, mobile: 190 },
+ { month: "May", desktop: 209, mobile: 130 },
+ { month: "June", desktop: 214, mobile: 140 },
+]
+
+const lineChartConfig = {
+ desktop: {
+ label: "Desktop",
+ color: "var(--chart-1)",
+ },
+ mobile: {
+ label: "Mobile",
+ color: "var(--chart-2)",
+ },
+} satisfies ChartConfig
+
+export function ChartLineExample() {
+ return (
+
+
+ Line Chart - Multiple
+ January - June 2024
+
+
+
+
+
+ value.slice(0, 3)}
+ />
+ } />
+
+
+
+
+
+
+
+
+
+ Trending up by 5.2% this month{" "}
+
+
+
+ Showing total visitors for the last 6 months
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/chart-pie-example.tsx b/apps/v4/examples/radix/chart-pie-example.tsx
new file mode 100644
index 000000000..705f08bad
--- /dev/null
+++ b/apps/v4/examples/radix/chart-pie-example.tsx
@@ -0,0 +1,126 @@
+"use client"
+
+import * as React from "react"
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "@/examples/radix/ui/card"
+import {
+ ChartContainer,
+ ChartTooltip,
+ ChartTooltipContent,
+ type ChartConfig,
+} from "@/examples/radix/ui/chart"
+import { TrendingUpIcon } from "lucide-react"
+import { Label, Pie, PieChart } from "recharts"
+
+const pieChartData = [
+ { browser: "chrome", visitors: 275, fill: "var(--color-chrome)" },
+ { browser: "safari", visitors: 200, fill: "var(--color-safari)" },
+ { browser: "firefox", visitors: 287, fill: "var(--color-firefox)" },
+ { browser: "edge", visitors: 173, fill: "var(--color-edge)" },
+ { browser: "other", visitors: 190, fill: "var(--color-other)" },
+]
+
+const pieChartConfig = {
+ visitors: {
+ label: "Visitors",
+ },
+ chrome: {
+ label: "Chrome",
+ color: "var(--chart-1)",
+ },
+ safari: {
+ label: "Safari",
+ color: "var(--chart-2)",
+ },
+ firefox: {
+ label: "Firefox",
+ color: "var(--chart-3)",
+ },
+ edge: {
+ label: "Edge",
+ color: "var(--chart-4)",
+ },
+ other: {
+ label: "Other",
+ color: "var(--chart-5)",
+ },
+} satisfies ChartConfig
+
+export function ChartPieExample() {
+ const totalVisitors = React.useMemo(() => {
+ return pieChartData.reduce((acc, curr) => acc + curr.visitors, 0)
+ }, [])
+
+ return (
+
+
+ Pie Chart - Donut with Text
+ January - June 2024
+
+
+
+
+ }
+ />
+
+ {
+ if (viewBox && "cx" in viewBox && "cy" in viewBox) {
+ return (
+
+
+ {totalVisitors.toLocaleString()}
+
+
+ Visitors
+
+
+ )
+ }
+ }}
+ />
+
+
+
+
+
+
+ Trending up by 5.2% this month
+
+
+ Showing total visitors for the last 6 months
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/chart-radar-example.tsx b/apps/v4/examples/radix/chart-radar-example.tsx
new file mode 100644
index 000000000..7724cddd5
--- /dev/null
+++ b/apps/v4/examples/radix/chart-radar-example.tsx
@@ -0,0 +1,78 @@
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "@/examples/radix/ui/card"
+import {
+ ChartContainer,
+ ChartTooltip,
+ ChartTooltipContent,
+ type ChartConfig,
+} from "@/examples/radix/ui/chart"
+import { TrendingUpIcon } from "lucide-react"
+import { PolarAngleAxis, PolarGrid, Radar, RadarChart } from "recharts"
+
+const radarChartData = [
+ { month: "January", desktop: 186, mobile: 80 },
+ { month: "February", desktop: 305, mobile: 200 },
+ { month: "March", desktop: 237, mobile: 120 },
+ { month: "April", desktop: 73, mobile: 190 },
+ { month: "May", desktop: 209, mobile: 130 },
+ { month: "June", desktop: 214, mobile: 140 },
+]
+
+const radarChartConfig = {
+ desktop: {
+ label: "Desktop",
+ color: "var(--chart-1)",
+ },
+ mobile: {
+ label: "Mobile",
+ color: "var(--chart-2)",
+ },
+} satisfies ChartConfig
+
+export function ChartRadarExample() {
+ return (
+
+
+ Radar Chart - Multiple
+
+ Showing total visitors for the last 6 months
+
+
+
+
+
+ }
+ />
+
+
+
+
+
+
+
+
+
+ Trending up by 5.2% this month
+
+
+ January - June 2024
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/chart-radial-example.tsx b/apps/v4/examples/radix/chart-radial-example.tsx
new file mode 100644
index 000000000..edef3934f
--- /dev/null
+++ b/apps/v4/examples/radix/chart-radial-example.tsx
@@ -0,0 +1,103 @@
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "@/examples/radix/ui/card"
+import { ChartContainer, type ChartConfig } from "@/examples/radix/ui/chart"
+import { TrendingUpIcon } from "lucide-react"
+import {
+ Label,
+ PolarGrid,
+ PolarRadiusAxis,
+ RadialBar,
+ RadialBarChart,
+} from "recharts"
+
+const radialChartData = [
+ { browser: "safari", visitors: 1260, fill: "var(--color-safari)" },
+]
+
+const radialChartConfig = {
+ visitors: {
+ label: "Visitors",
+ },
+ safari: {
+ label: "Safari",
+ color: "var(--chart-2)",
+ },
+} satisfies ChartConfig
+
+export function ChartRadialExample() {
+ return (
+
+
+ Radial Chart - Shape
+ January - June 2024
+
+
+
+
+
+
+
+ {
+ if (viewBox && "cx" in viewBox && "cy" in viewBox) {
+ return (
+
+
+ {radialChartData[0].visitors.toLocaleString()}
+
+
+ Visitors
+
+
+ )
+ }
+ }}
+ />
+
+
+
+
+
+
+ Trending up by 5.2% this month
+
+
+ Showing total visitors for the last 6 months
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/checkbox-basic.tsx b/apps/v4/examples/radix/checkbox-basic.tsx
new file mode 100644
index 000000000..0f0289830
--- /dev/null
+++ b/apps/v4/examples/radix/checkbox-basic.tsx
@@ -0,0 +1,11 @@
+import { Checkbox } from "@/examples/radix/ui/checkbox"
+import { Field, FieldLabel } from "@/examples/radix/ui/field"
+
+export function CheckboxBasic() {
+ return (
+
+
+ Accept terms and conditions
+
+ )
+}
diff --git a/apps/v4/examples/radix/checkbox-disabled.tsx b/apps/v4/examples/radix/checkbox-disabled.tsx
index cfb6568bd..7414cc655 100644
--- a/apps/v4/examples/radix/checkbox-disabled.tsx
+++ b/apps/v4/examples/radix/checkbox-disabled.tsx
@@ -1,15 +1,11 @@
import { Checkbox } from "@/examples/radix/ui/checkbox"
+import { Field, FieldLabel } from "@/examples/radix/ui/field"
-export default function CheckboxDisabled() {
+export function CheckboxDisabled() {
return (
-
-
-
- Accept terms and conditions
-
-
+
+
+ Enable notifications
+
)
}
diff --git a/apps/v4/examples/radix/checkbox-fields.tsx b/apps/v4/examples/radix/checkbox-fields.tsx
new file mode 100644
index 000000000..e83c228d8
--- /dev/null
+++ b/apps/v4/examples/radix/checkbox-fields.tsx
@@ -0,0 +1,91 @@
+import { Checkbox } from "@/examples/radix/ui/checkbox"
+import {
+ Field,
+ FieldContent,
+ FieldDescription,
+ FieldGroup,
+ FieldLabel,
+ FieldLegend,
+ FieldSet,
+ FieldTitle,
+} from "@/examples/radix/ui/field"
+import { Select } from "@/examples/radix/ui/select"
+
+export function CheckboxFields() {
+ return (
+
+
+
+
+ I agree to the terms and conditions
+
+
+
+
+ Accept terms and conditions
+
+
+
+
+
+
+
+ Subscribe to newsletter
+
+
+ Receive weekly updates about new features and promotions.
+
+
+
+
+
+
+
+ Enable Touch ID
+
+ Enable Touch ID to quickly unlock your device.
+
+
+
+
+
+ Preferences
+
+ Select all that apply to customize your experience.
+
+
+
+
+
+ Dark mode
+
+
+
+
+
+ Compact view
+
+
+
+
+
+ Enable notifications
+
+
+
+
+
+
+
+ Invalid checkbox
+
+
+
+
+
+ Disabled checkbox
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/checkbox-group.tsx b/apps/v4/examples/radix/checkbox-group.tsx
new file mode 100644
index 000000000..29478b361
--- /dev/null
+++ b/apps/v4/examples/radix/checkbox-group.tsx
@@ -0,0 +1,46 @@
+import { Checkbox } from "@/examples/radix/ui/checkbox"
+import { Field, FieldLabel } from "@/examples/radix/ui/field"
+
+export function CheckboxGroup() {
+ return (
+
+ Show these items on the desktop:
+
+
+
+ Hard disks
+
+
+
+
+
+ External disks
+
+
+
+
+
+ CDs, DVDs, and iPods
+
+
+
+
+
+ Connected servers
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/checkbox-in-table.tsx b/apps/v4/examples/radix/checkbox-in-table.tsx
new file mode 100644
index 000000000..7aa3ee602
--- /dev/null
+++ b/apps/v4/examples/radix/checkbox-in-table.tsx
@@ -0,0 +1,105 @@
+"use client"
+
+import * as React from "react"
+import { Checkbox } from "@/examples/radix/ui/checkbox"
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/examples/radix/ui/table"
+
+const tableData = [
+ {
+ id: "1",
+ name: "Sarah Chen",
+ email: "sarah.chen@example.com",
+ role: "Admin",
+ },
+ {
+ id: "2",
+ name: "Marcus Rodriguez",
+ email: "marcus.rodriguez@example.com",
+ role: "User",
+ },
+ {
+ id: "3",
+ name: "Priya Patel",
+ email: "priya.patel@example.com",
+ role: "User",
+ },
+ {
+ id: "4",
+ name: "David Kim",
+ email: "david.kim@example.com",
+ role: "Editor",
+ },
+]
+
+export function CheckboxInTable() {
+ const [selectedRows, setSelectedRows] = React.useState>(
+ new Set(["1"])
+ )
+
+ const selectAll = selectedRows.size === tableData.length
+
+ const handleSelectAll = (checked: boolean) => {
+ if (checked) {
+ setSelectedRows(new Set(tableData.map((row) => row.id)))
+ } else {
+ setSelectedRows(new Set())
+ }
+ }
+
+ const handleSelectRow = (id: string, checked: boolean) => {
+ const newSelected = new Set(selectedRows)
+ if (checked) {
+ newSelected.add(id)
+ } else {
+ newSelected.delete(id)
+ }
+ setSelectedRows(newSelected)
+ }
+
+ return (
+
+
+
+
+
+
+ Name
+ Email
+ Role
+
+
+
+ {tableData.map((row) => (
+
+
+
+ handleSelectRow(row.id, checked === true)
+ }
+ />
+
+ {row.name}
+ {row.email}
+ {row.role}
+
+ ))}
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/checkbox-invalid.tsx b/apps/v4/examples/radix/checkbox-invalid.tsx
new file mode 100644
index 000000000..579203c52
--- /dev/null
+++ b/apps/v4/examples/radix/checkbox-invalid.tsx
@@ -0,0 +1,11 @@
+import { Checkbox } from "@/examples/radix/ui/checkbox"
+import { Field, FieldLabel } from "@/examples/radix/ui/field"
+
+export function CheckboxInvalid() {
+ return (
+
+
+ Accept terms and conditions
+
+ )
+}
diff --git a/apps/v4/examples/radix/checkbox-with-description.tsx b/apps/v4/examples/radix/checkbox-with-description.tsx
new file mode 100644
index 000000000..a08df6299
--- /dev/null
+++ b/apps/v4/examples/radix/checkbox-with-description.tsx
@@ -0,0 +1,21 @@
+import { Checkbox } from "@/examples/radix/ui/checkbox"
+import {
+ Field,
+ FieldContent,
+ FieldDescription,
+ FieldLabel,
+} from "@/examples/radix/ui/field"
+
+export function CheckboxWithDescription() {
+ return (
+
+
+
+ Accept terms and conditions
+
+ By clicking this checkbox, you agree to the terms and conditions.
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/checkbox-with-title.tsx b/apps/v4/examples/radix/checkbox-with-title.tsx
new file mode 100644
index 000000000..c64cdac0d
--- /dev/null
+++ b/apps/v4/examples/radix/checkbox-with-title.tsx
@@ -0,0 +1,38 @@
+import { Checkbox } from "@/examples/radix/ui/checkbox"
+import {
+ Field,
+ FieldContent,
+ FieldDescription,
+ FieldGroup,
+ FieldLabel,
+ FieldTitle,
+} from "@/examples/radix/ui/field"
+
+export function CheckboxWithTitle() {
+ return (
+
+
+
+
+
+ Enable notifications
+
+ You can enable or disable notifications at any time.
+
+
+
+
+
+
+
+
+ Enable notifications
+
+ You can enable or disable notifications at any time.
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/collapsible-file-tree.tsx b/apps/v4/examples/radix/collapsible-file-tree.tsx
new file mode 100644
index 000000000..6ee6ac6cd
--- /dev/null
+++ b/apps/v4/examples/radix/collapsible-file-tree.tsx
@@ -0,0 +1,119 @@
+import { Button } from "@/examples/radix/ui/button"
+import { Card, CardContent, CardHeader } from "@/examples/radix/ui/card"
+import {
+ Collapsible,
+ CollapsibleContent,
+ CollapsibleTrigger,
+} from "@/examples/radix/ui/collapsible"
+import { Tabs, TabsList, TabsTrigger } from "@/examples/radix/ui/tabs"
+import { ChevronRightIcon, FileIcon, FolderIcon } from "lucide-react"
+
+type FileTreeItem = { name: string } | { name: string; items: FileTreeItem[] }
+
+export function CollapsibleFileTree() {
+ const fileTree: FileTreeItem[] = [
+ {
+ name: "components",
+ items: [
+ {
+ name: "ui",
+ items: [
+ { name: "button.tsx" },
+ { name: "card.tsx" },
+ { name: "dialog.tsx" },
+ { name: "input.tsx" },
+ { name: "select.tsx" },
+ { name: "table.tsx" },
+ ],
+ },
+ { name: "login-form.tsx" },
+ { name: "register-form.tsx" },
+ ],
+ },
+ {
+ name: "lib",
+ items: [{ name: "utils.ts" }, { name: "cn.ts" }, { name: "api.ts" }],
+ },
+ {
+ name: "hooks",
+ items: [
+ { name: "use-media-query.ts" },
+ { name: "use-debounce.ts" },
+ { name: "use-local-storage.ts" },
+ ],
+ },
+ {
+ name: "types",
+ items: [{ name: "index.d.ts" }, { name: "api.d.ts" }],
+ },
+ {
+ name: "public",
+ items: [
+ { name: "favicon.ico" },
+ { name: "logo.svg" },
+ { name: "images" },
+ ],
+ },
+ { name: "app.tsx" },
+ { name: "layout.tsx" },
+ { name: "globals.css" },
+ { name: "package.json" },
+ { name: "tsconfig.json" },
+ { name: "README.md" },
+ { name: ".gitignore" },
+ ]
+
+ const renderItem = (fileItem: FileTreeItem) => {
+ if ("items" in fileItem) {
+ return (
+
+
+
+
+
+ {fileItem.name}
+
+
+
+
+ {fileItem.items.map((child) => renderItem(child))}
+
+
+
+ )
+ }
+ return (
+
+
+ {fileItem.name}
+
+ )
+ }
+
+ return (
+
+
+
+
+ Explorer
+ Outline
+
+
+
+
+
+ {fileTree.map((item) => renderItem(item))}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/collapsible-settings.tsx b/apps/v4/examples/radix/collapsible-settings.tsx
new file mode 100644
index 000000000..c1db53ffb
--- /dev/null
+++ b/apps/v4/examples/radix/collapsible-settings.tsx
@@ -0,0 +1,73 @@
+"use client"
+
+import * as React from "react"
+import { Button } from "@/examples/radix/ui/button"
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@/examples/radix/ui/card"
+import {
+ Collapsible,
+ CollapsibleContent,
+ CollapsibleTrigger,
+} from "@/examples/radix/ui/collapsible"
+import { Field, FieldGroup, FieldLabel } from "@/examples/radix/ui/field"
+import { Input } from "@/examples/radix/ui/input"
+import { MaximizeIcon, MinimizeIcon } from "lucide-react"
+
+export function CollapsibleSettings() {
+ const [isOpen, setIsOpen] = React.useState(false)
+
+ return (
+
+
+ Radius
+ Set the corner radius of the element.
+
+
+
+
+
+
+ Radius X
+
+
+
+
+
+ Radius Y
+
+
+
+
+
+
+ Radius X
+
+
+
+
+
+ Radius Y
+
+
+
+
+
+
+
+ {isOpen ? : }
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/combobox-auto-highlight.tsx b/apps/v4/examples/radix/combobox-auto-highlight.tsx
new file mode 100644
index 000000000..b87de060e
--- /dev/null
+++ b/apps/v4/examples/radix/combobox-auto-highlight.tsx
@@ -0,0 +1,35 @@
+import {
+ Combobox,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxInput,
+ ComboboxItem,
+ ComboboxList,
+} from "@/examples/radix/ui/combobox"
+import { Select } from "@/examples/radix/ui/select"
+
+const frameworks = [
+ "Next.js",
+ "SvelteKit",
+ "Nuxt.js",
+ "Remix",
+ "Astro",
+] as const
+
+export function ComboboxAutoHighlight() {
+ return (
+
+
+
+ No items found.
+
+ {(item) => (
+
+ {item}
+
+ )}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/combobox-basic.tsx b/apps/v4/examples/radix/combobox-basic.tsx
new file mode 100644
index 000000000..73de495e6
--- /dev/null
+++ b/apps/v4/examples/radix/combobox-basic.tsx
@@ -0,0 +1,35 @@
+import {
+ Combobox,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxInput,
+ ComboboxItem,
+ ComboboxList,
+} from "@/examples/radix/ui/combobox"
+import { Select } from "@/examples/radix/ui/select"
+
+const frameworks = [
+ "Next.js",
+ "SvelteKit",
+ "Nuxt.js",
+ "Remix",
+ "Astro",
+] as const
+
+export function ComboboxBasic() {
+ return (
+
+
+
+ No items found.
+
+ {(item) => (
+
+ {item}
+
+ )}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/combobox-disabled.tsx b/apps/v4/examples/radix/combobox-disabled.tsx
new file mode 100644
index 000000000..5cf6b6bdd
--- /dev/null
+++ b/apps/v4/examples/radix/combobox-disabled.tsx
@@ -0,0 +1,35 @@
+import {
+ Combobox,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxInput,
+ ComboboxItem,
+ ComboboxList,
+} from "@/examples/radix/ui/combobox"
+import { Select } from "@/examples/radix/ui/select"
+
+const frameworks = [
+ "Next.js",
+ "SvelteKit",
+ "Nuxt.js",
+ "Remix",
+ "Astro",
+] as const
+
+export function ComboboxDisabled() {
+ return (
+
+
+
+ No items found.
+
+ {(item) => (
+
+ {item}
+
+ )}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/combobox-in-dialog.tsx b/apps/v4/examples/radix/combobox-in-dialog.tsx
new file mode 100644
index 000000000..0d64e5e70
--- /dev/null
+++ b/apps/v4/examples/radix/combobox-in-dialog.tsx
@@ -0,0 +1,91 @@
+"use client"
+
+import * as React from "react"
+import { Button } from "@/examples/radix/ui/button"
+import {
+ Combobox,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxInput,
+ ComboboxItem,
+ ComboboxList,
+} from "@/examples/radix/ui/combobox"
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+ DialogTrigger,
+} from "@/examples/radix/ui/dialog"
+import { Field, FieldLabel } from "@/examples/radix/ui/field"
+import { Select } from "@/examples/radix/ui/select"
+import { toast } from "sonner"
+
+const frameworks = [
+ "Next.js",
+ "SvelteKit",
+ "Nuxt.js",
+ "Remix",
+ "Astro",
+] as const
+
+export function ComboboxInDialog() {
+ const [open, setOpen] = React.useState(false)
+
+ return (
+
+
+ Open Dialog
+
+
+
+ Select Framework
+
+ Choose your preferred framework from the list below.
+
+
+
+
+ Framework
+
+
+
+
+ No items found.
+
+ {(item) => (
+
+ {item}
+
+ )}
+
+
+
+
+
+ setOpen(false)}
+ >
+ Cancel
+
+ {
+ toast("Framework selected.")
+ setOpen(false)
+ }}
+ >
+ Confirm
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/combobox-in-popup.tsx b/apps/v4/examples/radix/combobox-in-popup.tsx
new file mode 100644
index 000000000..c4becdaf2
--- /dev/null
+++ b/apps/v4/examples/radix/combobox-in-popup.tsx
@@ -0,0 +1,453 @@
+import { Button } from "@/examples/radix/ui/button"
+import {
+ Combobox,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxInput,
+ ComboboxItem,
+ ComboboxList,
+ ComboboxTrigger,
+ ComboboxValue,
+} from "@/examples/radix/ui/combobox"
+import { Select } from "@/examples/radix/ui/select"
+
+const countries = [
+ { code: "", value: "", continent: "", label: "Select country" },
+ { code: "af", value: "afghanistan", label: "Afghanistan", continent: "Asia" },
+ { code: "al", value: "albania", label: "Albania", continent: "Europe" },
+ { code: "dz", value: "algeria", label: "Algeria", continent: "Africa" },
+ { code: "ad", value: "andorra", label: "Andorra", continent: "Europe" },
+ { code: "ao", value: "angola", label: "Angola", continent: "Africa" },
+ {
+ code: "ar",
+ value: "argentina",
+ label: "Argentina",
+ continent: "South America",
+ },
+ { code: "am", value: "armenia", label: "Armenia", continent: "Asia" },
+ { code: "au", value: "australia", label: "Australia", continent: "Oceania" },
+ { code: "at", value: "austria", label: "Austria", continent: "Europe" },
+ { code: "az", value: "azerbaijan", label: "Azerbaijan", continent: "Asia" },
+ {
+ code: "bs",
+ value: "bahamas",
+ label: "Bahamas",
+ continent: "North America",
+ },
+ { code: "bh", value: "bahrain", label: "Bahrain", continent: "Asia" },
+ { code: "bd", value: "bangladesh", label: "Bangladesh", continent: "Asia" },
+ {
+ code: "bb",
+ value: "barbados",
+ label: "Barbados",
+ continent: "North America",
+ },
+ { code: "by", value: "belarus", label: "Belarus", continent: "Europe" },
+ { code: "be", value: "belgium", label: "Belgium", continent: "Europe" },
+ { code: "bz", value: "belize", label: "Belize", continent: "North America" },
+ { code: "bj", value: "benin", label: "Benin", continent: "Africa" },
+ { code: "bt", value: "bhutan", label: "Bhutan", continent: "Asia" },
+ {
+ code: "bo",
+ value: "bolivia",
+ label: "Bolivia",
+ continent: "South America",
+ },
+ {
+ code: "ba",
+ value: "bosnia-and-herzegovina",
+ label: "Bosnia and Herzegovina",
+ continent: "Europe",
+ },
+ { code: "bw", value: "botswana", label: "Botswana", continent: "Africa" },
+ { code: "br", value: "brazil", label: "Brazil", continent: "South America" },
+ { code: "bn", value: "brunei", label: "Brunei", continent: "Asia" },
+ { code: "bg", value: "bulgaria", label: "Bulgaria", continent: "Europe" },
+ {
+ code: "bf",
+ value: "burkina-faso",
+ label: "Burkina Faso",
+ continent: "Africa",
+ },
+ { code: "bi", value: "burundi", label: "Burundi", continent: "Africa" },
+ { code: "kh", value: "cambodia", label: "Cambodia", continent: "Asia" },
+ { code: "cm", value: "cameroon", label: "Cameroon", continent: "Africa" },
+ { code: "ca", value: "canada", label: "Canada", continent: "North America" },
+ { code: "cv", value: "cape-verde", label: "Cape Verde", continent: "Africa" },
+ {
+ code: "cf",
+ value: "central-african-republic",
+ label: "Central African Republic",
+ continent: "Africa",
+ },
+ { code: "td", value: "chad", label: "Chad", continent: "Africa" },
+ { code: "cl", value: "chile", label: "Chile", continent: "South America" },
+ { code: "cn", value: "china", label: "China", continent: "Asia" },
+ {
+ code: "co",
+ value: "colombia",
+ label: "Colombia",
+ continent: "South America",
+ },
+ { code: "km", value: "comoros", label: "Comoros", continent: "Africa" },
+ { code: "cg", value: "congo", label: "Congo", continent: "Africa" },
+ {
+ code: "cr",
+ value: "costa-rica",
+ label: "Costa Rica",
+ continent: "North America",
+ },
+ { code: "hr", value: "croatia", label: "Croatia", continent: "Europe" },
+ { code: "cu", value: "cuba", label: "Cuba", continent: "North America" },
+ { code: "cy", value: "cyprus", label: "Cyprus", continent: "Asia" },
+ {
+ code: "cz",
+ value: "czech-republic",
+ label: "Czech Republic",
+ continent: "Europe",
+ },
+ { code: "dk", value: "denmark", label: "Denmark", continent: "Europe" },
+ { code: "dj", value: "djibouti", label: "Djibouti", continent: "Africa" },
+ {
+ code: "dm",
+ value: "dominica",
+ label: "Dominica",
+ continent: "North America",
+ },
+ {
+ code: "do",
+ value: "dominican-republic",
+ label: "Dominican Republic",
+ continent: "North America",
+ },
+ {
+ code: "ec",
+ value: "ecuador",
+ label: "Ecuador",
+ continent: "South America",
+ },
+ { code: "eg", value: "egypt", label: "Egypt", continent: "Africa" },
+ {
+ code: "sv",
+ value: "el-salvador",
+ label: "El Salvador",
+ continent: "North America",
+ },
+ {
+ code: "gq",
+ value: "equatorial-guinea",
+ label: "Equatorial Guinea",
+ continent: "Africa",
+ },
+ { code: "er", value: "eritrea", label: "Eritrea", continent: "Africa" },
+ { code: "ee", value: "estonia", label: "Estonia", continent: "Europe" },
+ { code: "et", value: "ethiopia", label: "Ethiopia", continent: "Africa" },
+ { code: "fj", value: "fiji", label: "Fiji", continent: "Oceania" },
+ { code: "fi", value: "finland", label: "Finland", continent: "Europe" },
+ { code: "fr", value: "france", label: "France", continent: "Europe" },
+ { code: "ga", value: "gabon", label: "Gabon", continent: "Africa" },
+ { code: "gm", value: "gambia", label: "Gambia", continent: "Africa" },
+ { code: "ge", value: "georgia", label: "Georgia", continent: "Asia" },
+ { code: "de", value: "germany", label: "Germany", continent: "Europe" },
+ { code: "gh", value: "ghana", label: "Ghana", continent: "Africa" },
+ { code: "gr", value: "greece", label: "Greece", continent: "Europe" },
+ {
+ code: "gd",
+ value: "grenada",
+ label: "Grenada",
+ continent: "North America",
+ },
+ {
+ code: "gt",
+ value: "guatemala",
+ label: "Guatemala",
+ continent: "North America",
+ },
+ { code: "gn", value: "guinea", label: "Guinea", continent: "Africa" },
+ {
+ code: "gw",
+ value: "guinea-bissau",
+ label: "Guinea-Bissau",
+ continent: "Africa",
+ },
+ { code: "gy", value: "guyana", label: "Guyana", continent: "South America" },
+ { code: "ht", value: "haiti", label: "Haiti", continent: "North America" },
+ {
+ code: "hn",
+ value: "honduras",
+ label: "Honduras",
+ continent: "North America",
+ },
+ { code: "hu", value: "hungary", label: "Hungary", continent: "Europe" },
+ { code: "is", value: "iceland", label: "Iceland", continent: "Europe" },
+ { code: "in", value: "india", label: "India", continent: "Asia" },
+ { code: "id", value: "indonesia", label: "Indonesia", continent: "Asia" },
+ { code: "ir", value: "iran", label: "Iran", continent: "Asia" },
+ { code: "iq", value: "iraq", label: "Iraq", continent: "Asia" },
+ { code: "ie", value: "ireland", label: "Ireland", continent: "Europe" },
+ { code: "il", value: "israel", label: "Israel", continent: "Asia" },
+ { code: "it", value: "italy", label: "Italy", continent: "Europe" },
+ {
+ code: "jm",
+ value: "jamaica",
+ label: "Jamaica",
+ continent: "North America",
+ },
+ { code: "jp", value: "japan", label: "Japan", continent: "Asia" },
+ { code: "jo", value: "jordan", label: "Jordan", continent: "Asia" },
+ { code: "kz", value: "kazakhstan", label: "Kazakhstan", continent: "Asia" },
+ { code: "ke", value: "kenya", label: "Kenya", continent: "Africa" },
+ { code: "kw", value: "kuwait", label: "Kuwait", continent: "Asia" },
+ { code: "kg", value: "kyrgyzstan", label: "Kyrgyzstan", continent: "Asia" },
+ { code: "la", value: "laos", label: "Laos", continent: "Asia" },
+ { code: "lv", value: "latvia", label: "Latvia", continent: "Europe" },
+ { code: "lb", value: "lebanon", label: "Lebanon", continent: "Asia" },
+ { code: "ls", value: "lesotho", label: "Lesotho", continent: "Africa" },
+ { code: "lr", value: "liberia", label: "Liberia", continent: "Africa" },
+ { code: "ly", value: "libya", label: "Libya", continent: "Africa" },
+ {
+ code: "li",
+ value: "liechtenstein",
+ label: "Liechtenstein",
+ continent: "Europe",
+ },
+ { code: "lt", value: "lithuania", label: "Lithuania", continent: "Europe" },
+ { code: "lu", value: "luxembourg", label: "Luxembourg", continent: "Europe" },
+ { code: "mg", value: "madagascar", label: "Madagascar", continent: "Africa" },
+ { code: "mw", value: "malawi", label: "Malawi", continent: "Africa" },
+ { code: "my", value: "malaysia", label: "Malaysia", continent: "Asia" },
+ { code: "mv", value: "maldives", label: "Maldives", continent: "Asia" },
+ { code: "ml", value: "mali", label: "Mali", continent: "Africa" },
+ { code: "mt", value: "malta", label: "Malta", continent: "Europe" },
+ {
+ code: "mh",
+ value: "marshall-islands",
+ label: "Marshall Islands",
+ continent: "Oceania",
+ },
+ { code: "mr", value: "mauritania", label: "Mauritania", continent: "Africa" },
+ { code: "mu", value: "mauritius", label: "Mauritius", continent: "Africa" },
+ { code: "mx", value: "mexico", label: "Mexico", continent: "North America" },
+ {
+ code: "fm",
+ value: "micronesia",
+ label: "Micronesia",
+ continent: "Oceania",
+ },
+ { code: "md", value: "moldova", label: "Moldova", continent: "Europe" },
+ { code: "mc", value: "monaco", label: "Monaco", continent: "Europe" },
+ { code: "mn", value: "mongolia", label: "Mongolia", continent: "Asia" },
+ { code: "me", value: "montenegro", label: "Montenegro", continent: "Europe" },
+ { code: "ma", value: "morocco", label: "Morocco", continent: "Africa" },
+ { code: "mz", value: "mozambique", label: "Mozambique", continent: "Africa" },
+ { code: "mm", value: "myanmar", label: "Myanmar", continent: "Asia" },
+ { code: "na", value: "namibia", label: "Namibia", continent: "Africa" },
+ { code: "nr", value: "nauru", label: "Nauru", continent: "Oceania" },
+ { code: "np", value: "nepal", label: "Nepal", continent: "Asia" },
+ {
+ code: "nl",
+ value: "netherlands",
+ label: "Netherlands",
+ continent: "Europe",
+ },
+ {
+ code: "nz",
+ value: "new-zealand",
+ label: "New Zealand",
+ continent: "Oceania",
+ },
+ {
+ code: "ni",
+ value: "nicaragua",
+ label: "Nicaragua",
+ continent: "North America",
+ },
+ { code: "ne", value: "niger", label: "Niger", continent: "Africa" },
+ { code: "ng", value: "nigeria", label: "Nigeria", continent: "Africa" },
+ { code: "kp", value: "north-korea", label: "North Korea", continent: "Asia" },
+ {
+ code: "mk",
+ value: "north-macedonia",
+ label: "North Macedonia",
+ continent: "Europe",
+ },
+ { code: "no", value: "norway", label: "Norway", continent: "Europe" },
+ { code: "om", value: "oman", label: "Oman", continent: "Asia" },
+ { code: "pk", value: "pakistan", label: "Pakistan", continent: "Asia" },
+ { code: "pw", value: "palau", label: "Palau", continent: "Oceania" },
+ { code: "ps", value: "palestine", label: "Palestine", continent: "Asia" },
+ { code: "pa", value: "panama", label: "Panama", continent: "North America" },
+ {
+ code: "pg",
+ value: "papua-new-guinea",
+ label: "Papua New Guinea",
+ continent: "Oceania",
+ },
+ {
+ code: "py",
+ value: "paraguay",
+ label: "Paraguay",
+ continent: "South America",
+ },
+ { code: "pe", value: "peru", label: "Peru", continent: "South America" },
+ { code: "ph", value: "philippines", label: "Philippines", continent: "Asia" },
+ { code: "pl", value: "poland", label: "Poland", continent: "Europe" },
+ { code: "pt", value: "portugal", label: "Portugal", continent: "Europe" },
+ { code: "qa", value: "qatar", label: "Qatar", continent: "Asia" },
+ { code: "ro", value: "romania", label: "Romania", continent: "Europe" },
+ { code: "ru", value: "russia", label: "Russia", continent: "Europe" },
+ { code: "rw", value: "rwanda", label: "Rwanda", continent: "Africa" },
+ { code: "ws", value: "samoa", label: "Samoa", continent: "Oceania" },
+ { code: "sm", value: "san-marino", label: "San Marino", continent: "Europe" },
+ {
+ code: "sa",
+ value: "saudi-arabia",
+ label: "Saudi Arabia",
+ continent: "Asia",
+ },
+ { code: "sn", value: "senegal", label: "Senegal", continent: "Africa" },
+ { code: "rs", value: "serbia", label: "Serbia", continent: "Europe" },
+ { code: "sc", value: "seychelles", label: "Seychelles", continent: "Africa" },
+ {
+ code: "sl",
+ value: "sierra-leone",
+ label: "Sierra Leone",
+ continent: "Africa",
+ },
+ { code: "sg", value: "singapore", label: "Singapore", continent: "Asia" },
+ { code: "sk", value: "slovakia", label: "Slovakia", continent: "Europe" },
+ { code: "si", value: "slovenia", label: "Slovenia", continent: "Europe" },
+ {
+ code: "sb",
+ value: "solomon-islands",
+ label: "Solomon Islands",
+ continent: "Oceania",
+ },
+ { code: "so", value: "somalia", label: "Somalia", continent: "Africa" },
+ {
+ code: "za",
+ value: "south-africa",
+ label: "South Africa",
+ continent: "Africa",
+ },
+ { code: "kr", value: "south-korea", label: "South Korea", continent: "Asia" },
+ {
+ code: "ss",
+ value: "south-sudan",
+ label: "South Sudan",
+ continent: "Africa",
+ },
+ { code: "es", value: "spain", label: "Spain", continent: "Europe" },
+ { code: "lk", value: "sri-lanka", label: "Sri Lanka", continent: "Asia" },
+ { code: "sd", value: "sudan", label: "Sudan", continent: "Africa" },
+ {
+ code: "sr",
+ value: "suriname",
+ label: "Suriname",
+ continent: "South America",
+ },
+ { code: "se", value: "sweden", label: "Sweden", continent: "Europe" },
+ {
+ code: "ch",
+ value: "switzerland",
+ label: "Switzerland",
+ continent: "Europe",
+ },
+ { code: "sy", value: "syria", label: "Syria", continent: "Asia" },
+ { code: "tw", value: "taiwan", label: "Taiwan", continent: "Asia" },
+ { code: "tj", value: "tajikistan", label: "Tajikistan", continent: "Asia" },
+ { code: "tz", value: "tanzania", label: "Tanzania", continent: "Africa" },
+ { code: "th", value: "thailand", label: "Thailand", continent: "Asia" },
+ { code: "tl", value: "timor-leste", label: "Timor-Leste", continent: "Asia" },
+ { code: "tg", value: "togo", label: "Togo", continent: "Africa" },
+ { code: "to", value: "tonga", label: "Tonga", continent: "Oceania" },
+ {
+ code: "tt",
+ value: "trinidad-and-tobago",
+ label: "Trinidad and Tobago",
+ continent: "North America",
+ },
+ { code: "tn", value: "tunisia", label: "Tunisia", continent: "Africa" },
+ { code: "tr", value: "turkey", label: "Turkey", continent: "Asia" },
+ {
+ code: "tm",
+ value: "turkmenistan",
+ label: "Turkmenistan",
+ continent: "Asia",
+ },
+ { code: "tv", value: "tuvalu", label: "Tuvalu", continent: "Oceania" },
+ { code: "ug", value: "uganda", label: "Uganda", continent: "Africa" },
+ { code: "ua", value: "ukraine", label: "Ukraine", continent: "Europe" },
+ {
+ code: "ae",
+ value: "united-arab-emirates",
+ label: "United Arab Emirates",
+ continent: "Asia",
+ },
+ {
+ code: "gb",
+ value: "united-kingdom",
+ label: "United Kingdom",
+ continent: "Europe",
+ },
+ {
+ code: "us",
+ value: "united-states",
+ label: "United States",
+ continent: "North America",
+ },
+ {
+ code: "uy",
+ value: "uruguay",
+ label: "Uruguay",
+ continent: "South America",
+ },
+ { code: "uz", value: "uzbekistan", label: "Uzbekistan", continent: "Asia" },
+ { code: "vu", value: "vanuatu", label: "Vanuatu", continent: "Oceania" },
+ {
+ code: "va",
+ value: "vatican-city",
+ label: "Vatican City",
+ continent: "Europe",
+ },
+ {
+ code: "ve",
+ value: "venezuela",
+ label: "Venezuela",
+ continent: "South America",
+ },
+ { code: "vn", value: "vietnam", label: "Vietnam", continent: "Asia" },
+ { code: "ye", value: "yemen", label: "Yemen", continent: "Asia" },
+ { code: "zm", value: "zambia", label: "Zambia", continent: "Africa" },
+ { code: "zw", value: "zimbabwe", label: "Zimbabwe", continent: "Africa" },
+]
+
+export function ComboboxInPopup() {
+ return (
+ <>
+
+
+ }
+ >
+
+
+
+
+ No items found.
+
+ {(item) => (
+
+ {item.label}
+
+ )}
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/radix/combobox-invalid.tsx b/apps/v4/examples/radix/combobox-invalid.tsx
new file mode 100644
index 000000000..561595688
--- /dev/null
+++ b/apps/v4/examples/radix/combobox-invalid.tsx
@@ -0,0 +1,65 @@
+import {
+ Combobox,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxInput,
+ ComboboxItem,
+ ComboboxList,
+} from "@/examples/radix/ui/combobox"
+import {
+ Field,
+ FieldDescription,
+ FieldError,
+ FieldLabel,
+} from "@/examples/radix/ui/field"
+import { Select } from "@/examples/radix/ui/select"
+
+const frameworks = [
+ "Next.js",
+ "SvelteKit",
+ "Nuxt.js",
+ "Remix",
+ "Astro",
+] as const
+
+export function ComboboxInvalid() {
+ return (
+
+
+
+
+ No items found.
+
+ {(item) => (
+
+ {item}
+
+ )}
+
+
+
+
+ Framework
+
+
+
+ No items found.
+
+ {(item) => (
+
+ {item}
+
+ )}
+
+
+
+ Please select a valid framework.
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/combobox-large-list.tsx b/apps/v4/examples/radix/combobox-large-list.tsx
new file mode 100644
index 000000000..1f5b6075e
--- /dev/null
+++ b/apps/v4/examples/radix/combobox-large-list.tsx
@@ -0,0 +1,29 @@
+import {
+ Combobox,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxInput,
+ ComboboxItem,
+ ComboboxList,
+} from "@/examples/radix/ui/combobox"
+import { Item } from "@/examples/radix/ui/item"
+
+const largeListItems = Array.from({ length: 100 }, (_, i) => `Item ${i + 1}`)
+
+export function ComboboxLargeList() {
+ return (
+
+
+
+ No items found.
+
+ {(item) => (
+
+ {item}
+
+ )}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/combobox-multiple-disabled.tsx b/apps/v4/examples/radix/combobox-multiple-disabled.tsx
new file mode 100644
index 000000000..9be489358
--- /dev/null
+++ b/apps/v4/examples/radix/combobox-multiple-disabled.tsx
@@ -0,0 +1,58 @@
+import * as React from "react"
+import {
+ Combobox,
+ ComboboxChip,
+ ComboboxChips,
+ ComboboxChipsInput,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxItem,
+ ComboboxList,
+ ComboboxValue,
+ useComboboxAnchor,
+} from "@/examples/radix/ui/combobox"
+
+const frameworks = [
+ "Next.js",
+ "SvelteKit",
+ "Nuxt.js",
+ "Remix",
+ "Astro",
+] as const
+
+export function ComboboxMultipleDisabled() {
+ const anchor = useComboboxAnchor()
+
+ return (
+
+
+
+ {(values) => (
+
+ {values.map((value: string) => (
+ {value}
+ ))}
+
+
+ )}
+
+
+
+ No items found.
+
+ {(item) => (
+
+ {item}
+
+ )}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/combobox-multiple-invalid.tsx b/apps/v4/examples/radix/combobox-multiple-invalid.tsx
new file mode 100644
index 000000000..3b8619bf7
--- /dev/null
+++ b/apps/v4/examples/radix/combobox-multiple-invalid.tsx
@@ -0,0 +1,105 @@
+import * as React from "react"
+import {
+ Combobox,
+ ComboboxChip,
+ ComboboxChips,
+ ComboboxChipsInput,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxItem,
+ ComboboxList,
+ ComboboxValue,
+ useComboboxAnchor,
+} from "@/examples/radix/ui/combobox"
+import {
+ Field,
+ FieldDescription,
+ FieldError,
+ FieldLabel,
+} from "@/examples/radix/ui/field"
+
+const frameworks = [
+ "Next.js",
+ "SvelteKit",
+ "Nuxt.js",
+ "Remix",
+ "Astro",
+] as const
+
+export function ComboboxMultipleInvalid() {
+ const anchor1 = useComboboxAnchor()
+ const anchor2 = useComboboxAnchor()
+
+ return (
+
+
+
+
+ {(values) => (
+
+ {values.map((value: string) => (
+ {value}
+ ))}
+
+
+ )}
+
+
+
+ No items found.
+
+ {(item) => (
+
+ {item}
+
+ )}
+
+
+
+
+ Frameworks
+
+
+
+ {(values) => (
+
+ {values.map((value: string) => (
+ {value}
+ ))}
+
+
+ )}
+
+
+
+ No items found.
+
+ {(item) => (
+
+ {item}
+
+ )}
+
+
+
+
+ Please select at least one framework.
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/combobox-multiple-no-remove.tsx b/apps/v4/examples/radix/combobox-multiple-no-remove.tsx
new file mode 100644
index 000000000..94da9cf1d
--- /dev/null
+++ b/apps/v4/examples/radix/combobox-multiple-no-remove.tsx
@@ -0,0 +1,59 @@
+import * as React from "react"
+import {
+ Combobox,
+ ComboboxChip,
+ ComboboxChips,
+ ComboboxChipsInput,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxItem,
+ ComboboxList,
+ ComboboxValue,
+ useComboboxAnchor,
+} from "@/examples/radix/ui/combobox"
+
+const frameworks = [
+ "Next.js",
+ "SvelteKit",
+ "Nuxt.js",
+ "Remix",
+ "Astro",
+] as const
+
+export function ComboboxMultipleNoRemove() {
+ const anchor = useComboboxAnchor()
+
+ return (
+
+
+
+ {(values) => (
+
+ {values.map((value: string) => (
+
+ {value}
+
+ ))}
+
+
+ )}
+
+
+
+ No items found.
+
+ {(item) => (
+
+ {item}
+
+ )}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/combobox-multiple.tsx b/apps/v4/examples/radix/combobox-multiple.tsx
new file mode 100644
index 000000000..844373dab
--- /dev/null
+++ b/apps/v4/examples/radix/combobox-multiple.tsx
@@ -0,0 +1,57 @@
+import * as React from "react"
+import {
+ Combobox,
+ ComboboxChip,
+ ComboboxChips,
+ ComboboxChipsInput,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxItem,
+ ComboboxList,
+ ComboboxValue,
+ useComboboxAnchor,
+} from "@/examples/radix/ui/combobox"
+
+const frameworks = [
+ "Next.js",
+ "SvelteKit",
+ "Nuxt.js",
+ "Remix",
+ "Astro",
+] as const
+
+export function ComboboxMultiple() {
+ const anchor = useComboboxAnchor()
+
+ return (
+
+
+
+ {(values) => (
+
+ {values.map((value: string) => (
+ {value}
+ ))}
+
+
+ )}
+
+
+
+ No items found.
+
+ {(item) => (
+
+ {item}
+
+ )}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/combobox-with-clear.tsx b/apps/v4/examples/radix/combobox-with-clear.tsx
new file mode 100644
index 000000000..81c47bfda
--- /dev/null
+++ b/apps/v4/examples/radix/combobox-with-clear.tsx
@@ -0,0 +1,36 @@
+import { Button } from "@/examples/radix/ui/button"
+import {
+ Combobox,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxInput,
+ ComboboxItem,
+ ComboboxList,
+} from "@/examples/radix/ui/combobox"
+import { Select } from "@/examples/radix/ui/select"
+
+const frameworks = [
+ "Next.js",
+ "SvelteKit",
+ "Nuxt.js",
+ "Remix",
+ "Astro",
+] as const
+
+export function ComboboxWithClear() {
+ return (
+
+
+
+ No items found.
+
+ {(item) => (
+
+ {item}
+
+ )}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/combobox-with-custom-items.tsx b/apps/v4/examples/radix/combobox-with-custom-items.tsx
new file mode 100644
index 000000000..a87fb9c74
--- /dev/null
+++ b/apps/v4/examples/radix/combobox-with-custom-items.tsx
@@ -0,0 +1,456 @@
+import {
+ Combobox,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxInput,
+ ComboboxItem,
+ ComboboxList,
+} from "@/examples/radix/ui/combobox"
+import {
+ Item,
+ ItemContent,
+ ItemDescription,
+ ItemTitle,
+} from "@/examples/radix/ui/item"
+import { Select } from "@/examples/radix/ui/select"
+
+const countries = [
+ { code: "", value: "", continent: "", label: "Select country" },
+ { code: "af", value: "afghanistan", label: "Afghanistan", continent: "Asia" },
+ { code: "al", value: "albania", label: "Albania", continent: "Europe" },
+ { code: "dz", value: "algeria", label: "Algeria", continent: "Africa" },
+ { code: "ad", value: "andorra", label: "Andorra", continent: "Europe" },
+ { code: "ao", value: "angola", label: "Angola", continent: "Africa" },
+ {
+ code: "ar",
+ value: "argentina",
+ label: "Argentina",
+ continent: "South America",
+ },
+ { code: "am", value: "armenia", label: "Armenia", continent: "Asia" },
+ { code: "au", value: "australia", label: "Australia", continent: "Oceania" },
+ { code: "at", value: "austria", label: "Austria", continent: "Europe" },
+ { code: "az", value: "azerbaijan", label: "Azerbaijan", continent: "Asia" },
+ {
+ code: "bs",
+ value: "bahamas",
+ label: "Bahamas",
+ continent: "North America",
+ },
+ { code: "bh", value: "bahrain", label: "Bahrain", continent: "Asia" },
+ { code: "bd", value: "bangladesh", label: "Bangladesh", continent: "Asia" },
+ {
+ code: "bb",
+ value: "barbados",
+ label: "Barbados",
+ continent: "North America",
+ },
+ { code: "by", value: "belarus", label: "Belarus", continent: "Europe" },
+ { code: "be", value: "belgium", label: "Belgium", continent: "Europe" },
+ { code: "bz", value: "belize", label: "Belize", continent: "North America" },
+ { code: "bj", value: "benin", label: "Benin", continent: "Africa" },
+ { code: "bt", value: "bhutan", label: "Bhutan", continent: "Asia" },
+ {
+ code: "bo",
+ value: "bolivia",
+ label: "Bolivia",
+ continent: "South America",
+ },
+ {
+ code: "ba",
+ value: "bosnia-and-herzegovina",
+ label: "Bosnia and Herzegovina",
+ continent: "Europe",
+ },
+ { code: "bw", value: "botswana", label: "Botswana", continent: "Africa" },
+ { code: "br", value: "brazil", label: "Brazil", continent: "South America" },
+ { code: "bn", value: "brunei", label: "Brunei", continent: "Asia" },
+ { code: "bg", value: "bulgaria", label: "Bulgaria", continent: "Europe" },
+ {
+ code: "bf",
+ value: "burkina-faso",
+ label: "Burkina Faso",
+ continent: "Africa",
+ },
+ { code: "bi", value: "burundi", label: "Burundi", continent: "Africa" },
+ { code: "kh", value: "cambodia", label: "Cambodia", continent: "Asia" },
+ { code: "cm", value: "cameroon", label: "Cameroon", continent: "Africa" },
+ { code: "ca", value: "canada", label: "Canada", continent: "North America" },
+ { code: "cv", value: "cape-verde", label: "Cape Verde", continent: "Africa" },
+ {
+ code: "cf",
+ value: "central-african-republic",
+ label: "Central African Republic",
+ continent: "Africa",
+ },
+ { code: "td", value: "chad", label: "Chad", continent: "Africa" },
+ { code: "cl", value: "chile", label: "Chile", continent: "South America" },
+ { code: "cn", value: "china", label: "China", continent: "Asia" },
+ {
+ code: "co",
+ value: "colombia",
+ label: "Colombia",
+ continent: "South America",
+ },
+ { code: "km", value: "comoros", label: "Comoros", continent: "Africa" },
+ { code: "cg", value: "congo", label: "Congo", continent: "Africa" },
+ {
+ code: "cr",
+ value: "costa-rica",
+ label: "Costa Rica",
+ continent: "North America",
+ },
+ { code: "hr", value: "croatia", label: "Croatia", continent: "Europe" },
+ { code: "cu", value: "cuba", label: "Cuba", continent: "North America" },
+ { code: "cy", value: "cyprus", label: "Cyprus", continent: "Asia" },
+ {
+ code: "cz",
+ value: "czech-republic",
+ label: "Czech Republic",
+ continent: "Europe",
+ },
+ { code: "dk", value: "denmark", label: "Denmark", continent: "Europe" },
+ { code: "dj", value: "djibouti", label: "Djibouti", continent: "Africa" },
+ {
+ code: "dm",
+ value: "dominica",
+ label: "Dominica",
+ continent: "North America",
+ },
+ {
+ code: "do",
+ value: "dominican-republic",
+ label: "Dominican Republic",
+ continent: "North America",
+ },
+ {
+ code: "ec",
+ value: "ecuador",
+ label: "Ecuador",
+ continent: "South America",
+ },
+ { code: "eg", value: "egypt", label: "Egypt", continent: "Africa" },
+ {
+ code: "sv",
+ value: "el-salvador",
+ label: "El Salvador",
+ continent: "North America",
+ },
+ {
+ code: "gq",
+ value: "equatorial-guinea",
+ label: "Equatorial Guinea",
+ continent: "Africa",
+ },
+ { code: "er", value: "eritrea", label: "Eritrea", continent: "Africa" },
+ { code: "ee", value: "estonia", label: "Estonia", continent: "Europe" },
+ { code: "et", value: "ethiopia", label: "Ethiopia", continent: "Africa" },
+ { code: "fj", value: "fiji", label: "Fiji", continent: "Oceania" },
+ { code: "fi", value: "finland", label: "Finland", continent: "Europe" },
+ { code: "fr", value: "france", label: "France", continent: "Europe" },
+ { code: "ga", value: "gabon", label: "Gabon", continent: "Africa" },
+ { code: "gm", value: "gambia", label: "Gambia", continent: "Africa" },
+ { code: "ge", value: "georgia", label: "Georgia", continent: "Asia" },
+ { code: "de", value: "germany", label: "Germany", continent: "Europe" },
+ { code: "gh", value: "ghana", label: "Ghana", continent: "Africa" },
+ { code: "gr", value: "greece", label: "Greece", continent: "Europe" },
+ {
+ code: "gd",
+ value: "grenada",
+ label: "Grenada",
+ continent: "North America",
+ },
+ {
+ code: "gt",
+ value: "guatemala",
+ label: "Guatemala",
+ continent: "North America",
+ },
+ { code: "gn", value: "guinea", label: "Guinea", continent: "Africa" },
+ {
+ code: "gw",
+ value: "guinea-bissau",
+ label: "Guinea-Bissau",
+ continent: "Africa",
+ },
+ { code: "gy", value: "guyana", label: "Guyana", continent: "South America" },
+ { code: "ht", value: "haiti", label: "Haiti", continent: "North America" },
+ {
+ code: "hn",
+ value: "honduras",
+ label: "Honduras",
+ continent: "North America",
+ },
+ { code: "hu", value: "hungary", label: "Hungary", continent: "Europe" },
+ { code: "is", value: "iceland", label: "Iceland", continent: "Europe" },
+ { code: "in", value: "india", label: "India", continent: "Asia" },
+ { code: "id", value: "indonesia", label: "Indonesia", continent: "Asia" },
+ { code: "ir", value: "iran", label: "Iran", continent: "Asia" },
+ { code: "iq", value: "iraq", label: "Iraq", continent: "Asia" },
+ { code: "ie", value: "ireland", label: "Ireland", continent: "Europe" },
+ { code: "il", value: "israel", label: "Israel", continent: "Asia" },
+ { code: "it", value: "italy", label: "Italy", continent: "Europe" },
+ {
+ code: "jm",
+ value: "jamaica",
+ label: "Jamaica",
+ continent: "North America",
+ },
+ { code: "jp", value: "japan", label: "Japan", continent: "Asia" },
+ { code: "jo", value: "jordan", label: "Jordan", continent: "Asia" },
+ { code: "kz", value: "kazakhstan", label: "Kazakhstan", continent: "Asia" },
+ { code: "ke", value: "kenya", label: "Kenya", continent: "Africa" },
+ { code: "kw", value: "kuwait", label: "Kuwait", continent: "Asia" },
+ { code: "kg", value: "kyrgyzstan", label: "Kyrgyzstan", continent: "Asia" },
+ { code: "la", value: "laos", label: "Laos", continent: "Asia" },
+ { code: "lv", value: "latvia", label: "Latvia", continent: "Europe" },
+ { code: "lb", value: "lebanon", label: "Lebanon", continent: "Asia" },
+ { code: "ls", value: "lesotho", label: "Lesotho", continent: "Africa" },
+ { code: "lr", value: "liberia", label: "Liberia", continent: "Africa" },
+ { code: "ly", value: "libya", label: "Libya", continent: "Africa" },
+ {
+ code: "li",
+ value: "liechtenstein",
+ label: "Liechtenstein",
+ continent: "Europe",
+ },
+ { code: "lt", value: "lithuania", label: "Lithuania", continent: "Europe" },
+ { code: "lu", value: "luxembourg", label: "Luxembourg", continent: "Europe" },
+ { code: "mg", value: "madagascar", label: "Madagascar", continent: "Africa" },
+ { code: "mw", value: "malawi", label: "Malawi", continent: "Africa" },
+ { code: "my", value: "malaysia", label: "Malaysia", continent: "Asia" },
+ { code: "mv", value: "maldives", label: "Maldives", continent: "Asia" },
+ { code: "ml", value: "mali", label: "Mali", continent: "Africa" },
+ { code: "mt", value: "malta", label: "Malta", continent: "Europe" },
+ {
+ code: "mh",
+ value: "marshall-islands",
+ label: "Marshall Islands",
+ continent: "Oceania",
+ },
+ { code: "mr", value: "mauritania", label: "Mauritania", continent: "Africa" },
+ { code: "mu", value: "mauritius", label: "Mauritius", continent: "Africa" },
+ { code: "mx", value: "mexico", label: "Mexico", continent: "North America" },
+ {
+ code: "fm",
+ value: "micronesia",
+ label: "Micronesia",
+ continent: "Oceania",
+ },
+ { code: "md", value: "moldova", label: "Moldova", continent: "Europe" },
+ { code: "mc", value: "monaco", label: "Monaco", continent: "Europe" },
+ { code: "mn", value: "mongolia", label: "Mongolia", continent: "Asia" },
+ { code: "me", value: "montenegro", label: "Montenegro", continent: "Europe" },
+ { code: "ma", value: "morocco", label: "Morocco", continent: "Africa" },
+ { code: "mz", value: "mozambique", label: "Mozambique", continent: "Africa" },
+ { code: "mm", value: "myanmar", label: "Myanmar", continent: "Asia" },
+ { code: "na", value: "namibia", label: "Namibia", continent: "Africa" },
+ { code: "nr", value: "nauru", label: "Nauru", continent: "Oceania" },
+ { code: "np", value: "nepal", label: "Nepal", continent: "Asia" },
+ {
+ code: "nl",
+ value: "netherlands",
+ label: "Netherlands",
+ continent: "Europe",
+ },
+ {
+ code: "nz",
+ value: "new-zealand",
+ label: "New Zealand",
+ continent: "Oceania",
+ },
+ {
+ code: "ni",
+ value: "nicaragua",
+ label: "Nicaragua",
+ continent: "North America",
+ },
+ { code: "ne", value: "niger", label: "Niger", continent: "Africa" },
+ { code: "ng", value: "nigeria", label: "Nigeria", continent: "Africa" },
+ { code: "kp", value: "north-korea", label: "North Korea", continent: "Asia" },
+ {
+ code: "mk",
+ value: "north-macedonia",
+ label: "North Macedonia",
+ continent: "Europe",
+ },
+ { code: "no", value: "norway", label: "Norway", continent: "Europe" },
+ { code: "om", value: "oman", label: "Oman", continent: "Asia" },
+ { code: "pk", value: "pakistan", label: "Pakistan", continent: "Asia" },
+ { code: "pw", value: "palau", label: "Palau", continent: "Oceania" },
+ { code: "ps", value: "palestine", label: "Palestine", continent: "Asia" },
+ { code: "pa", value: "panama", label: "Panama", continent: "North America" },
+ {
+ code: "pg",
+ value: "papua-new-guinea",
+ label: "Papua New Guinea",
+ continent: "Oceania",
+ },
+ {
+ code: "py",
+ value: "paraguay",
+ label: "Paraguay",
+ continent: "South America",
+ },
+ { code: "pe", value: "peru", label: "Peru", continent: "South America" },
+ { code: "ph", value: "philippines", label: "Philippines", continent: "Asia" },
+ { code: "pl", value: "poland", label: "Poland", continent: "Europe" },
+ { code: "pt", value: "portugal", label: "Portugal", continent: "Europe" },
+ { code: "qa", value: "qatar", label: "Qatar", continent: "Asia" },
+ { code: "ro", value: "romania", label: "Romania", continent: "Europe" },
+ { code: "ru", value: "russia", label: "Russia", continent: "Europe" },
+ { code: "rw", value: "rwanda", label: "Rwanda", continent: "Africa" },
+ { code: "ws", value: "samoa", label: "Samoa", continent: "Oceania" },
+ { code: "sm", value: "san-marino", label: "San Marino", continent: "Europe" },
+ {
+ code: "sa",
+ value: "saudi-arabia",
+ label: "Saudi Arabia",
+ continent: "Asia",
+ },
+ { code: "sn", value: "senegal", label: "Senegal", continent: "Africa" },
+ { code: "rs", value: "serbia", label: "Serbia", continent: "Europe" },
+ { code: "sc", value: "seychelles", label: "Seychelles", continent: "Africa" },
+ {
+ code: "sl",
+ value: "sierra-leone",
+ label: "Sierra Leone",
+ continent: "Africa",
+ },
+ { code: "sg", value: "singapore", label: "Singapore", continent: "Asia" },
+ { code: "sk", value: "slovakia", label: "Slovakia", continent: "Europe" },
+ { code: "si", value: "slovenia", label: "Slovenia", continent: "Europe" },
+ {
+ code: "sb",
+ value: "solomon-islands",
+ label: "Solomon Islands",
+ continent: "Oceania",
+ },
+ { code: "so", value: "somalia", label: "Somalia", continent: "Africa" },
+ {
+ code: "za",
+ value: "south-africa",
+ label: "South Africa",
+ continent: "Africa",
+ },
+ { code: "kr", value: "south-korea", label: "South Korea", continent: "Asia" },
+ {
+ code: "ss",
+ value: "south-sudan",
+ label: "South Sudan",
+ continent: "Africa",
+ },
+ { code: "es", value: "spain", label: "Spain", continent: "Europe" },
+ { code: "lk", value: "sri-lanka", label: "Sri Lanka", continent: "Asia" },
+ { code: "sd", value: "sudan", label: "Sudan", continent: "Africa" },
+ {
+ code: "sr",
+ value: "suriname",
+ label: "Suriname",
+ continent: "South America",
+ },
+ { code: "se", value: "sweden", label: "Sweden", continent: "Europe" },
+ {
+ code: "ch",
+ value: "switzerland",
+ label: "Switzerland",
+ continent: "Europe",
+ },
+ { code: "sy", value: "syria", label: "Syria", continent: "Asia" },
+ { code: "tw", value: "taiwan", label: "Taiwan", continent: "Asia" },
+ { code: "tj", value: "tajikistan", label: "Tajikistan", continent: "Asia" },
+ { code: "tz", value: "tanzania", label: "Tanzania", continent: "Africa" },
+ { code: "th", value: "thailand", label: "Thailand", continent: "Asia" },
+ { code: "tl", value: "timor-leste", label: "Timor-Leste", continent: "Asia" },
+ { code: "tg", value: "togo", label: "Togo", continent: "Africa" },
+ { code: "to", value: "tonga", label: "Tonga", continent: "Oceania" },
+ {
+ code: "tt",
+ value: "trinidad-and-tobago",
+ label: "Trinidad and Tobago",
+ continent: "North America",
+ },
+ { code: "tn", value: "tunisia", label: "Tunisia", continent: "Africa" },
+ { code: "tr", value: "turkey", label: "Turkey", continent: "Asia" },
+ {
+ code: "tm",
+ value: "turkmenistan",
+ label: "Turkmenistan",
+ continent: "Asia",
+ },
+ { code: "tv", value: "tuvalu", label: "Tuvalu", continent: "Oceania" },
+ { code: "ug", value: "uganda", label: "Uganda", continent: "Africa" },
+ { code: "ua", value: "ukraine", label: "Ukraine", continent: "Europe" },
+ {
+ code: "ae",
+ value: "united-arab-emirates",
+ label: "United Arab Emirates",
+ continent: "Asia",
+ },
+ {
+ code: "gb",
+ value: "united-kingdom",
+ label: "United Kingdom",
+ continent: "Europe",
+ },
+ {
+ code: "us",
+ value: "united-states",
+ label: "United States",
+ continent: "North America",
+ },
+ {
+ code: "uy",
+ value: "uruguay",
+ label: "Uruguay",
+ continent: "South America",
+ },
+ { code: "uz", value: "uzbekistan", label: "Uzbekistan", continent: "Asia" },
+ { code: "vu", value: "vanuatu", label: "Vanuatu", continent: "Oceania" },
+ {
+ code: "va",
+ value: "vatican-city",
+ label: "Vatican City",
+ continent: "Europe",
+ },
+ {
+ code: "ve",
+ value: "venezuela",
+ label: "Venezuela",
+ continent: "South America",
+ },
+ { code: "vn", value: "vietnam", label: "Vietnam", continent: "Asia" },
+ { code: "ye", value: "yemen", label: "Yemen", continent: "Asia" },
+ { code: "zm", value: "zambia", label: "Zambia", continent: "Africa" },
+ { code: "zw", value: "zimbabwe", label: "Zimbabwe", continent: "Africa" },
+]
+
+export function ComboboxWithCustomItems() {
+ return (
+ country.code !== "")}
+ itemToStringValue={(country: (typeof countries)[number]) => country.label}
+ >
+
+
+ No countries found.
+
+ {(country) => (
+
+ -
+
+
+ {country.label}
+
+
+ {country.continent} ({country.code})
+
+
+
+
+ )}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/combobox-with-form.tsx b/apps/v4/examples/radix/combobox-with-form.tsx
new file mode 100644
index 000000000..4523c0012
--- /dev/null
+++ b/apps/v4/examples/radix/combobox-with-form.tsx
@@ -0,0 +1,72 @@
+import * as React from "react"
+import { Button } from "@/examples/radix/ui/button"
+import { Card, CardContent, CardFooter } from "@/examples/radix/ui/card"
+import {
+ Combobox,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxInput,
+ ComboboxItem,
+ ComboboxList,
+} from "@/examples/radix/ui/combobox"
+import { Field, FieldGroup, FieldLabel } from "@/examples/radix/ui/field"
+import { Select } from "@/examples/radix/ui/select"
+import { toast } from "sonner"
+
+const frameworks = [
+ "Next.js",
+ "SvelteKit",
+ "Nuxt.js",
+ "Remix",
+ "Astro",
+] as const
+
+export function ComboboxWithForm() {
+ const handleSubmit = (event: React.FormEvent) => {
+ event.preventDefault()
+ const formData = new FormData(event.target as HTMLFormElement)
+ const framework = formData.get("framework") as string
+ toast(`You selected ${framework} as your framework.`)
+ }
+
+ return (
+
+
+
+
+
+
+ Submit
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/combobox-with-groups-and-separator.tsx b/apps/v4/examples/radix/combobox-with-groups-and-separator.tsx
new file mode 100644
index 000000000..4ae172174
--- /dev/null
+++ b/apps/v4/examples/radix/combobox-with-groups-and-separator.tsx
@@ -0,0 +1,75 @@
+import {
+ Combobox,
+ ComboboxCollection,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxGroup,
+ ComboboxInput,
+ ComboboxItem,
+ ComboboxLabel,
+ ComboboxList,
+ ComboboxSeparator,
+} from "@/examples/radix/ui/combobox"
+import { Select } from "@/examples/radix/ui/select"
+
+const timezones = [
+ {
+ value: "Americas",
+ items: [
+ "(GMT-5) New York",
+ "(GMT-8) Los Angeles",
+ "(GMT-6) Chicago",
+ "(GMT-5) Toronto",
+ "(GMT-8) Vancouver",
+ "(GMT-3) São Paulo",
+ ],
+ },
+ {
+ value: "Europe",
+ items: [
+ "(GMT+0) London",
+ "(GMT+1) Paris",
+ "(GMT+1) Berlin",
+ "(GMT+1) Rome",
+ "(GMT+1) Madrid",
+ "(GMT+1) Amsterdam",
+ ],
+ },
+ {
+ value: "Asia/Pacific",
+ items: [
+ "(GMT+9) Tokyo",
+ "(GMT+8) Shanghai",
+ "(GMT+8) Singapore",
+ "(GMT+4) Dubai",
+ "(GMT+11) Sydney",
+ "(GMT+9) Seoul",
+ ],
+ },
+] as const
+
+export function ComboboxWithGroupsAndSeparator() {
+ return (
+
+
+
+ No timezones found.
+
+ {(group) => (
+
+ {group.value}
+
+ {(item) => (
+
+ {item}
+
+ )}
+
+
+
+ )}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/combobox-with-groups.tsx b/apps/v4/examples/radix/combobox-with-groups.tsx
new file mode 100644
index 000000000..64557b874
--- /dev/null
+++ b/apps/v4/examples/radix/combobox-with-groups.tsx
@@ -0,0 +1,73 @@
+import {
+ Combobox,
+ ComboboxCollection,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxGroup,
+ ComboboxInput,
+ ComboboxItem,
+ ComboboxLabel,
+ ComboboxList,
+} from "@/examples/radix/ui/combobox"
+import { Select } from "@/examples/radix/ui/select"
+
+const timezones = [
+ {
+ value: "Americas",
+ items: [
+ "(GMT-5) New York",
+ "(GMT-8) Los Angeles",
+ "(GMT-6) Chicago",
+ "(GMT-5) Toronto",
+ "(GMT-8) Vancouver",
+ "(GMT-3) São Paulo",
+ ],
+ },
+ {
+ value: "Europe",
+ items: [
+ "(GMT+0) London",
+ "(GMT+1) Paris",
+ "(GMT+1) Berlin",
+ "(GMT+1) Rome",
+ "(GMT+1) Madrid",
+ "(GMT+1) Amsterdam",
+ ],
+ },
+ {
+ value: "Asia/Pacific",
+ items: [
+ "(GMT+9) Tokyo",
+ "(GMT+8) Shanghai",
+ "(GMT+8) Singapore",
+ "(GMT+4) Dubai",
+ "(GMT+11) Sydney",
+ "(GMT+9) Seoul",
+ ],
+ },
+] as const
+
+export function ComboboxWithGroups() {
+ return (
+
+
+
+ No timezones found.
+
+ {(group) => (
+
+ {group.value}
+
+ {(item) => (
+
+ {item}
+
+ )}
+
+
+ )}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/combobox-with-other-inputs.tsx b/apps/v4/examples/radix/combobox-with-other-inputs.tsx
new file mode 100644
index 000000000..298140604
--- /dev/null
+++ b/apps/v4/examples/radix/combobox-with-other-inputs.tsx
@@ -0,0 +1,80 @@
+import { Button } from "@/examples/radix/ui/button"
+import {
+ Combobox,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxInput,
+ ComboboxItem,
+ ComboboxList,
+} from "@/examples/radix/ui/combobox"
+import { Input } from "@/examples/radix/ui/input"
+import {
+ InputGroup,
+ InputGroupAddon,
+ InputGroupInput,
+} from "@/examples/radix/ui/input-group"
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/radix/ui/select"
+import { ChevronDownIcon } from "lucide-react"
+
+const frameworks = [
+ "Next.js",
+ "SvelteKit",
+ "Nuxt.js",
+ "Remix",
+ "Astro",
+] as const
+
+export function ComboboxWithOtherInputs() {
+ return (
+ <>
+
+
+
+ No items found.
+
+ {(item) => (
+
+ {item}
+
+ )}
+
+
+
+
+
+
+
+
+
+ {frameworks.map((framework) => (
+
+ {framework}
+
+ ))}
+
+
+
+
+ Select a framework
+
+
+
+
+
+
+
+
+
+ >
+ )
+}
diff --git a/apps/v4/examples/radix/comboxbox-input-addon.tsx b/apps/v4/examples/radix/comboxbox-input-addon.tsx
new file mode 100644
index 000000000..e7bd4c45c
--- /dev/null
+++ b/apps/v4/examples/radix/comboxbox-input-addon.tsx
@@ -0,0 +1,80 @@
+import {
+ Combobox,
+ ComboboxCollection,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxGroup,
+ ComboboxInput,
+ ComboboxItem,
+ ComboboxLabel,
+ ComboboxList,
+} from "@/examples/radix/ui/combobox"
+import { Input } from "@/examples/radix/ui/input"
+import { InputGroup, InputGroupAddon } from "@/examples/radix/ui/input-group"
+import { Select } from "@/examples/radix/ui/select"
+import { GlobeIcon } from "lucide-react"
+
+const timezones = [
+ {
+ value: "Americas",
+ items: [
+ "(GMT-5) New York",
+ "(GMT-8) Los Angeles",
+ "(GMT-6) Chicago",
+ "(GMT-5) Toronto",
+ "(GMT-8) Vancouver",
+ "(GMT-3) São Paulo",
+ ],
+ },
+ {
+ value: "Europe",
+ items: [
+ "(GMT+0) London",
+ "(GMT+1) Paris",
+ "(GMT+1) Berlin",
+ "(GMT+1) Rome",
+ "(GMT+1) Madrid",
+ "(GMT+1) Amsterdam",
+ ],
+ },
+ {
+ value: "Asia/Pacific",
+ items: [
+ "(GMT+9) Tokyo",
+ "(GMT+8) Shanghai",
+ "(GMT+8) Singapore",
+ "(GMT+4) Dubai",
+ "(GMT+11) Sydney",
+ "(GMT+9) Seoul",
+ ],
+ },
+] as const
+
+export function ComboxboxInputAddon() {
+ return (
+
+
+
+
+
+
+
+ No timezones found.
+
+ {(group) => (
+
+ {group.value}
+
+ {(item) => (
+
+ {item}
+
+ )}
+
+
+ )}
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/command-basic.tsx b/apps/v4/examples/radix/command-basic.tsx
new file mode 100644
index 000000000..fab25d251
--- /dev/null
+++ b/apps/v4/examples/radix/command-basic.tsx
@@ -0,0 +1,38 @@
+"use client"
+
+import * as React from "react"
+import { Button } from "@/examples/radix/ui/button"
+import {
+ Command,
+ CommandDialog,
+ CommandEmpty,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+ CommandList,
+} from "@/examples/radix/ui/command"
+
+export function CommandBasic() {
+ const [open, setOpen] = React.useState(false)
+
+ return (
+
+ setOpen(true)} variant="outline" className="w-fit">
+ Open Menu
+
+
+
+
+
+ No results found.
+
+ Calendar
+ Search Emoji
+ Calculator
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/command-many-items.tsx b/apps/v4/examples/radix/command-many-items.tsx
new file mode 100644
index 000000000..3ad311075
--- /dev/null
+++ b/apps/v4/examples/radix/command-many-items.tsx
@@ -0,0 +1,181 @@
+"use client"
+
+import * as React from "react"
+import { Button } from "@/examples/radix/ui/button"
+import {
+ Command,
+ CommandDialog,
+ CommandEmpty,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+ CommandList,
+ CommandSeparator,
+ CommandShortcut,
+} from "@/examples/radix/ui/command"
+import {
+ BellIcon,
+ CalculatorIcon,
+ CalendarIcon,
+ ClipboardPasteIcon,
+ CodeIcon,
+ CopyIcon,
+ CreditCardIcon,
+ FileTextIcon,
+ FolderIcon,
+ FolderPlusIcon,
+ HelpCircleIcon,
+ HomeIcon,
+ ImageIcon,
+ InboxIcon,
+ LayoutGridIcon,
+ ListIcon,
+ PlusIcon,
+ ScissorsIcon,
+ SettingsIcon,
+ TrashIcon,
+ UserIcon,
+ ZoomInIcon,
+ ZoomOutIcon,
+} from "lucide-react"
+
+export function CommandManyItems() {
+ const [open, setOpen] = React.useState(false)
+
+ return (
+
+
setOpen(true)} variant="outline" className="w-fit">
+ Open Menu
+
+
+
+
+
+ No results found.
+
+
+
+ Home
+ ⌘H
+
+
+
+ Inbox
+ ⌘I
+
+
+
+ Documents
+ ⌘D
+
+
+
+ Folders
+ ⌘F
+
+
+
+
+
+
+ New File
+ ⌘N
+
+
+
+ New Folder
+ ⇧⌘N
+
+
+
+ Copy
+ ⌘C
+
+
+
+ Cut
+ ⌘X
+
+
+
+ Paste
+ ⌘V
+
+
+
+ Delete
+ ⌫
+
+
+
+
+
+
+ Grid View
+
+
+
+ List View
+
+
+
+ Zoom In
+ ⌘+
+
+
+
+ Zoom Out
+ ⌘-
+
+
+
+
+
+
+ Profile
+ ⌘P
+
+
+
+ Billing
+ ⌘B
+
+
+
+ Settings
+ ⌘S
+
+
+
+ Notifications
+
+
+
+ Help & Support
+
+
+
+
+
+
+ Calculator
+
+
+
+ Calendar
+
+
+
+ Image Editor
+
+
+
+ Code Editor
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/command-with-groups.tsx b/apps/v4/examples/radix/command-with-groups.tsx
new file mode 100644
index 000000000..640b6ef27
--- /dev/null
+++ b/apps/v4/examples/radix/command-with-groups.tsx
@@ -0,0 +1,75 @@
+"use client"
+
+import * as React from "react"
+import { Button } from "@/examples/radix/ui/button"
+import {
+ Command,
+ CommandDialog,
+ CommandEmpty,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+ CommandList,
+ CommandSeparator,
+ CommandShortcut,
+} from "@/examples/radix/ui/command"
+import {
+ CalculatorIcon,
+ CalendarIcon,
+ CreditCardIcon,
+ SettingsIcon,
+ SmileIcon,
+ UserIcon,
+} from "lucide-react"
+
+export function CommandWithGroups() {
+ const [open, setOpen] = React.useState(false)
+
+ return (
+
+ setOpen(true)} variant="outline" className="w-fit">
+ Open Menu
+
+
+
+
+
+ No results found.
+
+
+
+ Calendar
+
+
+
+ Search Emoji
+
+
+
+ Calculator
+
+
+
+
+
+
+ Profile
+ ⌘P
+
+
+
+ Billing
+ ⌘B
+
+
+
+ Settings
+ ⌘S
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/command-with-shortcuts.tsx b/apps/v4/examples/radix/command-with-shortcuts.tsx
new file mode 100644
index 000000000..0cf1ce2f9
--- /dev/null
+++ b/apps/v4/examples/radix/command-with-shortcuts.tsx
@@ -0,0 +1,52 @@
+"use client"
+
+import * as React from "react"
+import { Button } from "@/examples/radix/ui/button"
+import {
+ Command,
+ CommandDialog,
+ CommandEmpty,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+ CommandList,
+ CommandShortcut,
+} from "@/examples/radix/ui/command"
+import { CreditCardIcon, SettingsIcon, UserIcon } from "lucide-react"
+
+export function CommandWithShortcuts() {
+ const [open, setOpen] = React.useState(false)
+
+ return (
+
+ setOpen(true)} variant="outline" className="w-fit">
+ Open Menu
+
+
+
+
+
+ No results found.
+
+
+
+ Profile
+ ⌘P
+
+
+
+ Billing
+ ⌘B
+
+
+
+ Settings
+ ⌘S
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/context-menu-basic.tsx b/apps/v4/examples/radix/context-menu-basic.tsx
new file mode 100644
index 000000000..b37b37bd0
--- /dev/null
+++ b/apps/v4/examples/radix/context-menu-basic.tsx
@@ -0,0 +1,24 @@
+import {
+ ContextMenu,
+ ContextMenuContent,
+ ContextMenuGroup,
+ ContextMenuItem,
+ ContextMenuTrigger,
+} from "@/examples/radix/ui/context-menu"
+
+export function ContextMenuBasic() {
+ return (
+
+
+ Right click here
+
+
+
+ Back
+ Forward
+ Reload
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/context-menu-in-dialog.tsx b/apps/v4/examples/radix/context-menu-in-dialog.tsx
new file mode 100644
index 000000000..8f99d1e7c
--- /dev/null
+++ b/apps/v4/examples/radix/context-menu-in-dialog.tsx
@@ -0,0 +1,87 @@
+import { Button } from "@/examples/radix/ui/button"
+import {
+ ContextMenu,
+ ContextMenuContent,
+ ContextMenuGroup,
+ ContextMenuItem,
+ ContextMenuSeparator,
+ ContextMenuSub,
+ ContextMenuSubContent,
+ ContextMenuSubTrigger,
+ ContextMenuTrigger,
+} from "@/examples/radix/ui/context-menu"
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogHeader,
+ DialogTitle,
+ DialogTrigger,
+} from "@/examples/radix/ui/dialog"
+import {
+ ClipboardPasteIcon,
+ CopyIcon,
+ ScissorsIcon,
+ TrashIcon,
+} from "lucide-react"
+
+export function ContextMenuInDialog() {
+ return (
+
+
+ Open Dialog
+
+
+
+ Context Menu Example
+
+ Right click on the area below to see the context menu.
+
+
+
+
+ Right click here
+
+
+
+
+
+ Copy
+
+
+
+ Cut
+
+
+
+ Paste
+
+
+
+
+ More Options
+
+
+ Save Page...
+ Create Shortcut...
+ Name Window...
+
+
+
+ Developer Tools
+
+
+
+
+
+
+
+ Delete
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/context-menu-with-checkboxes.tsx b/apps/v4/examples/radix/context-menu-with-checkboxes.tsx
new file mode 100644
index 000000000..3e740ca2b
--- /dev/null
+++ b/apps/v4/examples/radix/context-menu-with-checkboxes.tsx
@@ -0,0 +1,46 @@
+"use client"
+
+import * as React from "react"
+import {
+ ContextMenu,
+ ContextMenuCheckboxItem,
+ ContextMenuContent,
+ ContextMenuGroup,
+ ContextMenuTrigger,
+} from "@/examples/radix/ui/context-menu"
+
+export function ContextMenuWithCheckboxes() {
+ const [showBookmarksBar, setShowBookmarksBar] = React.useState(true)
+ const [showFullUrls, setShowFullUrls] = React.useState(false)
+ const [showDeveloperTools, setShowDeveloperTools] = React.useState(false)
+
+ return (
+
+
+ Right click here
+
+
+
+
+ Show Bookmarks Bar
+
+
+ Show Full URLs
+
+
+ Show Developer Tools
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/context-menu-with-destructive.tsx b/apps/v4/examples/radix/context-menu-with-destructive.tsx
new file mode 100644
index 000000000..5275a4e5a
--- /dev/null
+++ b/apps/v4/examples/radix/context-menu-with-destructive.tsx
@@ -0,0 +1,42 @@
+import {
+ ContextMenu,
+ ContextMenuContent,
+ ContextMenuGroup,
+ ContextMenuItem,
+ ContextMenuSeparator,
+ ContextMenuTrigger,
+} from "@/examples/radix/ui/context-menu"
+import { ArchiveIcon, PencilIcon, ShareIcon, TrashIcon } from "lucide-react"
+
+export function ContextMenuWithDestructive() {
+ return (
+
+
+ Right click here
+
+
+
+
+
+ Edit
+
+
+
+ Share
+
+
+
+
+
+
+ Archive
+
+
+
+ Delete
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/context-menu-with-groups.tsx b/apps/v4/examples/radix/context-menu-with-groups.tsx
new file mode 100644
index 000000000..40c6b0f2c
--- /dev/null
+++ b/apps/v4/examples/radix/context-menu-with-groups.tsx
@@ -0,0 +1,69 @@
+import {
+ ContextMenu,
+ ContextMenuContent,
+ ContextMenuGroup,
+ ContextMenuItem,
+ ContextMenuLabel,
+ ContextMenuSeparator,
+ ContextMenuShortcut,
+ ContextMenuTrigger,
+} from "@/examples/radix/ui/context-menu"
+
+export function ContextMenuWithGroups() {
+ return (
+
+
+ Right click here
+
+
+
+ File
+
+ New File
+ ⌘N
+
+
+ Open File
+ ⌘O
+
+
+ Save
+ ⌘S
+
+
+
+
+ Edit
+
+ Undo
+ ⌘Z
+
+
+ Redo
+ ⇧⌘Z
+
+
+
+ Cut
+ ⌘X
+
+
+ Copy
+ ⌘C
+
+
+ Paste
+ ⌘V
+
+
+
+
+
+ Delete
+ ⌫
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/context-menu-with-icons.tsx b/apps/v4/examples/radix/context-menu-with-icons.tsx
new file mode 100644
index 000000000..656381a91
--- /dev/null
+++ b/apps/v4/examples/radix/context-menu-with-icons.tsx
@@ -0,0 +1,47 @@
+import {
+ ContextMenu,
+ ContextMenuContent,
+ ContextMenuGroup,
+ ContextMenuItem,
+ ContextMenuSeparator,
+ ContextMenuTrigger,
+} from "@/examples/radix/ui/context-menu"
+import {
+ ClipboardPasteIcon,
+ CopyIcon,
+ ScissorsIcon,
+ TrashIcon,
+} from "lucide-react"
+
+export function ContextMenuWithIcons() {
+ return (
+
+
+ Right click here
+
+
+
+
+
+ Copy
+
+
+
+ Cut
+
+
+
+ Paste
+
+
+
+
+
+
+ Delete
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/context-menu-with-radio.tsx b/apps/v4/examples/radix/context-menu-with-radio.tsx
new file mode 100644
index 000000000..8012ecd30
--- /dev/null
+++ b/apps/v4/examples/radix/context-menu-with-radio.tsx
@@ -0,0 +1,46 @@
+"use client"
+
+import * as React from "react"
+import {
+ ContextMenu,
+ ContextMenuContent,
+ ContextMenuGroup,
+ ContextMenuLabel,
+ ContextMenuRadioGroup,
+ ContextMenuRadioItem,
+ ContextMenuSeparator,
+ ContextMenuTrigger,
+} from "@/examples/radix/ui/context-menu"
+
+export function ContextMenuWithRadio() {
+ const [user, setUser] = React.useState("pedro")
+ const [theme, setTheme] = React.useState("light")
+
+ return (
+
+
+ Right click here
+
+
+
+ People
+
+
+ Pedro Duarte
+
+ Colm Tuite
+
+
+
+
+ Theme
+
+ Light
+ Dark
+ System
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/context-menu-with-shortcuts.tsx b/apps/v4/examples/radix/context-menu-with-shortcuts.tsx
new file mode 100644
index 000000000..51988f5f2
--- /dev/null
+++ b/apps/v4/examples/radix/context-menu-with-shortcuts.tsx
@@ -0,0 +1,46 @@
+import {
+ ContextMenu,
+ ContextMenuContent,
+ ContextMenuGroup,
+ ContextMenuItem,
+ ContextMenuSeparator,
+ ContextMenuShortcut,
+ ContextMenuTrigger,
+} from "@/examples/radix/ui/context-menu"
+
+export function ContextMenuWithShortcuts() {
+ return (
+
+
+ Right click here
+
+
+
+
+ Back
+ ⌘[
+
+
+ Forward
+ ⌘]
+
+
+ Reload
+ ⌘R
+
+
+
+
+
+ Save
+ ⌘S
+
+
+ Save As...
+ ⇧⌘S
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/context-menu-with-sides.tsx b/apps/v4/examples/radix/context-menu-with-sides.tsx
new file mode 100644
index 000000000..11cfc0316
--- /dev/null
+++ b/apps/v4/examples/radix/context-menu-with-sides.tsx
@@ -0,0 +1,62 @@
+import {
+ ContextMenu,
+ ContextMenuContent,
+ ContextMenuGroup,
+ ContextMenuItem,
+ ContextMenuTrigger,
+} from "@/examples/radix/ui/context-menu"
+
+export function ContextMenuWithSides() {
+ return (
+
+
+
+ Right click (top)
+
+
+
+ Back
+ Forward
+ Reload
+
+
+
+
+
+ Right click (right)
+
+
+
+ Back
+ Forward
+ Reload
+
+
+
+
+
+ Right click (bottom)
+
+
+
+ Back
+ Forward
+ Reload
+
+
+
+
+
+ Right click (left)
+
+
+
+ Back
+ Forward
+ Reload
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/context-menu-with-submenu.tsx b/apps/v4/examples/radix/context-menu-with-submenu.tsx
new file mode 100644
index 000000000..bed4a5647
--- /dev/null
+++ b/apps/v4/examples/radix/context-menu-with-submenu.tsx
@@ -0,0 +1,52 @@
+import {
+ ContextMenu,
+ ContextMenuContent,
+ ContextMenuGroup,
+ ContextMenuItem,
+ ContextMenuSeparator,
+ ContextMenuShortcut,
+ ContextMenuSub,
+ ContextMenuSubContent,
+ ContextMenuSubTrigger,
+ ContextMenuTrigger,
+} from "@/examples/radix/ui/context-menu"
+
+export function ContextMenuWithSubmenu() {
+ return (
+
+
+ Right click here
+
+
+
+
+ Copy
+ ⌘C
+
+
+ Cut
+ ⌘X
+
+
+
+ More Tools
+
+
+ Save Page...
+ Create Shortcut...
+ Name Window...
+
+
+
+ Developer Tools
+
+
+
+ Delete
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/data-picker-with-dropdowns.tsx b/apps/v4/examples/radix/data-picker-with-dropdowns.tsx
new file mode 100644
index 000000000..6c10ce0a3
--- /dev/null
+++ b/apps/v4/examples/radix/data-picker-with-dropdowns.tsx
@@ -0,0 +1,56 @@
+"use client"
+
+import * as React from "react"
+import { Button } from "@/examples/radix/ui/button"
+import { Calendar } from "@/examples/radix/ui/calendar"
+import { Field, FieldLabel } from "@/examples/radix/ui/field"
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/examples/radix/ui/popover"
+import { format } from "date-fns"
+import { ChevronDownIcon } from "lucide-react"
+
+export function DataPickerWithDropdowns() {
+ const [date, setDate] = React.useState()
+ const [open, setOpen] = React.useState(false)
+
+ return (
+
+
+
+ Date
+
+
+
+ {date ? format(date, "PPP") : Pick a date }
+
+
+
+
+
+
+ setOpen(false)}
+ >
+ Done
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/date-picker-simple.tsx b/apps/v4/examples/radix/date-picker-simple.tsx
new file mode 100644
index 000000000..68d168742
--- /dev/null
+++ b/apps/v4/examples/radix/date-picker-simple.tsx
@@ -0,0 +1,38 @@
+"use client"
+
+import * as React from "react"
+import { Button } from "@/examples/radix/ui/button"
+import { Calendar } from "@/examples/radix/ui/calendar"
+import { Field, FieldLabel } from "@/examples/radix/ui/field"
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/examples/radix/ui/popover"
+import { format } from "date-fns"
+import { CalendarIcon } from "lucide-react"
+
+export function DatePickerSimple() {
+ const [date, setDate] = React.useState()
+
+ return (
+
+ Date
+
+
+
+
+ {date ? format(date, "PPP") : Pick a date }
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/date-picker-with-range.tsx b/apps/v4/examples/radix/date-picker-with-range.tsx
index 67948343b..fb717deff 100644
--- a/apps/v4/examples/radix/date-picker-with-range.tsx
+++ b/apps/v4/examples/radix/date-picker-with-range.tsx
@@ -3,6 +3,7 @@
import * as React from "react"
import { Button } from "@/examples/radix/ui/button"
import { Calendar } from "@/examples/radix/ui/calendar"
+import { Field, FieldLabel } from "@/examples/radix/ui/field"
import {
Popover,
PopoverContent,
@@ -12,27 +13,21 @@ import { addDays, format } from "date-fns"
import { CalendarIcon } from "lucide-react"
import { type DateRange } from "react-day-picker"
-import { cn } from "@/lib/utils"
-
-export function DatePickerWithRange({
- className,
-}: React.HTMLAttributes) {
+export function DatePickerWithRange() {
const [date, setDate] = React.useState({
- from: new Date(2022, 0, 20),
- to: addDays(new Date(2022, 0, 20), 20),
+ from: new Date(new Date().getFullYear(), 0, 20),
+ to: addDays(new Date(new Date().getFullYear(), 0, 20), 20),
})
return (
-
+
+ Date Picker Range
{date?.from ? (
@@ -51,7 +46,6 @@ export function DatePickerWithRange({
-
+
)
}
diff --git a/apps/v4/examples/radix/default-item-group.tsx b/apps/v4/examples/radix/default-item-group.tsx
new file mode 100644
index 000000000..f8e00aaab
--- /dev/null
+++ b/apps/v4/examples/radix/default-item-group.tsx
@@ -0,0 +1,32 @@
+import {
+ Item,
+ ItemContent,
+ ItemDescription,
+ ItemGroup,
+ ItemTitle,
+} from "@/examples/radix/ui/item"
+
+export function DefaultItemGroup() {
+ return (
+
+ -
+
+ Item 1
+ First item in the group.
+
+
+ -
+
+ Item 2
+ Second item in the group.
+
+
+ -
+
+ Item 3
+ Third item in the group.
+
+
+
+ )
+}
diff --git a/apps/v4/examples/radix/dialog-chat-settings.tsx b/apps/v4/examples/radix/dialog-chat-settings.tsx
new file mode 100644
index 000000000..a55e461ee
--- /dev/null
+++ b/apps/v4/examples/radix/dialog-chat-settings.tsx
@@ -0,0 +1,396 @@
+"use client"
+
+import * as React from "react"
+import { Button } from "@/examples/radix/ui/button"
+import { Checkbox } from "@/examples/radix/ui/checkbox"
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogHeader,
+ DialogTitle,
+ DialogTrigger,
+} from "@/examples/radix/ui/dialog"
+import {
+ Field,
+ FieldContent,
+ FieldDescription,
+ FieldGroup,
+ FieldLabel,
+ FieldSeparator,
+ FieldSet,
+ FieldTitle,
+} from "@/examples/radix/ui/field"
+import { Input } from "@/examples/radix/ui/input"
+import {
+ InputGroup,
+ InputGroupAddon,
+ InputGroupButton,
+ InputGroupInput,
+} from "@/examples/radix/ui/input-group"
+import { Kbd } from "@/examples/radix/ui/kbd"
+import {
+ NativeSelect,
+ NativeSelectOption,
+} from "@/examples/radix/ui/native-select"
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectSeparator,
+ SelectTrigger,
+ SelectValue,
+} from "@/examples/radix/ui/select"
+import { Switch } from "@/examples/radix/ui/switch"
+import {
+ Tabs,
+ TabsContent,
+ TabsList,
+ TabsTrigger,
+} from "@/examples/radix/ui/tabs"
+import { Textarea } from "@/examples/radix/ui/textarea"
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from "@/examples/radix/ui/tooltip"
+import { InfoIcon } from "lucide-react"
+
+const spokenLanguages = [
+ { label: "English", value: "en" },
+ { label: "Spanish", value: "es" },
+ { label: "French", value: "fr" },
+ { label: "German", value: "de" },
+ { label: "Italian", value: "it" },
+ { label: "Portuguese", value: "pt" },
+ { label: "Russian", value: "ru" },
+ { label: "Chinese", value: "zh" },
+ { label: "Japanese", value: "ja" },
+ { label: "Korean", value: "ko" },
+ { label: "Arabic", value: "ar" },
+ { label: "Hindi", value: "hi" },
+ { label: "Bengali", value: "bn" },
+ { label: "Telugu", value: "te" },
+ { label: "Marathi", value: "mr" },
+ { label: "Kannada", value: "kn" },
+ { label: "Malayalam", value: "ml" },
+]
+
+const voices = [
+ { label: "Samantha", value: "samantha" },
+ { label: "Alex", value: "alex" },
+ { label: "Fred", value: "fred" },
+ { label: "Victoria", value: "victoria" },
+ { label: "Tom", value: "tom" },
+ { label: "Karen", value: "karen" },
+ { label: "Sam", value: "sam" },
+ { label: "Daniel", value: "daniel" },
+]
+
+export function DialogChatSettings() {
+ const [tab, setTab] = React.useState("general")
+ const [theme, setTheme] = React.useState("system")
+ const [accentColor, setAccentColor] = React.useState("default")
+ const [spokenLanguage, setSpokenLanguage] = React.useState("en")
+ const [voice, setVoice] = React.useState("samantha")
+
+ return (
+
+
+ Chat Settings
+
+
+
+ Chat Settings
+
+ Customize your chat settings: theme, accent color, spoken language,
+ voice, personality, and custom instructions.
+
+
+
+
setTab(e.target.value)}
+ className="w-full md:hidden"
+ >
+ General
+
+ Notifications
+
+
+ Personalization
+
+ Security
+
+
+
+ General
+ Notifications
+ Personalization
+ Security
+
+
+
+
+
+
+ Theme
+
+