Compare commits
498
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
060bae06a7 | ||
|
|
003082e40c | ||
|
|
56a66ad075 | ||
|
|
4b4969b34f | ||
|
|
81b958efa0 | ||
|
|
8610e6cdc9 | ||
|
|
38330de14c | ||
|
|
5910ba3bff | ||
|
|
2e9710d38b | ||
|
|
2f6f8e60d6 | ||
|
|
0ee682af58 | ||
|
|
00a3f11d2c | ||
|
|
e30a6da393 | ||
|
|
d4db559e7a | ||
|
|
e088680532 | ||
|
|
bdd8648b69 | ||
|
|
2bc945221a | ||
|
|
554b426ca5 | ||
|
|
cedcf13f0e | ||
|
|
c3acde590f | ||
|
|
0752bbd5a4 | ||
|
|
04df7a41e5 | ||
|
|
380bf84092 | ||
|
|
39e7fcfe54 | ||
|
|
5ed3b8b95f | ||
|
|
b1390366fb | ||
|
|
dfa53b4be1 | ||
|
|
b226b5e802 | ||
|
|
fa870fdd31 | ||
|
|
d58395a11e | ||
|
|
6d1033c9a8 | ||
|
|
19e9453088 | ||
|
|
8728720857 | ||
|
|
1bad60aff3 | ||
|
|
d639608131 | ||
|
|
1b7c55aebe | ||
|
|
0b712367c2 | ||
|
|
9342b7061b | ||
|
|
224aba0f8b | ||
|
|
bf43384f24 | ||
|
|
1d9a78b844 | ||
|
|
6b43cd4359 | ||
|
|
0e3941860f | ||
|
|
685e0a0517 | ||
|
|
688c0271a0 | ||
|
|
b3b0f868ce | ||
|
|
b8ec4e05a0 | ||
|
|
21ee5e8e34 | ||
|
|
745e02dd6b | ||
|
|
d4d6276b49 | ||
|
|
c05ebaf3a1 | ||
|
|
658a7b99ff | ||
|
|
5b44b877b2 | ||
|
|
e4b20ca8b5 | ||
|
|
d4a956a9d0 | ||
|
|
eb158ccb1d | ||
|
|
55b4ef65b3 | ||
|
|
041ad4b73c | ||
|
|
07f915fb5f | ||
|
|
6d97f63ed7 | ||
|
|
ef076a69af | ||
|
|
2765c669d6 | ||
|
|
c8e8a70b8c | ||
|
|
6d26153de4 | ||
|
|
3969011ccf | ||
|
|
22d3802e9d | ||
|
|
9f112eada8 | ||
|
|
6cce2f4b00 | ||
|
|
4f751b5162 | ||
|
|
a65ec8c488 | ||
|
|
ac40bf996e | ||
|
|
a7ab2b17fd | ||
|
|
6b002b1c87 | ||
|
|
3a830e5cd8 | ||
|
|
c77df02293 | ||
|
|
92324212e3 | ||
|
|
2ca673d214 | ||
|
|
baf1e292c6 | ||
|
|
55da14c98a | ||
|
|
04a81678f5 | ||
|
|
fcea76c0b5 | ||
|
|
c070f58769 | ||
|
|
71569f01f0 | ||
|
|
4afc2aef8b | ||
|
|
ee6a2a66e4 | ||
|
|
eae6a521f1 | ||
|
|
43f7156895 | ||
|
|
463269fc1b | ||
|
|
c601e70a15 | ||
|
|
8b4cab92b3 | ||
|
|
3bebf18c9b | ||
|
|
918a0932e9 | ||
|
|
b049f50708 | ||
|
|
9ef1becb71 | ||
|
|
ae96d58e88 | ||
|
|
e9b45dbc87 | ||
|
|
fc70f5fb97 | ||
|
|
28e800838c | ||
|
|
92268c99e7 | ||
|
|
8a48906d81 | ||
|
|
3230acb906 | ||
|
|
7146ca3208 | ||
|
|
2f02269ddd | ||
|
|
97c6dff18e | ||
|
|
b167865b5c | ||
|
|
30619e16e8 | ||
|
|
df7bd3e4e5 | ||
|
|
93d827f5d9 | ||
|
|
30e190250e | ||
|
|
34c911d54c | ||
|
|
42db7e9ee1 | ||
|
|
521c89b669 | ||
|
|
c868168c89 | ||
|
|
f970d0242f | ||
|
|
be17cbd283 | ||
|
|
078afef155 | ||
|
|
1cf7b42856 | ||
|
|
f84a10b090 | ||
|
|
1e68f46190 | ||
|
|
dddd05909c | ||
|
|
a54250a818 | ||
|
|
a351e7f905 | ||
|
|
5cc4771783 | ||
|
|
844752bb22 | ||
|
|
71de35ae2b | ||
|
|
c52b27651d | ||
|
|
01697d03f0 | ||
|
|
80492d35c4 | ||
|
|
2c8df4de8f | ||
|
|
e1dc13103b | ||
|
|
305ff29e15 | ||
|
|
699d6c7ccd | ||
|
|
025022171d | ||
|
|
620b72a72c | ||
|
|
381b918a6f | ||
|
|
953cf69096 | ||
|
|
74331d8e4c | ||
|
|
2d39b09501 | ||
|
|
dac43918ee | ||
|
|
6ef0417c64 | ||
|
|
71d1c000e9 | ||
|
|
5888f8f040 | ||
|
|
03f7711a93 | ||
|
|
ad2b136589 | ||
|
|
ce059ffd52 | ||
|
|
fb0018d0ef | ||
|
|
7bf336a016 | ||
|
|
69ecfbaabf | ||
|
|
62e0cb32e0 | ||
|
|
33be4e60d0 | ||
|
|
e931126fb7 | ||
|
|
3f383daa20 | ||
|
|
f1c2861895 | ||
|
|
32cb7a10c8 | ||
|
|
255a4b6714 | ||
|
|
c3c9beeed6 | ||
|
|
c4849fda0e | ||
|
|
3617e13629 | ||
|
|
c340d4cb8d | ||
|
|
2c4488c697 | ||
|
|
067fbb8632 | ||
|
|
7f16413e21 | ||
|
|
a8594d7ace | ||
|
|
f5eab00976 | ||
|
|
5a25b5a1db | ||
|
|
1475939c99 | ||
|
|
656136c63b | ||
|
|
e8b55dea2f | ||
|
|
2c3ba53d61 | ||
|
|
1dc59b9416 | ||
|
|
6644864746 | ||
|
|
ec250da734 | ||
|
|
4e2003d586 | ||
|
|
bdf15c367c | ||
|
|
6befef901e | ||
|
|
5876807d18 | ||
|
|
44e2703466 | ||
|
|
8bdb6c7e7e | ||
|
|
eed249c667 | ||
|
|
a141e8e809 | ||
|
|
f3734c7f13 | ||
|
|
6ddef20817 | ||
|
|
eea9f34c27 | ||
|
|
0174252b09 | ||
|
|
e507201b88 | ||
|
|
ffe91ad7aa | ||
|
|
7e36bf87ef | ||
|
|
a045476113 | ||
|
|
41fb5d0d0c | ||
|
|
aa70dcf424 | ||
|
|
9a7d12dadc | ||
|
|
28643253ab | ||
|
|
0d8b52fbcb | ||
|
|
ade52fbdde | ||
|
|
e04550a15f | ||
|
|
ec5a47f3ba | ||
|
|
4965bc8184 | ||
|
|
3ddc214ac9 | ||
|
|
22f1a40bbe | ||
|
|
60f93c664b | ||
|
|
62363a415a | ||
|
|
f5d080742d | ||
|
|
626c29617d | ||
|
|
073a5464a0 | ||
|
|
2a178903b0 | ||
|
|
b77117d22d | ||
|
|
b3b8dc9c9b | ||
|
|
06b3e34794 | ||
|
|
6fe6a0f3e5 | ||
|
|
983bcdc268 | ||
|
|
29316aa6e6 | ||
|
|
e8811721b5 | ||
|
|
0fc3d78af3 | ||
|
|
a2107a5cc3 | ||
|
|
82eadf4497 | ||
|
|
423c792898 | ||
|
|
df150fea37 | ||
|
|
2fe581b038 | ||
|
|
edb4eb2740 | ||
|
|
0d85d6a28f | ||
|
|
b98339ce13 | ||
|
|
8318a509b5 | ||
|
|
938832b1e6 | ||
|
|
87baf9b616 | ||
|
|
ac57ce37f6 | ||
|
|
3e3402dd47 | ||
|
|
ea2cf8f675 | ||
|
|
1f43e32f5b | ||
|
|
d3c5a3d168 | ||
|
|
faa82a3458 | ||
|
|
7139ba4218 | ||
|
|
4764bf0678 | ||
|
|
b69a3e422b | ||
|
|
6f49733ae0 | ||
|
|
e6366c246b | ||
|
|
2fe2230d89 | ||
|
|
29c4e75e16 | ||
|
|
06465876eb | ||
|
|
59271694ee | ||
|
|
4df4ebe974 | ||
|
|
6750912612 | ||
|
|
b57325f399 | ||
|
|
2a24171333 | ||
|
|
0f3f17aaee | ||
|
|
e6df2b68cc | ||
|
|
9ae54783a9 | ||
|
|
9f6c50b394 | ||
|
|
8b5ce8d38b | ||
|
|
a69eec14ff | ||
|
|
2253534199 | ||
|
|
1615fe4441 | ||
|
|
7fb2655873 | ||
|
|
629fad72fd | ||
|
|
d501929505 | ||
|
|
5dd83a3592 | ||
|
|
be36468ca2 | ||
|
|
acb9347f1a | ||
|
|
fa33d8c29b | ||
|
|
bd3f8aa923 | ||
|
|
93dff1f009 | ||
|
|
2afd072409 | ||
|
|
4138b109c5 | ||
|
|
61cb15e8bc | ||
|
|
46d887e0bc | ||
|
|
82a6038c47 | ||
|
|
93f6727762 | ||
|
|
4bc755a791 | ||
|
|
49b0ee601f | ||
|
|
01cb78e57c | ||
|
|
f1ca32d21e | ||
|
|
1b21f86b8b | ||
|
|
c524470cb8 | ||
|
|
b39f9f2289 | ||
|
|
44f34d836b | ||
|
|
c55a5f35d1 | ||
|
|
ee65473a58 | ||
|
|
4dde3e3dd6 | ||
|
|
4ccd893389 | ||
|
|
a7fc90d13f | ||
|
|
67e49fc154 | ||
|
|
cace5fc811 | ||
|
|
3e83add3e2 | ||
|
|
273a4b8648 | ||
|
|
e627e9ef27 | ||
|
|
d69e7d1c77 | ||
|
|
e0f63907ae | ||
|
|
773ca72cf2 | ||
|
|
6d23619a37 | ||
|
|
14a795203c | ||
|
|
ea91af566a | ||
|
|
37011ec60d | ||
|
|
2419da1726 | ||
|
|
976f861b58 | ||
|
|
ac499c81ca | ||
|
|
9fdb8b4a5a | ||
|
|
3a41b988ee | ||
|
|
984327aae4 | ||
|
|
aae29ef081 | ||
|
|
6e0ca7db66 | ||
|
|
63bfec0ddc | ||
|
|
af5fbe035d | ||
|
|
2fc136456a | ||
|
|
14eb7940d6 | ||
|
|
1422312245 | ||
|
|
5cbed4104d | ||
|
|
486b8a8b29 | ||
|
|
db289770c7 | ||
|
|
d8061bb9d5 | ||
|
|
ba478f418e | ||
|
|
0bc659b092 | ||
|
|
25893f20a9 | ||
|
|
0821dbbdad | ||
|
|
a1279e1e29 | ||
|
|
a0721bd513 | ||
|
|
ea0d097b73 | ||
|
|
5bcbb3a8cd | ||
|
|
58c227381e | ||
|
|
7b90a6de5a | ||
|
|
d40a093370 | ||
|
|
867d52d9ce | ||
|
|
31b64724fd | ||
|
|
6ca2f8c755 | ||
|
|
ed09d8dbdd | ||
|
|
0ea786a0da | ||
|
|
61b16cf23f | ||
|
|
10be1a2b7f | ||
|
|
6c7c4fa142 | ||
|
|
fb2dd3b7c7 | ||
|
|
2608696537 | ||
|
|
0add0dc599 | ||
|
|
d5b7f820ad | ||
|
|
56f1392337 | ||
|
|
986fa4790d | ||
|
|
890ae7286c | ||
|
|
dcd14a9030 | ||
|
|
fdf2f76ee3 | ||
|
|
1d2cfb2cfe | ||
|
|
a96fa752e1 | ||
|
|
8415eb5dcd | ||
|
|
2bed0bc8aa | ||
|
|
0c3dd19dc1 | ||
|
|
0d6699aa88 | ||
|
|
449f9a4a05 | ||
|
|
c82fc2113e | ||
|
|
69bf1a66da | ||
|
|
895256e96c | ||
|
|
8417229dd2 | ||
|
|
c522bbaca0 | ||
|
|
9dc5caf06d | ||
|
|
9ac946a319 | ||
|
|
3b2cb3d4ce | ||
|
|
54c8441304 | ||
|
|
fe74c395e4 | ||
|
|
c8547d2163 | ||
|
|
c26a754f91 | ||
|
|
75fa462b0f | ||
|
|
a0b22b70fa | ||
|
|
e9ef254af1 | ||
|
|
8e891fd665 | ||
|
|
2120ebfd9b | ||
|
|
9c6e9b3329 | ||
|
|
4d1b2b68b1 | ||
|
|
cf235b8415 | ||
|
|
997b5a9d05 | ||
|
|
4e6f267218 | ||
|
|
27ecdd28d2 | ||
|
|
57cf7a8f1f | ||
|
|
54e6ae6c2d | ||
|
|
12fc8afe8d | ||
|
|
870e41557a | ||
|
|
b1e53f662b | ||
|
|
efaa553d7a | ||
|
|
9b08529113 | ||
|
|
1b7d3cf9fb | ||
|
|
5385fce6cb | ||
|
|
dc10c7c4c2 | ||
|
|
d94e4584e2 | ||
|
|
9a11c5373f | ||
|
|
24afb7f2dc | ||
|
|
208b3b883f | ||
|
|
207488a6f8 | ||
|
|
7615e85750 | ||
|
|
f3e629003a | ||
|
|
2ff81fe46f | ||
|
|
06c440dc2f | ||
|
|
d20022b63a | ||
|
|
c11ae264ca | ||
|
|
33af758b39 | ||
|
|
435d9ae3a5 | ||
|
|
8f3da9d80b | ||
|
|
4ecde298dd | ||
|
|
5f42bc03f8 | ||
|
|
54d681b03c | ||
|
|
fd9e8796c5 | ||
|
|
98c5593317 | ||
|
|
f7603cfbe0 | ||
|
|
63cd81b10e | ||
|
|
bf5945fb65 | ||
|
|
337344aa82 | ||
|
|
c15f770b1d | ||
|
|
d9c2543da1 | ||
|
|
1cd7240652 | ||
|
|
36e9ed65a1 | ||
|
|
f5a9772c49 | ||
|
|
4d8e0dfda4 | ||
|
|
aa9e51375c | ||
|
|
53007f1ffe | ||
|
|
edf753f374 | ||
|
|
304aa29ac5 | ||
|
|
3750c2135e | ||
|
|
484ddc42fc | ||
|
|
ea0dfbc31d | ||
|
|
9e8a5fb6fc | ||
|
|
140b88d4cf | ||
|
|
46afe7b8cc | ||
|
|
44d056787b | ||
|
|
d023d46047 | ||
|
|
8cce63176d | ||
|
|
9cbb053935 | ||
|
|
023ed1ba67 | ||
|
|
e8253aa242 | ||
|
|
c697c8be0f | ||
|
|
70b33015cb | ||
|
|
8fba9abe33 | ||
|
|
5fabb76f13 | ||
|
|
4ee4d32aec | ||
|
|
ae9c89a2fa | ||
|
|
949afebfcd | ||
|
|
192c085a7e | ||
|
|
9f99b6eae4 | ||
|
|
4ed1436c65 | ||
|
|
14e890c2eb | ||
|
|
3bb6c8b049 | ||
|
|
0582316dce | ||
|
|
a3b7e89d40 | ||
|
|
29628ea924 | ||
|
|
a83f54de8f | ||
|
|
f846cacede | ||
|
|
b8d03cd935 | ||
|
|
28efcab6f8 | ||
|
|
90198bf23f | ||
|
|
f8f7769c75 | ||
|
|
0424b6e631 | ||
|
|
5e377fdb7a | ||
|
|
747efd5598 | ||
|
|
6d084a346b | ||
|
|
60f89f1d55 | ||
|
|
e8494a690c | ||
|
|
ef13c47c9d | ||
|
|
f68eac6c73 | ||
|
|
e56a6f8cf6 | ||
|
|
f3a78041be | ||
|
|
6039340118 | ||
|
|
56fff06199 | ||
|
|
8039be8fab | ||
|
|
66f8f4dd65 | ||
|
|
ea23e448fe | ||
|
|
2744105f68 | ||
|
|
267d906647 | ||
|
|
a9f7866342 | ||
|
|
9fca67935c | ||
|
|
01876333dc | ||
|
|
dc34f05fc4 | ||
|
|
1aa7d52eac | ||
|
|
3d4fd32072 | ||
|
|
dd6d810da1 | ||
|
|
3655c031cb | ||
|
|
8f3cc521a8 | ||
|
|
777ba9a561 | ||
|
|
a5c0b4ce19 | ||
|
|
89a304cde5 | ||
|
|
476efa2864 | ||
|
|
aa939019a1 | ||
|
|
155756e988 | ||
|
|
3b4aedc4be | ||
|
|
7d91d135b7 | ||
|
|
7c509d9792 | ||
|
|
025f3e89d4 | ||
|
|
2f377769c9 | ||
|
|
b10052a65b | ||
|
|
9c12345177 | ||
|
|
9362a2ac1a | ||
|
|
d04164c190 | ||
|
|
f782bcbf43 | ||
|
|
d5f3b7d724 | ||
|
|
c172cb1d4c | ||
|
|
e5b9f9a91c | ||
|
|
a3a224a9ac | ||
|
|
6f7c53fa62 | ||
|
|
5268866317 | ||
|
|
a77439ec02 | ||
|
|
3293c88588 | ||
|
|
6224355f1d | ||
|
|
123ba84dca | ||
|
|
6110275b4b | ||
|
|
7f6643bc9f | ||
|
|
f586371f2b | ||
|
|
3b7fa39da3 |
@@ -1,8 +0,0 @@
|
||||
# Changesets
|
||||
|
||||
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
|
||||
with multi-package repos, or single-package repos to help you version and publish your code. You can
|
||||
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
|
||||
|
||||
We have a quick list of common questions to get you started engaging with this project in
|
||||
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json",
|
||||
"changelog": ["@changesets/changelog-github", { "repo": "shadcn/ui" }],
|
||||
"commit": false,
|
||||
"fixed": [],
|
||||
"linked": [],
|
||||
"access": "public",
|
||||
"baseBranch": "main",
|
||||
"updateInternalDependencies": "patch",
|
||||
"ignore": ["www", "playground", "**-template"]
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@shadcn/ui": patch
|
||||
---
|
||||
|
||||
add warning for command
|
||||
+2
-8
@@ -1,10 +1,4 @@
|
||||
# editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
quote_type = single
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
indent_size = 2
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/eslintrc",
|
||||
"root": true,
|
||||
"extends": [
|
||||
"next/core-web-vitals",
|
||||
"turbo",
|
||||
"prettier",
|
||||
"plugin:tailwindcss/recommended"
|
||||
],
|
||||
"plugins": ["tailwindcss"],
|
||||
"rules": {
|
||||
"@next/next/no-html-link-for-pages": "off",
|
||||
"react/jsx-key": "off",
|
||||
"tailwindcss/no-custom-classname": "off",
|
||||
"tailwindcss/classnames-order": "error"
|
||||
},
|
||||
"settings": {
|
||||
"tailwindcss": {
|
||||
"callees": ["cn"]
|
||||
},
|
||||
"next": {
|
||||
"rootDir": ["apps/*/"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
name: Lint
|
||||
name: pnpm lint
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -16,12 +16,13 @@ jobs:
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
node-version: 18
|
||||
|
||||
- uses: pnpm/action-setup@v2.2.4
|
||||
name: Install pnpm
|
||||
id: pnpm-install
|
||||
with:
|
||||
version: 8.6.1
|
||||
run_install: false
|
||||
|
||||
- name: Get pnpm store directory
|
||||
@@ -38,11 +39,11 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- run: pnpm lint
|
||||
#- run: pnpm lint
|
||||
|
||||
format:
|
||||
runs-on: ubuntu-latest
|
||||
name: Format
|
||||
name: pnpm format:check
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -51,12 +52,13 @@ jobs:
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
node-version: 18
|
||||
|
||||
- uses: pnpm/action-setup@v2.2.4
|
||||
name: Install pnpm
|
||||
id: pnpm-install
|
||||
with:
|
||||
version: 8.6.1
|
||||
run_install: false
|
||||
|
||||
- name: Get pnpm store directory
|
||||
@@ -79,7 +81,7 @@ jobs:
|
||||
|
||||
tsc:
|
||||
runs-on: ubuntu-latest
|
||||
name: TypeScript
|
||||
name: pnpm typecheck
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -88,12 +90,13 @@ jobs:
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
node-version: 18
|
||||
|
||||
- uses: pnpm/action-setup@v2.2.4
|
||||
name: Install pnpm
|
||||
id: pnpm-install
|
||||
with:
|
||||
version: 8.6.1
|
||||
run_install: false
|
||||
|
||||
- name: Get pnpm store directory
|
||||
|
||||
@@ -10,7 +10,7 @@ on:
|
||||
jobs:
|
||||
comment:
|
||||
if: |
|
||||
github.repository_owner == 'shadcn' &&
|
||||
github.repository_owner == 'hanzoai-ui' &&
|
||||
${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
runs-on: ubuntu-latest
|
||||
name: Write comment to the PR
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
|
||||
for (const artifact of allArtifacts.data.artifacts) {
|
||||
// Extract the PR number and package version from the artifact name
|
||||
const match = /^npm-package-@shadcn-ui@(.*?)-pr-(\d+)/.exec(artifact.name);
|
||||
const match = /^npm-package-hanzoai-ui@(.*?)-pr-(\d+)/.exec(artifact.name);
|
||||
|
||||
if (match) {
|
||||
require("fs").appendFileSync(
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
A new prerelease is available for testing:
|
||||
|
||||
```sh
|
||||
pnpm @shadcn/ui@${{ env.BETA_PACKAGE_VERSION }}
|
||||
npx hanzoai-ui@${{ env.BETA_PACKAGE_VERSION }}
|
||||
```
|
||||
|
||||
- name: "Remove the autorelease label once published"
|
||||
@@ -60,6 +60,6 @@ jobs:
|
||||
github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: ${{ env.WORKFLOW_RUN_PR }},
|
||||
issue_number: '${{ env.WORKFLOW_RUN_PR }}',
|
||||
name: '🚀 autorelease',
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ on:
|
||||
jobs:
|
||||
prerelease:
|
||||
if: |
|
||||
github.repository_owner == 'shadcn' &&
|
||||
github.repository_owner == 'hanzoai' &&
|
||||
contains(github.event.pull_request.labels.*.name, '🚀 autorelease')
|
||||
name: Build & Publish a beta release to NPM
|
||||
runs-on: ubuntu-latest
|
||||
@@ -24,6 +24,8 @@ jobs:
|
||||
|
||||
- name: Use PNPM
|
||||
uses: pnpm/action-setup@v2.2.4
|
||||
with:
|
||||
version: 8.6.1
|
||||
|
||||
- name: Use Node.js 18
|
||||
uses: actions/setup-node@v3
|
||||
@@ -54,5 +56,5 @@ jobs:
|
||||
- name: Upload packaged artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: npm-package-@shadcn-ui@${{ steps.package-version.outputs.current-version }}-pr-${{ github.event.number }} # encode the PR number into the artifact name
|
||||
name: npm-package-hanzoai-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
|
||||
|
||||
@@ -9,7 +9,7 @@ on:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
if: ${{ github.repository_owner == 'shadcn' }}
|
||||
if: ${{ github.repository_owner == 'hanzoai-ui' }}
|
||||
name: Create a PR for release workflow
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -20,18 +20,21 @@ jobs:
|
||||
|
||||
- name: Use PNPM
|
||||
uses: pnpm/action-setup@v2.2.4
|
||||
with:
|
||||
version: 8.6.1
|
||||
|
||||
- name: Use Node.js 18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
version: 8.6.1
|
||||
node-version: 18
|
||||
cache: "pnpm"
|
||||
|
||||
- name: Install NPM Dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Check for errors
|
||||
run: pnpm check
|
||||
# - name: Check for errors
|
||||
# run: pnpm check
|
||||
|
||||
- name: Build the package
|
||||
run: pnpm build:cli
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
name: Test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: ["*"]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
name: pnpm test
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- uses: pnpm/action-setup@v2.2.4
|
||||
name: Install pnpm
|
||||
id: pnpm-install
|
||||
with:
|
||||
version: 8.6.1
|
||||
run_install: false
|
||||
|
||||
- name: Get pnpm store directory
|
||||
id: pnpm-cache
|
||||
run: |
|
||||
echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT
|
||||
- uses: actions/cache@v3
|
||||
name: Setup pnpm cache
|
||||
with:
|
||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- run: pnpm test
|
||||
+15
-7
@@ -2,6 +2,7 @@
|
||||
|
||||
# dependencies
|
||||
node_modules
|
||||
**/node_modules
|
||||
.pnp
|
||||
.pnp.js
|
||||
|
||||
@@ -10,8 +11,6 @@ coverage
|
||||
|
||||
# next.js
|
||||
.next/
|
||||
out/
|
||||
build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
@@ -24,13 +23,22 @@ yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
**/.env
|
||||
**/.env.*
|
||||
|
||||
# turbo
|
||||
.turbo
|
||||
|
||||
.contentlayer
|
||||
tsconfig.tsbuildinfo
|
||||
**/tsconfig.tsbuildinfo
|
||||
|
||||
# build
|
||||
**/dist
|
||||
|
||||
**/.npmrc
|
||||
|
||||
**/.next
|
||||
|
||||
etc
|
||||
|
||||
bun.lockb
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npx commitlint --edit $1
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npx pretty-quick --staged
|
||||
Vendored
+3
-4
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"eslint.workingDirectories": [
|
||||
{ "pattern": "apps/*/" },
|
||||
{ "pattern": "packages/*/" }
|
||||
]
|
||||
"typescript.tsdk": "node_modules/.pnpm/typescript@5.3.3/node_modules/typescript/lib",
|
||||
"editor.gotoLocation.multipleDefinitions": "goto",
|
||||
"typescript.preferences.quoteStyle": "single"
|
||||
}
|
||||
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
# Contributing
|
||||
|
||||
Thanks for your interest in contributing to ui.hanzo.ai. We're happy to have you here.
|
||||
|
||||
Please take a moment to review this document before submitting your first pull request. We also strongly recommend that you check for open issues and pull requests to see if someone else is working on something similar.
|
||||
|
||||
If you need any help, feel free to reach out to [@hanzoai](https://twitter.com/hanzoai).
|
||||
|
||||
## About this repository
|
||||
|
||||
This repository is a monorepo.
|
||||
|
||||
- We use [pnpm](https://pnpm.io) and [`workspaces`](https://pnpm.io/workspaces) for development.
|
||||
- We use [Turborepo](https://turbo.build/repo) as our build system.
|
||||
- We use [changesets](https://github.com/changesets/changesets) for managing releases.
|
||||
|
||||
## Structure
|
||||
|
||||
This repository is structured as follows:
|
||||
|
||||
```
|
||||
apps
|
||||
└── web
|
||||
├── app
|
||||
├── components
|
||||
├── content
|
||||
└── registry
|
||||
├── default
|
||||
│ ├── example
|
||||
│ └── ui
|
||||
└── new-york
|
||||
├── example
|
||||
└── ui
|
||||
packages
|
||||
└── cli
|
||||
```
|
||||
|
||||
| Path | Description |
|
||||
| --------------------- | ---------------------------------------- |
|
||||
| `apps/web/app` | The Next.js application for the website. |
|
||||
| `apps/web/components` | The React components for the website. |
|
||||
| `apps/web/content` | The content for the website. |
|
||||
| `apps/web/registry` | The registry for the components. |
|
||||
| `packages/ui` | The `@hanzo/ui` package. |
|
||||
|
||||
## Development
|
||||
|
||||
### Fork this repo
|
||||
|
||||
You can fork this repo by clicking the fork button in the top right corner of this page.
|
||||
|
||||
### Clone on your local machine
|
||||
|
||||
```bash
|
||||
git clone https://github.com/your-username/ui.git
|
||||
```
|
||||
|
||||
### Navigate to project directory
|
||||
|
||||
```bash
|
||||
cd ui
|
||||
```
|
||||
|
||||
### Create a new Branch
|
||||
|
||||
```bash
|
||||
git checkout -b my-new-branch
|
||||
```
|
||||
|
||||
### Install dependencies
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
### Run a workspace
|
||||
|
||||
You can use the `pnpm --filter=[WORKSPACE]` command to start the development process for a workspace.
|
||||
|
||||
#### Examples
|
||||
|
||||
1. To run the `ui.hanzo.ai` website:
|
||||
|
||||
```bash
|
||||
pnpm --filter=web dev
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
The documentation for this project is located in the `web` workspace. You can run the documentation locally by running the following command:
|
||||
|
||||
```bash
|
||||
pnpm --filter=web dev
|
||||
```
|
||||
|
||||
Documentation is written using [MDX](https://mdxjs.com). You can find the documentation files in the `apps/web/content/docs` directory.
|
||||
|
||||
## Components
|
||||
|
||||
We use a registry system for developing components. You can find the source code for the components under `apps/web/registry`. The components are organized by styles.
|
||||
|
||||
```bash
|
||||
apps
|
||||
└── web
|
||||
└── registry
|
||||
├── default
|
||||
│ ├── example
|
||||
│ └── ui
|
||||
└── new-york
|
||||
├── example
|
||||
└── ui
|
||||
```
|
||||
|
||||
When adding or modifying components, please ensure that:
|
||||
|
||||
1. You make the changes for every style.
|
||||
2. You update the documentation.
|
||||
3. You run `pnpm build:registry` to update the registry.
|
||||
|
||||
## Commit Convention
|
||||
|
||||
Before you create a Pull Request, please check whether your commits comply with
|
||||
the commit conventions used in this repository.
|
||||
|
||||
When you create a commit we kindly ask you to follow the convention
|
||||
`category(scope or module): message` in your commit message while using one of
|
||||
the following categories:
|
||||
|
||||
- `feat / feature`: all changes that introduce completely new code or new
|
||||
features
|
||||
- `fix`: changes that fix a bug (ideally you will additionally reference an
|
||||
issue if present)
|
||||
- `refactor`: any code related change that is not a fix nor a feature
|
||||
- `docs`: changing existing or creating new documentation (i.e. README, docs for
|
||||
usage of a lib)
|
||||
- `build`: all changes regarding the build of the software, changes to
|
||||
dependencies or the addition of new dependencies
|
||||
- `test`: all changes regarding tests (adding new tests or changing existing
|
||||
ones)
|
||||
- `ci`: all changes regarding the configuration of continuous integration (i.e.
|
||||
github actions, ci system)
|
||||
- `chore`: all changes to the repository that do not fit into any of the above
|
||||
categories
|
||||
|
||||
e.g. `feat(components): add new prop to the avatar component`
|
||||
|
||||
If you are interested in the detailed specification you can visit
|
||||
https://web.conventionalcommits.org/ or check out the
|
||||
[Angular Commit Message Guidelines](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines).
|
||||
|
||||
## Requests for new components
|
||||
|
||||
If you have a request for a new component, please open a discussion on GitHub. We'll be happy to help you out.
|
||||
|
||||
## Testing
|
||||
|
||||
Tests are written using [Vitest](https://vitest.dev). You can run all the tests from the root of the repository.
|
||||
|
||||
```bash
|
||||
pnpm test
|
||||
```
|
||||
|
||||
Please ensure that the tests are passing when submitting a pull request. If you're adding new features, please include tests.
|
||||
+25
-17
@@ -1,21 +1,29 @@
|
||||
MIT License
|
||||
BSD License
|
||||
|
||||
Copyright (c) 2023 shadcn
|
||||
Copyright (c) 2015-present, Hanzo, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name Hanzo nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,46 +1,17 @@
|
||||
# shadcn/ui
|
||||
# @hanzo/ui
|
||||
|
||||
Accessible and customizable components that you can copy and paste into your apps. Free. Open Source. **Use this to build your own component library**.
|
||||
Accessible and customizable components that you can use to build your AI apps.
|
||||
|
||||

|
||||

|
||||
|
||||
## Roadmap
|
||||
## Documentation
|
||||
|
||||
> **Warning**
|
||||
> This is work in progress. I'm building this in public. You can follow the progress on Twitter [@shadcn](https://twitter.com/shadcn).
|
||||
Visit http://ui.hanzo.ai to view the documentation.
|
||||
|
||||
- [ ] Toggle Group
|
||||
- [ ] Toolbar
|
||||
- [x] ~Toast~
|
||||
- [x] ~Toggle~
|
||||
- [x] ~Navigation Menu~
|
||||
- [x] ~Figma~
|
||||
## Contributing
|
||||
|
||||
## Get Started
|
||||
|
||||
Starting a new project? Check out the Next.js template.
|
||||
|
||||
```bash
|
||||
npx create-next-app -e https://github.com/shadcn/next-template
|
||||
```
|
||||
|
||||
### Features
|
||||
|
||||
- Radix UI Primitives
|
||||
- Tailwind CSS
|
||||
- Fonts with `@next/font`
|
||||
- Icons from [Lucide](https://lucide.dev)
|
||||
- Dark mode with `next-themes`
|
||||
- Automatic import sorting with `@ianvs/prettier-plugin-sort-imports`
|
||||
|
||||
### Tailwind CSS Features
|
||||
|
||||
- Class merging with `tailwind-merge`
|
||||
- Animation with `tailwindcss-animate`
|
||||
- Conditional classes with `clsx`
|
||||
- Variants with `class-variance-authority`
|
||||
- Automatic class sorting with `eslint-plugin-tailwindcss`
|
||||
Please read the [contributing guide](/CONTRIBUTING.md).
|
||||
|
||||
## License
|
||||
|
||||
Licensed under the [MIT license](https://github.com/shadcn/ui/blob/main/LICENSE.md).
|
||||
Licensed under the [BSD 3 Clause](./LICENSE.md) License.
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# .kodiak.toml
|
||||
version = 1
|
||||
|
||||
[merge]
|
||||
automerge_label = "automerge"
|
||||
require_automerge_label = true
|
||||
method = "squash"
|
||||
delete_branch_on_merge = true
|
||||
optimistic_updates = false
|
||||
prioritize_ready_to_merge = true
|
||||
notify_on_conflict = true
|
||||
|
||||
[merge.message]
|
||||
title = "pull_request_title"
|
||||
body = "pull_request_body"
|
||||
include_pr_number = true
|
||||
body_type = "markdown"
|
||||
strip_html_comments = true
|
||||
@@ -3,4 +3,4 @@ node_modules
|
||||
.next
|
||||
build
|
||||
.contentlayer
|
||||
apps/www/pages/api/components.json
|
||||
apps/web/pages/api/registry.json
|
||||
@@ -0,0 +1 @@
|
||||
// The content of this directory is autogenerated by the registry server.
|
||||
@@ -0,0 +1 @@
|
||||
> Files inside this directory is autogenerated by `./scripts/build-registry.ts`. **Do not edit them manually.** - hanzo
|
||||
@@ -0,0 +1,45 @@
|
||||
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"
|
||||
|
||||
export const description =
|
||||
"A simple login form with email and password. The submit button says 'Sign in'."
|
||||
|
||||
export const iframeHeight = "600px"
|
||||
|
||||
export const containerClassName =
|
||||
"w-full h-screen flex items-center justify-center px-4"
|
||||
|
||||
export default function LoginForm() {
|
||||
return (
|
||||
<Card className="w-full max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-2xl">Login</CardTitle>
|
||||
<CardDescription>
|
||||
Enter your email below to login to your account.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent 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">
|
||||
<Label htmlFor="password">Password</Label>
|
||||
<Input id="password" type="password" required />
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<Button className="w-full">Sign in</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
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 const description =
|
||||
"A login form with email and password. There's an option to login with Google and a link to sign up if you don't have an account."
|
||||
|
||||
export const iframeHeight = "600px"
|
||||
|
||||
export const containerClassName =
|
||||
"w-full h-screen flex items-center justify-center px-4"
|
||||
|
||||
export default 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't have an account?{" "}
|
||||
<Link href="#" className="underline">
|
||||
Sign up
|
||||
</Link>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
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 const description =
|
||||
"A sign up form with first name, last name, email and password inside a card. There's an option to sign up with GitHub and a link to login if you already have an account"
|
||||
|
||||
export const iframeHeight = "600px"
|
||||
|
||||
export const containerClassName =
|
||||
"w-full h-screen flex items-center justify-center px-4"
|
||||
|
||||
export default function LoginForm() {
|
||||
return (
|
||||
<Card className="mx-auto max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-xl">Sign Up</CardTitle>
|
||||
<CardDescription>
|
||||
Enter your information to create an account
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid gap-4">
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="first-name">First name</Label>
|
||||
<Input id="first-name" placeholder="Max" required />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="last-name">Last name</Label>
|
||||
<Input id="last-name" placeholder="Robinson" required />
|
||||
</div>
|
||||
</div>
|
||||
<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">
|
||||
<Label htmlFor="password">Password</Label>
|
||||
<Input id="password" type="password" />
|
||||
</div>
|
||||
<Button type="submit" className="w-full">
|
||||
Create an account
|
||||
</Button>
|
||||
<Button variant="outline" className="w-full">
|
||||
Sign up with GitHub
|
||||
</Button>
|
||||
</div>
|
||||
<div className="mt-4 text-center text-sm">
|
||||
Already have an account?{" "}
|
||||
<Link href="#" className="underline">
|
||||
Sign in
|
||||
</Link>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import Image from "next/image"
|
||||
import Link from "next/link"
|
||||
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
import { Input } from "@/registry/default/ui/input"
|
||||
import { Label } from "@/registry/default/ui/label"
|
||||
|
||||
export const description =
|
||||
"A login page with two columns. The first column has the login form with email and password. There's a Forgot your passwork link and a link to sign up if you do not have an account. The second column has a cover image."
|
||||
|
||||
export const iframeHeight = "800px"
|
||||
|
||||
export const containerClassName = "w-full h-full p-4 lg:p-0"
|
||||
|
||||
export default function Dashboard() {
|
||||
return (
|
||||
<div className="w-full lg:grid lg:min-h-[600px] lg:grid-cols-2 xl:min-h-[800px]">
|
||||
<div className="flex items-center justify-center py-12">
|
||||
<div className="mx-auto grid w-[350px] gap-6">
|
||||
<div className="grid gap-2 text-center">
|
||||
<h1 className="text-3xl font-bold">Login</h1>
|
||||
<p className="text-balance text-muted-foreground">
|
||||
Enter your email below to login to your account
|
||||
</p>
|
||||
</div>
|
||||
<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="/forgot-password"
|
||||
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't have an account?{" "}
|
||||
<Link href="#" className="underline">
|
||||
Sign up
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="hidden bg-muted lg:block">
|
||||
<Image
|
||||
src="/placeholder.svg"
|
||||
alt="Image"
|
||||
width="1920"
|
||||
height="1080"
|
||||
className="h-full w-full object-cover dark:brightness-[0.2] dark:grayscale"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,455 @@
|
||||
import Link from "next/link"
|
||||
import {
|
||||
Activity,
|
||||
ArrowUpRight,
|
||||
CircleUser,
|
||||
CreditCard,
|
||||
DollarSign,
|
||||
Menu,
|
||||
Package2,
|
||||
Search,
|
||||
Users,
|
||||
} from "lucide-react"
|
||||
|
||||
import {
|
||||
Avatar,
|
||||
AvatarFallback,
|
||||
AvatarImage,
|
||||
} from "@/registry/default/ui/avatar"
|
||||
import { Badge } from "@/registry/default/ui/badge"
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/registry/default/ui/card"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/registry/default/ui/dropdown-menu"
|
||||
import { Input } from "@/registry/default/ui/input"
|
||||
import { Sheet, SheetContent, SheetTrigger } from "@/registry/default/ui/sheet"
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/registry/default/ui/table"
|
||||
|
||||
export const description =
|
||||
"An application shell with a header and main content area. The header has a navbar, a search input and and a user nav dropdown. The user nav is toggled by a button with an avatar image."
|
||||
|
||||
export const iframeHeight = "825px"
|
||||
|
||||
export const containerClassName = "w-full h-full"
|
||||
|
||||
export default function Dashboard() {
|
||||
return (
|
||||
<div className="flex min-h-screen w-full flex-col">
|
||||
<header className="sticky top-0 flex h-16 items-center gap-4 border-b bg-background px-4 md:px-6">
|
||||
<nav className="hidden flex-col gap-6 text-lg font-medium md:flex md:flex-row md:items-center md:gap-5 md:text-sm lg:gap-6">
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-2 text-lg font-semibold md:text-base"
|
||||
>
|
||||
<Package2 className="h-6 w-6" />
|
||||
<span className="sr-only">Acme Inc</span>
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-foreground transition-colors hover:text-foreground"
|
||||
>
|
||||
Dashboard
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-muted-foreground transition-colors hover:text-foreground"
|
||||
>
|
||||
Orders
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-muted-foreground transition-colors hover:text-foreground"
|
||||
>
|
||||
Products
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-muted-foreground transition-colors hover:text-foreground"
|
||||
>
|
||||
Customers
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-muted-foreground transition-colors hover:text-foreground"
|
||||
>
|
||||
Analytics
|
||||
</Link>
|
||||
</nav>
|
||||
<Sheet>
|
||||
<SheetTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="shrink-0 md:hidden"
|
||||
>
|
||||
<Menu className="h-5 w-5" />
|
||||
<span className="sr-only">Toggle navigation menu</span>
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent side="left">
|
||||
<nav className="grid gap-6 text-lg font-medium">
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-2 text-lg font-semibold"
|
||||
>
|
||||
<Package2 className="h-6 w-6" />
|
||||
<span className="sr-only">Acme Inc</span>
|
||||
</Link>
|
||||
<Link href="#" className="hover:text-foreground">
|
||||
Dashboard
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
Orders
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
Products
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
Customers
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
Analytics
|
||||
</Link>
|
||||
</nav>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
<div className="flex w-full items-center gap-4 md:ml-auto md:gap-2 lg:gap-4">
|
||||
<form className="ml-auto flex-1 sm:flex-initial">
|
||||
<div className="relative">
|
||||
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
type="search"
|
||||
placeholder="Search products..."
|
||||
className="pl-8 sm:w-[300px] md:w-[200px] lg:w-[300px]"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="secondary" size="icon" className="rounded-full">
|
||||
<CircleUser className="h-5 w-5" />
|
||||
<span className="sr-only">Toggle user menu</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>Settings</DropdownMenuItem>
|
||||
<DropdownMenuItem>Support</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>Logout</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</header>
|
||||
<main className="flex flex-1 flex-col gap-4 p-4 md:gap-8 md:p-8">
|
||||
<div className="grid gap-4 md:grid-cols-2 md:gap-8 lg:grid-cols-4">
|
||||
<Card x-chunk="dashboard-01-chunk-0">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">
|
||||
Total Revenue
|
||||
</CardTitle>
|
||||
<DollarSign className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">$45,231.89</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
+20.1% from last month
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card x-chunk="dashboard-01-chunk-1">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">
|
||||
Subscriptions
|
||||
</CardTitle>
|
||||
<Users className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">+2350</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
+180.1% from last month
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card x-chunk="dashboard-01-chunk-2">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Sales</CardTitle>
|
||||
<CreditCard className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">+12,234</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
+19% from last month
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card x-chunk="dashboard-01-chunk-3">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Active Now</CardTitle>
|
||||
<Activity className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">+573</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
+201 since last hour
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
<div className="grid gap-4 md:gap-8 lg:grid-cols-2 xl:grid-cols-3">
|
||||
<Card className="xl:col-span-2" x-chunk="dashboard-01-chunk-4">
|
||||
<CardHeader className="flex flex-row items-center">
|
||||
<div className="grid gap-2">
|
||||
<CardTitle>Transactions</CardTitle>
|
||||
<CardDescription>
|
||||
Recent transactions from your store.
|
||||
</CardDescription>
|
||||
</div>
|
||||
<Button asChild size="sm" className="ml-auto gap-1">
|
||||
<Link href="#">
|
||||
View All
|
||||
<ArrowUpRight className="h-4 w-4" />
|
||||
</Link>
|
||||
</Button>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Customer</TableHead>
|
||||
<TableHead className="hidden xl:table-column">
|
||||
Type
|
||||
</TableHead>
|
||||
<TableHead className="hidden xl:table-column">
|
||||
Status
|
||||
</TableHead>
|
||||
<TableHead className="hidden xl:table-column">
|
||||
Date
|
||||
</TableHead>
|
||||
<TableHead className="text-right">Amount</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<div className="font-medium">Liam Johnson</div>
|
||||
<div className="hidden text-sm text-muted-foreground md:inline">
|
||||
liam@example.com
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell className="hidden xl:table-column">
|
||||
Sale
|
||||
</TableCell>
|
||||
<TableCell className="hidden xl:table-column">
|
||||
<Badge className="text-xs" variant="outline">
|
||||
Approved
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell lg:hidden xl:table-column">
|
||||
2023-06-23
|
||||
</TableCell>
|
||||
<TableCell className="text-right">$250.00</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<div className="font-medium">Olivia Smith</div>
|
||||
<div className="hidden text-sm text-muted-foreground md:inline">
|
||||
olivia@example.com
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell className="hidden xl:table-column">
|
||||
Refund
|
||||
</TableCell>
|
||||
<TableCell className="hidden xl:table-column">
|
||||
<Badge className="text-xs" variant="outline">
|
||||
Declined
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell lg:hidden xl:table-column">
|
||||
2023-06-24
|
||||
</TableCell>
|
||||
<TableCell className="text-right">$150.00</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<div className="font-medium">Noah Williams</div>
|
||||
<div className="hidden text-sm text-muted-foreground md:inline">
|
||||
noah@example.com
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell className="hidden xl:table-column">
|
||||
Subscription
|
||||
</TableCell>
|
||||
<TableCell className="hidden xl:table-column">
|
||||
<Badge className="text-xs" variant="outline">
|
||||
Approved
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell lg:hidden xl:table-column">
|
||||
2023-06-25
|
||||
</TableCell>
|
||||
<TableCell className="text-right">$350.00</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<div className="font-medium">Emma Brown</div>
|
||||
<div className="hidden text-sm text-muted-foreground md:inline">
|
||||
emma@example.com
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell className="hidden xl:table-column">
|
||||
Sale
|
||||
</TableCell>
|
||||
<TableCell className="hidden xl:table-column">
|
||||
<Badge className="text-xs" variant="outline">
|
||||
Approved
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell lg:hidden xl:table-column">
|
||||
2023-06-26
|
||||
</TableCell>
|
||||
<TableCell className="text-right">$450.00</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<div className="font-medium">Liam Johnson</div>
|
||||
<div className="hidden text-sm text-muted-foreground md:inline">
|
||||
liam@example.com
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell className="hidden xl:table-column">
|
||||
Sale
|
||||
</TableCell>
|
||||
<TableCell className="hidden xl:table-column">
|
||||
<Badge className="text-xs" variant="outline">
|
||||
Approved
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell lg:hidden xl:table-column">
|
||||
2023-06-27
|
||||
</TableCell>
|
||||
<TableCell className="text-right">$550.00</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card x-chunk="dashboard-01-chunk-5">
|
||||
<CardHeader>
|
||||
<CardTitle>Recent Sales</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="grid gap-8">
|
||||
<div className="flex items-center gap-4">
|
||||
<Avatar className="hidden h-9 w-9 sm:flex">
|
||||
<AvatarImage src="/avatars/01.png" alt="Avatar" />
|
||||
<AvatarFallback>OM</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="grid gap-1">
|
||||
<p className="text-sm font-medium leading-none">
|
||||
Olivia Martin
|
||||
</p>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
olivia.martin@email.com
|
||||
</p>
|
||||
</div>
|
||||
<div className="ml-auto font-medium">+$1,999.00</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<Avatar className="hidden h-9 w-9 sm:flex">
|
||||
<AvatarImage src="/avatars/02.png" alt="Avatar" />
|
||||
<AvatarFallback>JL</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="grid gap-1">
|
||||
<p className="text-sm font-medium leading-none">
|
||||
Jackson Lee
|
||||
</p>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
jackson.lee@email.com
|
||||
</p>
|
||||
</div>
|
||||
<div className="ml-auto font-medium">+$39.00</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<Avatar className="hidden h-9 w-9 sm:flex">
|
||||
<AvatarImage src="/avatars/03.png" alt="Avatar" />
|
||||
<AvatarFallback>IN</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="grid gap-1">
|
||||
<p className="text-sm font-medium leading-none">
|
||||
Isabella Nguyen
|
||||
</p>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
isabella.nguyen@email.com
|
||||
</p>
|
||||
</div>
|
||||
<div className="ml-auto font-medium">+$299.00</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<Avatar className="hidden h-9 w-9 sm:flex">
|
||||
<AvatarImage src="/avatars/04.png" alt="Avatar" />
|
||||
<AvatarFallback>WK</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="grid gap-1">
|
||||
<p className="text-sm font-medium leading-none">
|
||||
William Kim
|
||||
</p>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
will@email.com
|
||||
</p>
|
||||
</div>
|
||||
<div className="ml-auto font-medium">+$99.00</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<Avatar className="hidden h-9 w-9 sm:flex">
|
||||
<AvatarImage src="/avatars/05.png" alt="Avatar" />
|
||||
<AvatarFallback>SD</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="grid gap-1">
|
||||
<p className="text-sm font-medium leading-none">
|
||||
Sofia Davis
|
||||
</p>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
sofia.davis@email.com
|
||||
</p>
|
||||
</div>
|
||||
<div className="ml-auto font-medium">+$39.00</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
import Link from "next/link"
|
||||
import {
|
||||
Bell,
|
||||
CircleUser,
|
||||
Home,
|
||||
LineChart,
|
||||
Menu,
|
||||
Package,
|
||||
Package2,
|
||||
Search,
|
||||
ShoppingCart,
|
||||
Users,
|
||||
} from "lucide-react"
|
||||
|
||||
import { Badge } from "@/registry/default/ui/badge"
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/registry/default/ui/card"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/registry/default/ui/dropdown-menu"
|
||||
import { Input } from "@/registry/default/ui/input"
|
||||
import { Sheet, SheetContent, SheetTrigger } from "@/registry/default/ui/sheet"
|
||||
|
||||
export const description =
|
||||
"A products dashboard with a sidebar navigation and a main content area. The dashboard has a header with a search input and a user menu. The sidebar has a logo, navigation links, and a card with a call to action. The main content area shows an empty state with a call to action."
|
||||
|
||||
export const iframeHeight = "800px"
|
||||
|
||||
export const containerClassName = "w-full h-full"
|
||||
|
||||
export default function Dashboard() {
|
||||
return (
|
||||
<div className="grid min-h-screen w-full md:grid-cols-[220px_1fr] lg:grid-cols-[280px_1fr]">
|
||||
<div className="hidden border-r bg-muted/40 md:block">
|
||||
<div className="flex h-full max-h-screen flex-col gap-2">
|
||||
<div className="flex h-14 items-center border-b px-4 lg:h-[60px] lg:px-6">
|
||||
<Link href="/" className="flex items-center gap-2 font-semibold">
|
||||
<Package2 className="h-6 w-6" />
|
||||
<span className="">Acme Inc</span>
|
||||
</Link>
|
||||
<Button variant="outline" size="icon" className="ml-auto h-8 w-8">
|
||||
<Bell className="h-4 w-4" />
|
||||
<span className="sr-only">Toggle notifications</span>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<nav className="grid items-start px-2 text-sm font-medium lg:px-4">
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-3 rounded-lg px-3 py-2 text-muted-foreground transition-all hover:text-primary"
|
||||
>
|
||||
<Home className="h-4 w-4" />
|
||||
Dashboard
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-3 rounded-lg px-3 py-2 text-muted-foreground transition-all hover:text-primary"
|
||||
>
|
||||
<ShoppingCart className="h-4 w-4" />
|
||||
Orders
|
||||
<Badge className="ml-auto flex h-6 w-6 shrink-0 items-center justify-center rounded-full">
|
||||
6
|
||||
</Badge>
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-3 rounded-lg bg-muted px-3 py-2 text-primary transition-all hover:text-primary"
|
||||
>
|
||||
<Package className="h-4 w-4" />
|
||||
Products{" "}
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-3 rounded-lg px-3 py-2 text-muted-foreground transition-all hover:text-primary"
|
||||
>
|
||||
<Users className="h-4 w-4" />
|
||||
Customers
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-3 rounded-lg px-3 py-2 text-muted-foreground transition-all hover:text-primary"
|
||||
>
|
||||
<LineChart className="h-4 w-4" />
|
||||
Analytics
|
||||
</Link>
|
||||
</nav>
|
||||
</div>
|
||||
<div className="mt-auto p-4">
|
||||
<Card x-chunk="dashboard-02-chunk-0">
|
||||
<CardHeader className="p-2 pt-0 md:p-4">
|
||||
<CardTitle>Upgrade to Pro</CardTitle>
|
||||
<CardDescription>
|
||||
Unlock all features and get unlimited access to our support
|
||||
team.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="p-2 pt-0 md:p-4 md:pt-0">
|
||||
<Button size="sm" className="w-full">
|
||||
Upgrade
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<header className="flex h-14 items-center gap-4 border-b bg-muted/40 px-4 lg:h-[60px] lg:px-6">
|
||||
<Sheet>
|
||||
<SheetTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="shrink-0 md:hidden"
|
||||
>
|
||||
<Menu className="h-5 w-5" />
|
||||
<span className="sr-only">Toggle navigation menu</span>
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent side="left" className="flex flex-col">
|
||||
<nav className="grid gap-2 text-lg font-medium">
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-2 text-lg font-semibold"
|
||||
>
|
||||
<Package2 className="h-6 w-6" />
|
||||
<span className="sr-only">Acme Inc</span>
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="mx-[-0.65rem] flex items-center gap-4 rounded-xl px-3 py-2 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<Home className="h-5 w-5" />
|
||||
Dashboard
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="mx-[-0.65rem] flex items-center gap-4 rounded-xl bg-muted px-3 py-2 text-foreground hover:text-foreground"
|
||||
>
|
||||
<ShoppingCart className="h-5 w-5" />
|
||||
Orders
|
||||
<Badge className="ml-auto flex h-6 w-6 shrink-0 items-center justify-center rounded-full">
|
||||
6
|
||||
</Badge>
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="mx-[-0.65rem] flex items-center gap-4 rounded-xl px-3 py-2 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<Package className="h-5 w-5" />
|
||||
Products
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="mx-[-0.65rem] flex items-center gap-4 rounded-xl px-3 py-2 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<Users className="h-5 w-5" />
|
||||
Customers
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="mx-[-0.65rem] flex items-center gap-4 rounded-xl px-3 py-2 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<LineChart className="h-5 w-5" />
|
||||
Analytics
|
||||
</Link>
|
||||
</nav>
|
||||
<div className="mt-auto">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Upgrade to Pro</CardTitle>
|
||||
<CardDescription>
|
||||
Unlock all features and get unlimited access to our
|
||||
support team.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Button size="sm" className="w-full">
|
||||
Upgrade
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
<div className="w-full flex-1">
|
||||
<form>
|
||||
<div className="relative">
|
||||
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
type="search"
|
||||
placeholder="Search products..."
|
||||
className="w-full appearance-none bg-background pl-8 shadow-none md:w-2/3 lg:w-1/3"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="secondary" size="icon" className="rounded-full">
|
||||
<CircleUser className="h-5 w-5" />
|
||||
<span className="sr-only">Toggle user menu</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>Settings</DropdownMenuItem>
|
||||
<DropdownMenuItem>Support</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>Logout</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</header>
|
||||
<main className="flex flex-1 flex-col gap-4 p-4 lg:gap-6 lg:p-6">
|
||||
<div className="flex items-center">
|
||||
<h1 className="text-lg font-semibold md:text-2xl">Inventory</h1>
|
||||
</div>
|
||||
<div
|
||||
className="flex flex-1 items-center justify-center rounded-lg border border-dashed shadow-sm"
|
||||
x-chunk="dashboard-02-chunk-1"
|
||||
>
|
||||
<div className="flex flex-col items-center gap-1 text-center">
|
||||
<h3 className="text-2xl font-bold tracking-tight">
|
||||
You have no products
|
||||
</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
You can start selling as soon as you add a product.
|
||||
</p>
|
||||
<Button className="mt-4">Add Product</Button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,464 @@
|
||||
import {
|
||||
Bird,
|
||||
Book,
|
||||
Bot,
|
||||
Code2,
|
||||
CornerDownLeft,
|
||||
LifeBuoy,
|
||||
Mic,
|
||||
Paperclip,
|
||||
Rabbit,
|
||||
Settings,
|
||||
Settings2,
|
||||
Share,
|
||||
SquareTerminal,
|
||||
SquareUser,
|
||||
Triangle,
|
||||
Turtle,
|
||||
} from "lucide-react"
|
||||
|
||||
import { Badge } from "@/registry/default/ui/badge"
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
import {
|
||||
Drawer,
|
||||
DrawerContent,
|
||||
DrawerDescription,
|
||||
DrawerHeader,
|
||||
DrawerTitle,
|
||||
DrawerTrigger,
|
||||
} from "@/registry/default/ui/drawer"
|
||||
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"
|
||||
import { Textarea } from "@/registry/default/ui/textarea"
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/registry/default/ui/tooltip"
|
||||
|
||||
export const description =
|
||||
"An AI playground with a sidebar navigation and a main content area. The playground has a header with a settings drawer and a share button. The sidebar has navigation links and a user menu. The main content area shows a form to configure the model and messages."
|
||||
|
||||
export const iframeHeight = "740px"
|
||||
|
||||
export const containerClassName = "w-full h-full"
|
||||
|
||||
export default function Dashboard() {
|
||||
return (
|
||||
<div className="grid h-screen w-full pl-[56px]">
|
||||
<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" />
|
||||
</Button>
|
||||
</div>
|
||||
<nav className="grid gap-1 p-2">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="rounded-lg bg-muted"
|
||||
aria-label="Playground"
|
||||
>
|
||||
<SquareTerminal className="size-5" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right" sideOffset={5}>
|
||||
Playground
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="rounded-lg"
|
||||
aria-label="Models"
|
||||
>
|
||||
<Bot className="size-5" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right" sideOffset={5}>
|
||||
Models
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="rounded-lg"
|
||||
aria-label="API"
|
||||
>
|
||||
<Code2 className="size-5" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right" sideOffset={5}>
|
||||
API
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="rounded-lg"
|
||||
aria-label="Documentation"
|
||||
>
|
||||
<Book className="size-5" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right" sideOffset={5}>
|
||||
Documentation
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="rounded-lg"
|
||||
aria-label="Settings"
|
||||
>
|
||||
<Settings2 className="size-5" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right" sideOffset={5}>
|
||||
Settings
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</nav>
|
||||
<nav className="mt-auto grid gap-1 p-2">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="mt-auto rounded-lg"
|
||||
aria-label="Help"
|
||||
>
|
||||
<LifeBuoy className="size-5" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right" sideOffset={5}>
|
||||
Help
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="mt-auto rounded-lg"
|
||||
aria-label="Account"
|
||||
>
|
||||
<SquareUser className="size-5" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right" sideOffset={5}>
|
||||
Account
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</nav>
|
||||
</aside>
|
||||
<div className="flex flex-col">
|
||||
<header className="sticky top-0 z-10 flex h-[57px] items-center gap-1 border-b bg-background px-4">
|
||||
<h1 className="text-xl font-semibold">Playground</h1>
|
||||
<Drawer>
|
||||
<DrawerTrigger asChild>
|
||||
<Button variant="ghost" size="icon" className="md:hidden">
|
||||
<Settings className="size-4" />
|
||||
<span className="sr-only">Settings</span>
|
||||
</Button>
|
||||
</DrawerTrigger>
|
||||
<DrawerContent className="max-h-[80vh]">
|
||||
<DrawerHeader>
|
||||
<DrawerTitle>Configuration</DrawerTitle>
|
||||
<DrawerDescription>
|
||||
Configure the settings for the model and messages.
|
||||
</DrawerDescription>
|
||||
</DrawerHeader>
|
||||
<form className="grid w-full items-start gap-6 overflow-auto p-4 pt-0">
|
||||
<fieldset className="grid gap-6 rounded-lg border p-4">
|
||||
<legend className="-ml-1 px-1 text-sm font-medium">
|
||||
Settings
|
||||
</legend>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="model">Model</Label>
|
||||
<Select>
|
||||
<SelectTrigger
|
||||
id="model"
|
||||
className="items-start [&_[data-description]]:hidden"
|
||||
>
|
||||
<SelectValue placeholder="Select a model" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="genesis">
|
||||
<div className="flex items-start gap-3 text-muted-foreground">
|
||||
<Rabbit className="size-5" />
|
||||
<div className="grid gap-0.5">
|
||||
<p>
|
||||
Neural{" "}
|
||||
<span className="font-medium text-foreground">
|
||||
Genesis
|
||||
</span>
|
||||
</p>
|
||||
<p className="text-xs" data-description>
|
||||
Our fastest model for general use cases.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</SelectItem>
|
||||
<SelectItem value="explorer">
|
||||
<div className="flex items-start gap-3 text-muted-foreground">
|
||||
<Bird className="size-5" />
|
||||
<div className="grid gap-0.5">
|
||||
<p>
|
||||
Neural{" "}
|
||||
<span className="font-medium text-foreground">
|
||||
Explorer
|
||||
</span>
|
||||
</p>
|
||||
<p className="text-xs" data-description>
|
||||
Performance and speed for efficiency.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</SelectItem>
|
||||
<SelectItem value="quantum">
|
||||
<div className="flex items-start gap-3 text-muted-foreground">
|
||||
<Turtle className="size-5" />
|
||||
<div className="grid gap-0.5">
|
||||
<p>
|
||||
Neural{" "}
|
||||
<span className="font-medium text-foreground">
|
||||
Quantum
|
||||
</span>
|
||||
</p>
|
||||
<p className="text-xs" data-description>
|
||||
The most powerful model for complex
|
||||
computations.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="temperature">Temperature</Label>
|
||||
<Input id="temperature" type="number" placeholder="0.4" />
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="top-p">Top P</Label>
|
||||
<Input id="top-p" type="number" placeholder="0.7" />
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="top-k">Top K</Label>
|
||||
<Input id="top-k" type="number" placeholder="0.0" />
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset className="grid gap-6 rounded-lg border p-4">
|
||||
<legend className="-ml-1 px-1 text-sm font-medium">
|
||||
Messages
|
||||
</legend>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="role">Role</Label>
|
||||
<Select defaultValue="system">
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select a role" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="system">System</SelectItem>
|
||||
<SelectItem value="user">User</SelectItem>
|
||||
<SelectItem value="assistant">Assistant</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="content">Content</Label>
|
||||
<Textarea id="content" placeholder="You are a..." />
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="ml-auto gap-1.5 text-sm"
|
||||
>
|
||||
<Share className="size-3.5" />
|
||||
Share
|
||||
</Button>
|
||||
</header>
|
||||
<main className="grid flex-1 gap-4 overflow-auto p-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
<div
|
||||
className="relative hidden flex-col items-start gap-8 md:flex"
|
||||
x-chunk="dashboard-03-chunk-0"
|
||||
>
|
||||
<form className="grid w-full items-start gap-6">
|
||||
<fieldset className="grid gap-6 rounded-lg border p-4">
|
||||
<legend className="-ml-1 px-1 text-sm font-medium">
|
||||
Settings
|
||||
</legend>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="model">Model</Label>
|
||||
<Select>
|
||||
<SelectTrigger
|
||||
id="model"
|
||||
className="items-start [&_[data-description]]:hidden"
|
||||
>
|
||||
<SelectValue placeholder="Select a model" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="genesis">
|
||||
<div className="flex items-start gap-3 text-muted-foreground">
|
||||
<Rabbit className="size-5" />
|
||||
<div className="grid gap-0.5">
|
||||
<p>
|
||||
Neural{" "}
|
||||
<span className="font-medium text-foreground">
|
||||
Genesis
|
||||
</span>
|
||||
</p>
|
||||
<p className="text-xs" data-description>
|
||||
Our fastest model for general use cases.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</SelectItem>
|
||||
<SelectItem value="explorer">
|
||||
<div className="flex items-start gap-3 text-muted-foreground">
|
||||
<Bird className="size-5" />
|
||||
<div className="grid gap-0.5">
|
||||
<p>
|
||||
Neural{" "}
|
||||
<span className="font-medium text-foreground">
|
||||
Explorer
|
||||
</span>
|
||||
</p>
|
||||
<p className="text-xs" data-description>
|
||||
Performance and speed for efficiency.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</SelectItem>
|
||||
<SelectItem value="quantum">
|
||||
<div className="flex items-start gap-3 text-muted-foreground">
|
||||
<Turtle className="size-5" />
|
||||
<div className="grid gap-0.5">
|
||||
<p>
|
||||
Neural{" "}
|
||||
<span className="font-medium text-foreground">
|
||||
Quantum
|
||||
</span>
|
||||
</p>
|
||||
<p className="text-xs" data-description>
|
||||
The most powerful model for complex computations.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="temperature">Temperature</Label>
|
||||
<Input id="temperature" type="number" placeholder="0.4" />
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="top-p">Top P</Label>
|
||||
<Input id="top-p" type="number" placeholder="0.7" />
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="top-k">Top K</Label>
|
||||
<Input id="top-k" type="number" placeholder="0.0" />
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset className="grid gap-6 rounded-lg border p-4">
|
||||
<legend className="-ml-1 px-1 text-sm font-medium">
|
||||
Messages
|
||||
</legend>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="role">Role</Label>
|
||||
<Select defaultValue="system">
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select a role" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="system">System</SelectItem>
|
||||
<SelectItem value="user">User</SelectItem>
|
||||
<SelectItem value="assistant">Assistant</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="content">Content</Label>
|
||||
<Textarea
|
||||
id="content"
|
||||
placeholder="You are a..."
|
||||
className="min-h-[9.5rem]"
|
||||
/>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
<div className="relative flex h-full min-h-[50vh] flex-col rounded-xl bg-muted/50 p-4 lg:col-span-2">
|
||||
<Badge variant="outline" className="absolute right-3 top-3">
|
||||
Output
|
||||
</Badge>
|
||||
<div className="flex-1" />
|
||||
<form
|
||||
className="relative overflow-hidden rounded-lg border bg-background focus-within:ring-1 focus-within:ring-ring"
|
||||
x-chunk="dashboard-03-chunk-1"
|
||||
>
|
||||
<Label htmlFor="message" className="sr-only">
|
||||
Message
|
||||
</Label>
|
||||
<Textarea
|
||||
id="message"
|
||||
placeholder="Type your message here..."
|
||||
className="min-h-12 resize-none border-0 p-3 shadow-none focus-visible:ring-0"
|
||||
/>
|
||||
<div className="flex items-center p-3 pt-0">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant="ghost" size="icon">
|
||||
<Paperclip className="size-4" />
|
||||
<span className="sr-only">Attach file</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="top">Attach File</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant="ghost" size="icon">
|
||||
<Mic className="size-4" />
|
||||
<span className="sr-only">Use Microphone</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="top">Use Microphone</TooltipContent>
|
||||
</Tooltip>
|
||||
<Button type="submit" size="sm" className="ml-auto gap-1.5">
|
||||
Send Message
|
||||
<CornerDownLeft className="size-3.5" />
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
import Link from "next/link"
|
||||
import { CircleUser, Menu, Package2, Search } from "lucide-react"
|
||||
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/registry/default/ui/card"
|
||||
import { Checkbox } from "@/registry/default/ui/checkbox"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/registry/default/ui/dropdown-menu"
|
||||
import { Input } from "@/registry/default/ui/input"
|
||||
import { Sheet, SheetContent, SheetTrigger } from "@/registry/default/ui/sheet"
|
||||
|
||||
export const description =
|
||||
"A settings page. The settings page has a sidebar navigation and a main content area. The main content area has a form to update the store name and a form to update the plugins directory. The sidebar navigation has links to general, security, integrations, support, organizations, and advanced settings."
|
||||
|
||||
export const iframeHeight = "780px"
|
||||
|
||||
export const containerClassName = "w-full h-full"
|
||||
|
||||
export default function Dashboard() {
|
||||
return (
|
||||
<div className="flex min-h-screen w-full flex-col">
|
||||
<header className="sticky top-0 flex h-16 items-center gap-4 border-b bg-background px-4 md:px-6">
|
||||
<nav className="hidden flex-col gap-6 text-lg font-medium md:flex md:flex-row md:items-center md:gap-5 md:text-sm lg:gap-6">
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-2 text-lg font-semibold md:text-base"
|
||||
>
|
||||
<Package2 className="h-6 w-6" />
|
||||
<span className="sr-only">Acme Inc</span>
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-muted-foreground transition-colors hover:text-foreground"
|
||||
>
|
||||
Dashboard
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-muted-foreground transition-colors hover:text-foreground"
|
||||
>
|
||||
Orders
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-muted-foreground transition-colors hover:text-foreground"
|
||||
>
|
||||
Products
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-muted-foreground transition-colors hover:text-foreground"
|
||||
>
|
||||
Customers
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-foreground transition-colors hover:text-foreground"
|
||||
>
|
||||
Settings
|
||||
</Link>
|
||||
</nav>
|
||||
<Sheet>
|
||||
<SheetTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="shrink-0 md:hidden"
|
||||
>
|
||||
<Menu className="h-5 w-5" />
|
||||
<span className="sr-only">Toggle navigation menu</span>
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent side="left">
|
||||
<nav className="grid gap-6 text-lg font-medium">
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-2 text-lg font-semibold"
|
||||
>
|
||||
<Package2 className="h-6 w-6" />
|
||||
<span className="sr-only">Acme Inc</span>
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
Dashboard
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
Orders
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
Products
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
Customers
|
||||
</Link>
|
||||
<Link href="#" className="hover:text-foreground">
|
||||
Settings
|
||||
</Link>
|
||||
</nav>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
<div className="flex w-full items-center gap-4 md:ml-auto md:gap-2 lg:gap-4">
|
||||
<form className="ml-auto flex-1 sm:flex-initial">
|
||||
<div className="relative">
|
||||
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
type="search"
|
||||
placeholder="Search products..."
|
||||
className="pl-8 sm:w-[300px] md:w-[200px] lg:w-[300px]"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="secondary" size="icon" className="rounded-full">
|
||||
<CircleUser className="h-5 w-5" />
|
||||
<span className="sr-only">Toggle user menu</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>Settings</DropdownMenuItem>
|
||||
<DropdownMenuItem>Support</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>Logout</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</header>
|
||||
<main className="flex min-h-[calc(100vh_-_theme(spacing.16))] flex-1 flex-col gap-4 bg-muted/40 p-4 md:gap-8 md:p-10">
|
||||
<div className="mx-auto grid w-full max-w-6xl gap-2">
|
||||
<h1 className="text-3xl font-semibold">Settings</h1>
|
||||
</div>
|
||||
<div className="mx-auto grid w-full max-w-6xl items-start gap-6 md:grid-cols-[180px_1fr] lg:grid-cols-[250px_1fr]">
|
||||
<nav
|
||||
className="grid gap-4 text-sm text-muted-foreground"
|
||||
x-chunk="dashboard-04-chunk-0"
|
||||
>
|
||||
<Link href="#" className="font-semibold text-primary">
|
||||
General
|
||||
</Link>
|
||||
<Link href="#">Security</Link>
|
||||
<Link href="#">Integrations</Link>
|
||||
<Link href="#">Support</Link>
|
||||
<Link href="#">Organizations</Link>
|
||||
<Link href="#">Advanced</Link>
|
||||
</nav>
|
||||
<div className="grid gap-6">
|
||||
<Card x-chunk="dashboard-04-chunk-1">
|
||||
<CardHeader>
|
||||
<CardTitle>Store Name</CardTitle>
|
||||
<CardDescription>
|
||||
Used to identify your store in the marketplace.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form>
|
||||
<Input placeholder="Store Name" />
|
||||
</form>
|
||||
</CardContent>
|
||||
<CardFooter className="border-t px-6 py-4">
|
||||
<Button>Save</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
<Card x-chunk="dashboard-04-chunk-2">
|
||||
<CardHeader>
|
||||
<CardTitle>Plugins Directory</CardTitle>
|
||||
<CardDescription>
|
||||
The directory within your project, in which your plugins are
|
||||
located.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form className="flex flex-col gap-4">
|
||||
<Input
|
||||
placeholder="Project Name"
|
||||
defaultValue="/content/plugins"
|
||||
/>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox id="include" defaultChecked />
|
||||
<label
|
||||
htmlFor="include"
|
||||
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||
>
|
||||
Allow administrators to change the directory.
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
</CardContent>
|
||||
<CardFooter className="border-t px-6 py-4">
|
||||
<Button>Save</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,720 @@
|
||||
import Image from "next/image"
|
||||
import Link from "next/link"
|
||||
import {
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Copy,
|
||||
CreditCard,
|
||||
File,
|
||||
Home,
|
||||
LineChart,
|
||||
ListFilter,
|
||||
MoreVertical,
|
||||
Package,
|
||||
Package2,
|
||||
PanelLeft,
|
||||
Search,
|
||||
Settings,
|
||||
ShoppingCart,
|
||||
Truck,
|
||||
Users2,
|
||||
} from "lucide-react"
|
||||
|
||||
import { Badge } from "@/registry/default/ui/badge"
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from "@/registry/default/ui/breadcrumb"
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/registry/default/ui/card"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/registry/default/ui/dropdown-menu"
|
||||
import { Input } from "@/registry/default/ui/input"
|
||||
import {
|
||||
Pagination,
|
||||
PaginationContent,
|
||||
PaginationItem,
|
||||
} from "@/registry/default/ui/pagination"
|
||||
import { Progress } from "@/registry/default/ui/progress"
|
||||
import { Separator } from "@/registry/default/ui/separator"
|
||||
import { Sheet, SheetContent, SheetTrigger } from "@/registry/default/ui/sheet"
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/registry/default/ui/table"
|
||||
import {
|
||||
Tabs,
|
||||
TabsContent,
|
||||
TabsList,
|
||||
TabsTrigger,
|
||||
} from "@/registry/default/ui/tabs"
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/registry/default/ui/tooltip"
|
||||
|
||||
export const description =
|
||||
"An orders dashboard with a sidebar navigation. The sidebar has icon navigation. The content area has a breadcrumb and search in the header. The main area has a list of recent orders with a filter and export button. The main area also has a detailed view of a single order with order details, shipping information, billing information, customer information, and payment information."
|
||||
|
||||
export const iframeHeight = "1112px"
|
||||
|
||||
export const containerClassName = "w-full h-full"
|
||||
|
||||
export default function Dashboard() {
|
||||
return (
|
||||
<div className="flex min-h-screen w-full flex-col bg-muted/40">
|
||||
<aside className="fixed inset-y-0 left-0 z-10 hidden w-14 flex-col border-r bg-background sm:flex">
|
||||
<nav className="flex flex-col items-center gap-4 px-2 sm:py-5">
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex h-9 w-9 shrink-0 items-center justify-center gap-2 rounded-full bg-primary text-lg font-semibold text-primary-foreground md:h-8 md:w-8 md:text-base"
|
||||
>
|
||||
<Package2 className="h-4 w-4 transition-all group-hover:scale-110" />
|
||||
<span className="sr-only">Acme Inc</span>
|
||||
</Link>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||
>
|
||||
<Home className="h-5 w-5" />
|
||||
<span className="sr-only">Dashboard</span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">Dashboard</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg bg-accent text-accent-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||
>
|
||||
<ShoppingCart className="h-5 w-5" />
|
||||
<span className="sr-only">Orders</span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">Orders</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||
>
|
||||
<Package className="h-5 w-5" />
|
||||
<span className="sr-only">Products</span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">Products</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||
>
|
||||
<Users2 className="h-5 w-5" />
|
||||
<span className="sr-only">Customers</span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">Customers</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||
>
|
||||
<LineChart className="h-5 w-5" />
|
||||
<span className="sr-only">Analytics</span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">Analytics</TooltipContent>
|
||||
</Tooltip>
|
||||
</nav>
|
||||
<nav className="mt-auto flex flex-col items-center gap-4 px-2 sm:py-5">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||
>
|
||||
<Settings className="h-5 w-5" />
|
||||
<span className="sr-only">Settings</span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">Settings</TooltipContent>
|
||||
</Tooltip>
|
||||
</nav>
|
||||
</aside>
|
||||
<div className="flex flex-col sm:gap-4 sm:py-4 sm:pl-14">
|
||||
<header className="sticky top-0 z-30 flex h-14 items-center gap-4 border-b bg-background px-4 sm:static sm:h-auto sm:border-0 sm:bg-transparent sm:px-6">
|
||||
<Sheet>
|
||||
<SheetTrigger asChild>
|
||||
<Button size="icon" variant="outline" className="sm:hidden">
|
||||
<PanelLeft className="h-5 w-5" />
|
||||
<span className="sr-only">Toggle Menu</span>
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent side="left" className="sm:max-w-xs">
|
||||
<nav className="grid gap-6 text-lg font-medium">
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex h-10 w-10 shrink-0 items-center justify-center gap-2 rounded-full bg-primary text-lg font-semibold text-primary-foreground md:text-base"
|
||||
>
|
||||
<Package2 className="h-5 w-5 transition-all group-hover:scale-110" />
|
||||
<span className="sr-only">Acme Inc</span>
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-4 px-2.5 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<Home className="h-5 w-5" />
|
||||
Dashboard
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-4 px-2.5 text-foreground"
|
||||
>
|
||||
<ShoppingCart className="h-5 w-5" />
|
||||
Orders
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-4 px-2.5 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<Package className="h-5 w-5" />
|
||||
Products
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-4 px-2.5 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<Users2 className="h-5 w-5" />
|
||||
Customers
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-4 px-2.5 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<LineChart className="h-5 w-5" />
|
||||
Settings
|
||||
</Link>
|
||||
</nav>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
<Breadcrumb className="hidden md:flex">
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink asChild>
|
||||
<Link href="#">Dashboard</Link>
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink asChild>
|
||||
<Link href="#">Orders</Link>
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage>Recent Orders</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
<div className="relative ml-auto flex-1 md:grow-0">
|
||||
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
type="search"
|
||||
placeholder="Search..."
|
||||
className="w-full rounded-lg bg-background pl-8 md:w-[200px] lg:w-[336px]"
|
||||
/>
|
||||
</div>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="overflow-hidden rounded-full"
|
||||
>
|
||||
<Image
|
||||
src="/placeholder-user.jpg"
|
||||
width={36}
|
||||
height={36}
|
||||
alt="Avatar"
|
||||
className="overflow-hidden rounded-full"
|
||||
/>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>Settings</DropdownMenuItem>
|
||||
<DropdownMenuItem>Support</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>Logout</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</header>
|
||||
<main className="grid flex-1 items-start gap-4 p-4 sm:px-6 sm:py-0 md:gap-8 lg:grid-cols-3 xl:grid-cols-3">
|
||||
<div className="grid auto-rows-max items-start gap-4 md:gap-8 lg:col-span-2">
|
||||
<div className="grid gap-4 sm:grid-cols-2 md:grid-cols-4 lg:grid-cols-2 xl:grid-cols-4">
|
||||
<Card className="sm:col-span-2" x-chunk="dashboard-05-chunk-0">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle>Your Orders</CardTitle>
|
||||
<CardDescription className="max-w-lg text-balance leading-relaxed">
|
||||
Introducing Our Dynamic Orders Dashboard for Seamless
|
||||
Management and Insightful Analysis.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardFooter>
|
||||
<Button>Create New Order</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
<Card x-chunk="dashboard-05-chunk-1">
|
||||
<CardHeader className="pb-2">
|
||||
<CardDescription>This Week</CardDescription>
|
||||
<CardTitle className="text-4xl">$1,329</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
+25% from last week
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<Progress value={25} aria-label="25% increase" />
|
||||
</CardFooter>
|
||||
</Card>
|
||||
<Card x-chunk="dashboard-05-chunk-2">
|
||||
<CardHeader className="pb-2">
|
||||
<CardDescription>This Month</CardDescription>
|
||||
<CardTitle className="text-4xl">$5,329</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
+10% from last month
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<Progress value={12} aria-label="12% increase" />
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</div>
|
||||
<Tabs defaultValue="week">
|
||||
<div className="flex items-center">
|
||||
<TabsList>
|
||||
<TabsTrigger value="week">Week</TabsTrigger>
|
||||
<TabsTrigger value="month">Month</TabsTrigger>
|
||||
<TabsTrigger value="year">Year</TabsTrigger>
|
||||
</TabsList>
|
||||
<div className="ml-auto flex items-center gap-2">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-7 gap-1 text-sm"
|
||||
>
|
||||
<ListFilter className="h-3.5 w-3.5" />
|
||||
<span className="sr-only sm:not-sr-only">Filter</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>Filter by</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuCheckboxItem checked>
|
||||
Fulfilled
|
||||
</DropdownMenuCheckboxItem>
|
||||
<DropdownMenuCheckboxItem>
|
||||
Declined
|
||||
</DropdownMenuCheckboxItem>
|
||||
<DropdownMenuCheckboxItem>
|
||||
Refunded
|
||||
</DropdownMenuCheckboxItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
className="h-7 gap-1 text-sm"
|
||||
>
|
||||
<File className="h-3.5 w-3.5" />
|
||||
<span className="sr-only sm:not-sr-only">Export</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<TabsContent value="week">
|
||||
<Card x-chunk="dashboard-05-chunk-3">
|
||||
<CardHeader className="px-7">
|
||||
<CardTitle>Orders</CardTitle>
|
||||
<CardDescription>
|
||||
Recent orders from your store.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Customer</TableHead>
|
||||
<TableHead className="hidden sm:table-cell">
|
||||
Type
|
||||
</TableHead>
|
||||
<TableHead className="hidden sm:table-cell">
|
||||
Status
|
||||
</TableHead>
|
||||
<TableHead className="hidden md:table-cell">
|
||||
Date
|
||||
</TableHead>
|
||||
<TableHead className="text-right">Amount</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow className="bg-accent">
|
||||
<TableCell>
|
||||
<div className="font-medium">Liam Johnson</div>
|
||||
<div className="hidden text-sm text-muted-foreground md:inline">
|
||||
liam@example.com
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
Sale
|
||||
</TableCell>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
<Badge className="text-xs" variant="secondary">
|
||||
Fulfilled
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
2023-06-23
|
||||
</TableCell>
|
||||
<TableCell className="text-right">$250.00</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<div className="font-medium">Olivia Smith</div>
|
||||
<div className="hidden text-sm text-muted-foreground md:inline">
|
||||
olivia@example.com
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
Refund
|
||||
</TableCell>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
<Badge className="text-xs" variant="outline">
|
||||
Declined
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
2023-06-24
|
||||
</TableCell>
|
||||
<TableCell className="text-right">$150.00</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<div className="font-medium">Noah Williams</div>
|
||||
<div className="hidden text-sm text-muted-foreground md:inline">
|
||||
noah@example.com
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
Subscription
|
||||
</TableCell>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
<Badge className="text-xs" variant="secondary">
|
||||
Fulfilled
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
2023-06-25
|
||||
</TableCell>
|
||||
<TableCell className="text-right">$350.00</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<div className="font-medium">Emma Brown</div>
|
||||
<div className="hidden text-sm text-muted-foreground md:inline">
|
||||
emma@example.com
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
Sale
|
||||
</TableCell>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
<Badge className="text-xs" variant="secondary">
|
||||
Fulfilled
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
2023-06-26
|
||||
</TableCell>
|
||||
<TableCell className="text-right">$450.00</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<div className="font-medium">Liam Johnson</div>
|
||||
<div className="hidden text-sm text-muted-foreground md:inline">
|
||||
liam@example.com
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
Sale
|
||||
</TableCell>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
<Badge className="text-xs" variant="secondary">
|
||||
Fulfilled
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
2023-06-23
|
||||
</TableCell>
|
||||
<TableCell className="text-right">$250.00</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<div className="font-medium">Liam Johnson</div>
|
||||
<div className="hidden text-sm text-muted-foreground md:inline">
|
||||
liam@example.com
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
Sale
|
||||
</TableCell>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
<Badge className="text-xs" variant="secondary">
|
||||
Fulfilled
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
2023-06-23
|
||||
</TableCell>
|
||||
<TableCell className="text-right">$250.00</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<div className="font-medium">Olivia Smith</div>
|
||||
<div className="hidden text-sm text-muted-foreground md:inline">
|
||||
olivia@example.com
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
Refund
|
||||
</TableCell>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
<Badge className="text-xs" variant="outline">
|
||||
Declined
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
2023-06-24
|
||||
</TableCell>
|
||||
<TableCell className="text-right">$150.00</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<div className="font-medium">Emma Brown</div>
|
||||
<div className="hidden text-sm text-muted-foreground md:inline">
|
||||
emma@example.com
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
Sale
|
||||
</TableCell>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
<Badge className="text-xs" variant="secondary">
|
||||
Fulfilled
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
2023-06-26
|
||||
</TableCell>
|
||||
<TableCell className="text-right">$450.00</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
<div>
|
||||
<Card className="overflow-hidden" x-chunk="dashboard-05-chunk-4">
|
||||
<CardHeader className="flex flex-row items-start bg-muted/50">
|
||||
<div className="grid gap-0.5">
|
||||
<CardTitle className="group flex items-center gap-2 text-lg">
|
||||
Order Oe31b70H
|
||||
<Button
|
||||
size="icon"
|
||||
variant="outline"
|
||||
className="h-6 w-6 opacity-0 transition-opacity group-hover:opacity-100"
|
||||
>
|
||||
<Copy className="h-3 w-3" />
|
||||
<span className="sr-only">Copy Order ID</span>
|
||||
</Button>
|
||||
</CardTitle>
|
||||
<CardDescription>Date: November 23, 2023</CardDescription>
|
||||
</div>
|
||||
<div className="ml-auto flex items-center gap-1">
|
||||
<Button size="sm" variant="outline" className="h-8 gap-1">
|
||||
<Truck className="h-3.5 w-3.5" />
|
||||
<span className="lg:sr-only xl:not-sr-only xl:whitespace-nowrap">
|
||||
Track Order
|
||||
</span>
|
||||
</Button>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button size="icon" variant="outline" className="h-8 w-8">
|
||||
<MoreVertical className="h-3.5 w-3.5" />
|
||||
<span className="sr-only">More</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuItem>Edit</DropdownMenuItem>
|
||||
<DropdownMenuItem>Export</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>Trash</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="p-6 text-sm">
|
||||
<div className="grid gap-3">
|
||||
<div className="font-semibold">Order Details</div>
|
||||
<ul className="grid gap-3">
|
||||
<li className="flex items-center justify-between">
|
||||
<span className="text-muted-foreground">
|
||||
Glimmer Lamps x <span>2</span>
|
||||
</span>
|
||||
<span>$250.00</span>
|
||||
</li>
|
||||
<li className="flex items-center justify-between">
|
||||
<span className="text-muted-foreground">
|
||||
Aqua Filters x <span>1</span>
|
||||
</span>
|
||||
<span>$49.00</span>
|
||||
</li>
|
||||
</ul>
|
||||
<Separator className="my-2" />
|
||||
<ul className="grid gap-3">
|
||||
<li className="flex items-center justify-between">
|
||||
<span className="text-muted-foreground">Subtotal</span>
|
||||
<span>$299.00</span>
|
||||
</li>
|
||||
<li className="flex items-center justify-between">
|
||||
<span className="text-muted-foreground">Shipping</span>
|
||||
<span>$5.00</span>
|
||||
</li>
|
||||
<li className="flex items-center justify-between">
|
||||
<span className="text-muted-foreground">Tax</span>
|
||||
<span>$25.00</span>
|
||||
</li>
|
||||
<li className="flex items-center justify-between font-semibold">
|
||||
<span className="text-muted-foreground">Total</span>
|
||||
<span>$329.00</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<Separator className="my-4" />
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="grid gap-3">
|
||||
<div className="font-semibold">Shipping Information</div>
|
||||
<address className="grid gap-0.5 not-italic text-muted-foreground">
|
||||
<span>Liam Johnson</span>
|
||||
<span>1234 Main St.</span>
|
||||
<span>Anytown, CA 12345</span>
|
||||
</address>
|
||||
</div>
|
||||
<div className="grid auto-rows-max gap-3">
|
||||
<div className="font-semibold">Billing Information</div>
|
||||
<div className="text-muted-foreground">
|
||||
Same as shipping address
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Separator className="my-4" />
|
||||
<div className="grid gap-3">
|
||||
<div className="font-semibold">Customer Information</div>
|
||||
<dl className="grid gap-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<dt className="text-muted-foreground">Customer</dt>
|
||||
<dd>Liam Johnson</dd>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<dt className="text-muted-foreground">Email</dt>
|
||||
<dd>
|
||||
<a href="mailto:">liam@acme.com</a>
|
||||
</dd>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<dt className="text-muted-foreground">Phone</dt>
|
||||
<dd>
|
||||
<a href="tel:">+1 234 567 890</a>
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
<Separator className="my-4" />
|
||||
<div className="grid gap-3">
|
||||
<div className="font-semibold">Payment Information</div>
|
||||
<dl className="grid gap-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<dt className="flex items-center gap-1 text-muted-foreground">
|
||||
<CreditCard className="h-4 w-4" />
|
||||
Visa
|
||||
</dt>
|
||||
<dd>**** **** **** 4532</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="flex flex-row items-center border-t bg-muted/50 px-6 py-3">
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Updated <time dateTime="2023-11-23">November 23, 2023</time>
|
||||
</div>
|
||||
<Pagination className="ml-auto mr-0 w-auto">
|
||||
<PaginationContent>
|
||||
<PaginationItem>
|
||||
<Button size="icon" variant="outline" className="h-6 w-6">
|
||||
<ChevronLeft className="h-3.5 w-3.5" />
|
||||
<span className="sr-only">Previous Order</span>
|
||||
</Button>
|
||||
</PaginationItem>
|
||||
<PaginationItem>
|
||||
<Button size="icon" variant="outline" className="h-6 w-6">
|
||||
<ChevronRight className="h-3.5 w-3.5" />
|
||||
<span className="sr-only">Next Order</span>
|
||||
</Button>
|
||||
</PaginationItem>
|
||||
</PaginationContent>
|
||||
</Pagination>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,637 @@
|
||||
import Image from "next/image"
|
||||
import Link from "next/link"
|
||||
import {
|
||||
File,
|
||||
Home,
|
||||
LineChart,
|
||||
ListFilter,
|
||||
MoreHorizontal,
|
||||
Package,
|
||||
Package2,
|
||||
PanelLeft,
|
||||
PlusCircle,
|
||||
Search,
|
||||
Settings,
|
||||
ShoppingCart,
|
||||
Users2,
|
||||
} from "lucide-react"
|
||||
|
||||
import { Badge } from "@/registry/default/ui/badge"
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from "@/registry/default/ui/breadcrumb"
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/registry/default/ui/card"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/registry/default/ui/dropdown-menu"
|
||||
import { Input } from "@/registry/default/ui/input"
|
||||
import { Sheet, SheetContent, SheetTrigger } from "@/registry/default/ui/sheet"
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/registry/default/ui/table"
|
||||
import {
|
||||
Tabs,
|
||||
TabsContent,
|
||||
TabsList,
|
||||
TabsTrigger,
|
||||
} from "@/registry/default/ui/tabs"
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/registry/default/ui/tooltip"
|
||||
|
||||
export const description =
|
||||
"An products dashboard with a sidebar navigation. The sidebar has icon navigation. The content area has a breadcrumb and search in the header. It displays a list of products in a table with actions."
|
||||
|
||||
export const iframeHeight = "938px"
|
||||
|
||||
export const containerClassName = "w-full h-full"
|
||||
|
||||
export default function Dashboard() {
|
||||
return (
|
||||
<div className="flex min-h-screen w-full flex-col bg-muted/40">
|
||||
<aside className="fixed inset-y-0 left-0 z-10 hidden w-14 flex-col border-r bg-background sm:flex">
|
||||
<nav className="flex flex-col items-center gap-4 px-2 sm:py-5">
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex h-9 w-9 shrink-0 items-center justify-center gap-2 rounded-full bg-primary text-lg font-semibold text-primary-foreground md:h-8 md:w-8 md:text-base"
|
||||
>
|
||||
<Package2 className="h-4 w-4 transition-all group-hover:scale-110" />
|
||||
<span className="sr-only">Acme Inc</span>
|
||||
</Link>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||
>
|
||||
<Home className="h-5 w-5" />
|
||||
<span className="sr-only">Dashboard</span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">Dashboard</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg bg-accent text-accent-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||
>
|
||||
<ShoppingCart className="h-5 w-5" />
|
||||
<span className="sr-only">Orders</span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">Orders</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||
>
|
||||
<Package className="h-5 w-5" />
|
||||
<span className="sr-only">Products</span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">Products</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||
>
|
||||
<Users2 className="h-5 w-5" />
|
||||
<span className="sr-only">Customers</span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">Customers</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||
>
|
||||
<LineChart className="h-5 w-5" />
|
||||
<span className="sr-only">Analytics</span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">Analytics</TooltipContent>
|
||||
</Tooltip>
|
||||
</nav>
|
||||
<nav className="mt-auto flex flex-col items-center gap-4 px-2 sm:py-5">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||
>
|
||||
<Settings className="h-5 w-5" />
|
||||
<span className="sr-only">Settings</span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">Settings</TooltipContent>
|
||||
</Tooltip>
|
||||
</nav>
|
||||
</aside>
|
||||
<div className="flex flex-col sm:gap-4 sm:py-4 sm:pl-14">
|
||||
<header className="sticky top-0 z-30 flex h-14 items-center gap-4 border-b bg-background px-4 sm:static sm:h-auto sm:border-0 sm:bg-transparent sm:px-6">
|
||||
<Sheet>
|
||||
<SheetTrigger asChild>
|
||||
<Button size="icon" variant="outline" className="sm:hidden">
|
||||
<PanelLeft className="h-5 w-5" />
|
||||
<span className="sr-only">Toggle Menu</span>
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent side="left" className="sm:max-w-xs">
|
||||
<nav className="grid gap-6 text-lg font-medium">
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex h-10 w-10 shrink-0 items-center justify-center gap-2 rounded-full bg-primary text-lg font-semibold text-primary-foreground md:text-base"
|
||||
>
|
||||
<Package2 className="h-5 w-5 transition-all group-hover:scale-110" />
|
||||
<span className="sr-only">Acme Inc</span>
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-4 px-2.5 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<Home className="h-5 w-5" />
|
||||
Dashboard
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-4 px-2.5 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<ShoppingCart className="h-5 w-5" />
|
||||
Orders
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-4 px-2.5 text-foreground"
|
||||
>
|
||||
<Package className="h-5 w-5" />
|
||||
Products
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-4 px-2.5 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<Users2 className="h-5 w-5" />
|
||||
Customers
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-4 px-2.5 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<LineChart className="h-5 w-5" />
|
||||
Settings
|
||||
</Link>
|
||||
</nav>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
<Breadcrumb className="hidden md:flex">
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink asChild>
|
||||
<Link href="#">Dashboard</Link>
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink asChild>
|
||||
<Link href="#">Products</Link>
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage>All Products</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
<div className="relative ml-auto flex-1 md:grow-0">
|
||||
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
type="search"
|
||||
placeholder="Search..."
|
||||
className="w-full rounded-lg bg-background pl-8 md:w-[200px] lg:w-[336px]"
|
||||
/>
|
||||
</div>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="overflow-hidden rounded-full"
|
||||
>
|
||||
<Image
|
||||
src="/placeholder-user.jpg"
|
||||
width={36}
|
||||
height={36}
|
||||
alt="Avatar"
|
||||
className="overflow-hidden rounded-full"
|
||||
/>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>Settings</DropdownMenuItem>
|
||||
<DropdownMenuItem>Support</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>Logout</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</header>
|
||||
<main className="grid flex-1 items-start gap-4 p-4 sm:px-6 sm:py-0 md:gap-8">
|
||||
<Tabs defaultValue="all">
|
||||
<div className="flex items-center">
|
||||
<TabsList>
|
||||
<TabsTrigger value="all">All</TabsTrigger>
|
||||
<TabsTrigger value="active">Active</TabsTrigger>
|
||||
<TabsTrigger value="draft">Draft</TabsTrigger>
|
||||
<TabsTrigger value="archived" className="hidden sm:flex">
|
||||
Archived
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<div className="ml-auto flex items-center gap-2">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline" size="sm" className="h-8 gap-1">
|
||||
<ListFilter className="h-3.5 w-3.5" />
|
||||
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
||||
Filter
|
||||
</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>Filter by</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuCheckboxItem checked>
|
||||
Active
|
||||
</DropdownMenuCheckboxItem>
|
||||
<DropdownMenuCheckboxItem>Draft</DropdownMenuCheckboxItem>
|
||||
<DropdownMenuCheckboxItem>
|
||||
Archived
|
||||
</DropdownMenuCheckboxItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<Button size="sm" variant="outline" className="h-8 gap-1">
|
||||
<File className="h-3.5 w-3.5" />
|
||||
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
||||
Export
|
||||
</span>
|
||||
</Button>
|
||||
<Button size="sm" className="h-8 gap-1">
|
||||
<PlusCircle className="h-3.5 w-3.5" />
|
||||
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
||||
Add Product
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<TabsContent value="all">
|
||||
<Card x-chunk="dashboard-06-chunk-0">
|
||||
<CardHeader>
|
||||
<CardTitle>Products</CardTitle>
|
||||
<CardDescription>
|
||||
Manage your products and view their sales performance.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="hidden w-[100px] sm:table-cell">
|
||||
<span className="sr-only">Image</span>
|
||||
</TableHead>
|
||||
<TableHead>Name</TableHead>
|
||||
<TableHead>Status</TableHead>
|
||||
<TableHead className="hidden md:table-cell">
|
||||
Price
|
||||
</TableHead>
|
||||
<TableHead className="hidden md:table-cell">
|
||||
Total Sales
|
||||
</TableHead>
|
||||
<TableHead className="hidden md:table-cell">
|
||||
Created at
|
||||
</TableHead>
|
||||
<TableHead>
|
||||
<span className="sr-only">Actions</span>
|
||||
</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
<Image
|
||||
alt="Product image"
|
||||
className="aspect-square rounded-md object-cover"
|
||||
height="64"
|
||||
src="/placeholder.svg"
|
||||
width="64"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">
|
||||
Laser Lemonade Machine
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant="outline">Draft</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
$499.99
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
25
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
2023-07-12 10:42 AM
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
aria-haspopup="true"
|
||||
size="icon"
|
||||
variant="ghost"
|
||||
>
|
||||
<MoreHorizontal className="h-4 w-4" />
|
||||
<span className="sr-only">Toggle menu</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
||||
<DropdownMenuItem>Edit</DropdownMenuItem>
|
||||
<DropdownMenuItem>Delete</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
<Image
|
||||
alt="Product image"
|
||||
className="aspect-square rounded-md object-cover"
|
||||
height="64"
|
||||
src="/placeholder.svg"
|
||||
width="64"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">
|
||||
Hypernova Headphones
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant="outline">Active</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
$129.99
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
100
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
2023-10-18 03:21 PM
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
aria-haspopup="true"
|
||||
size="icon"
|
||||
variant="ghost"
|
||||
>
|
||||
<MoreHorizontal className="h-4 w-4" />
|
||||
<span className="sr-only">Toggle menu</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
||||
<DropdownMenuItem>Edit</DropdownMenuItem>
|
||||
<DropdownMenuItem>Delete</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
<Image
|
||||
alt="Product image"
|
||||
className="aspect-square rounded-md object-cover"
|
||||
height="64"
|
||||
src="/placeholder.svg"
|
||||
width="64"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">
|
||||
AeroGlow Desk Lamp
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant="outline">Active</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
$39.99
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
50
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
2023-11-29 08:15 AM
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
aria-haspopup="true"
|
||||
size="icon"
|
||||
variant="ghost"
|
||||
>
|
||||
<MoreHorizontal className="h-4 w-4" />
|
||||
<span className="sr-only">Toggle menu</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
||||
<DropdownMenuItem>Edit</DropdownMenuItem>
|
||||
<DropdownMenuItem>Delete</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
<Image
|
||||
alt="Product image"
|
||||
className="aspect-square rounded-md object-cover"
|
||||
height="64"
|
||||
src="/placeholder.svg"
|
||||
width="64"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">
|
||||
TechTonic Energy Drink
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant="secondary">Draft</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
$2.99
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
0
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
2023-12-25 11:59 PM
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
aria-haspopup="true"
|
||||
size="icon"
|
||||
variant="ghost"
|
||||
>
|
||||
<MoreHorizontal className="h-4 w-4" />
|
||||
<span className="sr-only">Toggle menu</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
||||
<DropdownMenuItem>Edit</DropdownMenuItem>
|
||||
<DropdownMenuItem>Delete</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
<Image
|
||||
alt="Product image"
|
||||
className="aspect-square rounded-md object-cover"
|
||||
height="64"
|
||||
src="/placeholder.svg"
|
||||
width="64"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">
|
||||
Gamer Gear Pro Controller
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant="outline">Active</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
$59.99
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
75
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
2024-01-01 12:00 AM
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
aria-haspopup="true"
|
||||
size="icon"
|
||||
variant="ghost"
|
||||
>
|
||||
<MoreHorizontal className="h-4 w-4" />
|
||||
<span className="sr-only">Toggle menu</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
||||
<DropdownMenuItem>Edit</DropdownMenuItem>
|
||||
<DropdownMenuItem>Delete</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell className="hidden sm:table-cell">
|
||||
<Image
|
||||
alt="Product image"
|
||||
className="aspect-square rounded-md object-cover"
|
||||
height="64"
|
||||
src="/placeholder.svg"
|
||||
width="64"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">
|
||||
Luminous VR Headset
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant="outline">Active</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
$199.99
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
30
|
||||
</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
2024-02-14 02:14 PM
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
aria-haspopup="true"
|
||||
size="icon"
|
||||
variant="ghost"
|
||||
>
|
||||
<MoreHorizontal className="h-4 w-4" />
|
||||
<span className="sr-only">Toggle menu</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
||||
<DropdownMenuItem>Edit</DropdownMenuItem>
|
||||
<DropdownMenuItem>Delete</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Showing <strong>1-10</strong> of <strong>32</strong>{" "}
|
||||
products
|
||||
</div>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,610 @@
|
||||
import Image from "next/image"
|
||||
import Link from "next/link"
|
||||
import {
|
||||
ChevronLeft,
|
||||
Home,
|
||||
LineChart,
|
||||
Package,
|
||||
Package2,
|
||||
PanelLeft,
|
||||
PlusCircle,
|
||||
Search,
|
||||
Settings,
|
||||
ShoppingCart,
|
||||
Upload,
|
||||
Users2,
|
||||
} from "lucide-react"
|
||||
|
||||
import { Badge } from "@/registry/default/ui/badge"
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from "@/registry/default/ui/breadcrumb"
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/registry/default/ui/card"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/registry/default/ui/dropdown-menu"
|
||||
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"
|
||||
import { Sheet, SheetContent, SheetTrigger } from "@/registry/default/ui/sheet"
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/registry/default/ui/table"
|
||||
import { Textarea } from "@/registry/default/ui/textarea"
|
||||
import {
|
||||
ToggleGroup,
|
||||
ToggleGroupItem,
|
||||
} from "@/registry/default/ui/toggle-group"
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/registry/default/ui/tooltip"
|
||||
|
||||
export const description =
|
||||
"A product edit page. The product edit page has a form to edit the product details, stock, product category, product status, and product images. The product edit page has a sidebar navigation and a main content area. The main content area has a form to edit the product details, stock, product category, product status, and product images. The sidebar navigation has links to product details, stock, product category, product status, and product images."
|
||||
|
||||
export const iframeHeight = "1200px"
|
||||
|
||||
export const containerClassName = "w-full h-full"
|
||||
|
||||
export default function Dashboard() {
|
||||
return (
|
||||
<div className="flex min-h-screen w-full flex-col bg-muted/40">
|
||||
<aside className="fixed inset-y-0 left-0 z-10 hidden w-14 flex-col border-r bg-background sm:flex">
|
||||
<nav className="flex flex-col items-center gap-4 px-2 sm:py-5">
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex h-9 w-9 shrink-0 items-center justify-center gap-2 rounded-full bg-primary text-lg font-semibold text-primary-foreground md:h-8 md:w-8 md:text-base"
|
||||
>
|
||||
<Package2 className="h-4 w-4 transition-all group-hover:scale-110" />
|
||||
<span className="sr-only">Acme Inc</span>
|
||||
</Link>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||
>
|
||||
<Home className="h-5 w-5" />
|
||||
<span className="sr-only">Dashboard</span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">Dashboard</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg bg-accent text-accent-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||
>
|
||||
<ShoppingCart className="h-5 w-5" />
|
||||
<span className="sr-only">Orders</span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">Orders</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||
>
|
||||
<Package className="h-5 w-5" />
|
||||
<span className="sr-only">Products</span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">Products</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||
>
|
||||
<Users2 className="h-5 w-5" />
|
||||
<span className="sr-only">Customers</span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">Customers</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||
>
|
||||
<LineChart className="h-5 w-5" />
|
||||
<span className="sr-only">Analytics</span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">Analytics</TooltipContent>
|
||||
</Tooltip>
|
||||
</nav>
|
||||
<nav className="mt-auto flex flex-col items-center gap-4 px-2 sm:py-5">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
|
||||
>
|
||||
<Settings className="h-5 w-5" />
|
||||
<span className="sr-only">Settings</span>
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">Settings</TooltipContent>
|
||||
</Tooltip>
|
||||
</nav>
|
||||
</aside>
|
||||
<div className="flex flex-col sm:gap-4 sm:py-4 sm:pl-14">
|
||||
<header className="sticky top-0 z-30 flex h-14 items-center gap-4 border-b bg-background px-4 sm:static sm:h-auto sm:border-0 sm:bg-transparent sm:px-6">
|
||||
<Sheet>
|
||||
<SheetTrigger asChild>
|
||||
<Button size="icon" variant="outline" className="sm:hidden">
|
||||
<PanelLeft className="h-5 w-5" />
|
||||
<span className="sr-only">Toggle Menu</span>
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent side="left" className="sm:max-w-xs">
|
||||
<nav className="grid gap-6 text-lg font-medium">
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex h-10 w-10 shrink-0 items-center justify-center gap-2 rounded-full bg-primary text-lg font-semibold text-primary-foreground md:text-base"
|
||||
>
|
||||
<Package2 className="h-5 w-5 transition-all group-hover:scale-110" />
|
||||
<span className="sr-only">Acme Inc</span>
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-4 px-2.5 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<Home className="h-5 w-5" />
|
||||
Dashboard
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-4 px-2.5 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<ShoppingCart className="h-5 w-5" />
|
||||
Orders
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-4 px-2.5 text-foreground"
|
||||
>
|
||||
<Package className="h-5 w-5" />
|
||||
Products
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-4 px-2.5 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<Users2 className="h-5 w-5" />
|
||||
Customers
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center gap-4 px-2.5 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<LineChart className="h-5 w-5" />
|
||||
Settings
|
||||
</Link>
|
||||
</nav>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
<Breadcrumb className="hidden md:flex">
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink asChild>
|
||||
<Link href="#">Dashboard</Link>
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink asChild>
|
||||
<Link href="#">Products</Link>
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage>Edit Product</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
<div className="relative ml-auto flex-1 md:grow-0">
|
||||
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
type="search"
|
||||
placeholder="Search..."
|
||||
className="w-full rounded-lg bg-background pl-8 md:w-[200px] lg:w-[336px]"
|
||||
/>
|
||||
</div>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="overflow-hidden rounded-full"
|
||||
>
|
||||
<Image
|
||||
src="/placeholder-user.jpg"
|
||||
width={36}
|
||||
height={36}
|
||||
alt="Avatar"
|
||||
className="overflow-hidden rounded-full"
|
||||
/>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>Settings</DropdownMenuItem>
|
||||
<DropdownMenuItem>Support</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>Logout</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</header>
|
||||
<main className="grid flex-1 items-start gap-4 p-4 sm:px-6 sm:py-0 md:gap-8">
|
||||
<div className="mx-auto grid max-w-[59rem] flex-1 auto-rows-max gap-4">
|
||||
<div className="flex items-center gap-4">
|
||||
<Button variant="outline" size="icon" className="h-7 w-7">
|
||||
<ChevronLeft className="h-4 w-4" />
|
||||
<span className="sr-only">Back</span>
|
||||
</Button>
|
||||
<h1 className="flex-1 shrink-0 whitespace-nowrap text-xl font-semibold tracking-tight sm:grow-0">
|
||||
Pro Controller
|
||||
</h1>
|
||||
<Badge variant="outline" className="ml-auto sm:ml-0">
|
||||
In stock
|
||||
</Badge>
|
||||
<div className="hidden items-center gap-2 md:ml-auto md:flex">
|
||||
<Button variant="outline" size="sm">
|
||||
Discard
|
||||
</Button>
|
||||
<Button size="sm">Save Product</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid gap-4 md:grid-cols-[1fr_250px] lg:grid-cols-3 lg:gap-8">
|
||||
<div className="grid auto-rows-max items-start gap-4 lg:col-span-2 lg:gap-8">
|
||||
<Card x-chunk="dashboard-07-chunk-0">
|
||||
<CardHeader>
|
||||
<CardTitle>Product Details</CardTitle>
|
||||
<CardDescription>
|
||||
Lipsum dolor sit amet, consectetur adipiscing elit
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid gap-6">
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="name">Name</Label>
|
||||
<Input
|
||||
id="name"
|
||||
type="text"
|
||||
className="w-full"
|
||||
defaultValue="Gamer Gear Pro Controller"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="description">Description</Label>
|
||||
<Textarea
|
||||
id="description"
|
||||
defaultValue="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam auctor, nisl nec ultricies ultricies, nunc nisl ultricies nunc, nec ultricies nunc nisl nec nunc."
|
||||
className="min-h-32"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card x-chunk="dashboard-07-chunk-1">
|
||||
<CardHeader>
|
||||
<CardTitle>Stock</CardTitle>
|
||||
<CardDescription>
|
||||
Lipsum dolor sit amet, consectetur adipiscing elit
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-[100px]">SKU</TableHead>
|
||||
<TableHead>Stock</TableHead>
|
||||
<TableHead>Price</TableHead>
|
||||
<TableHead className="w-[100px]">Size</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell className="font-semibold">
|
||||
GGPC-001
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Label htmlFor="stock-1" className="sr-only">
|
||||
Stock
|
||||
</Label>
|
||||
<Input
|
||||
id="stock-1"
|
||||
type="number"
|
||||
defaultValue="100"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Label htmlFor="price-1" className="sr-only">
|
||||
Price
|
||||
</Label>
|
||||
<Input
|
||||
id="price-1"
|
||||
type="number"
|
||||
defaultValue="99.99"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<ToggleGroup
|
||||
type="single"
|
||||
defaultValue="s"
|
||||
variant="outline"
|
||||
>
|
||||
<ToggleGroupItem value="s">S</ToggleGroupItem>
|
||||
<ToggleGroupItem value="m">M</ToggleGroupItem>
|
||||
<ToggleGroupItem value="l">L</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell className="font-semibold">
|
||||
GGPC-002
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Label htmlFor="stock-2" className="sr-only">
|
||||
Stock
|
||||
</Label>
|
||||
<Input
|
||||
id="stock-2"
|
||||
type="number"
|
||||
defaultValue="143"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Label htmlFor="price-2" className="sr-only">
|
||||
Price
|
||||
</Label>
|
||||
<Input
|
||||
id="price-2"
|
||||
type="number"
|
||||
defaultValue="99.99"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<ToggleGroup
|
||||
type="single"
|
||||
defaultValue="m"
|
||||
variant="outline"
|
||||
>
|
||||
<ToggleGroupItem value="s">S</ToggleGroupItem>
|
||||
<ToggleGroupItem value="m">M</ToggleGroupItem>
|
||||
<ToggleGroupItem value="l">L</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell className="font-semibold">
|
||||
GGPC-003
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Label htmlFor="stock-3" className="sr-only">
|
||||
Stock
|
||||
</Label>
|
||||
<Input
|
||||
id="stock-3"
|
||||
type="number"
|
||||
defaultValue="32"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Label htmlFor="price-3" className="sr-only">
|
||||
Stock
|
||||
</Label>
|
||||
<Input
|
||||
id="price-3"
|
||||
type="number"
|
||||
defaultValue="99.99"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<ToggleGroup
|
||||
type="single"
|
||||
defaultValue="s"
|
||||
variant="outline"
|
||||
>
|
||||
<ToggleGroupItem value="s">S</ToggleGroupItem>
|
||||
<ToggleGroupItem value="m">M</ToggleGroupItem>
|
||||
<ToggleGroupItem value="l">L</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
<CardFooter className="justify-center border-t p-4">
|
||||
<Button size="sm" variant="ghost" className="gap-1">
|
||||
<PlusCircle className="h-3.5 w-3.5" />
|
||||
Add Variant
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
<Card x-chunk="dashboard-07-chunk-2">
|
||||
<CardHeader>
|
||||
<CardTitle>Product Category</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid gap-6 sm:grid-cols-3">
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="category">Category</Label>
|
||||
<Select>
|
||||
<SelectTrigger
|
||||
id="category"
|
||||
aria-label="Select category"
|
||||
>
|
||||
<SelectValue placeholder="Select category" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="clothing">Clothing</SelectItem>
|
||||
<SelectItem value="electronics">
|
||||
Electronics
|
||||
</SelectItem>
|
||||
<SelectItem value="accessories">
|
||||
Accessories
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="subcategory">
|
||||
Subcategory (optional)
|
||||
</Label>
|
||||
<Select>
|
||||
<SelectTrigger
|
||||
id="subcategory"
|
||||
aria-label="Select subcategory"
|
||||
>
|
||||
<SelectValue placeholder="Select subcategory" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="t-shirts">T-Shirts</SelectItem>
|
||||
<SelectItem value="hoodies">Hoodies</SelectItem>
|
||||
<SelectItem value="sweatshirts">
|
||||
Sweatshirts
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
<div className="grid auto-rows-max items-start gap-4 lg:gap-8">
|
||||
<Card x-chunk="dashboard-07-chunk-3">
|
||||
<CardHeader>
|
||||
<CardTitle>Product Status</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid gap-6">
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="status">Status</Label>
|
||||
<Select>
|
||||
<SelectTrigger id="status" aria-label="Select status">
|
||||
<SelectValue placeholder="Select status" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="draft">Draft</SelectItem>
|
||||
<SelectItem value="published">Active</SelectItem>
|
||||
<SelectItem value="archived">Archived</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card
|
||||
className="overflow-hidden"
|
||||
x-chunk="dashboard-07-chunk-4"
|
||||
>
|
||||
<CardHeader>
|
||||
<CardTitle>Product Images</CardTitle>
|
||||
<CardDescription>
|
||||
Lipsum dolor sit amet, consectetur adipiscing elit
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid gap-2">
|
||||
<Image
|
||||
alt="Product image"
|
||||
className="aspect-square w-full rounded-md object-cover"
|
||||
height="300"
|
||||
src="/placeholder.svg"
|
||||
width="300"
|
||||
/>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<button>
|
||||
<Image
|
||||
alt="Product image"
|
||||
className="aspect-square w-full rounded-md object-cover"
|
||||
height="84"
|
||||
src="/placeholder.svg"
|
||||
width="84"
|
||||
/>
|
||||
</button>
|
||||
<button>
|
||||
<Image
|
||||
alt="Product image"
|
||||
className="aspect-square w-full rounded-md object-cover"
|
||||
height="84"
|
||||
src="/placeholder.svg"
|
||||
width="84"
|
||||
/>
|
||||
</button>
|
||||
<button className="flex aspect-square w-full items-center justify-center rounded-md border border-dashed">
|
||||
<Upload className="h-4 w-4 text-muted-foreground" />
|
||||
<span className="sr-only">Upload</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card x-chunk="dashboard-07-chunk-5">
|
||||
<CardHeader>
|
||||
<CardTitle>Archive Product</CardTitle>
|
||||
<CardDescription>
|
||||
Lipsum dolor sit amet, consectetur adipiscing elit.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div></div>
|
||||
<Button size="sm" variant="secondary">
|
||||
Archive Product
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-center gap-2 md:hidden">
|
||||
<Button variant="outline" size="sm">
|
||||
Discard
|
||||
</Button>
|
||||
<Button size="sm">Save Product</Button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
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' aesthetic.
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
<AccordionItem value="item-3">
|
||||
<AccordionTrigger>Is it animated?</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
Yes. It's animated by default, but you can disable it if you
|
||||
prefer.
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
+4
-6
@@ -1,5 +1,3 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
@@ -10,14 +8,14 @@ import {
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog"
|
||||
import { Button } from "@/components/ui/button"
|
||||
} from "@/registry/default/ui/alert-dialog"
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
|
||||
export function AlertDialogDemo() {
|
||||
export default function AlertDialogDemo() {
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="outline">Open</Button>
|
||||
<Button variant="outline">Show Dialog</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
@@ -0,0 +1,16 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import {
|
||||
Avatar,
|
||||
AvatarFallback,
|
||||
AvatarImage,
|
||||
} from "@/registry/default/ui/avatar"
|
||||
|
||||
export default function AvatarDemo() {
|
||||
return (
|
||||
<Avatar>
|
||||
<AvatarImage src="https://github.com/hanzoai.png" alt="@hanzoai" />
|
||||
<AvatarFallback>CN</AvatarFallback>
|
||||
</Avatar>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Badge } from "@/registry/default/ui/badge"
|
||||
|
||||
export default function BadgeDemo() {
|
||||
return <Badge>Badge</Badge>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Badge } from "@/registry/default/ui/badge"
|
||||
|
||||
export default function BadgeDestructive() {
|
||||
return <Badge variant="destructive">Destructive</Badge>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Badge } from "@/registry/default/ui/badge"
|
||||
|
||||
export default function BadgeOutline() {
|
||||
return <Badge variant="outline">Outline</Badge>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Badge } from "@/registry/default/ui/badge"
|
||||
|
||||
export default function BadgeSecondary() {
|
||||
return <Badge variant="secondary">Secondary</Badge>
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
"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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
|
||||
export default function ButtonDemo() {
|
||||
return <Button>Button</Button>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
|
||||
export default function ButtonDestructive() {
|
||||
return <Button variant="destructive">Destructive</Button>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
|
||||
export default function ButtonGhost() {
|
||||
return <Button variant="ghost">Ghost</Button>
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
|
||||
export default function ButtonLink() {
|
||||
return <Button variant="link">Link</Button>
|
||||
}
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import { Loader2 } from "lucide-react"
|
||||
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
|
||||
export function ButtonLoading() {
|
||||
export default function ButtonLoading() {
|
||||
return (
|
||||
<Button disabled>
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
|
||||
export default function ButtonOutline() {
|
||||
return <Button variant="outline">Outline</Button>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
|
||||
export default function ButtonSecondary() {
|
||||
return <Button variant="secondary">Secondary</Button>
|
||||
}
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import { Mail } from "lucide-react"
|
||||
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
|
||||
export function ButtonWithIcon() {
|
||||
export default function ButtonWithIcon() {
|
||||
return (
|
||||
<Button>
|
||||
<Mail className="mr-2 h-4 w-4" /> Login with Email
|
||||
@@ -0,0 +1,18 @@
|
||||
"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"
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
"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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
"use client"
|
||||
|
||||
import { Checkbox } from "@/components/ui/checkbox"
|
||||
import { Checkbox } from "@/registry/default/ui/checkbox"
|
||||
|
||||
export function CheckboxDemo() {
|
||||
export default function CheckboxDemo() {
|
||||
return (
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox id="terms" />
|
||||
+2
-4
@@ -1,8 +1,6 @@
|
||||
"use client"
|
||||
import { Checkbox } from "@/registry/default/ui/checkbox"
|
||||
|
||||
import { Checkbox } from "@/components/ui/checkbox"
|
||||
|
||||
export function CheckboxDisabled() {
|
||||
export default function CheckboxDisabled() {
|
||||
return (
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox id="terms2" disabled />
|
||||
@@ -0,0 +1,127 @@
|
||||
"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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
"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>
|
||||
)
|
||||
}
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
"use client"
|
||||
|
||||
import { Checkbox } from "@/components/ui/checkbox"
|
||||
import { Checkbox } from "@/registry/default/ui/checkbox"
|
||||
|
||||
export function CheckboxWithText() {
|
||||
export default function CheckboxWithText() {
|
||||
return (
|
||||
<div className="items-top flex space-x-2">
|
||||
<Checkbox id="terms1" />
|
||||
@@ -13,7 +13,7 @@ export function CheckboxWithText() {
|
||||
>
|
||||
Accept terms and conditions
|
||||
</label>
|
||||
<p className="text-sm text-slate-500 dark:text-slate-400">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
You agree to our Terms of Service and Privacy Policy.
|
||||
</p>
|
||||
</div>
|
||||
+6
-6
@@ -3,14 +3,14 @@
|
||||
import * as React from "react"
|
||||
import { ChevronsUpDown, Plus, X } from "lucide-react"
|
||||
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "@/components/ui/collapsible"
|
||||
} from "@/registry/default/ui/collapsible"
|
||||
|
||||
export function CollapsibleDemo() {
|
||||
export default function CollapsibleDemo() {
|
||||
const [isOpen, setIsOpen] = React.useState(false)
|
||||
|
||||
return (
|
||||
@@ -30,14 +30,14 @@ export function CollapsibleDemo() {
|
||||
</Button>
|
||||
</CollapsibleTrigger>
|
||||
</div>
|
||||
<div className="rounded-md border border-slate-200 px-4 py-3 font-mono text-sm dark:border-slate-700">
|
||||
<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 border-slate-200 px-4 py-3 font-mono text-sm dark:border-slate-700">
|
||||
<div className="rounded-md border px-4 py-3 font-mono text-sm">
|
||||
@radix-ui/colors
|
||||
</div>
|
||||
<div className="rounded-md border border-slate-200 px-4 py-3 font-mono text-sm dark:border-slate-700">
|
||||
<div className="rounded-md border px-4 py-3 font-mono text-sm">
|
||||
@stitches/react
|
||||
</div>
|
||||
</CollapsibleContent>
|
||||
+5
-4
@@ -4,19 +4,19 @@ import * as React from "react"
|
||||
import { Check, ChevronsUpDown } from "lucide-react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
} from "@/components/ui/command"
|
||||
} from "@/registry/default/ui/command"
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover"
|
||||
} from "@/registry/default/ui/popover"
|
||||
|
||||
const frameworks = [
|
||||
{
|
||||
@@ -41,7 +41,7 @@ const frameworks = [
|
||||
},
|
||||
]
|
||||
|
||||
export function CommandCombobox() {
|
||||
export default function ComboboxDemo() {
|
||||
const [open, setOpen] = React.useState(false)
|
||||
const [value, setValue] = React.useState("")
|
||||
|
||||
@@ -68,6 +68,7 @@ export function CommandCombobox() {
|
||||
{frameworks.map((framework) => (
|
||||
<CommandItem
|
||||
key={framework.value}
|
||||
value={framework.value}
|
||||
onSelect={(currentValue) => {
|
||||
setValue(currentValue === value ? "" : currentValue)
|
||||
setOpen(false)
|
||||
+9
-8
@@ -1,9 +1,9 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Calendar, MoreHorizontal, Pen, Tags, Trash, User } from "lucide-react"
|
||||
import { Calendar, MoreHorizontal, Tags, Trash, User } from "lucide-react"
|
||||
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from "@/components/ui/command"
|
||||
} from "@/registry/default/ui/command"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
} from "@/registry/default/ui/dropdown-menu"
|
||||
|
||||
const labels = [
|
||||
"feature",
|
||||
@@ -36,17 +36,17 @@ const labels = [
|
||||
"maintenance",
|
||||
]
|
||||
|
||||
export function CommandDropdownMenu() {
|
||||
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 border-slate-200 py-3 px-4 dark:border-slate-700 sm:flex-row sm:items-center">
|
||||
<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-slate-900 px-2 py-1 text-xs text-slate-50 dark:bg-slate-800 dark:text-slate-100">
|
||||
<span className="mr-2 rounded-lg bg-primary px-2 py-1 text-xs text-primary-foreground">
|
||||
{label}
|
||||
</span>
|
||||
<span className="text-slate-500">Create a new project</span>
|
||||
<span className="text-muted-foreground">Create a new project</span>
|
||||
</p>
|
||||
<DropdownMenu open={open} onOpenChange={setOpen}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
@@ -83,6 +83,7 @@ export function CommandDropdownMenu() {
|
||||
{labels.map((label) => (
|
||||
<CommandItem
|
||||
key={label}
|
||||
value={label}
|
||||
onSelect={(value) => {
|
||||
setLabel(value)
|
||||
setOpen(false)
|
||||
@@ -0,0 +1,135 @@
|
||||
"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>
|
||||
)
|
||||
}
|
||||
+7
-6
@@ -11,7 +11,7 @@ import {
|
||||
} from "lucide-react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
@@ -19,12 +19,12 @@ import {
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from "@/components/ui/command"
|
||||
} from "@/registry/default/ui/command"
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover"
|
||||
} from "@/registry/default/ui/popover"
|
||||
|
||||
type Status = {
|
||||
value: string
|
||||
@@ -60,7 +60,7 @@ const statuses: Status[] = [
|
||||
},
|
||||
]
|
||||
|
||||
export function CommandPopover() {
|
||||
export default function ComboboxPopover() {
|
||||
const [open, setOpen] = React.useState(false)
|
||||
const [selectedStatus, setSelectedStatus] = React.useState<Status | null>(
|
||||
null
|
||||
@@ -68,13 +68,13 @@ export function CommandPopover() {
|
||||
|
||||
return (
|
||||
<div className="flex items-center space-x-4">
|
||||
<p className="text-sm text-slate-500 dark:text-slate-400">Status</p>
|
||||
<p className="text-sm text-muted-foreground">Status</p>
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="w-[120px] justify-start"
|
||||
className="w-[150px] justify-start"
|
||||
>
|
||||
{selectedStatus ? (
|
||||
<>
|
||||
@@ -95,6 +95,7 @@ export function CommandPopover() {
|
||||
{statuses.map((status) => (
|
||||
<CommandItem
|
||||
key={status.value}
|
||||
value={status.value}
|
||||
onSelect={(value) => {
|
||||
setSelectedStatus(
|
||||
statuses.find((priority) => priority.value === value) ||
|
||||
@@ -0,0 +1,123 @@
|
||||
"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>
|
||||
)
|
||||
}
|
||||
+3
-5
@@ -1,5 +1,3 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Calculator,
|
||||
Calendar,
|
||||
@@ -18,11 +16,11 @@ import {
|
||||
CommandList,
|
||||
CommandSeparator,
|
||||
CommandShortcut,
|
||||
} from "@/components/ui/command"
|
||||
} from "@/registry/default/ui/command"
|
||||
|
||||
export function CommandDemo() {
|
||||
export default function CommandDemo() {
|
||||
return (
|
||||
<Command className="rounded-lg border border-slate-100 shadow-md dark:border-slate-800">
|
||||
<Command className="rounded-lg border shadow-md">
|
||||
<CommandInput placeholder="Type a command or search..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>No results found.</CommandEmpty>
|
||||
+6
-5
@@ -19,14 +19,15 @@ import {
|
||||
CommandList,
|
||||
CommandSeparator,
|
||||
CommandShortcut,
|
||||
} from "@/components/ui/command"
|
||||
} from "@/registry/default/ui/command"
|
||||
|
||||
export function CommandDialogDemo() {
|
||||
export default function CommandDialogDemo() {
|
||||
const [open, setOpen] = React.useState(false)
|
||||
|
||||
React.useEffect(() => {
|
||||
const down = (e: KeyboardEvent) => {
|
||||
if (e.key === "j" && e.metaKey) {
|
||||
if (e.key === "j" && (e.metaKey || e.ctrlKey)) {
|
||||
e.preventDefault()
|
||||
setOpen((open) => !open)
|
||||
}
|
||||
}
|
||||
@@ -37,9 +38,9 @@ export function CommandDialogDemo() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<p className="text-sm text-slate-500 dark:text-slate-400">
|
||||
<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 border-slate-100 bg-slate-100 px-1.5 font-mono text-[10px] font-medium text-slate-600 opacity-100 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-400">
|
||||
<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>
|
||||
+3
-25
@@ -1,31 +1,9 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Cloud,
|
||||
CreditCard,
|
||||
Github,
|
||||
Keyboard,
|
||||
LifeBuoy,
|
||||
LogOut,
|
||||
Mail,
|
||||
MessageSquare,
|
||||
Plus,
|
||||
PlusCircle,
|
||||
Settings,
|
||||
User,
|
||||
UserPlus,
|
||||
Users,
|
||||
} from "lucide-react"
|
||||
|
||||
import { Button } from "@/components/ui/button"
|
||||
import {
|
||||
ContextMenu,
|
||||
ContextMenuCheckboxItem,
|
||||
ContextMenuContent,
|
||||
ContextMenuGroup,
|
||||
ContextMenuItem,
|
||||
ContextMenuLabel,
|
||||
ContextMenuPortal,
|
||||
ContextMenuRadioGroup,
|
||||
ContextMenuRadioItem,
|
||||
ContextMenuSeparator,
|
||||
@@ -34,12 +12,12 @@ import {
|
||||
ContextMenuSubContent,
|
||||
ContextMenuSubTrigger,
|
||||
ContextMenuTrigger,
|
||||
} from "@/components/ui/context-menu"
|
||||
} from "@/registry/default/ui/context-menu"
|
||||
|
||||
export function ContextMenuDemo() {
|
||||
export default function ContextMenuDemo() {
|
||||
return (
|
||||
<ContextMenu>
|
||||
<ContextMenuTrigger className="flex h-[150px] w-[300px] items-center justify-center rounded-md border border-dashed border-slate-200 text-sm dark:border-slate-700">
|
||||
<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">
|
||||
@@ -0,0 +1,312 @@
|
||||
"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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
"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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
"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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
"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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
"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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
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.hanzo.ai/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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
import * as React from "react"
|
||||
import { Minus, Plus } from "lucide-react"
|
||||
import { Bar, BarChart, ResponsiveContainer } from "recharts"
|
||||
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
import {
|
||||
Drawer,
|
||||
DrawerClose,
|
||||
DrawerContent,
|
||||
DrawerDescription,
|
||||
DrawerFooter,
|
||||
DrawerHeader,
|
||||
DrawerTitle,
|
||||
DrawerTrigger,
|
||||
} from "@/registry/default/ui/drawer"
|
||||
|
||||
const data = [
|
||||
{
|
||||
goal: 400,
|
||||
},
|
||||
{
|
||||
goal: 300,
|
||||
},
|
||||
{
|
||||
goal: 200,
|
||||
},
|
||||
{
|
||||
goal: 300,
|
||||
},
|
||||
{
|
||||
goal: 200,
|
||||
},
|
||||
{
|
||||
goal: 278,
|
||||
},
|
||||
{
|
||||
goal: 189,
|
||||
},
|
||||
{
|
||||
goal: 239,
|
||||
},
|
||||
{
|
||||
goal: 300,
|
||||
},
|
||||
{
|
||||
goal: 200,
|
||||
},
|
||||
{
|
||||
goal: 278,
|
||||
},
|
||||
{
|
||||
goal: 189,
|
||||
},
|
||||
{
|
||||
goal: 349,
|
||||
},
|
||||
]
|
||||
|
||||
export default function DrawerDemo() {
|
||||
const [goal, setGoal] = React.useState(350)
|
||||
|
||||
function onClick(adjustment: number) {
|
||||
setGoal(Math.max(200, Math.min(400, goal + adjustment)))
|
||||
}
|
||||
|
||||
return (
|
||||
<Drawer>
|
||||
<DrawerTrigger asChild>
|
||||
<Button variant="outline">Open Drawer</Button>
|
||||
</DrawerTrigger>
|
||||
<DrawerContent>
|
||||
<div className="mx-auto w-full max-w-sm">
|
||||
<DrawerHeader>
|
||||
<DrawerTitle>Move Goal</DrawerTitle>
|
||||
<DrawerDescription>Set your daily activity goal.</DrawerDescription>
|
||||
</DrawerHeader>
|
||||
<div className="p-4 pb-0">
|
||||
<div className="flex items-center justify-center space-x-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="h-8 w-8 shrink-0 rounded-full"
|
||||
onClick={() => onClick(-10)}
|
||||
disabled={goal <= 200}
|
||||
>
|
||||
<Minus className="h-4 w-4" />
|
||||
<span className="sr-only">Decrease</span>
|
||||
</Button>
|
||||
<div className="flex-1 text-center">
|
||||
<div className="text-7xl font-bold tracking-tighter">
|
||||
{goal}
|
||||
</div>
|
||||
<div className="text-[0.70rem] uppercase text-muted-foreground">
|
||||
Calories/day
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="h-8 w-8 shrink-0 rounded-full"
|
||||
onClick={() => onClick(10)}
|
||||
disabled={goal >= 400}
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
<span className="sr-only">Increase</span>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="mt-3 h-[120px]">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<BarChart data={data}>
|
||||
<Bar
|
||||
dataKey="goal"
|
||||
style={
|
||||
{
|
||||
fill: "hsl(var(--foreground))",
|
||||
opacity: 0.9,
|
||||
} as React.CSSProperties
|
||||
}
|
||||
/>
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</div>
|
||||
<DrawerFooter>
|
||||
<Button>Submit</Button>
|
||||
<DrawerClose asChild>
|
||||
<Button variant="outline">Cancel</Button>
|
||||
</DrawerClose>
|
||||
</DrawerFooter>
|
||||
</div>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { useMediaQuery } from "@/hooks/use-media-query"
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/registry/default/ui/dialog"
|
||||
import {
|
||||
Drawer,
|
||||
DrawerClose,
|
||||
DrawerContent,
|
||||
DrawerDescription,
|
||||
DrawerFooter,
|
||||
DrawerHeader,
|
||||
DrawerTitle,
|
||||
DrawerTrigger,
|
||||
} from "@/registry/default/ui/drawer"
|
||||
import { Input } from "@/registry/default/ui/input"
|
||||
import { Label } from "@/registry/default/ui/label"
|
||||
|
||||
export default function DrawerDialogDemo() {
|
||||
const [open, setOpen] = React.useState(false)
|
||||
const isDesktop = useMediaQuery("(min-width: 768px)")
|
||||
|
||||
if (isDesktop) {
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline">Edit Profile</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Edit profile</DialogTitle>
|
||||
<DialogDescription>
|
||||
Make changes to your profile here. Click save when you're done.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<ProfileForm />
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Drawer open={open} onOpenChange={setOpen}>
|
||||
<DrawerTrigger asChild>
|
||||
<Button variant="outline">Edit Profile</Button>
|
||||
</DrawerTrigger>
|
||||
<DrawerContent>
|
||||
<DrawerHeader className="text-left">
|
||||
<DrawerTitle>Edit profile</DrawerTitle>
|
||||
<DrawerDescription>
|
||||
Make changes to your profile here. Click save when you're done.
|
||||
</DrawerDescription>
|
||||
</DrawerHeader>
|
||||
<ProfileForm className="px-4" />
|
||||
<DrawerFooter className="pt-2">
|
||||
<DrawerClose asChild>
|
||||
<Button variant="outline">Cancel</Button>
|
||||
</DrawerClose>
|
||||
</DrawerFooter>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
)
|
||||
}
|
||||
|
||||
function ProfileForm({ className }: React.ComponentProps<"form">) {
|
||||
return (
|
||||
<form className={cn("grid items-start gap-4", className)}>
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="email">Email</Label>
|
||||
<Input type="email" id="email" defaultValue="hanzo@example.com" />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="username">Username</Label>
|
||||
<Input id="username" defaultValue="@hanzoai" />
|
||||
</div>
|
||||
<Button type="submit">Save changes</Button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
+3
-3
@@ -3,7 +3,7 @@
|
||||
import * as React from "react"
|
||||
import { DropdownMenuCheckboxItemProps } from "@radix-ui/react-dropdown-menu"
|
||||
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
@@ -11,11 +11,11 @@ import {
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
} from "@/registry/default/ui/dropdown-menu"
|
||||
|
||||
type Checked = DropdownMenuCheckboxItemProps["checked"]
|
||||
|
||||
export function DropdownMenuCheckboxes() {
|
||||
export default function DropdownMenuCheckboxes() {
|
||||
const [showStatusBar, setShowStatusBar] = React.useState<Checked>(true)
|
||||
const [showActivityBar, setShowActivityBar] = React.useState<Checked>(false)
|
||||
const [showPanel, setShowPanel] = React.useState<Checked>(false)
|
||||
+3
-5
@@ -1,5 +1,3 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Cloud,
|
||||
CreditCard,
|
||||
@@ -17,7 +15,7 @@ import {
|
||||
Users,
|
||||
} from "lucide-react"
|
||||
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
@@ -31,9 +29,9 @@ import {
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
} from "@/registry/default/ui/dropdown-menu"
|
||||
|
||||
export function DropdownMenuDemo() {
|
||||
export default function DropdownMenuDemo() {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
+3
-5
@@ -1,21 +1,19 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { DropdownMenuCheckboxItemProps } from "@radix-ui/react-dropdown-menu"
|
||||
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Button } from "@/registry/default/ui/button"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuRadioGroup,
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
} from "@/registry/default/ui/dropdown-menu"
|
||||
|
||||
export function DropdownMenuRadioGroupDemo() {
|
||||
export default function DropdownMenuRadioGroupDemo() {
|
||||
const [position, setPosition] = React.useState("bottom")
|
||||
|
||||
return (
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user