Compare commits

...

34 Commits

Author SHA1 Message Date
github-actions[bot]
061083006f chore(release): version packages (#4857)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-09-15 13:40:31 +04:00
Jack Herrington
1af66c2d08 Adding support for ~ in target specification (#4848)
* Adding support for ~ in target specification

* test(shadcn): add a test for srcDir false

* chore: changeset

---------

Co-authored-by: shadcn <m@shadcn.com>
2024-09-15 13:27:48 +04:00
shadcn
0993d98cc7 ci: update stale config (#4858) 2024-09-15 13:25:06 +04:00
Hichem Fantar
52d223393a (fix Input) choose file text color in dark mode (#4843)
This pull request fixes the issue with the choose file text color in dark mode. The changes ensure that the text color is correctly displayed in dark mode.

the reason this bug doesn't happen in the shadcn website is because it sets `color-scheme:dark` on the document;

this fix makes sure this always works even if color scheme isn't set.

Closes #4842

![image](https://github.com/user-attachments/assets/37cb3f2a-c1a7-49b3-8ef1-77823dd7bd45)

![image](https://github.com/user-attachments/assets/92913fec-5651-4cfc-8e16-2f12c06c33b8)
2024-09-15 09:20:19 +00:00
Shivang Rathore
207b69fe8d fix(cli): Ensure .scss files are considered in getTailwindCssFile (#4797)
* fix(cli): Ensure .scss files are considered in getTailwindCssFile

- Updated getTailwindCssFile function to include .scss files when checking for Tailwind CSS configuration.
- This change ensures that .scss files are properly identified and handled, improving compatibility with projects using SCSS.

* chore: add changeset

---------

Co-authored-by: shadcn <m@shadcn.com>
2024-09-15 12:55:08 +04:00
Rana Haris Ali
408760a93b fix: correct grammar in "path does not contain a package.json" message (#4815)
* fix: correct grammar in "path does not contain a package.json" message

* chore: add changeset

---------

Co-authored-by: shadcn <m@shadcn.com>
2024-09-15 12:51:23 +04:00
Devansh Mahant
a9ab7afebf Fix Incorrect Hook Import Path in Toast Component Example in ShadCN Docs (#4811)
#### Summary:
This pull request addresses a documentation error found in the ShadCN website's Toast component example. Specifically, the import route for the hook is incorrect in the example. and fixes [#4816](https://github.com/shadcn-ui/ui/issues/4816)

#### Issue:
Upon reviewing the [ShadCN Toast documentation](https://ui.shadcn.com/docs/components/toast), I found that the import path for the Toast component hook was wrongly mentioned as being located in the `components` folder. According to the `component.json` file, the correct location of the hook is within the `hooks` folder inside the main directory.

#### Fix:
- Corrected the import path in the Toast component example from `components` to `hooks`, as per the `component.json` file structure.

#### Example of Fix:
**Before:**
```js
import { useToast } from "@/components/use-toast";
```

**After:**
```js
import { useToast } from "@/hooks/use-toast";
```

#### Testing:
- Verified that the corrected path resolves correctly.
- Ensured the example works as expected after the change.

#### Impact:
This fix prevents confusion for users following the example and ensures that the import path accurately reflects the project structure, improving the overall developer experience.
2024-09-15 08:45:29 +00:00
Quinn Blenkinsop
b6221ea524 fix(www): update broken link to headless ui (#3542)
The link appears to have broken at some point, I've updated it

Co-authored-by: shadcn <m@shadcn.com>
2024-09-15 12:31:28 +04:00
github-actions[bot]
9ef7967b0d chore(release): version packages (#4821)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-09-12 17:54:41 +04:00
shadcn
64b2f1a5ad feat(shadcn): add experimental docs (#4820)
* feat(shadcn): add cli docs

* chore: add changeset

* fix: tests
2024-09-12 17:51:59 +04:00
github-actions[bot]
f4ca57a79c chore(release): version packages (#4788)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-09-09 12:34:19 +04:00
shadcn
99ff9caf71 fix(shadcn): add src to content in tailwind config (#4787)
* feat(shadcn): handle src dir

* chore: changeset
2024-09-09 12:32:12 +04:00
github-actions[bot]
cd9a55b76a chore(release): version packages (#4777)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-09-07 23:42:29 +04:00
shadcn
49373eed96 fix(shadcn): better error handling (#4776)
* fix(shadcn): better error messages

* chore: changeset
2024-09-07 23:35:37 +04:00
shadcn
078dfe6607 docs(www): Open in v0 docs (#4734)
* feat(www): open in v0

* feat: update copy

* fix: sidebar link

* fix(tests): snapshots
2024-09-04 00:37:57 +04:00
xuxucode
77fc5ec8db Fix use-toast module path (#4728) 2024-09-03 18:37:11 +00:00
github-actions[bot]
cfba3fdf70 chore(release): version packages (#4730)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-09-03 22:22:26 +04:00
adrianhelvikspond
4e4118f3cf Fix init command for default style - fixes #4722 (#4724)
* Fix init command for default style

The empty dependency string was tripping up package managers.

* fix(www): registry dependencies for default

---------

Co-authored-by: shadcn <m@shadcn.com>
2024-09-03 22:21:51 +04:00
shadcn
faa7a67fb3 fix(shadcn): init with src (#4731)
* fix(shadcn): init with src

* chore: add changesets
2024-09-03 22:16:59 +04:00
shadcn
701e1160ea feat(shadcn): add support for src dir (#4729)
* feat(shadcn): add support for src dir

* chore: add changesets
2024-09-03 21:47:15 +04:00
shadcn
f5931f8d09 docs(www): update installation docs (#4725) 2024-09-03 16:41:48 +04:00
shadcn
5a28937c6e Merge branch 'main' of github.com:shadcn/ui 2024-09-03 16:35:51 +04:00
shadcn
0b74059d38 docs(www): update laravel docs 2024-09-03 16:35:36 +04:00
shadcn
fab9877586 fix(shadcn): handle quote in theme values (#4726)
* fix(shadcn): handle quote in theme values

* chore(shadcn): fix theme values bug
2024-09-03 16:22:45 +04:00
shadcn
0f7591f67c docs(www): updates docs for Astro (#4723) 2024-09-03 15:35:24 +04:00
shadcn
81c7e44863 fix(www): url 2024-08-31 03:15:10 +04:00
shadcn
2fac3e40c2 fix(www): hide sidebar-01 for now 2024-08-31 03:10:14 +04:00
shadcn
5ad11ff851 docs(www): update callout 2024-08-31 03:01:42 +04:00
shadcn
6b92dd8eaf Merge branch 'main' of github.com:shadcn/ui 2024-08-31 02:57:49 +04:00
shadcn
84540f551d fix: blocks 2024-08-31 02:57:37 +04:00
shadcn
99588fff8f fix: cli (#4669) 2024-08-31 02:09:14 +04:00
github-actions[bot]
f99cd2aa5d chore(release): version packages (#2597)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-08-31 02:02:06 +04:00
shadcn
a62a155aac (1/N) cli: framework support (#4569) 2024-08-31 01:54:48 +04:00
shadcn
dc8853c8df chore: rebuild registry 2024-08-30 23:50:06 +04:00
911 changed files with 37023 additions and 14889 deletions

View File

@@ -1,5 +0,0 @@
---
"shadcn-ui": patch
---
update zod imports

View File

@@ -8,6 +8,7 @@
"plugin:tailwindcss/recommended"
],
"plugins": ["tailwindcss"],
"ignorePatterns": ["**/fixtures/**"],
"rules": {
"@next/next/no-html-link-for-pages": "off",
"tailwindcss/no-custom-classname": "off",

View File

@@ -4,7 +4,7 @@
import { exec } from "child_process"
import fs from "fs"
const pkgJsonPath = "packages/cli/package.json"
const pkgJsonPath = "packages/shadcn/package.json"
try {
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath))
exec("git rev-parse --short HEAD", (err, stdout) => {

View File

@@ -4,7 +4,7 @@
import { exec } from "child_process"
import fs from "fs"
const pkgJsonPath = "packages/cli/package.json"
const pkgJsonPath = "packages/shadcn/package.json"
try {
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath))
exec("git rev-parse --short HEAD", (err, stdout) => {

View File

@@ -16,11 +16,12 @@ jobs:
name: "Close stale issues with no reproduction"
with:
repo-token: ${{ secrets.STALE_TOKEN }}
close-issue-message: "This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you."
close-issue-message: "This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please reopen or leave a comment. Thank you.\n(This is an automated message.)"
days-before-issue-close: 7
days-before-issue-stale: 15
days-before-issue-stale: 30
stale-pr-label: "stale?"
days-before-pr-close: -1
days-before-pr-stale: -1
days-before-pr-close: 7
days-before-pr-stale: 15
only-pr-labels: "postpone: more info or changes requested,please add a reproduction"
exempt-issue-labels: "roadmap,next,bug"
operations-per-run: 300 # 1 operation per 100 issues, the rest is to label/comment/close

View File

@@ -28,8 +28,8 @@ jobs:
for (const artifact of allArtifacts.data.artifacts) {
// Extract the PR number and package version from the artifact name
const match = /^npm-package-shadcn-ui@(.*?)-pr-(\d+)/.exec(artifact.name);
const match = /^npm-package-shadcn@(.*?)-pr-(\d+)/.exec(artifact.name);
if (match) {
require("fs").appendFileSync(
process.env.GITHUB_ENV,
@@ -49,7 +49,7 @@ jobs:
A new prerelease is available for testing:
```sh
npx shadcn-ui@${{ env.BETA_PACKAGE_VERSION }}
npx shadcn@${{ env.BETA_PACKAGE_VERSION }}
```
- name: "Remove the autorelease label once published"

View File

@@ -40,7 +40,7 @@ jobs:
run: node .github/version-script-beta.js
- name: Authenticate to NPM
run: echo "//registry.npmjs.org/:_authToken=$NPM_ACCESS_TOKEN" >> packages/cli/.npmrc
run: echo "//registry.npmjs.org/:_authToken=$NPM_ACCESS_TOKEN" >> packages/shadcn/.npmrc
env:
NPM_ACCESS_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
@@ -51,10 +51,10 @@ jobs:
id: package-version
uses: martinbeentjes/npm-get-version-action@main
with:
path: packages/cli
path: packages/shadcn
- name: Upload packaged artifact
uses: actions/upload-artifact@v2
with:
name: npm-package-shadcn-ui@${{ steps.package-version.outputs.current-version }}-pr-${{ github.event.number }} # encode the PR number into the artifact name
path: packages/cli/dist/index.js
name: npm-package-shadcn@${{ steps.package-version.outputs.current-version }}-pr-${{ github.event.number }} # encode the PR number into the artifact name
path: packages/shadcn/dist/index.js

View File

@@ -37,7 +37,7 @@ jobs:
# run: pnpm check
- name: Build the package
run: pnpm build:cli
run: pnpm shadcn:build
- name: Create Version PR or Publish to NPM
id: changesets

View File

@@ -3,4 +3,5 @@ node_modules
.next
build
.contentlayer
apps/www/pages/api/registry.json
apps/www/pages/api/registry.json
**/fixtures

View File

@@ -6,5 +6,10 @@
"tailwindCSS.experimental.classRegex": [
["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
["cn\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"]
],
"vitest.debugExclude": [
"<node_internals>/**",
"**/node_modules/**",
"**/fixtures/**"
]
}

View File

@@ -0,0 +1,13 @@
import { LoginForm } from "@/registry/default/block/login-01/components/login-form"
export const iframeHeight = "870px"
export const containerClassName = "w-full h-full"
export default function Page() {
return (
<div className="flex h-screen w-full items-center justify-center px-4">
<LoginForm />
</div>
)
}

View File

@@ -0,0 +1,13 @@
import { LoginForm } from "@/registry/default/block/login-01/components/login-form"
export const iframeHeight = "870px"
export const containerClassName = "w-full h-full"
export default function Page() {
return (
<div className="flex h-screen w-full items-center justify-center px-4">
<LoginForm />
</div>
)
}

View File

@@ -0,0 +1,25 @@
import { AppSidebar } from "@/registry/default/block/sidebar-01/components/app-sidebar"
import {
SidebarLayout,
SidebarTrigger,
} from "@/registry/default/block/sidebar-01/ui/sidebar"
export const iframeHeight = "870px"
export const containerClassName = "w-full h-full"
export default async function Page() {
const { cookies } = await import("next/headers")
return (
<SidebarLayout
defaultOpen={cookies().get("sidebar:state")?.value === "true"}
>
<AppSidebar />
<main className="flex flex-1 flex-col p-2 transition-all duration-300 ease-in-out">
<div className="h-full rounded-md border-2 border-dashed p-2">
<SidebarTrigger />
</div>
</main>
</SidebarLayout>
)
}

View File

@@ -0,0 +1,25 @@
import { AppSidebar } from "@/registry/default/block/sidebar-01/components/app-sidebar"
import {
SidebarLayout,
SidebarTrigger,
} from "@/registry/default/block/sidebar-01/ui/sidebar"
export const iframeHeight = "870px"
export const containerClassName = "w-full h-full"
export default async function Page() {
const { cookies } = await import("next/headers")
return (
<SidebarLayout
defaultOpen={cookies().get("sidebar:state")?.value === "true"}
>
<AppSidebar />
<main className="flex flex-1 flex-col p-2 transition-all duration-300 ease-in-out">
<div className="h-full rounded-md border-2 border-dashed p-2">
<SidebarTrigger />
</div>
</main>
</SidebarLayout>
)
}

View File

@@ -1,33 +0,0 @@
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/registry/default/ui/accordion"
export default function AccordionDemo() {
return (
<Accordion type="single" collapsible className="w-full">
<AccordionItem value="item-1">
<AccordionTrigger>Is it accessible?</AccordionTrigger>
<AccordionContent>
Yes. It adheres to the WAI-ARIA design pattern.
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-2">
<AccordionTrigger>Is it styled?</AccordionTrigger>
<AccordionContent>
Yes. It comes with default styles that matches the other
components&apos; aesthetic.
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-3">
<AccordionTrigger>Is it animated?</AccordionTrigger>
<AccordionContent>
Yes. It&apos;s animated by default, but you can disable it if you
prefer.
</AccordionContent>
</AccordionItem>
</Accordion>
)
}

View File

@@ -1,19 +0,0 @@
import { Terminal } from "lucide-react"
import {
Alert,
AlertDescription,
AlertTitle,
} from "@/registry/default/ui/alert"
export default function AlertDemo() {
return (
<Alert>
<Terminal className="h-4 w-4" />
<AlertTitle>Heads up!</AlertTitle>
<AlertDescription>
You can add components to your app using the cli.
</AlertDescription>
</Alert>
)
}

View File

@@ -1,19 +0,0 @@
import { AlertCircle } from "lucide-react"
import {
Alert,
AlertDescription,
AlertTitle,
} from "@/registry/default/ui/alert"
export default function AlertDestructive() {
return (
<Alert variant="destructive">
<AlertCircle className="h-4 w-4" />
<AlertTitle>Error</AlertTitle>
<AlertDescription>
Your session has expired. Please log in again.
</AlertDescription>
</Alert>
)
}

View File

@@ -1,35 +0,0 @@
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/registry/default/ui/alert-dialog"
import { Button } from "@/registry/default/ui/button"
export default function AlertDialogDemo() {
return (
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="outline">Show Dialog</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
<AlertDialogDescription>
This action cannot be undone. This will permanently delete your
account and remove your data from our servers.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction>Continue</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
)
}

View File

@@ -1,16 +0,0 @@
import Image from "next/image"
import { AspectRatio } from "@/registry/default/ui/aspect-ratio"
export default function AspectRatioDemo() {
return (
<AspectRatio ratio={16 / 9} className="bg-muted">
<Image
src="https://images.unsplash.com/photo-1588345921523-c2dcdb7f1dcd?w=800&dpr=2&q=80"
alt="Photo by Drew Beamer"
fill
className="rounded-md object-cover"
/>
</AspectRatio>
)
}

View File

@@ -1,14 +0,0 @@
import {
Avatar,
AvatarFallback,
AvatarImage,
} from "@/registry/default/ui/avatar"
export default function AvatarDemo() {
return (
<Avatar>
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
)
}

View File

@@ -1,5 +0,0 @@
import { Badge } from "@/registry/default/ui/badge"
export default function BadgeDemo() {
return <Badge>Badge</Badge>
}

View File

@@ -1,5 +0,0 @@
import { Badge } from "@/registry/default/ui/badge"
export default function BadgeDestructive() {
return <Badge variant="destructive">Destructive</Badge>
}

View File

@@ -1,5 +0,0 @@
import { Badge } from "@/registry/default/ui/badge"
export default function BadgeOutline() {
return <Badge variant="outline">Outline</Badge>
}

View File

@@ -1,5 +0,0 @@
import { Badge } from "@/registry/default/ui/badge"
export default function BadgeSecondary() {
return <Badge variant="secondary">Secondary</Badge>
}

View File

@@ -1,49 +0,0 @@
import {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/default/ui/breadcrumb"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/registry/default/ui/dropdown-menu"
export default function BreadcrumbDemo() {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<DropdownMenu>
<DropdownMenuTrigger className="flex items-center gap-1">
<BreadcrumbEllipsis className="h-4 w-4" />
<span className="sr-only">Toggle menu</span>
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem>Documentation</DropdownMenuItem>
<DropdownMenuItem>Themes</DropdownMenuItem>
<DropdownMenuItem>GitHub</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="/docs/components">Components</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}

View File

@@ -1,50 +0,0 @@
import { ChevronDown, Slash } from "lucide-react"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/default/ui/breadcrumb"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/registry/default/ui/dropdown-menu"
export default function BreadcrumbWithDropdown() {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<Slash />
</BreadcrumbSeparator>
<BreadcrumbItem>
<DropdownMenu>
<DropdownMenuTrigger className="flex items-center gap-1">
Components
<ChevronDown className="h-4 w-4" />
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem>Documentation</DropdownMenuItem>
<DropdownMenuItem>Themes</DropdownMenuItem>
<DropdownMenuItem>GitHub</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbItem>
<BreadcrumbSeparator>
<Slash />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}

View File

@@ -1,39 +0,0 @@
import Link from "next/link"
import {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/default/ui/breadcrumb"
export default function BreadcrumbCollapsed() {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink asChild>
<Link href="/">Home</Link>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbEllipsis />
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink asChild>
<Link href="/docs/components">Components</Link>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}

View File

@@ -1,34 +0,0 @@
import Link from "next/link"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/default/ui/breadcrumb"
export default function BreadcrumbWithCustomSeparator() {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink>
<Link href="/">Home</Link>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink>
<Link href="/components">Components</Link>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}

View File

@@ -1,133 +0,0 @@
"use client"
import * as React from "react"
import Link from "next/link"
import { useMediaQuery } from "@/hooks/use-media-query"
import {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/default/ui/breadcrumb"
import { Button } from "@/registry/default/ui/button"
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from "@/registry/default/ui/drawer"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/registry/default/ui/dropdown-menu"
const items = [
{ href: "#", label: "Home" },
{ href: "#", label: "Documentation" },
{ href: "#", label: "Building Your Application" },
{ href: "#", label: "Data Fetching" },
{ label: "Caching and Revalidating" },
]
const ITEMS_TO_DISPLAY = 3
export default function BreadcrumbResponsive() {
const [open, setOpen] = React.useState(false)
const isDesktop = useMediaQuery("(min-width: 768px)")
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href={items[0].href}>{items[0].label}</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
{items.length > ITEMS_TO_DISPLAY ? (
<>
<BreadcrumbItem>
{isDesktop ? (
<DropdownMenu open={open} onOpenChange={setOpen}>
<DropdownMenuTrigger
className="flex items-center gap-1"
aria-label="Toggle menu"
>
<BreadcrumbEllipsis className="h-4 w-4" />
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
{items.slice(1, -2).map((item, index) => (
<DropdownMenuItem key={index}>
<Link href={item.href ? item.href : "#"}>
{item.label}
</Link>
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
) : (
<Drawer open={open} onOpenChange={setOpen}>
<DrawerTrigger aria-label="Toggle Menu">
<BreadcrumbEllipsis className="h-4 w-4" />
</DrawerTrigger>
<DrawerContent>
<DrawerHeader className="text-left">
<DrawerTitle>Navigate to</DrawerTitle>
<DrawerDescription>
Select a page to navigate to.
</DrawerDescription>
</DrawerHeader>
<div className="grid gap-1 px-4">
{items.slice(1, -2).map((item, index) => (
<Link
key={index}
href={item.href ? item.href : "#"}
className="py-1 text-sm"
>
{item.label}
</Link>
))}
</div>
<DrawerFooter className="pt-4">
<DrawerClose asChild>
<Button variant="outline">Close</Button>
</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>
)}
</BreadcrumbItem>
<BreadcrumbSeparator />
</>
) : null}
{items.slice(-ITEMS_TO_DISPLAY + 1).map((item, index) => (
<BreadcrumbItem key={index}>
{item.href ? (
<>
<BreadcrumbLink
asChild
className="max-w-20 truncate md:max-w-none"
>
<Link href={item.href}>{item.label}</Link>
</BreadcrumbLink>
<BreadcrumbSeparator />
</>
) : (
<BreadcrumbPage className="max-w-20 truncate md:max-w-none">
{item.label}
</BreadcrumbPage>
)}
</BreadcrumbItem>
))}
</BreadcrumbList>
</Breadcrumb>
)
}

View File

@@ -1,34 +0,0 @@
import { Slash } from "lucide-react"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/default/ui/breadcrumb"
export default function BreadcrumbWithCustomSeparator() {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<Slash />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbLink href="/components">Components</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<Slash />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}

View File

@@ -1,11 +0,0 @@
import Link from "next/link"
import { Button } from "@/registry/default/ui/button"
export default function ButtonAsChild() {
return (
<Button asChild>
<Link href="/login">Login</Link>
</Button>
)
}

View File

@@ -1,5 +0,0 @@
import { Button } from "@/registry/default/ui/button"
export default function ButtonDemo() {
return <Button>Button</Button>
}

View File

@@ -1,5 +0,0 @@
import { Button } from "@/registry/default/ui/button"
export default function ButtonDestructive() {
return <Button variant="destructive">Destructive</Button>
}

View File

@@ -1,5 +0,0 @@
import { Button } from "@/registry/default/ui/button"
export default function ButtonGhost() {
return <Button variant="ghost">Ghost</Button>
}

View File

@@ -1,11 +0,0 @@
import { ChevronRight } from "lucide-react"
import { Button } from "@/registry/default/ui/button"
export default function ButtonIcon() {
return (
<Button variant="outline" size="icon">
<ChevronRight className="h-4 w-4" />
</Button>
)
}

View File

@@ -1,5 +0,0 @@
import { Button } from "@/registry/default/ui/button"
export default function ButtonLink() {
return <Button variant="link">Link</Button>
}

View File

@@ -1,12 +0,0 @@
import { Loader2 } from "lucide-react"
import { Button } from "@/registry/default/ui/button"
export default function ButtonLoading() {
return (
<Button disabled>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Please wait
</Button>
)
}

View File

@@ -1,5 +0,0 @@
import { Button } from "@/registry/default/ui/button"
export default function ButtonOutline() {
return <Button variant="outline">Outline</Button>
}

View File

@@ -1,5 +0,0 @@
import { Button } from "@/registry/default/ui/button"
export default function ButtonSecondary() {
return <Button variant="secondary">Secondary</Button>
}

View File

@@ -1,11 +0,0 @@
import { Mail } from "lucide-react"
import { Button } from "@/registry/default/ui/button"
export default function ButtonWithIcon() {
return (
<Button>
<Mail className="mr-2 h-4 w-4" /> Login with Email
</Button>
)
}

View File

@@ -1,18 +0,0 @@
"use client"
import * as React from "react"
import { Calendar } from "@/registry/default/ui/calendar"
export default function CalendarDemo() {
const [date, setDate] = React.useState<Date | undefined>(new Date())
return (
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="rounded-md border"
/>
)
}

View File

@@ -1,101 +0,0 @@
"use client"
import { zodResolver } from "@hookform/resolvers/zod"
import { format } from "date-fns"
import { CalendarIcon } from "lucide-react"
import { useForm } from "react-hook-form"
import { z } from "zod"
import { cn } from "@/lib/utils"
import { Button } from "@/registry/default/ui/button"
import { Calendar } from "@/registry/default/ui/calendar"
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/registry/default/ui/form"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/registry/default/ui/popover"
import { toast } from "@/registry/default/ui/use-toast"
const FormSchema = z.object({
dob: z.date({
required_error: "A date of birth is required.",
}),
})
export default function CalendarForm() {
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
})
function onSubmit(data: z.infer<typeof FormSchema>) {
toast({
title: "You submitted the following values:",
description: (
<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
<code className="text-white">{JSON.stringify(data, null, 2)}</code>
</pre>
),
})
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="dob"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>Date of birth</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant={"outline"}
className={cn(
"w-[240px] pl-3 text-left font-normal",
!field.value && "text-muted-foreground"
)}
>
{field.value ? (
format(field.value, "PPP")
) : (
<span>Pick a date</span>
)}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={field.value}
onSelect={field.onChange}
disabled={(date) =>
date > new Date() || date < new Date("1900-01-01")
}
initialFocus
/>
</PopoverContent>
</Popover>
<FormDescription>
Your date of birth is used to calculate your age.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
)
}

View File

@@ -1,78 +0,0 @@
import { BellRing, Check } from "lucide-react"
import { cn } from "@/lib/utils"
import { Button } from "@/registry/default/ui/button"
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/registry/default/ui/card"
import { Switch } from "@/registry/default/ui/switch"
const notifications = [
{
title: "Your call has been confirmed.",
description: "1 hour ago",
},
{
title: "You have a new message!",
description: "1 hour ago",
},
{
title: "Your subscription is expiring soon!",
description: "2 hours ago",
},
]
type CardProps = React.ComponentProps<typeof Card>
export default function CardDemo({ className, ...props }: CardProps) {
return (
<Card className={cn("w-[380px]", className)} {...props}>
<CardHeader>
<CardTitle>Notifications</CardTitle>
<CardDescription>You have 3 unread messages.</CardDescription>
</CardHeader>
<CardContent className="grid gap-4">
<div className=" flex items-center space-x-4 rounded-md border p-4">
<BellRing />
<div className="flex-1 space-y-1">
<p className="text-sm font-medium leading-none">
Push Notifications
</p>
<p className="text-sm text-muted-foreground">
Send notifications to device.
</p>
</div>
<Switch />
</div>
<div>
{notifications.map((notification, index) => (
<div
key={index}
className="mb-4 grid grid-cols-[25px_1fr] items-start pb-4 last:mb-0 last:pb-0"
>
<span className="flex h-2 w-2 translate-y-1 rounded-full bg-sky-500" />
<div className="space-y-1">
<p className="text-sm font-medium leading-none">
{notification.title}
</p>
<p className="text-sm text-muted-foreground">
{notification.description}
</p>
</div>
</div>
))}
</div>
</CardContent>
<CardFooter>
<Button className="w-full">
<Check className="mr-2 h-4 w-4" /> Mark all as read
</Button>
</CardFooter>
</Card>
)
}

View File

@@ -1,59 +0,0 @@
import * as React from "react"
import { Button } from "@/registry/default/ui/button"
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/registry/default/ui/card"
import { Input } from "@/registry/default/ui/input"
import { Label } from "@/registry/default/ui/label"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/registry/default/ui/select"
export default function CardWithForm() {
return (
<Card className="w-[350px]">
<CardHeader>
<CardTitle>Create project</CardTitle>
<CardDescription>Deploy your new project in one-click.</CardDescription>
</CardHeader>
<CardContent>
<form>
<div className="grid w-full items-center gap-4">
<div className="flex flex-col space-y-1.5">
<Label htmlFor="name">Name</Label>
<Input id="name" placeholder="Name of your project" />
</div>
<div className="flex flex-col space-y-1.5">
<Label htmlFor="framework">Framework</Label>
<Select>
<SelectTrigger id="framework">
<SelectValue placeholder="Select" />
</SelectTrigger>
<SelectContent position="popper">
<SelectItem value="next">Next.js</SelectItem>
<SelectItem value="sveltekit">SvelteKit</SelectItem>
<SelectItem value="astro">Astro</SelectItem>
<SelectItem value="nuxt">Nuxt.js</SelectItem>
</SelectContent>
</Select>
</div>
</div>
</form>
</CardContent>
<CardFooter className="flex justify-between">
<Button variant="outline">Cancel</Button>
<Button>Deploy</Button>
</CardFooter>
</Card>
)
}

View File

@@ -1,54 +0,0 @@
import * as React from "react"
import { Card, CardContent } from "@/registry/default/ui/card"
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
type CarouselApi,
} from "@/registry/default/ui/carousel"
export default function CarouselDApiDemo() {
const [api, setApi] = React.useState<CarouselApi>()
const [current, setCurrent] = React.useState(0)
const [count, setCount] = React.useState(0)
React.useEffect(() => {
if (!api) {
return
}
setCount(api.scrollSnapList().length)
setCurrent(api.selectedScrollSnap() + 1)
api.on("select", () => {
console.log("current")
setCurrent(api.selectedScrollSnap() + 1)
})
}, [api])
return (
<div>
<Carousel setApi={setApi} className="w-full max-w-xs">
<CarouselContent>
{Array.from({ length: 5 }).map((_, index) => (
<CarouselItem key={index}>
<Card>
<CardContent className="flex aspect-square items-center justify-center p-6">
<span className="text-4xl font-semibold">{index + 1}</span>
</CardContent>
</Card>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
<div className="py-2 text-center text-sm text-muted-foreground">
Slide {current} of {count}
</div>
</div>
)
}

View File

@@ -1,32 +0,0 @@
import * as React from "react"
import { Card, CardContent } from "@/registry/default/ui/card"
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@/registry/default/ui/carousel"
export default function CarouselDemo() {
return (
<Carousel className="w-full max-w-xs">
<CarouselContent>
{Array.from({ length: 5 }).map((_, index) => (
<CarouselItem key={index}>
<div className="p-1">
<Card>
<CardContent className="flex aspect-square items-center justify-center p-6">
<span className="text-4xl font-semibold">{index + 1}</span>
</CardContent>
</Card>
</div>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
)
}

View File

@@ -1,38 +0,0 @@
import * as React from "react"
import { Card, CardContent } from "@/registry/default/ui/card"
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@/registry/default/ui/carousel"
export default function CarouselOrientation() {
return (
<Carousel
opts={{
align: "start",
}}
orientation="vertical"
className="w-full max-w-xs"
>
<CarouselContent className="-mt-1 h-[200px]">
{Array.from({ length: 5 }).map((_, index) => (
<CarouselItem key={index} className="pt-1 md:basis-1/2">
<div className="p-1">
<Card>
<CardContent className="flex items-center justify-center p-6">
<span className="text-3xl font-semibold">{index + 1}</span>
</CardContent>
</Card>
</div>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
)
}

View File

@@ -1,42 +0,0 @@
import * as React from "react"
import Autoplay from "embla-carousel-autoplay"
import { Card, CardContent } from "@/registry/default/ui/card"
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@/registry/default/ui/carousel"
export default function CarouselPlugin() {
const plugin = React.useRef(
Autoplay({ delay: 2000, stopOnInteraction: true })
)
return (
<Carousel
plugins={[plugin.current]}
className="w-full max-w-xs"
onMouseEnter={plugin.current.stop}
onMouseLeave={plugin.current.reset}
>
<CarouselContent>
{Array.from({ length: 5 }).map((_, index) => (
<CarouselItem key={index}>
<div className="p-1">
<Card>
<CardContent className="flex aspect-square items-center justify-center p-6">
<span className="text-4xl font-semibold">{index + 1}</span>
</CardContent>
</Card>
</div>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
)
}

View File

@@ -1,37 +0,0 @@
import * as React from "react"
import { Card, CardContent } from "@/registry/default/ui/card"
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@/registry/default/ui/carousel"
export default function CarouselSize() {
return (
<Carousel
opts={{
align: "start",
}}
className="w-full max-w-sm"
>
<CarouselContent>
{Array.from({ length: 5 }).map((_, index) => (
<CarouselItem key={index} className="md:basis-1/2 lg:basis-1/3">
<div className="p-1">
<Card>
<CardContent className="flex aspect-square items-center justify-center p-6">
<span className="text-3xl font-semibold">{index + 1}</span>
</CardContent>
</Card>
</div>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
)
}

View File

@@ -1,32 +0,0 @@
import * as React from "react"
import { Card, CardContent } from "@/registry/default/ui/card"
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@/registry/default/ui/carousel"
export default function CarouselSpacing() {
return (
<Carousel className="w-full max-w-sm">
<CarouselContent className="-ml-1">
{Array.from({ length: 5 }).map((_, index) => (
<CarouselItem key={index} className="pl-1 md:basis-1/2 lg:basis-1/3">
<div className="p-1">
<Card>
<CardContent className="flex aspect-square items-center justify-center p-6">
<span className="text-2xl font-semibold">{index + 1}</span>
</CardContent>
</Card>
</div>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
)
}

View File

@@ -1,17 +0,0 @@
"use client"
import { Checkbox } from "@/registry/default/ui/checkbox"
export default function CheckboxDemo() {
return (
<div className="flex items-center space-x-2">
<Checkbox id="terms" />
<label
htmlFor="terms"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Accept terms and conditions
</label>
</div>
)
}

View File

@@ -1,15 +0,0 @@
import { Checkbox } from "@/registry/default/ui/checkbox"
export default function CheckboxDisabled() {
return (
<div className="flex items-center space-x-2">
<Checkbox id="terms2" disabled />
<label
htmlFor="terms2"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Accept terms and conditions
</label>
</div>
)
}

View File

@@ -1,127 +0,0 @@
"use client"
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
import { Button } from "@/registry/default/ui/button"
import { Checkbox } from "@/registry/default/ui/checkbox"
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/registry/default/ui/form"
import { toast } from "@/registry/default/ui/use-toast"
const items = [
{
id: "recents",
label: "Recents",
},
{
id: "home",
label: "Home",
},
{
id: "applications",
label: "Applications",
},
{
id: "desktop",
label: "Desktop",
},
{
id: "downloads",
label: "Downloads",
},
{
id: "documents",
label: "Documents",
},
] as const
const FormSchema = z.object({
items: z.array(z.string()).refine((value) => value.some((item) => item), {
message: "You have to select at least one item.",
}),
})
export default function CheckboxReactHookFormMultiple() {
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: {
items: ["recents", "home"],
},
})
function onSubmit(data: z.infer<typeof FormSchema>) {
toast({
title: "You submitted the following values:",
description: (
<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
<code className="text-white">{JSON.stringify(data, null, 2)}</code>
</pre>
),
})
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="items"
render={() => (
<FormItem>
<div className="mb-4">
<FormLabel className="text-base">Sidebar</FormLabel>
<FormDescription>
Select the items you want to display in the sidebar.
</FormDescription>
</div>
{items.map((item) => (
<FormField
key={item.id}
control={form.control}
name="items"
render={({ field }) => {
return (
<FormItem
key={item.id}
className="flex flex-row items-start space-x-3 space-y-0"
>
<FormControl>
<Checkbox
checked={field.value?.includes(item.id)}
onCheckedChange={(checked) => {
return checked
? field.onChange([...field.value, item.id])
: field.onChange(
field.value?.filter(
(value) => value !== item.id
)
)
}}
/>
</FormControl>
<FormLabel className="font-normal">
{item.label}
</FormLabel>
</FormItem>
)
}}
/>
))}
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
)
}

View File

@@ -1,73 +0,0 @@
"use client"
import Link from "next/link"
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
import { Button } from "@/registry/default/ui/button"
import { Checkbox } from "@/registry/default/ui/checkbox"
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
} from "@/registry/default/ui/form"
import { toast } from "@/registry/default/ui/use-toast"
const FormSchema = z.object({
mobile: z.boolean().default(false).optional(),
})
export default function CheckboxReactHookFormSingle() {
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: {
mobile: true,
},
})
function onSubmit(data: z.infer<typeof FormSchema>) {
toast({
title: "You submitted the following values:",
description: (
<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
<code className="text-white">{JSON.stringify(data, null, 2)}</code>
</pre>
),
})
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
<FormField
control={form.control}
name="mobile"
render={({ field }) => (
<FormItem className="flex flex-row items-start space-x-3 space-y-0 rounded-md border p-4">
<FormControl>
<Checkbox
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
<div className="space-y-1 leading-none">
<FormLabel>
Use different settings for my mobile devices
</FormLabel>
<FormDescription>
You can manage your mobile notifications in the{" "}
<Link href="/examples/forms">mobile settings</Link> page.
</FormDescription>
</div>
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
)
}

View File

@@ -1,22 +0,0 @@
"use client"
import { Checkbox } from "@/registry/default/ui/checkbox"
export default function CheckboxWithText() {
return (
<div className="items-top flex space-x-2">
<Checkbox id="terms1" />
<div className="grid gap-1.5 leading-none">
<label
htmlFor="terms1"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Accept terms and conditions
</label>
<p className="text-sm text-muted-foreground">
You agree to our Terms of Service and Privacy Policy.
</p>
</div>
</div>
)
}

View File

@@ -1,46 +0,0 @@
"use client"
import * as React from "react"
import { ChevronsUpDown, Plus, X } from "lucide-react"
import { Button } from "@/registry/default/ui/button"
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/registry/default/ui/collapsible"
export default function CollapsibleDemo() {
const [isOpen, setIsOpen] = React.useState(false)
return (
<Collapsible
open={isOpen}
onOpenChange={setIsOpen}
className="w-[350px] space-y-2"
>
<div className="flex items-center justify-between space-x-4 px-4">
<h4 className="text-sm font-semibold">
@peduarte starred 3 repositories
</h4>
<CollapsibleTrigger asChild>
<Button variant="ghost" size="sm" className="w-9 p-0">
<ChevronsUpDown className="h-4 w-4" />
<span className="sr-only">Toggle</span>
</Button>
</CollapsibleTrigger>
</div>
<div className="rounded-md border px-4 py-3 font-mono text-sm">
@radix-ui/primitives
</div>
<CollapsibleContent className="space-y-2">
<div className="rounded-md border px-4 py-3 font-mono text-sm">
@radix-ui/colors
</div>
<div className="rounded-md border px-4 py-3 font-mono text-sm">
@stitches/react
</div>
</CollapsibleContent>
</Collapsible>
)
}

View File

@@ -1,91 +0,0 @@
"use client"
import * as React from "react"
import { Check, ChevronsUpDown } from "lucide-react"
import { cn } from "@/lib/utils"
import { Button } from "@/registry/default/ui/button"
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
} from "@/registry/default/ui/command"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/registry/default/ui/popover"
const frameworks = [
{
value: "next.js",
label: "Next.js",
},
{
value: "sveltekit",
label: "SvelteKit",
},
{
value: "nuxt.js",
label: "Nuxt.js",
},
{
value: "remix",
label: "Remix",
},
{
value: "astro",
label: "Astro",
},
]
export default function ComboboxDemo() {
const [open, setOpen] = React.useState(false)
const [value, setValue] = React.useState("")
return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={open}
className="w-[200px] justify-between"
>
{value
? frameworks.find((framework) => framework.value === value)?.label
: "Select framework..."}
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0">
<Command>
<CommandInput placeholder="Search framework..." />
<CommandEmpty>No framework found.</CommandEmpty>
<CommandGroup>
{frameworks.map((framework) => (
<CommandItem
key={framework.value}
value={framework.value}
onSelect={(currentValue) => {
setValue(currentValue === value ? "" : currentValue)
setOpen(false)
}}
>
<Check
className={cn(
"mr-2 h-4 w-4",
value === framework.value ? "opacity-100" : "opacity-0"
)}
/>
{framework.label}
</CommandItem>
))}
</CommandGroup>
</Command>
</PopoverContent>
</Popover>
)
}

View File

@@ -1,111 +0,0 @@
"use client"
import * as React from "react"
import { Calendar, MoreHorizontal, Tags, Trash, User } from "lucide-react"
import { Button } from "@/registry/default/ui/button"
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "@/registry/default/ui/command"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "@/registry/default/ui/dropdown-menu"
const labels = [
"feature",
"bug",
"enhancement",
"documentation",
"design",
"question",
"maintenance",
]
export default function ComboboxDropdownMenu() {
const [label, setLabel] = React.useState("feature")
const [open, setOpen] = React.useState(false)
return (
<div className="flex w-full flex-col items-start justify-between rounded-md border px-4 py-3 sm:flex-row sm:items-center">
<p className="text-sm font-medium leading-none">
<span className="mr-2 rounded-lg bg-primary px-2 py-1 text-xs text-primary-foreground">
{label}
</span>
<span className="text-muted-foreground">Create a new project</span>
</p>
<DropdownMenu open={open} onOpenChange={setOpen}>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="sm">
<MoreHorizontal />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-[200px]">
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuGroup>
<DropdownMenuItem>
<User className="mr-2 h-4 w-4" />
Assign to...
</DropdownMenuItem>
<DropdownMenuItem>
<Calendar className="mr-2 h-4 w-4" />
Set due date...
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuSub>
<DropdownMenuSubTrigger>
<Tags className="mr-2 h-4 w-4" />
Apply label
</DropdownMenuSubTrigger>
<DropdownMenuSubContent className="p-0">
<Command>
<CommandInput
placeholder="Filter label..."
autoFocus={true}
/>
<CommandList>
<CommandEmpty>No label found.</CommandEmpty>
<CommandGroup>
{labels.map((label) => (
<CommandItem
key={label}
value={label}
onSelect={(value) => {
setLabel(value)
setOpen(false)
}}
>
{label}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</DropdownMenuSubContent>
</DropdownMenuSub>
<DropdownMenuSeparator />
<DropdownMenuItem className="text-red-600">
<Trash className="mr-2 h-4 w-4" />
Delete
<DropdownMenuShortcut></DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
</div>
)
}

View File

@@ -1,135 +0,0 @@
"use client"
import { zodResolver } from "@hookform/resolvers/zod"
import { Check, ChevronsUpDown } from "lucide-react"
import { useForm } from "react-hook-form"
import { z } from "zod"
import { cn } from "@/lib/utils"
import { Button } from "@/registry/default/ui/button"
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
} from "@/registry/default/ui/command"
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/registry/default/ui/form"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/registry/default/ui/popover"
import { toast } from "@/registry/default/ui/use-toast"
const languages = [
{ label: "English", value: "en" },
{ label: "French", value: "fr" },
{ label: "German", value: "de" },
{ label: "Spanish", value: "es" },
{ label: "Portuguese", value: "pt" },
{ label: "Russian", value: "ru" },
{ label: "Japanese", value: "ja" },
{ label: "Korean", value: "ko" },
{ label: "Chinese", value: "zh" },
] as const
const FormSchema = z.object({
language: z.string({
required_error: "Please select a language.",
}),
})
export default function ComboboxForm() {
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
})
function onSubmit(data: z.infer<typeof FormSchema>) {
toast({
title: "You submitted the following values:",
description: (
<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
<code className="text-white">{JSON.stringify(data, null, 2)}</code>
</pre>
),
})
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
<FormField
control={form.control}
name="language"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>Language</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant="outline"
role="combobox"
className={cn(
"w-[200px] justify-between",
!field.value && "text-muted-foreground"
)}
>
{field.value
? languages.find(
(language) => language.value === field.value
)?.label
: "Select language"}
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0">
<Command>
<CommandInput placeholder="Search language..." />
<CommandEmpty>No language found.</CommandEmpty>
<CommandGroup>
{languages.map((language) => (
<CommandItem
value={language.label}
key={language.value}
onSelect={() => {
form.setValue("language", language.value)
}}
>
<Check
className={cn(
"mr-2 h-4 w-4",
language.value === field.value
? "opacity-100"
: "opacity-0"
)}
/>
{language.label}
</CommandItem>
))}
</CommandGroup>
</Command>
</PopoverContent>
</Popover>
<FormDescription>
This is the language that will be used in the dashboard.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
)
}

View File

@@ -1,125 +0,0 @@
"use client"
import * as React from "react"
import {
ArrowUpCircle,
CheckCircle2,
Circle,
HelpCircle,
LucideIcon,
XCircle,
} from "lucide-react"
import { cn } from "@/lib/utils"
import { Button } from "@/registry/default/ui/button"
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "@/registry/default/ui/command"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/registry/default/ui/popover"
type Status = {
value: string
label: string
icon: LucideIcon
}
const statuses: Status[] = [
{
value: "backlog",
label: "Backlog",
icon: HelpCircle,
},
{
value: "todo",
label: "Todo",
icon: Circle,
},
{
value: "in progress",
label: "In Progress",
icon: ArrowUpCircle,
},
{
value: "done",
label: "Done",
icon: CheckCircle2,
},
{
value: "canceled",
label: "Canceled",
icon: XCircle,
},
]
export default function ComboboxPopover() {
const [open, setOpen] = React.useState(false)
const [selectedStatus, setSelectedStatus] = React.useState<Status | null>(
null
)
return (
<div className="flex items-center space-x-4">
<p className="text-sm text-muted-foreground">Status</p>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
size="sm"
className="w-[150px] justify-start"
>
{selectedStatus ? (
<>
<selectedStatus.icon className="mr-2 h-4 w-4 shrink-0" />
{selectedStatus.label}
</>
) : (
<>+ Set status</>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="p-0" side="right" align="start">
<Command>
<CommandInput placeholder="Change status..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup>
{statuses.map((status) => (
<CommandItem
key={status.value}
value={status.value}
onSelect={(value) => {
setSelectedStatus(
statuses.find((priority) => priority.value === value) ||
null
)
setOpen(false)
}}
>
<status.icon
className={cn(
"mr-2 h-4 w-4",
status.value === selectedStatus?.value
? "opacity-100"
: "opacity-40"
)}
/>
<span>{status.label}</span>
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
</div>
)
}

View File

@@ -1,123 +0,0 @@
"use client"
import * as React from "react"
import { useMediaQuery } from "@/hooks/use-media-query"
import { Button } from "@/registry/default/ui/button"
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "@/registry/default/ui/command"
import {
Drawer,
DrawerContent,
DrawerTrigger,
} from "@/registry/default/ui/drawer"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/registry/default/ui/popover"
type Status = {
value: string
label: string
}
const statuses: Status[] = [
{
value: "backlog",
label: "Backlog",
},
{
value: "todo",
label: "Todo",
},
{
value: "in progress",
label: "In Progress",
},
{
value: "done",
label: "Done",
},
{
value: "canceled",
label: "Canceled",
},
]
export default function ComboBoxResponsive() {
const [open, setOpen] = React.useState(false)
const isDesktop = useMediaQuery("(min-width: 768px)")
const [selectedStatus, setSelectedStatus] = React.useState<Status | null>(
null
)
if (isDesktop) {
return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button variant="outline" className="w-[150px] justify-start">
{selectedStatus ? <>{selectedStatus.label}</> : <>+ Set status</>}
</Button>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0" align="start">
<StatusList setOpen={setOpen} setSelectedStatus={setSelectedStatus} />
</PopoverContent>
</Popover>
)
}
return (
<Drawer open={open} onOpenChange={setOpen}>
<DrawerTrigger asChild>
<Button variant="outline" className="w-[150px] justify-start">
{selectedStatus ? <>{selectedStatus.label}</> : <>+ Set status</>}
</Button>
</DrawerTrigger>
<DrawerContent>
<div className="mt-4 border-t">
<StatusList setOpen={setOpen} setSelectedStatus={setSelectedStatus} />
</div>
</DrawerContent>
</Drawer>
)
}
function StatusList({
setOpen,
setSelectedStatus,
}: {
setOpen: (open: boolean) => void
setSelectedStatus: (status: Status | null) => void
}) {
return (
<Command>
<CommandInput placeholder="Filter status..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup>
{statuses.map((status) => (
<CommandItem
key={status.value}
value={status.value}
onSelect={(value) => {
setSelectedStatus(
statuses.find((priority) => priority.value === value) || null
)
setOpen(false)
}}
>
{status.label}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
)
}

View File

@@ -1,62 +0,0 @@
import {
Calculator,
Calendar,
CreditCard,
Settings,
Smile,
User,
} from "lucide-react"
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
CommandShortcut,
} from "@/registry/default/ui/command"
export default function CommandDemo() {
return (
<Command className="rounded-lg border shadow-md">
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem>
<Calendar className="mr-2 h-4 w-4" />
<span>Calendar</span>
</CommandItem>
<CommandItem>
<Smile className="mr-2 h-4 w-4" />
<span>Search Emoji</span>
</CommandItem>
<CommandItem>
<Calculator className="mr-2 h-4 w-4" />
<span>Calculator</span>
</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Settings">
<CommandItem>
<User className="mr-2 h-4 w-4" />
<span>Profile</span>
<CommandShortcut>P</CommandShortcut>
</CommandItem>
<CommandItem>
<CreditCard className="mr-2 h-4 w-4" />
<span>Billing</span>
<CommandShortcut>B</CommandShortcut>
</CommandItem>
<CommandItem>
<Settings className="mr-2 h-4 w-4" />
<span>Settings</span>
<CommandShortcut>S</CommandShortcut>
</CommandItem>
</CommandGroup>
</CommandList>
</Command>
)
}

View File

@@ -1,87 +0,0 @@
"use client"
import * as React from "react"
import {
Calculator,
Calendar,
CreditCard,
Settings,
Smile,
User,
} from "lucide-react"
import {
CommandDialog,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
CommandShortcut,
} from "@/registry/default/ui/command"
export default function CommandDialogDemo() {
const [open, setOpen] = React.useState(false)
React.useEffect(() => {
const down = (e: KeyboardEvent) => {
if (e.key === "j" && (e.metaKey || e.ctrlKey)) {
e.preventDefault()
setOpen((open) => !open)
}
}
document.addEventListener("keydown", down)
return () => document.removeEventListener("keydown", down)
}, [])
return (
<>
<p className="text-sm text-muted-foreground">
Press{" "}
<kbd className="pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100">
<span className="text-xs"></span>J
</kbd>
</p>
<CommandDialog open={open} onOpenChange={setOpen}>
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem>
<Calendar className="mr-2 h-4 w-4" />
<span>Calendar</span>
</CommandItem>
<CommandItem>
<Smile className="mr-2 h-4 w-4" />
<span>Search Emoji</span>
</CommandItem>
<CommandItem>
<Calculator className="mr-2 h-4 w-4" />
<span>Calculator</span>
</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Settings">
<CommandItem>
<User className="mr-2 h-4 w-4" />
<span>Profile</span>
<CommandShortcut>P</CommandShortcut>
</CommandItem>
<CommandItem>
<CreditCard className="mr-2 h-4 w-4" />
<span>Billing</span>
<CommandShortcut>B</CommandShortcut>
</CommandItem>
<CommandItem>
<Settings className="mr-2 h-4 w-4" />
<span>Settings</span>
<CommandShortcut>S</CommandShortcut>
</CommandItem>
</CommandGroup>
</CommandList>
</CommandDialog>
</>
)
}

View File

@@ -1,67 +0,0 @@
import {
ContextMenu,
ContextMenuCheckboxItem,
ContextMenuContent,
ContextMenuItem,
ContextMenuLabel,
ContextMenuRadioGroup,
ContextMenuRadioItem,
ContextMenuSeparator,
ContextMenuShortcut,
ContextMenuSub,
ContextMenuSubContent,
ContextMenuSubTrigger,
ContextMenuTrigger,
} from "@/registry/default/ui/context-menu"
export default function ContextMenuDemo() {
return (
<ContextMenu>
<ContextMenuTrigger className="flex h-[150px] w-[300px] items-center justify-center rounded-md border border-dashed text-sm">
Right click here
</ContextMenuTrigger>
<ContextMenuContent className="w-64">
<ContextMenuItem inset>
Back
<ContextMenuShortcut>[</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuItem inset disabled>
Forward
<ContextMenuShortcut>]</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuItem inset>
Reload
<ContextMenuShortcut>R</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuSub>
<ContextMenuSubTrigger inset>More Tools</ContextMenuSubTrigger>
<ContextMenuSubContent className="w-48">
<ContextMenuItem>
Save Page As...
<ContextMenuShortcut>S</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuItem>Create Shortcut...</ContextMenuItem>
<ContextMenuItem>Name Window...</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuItem>Developer Tools</ContextMenuItem>
</ContextMenuSubContent>
</ContextMenuSub>
<ContextMenuSeparator />
<ContextMenuCheckboxItem checked>
Show Bookmarks Bar
<ContextMenuShortcut>B</ContextMenuShortcut>
</ContextMenuCheckboxItem>
<ContextMenuCheckboxItem>Show Full URLs</ContextMenuCheckboxItem>
<ContextMenuSeparator />
<ContextMenuRadioGroup value="pedro">
<ContextMenuLabel inset>People</ContextMenuLabel>
<ContextMenuSeparator />
<ContextMenuRadioItem value="pedro">
Pedro Duarte
</ContextMenuRadioItem>
<ContextMenuRadioItem value="colm">Colm Tuite</ContextMenuRadioItem>
</ContextMenuRadioGroup>
</ContextMenuContent>
</ContextMenu>
)
}

View File

@@ -1,312 +0,0 @@
"use client"
import * as React from "react"
import {
ColumnDef,
ColumnFiltersState,
SortingState,
VisibilityState,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table"
import { ArrowUpDown, ChevronDown, MoreHorizontal } from "lucide-react"
import { Button } from "@/registry/default/ui/button"
import { Checkbox } from "@/registry/default/ui/checkbox"
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/registry/default/ui/dropdown-menu"
import { Input } from "@/registry/default/ui/input"
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/registry/default/ui/table"
const data: Payment[] = [
{
id: "m5gr84i9",
amount: 316,
status: "success",
email: "ken99@yahoo.com",
},
{
id: "3u1reuv4",
amount: 242,
status: "success",
email: "Abe45@gmail.com",
},
{
id: "derv1ws0",
amount: 837,
status: "processing",
email: "Monserrat44@gmail.com",
},
{
id: "5kma53ae",
amount: 874,
status: "success",
email: "Silas22@gmail.com",
},
{
id: "bhqecj4p",
amount: 721,
status: "failed",
email: "carmella@hotmail.com",
},
]
export type Payment = {
id: string
amount: number
status: "pending" | "processing" | "success" | "failed"
email: string
}
export const columns: ColumnDef<Payment>[] = [
{
id: "select",
header: ({ table }) => (
<Checkbox
checked={
table.getIsAllPageRowsSelected() ||
(table.getIsSomePageRowsSelected() && "indeterminate")
}
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
aria-label="Select all"
/>
),
cell: ({ row }) => (
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value) => row.toggleSelected(!!value)}
aria-label="Select row"
/>
),
enableSorting: false,
enableHiding: false,
},
{
accessorKey: "status",
header: "Status",
cell: ({ row }) => (
<div className="capitalize">{row.getValue("status")}</div>
),
},
{
accessorKey: "email",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Email
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
)
},
cell: ({ row }) => <div className="lowercase">{row.getValue("email")}</div>,
},
{
accessorKey: "amount",
header: () => <div className="text-right">Amount</div>,
cell: ({ row }) => {
const amount = parseFloat(row.getValue("amount"))
// Format the amount as a dollar amount
const formatted = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
}).format(amount)
return <div className="text-right font-medium">{formatted}</div>
},
},
{
id: "actions",
enableHiding: false,
cell: ({ row }) => {
const payment = row.original
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="h-8 w-8 p-0">
<span className="sr-only">Open menu</span>
<MoreHorizontal className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuItem
onClick={() => navigator.clipboard.writeText(payment.id)}
>
Copy payment ID
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>View customer</DropdownMenuItem>
<DropdownMenuItem>View payment details</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
},
},
]
export default function DataTableDemo() {
const [sorting, setSorting] = React.useState<SortingState>([])
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
)
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({})
const [rowSelection, setRowSelection] = React.useState({})
const table = useReactTable({
data,
columns,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onColumnVisibilityChange: setColumnVisibility,
onRowSelectionChange: setRowSelection,
state: {
sorting,
columnFilters,
columnVisibility,
rowSelection,
},
})
return (
<div className="w-full">
<div className="flex items-center py-4">
<Input
placeholder="Filter emails..."
value={(table.getColumn("email")?.getFilterValue() as string) ?? ""}
onChange={(event) =>
table.getColumn("email")?.setFilterValue(event.target.value)
}
className="max-w-sm"
/>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" className="ml-auto">
Columns <ChevronDown className="ml-2 h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{table
.getAllColumns()
.filter((column) => column.getCanHide())
.map((column) => {
return (
<DropdownMenuCheckboxItem
key={column.id}
className="capitalize"
checked={column.getIsVisible()}
onCheckedChange={(value) =>
column.toggleVisibility(!!value)
}
>
{column.id}
</DropdownMenuCheckboxItem>
)
})}
</DropdownMenuContent>
</DropdownMenu>
</div>
<div className="rounded-md border">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
)
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
<div className="flex items-center justify-end space-x-2 py-4">
<div className="flex-1 text-sm text-muted-foreground">
{table.getFilteredSelectedRowModel().rows.length} of{" "}
{table.getFilteredRowModel().rows.length} row(s) selected.
</div>
<div className="space-x-2">
<Button
variant="outline"
size="sm"
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
>
Previous
</Button>
<Button
variant="outline"
size="sm"
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
>
Next
</Button>
</div>
</div>
</div>
)
}

View File

@@ -1,43 +0,0 @@
"use client"
import * as React from "react"
import { format } from "date-fns"
import { Calendar as CalendarIcon } from "lucide-react"
import { cn } from "@/lib/utils"
import { Button } from "@/registry/default/ui/button"
import { Calendar } from "@/registry/default/ui/calendar"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/registry/default/ui/popover"
export default function DatePickerDemo() {
const [date, setDate] = React.useState<Date>()
return (
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!date && "text-muted-foreground"
)}
>
<CalendarIcon className="mr-2 h-4 w-4" />
{date ? format(date, "PPP") : <span>Pick a date</span>}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={date}
onSelect={setDate}
initialFocus
/>
</PopoverContent>
</Popover>
)
}

View File

@@ -1,101 +0,0 @@
"use client"
import { zodResolver } from "@hookform/resolvers/zod"
import { format } from "date-fns"
import { CalendarIcon } from "lucide-react"
import { useForm } from "react-hook-form"
import { z } from "zod"
import { cn } from "@/lib/utils"
import { Button } from "@/registry/default/ui/button"
import { Calendar } from "@/registry/default/ui/calendar"
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/registry/default/ui/form"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/registry/default/ui/popover"
import { toast } from "@/registry/default/ui/use-toast"
const FormSchema = z.object({
dob: z.date({
required_error: "A date of birth is required.",
}),
})
export default function DatePickerForm() {
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
})
function onSubmit(data: z.infer<typeof FormSchema>) {
toast({
title: "You submitted the following values:",
description: (
<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
<code className="text-white">{JSON.stringify(data, null, 2)}</code>
</pre>
),
})
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="dob"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>Date of birth</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant={"outline"}
className={cn(
"w-[240px] pl-3 text-left font-normal",
!field.value && "text-muted-foreground"
)}
>
{field.value ? (
format(field.value, "PPP")
) : (
<span>Pick a date</span>
)}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={field.value}
onSelect={field.onChange}
disabled={(date) =>
date > new Date() || date < new Date("1900-01-01")
}
initialFocus
/>
</PopoverContent>
</Popover>
<FormDescription>
Your date of birth is used to calculate your age.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
)
}

View File

@@ -1,62 +0,0 @@
"use client"
import * as React from "react"
import { addDays, format } from "date-fns"
import { Calendar as CalendarIcon } from "lucide-react"
import { cn } from "@/lib/utils"
import { Button } from "@/registry/default/ui/button"
import { Calendar } from "@/registry/default/ui/calendar"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/registry/default/ui/popover"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/registry/default/ui/select"
export default function DatePickerWithPresets() {
const [date, setDate] = React.useState<Date>()
return (
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!date && "text-muted-foreground"
)}
>
<CalendarIcon className="mr-2 h-4 w-4" />
{date ? format(date, "PPP") : <span>Pick a date</span>}
</Button>
</PopoverTrigger>
<PopoverContent className="flex w-auto flex-col space-y-2 p-2">
<Select
onValueChange={(value) =>
setDate(addDays(new Date(), parseInt(value)))
}
>
<SelectTrigger>
<SelectValue placeholder="Select" />
</SelectTrigger>
<SelectContent position="popper">
<SelectItem value="0">Today</SelectItem>
<SelectItem value="1">Tomorrow</SelectItem>
<SelectItem value="3">In 3 days</SelectItem>
<SelectItem value="7">In a week</SelectItem>
</SelectContent>
</Select>
<div className="rounded-md border">
<Calendar mode="single" selected={date} onSelect={setDate} />
</div>
</PopoverContent>
</Popover>
)
}

View File

@@ -1,65 +0,0 @@
"use client"
import * as React from "react"
import { addDays, format } from "date-fns"
import { Calendar as CalendarIcon } from "lucide-react"
import { DateRange } from "react-day-picker"
import { cn } from "@/lib/utils"
import { Button } from "@/registry/default/ui/button"
import { Calendar } from "@/registry/default/ui/calendar"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/registry/default/ui/popover"
export default function DatePickerWithRange({
className,
}: React.HTMLAttributes<HTMLDivElement>) {
const [date, setDate] = React.useState<DateRange | undefined>({
from: new Date(2022, 0, 20),
to: addDays(new Date(2022, 0, 20), 20),
})
return (
<div className={cn("grid gap-2", className)}>
<Popover>
<PopoverTrigger asChild>
<Button
id="date"
variant={"outline"}
className={cn(
"w-[300px] justify-start text-left font-normal",
!date && "text-muted-foreground"
)}
>
<CalendarIcon className="mr-2 h-4 w-4" />
{date?.from ? (
date.to ? (
<>
{format(date.from, "LLL dd, y")} -{" "}
{format(date.to, "LLL dd, y")}
</>
) : (
format(date.from, "LLL dd, y")
)
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
initialFocus
mode="range"
defaultMonth={date?.from}
selected={date}
onSelect={setDate}
numberOfMonths={2}
/>
</PopoverContent>
</Popover>
</div>
)
}

View File

@@ -1,56 +0,0 @@
import { Copy } from "lucide-react"
import { Button } from "@/registry/default/ui/button"
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/registry/default/ui/dialog"
import { Input } from "@/registry/default/ui/input"
import { Label } from "@/registry/default/ui/label"
export default function DialogCloseButton() {
return (
<Dialog>
<DialogTrigger asChild>
<Button variant="outline">Share</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>Share link</DialogTitle>
<DialogDescription>
Anyone who has this link will be able to view this.
</DialogDescription>
</DialogHeader>
<div className="flex items-center space-x-2">
<div className="grid flex-1 gap-2">
<Label htmlFor="link" className="sr-only">
Link
</Label>
<Input
id="link"
defaultValue="https://ui.shadcn.com/docs/installation"
readOnly
/>
</div>
<Button type="submit" size="sm" className="px-3">
<span className="sr-only">Copy</span>
<Copy className="h-4 w-4" />
</Button>
</div>
<DialogFooter className="sm:justify-start">
<DialogClose asChild>
<Button type="button" variant="secondary">
Close
</Button>
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
)
}

View File

@@ -1,55 +0,0 @@
import { Button } from "@/registry/default/ui/button"
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/registry/default/ui/dialog"
import { Input } from "@/registry/default/ui/input"
import { Label } from "@/registry/default/ui/label"
export default function DialogDemo() {
return (
<Dialog>
<DialogTrigger asChild>
<Button variant="outline">Edit Profile</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Edit profile</DialogTitle>
<DialogDescription>
Make changes to your profile here. Click save when you're done.
</DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="name" className="text-right">
Name
</Label>
<Input
id="name"
defaultValue="Pedro Duarte"
className="col-span-3"
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="username" className="text-right">
Username
</Label>
<Input
id="username"
defaultValue="@peduarte"
className="col-span-3"
/>
</div>
</div>
<DialogFooter>
<Button type="submit">Save changes</Button>
</DialogFooter>
</DialogContent>
</Dialog>
)
}

View File

@@ -1,134 +0,0 @@
import * as React from "react"
import { Minus, Plus } from "lucide-react"
import { Bar, BarChart, ResponsiveContainer } from "recharts"
import { Button } from "@/registry/default/ui/button"
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from "@/registry/default/ui/drawer"
const data = [
{
goal: 400,
},
{
goal: 300,
},
{
goal: 200,
},
{
goal: 300,
},
{
goal: 200,
},
{
goal: 278,
},
{
goal: 189,
},
{
goal: 239,
},
{
goal: 300,
},
{
goal: 200,
},
{
goal: 278,
},
{
goal: 189,
},
{
goal: 349,
},
]
export default function DrawerDemo() {
const [goal, setGoal] = React.useState(350)
function onClick(adjustment: number) {
setGoal(Math.max(200, Math.min(400, goal + adjustment)))
}
return (
<Drawer>
<DrawerTrigger asChild>
<Button variant="outline">Open Drawer</Button>
</DrawerTrigger>
<DrawerContent>
<div className="mx-auto w-full max-w-sm">
<DrawerHeader>
<DrawerTitle>Move Goal</DrawerTitle>
<DrawerDescription>Set your daily activity goal.</DrawerDescription>
</DrawerHeader>
<div className="p-4 pb-0">
<div className="flex items-center justify-center space-x-2">
<Button
variant="outline"
size="icon"
className="h-8 w-8 shrink-0 rounded-full"
onClick={() => onClick(-10)}
disabled={goal <= 200}
>
<Minus className="h-4 w-4" />
<span className="sr-only">Decrease</span>
</Button>
<div className="flex-1 text-center">
<div className="text-7xl font-bold tracking-tighter">
{goal}
</div>
<div className="text-[0.70rem] uppercase text-muted-foreground">
Calories/day
</div>
</div>
<Button
variant="outline"
size="icon"
className="h-8 w-8 shrink-0 rounded-full"
onClick={() => onClick(10)}
disabled={goal >= 400}
>
<Plus className="h-4 w-4" />
<span className="sr-only">Increase</span>
</Button>
</div>
<div className="mt-3 h-[120px]">
<ResponsiveContainer width="100%" height="100%">
<BarChart data={data}>
<Bar
dataKey="goal"
style={
{
fill: "hsl(var(--foreground))",
opacity: 0.9,
} as React.CSSProperties
}
/>
</BarChart>
</ResponsiveContainer>
</div>
</div>
<DrawerFooter>
<Button>Submit</Button>
<DrawerClose asChild>
<Button variant="outline">Cancel</Button>
</DrawerClose>
</DrawerFooter>
</div>
</DrawerContent>
</Drawer>
)
}

View File

@@ -1,87 +0,0 @@
import * as React from "react"
import { cn } from "@/lib/utils"
import { useMediaQuery } from "@/hooks/use-media-query"
import { Button } from "@/registry/default/ui/button"
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/registry/default/ui/dialog"
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from "@/registry/default/ui/drawer"
import { Input } from "@/registry/default/ui/input"
import { Label } from "@/registry/default/ui/label"
export default function DrawerDialogDemo() {
const [open, setOpen] = React.useState(false)
const isDesktop = useMediaQuery("(min-width: 768px)")
if (isDesktop) {
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button variant="outline">Edit Profile</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Edit profile</DialogTitle>
<DialogDescription>
Make changes to your profile here. Click save when you're done.
</DialogDescription>
</DialogHeader>
<ProfileForm />
</DialogContent>
</Dialog>
)
}
return (
<Drawer open={open} onOpenChange={setOpen}>
<DrawerTrigger asChild>
<Button variant="outline">Edit Profile</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader className="text-left">
<DrawerTitle>Edit profile</DrawerTitle>
<DrawerDescription>
Make changes to your profile here. Click save when you're done.
</DrawerDescription>
</DrawerHeader>
<ProfileForm className="px-4" />
<DrawerFooter className="pt-2">
<DrawerClose asChild>
<Button variant="outline">Cancel</Button>
</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>
)
}
function ProfileForm({ className }: React.ComponentProps<"form">) {
return (
<form className={cn("grid items-start gap-4", className)}>
<div className="grid gap-2">
<Label htmlFor="email">Email</Label>
<Input type="email" id="email" defaultValue="shadcn@example.com" />
</div>
<div className="grid gap-2">
<Label htmlFor="username">Username</Label>
<Input id="username" defaultValue="@shadcn" />
</div>
<Button type="submit">Save changes</Button>
</form>
)
}

View File

@@ -1,53 +0,0 @@
"use client"
import * as React from "react"
import { DropdownMenuCheckboxItemProps } from "@radix-ui/react-dropdown-menu"
import { Button } from "@/registry/default/ui/button"
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/registry/default/ui/dropdown-menu"
type Checked = DropdownMenuCheckboxItemProps["checked"]
export default function DropdownMenuCheckboxes() {
const [showStatusBar, setShowStatusBar] = React.useState<Checked>(true)
const [showActivityBar, setShowActivityBar] = React.useState<Checked>(false)
const [showPanel, setShowPanel] = React.useState<Checked>(false)
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline">Open</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56">
<DropdownMenuLabel>Appearance</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuCheckboxItem
checked={showStatusBar}
onCheckedChange={setShowStatusBar}
>
Status Bar
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem
checked={showActivityBar}
onCheckedChange={setShowActivityBar}
disabled
>
Activity Bar
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem
checked={showPanel}
onCheckedChange={setShowPanel}
>
Panel
</DropdownMenuCheckboxItem>
</DropdownMenuContent>
</DropdownMenu>
)
}

View File

@@ -1,122 +0,0 @@
import {
Cloud,
CreditCard,
Github,
Keyboard,
LifeBuoy,
LogOut,
Mail,
MessageSquare,
Plus,
PlusCircle,
Settings,
User,
UserPlus,
Users,
} from "lucide-react"
import { Button } from "@/registry/default/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuPortal,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "@/registry/default/ui/dropdown-menu"
export default function DropdownMenuDemo() {
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline">Open</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56">
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem>
<User className="mr-2 h-4 w-4" />
<span>Profile</span>
<DropdownMenuShortcut>P</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
<CreditCard className="mr-2 h-4 w-4" />
<span>Billing</span>
<DropdownMenuShortcut>B</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
<Settings className="mr-2 h-4 w-4" />
<span>Settings</span>
<DropdownMenuShortcut>S</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
<Keyboard className="mr-2 h-4 w-4" />
<span>Keyboard shortcuts</span>
<DropdownMenuShortcut>K</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem>
<Users className="mr-2 h-4 w-4" />
<span>Team</span>
</DropdownMenuItem>
<DropdownMenuSub>
<DropdownMenuSubTrigger>
<UserPlus className="mr-2 h-4 w-4" />
<span>Invite users</span>
</DropdownMenuSubTrigger>
<DropdownMenuPortal>
<DropdownMenuSubContent>
<DropdownMenuItem>
<Mail className="mr-2 h-4 w-4" />
<span>Email</span>
</DropdownMenuItem>
<DropdownMenuItem>
<MessageSquare className="mr-2 h-4 w-4" />
<span>Message</span>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>
<PlusCircle className="mr-2 h-4 w-4" />
<span>More...</span>
</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuPortal>
</DropdownMenuSub>
<DropdownMenuItem>
<Plus className="mr-2 h-4 w-4" />
<span>New Team</span>
<DropdownMenuShortcut>+T</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuItem>
<Github className="mr-2 h-4 w-4" />
<span>GitHub</span>
</DropdownMenuItem>
<DropdownMenuItem>
<LifeBuoy className="mr-2 h-4 w-4" />
<span>Support</span>
</DropdownMenuItem>
<DropdownMenuItem disabled>
<Cloud className="mr-2 h-4 w-4" />
<span>API</span>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>
<LogOut className="mr-2 h-4 w-4" />
<span>Log out</span>
<DropdownMenuShortcut>Q</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
}

View File

@@ -1,35 +0,0 @@
"use client"
import * as React from "react"
import { Button } from "@/registry/default/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuLabel,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/registry/default/ui/dropdown-menu"
export default function DropdownMenuRadioGroupDemo() {
const [position, setPosition] = React.useState("bottom")
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline">Open</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56">
<DropdownMenuLabel>Panel Position</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuRadioGroup value={position} onValueChange={setPosition}>
<DropdownMenuRadioItem value="top">Top</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="bottom">Bottom</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="right">Right</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
)
}

View File

@@ -1,43 +0,0 @@
import { CalendarDays } from "lucide-react"
import {
Avatar,
AvatarFallback,
AvatarImage,
} from "@/registry/default/ui/avatar"
import { Button } from "@/registry/default/ui/button"
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from "@/registry/default/ui/hover-card"
export default function HoverCardDemo() {
return (
<HoverCard>
<HoverCardTrigger asChild>
<Button variant="link">@nextjs</Button>
</HoverCardTrigger>
<HoverCardContent className="w-80">
<div className="flex justify-between space-x-4">
<Avatar>
<AvatarImage src="https://github.com/vercel.png" />
<AvatarFallback>VC</AvatarFallback>
</Avatar>
<div className="space-y-1">
<h4 className="text-sm font-semibold">@nextjs</h4>
<p className="text-sm">
The React Framework created and maintained by @vercel.
</p>
<div className="flex items-center pt-2">
<CalendarDays className="mr-2 h-4 w-4 opacity-70" />{" "}
<span className="text-xs text-muted-foreground">
Joined December 2021
</span>
</div>
</div>
</div>
</HoverCardContent>
</HoverCard>
)
}

View File

@@ -1,5 +0,0 @@
import { Input } from "@/registry/default/ui/input"
export default function InputDemo() {
return <Input type="email" placeholder="Email" />
}

View File

@@ -1,5 +0,0 @@
import { Input } from "@/registry/default/ui/input"
export default function InputDisabled() {
return <Input disabled type="email" placeholder="Email" />
}

View File

@@ -1,11 +0,0 @@
import { Input } from "@/registry/default/ui/input"
import { Label } from "@/registry/default/ui/label"
export default function InputFile() {
return (
<div className="grid w-full max-w-sm items-center gap-1.5">
<Label htmlFor="picture">Picture</Label>
<Input id="picture" type="file" />
</div>
)
}

View File

@@ -1,68 +0,0 @@
"use client"
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
import { Button } from "@/registry/default/ui/button"
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/registry/default/ui/form"
import { Input } from "@/registry/default/ui/input"
import { toast } from "@/registry/default/ui/use-toast"
const FormSchema = z.object({
username: z.string().min(2, {
message: "Username must be at least 2 characters.",
}),
})
export default function InputForm() {
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: {
username: "",
},
})
function onSubmit(data: z.infer<typeof FormSchema>) {
toast({
title: "You submitted the following values:",
description: (
<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
<code className="text-white">{JSON.stringify(data, null, 2)}</code>
</pre>
),
})
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="w-2/3 space-y-6">
<FormField
control={form.control}
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="shadcn" {...field} />
</FormControl>
<FormDescription>
This is your public display name.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
)
}

View File

@@ -1,39 +0,0 @@
"use client"
import * as React from "react"
import {
InputOTP,
InputOTPGroup,
InputOTPSlot,
} from "@/registry/default/ui/input-otp"
export default function InputOTPControlled() {
const [value, setValue] = React.useState("")
return (
<div className="space-y-2">
<InputOTP
maxLength={6}
value={value}
onChange={(value) => setValue(value)}
>
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
<InputOTPSlot index={2} />
<InputOTPSlot index={3} />
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
</InputOTPGroup>
</InputOTP>
<div className="text-center text-sm">
{value === "" ? (
<>Enter your one-time password.</>
) : (
<>You entered: {value}</>
)}
</div>
</div>
)
}

View File

@@ -1,24 +0,0 @@
import {
InputOTP,
InputOTPGroup,
InputOTPSeparator,
InputOTPSlot,
} from "@/registry/default/ui/input-otp"
export default function InputOTPDemo() {
return (
<InputOTP maxLength={6}>
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
<InputOTPSlot index={2} />
</InputOTPGroup>
<InputOTPSeparator />
<InputOTPGroup>
<InputOTPSlot index={3} />
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
</InputOTPGroup>
</InputOTP>
)
}

View File

@@ -1,82 +0,0 @@
"use client"
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
import { Button } from "@/registry/default/ui/button"
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/registry/default/ui/form"
import {
InputOTP,
InputOTPGroup,
InputOTPSlot,
} from "@/registry/default/ui/input-otp"
import { toast } from "@/registry/default/ui/use-toast"
const FormSchema = z.object({
pin: z.string().min(6, {
message: "Your one-time password must be 6 characters.",
}),
})
export default function InputOTPForm() {
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: {
pin: "",
},
})
function onSubmit(data: z.infer<typeof FormSchema>) {
toast({
title: "You submitted the following values:",
description: (
<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
<code className="text-white">{JSON.stringify(data, null, 2)}</code>
</pre>
),
})
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="w-2/3 space-y-6">
<FormField
control={form.control}
name="pin"
render={({ field }) => (
<FormItem>
<FormLabel>One-Time Password</FormLabel>
<FormControl>
<InputOTP maxLength={6} {...field}>
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
<InputOTPSlot index={2} />
<InputOTPSlot index={3} />
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
</InputOTPGroup>
</InputOTP>
</FormControl>
<FormDescription>
Please enter the one-time password sent to your phone.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
)
}

View File

@@ -1,22 +0,0 @@
import { REGEXP_ONLY_DIGITS_AND_CHARS } from "input-otp"
import {
InputOTP,
InputOTPGroup,
InputOTPSlot,
} from "@/registry/default/ui/input-otp"
export default function InputOTPPattern() {
return (
<InputOTP maxLength={6} pattern={REGEXP_ONLY_DIGITS_AND_CHARS}>
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
<InputOTPSlot index={2} />
<InputOTPSlot index={3} />
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
</InputOTPGroup>
</InputOTP>
)
}

View File

@@ -1,29 +0,0 @@
import React from "react"
import {
InputOTP,
InputOTPGroup,
InputOTPSeparator,
InputOTPSlot,
} from "@/registry/default/ui/input-otp"
export default function InputOTPWithSeparator() {
return (
<InputOTP maxLength={6}>
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
</InputOTPGroup>
<InputOTPSeparator />
<InputOTPGroup>
<InputOTPSlot index={2} />
<InputOTPSlot index={3} />
</InputOTPGroup>
<InputOTPSeparator />
<InputOTPGroup>
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
</InputOTPGroup>
</InputOTP>
)
}

View File

@@ -1,11 +0,0 @@
import { Button } from "@/registry/default/ui/button"
import { Input } from "@/registry/default/ui/input"
export default function InputWithButton() {
return (
<div className="flex w-full max-w-sm items-center space-x-2">
<Input type="email" placeholder="Email" />
<Button type="submit">Subscribe</Button>
</div>
)
}

View File

@@ -1,11 +0,0 @@
import { Input } from "@/registry/default/ui/input"
import { Label } from "@/registry/default/ui/label"
export default function InputWithLabel() {
return (
<div className="grid w-full max-w-sm items-center gap-1.5">
<Label htmlFor="email">Email</Label>
<Input type="email" id="email" placeholder="Email" />
</div>
)
}

View File

@@ -1,12 +0,0 @@
import { Input } from "@/registry/default/ui/input"
import { Label } from "@/registry/default/ui/label"
export default function InputWithText() {
return (
<div className="grid w-full max-w-sm items-center gap-1.5">
<Label htmlFor="email-2">Email</Label>
<Input type="email" id="email-2" placeholder="Email" />
<p className="text-sm text-muted-foreground">Enter your email address.</p>
</div>
)
}

View File

@@ -1,13 +0,0 @@
import { Checkbox } from "@/registry/default/ui/checkbox"
import { Label } from "@/registry/default/ui/label"
export default function LabelDemo() {
return (
<div>
<div className="flex items-center space-x-2">
<Checkbox id="terms" />
<Label htmlFor="terms">Accept terms and conditions</Label>
</div>
</div>
)
}

View File

@@ -1,107 +0,0 @@
import {
Menubar,
MenubarCheckboxItem,
MenubarContent,
MenubarItem,
MenubarMenu,
MenubarRadioGroup,
MenubarRadioItem,
MenubarSeparator,
MenubarShortcut,
MenubarSub,
MenubarSubContent,
MenubarSubTrigger,
MenubarTrigger,
} from "@/registry/default/ui/menubar"
export default function MenubarDemo() {
return (
<Menubar>
<MenubarMenu>
<MenubarTrigger>File</MenubarTrigger>
<MenubarContent>
<MenubarItem>
New Tab <MenubarShortcut>T</MenubarShortcut>
</MenubarItem>
<MenubarItem>
New Window <MenubarShortcut>N</MenubarShortcut>
</MenubarItem>
<MenubarItem disabled>New Incognito Window</MenubarItem>
<MenubarSeparator />
<MenubarSub>
<MenubarSubTrigger>Share</MenubarSubTrigger>
<MenubarSubContent>
<MenubarItem>Email link</MenubarItem>
<MenubarItem>Messages</MenubarItem>
<MenubarItem>Notes</MenubarItem>
</MenubarSubContent>
</MenubarSub>
<MenubarSeparator />
<MenubarItem>
Print... <MenubarShortcut>P</MenubarShortcut>
</MenubarItem>
</MenubarContent>
</MenubarMenu>
<MenubarMenu>
<MenubarTrigger>Edit</MenubarTrigger>
<MenubarContent>
<MenubarItem>
Undo <MenubarShortcut>Z</MenubarShortcut>
</MenubarItem>
<MenubarItem>
Redo <MenubarShortcut>Z</MenubarShortcut>
</MenubarItem>
<MenubarSeparator />
<MenubarSub>
<MenubarSubTrigger>Find</MenubarSubTrigger>
<MenubarSubContent>
<MenubarItem>Search the web</MenubarItem>
<MenubarSeparator />
<MenubarItem>Find...</MenubarItem>
<MenubarItem>Find Next</MenubarItem>
<MenubarItem>Find Previous</MenubarItem>
</MenubarSubContent>
</MenubarSub>
<MenubarSeparator />
<MenubarItem>Cut</MenubarItem>
<MenubarItem>Copy</MenubarItem>
<MenubarItem>Paste</MenubarItem>
</MenubarContent>
</MenubarMenu>
<MenubarMenu>
<MenubarTrigger>View</MenubarTrigger>
<MenubarContent>
<MenubarCheckboxItem>Always Show Bookmarks Bar</MenubarCheckboxItem>
<MenubarCheckboxItem checked>
Always Show Full URLs
</MenubarCheckboxItem>
<MenubarSeparator />
<MenubarItem inset>
Reload <MenubarShortcut>R</MenubarShortcut>
</MenubarItem>
<MenubarItem disabled inset>
Force Reload <MenubarShortcut>R</MenubarShortcut>
</MenubarItem>
<MenubarSeparator />
<MenubarItem inset>Toggle Fullscreen</MenubarItem>
<MenubarSeparator />
<MenubarItem inset>Hide Sidebar</MenubarItem>
</MenubarContent>
</MenubarMenu>
<MenubarMenu>
<MenubarTrigger>Profiles</MenubarTrigger>
<MenubarContent>
<MenubarRadioGroup value="benoit">
<MenubarRadioItem value="andy">Andy</MenubarRadioItem>
<MenubarRadioItem value="benoit">Benoit</MenubarRadioItem>
<MenubarRadioItem value="Luis">Luis</MenubarRadioItem>
</MenubarRadioGroup>
<MenubarSeparator />
<MenubarItem inset>Edit...</MenubarItem>
<MenubarSeparator />
<MenubarItem inset>Add Profile...</MenubarItem>
</MenubarContent>
</MenubarMenu>
</Menubar>
)
}

View File

@@ -1,40 +0,0 @@
"use client"
import * as React from "react"
import { Moon, Sun } from "lucide-react"
import { useTheme } from "next-themes"
import { Button } from "@/registry/default/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/registry/default/ui/dropdown-menu"
export default function ModeToggle() {
const { setTheme } = useTheme()
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" size="icon">
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Toggle theme</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem onClick={() => setTheme("light")}>
Light
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("dark")}>
Dark
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("system")}>
System
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
}

View File

@@ -1,146 +0,0 @@
"use client"
import * as React from "react"
import Link from "next/link"
import { cn } from "@/lib/utils"
import { Icons } from "@/components/icons"
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
navigationMenuTriggerStyle,
} from "@/registry/default/ui/navigation-menu"
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.",
},
]
export default function NavigationMenuDemo() {
return (
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>Getting started</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid gap-3 p-6 md:w-[400px] lg:w-[500px] lg:grid-cols-[.75fr_1fr]">
<li className="row-span-3">
<NavigationMenuLink asChild>
<a
className="flex h-full w-full select-none flex-col justify-end rounded-md bg-gradient-to-b from-muted/50 to-muted p-6 no-underline outline-none focus:shadow-md"
href="/"
>
<Icons.logo className="h-6 w-6" />
<div className="mb-2 mt-4 text-lg font-medium">
shadcn/ui
</div>
<p className="text-sm leading-tight text-muted-foreground">
Beautifully designed components that you can copy and
paste into your apps. Accessible. Customizable. Open
Source.
</p>
</a>
</NavigationMenuLink>
</li>
<ListItem href="/docs" title="Introduction">
Re-usable components built using Radix UI and Tailwind CSS.
</ListItem>
<ListItem href="/docs/installation" title="Installation">
How to install dependencies and structure your app.
</ListItem>
<ListItem href="/docs/primitives/typography" title="Typography">
Styles for headings, paragraphs, lists...etc
</ListItem>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuTrigger>Components</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px] ">
{components.map((component) => (
<ListItem
key={component.title}
title={component.title}
href={component.href}
>
{component.description}
</ListItem>
))}
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem>
<Link href="/docs" legacyBehavior passHref>
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
Documentation
</NavigationMenuLink>
</Link>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
)
}
const ListItem = React.forwardRef<
React.ElementRef<"a">,
React.ComponentPropsWithoutRef<"a">
>(({ className, title, children, ...props }, ref) => {
return (
<li>
<NavigationMenuLink asChild>
<a
ref={ref}
className={cn(
"block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
className
)}
{...props}
>
<div className="text-sm font-medium leading-none">{title}</div>
<p className="line-clamp-2 text-sm leading-snug text-muted-foreground">
{children}
</p>
</a>
</NavigationMenuLink>
</li>
)
})
ListItem.displayName = "ListItem"

View File

@@ -1,38 +0,0 @@
import {
Pagination,
PaginationContent,
PaginationEllipsis,
PaginationItem,
PaginationLink,
PaginationNext,
PaginationPrevious,
} from "@/registry/default/ui/pagination"
export default function PaginationDemo() {
return (
<Pagination>
<PaginationContent>
<PaginationItem>
<PaginationPrevious href="#" />
</PaginationItem>
<PaginationItem>
<PaginationLink href="#">1</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="#" isActive>
2
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="#">3</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationEllipsis />
</PaginationItem>
<PaginationItem>
<PaginationNext href="#" />
</PaginationItem>
</PaginationContent>
</Pagination>
)
}

View File

@@ -1,62 +0,0 @@
import { Button } from "@/registry/default/ui/button"
import { Input } from "@/registry/default/ui/input"
import { Label } from "@/registry/default/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/registry/default/ui/popover"
export default function PopoverDemo() {
return (
<Popover>
<PopoverTrigger asChild>
<Button variant="outline">Open popover</Button>
</PopoverTrigger>
<PopoverContent className="w-80">
<div className="grid gap-4">
<div className="space-y-2">
<h4 className="font-medium leading-none">Dimensions</h4>
<p className="text-sm text-muted-foreground">
Set the dimensions for the layer.
</p>
</div>
<div className="grid gap-2">
<div className="grid grid-cols-3 items-center gap-4">
<Label htmlFor="width">Width</Label>
<Input
id="width"
defaultValue="100%"
className="col-span-2 h-8"
/>
</div>
<div className="grid grid-cols-3 items-center gap-4">
<Label htmlFor="maxWidth">Max. width</Label>
<Input
id="maxWidth"
defaultValue="300px"
className="col-span-2 h-8"
/>
</div>
<div className="grid grid-cols-3 items-center gap-4">
<Label htmlFor="height">Height</Label>
<Input
id="height"
defaultValue="25px"
className="col-span-2 h-8"
/>
</div>
<div className="grid grid-cols-3 items-center gap-4">
<Label htmlFor="maxHeight">Max. height</Label>
<Input
id="maxHeight"
defaultValue="none"
className="col-span-2 h-8"
/>
</div>
</div>
</div>
</PopoverContent>
</Popover>
)
}

View File

@@ -1,16 +0,0 @@
"use client"
import * as React from "react"
import { Progress } from "@/registry/default/ui/progress"
export default function ProgressDemo() {
const [progress, setProgress] = React.useState(13)
React.useEffect(() => {
const timer = setTimeout(() => setProgress(66), 500)
return () => clearTimeout(timer)
}, [])
return <Progress value={progress} className="w-[60%]" />
}

View File

@@ -1,21 +0,0 @@
import { Label } from "@/registry/default/ui/label"
import { RadioGroup, RadioGroupItem } from "@/registry/default/ui/radio-group"
export default function RadioGroupDemo() {
return (
<RadioGroup defaultValue="comfortable">
<div className="flex items-center space-x-2">
<RadioGroupItem value="default" id="r1" />
<Label htmlFor="r1">Default</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="comfortable" id="r2" />
<Label htmlFor="r2">Comfortable</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="compact" id="r3" />
<Label htmlFor="r3">Compact</Label>
</div>
</RadioGroup>
)
}

View File

@@ -1,88 +0,0 @@
"use client"
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
import { Button } from "@/registry/default/ui/button"
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/registry/default/ui/form"
import { RadioGroup, RadioGroupItem } from "@/registry/default/ui/radio-group"
import { toast } from "@/registry/default/ui/use-toast"
const FormSchema = z.object({
type: z.enum(["all", "mentions", "none"], {
required_error: "You need to select a notification type.",
}),
})
export default function RadioGroupForm() {
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
})
function onSubmit(data: z.infer<typeof FormSchema>) {
toast({
title: "You submitted the following values:",
description: (
<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
<code className="text-white">{JSON.stringify(data, null, 2)}</code>
</pre>
),
})
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="w-2/3 space-y-6">
<FormField
control={form.control}
name="type"
render={({ field }) => (
<FormItem className="space-y-3">
<FormLabel>Notify me about...</FormLabel>
<FormControl>
<RadioGroup
onValueChange={field.onChange}
defaultValue={field.value}
className="flex flex-col space-y-1"
>
<FormItem className="flex items-center space-x-3 space-y-0">
<FormControl>
<RadioGroupItem value="all" />
</FormControl>
<FormLabel className="font-normal">
All new messages
</FormLabel>
</FormItem>
<FormItem className="flex items-center space-x-3 space-y-0">
<FormControl>
<RadioGroupItem value="mentions" />
</FormControl>
<FormLabel className="font-normal">
Direct messages and mentions
</FormLabel>
</FormItem>
<FormItem className="flex items-center space-x-3 space-y-0">
<FormControl>
<RadioGroupItem value="none" />
</FormControl>
<FormLabel className="font-normal">Nothing</FormLabel>
</FormItem>
</RadioGroup>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
)
}

View File

@@ -1,36 +0,0 @@
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@/registry/default/ui/resizable"
export default function ResizableDemo() {
return (
<ResizablePanelGroup
direction="horizontal"
className="max-w-md rounded-lg border"
>
<ResizablePanel defaultSize={50}>
<div className="flex h-[200px] items-center justify-center p-6">
<span className="font-semibold">One</span>
</div>
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel defaultSize={50}>
<ResizablePanelGroup direction="vertical">
<ResizablePanel defaultSize={25}>
<div className="flex h-full items-center justify-center p-6">
<span className="font-semibold">Two</span>
</div>
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel defaultSize={75}>
<div className="flex h-full items-center justify-center p-6">
<span className="font-semibold">Three</span>
</div>
</ResizablePanel>
</ResizablePanelGroup>
</ResizablePanel>
</ResizablePanelGroup>
)
}

View File

@@ -1,36 +0,0 @@
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@/registry/default/ui/resizable"
export default function ResizableDemo() {
return (
<ResizablePanelGroup
direction="horizontal"
className="max-w-md rounded-lg border"
>
<ResizablePanel defaultSize={50}>
<div className="flex h-[200px] items-center justify-center p-6">
<span className="font-semibold">One</span>
</div>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel defaultSize={50}>
<ResizablePanelGroup direction="vertical">
<ResizablePanel defaultSize={25}>
<div className="flex h-full items-center justify-center p-6">
<span className="font-semibold">Two</span>
</div>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel defaultSize={75}>
<div className="flex h-full items-center justify-center p-6">
<span className="font-semibold">Three</span>
</div>
</ResizablePanel>
</ResizablePanelGroup>
</ResizablePanel>
</ResizablePanelGroup>
)
}

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