Compare commits

..

97 Commits

Author SHA1 Message Date
github-actions[bot]
2b276de95a chore(release): version packages (#5625)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-29 21:39:58 +04:00
shadcn
64739f8399 feat: react 19 (#5621)
* feat(shadcn): add flag prompt for npm

* docs: add docs for react 19

* chore: add changeset

* test: update snapshots

* docs: add notes for recharts

* docs: fix

* fix

* fix: linting
2024-10-29 21:30:05 +04:00
shadcn
f0cff7e0eb fix: gaps in command and dropdown-menu (#5570)
* fix: gaps in command and dropdown-menu

* chore: update snapshots
2024-10-25 18:13:13 +04:00
github-actions[bot]
e242adaa9c chore(release): version packages (#5568)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-25 17:52:32 +04:00
Kiyan
986c00ee0e fix: shadcn init with correct packageManager (#5299)
* fix: shadcn init with correct  packageManager

* chore: changeset

---------

Co-authored-by: shadcn <m@shadcn.com>
2024-10-25 17:46:48 +04:00
shadcn
d0eece06d4 fix: update registry (#5530) 2024-10-23 17:35:26 +04:00
github-actions[bot]
0a0a566a4e chore(release): version packages (#5526)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-23 11:35:28 +04:00
Braden Corbold
bf5a79c4d4 fix(shadcn): fix transformRsc to account for ' (#5518)
* fix(shadcn): fix transformRsc to account for '

* chore: add changeset

---------

Co-authored-by: shadcn <m@shadcn.com>
2024-10-23 11:33:11 +04:00
shadcn
f02b412478 fix(shadcn): temporarily pin create-next-app (#5525)
* feat: temporarily pin create-next-app

* chore: add changeset
2024-10-23 11:30:29 +04:00
DADDOU Mohamed El Amine
0d31293c7b docs: add missing installation step in the sidebar documentation (#5467) 2024-10-22 12:15:03 +04:00
Jacob Paris
3d1d19fc1b fix(sidebar): only apply text-sidebar-foreground to sidebar (#5491)
The text-sidebar-foreground class was applied to the SidebarProvider, which is designed to wrap the whole app, therefore making the whole app inherit its font color. This has been removed. The correct place for it is in the Sidebar component

Of the 3 possible return cases in the Sidebar component, 2 already applied the text-sidebar-foreground and I have added it to the third
2024-10-22 08:02:20 +00:00
BNaushad
e5b56c84a9 docs(sidebar): fix typo in sidebar documentation (#5487) 2024-10-22 11:42:38 +04:00
shadcn
630afe836e fix: sidebar provider 2024-10-21 12:38:51 +04:00
Jakob Ortmann
52c12bc27a fix import in sidebar example (#5438) 2024-10-21 11:46:27 +04:00
JEM
182f2083cd docs(sidebar): Fix sidebar toggle text for consistent behavior (#5428) 2024-10-21 11:45:11 +04:00
Phaired
3febcdc523 docs: fix type in sidebar.mdx (#5452) 2024-10-21 11:43:35 +04:00
EdamAmex
ced2513137 docs: fix prop name (#5460) 2024-10-21 11:43:08 +04:00
shadcn
93ae8bd67f chore: deprecate next-template (#5478)
* chore: deprecate next-template

* chore: tests
2024-10-21 11:40:54 +04:00
shadcn
3259fb7ca1 fix: overflow on icon 2024-10-19 01:28:07 +04:00
shadcn
d8397d80a8 chore: rebuild registry 2024-10-18 23:25:49 +04:00
shadcn
06e74fce78 Merge branch 'shadcn/sidebar-tsx'
# Conflicts:
#	apps/www/public/r/styles/default/use-mobile.json
#	apps/www/public/r/styles/new-york/button.json
#	apps/www/public/r/styles/new-york/dropdown-menu.json
#	apps/www/public/r/styles/new-york/use-mobile.json
#	apps/www/registry/new-york/ui/button.tsx
#	apps/www/registry/new-york/ui/dropdown-menu.tsx
2024-10-18 23:14:27 +04:00
shadcn
bc9e5eaaab test: fix 2024-10-18 22:52:25 +04:00
shadcn
c9b69d0836 docs: remove beta 2024-10-18 22:22:25 +04:00
shadcn
539212c49e feat: add redirect 2024-10-18 15:29:28 +04:00
shadcn
123887c36c fix: blocks 2024-10-18 00:54:19 +04:00
shadcn
35c1ba57c2 feat: add login-01 to v0 2024-10-18 00:34:03 +04:00
shadcn
b34516f471 fix: lint 2024-10-17 22:59:23 +04:00
shadcn
66b95402c1 feat: add v0 registry blocks 2024-10-17 22:58:20 +04:00
shadcn
5460177a7a fix: sidebar-07 2024-10-17 19:49:28 +04:00
shadcn
b0049c2266 fix: data-name 2024-10-17 17:13:47 +04:00
shadcn
4e6e21f094 fix: dark mode blocks 2024-10-17 17:01:24 +04:00
shadcn
3b808c83be fix: lint 2024-10-17 16:33:34 +04:00
shadcn
0e6b37e99a feat: update preview for mobile 2024-10-17 16:28:09 +04:00
shadcn
9ec433838f fix: lint 2024-10-17 01:11:00 +04:00
shadcn
444ff70590 feat: add notice 2024-10-17 01:06:35 +04:00
shadcn
27bc5deff1 docs: beta testers 2024-10-17 00:55:28 +04:00
shadcn
cacd7c8798 fix: use-mobile 2024-10-17 00:36:50 +04:00
shadcn
f227f93742 fix: sidebar 2024-10-17 00:34:50 +04:00
shadcn
87e099a3d7 feat: update button and dropdown menu (#5408) 2024-10-17 00:21:03 +04:00
shadcn
303d65718c chore: registry updates 2024-10-16 23:58:44 +04:00
shadcn
909219df14 docs 2024-10-16 15:33:16 +04:00
shadcn
e8ada4e3c7 docs 2024-10-16 14:33:43 +04:00
shadcn
8fc80836ff docs 2024-10-16 12:54:21 +04:00
shadcn
d0a308cc64 fix: edit in v0 2024-10-16 11:12:58 +04:00
shadcn
e461c02389 feat: update open in v0 2024-10-15 21:28:38 +04:00
shadcn
50c2f6045a chore: fix lint 2024-10-15 12:52:40 +04:00
shadcn
14aca65eee docs: add sidebar docs 2024-10-15 12:49:22 +04:00
shadcn
14c952b594 chore: update registry 2024-10-15 12:41:20 +04:00
shadcn
1e9434e6f9 chore: build registry 2024-10-15 12:38:45 +04:00
shadcn
f3d14c48cb feat(www): update button and tooltip 2024-10-15 12:38:32 +04:00
shadcn
c668c35bb9 feat(www): add sidebar components 2024-10-15 12:37:47 +04:00
shadcn
1297abc882 fix: v0 2024-10-07 21:13:33 +04:00
shadcn
36ebbf26dc docs(www): update figma 2024-09-29 14:52:52 +04:00
github-actions[bot]
a2abc4ad95 chore(release): version packages (#4963)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-09-27 22:10:05 +04:00
Thomas Raffray
4b546bfb13 fix(cli): remix detection (#4972)
# What

Some remix templates doesn't package a `vite.config.*` file at their root.
It's the case for the recommended starter "stack" templates: blues-stack, indie-stack and grunge-stack.
As recommended in a TODO comment, it's more suitable to check for a `@remix-run/*` dependency in the package dependencies.

# How

- decouple vite and remix checks
- retrieve the `package.json`
- allow passing a `cwd` to the retrieval method
- remove the "empty config file list" that can be empty for a remix stack
- check that the `package.json` contains a `@remix-run/*` dependency

# Test

Added a fixture by running `npx create-remix@latest --template remix-run/indie-stack` in the [frameworks](/Fluf22/shadcn-ui/tree/fix/cli-remix-detection/packages/cli/test/fixtures/frameworks) folder and named it `remix-indie-stack`, if ever we want another stack as a fixture later

---

Fixes shadcn-ui/ui#4967
2024-09-27 17:58:46 +00:00
shadcn
5fc9ade413 chore(cli): add deprecation notice (#4988)
* feat(cli): add deprecation message

* chore: changesets
2024-09-27 17:43:16 +04:00
Nami Sunami
96880e7c9a fix: Fix the typo in error messages (component.jsoncomponents.json) (#4977)
* fix(prompt): fix error message, component.json -> components.json

* fix(config): fix the error message, component.json -> components.json

* chore: changeset

---------

Co-authored-by: shadcn <m@shadcn.com>
2024-09-27 16:01:04 +04:00
Artem Zakharchenko
7dfdb029e7 use "?url" suffix in "tailwind.css" import (Remix) (#4945)
Importing `tailwind.css` is incorrect as it will treat that file as a CSS Module, throwing that it has no `default` export. 

Instead, the tutorial relies on the import returning a _URL_ to the stylesheet. Adding `?url` to the import specifier is the way to go.
2024-09-26 12:42:49 +00:00
shadcn
28f34ed3c3 feat(shadcn): recursively resolve registry dependencies (#4961)
* feat(shadcn): recursively resolve registry dependencies

* chore: add changeset

* ci: update actions/upload-artifact
2024-09-25 22:56:39 +04:00
github-actions[bot]
bd54184e60 chore(release): version packages (#4938)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-09-23 15:21:55 +04:00
Braden Corbold
ce3adfa075 fix(shadcn): Support single quote formatted registry files (#4870) (#4871) 2024-09-23 11:47:37 +04:00
Shivang Rathore
674807c1b4 fix(shadcn): Ensure .scss files are considered in init command (#4866)
Co-authored-by: shadcn <m@shadcn.com>
2024-09-23 11:44:27 +04:00
sapenlei
c62167a449 fix(shadcn): default next styles are not completely cleared (#4922)
* fix(shadcn):  default next styles are not completely cleared

* chore: add changeset

* fix(shadcn): tests

---------

Co-authored-by: shadcn <m@shadcn.com>
2024-09-23 11:38:59 +04:00
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
2088 changed files with 84391 additions and 24084 deletions

View File

@@ -1,14 +1,11 @@
{
"$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json",
"changelog": [
"@changesets/changelog-github",
{ "repo": "shadcn-ui/ui-private" }
],
"changelog": ["@changesets/changelog-github", { "repo": "shadcn-ui/ui" }],
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": ["www", "**-template"]
"ignore": ["www"]
}

View File

@@ -1,5 +0,0 @@
---
"shadcn-ui": minor
---
Add support for frameworks

View File

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

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

@@ -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
uses: actions/upload-artifact@v3
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

7
.gitignore vendored
View File

@@ -33,4 +33,9 @@ yarn-error.log*
.turbo
.contentlayer
tsconfig.tsbuildinfo
tsconfig.tsbuildinfo
# ide
.idea
.fleet
.vscode

View File

@@ -56,7 +56,7 @@ export default function Dashboard() {
<aside className="inset-y fixed left-0 z-20 flex h-full flex-col border-r">
<div className="border-b p-2">
<Button variant="outline" size="icon" aria-label="Home">
<Triangle className="size-5 fill-foreground" />
<Triangle className="w-5 h-5 fill-foreground" />
</Button>
</div>
<nav className="grid gap-1 p-2">
@@ -68,7 +68,7 @@ export default function Dashboard() {
className="rounded-lg bg-muted"
aria-label="Playground"
>
<SquareTerminal className="size-5" />
<SquareTerminal className="w-5 h-5" />
</Button>
</TooltipTrigger>
<TooltipContent side="right" sideOffset={5}>
@@ -83,7 +83,7 @@ export default function Dashboard() {
className="rounded-lg"
aria-label="Models"
>
<Bot className="size-5" />
<Bot className="w-5 h-5" />
</Button>
</TooltipTrigger>
<TooltipContent side="right" sideOffset={5}>
@@ -98,7 +98,7 @@ export default function Dashboard() {
className="rounded-lg"
aria-label="API"
>
<Code2 className="size-5" />
<Code2 className="w-5 h-5" />
</Button>
</TooltipTrigger>
<TooltipContent side="right" sideOffset={5}>
@@ -113,7 +113,7 @@ export default function Dashboard() {
className="rounded-lg"
aria-label="Documentation"
>
<Book className="size-5" />
<Book className="w-5 h-5" />
</Button>
</TooltipTrigger>
<TooltipContent side="right" sideOffset={5}>
@@ -128,7 +128,7 @@ export default function Dashboard() {
className="rounded-lg"
aria-label="Settings"
>
<Settings2 className="size-5" />
<Settings2 className="w-5 h-5" />
</Button>
</TooltipTrigger>
<TooltipContent side="right" sideOffset={5}>
@@ -145,7 +145,7 @@ export default function Dashboard() {
className="mt-auto rounded-lg"
aria-label="Help"
>
<LifeBuoy className="size-5" />
<LifeBuoy className="w-5 h-5" />
</Button>
</TooltipTrigger>
<TooltipContent side="right" sideOffset={5}>
@@ -160,7 +160,7 @@ export default function Dashboard() {
className="mt-auto rounded-lg"
aria-label="Account"
>
<SquareUser className="size-5" />
<SquareUser className="w-5 h-5" />
</Button>
</TooltipTrigger>
<TooltipContent side="right" sideOffset={5}>
@@ -175,7 +175,7 @@ export default function Dashboard() {
<Drawer>
<DrawerTrigger asChild>
<Button variant="ghost" size="icon" className="md:hidden">
<Settings className="size-4" />
<Settings className="w-4 h-4" />
<span className="sr-only">Settings</span>
</Button>
</DrawerTrigger>
@@ -203,7 +203,7 @@ export default function Dashboard() {
<SelectContent>
<SelectItem value="genesis">
<div className="flex items-start gap-3 text-muted-foreground">
<Rabbit className="size-5" />
<Rabbit className="w-5 h-5" />
<div className="grid gap-0.5">
<p>
Neural{" "}
@@ -219,7 +219,7 @@ export default function Dashboard() {
</SelectItem>
<SelectItem value="explorer">
<div className="flex items-start gap-3 text-muted-foreground">
<Bird className="size-5" />
<Bird className="w-5 h-5" />
<div className="grid gap-0.5">
<p>
Neural{" "}
@@ -235,7 +235,7 @@ export default function Dashboard() {
</SelectItem>
<SelectItem value="quantum">
<div className="flex items-start gap-3 text-muted-foreground">
<Turtle className="size-5" />
<Turtle className="w-5 h-5" />
<div className="grid gap-0.5">
<p>
Neural{" "}
@@ -296,7 +296,7 @@ export default function Dashboard() {
size="sm"
className="ml-auto gap-1.5 text-sm"
>
<Share className="size-3.5" />
<Share className="w-3.5 h-3.5" />
Share
</Button>
</header>
@@ -322,7 +322,7 @@ export default function Dashboard() {
<SelectContent>
<SelectItem value="genesis">
<div className="flex items-start gap-3 text-muted-foreground">
<Rabbit className="size-5" />
<Rabbit className="w-5 h-5" />
<div className="grid gap-0.5">
<p>
Neural{" "}
@@ -338,7 +338,7 @@ export default function Dashboard() {
</SelectItem>
<SelectItem value="explorer">
<div className="flex items-start gap-3 text-muted-foreground">
<Bird className="size-5" />
<Bird className="w-5 h-5" />
<div className="grid gap-0.5">
<p>
Neural{" "}
@@ -354,7 +354,7 @@ export default function Dashboard() {
</SelectItem>
<SelectItem value="quantum">
<div className="flex items-start gap-3 text-muted-foreground">
<Turtle className="size-5" />
<Turtle className="w-5 h-5" />
<div className="grid gap-0.5">
<p>
Neural{" "}
@@ -435,7 +435,7 @@ export default function Dashboard() {
<Tooltip>
<TooltipTrigger asChild>
<Button variant="ghost" size="icon">
<Paperclip className="size-4" />
<Paperclip className="w-4 h-4" />
<span className="sr-only">Attach file</span>
</Button>
</TooltipTrigger>
@@ -444,7 +444,7 @@ export default function Dashboard() {
<Tooltip>
<TooltipTrigger asChild>
<Button variant="ghost" size="icon">
<Mic className="size-4" />
<Mic className="w-4 h-4" />
<span className="sr-only">Use Microphone</span>
</Button>
</TooltipTrigger>
@@ -452,7 +452,7 @@ export default function Dashboard() {
</Tooltip>
<Button type="submit" size="sm" className="ml-auto gap-1.5">
Send Message
<CornerDownLeft className="size-3.5" />
<CornerDownLeft className="w-3.5 h-3.5" />
</Button>
</div>
</form>

View File

@@ -0,0 +1,96 @@
"use client"
import * as React from "react"
import {
Frame,
LifeBuoy,
Map,
PanelLeftClose,
PanelLeftOpen,
PieChart,
Send,
} from "lucide-react"
import { Button } from "@/registry/default/ui/button"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarInset,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
} from "@/registry/default/ui/sidebar"
const projects = [
{
name: "Design Engineering",
url: "#",
icon: Frame,
},
{
name: "Sales & Marketing",
url: "#",
icon: PieChart,
},
{
name: "Travel",
url: "#",
icon: Map,
},
{
name: "Support",
url: "#",
icon: LifeBuoy,
},
{
name: "Feedback",
url: "#",
icon: Send,
},
]
export default function AppSidebar() {
const [open, setOpen] = React.useState(true)
return (
<SidebarProvider open={open} onOpenChange={setOpen}>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Projects</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{projects.map((project) => (
<SidebarMenuItem key={project.name}>
<SidebarMenuButton asChild>
<a href={project.url}>
<project.icon />
<span>{project.name}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
<SidebarInset>
<header className="flex items-center h-12 px-4 justify-between">
<Button
onClick={() => setOpen((open) => !open)}
size="sm"
variant="ghost"
>
{open ? <PanelLeftClose /> : <PanelLeftOpen />}
<span>{open ? "Close" : "Open"} Sidebar</span>
</Button>
</header>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,66 @@
"use client"
import { ChevronDown, ChevronUp, User2 } from "lucide-react"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/registry/default/ui/dropdown-menu"
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarHeader,
SidebarInset,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
SidebarTrigger,
} from "@/registry/default/ui/sidebar"
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarHeader />
<SidebarContent />
<SidebarFooter>
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<SidebarMenuButton className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground">
Username
<ChevronUp className="ml-auto" />
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent
side="top"
className="w-[--radix-popper-anchor-width]"
>
<DropdownMenuItem>
<span>Account</span>
</DropdownMenuItem>
<DropdownMenuItem>
<span>Billing</span>
</DropdownMenuItem>
<DropdownMenuItem>
<span>Sign out</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
</SidebarFooter>
</Sidebar>
<SidebarInset>
<header className="flex items-center justify-between px-4 h-12">
<SidebarTrigger />
</header>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,79 @@
"use client"
import {
ChevronDown,
Frame,
LifeBuoy,
Map,
PieChart,
Plus,
Send,
} from "lucide-react"
import { Toaster, toast } from "sonner"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupAction,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
} from "@/registry/default/ui/sidebar"
export default function AppSidebar() {
return (
<SidebarProvider>
<Toaster
position="bottom-left"
toastOptions={{
className: "ml-[160px]",
}}
/>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Projects</SidebarGroupLabel>
<SidebarGroupAction
title="Add Project"
onClick={() => toast("You clicked the group action!")}
>
<Plus /> <span className="sr-only">Add Project</span>
</SidebarGroupAction>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton asChild>
<a href="#">
<Frame />
<span>Design Engineering</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton asChild>
<a href="#">
<PieChart />
<span>Sales & Marketing</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton asChild>
<a href="#">
<Map />
<span>Travel</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,62 @@
"use client"
import { ChevronDown, LifeBuoy, Send } from "lucide-react"
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/registry/default/ui/collapsible"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
} from "@/registry/default/ui/sidebar"
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<Collapsible defaultOpen className="group/collapsible">
<SidebarGroup>
<SidebarGroupLabel
asChild
className="text-sm hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"
>
<CollapsibleTrigger>
Help
<ChevronDown className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-180" />
</CollapsibleTrigger>
</SidebarGroupLabel>
<CollapsibleContent>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton>
<LifeBuoy />
Support
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton>
<Send />
Feedback
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</CollapsibleContent>
</SidebarGroup>
</Collapsible>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,45 @@
"use client"
import { LifeBuoy, Send } from "lucide-react"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
} from "@/registry/default/ui/sidebar"
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Help</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton>
<LifeBuoy />
Support
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton>
<Send />
Feedback
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,56 @@
"use client"
import { ChevronDown } from "lucide-react"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/registry/default/ui/dropdown-menu"
import {
Sidebar,
SidebarHeader,
SidebarInset,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
SidebarTrigger,
} from "@/registry/default/ui/sidebar"
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<SidebarMenuButton className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground">
Select Workspace
<ChevronDown className="ml-auto" />
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-[--radix-popper-anchor-width]">
<DropdownMenuItem>
<span>Acme Inc</span>
</DropdownMenuItem>
<DropdownMenuItem>
<span>Acme Corp.</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
</Sidebar>
<SidebarInset>
<header className="flex items-center justify-between px-4 h-12">
<SidebarTrigger />
</header>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,104 @@
"use client"
import {
Frame,
LifeBuoy,
Map,
MoreHorizontal,
PieChart,
Send,
} from "lucide-react"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/registry/default/ui/dropdown-menu"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuAction,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
} from "@/registry/default/ui/sidebar"
const projects = [
{
name: "Design Engineering",
url: "#",
icon: Frame,
},
{
name: "Sales & Marketing",
url: "#",
icon: PieChart,
},
{
name: "Travel",
url: "#",
icon: Map,
},
{
name: "Support",
url: "#",
icon: LifeBuoy,
},
{
name: "Feedback",
url: "#",
icon: Send,
},
]
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Projects</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{projects.map((project, index) => (
<SidebarMenuItem key={project.name}>
<SidebarMenuButton
asChild
className="group-has-[[data-state=open]]/menu-item:bg-sidebar-accent"
>
<a href={project.url}>
<project.icon />
<span>{project.name}</span>
</a>
</SidebarMenuButton>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<SidebarMenuAction>
<MoreHorizontal />
<span className="sr-only">More</span>
</SidebarMenuAction>
</DropdownMenuTrigger>
<DropdownMenuContent side="right" align="start">
<DropdownMenuItem>
<span>Edit Project</span>
</DropdownMenuItem>
<DropdownMenuItem>
<span>Delete Project</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,81 @@
"use client"
import { Frame, LifeBuoy, Map, PieChart, Send } from "lucide-react"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuBadge,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
} from "@/registry/default/ui/sidebar"
const projects = [
{
name: "Design Engineering",
url: "#",
icon: Frame,
badge: "24",
},
{
name: "Sales & Marketing",
url: "#",
icon: PieChart,
badge: "12",
},
{
name: "Travel",
url: "#",
icon: Map,
badge: "3",
},
{
name: "Support",
url: "#",
icon: LifeBuoy,
badge: "21",
},
{
name: "Feedback",
url: "#",
icon: Send,
badge: "8",
},
]
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Projects</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{projects.map((project) => (
<SidebarMenuItem key={project.name}>
<SidebarMenuButton
asChild
className="group-has-[[data-state=open]]/menu-item:bg-sidebar-accent"
>
<a href={project.url}>
<project.icon />
<span>{project.name}</span>
</a>
</SidebarMenuButton>
<SidebarMenuBadge>{project.badge}</SidebarMenuBadge>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,197 @@
"use client"
import { ChevronRight } from "lucide-react"
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/registry/default/ui/collapsible"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSub,
SidebarMenuSubButton,
SidebarMenuSubItem,
SidebarProvider,
} from "@/registry/default/ui/sidebar"
const items = [
{
title: "Getting Started",
url: "#",
items: [
{
title: "Installation",
url: "#",
},
{
title: "Project Structure",
url: "#",
},
],
},
{
title: "Building Your Application",
url: "#",
items: [
{
title: "Routing",
url: "#",
},
{
title: "Data Fetching",
url: "#",
isActive: true,
},
{
title: "Rendering",
url: "#",
},
{
title: "Caching",
url: "#",
},
{
title: "Styling",
url: "#",
},
{
title: "Optimizing",
url: "#",
},
{
title: "Configuring",
url: "#",
},
{
title: "Testing",
url: "#",
},
{
title: "Authentication",
url: "#",
},
{
title: "Deploying",
url: "#",
},
{
title: "Upgrading",
url: "#",
},
{
title: "Examples",
url: "#",
},
],
},
{
title: "API Reference",
url: "#",
items: [
{
title: "Components",
url: "#",
},
{
title: "File Conventions",
url: "#",
},
{
title: "Functions",
url: "#",
},
{
title: "next.config.js Options",
url: "#",
},
{
title: "CLI",
url: "#",
},
{
title: "Edge Runtime",
url: "#",
},
],
},
{
title: "Architecture",
url: "#",
items: [
{
title: "Accessibility",
url: "#",
},
{
title: "Fast Refresh",
url: "#",
},
{
title: "Next.js Compiler",
url: "#",
},
{
title: "Supported Browsers",
url: "#",
},
{
title: "Turbopack",
url: "#",
},
],
},
]
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupContent>
<SidebarMenu>
{items.map((item, index) => (
<Collapsible
key={index}
className="group/collapsible"
defaultOpen={index === 0}
>
<SidebarMenuItem>
<CollapsibleTrigger asChild>
<SidebarMenuButton>
<span>{item.title}</span>
<ChevronRight className="transition-transform ml-auto group-data-[state=open]/collapsible:rotate-90" />
</SidebarMenuButton>
</CollapsibleTrigger>
<CollapsibleContent>
<SidebarMenuSub>
{item.items.map((subItem, subIndex) => (
<SidebarMenuSubItem key={subIndex}>
<SidebarMenuSubButton asChild>
<a href={subItem.url}>
<span>{subItem.title}</span>
</a>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
))}
</SidebarMenuSub>
</CollapsibleContent>
</SidebarMenuItem>
</Collapsible>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,180 @@
"use client"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSub,
SidebarMenuSubButton,
SidebarMenuSubItem,
SidebarProvider,
} from "@/registry/default/ui/sidebar"
const items = [
{
title: "Getting Started",
url: "#",
items: [
{
title: "Installation",
url: "#",
},
{
title: "Project Structure",
url: "#",
},
],
},
{
title: "Building Your Application",
url: "#",
items: [
{
title: "Routing",
url: "#",
},
{
title: "Data Fetching",
url: "#",
isActive: true,
},
{
title: "Rendering",
url: "#",
},
{
title: "Caching",
url: "#",
},
{
title: "Styling",
url: "#",
},
{
title: "Optimizing",
url: "#",
},
{
title: "Configuring",
url: "#",
},
{
title: "Testing",
url: "#",
},
{
title: "Authentication",
url: "#",
},
{
title: "Deploying",
url: "#",
},
{
title: "Upgrading",
url: "#",
},
{
title: "Examples",
url: "#",
},
],
},
{
title: "API Reference",
url: "#",
items: [
{
title: "Components",
url: "#",
},
{
title: "File Conventions",
url: "#",
},
{
title: "Functions",
url: "#",
},
{
title: "next.config.js Options",
url: "#",
},
{
title: "CLI",
url: "#",
},
{
title: "Edge Runtime",
url: "#",
},
],
},
{
title: "Architecture",
url: "#",
items: [
{
title: "Accessibility",
url: "#",
},
{
title: "Fast Refresh",
url: "#",
},
{
title: "Next.js Compiler",
url: "#",
},
{
title: "Supported Browsers",
url: "#",
},
{
title: "Turbopack",
url: "#",
},
],
},
]
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupContent>
<SidebarMenu>
{items.map((item, index) => (
<SidebarMenuItem key={index}>
<SidebarMenuButton asChild>
<a href={item.url}>
<span>{item.title}</span>
</a>
</SidebarMenuButton>
<SidebarMenuSub>
{item.items.map((subItem, subIndex) => (
<SidebarMenuSubItem key={subIndex}>
<SidebarMenuSubButton asChild>
<a href={subItem.url}>
<span>{subItem.title}</span>
</a>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
))}
</SidebarMenuSub>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,71 @@
"use client"
import { Frame, LifeBuoy, Map, PieChart, Send } from "lucide-react"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
} from "@/registry/default/ui/sidebar"
const projects = [
{
name: "Design Engineering",
url: "#",
icon: Frame,
},
{
name: "Sales & Marketing",
url: "#",
icon: PieChart,
},
{
name: "Travel",
url: "#",
icon: Map,
},
{
name: "Support",
url: "#",
icon: LifeBuoy,
},
{
name: "Feedback",
url: "#",
icon: Send,
},
]
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Projects</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{projects.map((project) => (
<SidebarMenuItem key={project.name}>
<SidebarMenuButton asChild>
<a href={project.url}>
<project.icon />
<span>{project.name}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,104 @@
import * as React from "react"
import { Frame, LifeBuoy, Map, PieChart, Send } from "lucide-react"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSkeleton,
SidebarProvider,
} from "@/registry/default/ui/sidebar"
const projects = [
{
name: "Design Engineering",
url: "#",
icon: Frame,
badge: "24",
},
{
name: "Sales & Marketing",
url: "#",
icon: PieChart,
badge: "12",
},
{
name: "Travel",
url: "#",
icon: Map,
badge: "3",
},
{
name: "Support",
url: "#",
icon: LifeBuoy,
badge: "21",
},
{
name: "Feedback",
url: "#",
icon: Send,
badge: "8",
},
]
// Dummy fetch function
async function fetchProjects() {
await new Promise((resolve) => setTimeout(resolve, 3000))
return projects
}
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Projects</SidebarGroupLabel>
<SidebarGroupContent>
<React.Suspense fallback={<NavProjectsSkeleton />}>
<NavProjects />
</React.Suspense>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}
function NavProjectsSkeleton() {
return (
<SidebarMenu>
{Array.from({ length: 5 }).map((_, index) => (
<SidebarMenuItem key={index}>
<SidebarMenuSkeleton showIcon />
</SidebarMenuItem>
))}
</SidebarMenu>
)
}
async function NavProjects() {
const projects = await fetchProjects()
return (
<SidebarMenu>
{projects.map((project) => (
<SidebarMenuItem key={project.name}>
<SidebarMenuButton asChild>
<a href={project.url}>
<project.icon />
<span>{project.name}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
)
}

View File

@@ -0,0 +1,79 @@
"use client"
import { Calendar, Home, Inbox, Search, Settings } from "lucide-react"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarInset,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
SidebarTrigger,
} from "@/registry/default/ui/sidebar"
// Menu items.
const items = [
{
title: "Home",
url: "#",
icon: Home,
},
{
title: "Inbox",
url: "#",
icon: Inbox,
},
{
title: "Calendar",
url: "#",
icon: Calendar,
},
{
title: "Search",
url: "#",
icon: Search,
},
{
title: "Settings",
url: "#",
icon: Settings,
},
]
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Application</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{items.map((item) => (
<SidebarMenuItem key={item.title}>
<SidebarMenuButton asChild>
<a href={item.url}>
<item.icon />
<span>{item.title}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
<SidebarInset>
<header className="flex items-center justify-between px-4 h-12">
<SidebarTrigger />
</header>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -1,26 +0,0 @@
"use client"
import { HelloCard } from "@/registry/default/block/hello-block/components/hello-card"
import { useMediaQuery } from "@/registry/default/hooks/use-media-query"
import { cn } from "@/registry/default/lib/utils"
import { Button } from "@/registry/default/ui/button"
export default function HelloBlock() {
const isDesktop = useMediaQuery("(min-width: 768px)")
return (
<HelloCard
title="Hello Block"
className={cn(
"p-12",
isDesktop
? "bg-muted text-muted-foreground"
: "bg-primary text-primary-foreground"
)}
>
<p>Hello. This is a component inside a block.</p>
<p>You are currently on {isDesktop ? "desktop" : "mobile"}</p>
<Button>Click me</Button>
</HelloCard>
)
}

View File

@@ -1,15 +1,4 @@
import Link from "next/link"
import { Button } from "@/registry/new-york/ui/button"
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/registry/new-york/ui/card"
import { Input } from "@/registry/new-york/ui/input"
import { Label } from "@/registry/new-york/ui/label"
import { LoginForm } from "@/registry/default/block/login-01/components/login-form"
export const iframeHeight = "870px"
@@ -18,51 +7,7 @@ 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">
<Card className="mx-auto max-w-sm">
<CardHeader>
<CardTitle className="text-2xl">Login</CardTitle>
<CardDescription>
Enter your email below to login to your account
</CardDescription>
</CardHeader>
<CardContent>
<div className="grid gap-4">
<div className="grid gap-2">
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
placeholder="m@example.com"
required
/>
</div>
<div className="grid gap-2">
<div className="flex items-center">
<Label htmlFor="password">Password</Label>
<Link
href="#"
className="ml-auto inline-block text-sm underline"
>
Forgot your password?
</Link>
</div>
<Input id="password" type="password" required />
</div>
<Button type="submit" className="w-full">
Login
</Button>
<Button variant="outline" className="w-full">
Login with Google
</Button>
</div>
<div className="mt-4 text-center text-sm">
Don&apos;t have an account?{" "}
<Link href="#" className="underline">
Sign up
</Link>
</div>
</CardContent>
</Card>
<LoginForm />
</div>
)
}

View File

@@ -0,0 +1,59 @@
import Link from "next/link"
import { Button } from "@/registry/default/ui/button"
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/registry/default/ui/card"
import { Input } from "@/registry/default/ui/input"
import { Label } from "@/registry/default/ui/label"
export function LoginForm() {
return (
<Card className="mx-auto max-w-sm">
<CardHeader>
<CardTitle className="text-2xl">Login</CardTitle>
<CardDescription>
Enter your email below to login to your account
</CardDescription>
</CardHeader>
<CardContent>
<div className="grid gap-4">
<div className="grid gap-2">
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
placeholder="m@example.com"
required
/>
</div>
<div className="grid gap-2">
<div className="flex items-center">
<Label htmlFor="password">Password</Label>
<Link href="#" className="ml-auto inline-block text-sm underline">
Forgot your password?
</Link>
</div>
<Input id="password" type="password" required />
</div>
<Button type="submit" className="w-full">
Login
</Button>
<Button variant="outline" className="w-full">
Login with Google
</Button>
</div>
<div className="mt-4 text-center text-sm">
Don&apos;t have an account?{" "}
<Link href="#" className="underline">
Sign up
</Link>
</div>
</CardContent>
</Card>
)
}

View File

@@ -0,0 +1,15 @@
import { LoginForm } from "@/registry/default/block/login-01/components/login-form"
export const description = "A simple 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

@@ -1,8 +1,8 @@
import { AppSidebar } from "@/registry/new-york/block/sidebar-01/components/app-sidebar"
import { AppSidebar } from "@/registry/default/block/sidebar-01/components/app-sidebar"
import {
SidebarLayout,
SidebarTrigger,
} from "@/registry/new-york/block/sidebar-01/ui/sidebar"
} from "@/registry/default/block/sidebar-01/ui/sidebar"
export const iframeHeight = "870px"

View File

@@ -0,0 +1,55 @@
import { AppSidebar } from "@/registry/default/block/sidebar-01/components/app-sidebar"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/default/ui/breadcrumb"
import { Separator } from "@/registry/default/ui/separator"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/registry/default/ui/sidebar"
export const iframeHeight = "800px"
export const description =
"A simple sidebar with navigation grouped by section."
export default function Page() {
return (
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<header className="flex h-16 shrink-0 items-center gap-2 border-b px-4">
<SidebarTrigger className="-ml-1" />
<Separator orientation="vertical" className="mr-2 h-4" />
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">
Building Your Application
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</header>
<div className="flex flex-1 flex-col gap-4 p-4">
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
</div>
<div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
</div>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,54 @@
import { AppSidebar } from "@/registry/default/block/sidebar-02/components/app-sidebar"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/default/ui/breadcrumb"
import { Separator } from "@/registry/default/ui/separator"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/registry/default/ui/sidebar"
export const iframeHeight = "800px"
export const description = "A sidebar with collapsible sections."
export default function Page() {
return (
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<header className="flex sticky top-0 bg-background h-16 shrink-0 items-center gap-2 border-b px-4">
<SidebarTrigger className="-ml-1" />
<Separator orientation="vertical" className="mr-2 h-4" />
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">
Building Your Application
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</header>
<div className="flex flex-1 flex-col gap-4 p-4">
{Array.from({ length: 24 }).map((_, index) => (
<div
key={index}
className="aspect-video h-12 w-full rounded-lg bg-muted/50"
/>
))}
</div>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,56 @@
import { AppSidebar } from "@/registry/default/block/sidebar-03/components/app-sidebar"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/default/ui/breadcrumb"
import { Separator } from "@/registry/default/ui/separator"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/registry/default/ui/sidebar"
export const iframeHeight = "800px"
export const description = "A sidebar with submenus."
export default function Page() {
return (
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<header className="flex h-16 shrink-0 items-center gap-2 border-b">
<div className="flex items-center gap-2 px-3">
<SidebarTrigger />
<Separator orientation="vertical" className="mr-2 h-4" />
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">
Building Your Application
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</div>
</header>
<div className="flex flex-1 flex-col gap-4 p-4">
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
</div>
<div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
</div>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,60 @@
import { AppSidebar } from "@/registry/default/block/sidebar-04/components/app-sidebar"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/default/ui/breadcrumb"
import { Separator } from "@/registry/default/ui/separator"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/registry/default/ui/sidebar"
export const iframeHeight = "800px"
export const description = "A floating sidebar with submenus."
export default function Page() {
return (
<SidebarProvider
style={
{
"--sidebar-width": "19rem",
} as React.CSSProperties
}
>
<AppSidebar />
<SidebarInset>
<header className="flex h-16 shrink-0 items-center gap-2 px-4">
<SidebarTrigger className="-ml-1" />
<Separator orientation="vertical" className="mr-2 h-4" />
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">
Building Your Application
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</header>
<div className="flex flex-1 flex-col gap-4 p-4 pt-0">
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
</div>
<div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
</div>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,54 @@
import { AppSidebar } from "@/registry/default/block/sidebar-05/components/app-sidebar"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/default/ui/breadcrumb"
import { Separator } from "@/registry/default/ui/separator"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/registry/default/ui/sidebar"
export const iframeHeight = "800px"
export const description = "A sidebar with collapsible submenus."
export default function Page() {
return (
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<header className="flex h-16 shrink-0 items-center gap-2 border-b px-4">
<SidebarTrigger className="-ml-1" />
<Separator orientation="vertical" className="mr-2 h-4" />
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">
Building Your Application
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</header>
<div className="flex flex-1 flex-col gap-4 p-4">
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
</div>
<div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
</div>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,54 @@
import { AppSidebar } from "@/registry/default/block/sidebar-06/components/app-sidebar"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/default/ui/breadcrumb"
import { Separator } from "@/registry/default/ui/separator"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/registry/default/ui/sidebar"
export const iframeHeight = "800px"
export const description = "A sidebar with submenus as dropdowns."
export default function Page() {
return (
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<header className="flex h-16 shrink-0 items-center gap-2 border-b px-4">
<SidebarTrigger className="-ml-1" />
<Separator orientation="vertical" className="mr-2 h-4" />
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">
Building Your Application
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</header>
<div className="flex flex-1 flex-col gap-4 p-4">
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
</div>
<div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
</div>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,56 @@
import { AppSidebar } from "@/registry/default/block/sidebar-07/components/app-sidebar"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/default/ui/breadcrumb"
import { Separator } from "@/registry/default/ui/separator"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/registry/default/ui/sidebar"
export const iframeHeight = "800px"
export const description = "A sidebar that collapses to icons."
export default function Page() {
return (
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<header className="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12">
<div className="flex items-center gap-2 px-4">
<SidebarTrigger className="-ml-1" />
<Separator orientation="vertical" className="mr-2 h-4" />
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">
Building Your Application
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</div>
</header>
<div className="flex flex-1 flex-col gap-4 p-4 pt-0">
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
</div>
<div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
</div>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,56 @@
import { AppSidebar } from "@/registry/default/block/sidebar-08/components/app-sidebar"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/default/ui/breadcrumb"
import { Separator } from "@/registry/default/ui/separator"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/registry/default/ui/sidebar"
export const iframeHeight = "800px"
export const description = "An inset sidebar with secondary navigation."
export default function Page() {
return (
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<header className="flex h-16 shrink-0 items-center gap-2">
<div className="flex items-center gap-2 px-4">
<SidebarTrigger className="-ml-1" />
<Separator orientation="vertical" className="mr-2 h-4" />
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">
Building Your Application
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</div>
</header>
<div className="flex flex-1 flex-col gap-4 p-4 pt-0">
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
</div>
<div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
</div>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,58 @@
import { AppSidebar } from "@/registry/default/block/sidebar-09/components/app-sidebar"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/default/ui/breadcrumb"
import { Separator } from "@/registry/default/ui/separator"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/registry/default/ui/sidebar"
export const iframeHeight = "800px"
export const description = "Collapsible nested sidebars."
export default function Page() {
return (
<SidebarProvider
style={
{
"--sidebar-width": "350px",
} as React.CSSProperties
}
>
<AppSidebar />
<SidebarInset>
<header className="sticky top-0 flex shrink-0 items-center gap-2 border-b bg-background p-4">
<SidebarTrigger className="-ml-1" />
<Separator orientation="vertical" className="mr-2 h-4" />
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">All Inboxes</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Inbox</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</header>
<div className="flex flex-1 flex-col gap-4 p-4">
{Array.from({ length: 24 }).map((_, index) => (
<div
key={index}
className="aspect-video h-12 w-full rounded-lg bg-muted/50"
/>
))}
</div>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,50 @@
import { AppSidebar } from "@/registry/default/block/sidebar-10/components/app-sidebar"
import { NavActions } from "@/registry/default/block/sidebar-10/components/nav-actions"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbList,
BreadcrumbPage,
} from "@/registry/default/ui/breadcrumb"
import { Separator } from "@/registry/default/ui/separator"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/registry/default/ui/sidebar"
export const iframeHeight = "800px"
export const description = "A sidebar in a popover."
export default function Page() {
return (
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<header className="flex h-14 shrink-0 items-center gap-2">
<div className="flex flex-1 items-center gap-2 px-3">
<SidebarTrigger />
<Separator orientation="vertical" className="mr-2 h-4" />
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbPage className="line-clamp-1">
Project Management & Task Tracking
</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</div>
<div className="ml-auto px-3">
<NavActions />
</div>
</header>
<div className="flex flex-1 flex-col gap-4 px-4 py-10">
<div className="mx-auto h-24 w-full max-w-3xl rounded-xl bg-muted/50" />
<div className="mx-auto h-full w-full max-w-3xl rounded-xl bg-muted/50" />
</div>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,56 @@
import { AppSidebar } from "@/registry/default/block/sidebar-11/components/app-sidebar"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/default/ui/breadcrumb"
import { Separator } from "@/registry/default/ui/separator"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/registry/default/ui/sidebar"
export const iframeHeight = "800px"
export const description = "A sidebar with a collapsible file tree."
export default function Page() {
return (
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<header className="flex h-16 shrink-0 items-center gap-2 border-b px-4">
<SidebarTrigger className="-ml-1" />
<Separator orientation="vertical" className="mr-2 h-4" />
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">components</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">ui</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>button.tsx</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</header>
<div className="flex flex-1 flex-col gap-4 p-4">
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
</div>
<div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
</div>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,45 @@
import { AppSidebar } from "@/registry/default/block/sidebar-12/components/app-sidebar"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbList,
BreadcrumbPage,
} from "@/registry/default/ui/breadcrumb"
import { Separator } from "@/registry/default/ui/separator"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/registry/default/ui/sidebar"
export const iframeHeight = "800px"
export const description = "A sidebar with a calendar."
export default function Page() {
return (
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<header className="sticky top-0 flex h-16 shrink-0 items-center gap-2 border-b bg-background px-4">
<SidebarTrigger className="-ml-1" />
<Separator orientation="vertical" className="mr-2 h-4" />
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbPage>October 2024</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</header>
<div className="flex flex-1 flex-col gap-4 p-4">
<div className="grid auto-rows-min gap-4 md:grid-cols-5">
{Array.from({ length: 20 }).map((_, i) => (
<div key={i} className="aspect-square rounded-xl bg-muted/50" />
))}
</div>
</div>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,13 @@
import { SettingsDialog } from "@/registry/default/block/sidebar-13/components/settings-dialog"
export const iframeHeight = "800px"
export const description = "A sidebar in a dialog."
export default function Page() {
return (
<div className="flex h-svh items-center justify-center">
<SettingsDialog />
</div>
)
}

View File

@@ -0,0 +1,52 @@
import { AppSidebar } from "@/registry/default/block/sidebar-14/components/app-sidebar"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/registry/default/ui/breadcrumb"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/registry/default/ui/sidebar"
export const iframeHeight = "800px"
export const description = "A sidebar on the right."
export default function Page() {
return (
<SidebarProvider>
<SidebarInset>
<header className="flex h-16 shrink-0 items-center gap-2 border-b px-4">
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">
Building Your Application
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
<SidebarTrigger className="-mr-1 ml-auto rotate-180" />
</header>
<div className="flex flex-1 flex-col gap-4 p-4">
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
<div className="aspect-video rounded-xl bg-muted/50" />
</div>
<div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
</div>
</SidebarInset>
<AppSidebar side="right" />
</SidebarProvider>
)
}

View File

@@ -0,0 +1,48 @@
import { SidebarLeft } from "@/registry/default/block/sidebar-15/components/sidebar-left"
import { SidebarRight } from "@/registry/default/block/sidebar-15/components/sidebar-right"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbList,
BreadcrumbPage,
} from "@/registry/default/ui/breadcrumb"
import { Separator } from "@/registry/default/ui/separator"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/registry/default/ui/sidebar"
export const iframeHeight = "800px"
export const description = "A left and right sidebar."
export default function Page() {
return (
<SidebarProvider>
<SidebarLeft />
<SidebarInset>
<header className="sticky top-0 flex h-14 shrink-0 items-center gap-2 bg-background">
<div className="flex flex-1 items-center gap-2 px-3">
<SidebarTrigger />
<Separator orientation="vertical" className="mr-2 h-4" />
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbPage className="line-clamp-1">
Project Management & Task Tracking
</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</div>
</header>
<div className="flex flex-1 flex-col gap-4 p-4">
<div className="mx-auto h-24 w-full max-w-3xl rounded-xl bg-muted/50" />
<div className="mx-auto h-[100vh] w-full max-w-3xl rounded-xl bg-muted/50" />
</div>
</SidebarInset>
<SidebarRight />
</SidebarProvider>
)
}

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>
)
}

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