mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-15 20:48:12 +01:00
Compare commits
492 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64897a39bf | ||
|
|
dfda33c1aa | ||
|
|
d46eafb248 | ||
|
|
ee6f0d0c49 | ||
|
|
b7b86bcc44 | ||
|
|
bbf3424933 | ||
|
|
2fc938575d | ||
|
|
ff9d51863e | ||
|
|
adb0a0fbe4 | ||
|
|
a071e4b875 | ||
|
|
a74de152d7 | ||
|
|
109ec52d50 | ||
|
|
874447cb41 | ||
|
|
8b7a013319 | ||
|
|
3e647e4af1 | ||
|
|
0da85e1463 | ||
|
|
dcf6e63471 | ||
|
|
cbb2f28c3f | ||
|
|
be734fc026 | ||
|
|
b306138574 | ||
|
|
1ebf456ffc | ||
|
|
8257a11dcb | ||
|
|
6887f732ee | ||
|
|
d088d8a7b8 | ||
|
|
f60543a234 | ||
|
|
2531c8e66d | ||
|
|
4b68760f6a | ||
|
|
568772382f | ||
|
|
46879dc1b7 | ||
|
|
a94782d94b | ||
|
|
853d58ad5f | ||
|
|
38b1eb6c5f | ||
|
|
f24ff9c47f | ||
|
|
60210aad75 | ||
|
|
67e85f98e2 | ||
|
|
b3a52482f2 | ||
|
|
86dc49ecc9 | ||
|
|
c937736734 | ||
|
|
d379c579c0 | ||
|
|
f983c974c4 | ||
|
|
b90b151588 | ||
|
|
34d2f57801 | ||
|
|
2c98628f98 | ||
|
|
681f0e5684 | ||
|
|
e40491208a | ||
|
|
00594ea59b | ||
|
|
3ba95d3c4d | ||
|
|
3424ce118d | ||
|
|
40b1d30f5c | ||
|
|
8ec23c042d | ||
|
|
81463cd21d | ||
|
|
c44d363f62 | ||
|
|
fbfa14a6a3 | ||
|
|
4127caac76 | ||
|
|
d6476d17f9 | ||
|
|
5fc44b97c6 | ||
|
|
15e418e6c6 | ||
|
|
3b8ca9886d | ||
|
|
4c5833083f | ||
|
|
83d609d530 | ||
|
|
1b34df15ac | ||
|
|
0178ca9586 | ||
|
|
40ecb23d9a | ||
|
|
85734b8615 | ||
|
|
ab26e4ba7d | ||
|
|
edbbb33f69 | ||
|
|
3de3aa006c | ||
|
|
784f1f51dd | ||
|
|
0787ec2d12 | ||
|
|
a8f643939e | ||
|
|
6f77ee80ce | ||
|
|
e2d4ba529d | ||
|
|
1c707ca00d | ||
|
|
00e951f708 | ||
|
|
0544a01c5b | ||
|
|
290ab1d9c5 | ||
|
|
254c4ed7d3 | ||
|
|
a603ea56c1 | ||
|
|
a90e95f7d1 | ||
|
|
bc2315b7d9 | ||
|
|
87fd85ec3f | ||
|
|
3fef86834f | ||
|
|
b5e8685a2c | ||
|
|
15ee768729 | ||
|
|
8955595dc6 | ||
|
|
fd6bcd3f84 | ||
|
|
9d23b82d1d | ||
|
|
511ed6a86c | ||
|
|
e8daf7f810 | ||
|
|
a43c68c501 | ||
|
|
ef7d3ce549 | ||
|
|
c2e561cfe4 | ||
|
|
1d1c36b44c | ||
|
|
95abc759b9 | ||
|
|
700b2bb4d7 | ||
|
|
1d077c45d5 | ||
|
|
14cca48e96 | ||
|
|
22430e168a | ||
|
|
c1e0654417 | ||
|
|
1a7eb27cad | ||
|
|
0d5f008168 | ||
|
|
ba2716a66a | ||
|
|
5d66155885 | ||
|
|
02f3164af3 | ||
|
|
240db8ee19 | ||
|
|
b905216a95 | ||
|
|
c47d928f49 | ||
|
|
7e0a655c64 | ||
|
|
02bbc9b9cf | ||
|
|
98e1d1b90e | ||
|
|
2b1e7bcc57 | ||
|
|
52958af81a | ||
|
|
de4416d5bf | ||
|
|
9ae038489e | ||
|
|
6ad1afd308 | ||
|
|
ab5153ac19 | ||
|
|
eebff72d01 | ||
|
|
c20aefdd91 | ||
|
|
0f252d0caf | ||
|
|
888effea0a | ||
|
|
3ed282df98 | ||
|
|
22f7536154 | ||
|
|
9f9d8f5cec | ||
|
|
190378aaa9 | ||
|
|
9b3a22ea14 | ||
|
|
7c157ce886 | ||
|
|
e49c673573 | ||
|
|
e578b0dd9e | ||
|
|
b3bc6e2e9e | ||
|
|
e04c212d0d | ||
|
|
92da3238eb | ||
|
|
d9363168b2 | ||
|
|
53b2655ae5 | ||
|
|
f12c149e4e | ||
|
|
c4bcf0220b | ||
|
|
73fc310e8d | ||
|
|
7dff23912d | ||
|
|
1145f88bca | ||
|
|
573c8a2f54 | ||
|
|
7dbfe4ecd6 | ||
|
|
98b3c3550c | ||
|
|
791804b2fb | ||
|
|
f1ed0076e5 | ||
|
|
11980a3c9c | ||
|
|
b901222c4b | ||
|
|
2e056fa3cf | ||
|
|
b955f57084 | ||
|
|
1435856586 | ||
|
|
ce160c9a97 | ||
|
|
c88c8094a5 | ||
|
|
7e7e9d0f85 | ||
|
|
ee663157b7 | ||
|
|
44ba758c0d | ||
|
|
cb5484a603 | ||
|
|
998314e1cb | ||
|
|
d4e3ab606b | ||
|
|
0a7c50ba98 | ||
|
|
88cc2e93af | ||
|
|
39042b3de1 | ||
|
|
8880bdc456 | ||
|
|
6d7973f6e1 | ||
|
|
60bb74675c | ||
|
|
a488b879f5 | ||
|
|
fa1103b4ec | ||
|
|
28ebfc2575 | ||
|
|
fdce429b3e | ||
|
|
7e2bebd3ef | ||
|
|
ccb0f6207c | ||
|
|
f501460ebb | ||
|
|
858886a852 | ||
|
|
74f4903836 | ||
|
|
16ac4a0533 | ||
|
|
451e72a583 | ||
|
|
a8a1c150a0 | ||
|
|
b243e8c946 | ||
|
|
a29877059e | ||
|
|
55daed0e5a | ||
|
|
1c00a366c2 | ||
|
|
9866f051b2 | ||
|
|
3d6839da97 | ||
|
|
8b19b1880e | ||
|
|
2d6badd4b0 | ||
|
|
df3b2028ed | ||
|
|
eb609b13e4 | ||
|
|
aaf09ad555 | ||
|
|
ad0fe230ba | ||
|
|
c6056ed133 | ||
|
|
7008df0988 | ||
|
|
dc951ff69d | ||
|
|
e2146a5a58 | ||
|
|
75d26e0c2b | ||
|
|
32a32d00ab | ||
|
|
189bd4cd3e | ||
|
|
871d3b3a85 | ||
|
|
248b0a68c6 | ||
|
|
396aae7563 | ||
|
|
dc1979cae1 | ||
|
|
d51ad93f40 | ||
|
|
c59595f2c6 | ||
|
|
a3aba1abad | ||
|
|
c37a927b4e | ||
|
|
05ea5d2d78 | ||
|
|
963d81324c | ||
|
|
927b63fa2e | ||
|
|
cefe5a76e0 | ||
|
|
a9300db91e | ||
|
|
8e1aa2f1b6 | ||
|
|
5221294f78 | ||
|
|
1bc055935e | ||
|
|
e25be118b7 | ||
|
|
93aebe6fc6 | ||
|
|
2b3dc8d065 | ||
|
|
5cf3bcf32d | ||
|
|
3b183ac9cd | ||
|
|
3400e17d17 | ||
|
|
4cd38ecc5a | ||
|
|
8380607a85 | ||
|
|
4561816b50 | ||
|
|
e6d1106b83 | ||
|
|
94f1c4e6a0 | ||
|
|
09d0ea27ab | ||
|
|
66ab95a2be | ||
|
|
2cd620899f | ||
|
|
0300be8539 | ||
|
|
5bd5dc2bca | ||
|
|
572b7a5984 | ||
|
|
ab2abae48a | ||
|
|
8298b62f21 | ||
|
|
10890e6704 | ||
|
|
3af39cacf7 | ||
|
|
58e3958390 | ||
|
|
3dd0492f91 | ||
|
|
9a73c5fb64 | ||
|
|
e7cfca2aa7 | ||
|
|
dc77cf292b | ||
|
|
05503e564c | ||
|
|
0420a17c1d | ||
|
|
a9578f8c50 | ||
|
|
d9ae1ee5b0 | ||
|
|
9e5f265f42 | ||
|
|
041f9e17de | ||
|
|
df1e4a40ca | ||
|
|
f005cbb95e | ||
|
|
d2a8a07a21 | ||
|
|
b0440f81ce | ||
|
|
4f4a659ccc | ||
|
|
beffde1849 | ||
|
|
959c968420 | ||
|
|
7cccbcfef8 | ||
|
|
df455db3ca | ||
|
|
9fc786eda0 | ||
|
|
92a9ac0c85 | ||
|
|
5a9910c2a3 | ||
|
|
a0f485c49d | ||
|
|
e92f341224 | ||
|
|
c4e0e5a685 | ||
|
|
72ee359b73 | ||
|
|
8a2b2604be | ||
|
|
d94c1b5b15 | ||
|
|
b0486140e2 | ||
|
|
b7d9c08a1c | ||
|
|
dbcb02d0ea | ||
|
|
208acca1e9 | ||
|
|
82e152be02 | ||
|
|
403899f11a | ||
|
|
914d156103 | ||
|
|
0f06b7c3fe | ||
|
|
2c454b528a | ||
|
|
b28ae68945 | ||
|
|
1171724791 | ||
|
|
ad63c72d37 | ||
|
|
d7f74d1868 | ||
|
|
a0ffdce36c | ||
|
|
a31e7dfa28 | ||
|
|
c91ea60c84 | ||
|
|
a11248fd33 | ||
|
|
2fc579560e | ||
|
|
5f8fe8559f | ||
|
|
46b444a3e0 | ||
|
|
0ea1f310a9 | ||
|
|
b1825ffa7d | ||
|
|
7be48fd6f3 | ||
|
|
d292706967 | ||
|
|
31d571abb5 | ||
|
|
2ec28e7cbd | ||
|
|
908235e8dd | ||
|
|
5a4d0e1097 | ||
|
|
773a23f969 | ||
|
|
7554a10206 | ||
|
|
914cb03a5d | ||
|
|
4afdd3bd64 | ||
|
|
05b8a22eec | ||
|
|
7e08e5b024 | ||
|
|
d15e8163e7 | ||
|
|
2cc5c0d810 | ||
|
|
e08263ff38 | ||
|
|
57c3023909 | ||
|
|
b874bb5061 | ||
|
|
cbe2b1bfb8 | ||
|
|
3b432fde7a | ||
|
|
a79c165eee | ||
|
|
cd2b671075 | ||
|
|
3de6b349d8 | ||
|
|
eaf0043da6 | ||
|
|
b78fcf91a4 | ||
|
|
e0f1798f07 | ||
|
|
e4233718a6 | ||
|
|
a11abd6347 | ||
|
|
db346652b8 | ||
|
|
52b614fcb0 | ||
|
|
5dffa868b1 | ||
|
|
cbd8cc49fb | ||
|
|
f3c6f83232 | ||
|
|
80a9738490 | ||
|
|
54b6f734a3 | ||
|
|
41a5238579 | ||
|
|
c92dc980c9 | ||
|
|
2451541d7d | ||
|
|
103a20897c | ||
|
|
e50f377b94 | ||
|
|
0bfe4b01bd | ||
|
|
80e09df342 | ||
|
|
7a2845d75e | ||
|
|
10a9a3ea2b | ||
|
|
1ff11ac1a3 | ||
|
|
07b27a228d | ||
|
|
6be9290f68 | ||
|
|
0f3fe0d54e | ||
|
|
0815f688ed | ||
|
|
8399ffe1f1 | ||
|
|
91f6103719 | ||
|
|
278a1ea93c | ||
|
|
3f27c0ccae | ||
|
|
5a2f46683a | ||
|
|
c8a0005253 | ||
|
|
881f3547f2 | ||
|
|
8c99b871e2 | ||
|
|
41b85d50a8 | ||
|
|
759af058df | ||
|
|
48636363d1 | ||
|
|
4ea114a4d6 | ||
|
|
ad2349e570 | ||
|
|
ffb312d34d | ||
|
|
97a1c86433 | ||
|
|
c2ebb0416e | ||
|
|
e1548062c7 | ||
|
|
9cd73aa49d | ||
|
|
a880379480 | ||
|
|
71c2465d7b | ||
|
|
0272307f28 | ||
|
|
2ea358703e | ||
|
|
c458f388bb | ||
|
|
1b03b8a531 | ||
|
|
e2f7d82d62 | ||
|
|
c8e6ed8df9 | ||
|
|
a67f691a00 | ||
|
|
dfccbcf1a9 | ||
|
|
38ecb088ec | ||
|
|
8236b18d0d | ||
|
|
1e05b0f072 | ||
|
|
87e98f038a | ||
|
|
f7e2082983 | ||
|
|
f719111abb | ||
|
|
3bac0874f1 | ||
|
|
457b7a9fb7 | ||
|
|
4023fbec29 | ||
|
|
a274a0cdbb | ||
|
|
717a514451 | ||
|
|
786d7765f5 | ||
|
|
a733c13866 | ||
|
|
88c1930845 | ||
|
|
c3f5c44461 | ||
|
|
2cfa1f8d03 | ||
|
|
5f7de8e595 | ||
|
|
cdce519742 | ||
|
|
ccd9ca5106 | ||
|
|
9031742acc | ||
|
|
9559d0b3bc | ||
|
|
0e6550ec45 | ||
|
|
20fa4d2317 | ||
|
|
e12e9740c9 | ||
|
|
cbc8ef13cc | ||
|
|
652af93f5c | ||
|
|
b4a96a8b01 | ||
|
|
bc81d45b2b | ||
|
|
429791dab0 | ||
|
|
fe833eb2b2 | ||
|
|
be5f352296 | ||
|
|
47415322ea | ||
|
|
d20983d355 | ||
|
|
f0b24ba25d | ||
|
|
f7a34c8fee | ||
|
|
4e5e614eb4 | ||
|
|
07f7855a26 | ||
|
|
57f95102e2 | ||
|
|
3f8d927438 | ||
|
|
d91c0bb894 | ||
|
|
a6176720c7 | ||
|
|
a6903df58f | ||
|
|
19b149518e | ||
|
|
c66a99a60f | ||
|
|
4a7c6035b6 | ||
|
|
207444fdea | ||
|
|
60eea0e46b | ||
|
|
5e50eb9eb8 | ||
|
|
af65683123 | ||
|
|
2c673f5377 | ||
|
|
192b0e6301 | ||
|
|
71edb91c4f | ||
|
|
f9b935f5f5 | ||
|
|
23833e92cb | ||
|
|
241df7f05e | ||
|
|
130a1f2c54 | ||
|
|
c63981e31c | ||
|
|
687f0c6f63 | ||
|
|
f59a92ca15 | ||
|
|
01fa85c7a3 | ||
|
|
3434bc7f2b | ||
|
|
9b1aacb1da | ||
|
|
8951923a11 | ||
|
|
e200d4cc74 | ||
|
|
e05619f8c8 | ||
|
|
5ea43ab4e4 | ||
|
|
ba44c58a80 | ||
|
|
490025a981 | ||
|
|
2966373a86 | ||
|
|
8bdb8c45f7 | ||
|
|
9827de0b58 | ||
|
|
23f01fde41 | ||
|
|
f680318e44 | ||
|
|
cd2d1eb1fa | ||
|
|
3ba0aedcba | ||
|
|
40b6884424 | ||
|
|
a2638c6057 | ||
|
|
6bd5142a37 | ||
|
|
bc1d653857 | ||
|
|
6c215e07a6 | ||
|
|
272af9d24c | ||
|
|
cce000ab2b | ||
|
|
4a99d6a7bb | ||
|
|
4458656be5 | ||
|
|
daca46371c | ||
|
|
8ee2ac10e7 | ||
|
|
1ebaa5aa00 | ||
|
|
cb43548305 | ||
|
|
360084af7c | ||
|
|
0af5184c70 | ||
|
|
44c3e2c46a | ||
|
|
a96dc19215 | ||
|
|
aa881a8d00 | ||
|
|
08413f198b | ||
|
|
75ab1d2ed5 | ||
|
|
2d6ce654f4 | ||
|
|
9ce531a06f | ||
|
|
1a9dc5c980 | ||
|
|
589f86ef1b | ||
|
|
1b61ec72e2 | ||
|
|
1f22f84360 | ||
|
|
2c6db975f9 | ||
|
|
b7099aa0d3 | ||
|
|
36b0869bc2 | ||
|
|
28167e41ff | ||
|
|
19923cbf1e | ||
|
|
1210e99ec1 | ||
|
|
fc894bc1ae | ||
|
|
9491ac7172 | ||
|
|
32dc2264d8 | ||
|
|
45ba3b26da | ||
|
|
6d3309c42d | ||
|
|
530b85136d | ||
|
|
cb9ed9ad3f | ||
|
|
524e220914 | ||
|
|
e3e6ef27a2 | ||
|
|
55f115f9fe | ||
|
|
bdaf2dbbd4 | ||
|
|
e7eea067b2 | ||
|
|
a56dbeab35 | ||
|
|
570b82d1e7 | ||
|
|
b5189c0c07 | ||
|
|
8a0a5d8ba0 | ||
|
|
d3e5f4e15d | ||
|
|
5a592b7ee0 | ||
|
|
43787eca74 | ||
|
|
595ed9fb46 | ||
|
|
5c4ab26d25 | ||
|
|
2030f24a47 | ||
|
|
6eda322496 | ||
|
|
318f8b2f08 | ||
|
|
dfab900562 | ||
|
|
d2ee5058f8 | ||
|
|
e358183165 | ||
|
|
26579538f5 |
@@ -2,11 +2,44 @@ module.exports = {
|
||||
root: true,
|
||||
extends: ['@nuxt/eslint-config'],
|
||||
rules: {
|
||||
// General
|
||||
semi: ['error', 'never'],
|
||||
quotes: ['error', 'single'],
|
||||
'comma-dangle': ['error', 'never'],
|
||||
'comma-spacing': ['error', { before: false, after: true }],
|
||||
'keyword-spacing': ['error', { before: true, after: true }],
|
||||
'space-before-function-paren': ['error', 'always'],
|
||||
'object-curly-spacing': ['error', 'always'],
|
||||
'arrow-spacing': ['error', { before: true, after: true }],
|
||||
'key-spacing': ['error', { beforeColon: false, afterColon: true, mode: 'strict' }],
|
||||
'space-before-blocks': ['error', 'always'],
|
||||
'space-infix-ops': ['error', { int32Hint: false }],
|
||||
'no-multi-spaces': ['error', { ignoreEOLComments: true }],
|
||||
|
||||
// Typescript
|
||||
'@typescript-eslint/type-annotation-spacing': 'error',
|
||||
|
||||
// Vuejs
|
||||
'vue/multi-word-component-names': 0,
|
||||
'vue/max-attributes-per-line': ['error', {
|
||||
singleline: {
|
||||
max: 5
|
||||
'vue/html-indent': ['error', 2],
|
||||
'vue/comma-spacing': ['error', { before: false, after: true }],
|
||||
'vue/script-indent': ['error', 2, { baseIndent: 0 }],
|
||||
'vue/keyword-spacing': ['error', { before: true, after: true }],
|
||||
'vue/object-curly-spacing': ['error', 'always'],
|
||||
'vue/key-spacing': ['error', { beforeColon: false, afterColon: true, mode: 'strict' }],
|
||||
'vue/arrow-spacing': ['error', { before: true, after: true }],
|
||||
'vue/array-bracket-spacing': ['error', 'never'],
|
||||
'vue/block-spacing': ['error', 'always'],
|
||||
'vue/brace-style': ['error', 'stroustrup', { allowSingleLine: true }],
|
||||
'vue/space-infix-ops': ['error', { int32Hint: false }],
|
||||
'vue/max-attributes-per-line': [
|
||||
'error',
|
||||
{
|
||||
singleline: {
|
||||
max: 5
|
||||
}
|
||||
}
|
||||
}]
|
||||
],
|
||||
'vue/padding-line-between-blocks': ['error', 'always']
|
||||
}
|
||||
}
|
||||
|
||||
31
.github/ISSUE_TEMPLATE/bug-report.md
vendored
31
.github/ISSUE_TEMPLATE/bug-report.md
vendored
@@ -1,31 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Report a bug report to help us improve the module.
|
||||
title: ''
|
||||
labels: 'bug'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- **IMPORTANT!**
|
||||
Before reporting a bug, please make sure that you have read through our documentation and you think your problem is indeed an issue related to our module. -->
|
||||
|
||||
### Version
|
||||
@nuxthq/ui: <!-- ex: v2.0.0 -->
|
||||
nuxt: <!-- ex: v3.5.0 -->
|
||||
|
||||
### Reproduction Link
|
||||
|
||||
<!--
|
||||
A minimal test case based on one of:
|
||||
- a GitHub repository that can reproduce the bug
|
||||
- https://stackblitz.com/edit/nuxtlabs-ui
|
||||
-->
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
|
||||
### What is Expected?
|
||||
|
||||
|
||||
### What is actually happening?
|
||||
60
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
60
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
name: "🐛 Bug report"
|
||||
description: Report a bug to help us improve the module.
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before reporting a bug, please make sure that you have read through our [documentation](https://ui.nuxt.com) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
|
||||
- type: textarea
|
||||
id: env
|
||||
attributes:
|
||||
label: Environment
|
||||
description: You can use `npx nuxi info` to fill this section
|
||||
placeholder: |
|
||||
- Operating System: `Darwin`
|
||||
- Node Version: `v18.16.0`
|
||||
- Nuxt Version: `3.7.3`
|
||||
- CLI Version: `3.8.4`
|
||||
- Nitro Version: `2.6.3`
|
||||
- Package Manager: `pnpm@8.7.4`
|
||||
- Builder: `-`
|
||||
- User Config: `-`
|
||||
- Runtime Modules: `-`
|
||||
- Build Modules: `-`
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
placeholder: v2.8.0
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Reproduction
|
||||
description: Please provide a reproduction link using this template https://stackblitz.com/edit/nuxt-ui. A minimal [reproduction is required](https://antfu.me/posts/why-reproductions-are-required) unless you are absolutely sure that the issue is obvious and the provided information is enough to understand the problem. If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a "needs reproduction" label. If no reproduction is provided we might close it.
|
||||
placeholder: https://stackblitz.com/edit/nuxt-ui
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us in the description.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: additonal
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: If applicable, add any other context or screenshots here.
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Logs
|
||||
description: |
|
||||
Optional if provided reproduction. Please try not to insert an image but copy paste the log text.
|
||||
render: shell-script
|
||||
9
.github/ISSUE_TEMPLATE/config.yml
vendored
9
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,5 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Nuxt Community Discord
|
||||
url: https://discord.nuxtjs.org/
|
||||
about: Consider asking questions about the module here.
|
||||
- name: 📖 Documentation
|
||||
url: https://ui.nuxt.com
|
||||
about: Check the documentation for guides and examples.
|
||||
- name: 📚 Discord
|
||||
url: https://discord.com/channels/473401852243869706/1153996761426300948
|
||||
about: Consider asking questions in the `#ui` channel.
|
||||
|
||||
20
.github/ISSUE_TEMPLATE/feature-request.md
vendored
20
.github/ISSUE_TEMPLATE/feature-request.md
vendored
@@ -1,20 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea or enhancement for the module.
|
||||
title: ''
|
||||
labels: 'enhancement'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### Is your feature request related to a problem? Please describe.
|
||||
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
|
||||
|
||||
### Describe the solution you'd like
|
||||
<!-- A clear and concise description of what you want to happen. -->
|
||||
|
||||
### Describe alternatives you've considered
|
||||
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
|
||||
|
||||
### Additional context
|
||||
<!-- Add any other context or screenshots about the feature request here. -->
|
||||
20
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
name: "🚀 Feature request"
|
||||
description: Suggest an idea or enhancement for the module.
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before requesting a feature, please make sure that you have read through our [documentation](https://ui.nuxt.com) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: A clear and concise description of what you think would be an helpful addition to the module, including the possible use cases and alternatives you have considered. If you have a working prototype or module that implements it, please include a link.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: additonal
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: If applicable, add any other context or screenshots here.
|
||||
16
.github/ISSUE_TEMPLATE/question.md
vendored
16
.github/ISSUE_TEMPLATE/question.md
vendored
@@ -1,16 +0,0 @@
|
||||
---
|
||||
name: Question
|
||||
about: Ask a question about the module.
|
||||
title: ''
|
||||
labels: 'question'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- **IMPORTANT!**
|
||||
Please make sure to look for an answer to your question in our documentation and the documentation before asking a question here.
|
||||
|
||||
If you have a general question regarding the module use Discord `modules` channel. Thanks!
|
||||
|
||||
Nuxt Discord: https://discord.nuxtjs.org/
|
||||
-->
|
||||
14
.github/ISSUE_TEMPLATE/question.yml
vendored
Normal file
14
.github/ISSUE_TEMPLATE/question.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
name: "💬 Question"
|
||||
description: Ask a question about the module.
|
||||
labels: ["question"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before asking a question, please make sure that you have read through our [documentation](https://ui.nuxt.com) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
validations:
|
||||
required: true
|
||||
33
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
33
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<!---
|
||||
☝️ PR title should follow conventional commits (https://conventionalcommits.org)
|
||||
-->
|
||||
|
||||
### 🔗 Linked issue
|
||||
|
||||
<!-- Please ensure there is an open issue and mention its number as #123 -->
|
||||
|
||||
### ❓ Type of change
|
||||
|
||||
<!-- What types of changes does your code introduce? Put an `x` in all the boxes that apply. -->
|
||||
|
||||
- [ ] 📖 Documentation (updates to the documentation or readme)
|
||||
- [ ] 🐞 Bug fix (a non-breaking change that fixes an issue)
|
||||
- [ ] 👌 Enhancement (improving an existing functionality)
|
||||
- [ ] ✨ New feature (a non-breaking change that adds functionality)
|
||||
- [ ] 🧹 Chore (updates to the build process or auxiliary tools and libraries)
|
||||
- [ ] ⚠️ Breaking change (fix or feature that would cause existing functionality to change)
|
||||
|
||||
### 📚 Description
|
||||
|
||||
<!-- Describe your changes in detail -->
|
||||
<!-- Why is this change required? What problem does it solve? -->
|
||||
<!-- If it resolves an open issue, please link to the issue here. For example "Resolves #1337" -->
|
||||
|
||||
### 📝 Checklist
|
||||
|
||||
<!-- Put an `x` in all the boxes that apply. -->
|
||||
<!-- If your change requires a documentation PR, please link it appropriately -->
|
||||
<!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
||||
|
||||
- [ ] I have linked an issue or discussion.
|
||||
- [ ] I have updated the documentation accordingly.
|
||||
42
.github/workflows/ci-dev.yml
vendored
42
.github/workflows/ci-dev.yml
vendored
@@ -22,30 +22,44 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
|
||||
- name: Checkout
|
||||
- name: checkout
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache
|
||||
uses: actions/cache@v3
|
||||
- uses: pnpm/action-setup@v2
|
||||
name: Install pnpm
|
||||
id: pnpm-install
|
||||
with:
|
||||
path: node_modules
|
||||
key: ${{ matrix.os }}-node-v${{ matrix.node }}-deps-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }}
|
||||
version: 8
|
||||
run_install: false
|
||||
|
||||
- name: Dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: yarn
|
||||
- name: Get pnpm store directory
|
||||
id: pnpm-cache
|
||||
shell: bash
|
||||
run: |
|
||||
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/cache@v3
|
||||
name: Setup pnpm cache
|
||||
with:
|
||||
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Prepare
|
||||
run: pnpm run dev:prepare
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint
|
||||
run: pnpm run lint
|
||||
|
||||
- name: Typecheck
|
||||
run: yarn typecheck
|
||||
run: pnpm run typecheck
|
||||
|
||||
- name: Build
|
||||
run: yarn build
|
||||
run: pnpm run build
|
||||
|
||||
- name: Release Edge
|
||||
if: github.event_name == 'push'
|
||||
|
||||
42
.github/workflows/ci.yml
vendored
42
.github/workflows/ci.yml
vendored
@@ -22,30 +22,44 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
|
||||
- name: Checkout
|
||||
- name: checkout
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache
|
||||
uses: actions/cache@v3
|
||||
- uses: pnpm/action-setup@v2
|
||||
name: Install pnpm
|
||||
id: pnpm-install
|
||||
with:
|
||||
path: node_modules
|
||||
key: ${{ matrix.os }}-node-v${{ matrix.node }}-deps-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }}
|
||||
version: 8
|
||||
run_install: false
|
||||
|
||||
- name: Dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: yarn
|
||||
- name: Get pnpm store directory
|
||||
id: pnpm-cache
|
||||
shell: bash
|
||||
run: |
|
||||
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/cache@v3
|
||||
name: Setup pnpm cache
|
||||
with:
|
||||
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Prepare
|
||||
run: pnpm run dev:prepare
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint
|
||||
run: pnpm run lint
|
||||
|
||||
- name: Typecheck
|
||||
run: yarn typecheck
|
||||
run: pnpm run typecheck
|
||||
|
||||
- name: Build
|
||||
run: yarn build
|
||||
run: pnpm run build
|
||||
|
||||
- name: Version Check
|
||||
id: check
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -6,3 +6,6 @@ nuxt.d.ts
|
||||
dist
|
||||
.DS_Store
|
||||
.history
|
||||
.vercel
|
||||
.idea
|
||||
.env
|
||||
|
||||
3
.nuxtrc
Normal file
3
.nuxtrc
Normal file
@@ -0,0 +1,3 @@
|
||||
imports.autoImport=false
|
||||
typescript.includeWorkspace=true
|
||||
typescript.strict=false
|
||||
25
.release-it.json
Normal file
25
.release-it.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"git": {
|
||||
"commitMessage": "chore(release): ${version}"
|
||||
},
|
||||
"npm": {
|
||||
"publish": false
|
||||
},
|
||||
"github": {
|
||||
"release": true,
|
||||
"web": true
|
||||
},
|
||||
"hooks": {
|
||||
"before:init": ["pnpm lint"]
|
||||
},
|
||||
"plugins": {
|
||||
"@release-it/conventional-changelog": {
|
||||
"preset": {
|
||||
"name": "conventionalcommits"
|
||||
},
|
||||
"infile": "CHANGELOG.md",
|
||||
"header": "# Changelog",
|
||||
"ignoreRecommendedBump": true
|
||||
}
|
||||
}
|
||||
}
|
||||
315
CHANGELOG.md
315
CHANGELOG.md
@@ -1,6 +1,317 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
## [2.9.0](https://github.com/nuxt/ui/compare/v2.8.1...v2.9.0) (2023-10-02)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **module:** use `tailwind-merge` for `app.config` & move config to components & type props (#692)
|
||||
|
||||
### Features
|
||||
|
||||
* **FormGroup:** add slots ([#714](https://github.com/nuxt/ui/issues/714)) ([2fc9385](https://github.com/nuxt/ui/commit/2fc938575d2e409ba9df9fb2ddb8d51d021a1756))
|
||||
* **Link:** add `active` prop to override default behaviour ([#732](https://github.com/nuxt/ui/issues/732)) ([8257a11](https://github.com/nuxt/ui/commit/8257a11dcba9c34053f8061ed1383894d06b2a6c))
|
||||
* **Link:** add `as` prop ([#535](https://github.com/nuxt/ui/issues/535)) ([e404912](https://github.com/nuxt/ui/commit/e40491208ac1096e505803072df0d9e2e771008e))
|
||||
* **module:** use `tailwind-merge` for `app.config` & move config to components & type props ([#692](https://github.com/nuxt/ui/issues/692)) ([34d2f57](https://github.com/nuxt/ui/commit/34d2f57801d08d26262fdff4398ec3d3329b4bb0))
|
||||
* remove `lodash-es` ([#648](https://github.com/nuxt/ui/issues/648)) ([d6476d1](https://github.com/nuxt/ui/commit/d6476d17f9b17317a7160271dacdb854f30237ae))
|
||||
* **Table:** add ability to custom style for `td` and `tr` ([#741](https://github.com/nuxt/ui/issues/741)) ([874447c](https://github.com/nuxt/ui/commit/874447cb41a77868513459eee5d3301fe8b8e9a1))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Accordion:** close other items in circular order ([#735](https://github.com/nuxt/ui/issues/735)) ([6887f73](https://github.com/nuxt/ui/commit/6887f732ee8e14625459a0576460523845cb0a6d))
|
||||
* **FormGroup:** prevent input click from propagating to label ([#651](https://github.com/nuxt/ui/issues/651)) ([4c58330](https://github.com/nuxt/ui/commit/4c5833083f0840add52f3c67efc42b8db5687d37))
|
||||
* **FormGroup:** use explicit label instead of implicit label ([#638](https://github.com/nuxt/ui/issues/638)) ([681f0e5](https://github.com/nuxt/ui/commit/681f0e5684feaad0c711130404751f2fd65ddbe4))
|
||||
* **module:** move `@headlessui/tailwindcss` to plugins on module install ([3e647e4](https://github.com/nuxt/ui/commit/3e647e4af154dad7fa186f062ce984e4d8d0e202))
|
||||
* **module:** retain props reactivity through `useUI` ([#745](https://github.com/nuxt/ui/issues/745)) ([109ec52](https://github.com/nuxt/ui/commit/109ec52d50b0b32b0f0b24ece5b92cd7bbce29da))
|
||||
* **Pagination:** handle `max > 5` and `max` equal total pages ([#728](https://github.com/nuxt/ui/issues/728)) ([a071e4b](https://github.com/nuxt/ui/commit/a071e4b8755f5dbbdfd05985c8fcb65c3cdab3ec))
|
||||
* **Range:** fix track pseudo-elements for mozilla ([#636](https://github.com/nuxt/ui/issues/636)) ([8955595](https://github.com/nuxt/ui/commit/8955595dc6904d0090ad7f82ed8b376a15e51f94))
|
||||
* **SelectMenu:** handle numbers ([0544a01](https://github.com/nuxt/ui/commit/0544a01c5b7ae534a595e6c91d2884a601ae3185)), closes [#574](https://github.com/nuxt/ui/issues/574)
|
||||
* **Table:** add missing classes in `app.config.ts` ([a603ea5](https://github.com/nuxt/ui/commit/a603ea56c165e9ad01482d092460da3991f3e41d)), closes [#655](https://github.com/nuxt/ui/issues/655)
|
||||
* **Table:** select all rows without select listener ([#652](https://github.com/nuxt/ui/issues/652)) ([83d609d](https://github.com/nuxt/ui/commit/83d609d53067b2639a55a0e367a5e7adbd8a22fc))
|
||||
* **Tabs:** add visible focus indicator on active tabs ([#690](https://github.com/nuxt/ui/issues/690)) ([be734fc](https://github.com/nuxt/ui/commit/be734fc026b75bc8c921e9401ba6e97f65356cec))
|
||||
* **Tabs:** allow custom keys in `TabItem` ([#671](https://github.com/nuxt/ui/issues/671)) ([15e418e](https://github.com/nuxt/ui/commit/15e418e6c6f981afd2c0e8f27dedb303b8cbad70))
|
||||
* **Tabs:** prevent focus of `TabPanel` with `tabindex="-1"` ([cbb2f28](https://github.com/nuxt/ui/commit/cbb2f28c3fd96e45c7af20675b5b67576ddc0d63))
|
||||
|
||||
## [2.8.1](https://github.com/nuxt/ui/compare/v2.8.0...v2.8.1) (2023-09-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Form:** fix `getValibotError` to avoid importing `safeParseAsync` ([#640](https://github.com/nuxt/ui/issues/640)) ([e8daf7f](https://github.com/nuxt/ui/commit/e8daf7f81018c01c28c2c38aed6ee57ef887f823))
|
||||
* **Form:** fix valibot imports ([#617](https://github.com/nuxt/ui/issues/617)) ([1a7eb27](https://github.com/nuxt/ui/commit/1a7eb27cad9f3357c4dcde188530cdb0001d3ae6))
|
||||
* **Pagination:** page numbers not clickable ([#624](https://github.com/nuxt/ui/issues/624)) ([c1e0654](https://github.com/nuxt/ui/commit/c1e0654417ad39df8be3f2172ab4e0af6dacb631))
|
||||
|
||||
## [2.8.0](https://github.com/nuxt/ui/compare/v2.7.0...v2.8.0) (2023-09-07)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **module:** use `tailwind-merge` for class merging (#509)
|
||||
|
||||
### Features
|
||||
|
||||
* **Avatar:** add `icon` prop as fallback ([df3b202](https://github.com/nuxt/ui/commit/df3b2028ed2a68178c41e136985500bc0e6f4608))
|
||||
* **Avatar:** handle `icon` default from `app.config.ts` ([55daed0](https://github.com/nuxt/ui/commit/55daed0e5a220cc5f2abf1bf4a27bc86773b7939))
|
||||
* **ButtonGroup:** add `orientation` prop ([#603](https://github.com/nuxt/ui/issues/603)) ([b3bc6e2](https://github.com/nuxt/ui/commit/b3bc6e2e9e9446ee3dab7ae02f939a9c01c4218b))
|
||||
* **Form:** add valibot supprt ([#615](https://github.com/nuxt/ui/issues/615)) ([ab5153a](https://github.com/nuxt/ui/commit/ab5153ac19703c11b107825208e33d04e01a9be2))
|
||||
* **Form:** improve form control and input validation trigger ([#487](https://github.com/nuxt/ui/issues/487)) ([6d7973f](https://github.com/nuxt/ui/commit/6d7973f6e1cc3552df45ac7ce2e2107d18061abf))
|
||||
* **Modal:** add `fullscreen` prop ([#523](https://github.com/nuxt/ui/issues/523)) ([7e2bebd](https://github.com/nuxt/ui/commit/7e2bebd3ef88ea65a0dd03686e6a9d08b0d1edd7))
|
||||
* **module:** add `DEFAULT` shade to `primary` color ([#493](https://github.com/nuxt/ui/issues/493)) ([c6056ed](https://github.com/nuxt/ui/commit/c6056ed13323f854a9ab4a07303b9e64cd0f563a))
|
||||
* **module:** use `tailwind-merge` for class merging ([#509](https://github.com/nuxt/ui/issues/509)) ([8880bdc](https://github.com/nuxt/ui/commit/8880bdc45640103aea3e84a5410567bd87607738))
|
||||
* **Table:** support nested keys in columns ([#503](https://github.com/nuxt/ui/issues/503)) ([858886a](https://github.com/nuxt/ui/commit/858886a85288370bfc7c0991e96929811f20f561))
|
||||
* **Tabs:** control selected index ([#490](https://github.com/nuxt/ui/issues/490)) ([aaf09ad](https://github.com/nuxt/ui/commit/aaf09ad555f713738958b191e5649dc80bd3ba96))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Alert:** fix wrong type of `actions` ([#507](https://github.com/nuxt/ui/issues/507)) ([b243e8c](https://github.com/nuxt/ui/commit/b243e8c94649a50358a5961d45b5f48c6c670383))
|
||||
* **AvatarGroup:** add `justify-end` to wrapper to prevent right align ([e578b0d](https://github.com/nuxt/ui/commit/e578b0dd9e924cacf22ed541e4da54e558654254))
|
||||
* **AvatarGroup:** pass default `size` to max avatar ([e49c673](https://github.com/nuxt/ui/commit/e49c67357364483d742bf9ccc7a94dc67edafe96))
|
||||
* **AvatarGroup:** use `ui.wrapper` as `inheritAttrs` is not false ([eb609b1](https://github.com/nuxt/ui/commit/eb609b13e47da3e171351884f7fe6e7dcaa5ed77))
|
||||
* **Badge:** allow `label` as number ([7c157ce](https://github.com/nuxt/ui/commit/7c157ce886fd6f35886255a5a2ee468c2b2089c3))
|
||||
* **Button:** add missing prop types ([#508](https://github.com/nuxt/ui/issues/508)) ([a8a1c15](https://github.com/nuxt/ui/commit/a8a1c150a00212eeb8cde32ff06ee3b6c45fbedd))
|
||||
* **ButtonGroup:** switch back to `ui` prop ([d4e3ab6](https://github.com/nuxt/ui/commit/d4e3ab606b19337c33e541ae399466ba8551e898))
|
||||
* **Form:** fix wrong type of validate ([#496](https://github.com/nuxt/ui/issues/496)) ([3d6839d](https://github.com/nuxt/ui/commit/3d6839da97a09747b0090a3d5aa1ebe3d28b85fd))
|
||||
* **FormGroup:** `size` were invalid since default has been removed ([7008df0](https://github.com/nuxt/ui/commit/7008df098887965f2ed3e43d2ccb64b3d32524b9))
|
||||
* **FormGroup:** add missing `ref` import from vue ([39042b3](https://github.com/nuxt/ui/commit/39042b3de17efc26ee86b003a05e42e7a41f50bf))
|
||||
* **Form:** use safeParseAsync for zod ([#497](https://github.com/nuxt/ui/issues/497)) ([8b19b18](https://github.com/nuxt/ui/commit/8b19b1880e744d81481b4e1f5b4e88d7f48f7bdb))
|
||||
* **module:** missing `useHead` import ([0f252d0](https://github.com/nuxt/ui/commit/0f252d0caf550ba7ea4cfb24bed5f95a42e78970))
|
||||
* **module:** missing `useNuxtApp` import ([888effe](https://github.com/nuxt/ui/commit/888effea0a66f5dd88cdd47d5d65da02bdec6ad6))
|
||||
* **Popover:** handle `hover` mode with padding like dropdown ([dc951ff](https://github.com/nuxt/ui/commit/dc951ff69dd15dc942e5c61edb6bc0a5a516c89b))
|
||||
* **Radio:** put back `id` for label selection ([9b3a22e](https://github.com/nuxt/ui/commit/9b3a22ea140e5a70c288c7b6241671e9d3542572))
|
||||
* **SelectMenu:** invalid `gap` values ([998314e](https://github.com/nuxt/ui/commit/998314e1cbafced2844b06eac5f34fa3ddb8d1e5))
|
||||
* **Table:** empty state is displayed if null ([#517](https://github.com/nuxt/ui/issues/517)) ([44ba758](https://github.com/nuxt/ui/commit/44ba758c0d50f2214554a477d661a914df2025ba))
|
||||
* **Table:** missing component imports ([#608](https://github.com/nuxt/ui/issues/608)) ([d936316](https://github.com/nuxt/ui/commit/d9363168b282acc332a473340b77ee8f702e0e3f))
|
||||
* **Tabs:** recompute marker position when `v-model` changes ([#524](https://github.com/nuxt/ui/issues/524)) ([fdce429](https://github.com/nuxt/ui/commit/fdce429b3ef1d203b2438299e46e57a010355fb0))
|
||||
* **Tooltip:** hide on touch devices ([#580](https://github.com/nuxt/ui/issues/580)) ([f1ed007](https://github.com/nuxt/ui/commit/f1ed0076e5ada78ba6150745ce9d8459cc731b4e))
|
||||
* use head instance from plugin ([791804b](https://github.com/nuxt/ui/commit/791804b2fba6493f07dc75b09f8b8ac95f71644d))
|
||||
|
||||
## [2.7.0](https://github.com/nuxtlabs/ui/compare/v2.6.0...v2.7.0) (2023-08-01)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **Link:** rename from `LinkCustom` and add `exact-query` / `exact-hash` props
|
||||
* **Badge:** add colors and variants (solid has changed)
|
||||
* **SelectMenu:** invert `ui` and `ui-select` props (#432)
|
||||
|
||||
### Features
|
||||
|
||||
* **Alert:** new component ([#449](https://github.com/nuxtlabs/ui/issues/449)) ([ab2abae](https://github.com/nuxtlabs/ui/commit/ab2abae48a03200d273b4f0cb3ce300fffcee64b))
|
||||
* **Badge:** add colors and variants (solid has changed) ([05503e5](https://github.com/nuxtlabs/ui/commit/05503e564c3e8dfaee2e27e25b3409edb4c555a1))
|
||||
* **Badge:** rename `outline` to `subtle` + add `soft` variants ([5bd5dc2](https://github.com/nuxtlabs/ui/commit/5bd5dc2bcaeb59d4b0a1aea802bd3e2b2160ad53))
|
||||
* **CommandPalette:** bind active and selected to scoped slot ([#441](https://github.com/nuxtlabs/ui/issues/441)) ([b0440f8](https://github.com/nuxtlabs/ui/commit/b0440f81ce2960704ed7386ec069e52ecd7bb787))
|
||||
* **FormGroup:** add `size` prop and theme options ([#391](https://github.com/nuxtlabs/ui/issues/391)) ([d2a8a07](https://github.com/nuxtlabs/ui/commit/d2a8a07a21a4943144bd990fdbfe645ea308ae7b))
|
||||
* **Form:** new component ([#439](https://github.com/nuxtlabs/ui/issues/439)) ([a3aba1a](https://github.com/nuxtlabs/ui/commit/a3aba1abadd569b69f15697bcc5908b49e0a7f8a))
|
||||
* **Link:** rename from `LinkCustom` and add `exact-query` / `exact-hash` props ([cefe5a7](https://github.com/nuxtlabs/ui/commit/cefe5a76e0a4820f648d23734228540e3010b233))
|
||||
* **Notification:** support html with `title` and `description` slots ([#431](https://github.com/nuxtlabs/ui/issues/431)) ([df455db](https://github.com/nuxtlabs/ui/commit/df455db3caeb689ac1f24f224606183d4f5135ea))
|
||||
* **Range:** increase narrowed surface ([#459](https://github.com/nuxtlabs/ui/issues/459)) ([3b183ac](https://github.com/nuxtlabs/ui/commit/3b183ac9cde86cf3ab6fbdc5dd124d66deec865d))
|
||||
* **SelectMenu:** add `value-attribute` prop ([#429](https://github.com/nuxtlabs/ui/issues/429)) ([959c968](https://github.com/nuxtlabs/ui/commit/959c968420945fc0a143edb909c1289123fd62cb))
|
||||
* **Tabs:** new component ([#450](https://github.com/nuxtlabs/ui/issues/450)) ([8298b62](https://github.com/nuxtlabs/ui/commit/8298b62f216712fc156ef1a114d6cff3a573efdb))
|
||||
* **ui:** apply primary bg on `::selection` ([09d0ea2](https://github.com/nuxtlabs/ui/commit/09d0ea27ab36b0655106f0cf000f2c13c63b92bd))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **FormGroup:** `required` star display ([3dd0492](https://github.com/nuxtlabs/ui/commit/3dd0492f91422c8248691ac9d3f5de6d37278721))
|
||||
* **FormGroup:** err when no prop defined ([93aebe6](https://github.com/nuxtlabs/ui/commit/93aebe6fc614bc2a78109f632297c3843f7a785a))
|
||||
* **FormGroup:** missing imports ([#470](https://github.com/nuxtlabs/ui/issues/470)) ([dc1979c](https://github.com/nuxtlabs/ui/commit/dc1979cae1478cf864aab5ea573cc87d070185ce))
|
||||
* **FormGroup:** set `size` default to null ([c59595f](https://github.com/nuxtlabs/ui/commit/c59595f2c6cf414bf04bb5995ba029a59ef8035b))
|
||||
* **Form:** return state on validate ([#472](https://github.com/nuxtlabs/ui/issues/472)) ([248b0a6](https://github.com/nuxtlabs/ui/commit/248b0a68c675255a586d0ff61b0561f2f47b2682))
|
||||
* **LinkCustom:** `exact` prop wasn't working ([82e152b](https://github.com/nuxtlabs/ui/commit/82e152be02ca7b8fc5d6e27ffd81ff3f0d8a8f80)), closes [#417](https://github.com/nuxtlabs/ui/issues/417)
|
||||
* **LinkCustom:** improve prop binding and prevent error with externals ([914d156](https://github.com/nuxtlabs/ui/commit/914d156103d5ebca6b14ea705ed329508bf66d74))
|
||||
* **Link:** handle `disabled` prop ([396aae7](https://github.com/nuxtlabs/ui/commit/396aae75638da88a736179f71324374d74a89d70)), closes [#473](https://github.com/nuxtlabs/ui/issues/473)
|
||||
* **module:** ensure `red` color is safelisted for form elements ([208acca](https://github.com/nuxtlabs/ui/commit/208acca1e9269494310ff000104b21e999b66cf8)), closes [#423](https://github.com/nuxtlabs/ui/issues/423) [#373](https://github.com/nuxtlabs/ui/issues/373)
|
||||
* **module:** omit colors defined as strings ([927b63f](https://github.com/nuxtlabs/ui/commit/927b63fa2e33cc5ee303554c0c43c9e89156b7c8))
|
||||
* **module:** safelist all colors for `toast.add` ([2cd6208](https://github.com/nuxtlabs/ui/commit/2cd620899f3e997357f6274cc7a0bfc79a8277b6)), closes [#375](https://github.com/nuxtlabs/ui/issues/375) [#440](https://github.com/nuxtlabs/ui/issues/440)
|
||||
* **module:** smart safelisting for components in snake case ([e25be11](https://github.com/nuxtlabs/ui/commit/e25be118b7fe4bfd4ec26be9aacfb0d87ee94d81)), closes [#461](https://github.com/nuxtlabs/ui/issues/461)
|
||||
* **Popover:** hover mode ([#453](https://github.com/nuxtlabs/ui/issues/453)) ([10890e6](https://github.com/nuxtlabs/ui/commit/10890e6704e9884a7e86b37d0dc72e8f9c5177e7))
|
||||
* **SelectMenu:** invert `ui` and `ui-select` props ([#432](https://github.com/nuxtlabs/ui/issues/432)) ([7cccbcf](https://github.com/nuxtlabs/ui/commit/7cccbcfef899a64d63c8d33639a2d0da155c46cb))
|
||||
* **Table:** hide data when loading state is active ([#460](https://github.com/nuxtlabs/ui/issues/460)) ([2b3dc8d](https://github.com/nuxtlabs/ui/commit/2b3dc8d065c35671434975a07af4b2182a793b58))
|
||||
|
||||
## [2.6.0](https://github.com/nuxtlabs/ui/compare/v2.5.0...v2.6.0) (2023-07-18)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **Avatar:** bind component attributes to img element (#421)
|
||||
|
||||
### Features
|
||||
|
||||
* **Accordion:** add `multiple` prop and close others by default ([#364](https://github.com/nuxtlabs/ui/issues/364)) ([b78fcf9](https://github.com/nuxtlabs/ui/commit/b78fcf91a4b592a6ca83ca4333e1d6658ec6458d))
|
||||
* **Accordion:** new component ([#301](https://github.com/nuxtlabs/ui/issues/301)) ([e50f377](https://github.com/nuxtlabs/ui/commit/e50f377b946996efd4546195e528fbed59dcb22f))
|
||||
* **Avatar:** bind component attributes to img element ([#421](https://github.com/nuxtlabs/ui/issues/421)) ([773a23f](https://github.com/nuxtlabs/ui/commit/773a23f969d2dbbbcb01582f9e127e02f0248be9))
|
||||
* **Modal:** add `prevent-close` prop ([2cc5c0d](https://github.com/nuxtlabs/ui/commit/2cc5c0d810e30b889081d1f457d725004bd0b933)), closes [#303](https://github.com/nuxtlabs/ui/issues/303)
|
||||
* **SelectMenu:** handle async search ([#426](https://github.com/nuxtlabs/ui/issues/426)) ([5f8fe85](https://github.com/nuxtlabs/ui/commit/5f8fe8559f2eb12d3916387d5acf65a391bfa0eb))
|
||||
* **Slideover:** add `prevent-close` prop ([d15e816](https://github.com/nuxtlabs/ui/commit/d15e8163e7d7eb3eb7624bb982c139581902d596))
|
||||
* **Table:** add click event for the entire row ([#353](https://github.com/nuxtlabs/ui/issues/353)) ([d292706](https://github.com/nuxtlabs/ui/commit/d2927069673840dad58d388ab982b5488642edec))
|
||||
* **Table:** allow columns `class` customization ([5dffa86](https://github.com/nuxtlabs/ui/commit/5dffa868b11760610ea0bf9f2ce37931cdac4eb9)), closes [#366](https://github.com/nuxtlabs/ui/issues/366)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Accordion:** missing `ref` import from vue ([3de6b34](https://github.com/nuxtlabs/ui/commit/3de6b349d8b043ed2524bd6418f350ebb4557adb))
|
||||
* **Accordion:** solve the shift between buttons when they are opened ([#379](https://github.com/nuxtlabs/ui/issues/379)) ([eaf0043](https://github.com/nuxtlabs/ui/commit/eaf0043da660dfb168a7d4f2312d4344598c2f86))
|
||||
* **ButtonGroup:** err when no props on buttons ([80a9738](https://github.com/nuxtlabs/ui/commit/80a97384909891a14edca4ff760d5c81b26b3307)), closes [#360](https://github.com/nuxtlabs/ui/issues/360)
|
||||
* **Button:** missing `disabled` state on some variants ([41a5238](https://github.com/nuxtlabs/ui/commit/41a523857902b1674ba7f6021938f68d66a2ddbd))
|
||||
* **Modal:** disabling `transition` prop had no effect ([db34665](https://github.com/nuxtlabs/ui/commit/db346652b829ea02b8b1f5355f7080f5e530dcb2))
|
||||
* **Range:** `disabled` thumb opacity ([c92dc98](https://github.com/nuxtlabs/ui/commit/c92dc980c984cff8e9f9c38eb9524d151523c16b))
|
||||
* **Range:** progress style ([#385](https://github.com/nuxtlabs/ui/issues/385)) ([a79c165](https://github.com/nuxtlabs/ui/commit/a79c165eeeb3e8ea76cd3abc1b8f1218d02b446b))
|
||||
* **SelectMenu:** missing `appear` on transition ([cbe2b1b](https://github.com/nuxtlabs/ui/commit/cbe2b1bfb802f8cb10dd4a0d36a8cefb215debb2)), closes [#400](https://github.com/nuxtlabs/ui/issues/400)
|
||||
* **Table:** fixed row deletion bug on deselect ([#425](https://github.com/nuxtlabs/ui/issues/425)) ([46b444a](https://github.com/nuxtlabs/ui/commit/46b444a3e0cc988c89bfde7442b42b1e82095fc9))
|
||||
|
||||
## [2.5.0](https://github.com/nuxtlabs/ui/compare/v2.4.1...v2.5.0) (2023-06-27)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **Radio/Checkbox/Toggle:** handle `color` prop for form elements (#323)
|
||||
|
||||
### Features
|
||||
|
||||
* **Avatar:** handle `chipText` ([#306](https://github.com/nuxtlabs/ui/issues/306)) ([759af05](https://github.com/nuxtlabs/ui/commit/759af058df636f55a54326b21ebb1c315c73c26b))
|
||||
* **defineShortcuts:** chained shortcuts + docs update ([#282](https://github.com/nuxtlabs/ui/issues/282)) ([a67f691](https://github.com/nuxtlabs/ui/commit/a67f691a0066e4d017f580388df31b22d1c45372))
|
||||
* **Radio/Checkbox/Toggle:** handle `color` prop for form elements ([#323](https://github.com/nuxtlabs/ui/issues/323)) ([ffb312d](https://github.com/nuxtlabs/ui/commit/ffb312d34dfc2ac7a7aabdcbdf9ddb1d04d8a66f))
|
||||
* **Range:** new component ([#290](https://github.com/nuxtlabs/ui/issues/290)) ([97a1c86](https://github.com/nuxtlabs/ui/commit/97a1c8643314d5ff950b122f46f31b206485cd50))
|
||||
* RTL support ([#320](https://github.com/nuxtlabs/ui/issues/320)) ([4ea114a](https://github.com/nuxtlabs/ui/commit/4ea114a4d6b11277674c121130f746927045ade3))
|
||||
* **Table:** pass row index to table cell ([#291](https://github.com/nuxtlabs/ui/issues/291)) ([71c2465](https://github.com/nuxtlabs/ui/commit/71c2465d7be78cfb0e274b107aceda9de5384fb7))
|
||||
* **Table:** reset sort on third click ([1ff11ac](https://github.com/nuxtlabs/ui/commit/1ff11ac1a3eff537a4ee854a049668f312f1d415)), closes [#300](https://github.com/nuxtlabs/ui/issues/300)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **components:** prefix `@headlessui/vue` components ([41b85d5](https://github.com/nuxtlabs/ui/commit/41b85d50a865cfe4aa0f06a62f5209358422eaec)), closes [#315](https://github.com/nuxtlabs/ui/issues/315)
|
||||
* **defineShortcuts:** missing `ref` import ([a880379](https://github.com/nuxtlabs/ui/commit/a8803794802c4032f703a0a0a6343a8204b19bc8))
|
||||
* **defineShortcuts:** missing `useDebounceFn` import ([9cd73aa](https://github.com/nuxtlabs/ui/commit/9cd73aa49d1dd43bac8ec71932b850bdcb375fcf))
|
||||
* **FormGroup:** prevent overriding `color` of children ([6be9290](https://github.com/nuxtlabs/ui/commit/6be9290f689c449b6a6435a3ef25e89a106e1c06)), closes [#352](https://github.com/nuxtlabs/ui/issues/352)
|
||||
* **Table:** default `sortButton` icon ([07b27a2](https://github.com/nuxtlabs/ui/commit/07b27a228d293655368825979a6ca0bc1dd6e51a))
|
||||
* **Table:** missing default sort icon when overriding `sort-button` prop ([0f3fe0d](https://github.com/nuxtlabs/ui/commit/0f3fe0d54ef8b45a046b84ceb31ae55a26e153fb))
|
||||
* **Toggle:** add `opacity-50` when disabled ([c2ebb04](https://github.com/nuxtlabs/ui/commit/c2ebb0416eb2c92b759be5a4bf0d219031889b4b))
|
||||
* **Tooltip:** add `color` in config ([1b03b8a](https://github.com/nuxtlabs/ui/commit/1b03b8a531d397871e0df4f8574d7f47ac4ec610))
|
||||
|
||||
### [2.4.1](https://github.com/nuxtlabs/ui/compare/v2.4.0...v2.4.1) (2023-06-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **forms:** precise type assertion for `onInput` event handler ([#293](https://github.com/nuxtlabs/ui/issues/293)) ([457b7a9](https://github.com/nuxtlabs/ui/commit/457b7a9fb72e6469014b6ca18e7034dd5c6f44b8))
|
||||
* **module:** let `tailwindcss` viewer enabled by default ([4023fbe](https://github.com/nuxtlabs/ui/commit/4023fbec29e5b4d40fd23e8c2ae3d0cf23addc64)), closes [#292](https://github.com/nuxtlabs/ui/issues/292)
|
||||
* **module:** safelist aliases for input ([f719111](https://github.com/nuxtlabs/ui/commit/f719111abb94c81f3932927a0154b3e1bed73a9a))
|
||||
* **module:** safelist regex when a `:` was present before color ([f7e2082](https://github.com/nuxtlabs/ui/commit/f7e2082983c2eb650e95a9040aafde4ce2c88c54))
|
||||
* **Radio/Checkbox:** remove legacy `custom` ([3bac087](https://github.com/nuxtlabs/ui/commit/3bac0874f106a8ff7436b541f9d064c1c7c27464))
|
||||
|
||||
|
||||
## [2.4.0](https://github.com/nuxtlabs/ui/compare/v2.3.0...v2.4.0) (2023-06-13)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **forms:** bind `$attrs` to elements (#279)
|
||||
* **Select:** rename `text-attribute` to `option-attribute` and defaults to `label`
|
||||
|
||||
### Features
|
||||
|
||||
* **CommandPalette:** handle `empty-state` ([#271](https://github.com/nuxtlabs/ui/issues/271)) ([652af93](https://github.com/nuxtlabs/ui/commit/652af93f5c7cd4b34044a5597f3c14441ed6d998))
|
||||
* **module:** smart safelisting ([#268](https://github.com/nuxtlabs/ui/issues/268)) ([20fa4d2](https://github.com/nuxtlabs/ui/commit/20fa4d2317fc1e14fe87fa273957b92e63668945))
|
||||
* **Pagination:** new component ([#257](https://github.com/nuxtlabs/ui/issues/257)) ([f0b24ba](https://github.com/nuxtlabs/ui/commit/f0b24ba25d52184b8683e364016ed8fb800fc96b))
|
||||
* **table:** add loading state ([#259](https://github.com/nuxtlabs/ui/issues/259)) ([4741532](https://github.com/nuxtlabs/ui/commit/47415322ea56b5388e55c404c901531e807a9f00))
|
||||
* **table:** add slot for empty state ([#260](https://github.com/nuxtlabs/ui/issues/260)) ([f7a34c8](https://github.com/nuxtlabs/ui/commit/f7a34c8feeda6a4e1e1daff87b37b375aaa0c90d))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ButtonGroup:** invalid `size` validator ([a617672](https://github.com/nuxtlabs/ui/commit/a6176720c75b26768ba91efcab50689a932931ad))
|
||||
* **ButtonGroup:** use `-space-x-px` on wrapper ([d91c0bb](https://github.com/nuxtlabs/ui/commit/d91c0bb8944224d4e8eb62f99a33a6be94e5cd92))
|
||||
* **Button:** same size when no label + uniformize form elements ([a6903df](https://github.com/nuxtlabs/ui/commit/a6903df58fb91da44e6f83cc2bd9c963827fe5dd))
|
||||
* **CommandPalette:** input focus after be5f352 ([cbc8ef1](https://github.com/nuxtlabs/ui/commit/cbc8ef13cc3253690c22c32d90ea9746970c345a))
|
||||
* **deps:** move `@tailwindcss/container-queries` to dependencies ([9559d0b](https://github.com/nuxtlabs/ui/commit/9559d0b3bc09956d7fe17ee0deeef03599d02d45))
|
||||
* **forms:** `padded` prop with `p-0` class ([207444f](https://github.com/nuxtlabs/ui/commit/207444fdea773b8ee64dd4f80b4f70b76462a9d6))
|
||||
* **forms:** bind `$attrs` to elements ([#279](https://github.com/nuxtlabs/ui/issues/279)) ([e12e974](https://github.com/nuxtlabs/ui/commit/e12e9740c97b75d3b7b70c38978e249b5e26eead))
|
||||
* **module:** deduplicate default safelist as components may share same rules ([2cfa1f8](https://github.com/nuxtlabs/ui/commit/2cfa1f8d0355d4c9cec5d4294d63e043d223cd64))
|
||||
* **module:** hardcode `gray` safelist instead of deduplicate complex logic ([a733c13](https://github.com/nuxtlabs/ui/commit/a733c13866cdb74398f3e6f022cc63223e269e19))
|
||||
* **module:** only safelist known colors ([cdce519](https://github.com/nuxtlabs/ui/commit/cdce519742b86ff29460aa50264d7bb34ad24bd0))
|
||||
* **module:** prevent safelisting dynamic `:color` variables ([ccd9ca5](https://github.com/nuxtlabs/ui/commit/ccd9ca5106d0b81aed6591097f121eb81dcc9b47))
|
||||
* **module:** transform `vue` files to detect multi-line components ([88c1930](https://github.com/nuxtlabs/ui/commit/88c1930845d26c66c2fbd32f99f52dbd23244341))
|
||||
* **module:** use `@tailwindcss/forms` class strategy ([#278](https://github.com/nuxtlabs/ui/issues/278)) ([be5f352](https://github.com/nuxtlabs/ui/commit/be5f352296cf4e0c9099cf468ed905283b31007d))
|
||||
* **Notification:** class priority for icon color ([07f7855](https://github.com/nuxtlabs/ui/commit/07f7855a263e516250f62d0730afc69753d0322c))
|
||||
* **Radio/Checkbox:** split preset as `indeterminate` is checkbox only ([429791d](https://github.com/nuxtlabs/ui/commit/429791dab0fbb84bae1e1e13e7e688708f0b5c98))
|
||||
* **SelectMenu:** input focus after `be5f352` ([717a514](https://github.com/nuxtlabs/ui/commit/717a5144511c4db013a57869ac06421accf51e38))
|
||||
* **Table:** colspan of `empty` and `loading` is wrong when selection enabled ([#284](https://github.com/nuxtlabs/ui/issues/284)) ([786d776](https://github.com/nuxtlabs/ui/commit/786d7765f5517a7e8cdd718ce93fd9fecc427ba7))
|
||||
* **Toggle:** missing `disabled` prop ([fe833eb](https://github.com/nuxtlabs/ui/commit/fe833eb2b2b4d1d32eb9e082b437a0259b6f75c6))
|
||||
|
||||
|
||||
* **Select:** rename `text-attribute` to `option-attribute` and defaults to `label` ([b4a96a8](https://github.com/nuxtlabs/ui/commit/b4a96a8b01b52751c9a9c6609ed8cf7ccf516a04))
|
||||
|
||||
## [2.3.0](https://github.com/nuxtlabs/ui/compare/v2.2.1...v2.3.0) (2023-06-05)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **Input:** move pointer class inside its own preset class
|
||||
* **SelectMenu:** remove `inline-flex` from wrapper to behave like other form elements
|
||||
* **Notification:** rename to `closeButton` and `actionButton` for consistency
|
||||
* **CommandPalette:** rename props to `emptyState` and `closeButton` for consistency
|
||||
* **Toggle:** rename icons to `onIcon` / `offIcon` for consistency
|
||||
|
||||
### Features
|
||||
|
||||
* add `Table` component ([#237](https://github.com/nuxtlabs/ui/issues/237)) ([cce000a](https://github.com/nuxtlabs/ui/commit/cce000ab2b2af1079216e0e79769703fc4d9933e))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Avatar:** placeholder font size ([71edb91](https://github.com/nuxtlabs/ui/commit/71edb91c4ff17a258d6229ed6c6fa6a4b54bdd53))
|
||||
* **Badge:** remove `console.log` in validator ([f9b935f](https://github.com/nuxtlabs/ui/commit/f9b935f5f59b872fd952a2739d305d6574bf7cf8))
|
||||
* **Button:** invalid padding when using `square` prop ([1ebaa5a](https://github.com/nuxtlabs/ui/commit/1ebaa5aa00752cd276f7c754d64ac7f85b14dc26))
|
||||
* **CommandPalette:** override of `closeButton` and `emptyState` props ([2c673f5](https://github.com/nuxtlabs/ui/commit/2c673f5377dbbcdefa6b57eddba2c19d065d5f1f))
|
||||
* **defineShortcuts:** err with input autocomplete that triggers `keydown` ([01fa85c](https://github.com/nuxtlabs/ui/commit/01fa85c7a3e476d4f710ed3a36c1e815fc986a94))
|
||||
* **SelectMenu:** disable on loading ([8951923](https://github.com/nuxtlabs/ui/commit/8951923a11d533ebf53dbec5f852800555af253c))
|
||||
* **Table:** add missing `text-left` in `th.base` ([6bd5142](https://github.com/nuxtlabs/ui/commit/6bd5142a377694599952e0f9b53fde0d0132b61b))
|
||||
* **Table:** missing `ref` import from `vue` ([272af9d](https://github.com/nuxtlabs/ui/commit/272af9d24c7cda8341e66b57f76acdb9f46ea23e))
|
||||
* **Table:** override of `sortButton` and `emptyState` props ([192b0e6](https://github.com/nuxtlabs/ui/commit/192b0e63018ae73e8acaa8b4b1771cda2b59bdb6))
|
||||
* **Table:** type `sort` prop ([3ba0aed](https://github.com/nuxtlabs/ui/commit/3ba0aedcba578350e2fdd9c180505ed8920e0404))
|
||||
* use `cloneVNode` when altering props in render functions ([5e50eb9](https://github.com/nuxtlabs/ui/commit/5e50eb9eb82571d22e0a2f1a2fe985addf7efe18)), closes [#252](https://github.com/nuxtlabs/ui/issues/252)
|
||||
|
||||
|
||||
* **CommandPalette:** rename props to `emptyState` and `closeButton` for consistency ([daca463](https://github.com/nuxtlabs/ui/commit/daca46371cab1344bd87ffb0abe0f7e9cdb08609))
|
||||
* **Input:** move pointer class inside its own preset class ([f59a92c](https://github.com/nuxtlabs/ui/commit/f59a92ca1533a44e17fbc8b7945bdaa9a83e805a))
|
||||
* **Notification:** rename to `closeButton` and `actionButton` for consistency ([4458656](https://github.com/nuxtlabs/ui/commit/4458656be5547fc9505a5c4758bea4818ada408b))
|
||||
* **SelectMenu:** remove `inline-flex` from wrapper to behave like other form elements ([ba44c58](https://github.com/nuxtlabs/ui/commit/ba44c58a80252a4394fcf2f84611ea2696883120))
|
||||
* **Toggle:** rename icons to `onIcon` / `offIcon` for consistency ([8ee2ac1](https://github.com/nuxtlabs/ui/commit/8ee2ac10e7eda4c54418f613a5ef87dd89e1f7eb))
|
||||
|
||||
### [2.2.1](https://github.com/nuxtlabs/ui/compare/v2.2.0...v2.2.1) (2023-05-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **FormGroup:** missing `h` import from `vue` ([a96dc19](https://github.com/nuxtlabs/ui/commit/a96dc192157725143503b1a5e4b404cb48dc9d3f)), closes [#236](https://github.com/nuxtlabs/ui/issues/236)
|
||||
|
||||
## [2.2.0](https://github.com/nuxtlabs/ui/compare/v2.1.0...v2.2.0) (2023-05-26)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* handle color states on form elements (#234)
|
||||
* **Notification:** rename `progressColor` to `color` and style icon
|
||||
* **Avatar:** remove `chipVariant` prop
|
||||
* **VerticalNavigation:** split preset
|
||||
|
||||
### Features
|
||||
|
||||
* handle color states on form elements ([#234](https://github.com/nuxtlabs/ui/issues/234)) ([9ce531a](https://github.com/nuxtlabs/ui/commit/9ce531a06f1a972bc003876162e0503c1bbbdbd8))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Notification:** remove default color on icon ([1a9dc5c](https://github.com/nuxtlabs/ui/commit/1a9dc5c980d8477cdf9386a17e20fc9fec0d883e))
|
||||
* **Radio/Checkbox:** remove ring offset on focus ([a56dbea](https://github.com/nuxtlabs/ui/commit/a56dbeab351a5c58e5bb49f5762669e2884c6483))
|
||||
* **VerticalNavigation:** badge display ([d2ee505](https://github.com/nuxtlabs/ui/commit/d2ee5058f819fc17f281f323dab2f0b3d80cf7bd)), closes [#205](https://github.com/nuxtlabs/ui/issues/205)
|
||||
|
||||
|
||||
* **Avatar:** remove `chipVariant` prop ([1f22f84](https://github.com/nuxtlabs/ui/commit/1f22f84360c20498eea8971b21db9293a4c9c3dc))
|
||||
* **Notification:** rename `progressColor` to `color` and style icon ([1b61ec7](https://github.com/nuxtlabs/ui/commit/1b61ec72e292325d7776a4719f14a75bdb18e110))
|
||||
* **VerticalNavigation:** split preset ([19923cb](https://github.com/nuxtlabs/ui/commit/19923cbf1edc6c6d4aefb9ffab9f908b116e1c69))
|
||||
|
||||
## [2.1.0](https://github.com/nuxtlabs/ui/compare/v2.0.4...v2.1.0) (2023-05-19)
|
||||
|
||||
@@ -508,4 +819,4 @@ All notable changes to this project will be documented in this file. See [standa
|
||||
* **Toggle:** add missing `computed` import ([0f09c9b](https://github.com/nuxtlabs/ui/commit/0f09c9baae501458af029f853c78b1c10a3ac133))
|
||||
* **Tooltip:** missing `ref` import ([b08a8cc](https://github.com/nuxtlabs/ui/commit/b08a8cc0ac79e89817e338281a81c477d5ec645a))
|
||||
* **useTimer:** remove log ([c6dcbd1](https://github.com/nuxtlabs/ui/commit/c6dcbd1b2b542dab1850504a60451a485e2d4004))
|
||||
* **VerticalNavigation:** add `v-if` on label ([79d8e08](https://github.com/nuxtlabs/ui/commit/79d8e086f0c61887c52da6fe4a13f1bdf7077227))
|
||||
* **VerticalNavigation:** add `v-if` on label ([79d8e08](https://github.com/nuxtlabs/ui/commit/79d8e086f0c61887c52da6fe4a13f1bdf7077227))
|
||||
43
README.md
43
README.md
@@ -1,27 +1,40 @@
|
||||
# NuxtLabs UI
|
||||
[](https://ui.nuxt.com)
|
||||
|
||||
# Nuxt UI
|
||||
|
||||
[![npm version][npm-version-src]][npm-version-href]
|
||||
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
||||
[![License][license-src]][license-href]
|
||||
[![Nuxt][nuxt-src]][nuxt-href]
|
||||
|
||||
This module has been developed by [NuxtLabs](https://nuxtlabs.com/) for [Volta](https://volta.net) and [Nuxt Studio](https://nuxt.studio/). It provides everything related to UI when building a Nuxt application, including components, icons, colors, dark mode and also keyboard shortcuts.
|
||||
Nuxt UI provides everything related to UI when building Nuxt applications: components, icons, colors, dark mode and also keyboard shortcuts.
|
||||
|
||||
[](https://ui.nuxtlabs.com)
|
||||
Is has been developed by [NuxtLabs](https://nuxtlabs.com/) for [Volta](https://volta.net), [Nuxt Studio](https://nuxt.studio/) and the Nuxt community.
|
||||
|
||||
## Features
|
||||
|
||||
- Built with [Headless UI](https://headlessui.dev/) and [Tailwind CSS](https://tailwindcss.com/)
|
||||
- HMR support through Nuxt App Config
|
||||
- Dark mode support
|
||||
- Support for LTR and RTL languages
|
||||
- Keyboard shortcuts
|
||||
- Bundled icons
|
||||
- Fully typed
|
||||
- [Figma Kit](https://www.figma.com/community/file/1288455405058138934)
|
||||
|
||||
Read more on [ui.nuxt.com](https://ui.nuxt.com)
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
yarn add --dev @nuxthq/ui
|
||||
# Using npm
|
||||
npm install @nuxt/ui
|
||||
|
||||
# Using yarn
|
||||
yarn add @nuxt/ui
|
||||
|
||||
# Using pnpm
|
||||
pnpm add @nuxt/ui
|
||||
```
|
||||
|
||||
Then, register the module in your `nuxt.config.ts`:
|
||||
@@ -29,24 +42,24 @@ Then, register the module in your `nuxt.config.ts`:
|
||||
```js
|
||||
export default defineNuxtConfig({
|
||||
modules: [
|
||||
'@nuxthq/ui'
|
||||
'@nuxt/ui'
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
If you want latest updates, please use `@nuxthq/ui-edge` in your `package.json`:
|
||||
If you want latest updates, please use `@nuxt/ui-edge` in your `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"devDependencies": {
|
||||
"@nuxthq/ui": "npm:@nuxthq/ui-edge@latest"
|
||||
"@nuxt/ui": "npm:@nuxt/ui-edge@latest"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
Visit http://ui.nuxtlabs.com to view the documentation.
|
||||
Visit https://ui.nuxt.com to explore the documentation.
|
||||
|
||||
## Credits
|
||||
|
||||
@@ -60,17 +73,17 @@ Visit http://ui.nuxtlabs.com to view the documentation.
|
||||
|
||||
## License
|
||||
|
||||
Licensed under the [MIT license](https://github.com/nuxtlabs/ui/blob/dev/LICENSE.md).
|
||||
Licensed under the [MIT license](https://github.com/nuxt/ui/blob/dev/LICENSE.md).
|
||||
|
||||
<!-- Badges -->
|
||||
[npm-version-src]: https://img.shields.io/npm/v/@nuxthq/ui/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
|
||||
[npm-version-href]: https://npmjs.com/package/@nuxthq/ui
|
||||
[npm-version-src]: https://img.shields.io/npm/v/@nuxt/ui/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
|
||||
[npm-version-href]: https://npmjs.com/package/@nuxt/ui
|
||||
|
||||
[npm-downloads-src]: https://img.shields.io/npm/dm/@nuxthq/ui.svg?style=flat&colorA=18181B&colorB=28CF8D
|
||||
[npm-downloads-href]: https://npmjs.com/package/@nuxthq/ui
|
||||
[npm-downloads-src]: https://img.shields.io/npm/dm/@nuxt/ui.svg?style=flat&colorA=18181B&colorB=28CF8D
|
||||
[npm-downloads-href]: https://npmjs.com/package/@nuxt/ui
|
||||
|
||||
[license-src]: https://img.shields.io/github/license/nuxtlabs/ui.svg?style=flat&colorA=18181B&colorB=28CF8D
|
||||
[license-href]: https://github.com/nuxtlabs/ui/blob/main/LICENSE
|
||||
[license-src]: https://img.shields.io/github/license/nuxt/ui.svg?style=flat&colorA=18181B&colorB=28CF8D
|
||||
[license-href]: https://github.com/nuxt/ui/blob/main/LICENSE
|
||||
|
||||
[nuxt-src]: https://img.shields.io/badge/Nuxt-18181B?logo=nuxt.js
|
||||
[nuxt-href]: https://nuxt.com
|
||||
|
||||
6
docs/.env.example
Normal file
6
docs/.env.example
Normal file
@@ -0,0 +1,6 @@
|
||||
# To link Nuxt UI Pro in development
|
||||
NUXT_UI_PRO_PATH=
|
||||
# To use Nuxt UI Pro in production
|
||||
NUXT_UI_PRO_TOKEN=
|
||||
# Used when pre-rendering the docs for dynamic OG images
|
||||
NUXT_PUBLIC_SITE_URL=
|
||||
1
docs/.nuxtrc
Normal file
1
docs/.nuxtrc
Normal file
@@ -0,0 +1 @@
|
||||
imports.autoImport=true
|
||||
6
docs/app.config.ts
Normal file
6
docs/app.config.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export default defineAppConfig({
|
||||
ui: {
|
||||
primary: 'green',
|
||||
gray: 'slate'
|
||||
}
|
||||
})
|
||||
94
docs/app.vue
94
docs/app.vue
@@ -1,68 +1,96 @@
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<template>
|
||||
<div>
|
||||
<Header />
|
||||
|
||||
<UContainer>
|
||||
<div class="relative grid lg:grid-cols-10 lg:gap-8">
|
||||
<DocsAside class="lg:col-span-2" />
|
||||
<NuxtLayout>
|
||||
<NuxtPage />
|
||||
</NuxtLayout>
|
||||
|
||||
<div class="relative pt-8 pb-16" :class="[toc ? 'lg:col-span-6' : 'lg:col-span-8']">
|
||||
<DocsPageHeader />
|
||||
|
||||
<NuxtPage />
|
||||
|
||||
<DocsPageFooter class="mt-12" />
|
||||
|
||||
<hr class="border-gray-200 dark:border-gray-800 my-6">
|
||||
|
||||
<DocsPrevNext />
|
||||
|
||||
<DocsFooter class="mt-16" />
|
||||
</div>
|
||||
|
||||
<DocsToc v-if="toc" class="lg:col-span-2 order-first lg:order-last" />
|
||||
</div>
|
||||
</UContainer>
|
||||
<Footer />
|
||||
|
||||
<ClientOnly>
|
||||
<DocsSearch />
|
||||
<LazyUDocsSearch ref="searchRef" :files="files" :navigation="navigation" :groups="groups" />
|
||||
</ClientOnly>
|
||||
|
||||
<UNotifications />
|
||||
<UNotifications>
|
||||
<template #title="{ title }">
|
||||
<span v-html="title" />
|
||||
</template>
|
||||
|
||||
<template #description="{ description }">
|
||||
<span v-html="description" />
|
||||
</template>
|
||||
</UNotifications>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const { toc } = useContent()
|
||||
import { withoutTrailingSlash } from 'ufo'
|
||||
import { debounce } from 'perfect-debounce'
|
||||
import type { ParsedContent } from '@nuxt/content/dist/runtime/types'
|
||||
|
||||
const searchRef = ref()
|
||||
|
||||
const route = useRoute()
|
||||
const colorMode = useColorMode()
|
||||
const { branch, branches } = useContentSource()
|
||||
|
||||
const { data: nav } = await useAsyncData('navigation', () => fetchContentNavigation())
|
||||
const { data: files } = useLazyFetch<ParsedContent[]>('/api/search.json', { default: () => [], server: false })
|
||||
|
||||
// Computed
|
||||
|
||||
const navigation = computed(() => {
|
||||
const main = nav.value.filter(item => item._path !== '/dev')
|
||||
const dev = nav.value.find(item => item._path === '/dev')?.children
|
||||
|
||||
return branch.value?.name === 'dev' ? dev : main
|
||||
})
|
||||
|
||||
const groups = computed(() => {
|
||||
if (route.path === '/') {
|
||||
return []
|
||||
}
|
||||
|
||||
return [{ key: 'branch', label: 'Branch', commands: branches.value }]
|
||||
})
|
||||
|
||||
const color = computed(() => colorMode.value === 'dark' ? '#18181b' : 'white')
|
||||
|
||||
// Watch
|
||||
|
||||
watch(() => searchRef.value?.commandPaletteRef?.query, debounce((query: string) => {
|
||||
if (!query) {
|
||||
return
|
||||
}
|
||||
|
||||
useTrackEvent('Search', { props: { query: `${query} - ${searchRef.value?.commandPaletteRef.results.length} results` } })
|
||||
}, 500))
|
||||
|
||||
// Head
|
||||
|
||||
useHead({
|
||||
titleTemplate: title => title && title.includes('NuxtLabs UI') ? title : `${title} - NuxtLabs UI`,
|
||||
meta: [
|
||||
{ name: 'viewport', content: 'width=device-width, initial-scale=1, maximum-scale=1' },
|
||||
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
|
||||
{ key: 'theme-color', name: 'theme-color', content: color }
|
||||
],
|
||||
link: [
|
||||
{ rel: 'stylesheet', href: 'https://rsms.me/inter/inter.css' },
|
||||
{ rel: 'icon', type: 'image/svg+xml', href: '/icon.svg' }
|
||||
{ rel: 'icon', type: 'image/svg+xml', href: '/icon.svg' },
|
||||
{ rel: 'canonical', href: `https://ui.nuxt.com${withoutTrailingSlash(route.path)}` }
|
||||
],
|
||||
htmlAttrs: {
|
||||
lang: 'en'
|
||||
},
|
||||
bodyAttrs: {
|
||||
class: 'antialiased font-sans text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-900'
|
||||
}
|
||||
})
|
||||
|
||||
useSeoMeta({
|
||||
ogImage: '/social-preview.jpg',
|
||||
twitterImage: '/social-preview.jpg',
|
||||
useServerSeoMeta({
|
||||
ogSiteName: 'Nuxt UI',
|
||||
twitterCard: 'summary_large_image'
|
||||
})
|
||||
|
||||
// Provide
|
||||
|
||||
provide('navigation', navigation)
|
||||
provide('files', files)
|
||||
</script>
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
import type { RouterConfig } from '@nuxt/schema'
|
||||
|
||||
function findHashPosition (hash): { el: any, behavior: ScrollBehavior, top: number } {
|
||||
const el = document.querySelector(hash)
|
||||
// vue-router does not incorporate scroll-margin-top on its own.
|
||||
if (el) {
|
||||
const top = parseFloat(getComputedStyle(el).scrollMarginTop)
|
||||
|
||||
return {
|
||||
el: hash,
|
||||
behavior: 'smooth',
|
||||
top
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://router.vuejs.org/api/#routeroptions
|
||||
export default <RouterConfig>{
|
||||
scrollBehavior (to, from, savedPosition) {
|
||||
const nuxtApp = useNuxtApp()
|
||||
|
||||
// If history back
|
||||
if (savedPosition) {
|
||||
// Handle Suspense resolution
|
||||
return new Promise((resolve) => {
|
||||
nuxtApp.hooks.hookOnce('page:finish', () => {
|
||||
setTimeout(() => resolve(savedPosition), 50)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Scroll to heading on click
|
||||
if (to.hash) {
|
||||
return new Promise((resolve) => {
|
||||
if (to.path === from.path) {
|
||||
setTimeout(() => resolve(findHashPosition(to.hash)), 50)
|
||||
} else {
|
||||
nuxtApp.hooks.hookOnce('page:finish', () => {
|
||||
setTimeout(() => resolve(findHashPosition(to.hash)), 50)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Scroll to top of window
|
||||
return { top: 0 }
|
||||
}
|
||||
}
|
||||
36
docs/components/BranchSelect.vue
Normal file
36
docs/components/BranchSelect.vue
Normal file
@@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<div class="mb-3 lg:mb-6">
|
||||
<label for="branch" class="block mb-1.5 font-semibold text-sm/6">Version</label>
|
||||
|
||||
<USelectMenu
|
||||
id="branch"
|
||||
:model-value="branch"
|
||||
name="branch"
|
||||
:options="branches"
|
||||
color="gray"
|
||||
:ui="{ icon: { trailing: { padding: { sm: 'pe-1.5' } } } }"
|
||||
:ui-menu="{ option: { container: 'gap-1.5' } }"
|
||||
@update:model-value="select"
|
||||
>
|
||||
<template #label>
|
||||
<UIcon v-if="branch.icon" :name="branch.icon" class="w-4 h-4 flex-shrink-0 text-gray-600 dark:text-gray-300" />
|
||||
|
||||
<span class="font-medium">{{ branch.label }}</span>
|
||||
|
||||
<span class="truncate text-gray-400 dark:text-gray-500">{{ branch.suffix }}</span>
|
||||
</template>
|
||||
|
||||
<template #option="{ option }">
|
||||
<UIcon v-if="option.icon" :name="option.icon" class="w-4 h-4 flex-shrink-0 text-gray-600 dark:text-gray-300" />
|
||||
|
||||
<span class="font-medium">{{ option.label }}</span>
|
||||
|
||||
<span class="truncate text-gray-400 dark:text-gray-500">{{ option.suffix }}</span>
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const { branches, branch, select } = useContentSource()
|
||||
</script>
|
||||
37
docs/components/Footer.vue
Normal file
37
docs/components/Footer.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div v-if="$route.path !== '/playground'" class="w-full h-px bg-gray-200 dark:bg-gray-800 flex items-center justify-center">
|
||||
<div class="bg-white dark:bg-gray-900 px-4">
|
||||
<LogoOnly class="w-5 h-5" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<UFooter :links="[]" :ui="{ bottom: { container: 'lg:py-4' } }">
|
||||
<template #left>
|
||||
<div class="text-sm text-gray-500 dark:text-gray-400">
|
||||
Made by
|
||||
<NuxtLink to="https://nuxtlabs.com" aria-label="NuxtLabs" class="inline-block">
|
||||
<LogoLabs class="text-gray-900 dark:text-white h-4 w-auto" />
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #center>
|
||||
<span class="text-sm text-gray-500 dark:text-gray-400">
|
||||
Published under <NuxtLink to="https://github.com/nuxt/ui" target="_blank" class="text-gray-900 dark:text-white">
|
||||
MIT License
|
||||
</NuxtLink>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template #right>
|
||||
<UButton aria-label="Nuxt Website" icon="i-simple-icons-nuxtdotjs" to="https://nuxt.com" target="_blank" v-bind="($ui.button.secondary as any)" />
|
||||
<UButton aria-label="Nuxt UI on Discord" icon="i-simple-icons-discord" to="https://discord.com/invite/ps2h6QT" target="_blank" v-bind="($ui.button.secondary as any)" />
|
||||
<UButton aria-label="Nuxt on X" icon="i-simple-icons-x" to="https://x.com/nuxt_js" target="_blank" v-bind="($ui.button.secondary as any)" />
|
||||
<UButton aria-label="Nuxt UI on GitHub" icon="i-simple-icons-github" to="https://github.com/nuxt/ui" target="_blank" v-bind="($ui.button.secondary as any)" />
|
||||
</template>
|
||||
</UFooter>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// force typescript
|
||||
</script>
|
||||
@@ -1,117 +1,69 @@
|
||||
<template>
|
||||
<header class="sticky top-0 z-50 w-full backdrop-blur flex-none border-b border-gray-900/10 dark:border-gray-50/[0.06] bg-white/75 dark:bg-gray-900/75">
|
||||
<UContainer>
|
||||
<div class="flex items-center justify-between h-16">
|
||||
<div class="flex items-center gap-3">
|
||||
<NuxtLink to="/" class="flex items-end gap-1.5 font-bold text-xl text-gray-900 dark:text-white">
|
||||
<Logo class="w-8 h-8 text-primary-500 dark:text-primary-400" />
|
||||
<UHeader
|
||||
:links="links"
|
||||
:class="{
|
||||
'border-primary-200/75 dark:border-primary-900/50': $route.path === '/',
|
||||
'border-gray-200 dark:border-gray-800': $route.path !== '/'
|
||||
}"
|
||||
>
|
||||
<template #left>
|
||||
<NuxtLink to="/" class="flex items-end gap-1.5 font-bold text-xl text-gray-900 dark:text-white" aria-label="Nuxt UI">
|
||||
<Logo class="w-auto h-6" />
|
||||
</NuxtLink>
|
||||
</template>
|
||||
|
||||
NuxtLabs<span class="text-primary-500 dark:text-primary-400">UI</span>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
<template #right>
|
||||
<ColorPicker />
|
||||
|
||||
<div class="flex items-center -mr-1.5">
|
||||
<div class="mr-1.5 hidden lg:block">
|
||||
<ThemeSelect />
|
||||
</div>
|
||||
<UTooltip text="Search" :shortcuts="[metaSymbol, 'K']">
|
||||
<UDocsSearchButton :label="null" />
|
||||
</UTooltip>
|
||||
|
||||
<UButton
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
class="lg:hidden"
|
||||
icon="i-heroicons-magnifying-glass-20-solid"
|
||||
@click="openDocsSearch"
|
||||
/>
|
||||
<UColorModeButton />
|
||||
|
||||
<ClientOnly>
|
||||
<UButton
|
||||
:icon="isDark ? 'i-heroicons-moon' : 'i-heroicons-sun'"
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
aria-label="Theme"
|
||||
@click="isDark = !isDark"
|
||||
/>
|
||||
<UButton
|
||||
to="https://github.com/nuxt/ui"
|
||||
target="_blank"
|
||||
icon="i-simple-icons-github"
|
||||
aria-label="GitHub"
|
||||
class="hidden lg:inline-flex"
|
||||
v-bind="($ui.button.secondary as any)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #fallback>
|
||||
<div class="w-8 h-8" />
|
||||
</template>
|
||||
</ClientOnly>
|
||||
<template #panel>
|
||||
<BranchSelect />
|
||||
|
||||
<UButton
|
||||
to="https://github.com/nuxtlabs/ui"
|
||||
target="_blank"
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
icon="i-simple-icons-github"
|
||||
/>
|
||||
|
||||
<UButton
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
class="lg:hidden"
|
||||
icon="i-heroicons-bars-3-20-solid"
|
||||
@click="isDialogOpen = true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</UContainer>
|
||||
|
||||
<TransitionRoot :show="isDialogOpen" as="template">
|
||||
<Dialog as="div" @close="isDialogOpen = false">
|
||||
<DialogPanel class="fixed inset-0 z-50 overflow-y-auto bg-white dark:bg-gray-900 lg:hidden">
|
||||
<div class="px-4 sm:px-6 sticky top-0 border-b border-gray-900/10 dark:border-gray-50/[0.06] bg-white/75 dark:bg-gray-900/75 backdrop-blur z-10">
|
||||
<div class="flex items-center justify-between h-16">
|
||||
<div class="flex items-center gap-3">
|
||||
<NuxtLink to="/" class="flex items-end gap-2 font-bold text-xl text-gray-900 dark:text-white">
|
||||
<Logo class="w-8 h-8 text-primary-500 dark:text-primary-400" />
|
||||
|
||||
nuxthq/ui
|
||||
</NuxtLink>
|
||||
</div>
|
||||
|
||||
<div class="flex -mr-1.5">
|
||||
<UButton
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
icon="i-heroicons-x-mark-20-solid"
|
||||
@click="isDialogOpen = false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-4 sm:px-6 py-4 sm:py-6">
|
||||
<ThemeSelect class="mb-4 sm:mb-6 w-full" />
|
||||
|
||||
<DocsAsideLinks @click="isDialogOpen = false" />
|
||||
</div>
|
||||
</DialogPanel>
|
||||
</Dialog>
|
||||
</TransitionRoot>
|
||||
</header>
|
||||
<UNavigationTree :links="mapContentNavigation(navigation)" />
|
||||
</template>
|
||||
</UHeader>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Dialog, DialogPanel, TransitionRoot } from '@headlessui/vue'
|
||||
import type { NavItem } from '@nuxt/content/dist/runtime/types'
|
||||
|
||||
const { isSearchModalOpen } = useDocs()
|
||||
const colorMode = useColorMode()
|
||||
const { metaSymbol } = useShortcuts()
|
||||
|
||||
const isDialogOpen = ref(false)
|
||||
const navigation = inject<Ref<NavItem[]>>('navigation')
|
||||
|
||||
const isDark = computed({
|
||||
get () {
|
||||
return colorMode.value === 'dark'
|
||||
},
|
||||
set () {
|
||||
colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark'
|
||||
}
|
||||
const links = computed(() => {
|
||||
return [{
|
||||
label: 'Documentation',
|
||||
icon: 'i-heroicons-book-open-solid',
|
||||
to: '/getting-started'
|
||||
}, {
|
||||
label: 'Examples',
|
||||
icon: 'i-heroicons-square-3-stack-3d',
|
||||
to: '/getting-started/examples'
|
||||
}, {
|
||||
label: 'Playground',
|
||||
icon: 'i-simple-icons-stackblitz',
|
||||
to: '/playground'
|
||||
}, {
|
||||
label: 'Releases',
|
||||
icon: 'i-heroicons-rocket-launch-solid',
|
||||
to: 'https://github.com/nuxt/ui/releases',
|
||||
target: '_blank'
|
||||
}]
|
||||
})
|
||||
|
||||
function openDocsSearch () {
|
||||
isDialogOpen.value = false
|
||||
|
||||
setTimeout(() => {
|
||||
isSearchModalOpen.value = true
|
||||
}, 100)
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
<template>
|
||||
<svg width="900" height="900" viewBox="0 0 900 900" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M504.908 750H839.476C850.103 750.001 860.542 747.229 869.745 741.963C878.948 736.696 886.589 729.121 891.9 719.999C897.211 710.876 900.005 700.529 900 689.997C899.995 679.465 897.193 669.12 891.873 660.002L667.187 274.289C661.876 265.169 654.237 257.595 645.036 252.329C635.835 247.064 625.398 244.291 614.773 244.291C604.149 244.291 593.711 247.064 584.511 252.329C575.31 257.595 567.67 265.169 562.36 274.289L504.908 372.979L392.581 179.993C387.266 170.874 379.623 163.301 370.42 158.036C361.216 152.772 350.777 150 340.151 150C329.525 150 319.086 152.772 309.883 158.036C300.679 163.301 293.036 170.874 287.721 179.993L8.12649 660.002C2.80743 669.12 0.00462935 679.465 5.72978e-06 689.997C-0.00461789 700.529 2.78909 710.876 8.10015 719.999C13.4112 729.121 21.0523 736.696 30.255 741.963C39.4576 747.229 49.8973 750.001 60.524 750H270.538C353.748 750 415.112 713.775 457.336 643.101L559.849 467.145L614.757 372.979L779.547 655.834H559.849L504.908 750ZM267.114 655.737L120.551 655.704L340.249 278.586L449.87 467.145L376.474 593.175C348.433 639.03 316.577 655.737 267.114 655.737Z" fill="currentColor" />
|
||||
<svg width="1020" height="200" viewBox="0 0 1020 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M377 200C379.16 200 381 198.209 381 196V103C381 103 386 112 395 127L434 194C435.785 197.74 439.744 200 443 200H470V50H443C441.202 50 439 51.4941 439 54V148L421 116L385 55C383.248 51.8912 379.479 50 376 50H350V200H377Z" fill="currentColor" />
|
||||
<path d="M726 92H739C742.314 92 745 89.3137 745 86V60H773V92H800V116H773V159C773 169.5 778.057 174 787 174H800V200H783C759.948 200 745 185.071 745 160V116H726V92Z" fill="currentColor" />
|
||||
<path d="M591 92V154C591 168.004 585.742 179.809 578 188C570.258 196.191 559.566 200 545 200C530.434 200 518.742 196.191 511 188C503.389 179.809 498 168.004 498 154V92H514C517.412 92 520.769 92.622 523 95C525.231 97.2459 526 98.5652 526 102V154C526 162.059 526.457 167.037 530 171C533.543 174.831 537.914 176 545 176C552.217 176 555.457 174.831 559 171C562.543 167.037 563 162.059 563 154V102C563 98.5652 563.769 96.378 566 94C567.96 91.9107 570.028 91.9599 573 92C573.411 92.0055 574.586 92 575 92H591Z" fill="currentColor" />
|
||||
<path d="M676 144L710 92H684C680.723 92 677.812 93.1758 676 96L660 120L645 97C643.188 94.1758 639.277 92 636 92H611L645 143L608 200H634C637.25 200 640.182 196.787 642 194L660 167L679 195C680.818 197.787 683.75 200 687 200H713L676 144Z" fill="currentColor" />
|
||||
<path d="M168 200H279C282.542 200 285.932 198.756 289 197C292.068 195.244 295.23 193.041 297 190C298.77 186.959 300.002 183.51 300 179.999C299.998 176.488 298.773 173.04 297 170.001L222 41C220.23 37.96 218.067 35.7552 215 34C211.933 32.2448 207.542 31 204 31C200.458 31 197.067 32.2448 194 34C190.933 35.7552 188.77 37.96 187 41L168 74L130 9.99764C128.228 6.95784 126.068 3.75491 123 2C119.932 0.245087 116.542 0 113 0C109.458 0 106.068 0.245087 103 2C99.9323 3.75491 96.7717 6.95784 95 9.99764L2 170.001C0.226979 173.04 0.00154312 176.488 1.90993e-06 179.999C-0.0015393 183.51 0.229648 186.959 2 190C3.77035 193.04 6.93245 195.244 10 197C13.0675 198.756 16.4578 200 20 200H90C117.737 200 137.925 187.558 152 164L186 105L204 74L259 168H186L168 200ZM89 168H40L113 42L150 105L125.491 147.725C116.144 163.01 105.488 168 89 168Z" fill="rgb(var(--color-primary-DEFAULT))" />
|
||||
<path d="M958 60.0001H938C933.524 60.0001 929.926 59.9395 927 63C924.074 65.8905 925 67.5792 925 72V141C925 151.372 923.648 156.899 919 162C914.352 166.931 908.468 169 899 169C889.705 169 882.648 166.931 878 162C873.352 156.899 873 151.372 873 141V72.0001C873 67.5793 872.926 65.8906 870 63.0001C867.074 59.9396 863.476 60.0001 859 60.0001H840V141C840 159.023 845.016 173.458 855 184C865.156 194.542 879.893 200 899 200C918.107 200 932.844 194.542 943 184C953.156 173.458 958 159.023 958 141V60.0001Z" fill="rgb(var(--color-primary-DEFAULT))" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1000 60.0233L1020 60V77L1020 128V156.007L1020 181L1020 189.004C1020 192.938 1019.98 194.429 1017 197.001C1014.02 199.725 1009.56 200 1005 200H986.001V181.006L986 130.012V70.0215C986 66.1576 986.016 64.5494 989 62.023C991.819 59.6358 995.437 60.0233 1000 60.0233Z" fill="rgb(var(--color-primary-DEFAULT))" />
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
11
docs/components/LogoGreen.vue
Normal file
11
docs/components/LogoGreen.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<svg width="1020" height="200" viewBox="0 0 1020 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M377 200C379.16 200 381 198.209 381 196V103C381 103 386 112 395 127L434 194C435.785 197.74 439.744 200 443 200H470V50H443C441.202 50 439 51.4941 439 54V148L421 116L385 55C383.248 51.8912 379.479 50 376 50H350V200H377Z" fill="currentColor" />
|
||||
<path d="M726 92H739C742.314 92 745 89.3137 745 86V60H773V92H800V116H773V159C773 169.5 778.057 174 787 174H800V200H783C759.948 200 745 185.071 745 160V116H726V92Z" fill="currentColor" />
|
||||
<path d="M591 92V154C591 168.004 585.742 179.809 578 188C570.258 196.191 559.566 200 545 200C530.434 200 518.742 196.191 511 188C503.389 179.809 498 168.004 498 154V92H514C517.412 92 520.769 92.622 523 95C525.231 97.2459 526 98.5652 526 102V154C526 162.059 526.457 167.037 530 171C533.543 174.831 537.914 176 545 176C552.217 176 555.457 174.831 559 171C562.543 167.037 563 162.059 563 154V102C563 98.5652 563.769 96.378 566 94C567.96 91.9107 570.028 91.9599 573 92C573.411 92.0055 574.586 92 575 92H591Z" fill="currentColor" />
|
||||
<path d="M676 144L710 92H684C680.723 92 677.812 93.1758 676 96L660 120L645 97C643.188 94.1758 639.277 92 636 92H611L645 143L608 200H634C637.25 200 640.182 196.787 642 194L660 167L679 195C680.818 197.787 683.75 200 687 200H713L676 144Z" fill="currentColor" />
|
||||
<path d="M168 200H279C282.542 200 285.932 198.756 289 197C292.068 195.244 295.23 193.041 297 190C298.77 186.959 300.002 183.51 300 179.999C299.998 176.488 298.773 173.04 297 170.001L222 41C220.23 37.96 218.067 35.7552 215 34C211.933 32.2448 207.542 31 204 31C200.458 31 197.067 32.2448 194 34C190.933 35.7552 188.77 37.96 187 41L168 74L130 9.99764C128.228 6.95784 126.068 3.75491 123 2C119.932 0.245087 116.542 0 113 0C109.458 0 106.068 0.245087 103 2C99.9323 3.75491 96.7717 6.95784 95 9.99764L2 170.001C0.226979 173.04 0.00154312 176.488 1.90993e-06 179.999C-0.0015393 183.51 0.229648 186.959 2 190C3.77035 193.04 6.93245 195.244 10 197C13.0675 198.756 16.4578 200 20 200H90C117.737 200 137.925 187.558 152 164L186 105L204 74L259 168H186L168 200ZM89 168H40L113 42L150 105L125.491 147.725C116.144 163.01 105.488 168 89 168Z" fill="#00DC82" />
|
||||
<path d="M958 60.0001H938C933.524 60.0001 929.926 59.9395 927 63C924.074 65.8905 925 67.5792 925 72V141C925 151.372 923.648 156.899 919 162C914.352 166.931 908.468 169 899 169C889.705 169 882.648 166.931 878 162C873.352 156.899 873 151.372 873 141V72.0001C873 67.5793 872.926 65.8906 870 63.0001C867.074 59.9396 863.476 60.0001 859 60.0001H840V141C840 159.023 845.016 173.458 855 184C865.156 194.542 879.893 200 899 200C918.107 200 932.844 194.542 943 184C953.156 173.458 958 159.023 958 141V60.0001Z" fill="#00DC82" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1000 60.0233L1020 60V77L1020 128V156.007L1020 181L1020 189.004C1020 192.938 1019.98 194.429 1017 197.001C1014.02 199.725 1009.56 200 1005 200H986.001V181.006L986 130.012V70.0215C986 66.1576 986.016 64.5494 989 62.023C991.819 59.6358 995.437 60.0233 1000 60.0233Z" fill="#00DC82" />
|
||||
</svg>
|
||||
</template>
|
||||
@@ -1,9 +1,13 @@
|
||||
<template>
|
||||
<svg width="312" height="78" viewBox="0 0 312 78" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M65.6381 78H109.132C110.513 78.0002 111.87 77.6398 113.067 76.9552C114.263 76.2705 115.257 75.2857 115.947 74.0998C116.637 72.9139 117.001 71.5688 117 70.1996C116.999 68.8305 116.635 67.4856 115.944 66.3003L86.7343 16.1575C86.0439 14.9719 85.0508 13.9873 83.8547 13.3028C82.6586 12.6183 81.3017 12.2579 79.9205 12.2579C78.5393 12.2579 77.1825 12.6183 75.9864 13.3028C74.7903 13.9873 73.7971 14.9719 73.1067 16.1575L65.6381 28.9873L51.0356 3.89908C50.3446 2.71356 49.351 1.72914 48.1546 1.04472C46.9581 0.360308 45.6011 0 44.2196 0C42.8382 0 41.4811 0.360308 40.2847 1.04472C39.0883 1.72914 38.0947 2.71356 37.4037 3.89908L1.05644 66.3003C0.364965 67.4856 0.000601816 68.8305 7.44871e-07 70.1996C-0.000600326 71.5688 0.362582 72.9139 1.05302 74.0998C1.74346 75.2857 2.7368 76.2705 3.93315 76.9552C5.12949 77.6398 6.48665 78.0002 7.86812 78H35.1699C45.9872 78 53.9645 73.2907 59.4537 64.1032L72.7803 41.2289L79.9184 28.9873L101.341 65.7584H72.7803L65.6381 78ZM34.7248 65.7458L15.6717 65.7416L44.2324 16.7162L58.483 41.2289L48.9416 57.6127C45.2963 63.5739 41.155 65.7458 34.7248 65.7458Z" fill="currentColor" />
|
||||
<path d="M175.417 77.3598V66.9562H149.03V21.3406H136.5V77.3598H175.417Z" fill="currentColor" />
|
||||
<path d="M198.81 78C203.706 78 208.103 76.0793 210.178 73.1183V77.3598H221.795V37.026H210.178V41.0274C207.854 38.2264 203.706 36.3858 198.644 36.3858C186.446 36.3858 179.061 44.6286 179.061 57.1929C179.061 69.7572 186.446 78 198.81 78ZM200.635 68.3967C194.495 68.3967 190.429 63.9152 190.429 57.1929C190.429 50.3906 194.495 45.909 200.635 45.909C206.859 45.909 210.925 50.3906 210.925 57.1929C210.925 63.9152 206.859 68.3967 200.635 68.3967Z" fill="currentColor" />
|
||||
<path d="M254.606 78C266.97 78 274.604 69.7572 274.604 57.1929C274.604 44.6286 266.97 36.3858 254.772 36.3858C249.544 36.3858 245.478 38.3064 243.155 41.2674V19.5H231.621V77.3598H243.155V72.9583C245.478 76.0793 249.793 78 254.606 78ZM252.78 68.3967C246.557 68.3967 242.491 63.9152 242.491 57.1929C242.491 50.3906 246.557 45.909 252.78 45.909C258.838 45.909 262.987 50.3906 262.987 57.1929C262.987 63.9152 258.838 68.3967 252.78 68.3967Z" fill="currentColor" />
|
||||
<path d="M295.736 78C305.528 78 312 72.9583 312 65.2757C312 47.0294 289.098 56.3926 289.098 48.1498C289.098 45.5889 291.339 44.2285 294.575 44.2285C297.728 44.2285 300.964 46.0691 301.462 49.5103H311.502C311.087 41.5876 304.283 36.3858 294.243 36.3858C285.696 36.3858 279.307 41.4275 279.307 48.5499C279.307 65.5157 301.794 57.433 301.794 65.6758C301.794 67.9166 299.304 69.5971 295.736 69.5971C291.422 69.5971 288.517 67.3564 288.102 63.7551H278.145C278.56 72.4781 285.53 78 295.736 78Z" fill="currentColor" />
|
||||
<svg width="1240" height="200" viewBox="0 0 1240 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M168 200H279C282.542 200 285.932 198.756 289 197C292.068 195.244 295.23 193.041 297 190C298.77 186.959 300.002 183.51 300 179.999C299.998 176.488 298.773 173.04 297 170.001L222 41C220.23 37.96 218.067 35.7552 215 34C211.933 32.2448 207.542 31 204 31C200.458 31 197.067 32.2448 194 34C190.933 35.7552 188.77 37.96 187 41L168 74L130 9.99764C128.228 6.95784 126.068 3.75491 123 2C119.932 0.245087 116.542 0 113 0C109.458 0 106.068 0.245087 103 2C99.9323 3.75491 96.7717 6.95784 95 9.99764L2 170.001C0.226979 173.04 0.00154312 176.488 1.90993e-06 179.999C-0.0015393 183.51 0.229648 186.959 2 190C3.77035 193.04 6.93245 195.244 10 197C13.0675 198.756 16.4578 200 20 200H90C117.737 200 137.925 187.558 152 164L186 105L204 74L259 168H186L168 200ZM89 168H40L113 42L150 105L125.491 147.725C116.144 163.01 105.488 168 89 168Z" fill="currentColor" />
|
||||
<path d="M375 200C377.16 200 379 198.209 379 196V103C379 103 384 112 393 127L432 194C433.785 197.74 437.744 200 441 200H468V50H441C439.202 50 437 51.4941 437 54V148L419 116L383 55C381.248 51.8912 377.479 50 374 50H348V200H375Z" fill="currentColor" />
|
||||
<path d="M724 92H737C740.314 92 743 89.3137 743 86V60H771V92H798V116H771V159C771 169.5 776.057 174 785 174H798V200H781C757.948 200 743 185.071 743 160V116H724V92Z" fill="currentColor" />
|
||||
<path d="M589 154V92H573L572.832 92.0002L572.498 92.001H572.497C571.979 92.0023 571.294 92.004 571 92L570.912 91.9988C567.987 91.9592 565.941 91.9315 564 94C561.769 96.378 561 98.5652 561 102V154C561 162.059 560.543 167.037 557 171C553.457 174.831 550.217 176 543 176C535.914 176 531.543 174.831 528 171C524.457 167.037 524 162.059 524 154V102C524 98.5652 523.231 97.2459 521 95C518.769 92.622 515.412 92 512 92H496V154C496 168.004 501.389 179.809 509 188C516.742 196.191 528.434 200 543 200C557.566 200 568.258 196.191 576 188C583.742 179.809 589 168.004 589 154Z" fill="currentColor" />
|
||||
<path d="M674 144L708 92H682C678.723 92 675.812 93.1758 674 96L658 120L643 97C641.188 94.1758 637.277 92 634 92H609L643 143L606 200H632C635.25 200 638.182 196.787 640 194L658 167L677 195C678.818 197.787 681.75 200 685 200H711L674 144Z" fill="currentColor" />
|
||||
<path d="M931 200V175H868V66C868 62.6863 865.314 60 862 60H838V194C838 197.314 840.686 200 844 200H931Z" fill="currentColor" />
|
||||
<path d="M1202 200C1225.14 200 1240 187.277 1240 169C1240 143.04 1220.69 140.838 1205.16 139.067C1194.72 137.877 1186 136.882 1186 129C1186 122.908 1190.35 120 1198 120C1205.45 120 1213.82 123.813 1215 132H1232.68C1236.12 132 1238.91 129.086 1238.06 125.757C1234.16 110.512 1218.99 101 1198 101C1177.8 101 1163 113.056 1163 130C1163 153.784 1181.4 156.618 1196.52 158.946C1207.06 160.569 1216 161.946 1216 170C1216 175.331 1209.43 179 1201 179C1190.8 179 1183.98 174.567 1183 166H1166.29C1162.87 166 1160.08 168.888 1160.81 172.233C1164.58 189.368 1180.39 200 1202 200Z" fill="currentColor" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1151 149C1151 179.068 1133.34 200 1104 200C1092.58 200 1081.51 195.469 1076 188V200H1049V60H1076V111C1081.51 103.914 1091.59 100 1104 100C1132.95 100 1151 118.932 1151 149ZM1075 150C1075 166.088 1084.23 177 1099 177C1113.37 177 1123 166.088 1123 150C1123 133.721 1113.37 122 1099 122C1084.23 122 1075 133.721 1075 150Z" fill="currentColor" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1005 105C998.647 101.954 991.004 101 983 101C974.487 101 967.353 101.954 961 105C954.647 108.046 949.558 112.669 946 118C943.659 121.424 941.966 124.9 940.973 128.721C940.105 132.063 942.911 135 946.364 135H963C963.254 130.685 964.951 127.919 968 125C971.176 122.081 975.537 120 981 120C986.336 120 990.951 121.462 994 124C997.049 126.412 999 129.938 999 134C999 136.031 998.271 137.604 997 139C995.729 140.269 993.287 141 991 141H975C964.454 141 956.48 143.542 950 149C943.647 154.331 940 161.608 940 171C940 176.458 941.332 181.558 944 186C946.668 190.315 950.299 193.462 955 196C959.828 198.412 965.901 200 972 200C978.607 200 984.172 198.667 989 196.002C993.955 193.21 997.348 189.442 999 185V200H1025V137C1025 129.892 1022.68 123.331 1019 118C1015.44 112.542 1011.35 107.919 1005 105ZM993.173 174.679C989.615 178.74 984.66 180.771 978.307 180.771C974.623 180.771 971.573 179.819 969.159 177.915C966.745 175.885 965.538 173.283 965.538 170.11C965.538 166.429 966.809 163.446 969.35 161.162C971.891 158.877 975.194 157.735 979.26 157.735H998.7V159.067C998.7 165.413 996.857 170.617 993.173 174.679Z" fill="currentColor" />
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
5
docs/components/LogoOnly.vue
Normal file
5
docs/components/LogoOnly.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<svg width="264" height="264" viewBox="0 0 264 264" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M146.496 211.2H234.822C237.627 211.2 240.383 210.468 242.813 209.078C245.242 207.688 247.259 205.688 248.662 203.279C250.064 200.871 250.801 198.139 250.8 195.359C250.799 192.579 250.059 189.847 248.655 187.44L189.337 85.612C187.935 83.2043 185.918 81.2049 183.489 79.8147C181.06 78.4246 178.305 77.6927 175.5 77.6927C172.695 77.6927 169.94 78.4246 167.511 79.8147C165.082 81.2049 163.065 83.2043 161.663 85.612L146.496 111.666L116.841 60.7179C115.438 58.3104 113.42 56.3113 110.991 54.9214C108.561 53.5315 105.805 52.7998 103 52.7998C100.195 52.7998 97.4386 53.5315 95.0089 54.9214C92.5793 56.3113 90.5615 58.3104 89.1583 60.7179L15.3453 187.44C13.9411 189.847 13.2012 192.579 13.2 195.359C13.1987 198.139 13.9363 200.871 15.3384 203.279C16.7405 205.688 18.7578 207.688 21.1873 209.078C23.6168 210.468 26.3728 211.2 29.1783 211.2H84.6219C106.589 211.2 122.789 201.636 133.937 182.979L161 136.526L175.496 111.666L219 186.34H161L146.496 211.2ZM83.7181 186.314L45.0255 186.306L103.026 86.7466L131.966 136.526L112.589 169.798C105.186 181.904 96.7763 186.314 83.7181 186.314Z" fill="currentColor" />
|
||||
</svg>
|
||||
</template>
|
||||
33
docs/components/OgImage/OgImageDocs.vue
Normal file
33
docs/components/OgImage/OgImageDocs.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<script lang="ts" setup>
|
||||
defineOptions({
|
||||
inheritAttrs: false
|
||||
})
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full h-full flex flex-col justify-between items-start bg-[#020420] p-20 pt-32 pb-16">
|
||||
<div
|
||||
style="position: absolute;width: 1156px;height: 1000px;left: -215px;top: -337px;background: radial-gradient(50% 50% at 50% 50%, #00DC82 0%, rgba(0, 220, 130, 0) 100%);filter: blur(180.5px);opacity: 0.5;"
|
||||
/>
|
||||
<div>
|
||||
<h1 class="text-8xl mb-4 text-white">
|
||||
{{ title }}
|
||||
</h1>
|
||||
<p class="text-5xl text-gray-200 leading-tight pr-10">
|
||||
{{ description }}
|
||||
</p>
|
||||
</div>
|
||||
<LogoGreen class="w-[306px] h-[60px] text-white" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,87 +0,0 @@
|
||||
<template>
|
||||
<div class="flex items-center shadow-sm">
|
||||
<USelectMenu
|
||||
v-model="primary"
|
||||
name="primary"
|
||||
class="w-full [&>div>button]:!rounded-r-none"
|
||||
appearance="gray"
|
||||
:ui="{ width: 'w-[194px]' }"
|
||||
:popper="{ placement: 'bottom-start' }"
|
||||
:options="primaryOptions"
|
||||
>
|
||||
<template #label>
|
||||
<span class="flex-shrink-0 h-3 w-3 rounded-full" :style="{ backgroundColor: `${primary.hex}`}" />
|
||||
|
||||
{{ primary.text }}
|
||||
</template>
|
||||
|
||||
<template #option="{ option }">
|
||||
<span class="flex-shrink-0 h-3 w-3 rounded-full" :style="{ backgroundColor: `${option.hex}`}" />
|
||||
|
||||
{{ option.text }}
|
||||
</template>
|
||||
</USelectMenu>
|
||||
|
||||
<USelectMenu
|
||||
v-model="gray"
|
||||
name="gray"
|
||||
class="w-full [&>div>button]:!rounded-l-none [&>div>button]:-ml-px"
|
||||
appearance="gray"
|
||||
:ui="{ width: 'w-[194px]' }"
|
||||
:popper="{ placement: 'bottom-end' }"
|
||||
:options="grayOptions"
|
||||
>
|
||||
<template #label>
|
||||
<span class="flex-shrink-0 h-3 w-3 rounded-full" :style="{ backgroundColor: `${gray.hex}`}" />
|
||||
|
||||
{{ gray.text }}
|
||||
</template>
|
||||
|
||||
<template #option="{ option }">
|
||||
<span class="flex-shrink-0 h-3 w-3 rounded-full" :style="{ backgroundColor: `${option.hex}`}" />
|
||||
|
||||
{{ option.text }}
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import colors from '#tailwind-config/theme/colors'
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const colorMode = useColorMode()
|
||||
|
||||
const primaryCookie = useCookie('primary', { path: '/', default: () => appConfig.ui.primary })
|
||||
const grayCookie = useCookie('gray', { path: '/', default: () => appConfig.ui.gray })
|
||||
|
||||
watch(primaryCookie, (primary) => {
|
||||
appConfig.ui.primary = primary
|
||||
}, { immediate: true })
|
||||
|
||||
watch(grayCookie, (gray) => {
|
||||
appConfig.ui.gray = gray
|
||||
}, { immediate: true })
|
||||
|
||||
// Computed
|
||||
|
||||
const primaryOptions = computed(() => useWithout(appConfig.ui.colors, 'primary').map(color => ({ value: color, text: color, hex: colors[color][colorMode.value === 'dark' ? 400 : 500] })))
|
||||
const primary = computed({
|
||||
get () {
|
||||
return primaryOptions.value.find(option => option.value === primaryCookie.value)
|
||||
},
|
||||
set (option) {
|
||||
primaryCookie.value = option.value
|
||||
}
|
||||
})
|
||||
|
||||
const grayOptions = computed(() => ['slate', 'cool', 'zinc', 'neutral', 'stone'].map(color => ({ value: color, text: color, hex: colors[color][colorMode.value === 'dark' ? 400 : 500] })))
|
||||
const gray = computed({
|
||||
get () {
|
||||
return grayOptions.value.find(option => option.value === grayCookie.value)
|
||||
},
|
||||
set (option) {
|
||||
grayCookie.value = option.value
|
||||
}
|
||||
})
|
||||
</script>
|
||||
56
docs/components/color-picker/ColorPicker.vue
Normal file
56
docs/components/color-picker/ColorPicker.vue
Normal file
@@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<UPopover mode="hover">
|
||||
<template #default="{ open }">
|
||||
<UButton color="gray" variant="ghost" square :class="[open && 'bg-gray-50 dark:bg-gray-800']" aria-label="Color picker">
|
||||
<UIcon name="i-heroicons-swatch-20-solid" class="w-5 h-5 text-primary-500 dark:text-primary-400" />
|
||||
</UButton>
|
||||
</template>
|
||||
|
||||
<template #panel>
|
||||
<div class="p-2">
|
||||
<div class="grid grid-cols-5 gap-px">
|
||||
<ColorPickerPill v-for="color in primaryColors" :key="color.value" :color="color" :selected="primary" @select="primary = color" />
|
||||
</div>
|
||||
|
||||
<hr class="border-gray-200 dark:border-gray-800 my-2">
|
||||
|
||||
<div class="grid grid-cols-5 gap-px">
|
||||
<ColorPickerPill v-for="color in grayColors" :key="color.value" :color="color" :selected="gray" @select="gray = color" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</UPopover>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import colors from '#tailwind-config/theme/colors'
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const colorMode = useColorMode()
|
||||
|
||||
// Computed
|
||||
|
||||
const primaryColors = computed(() => appConfig.ui.colors.filter(color => color !== 'primary').map(color => ({ value: color, text: color, hex: colors[color][colorMode.value === 'dark' ? 400 : 500] })))
|
||||
const primary = computed({
|
||||
get () {
|
||||
return primaryColors.value.find(option => option.value === appConfig.ui.primary)
|
||||
},
|
||||
set (option) {
|
||||
appConfig.ui.primary = option.value
|
||||
|
||||
window.localStorage.setItem('nuxt-ui-primary', appConfig.ui.primary)
|
||||
}
|
||||
})
|
||||
|
||||
const grayColors = computed(() => ['slate', 'cool', 'zinc', 'neutral', 'stone'].map(color => ({ value: color, text: color, hex: colors[color][colorMode.value === 'dark' ? 400 : 500] })))
|
||||
const gray = computed({
|
||||
get () {
|
||||
return grayColors.value.find(option => option.value === appConfig.ui.gray)
|
||||
},
|
||||
set (option) {
|
||||
appConfig.ui.gray = option.value
|
||||
|
||||
window.localStorage.setItem('nuxt-ui-gray', appConfig.ui.gray)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
25
docs/components/color-picker/ColorPickerPill.vue
Normal file
25
docs/components/color-picker/ColorPickerPill.vue
Normal file
@@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<UTooltip :text="color.value" class="capitalize" :open-delay="500">
|
||||
<UButton
|
||||
color="white"
|
||||
square
|
||||
:ui="{
|
||||
color: {
|
||||
white: {
|
||||
solid: 'ring-0 bg-gray-100 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-800',
|
||||
ghost: 'hover:bg-gray-50 dark:hover:bg-gray-800/50'
|
||||
}
|
||||
}
|
||||
}"
|
||||
:variant="color.value === selected.value ? 'solid' : 'ghost'"
|
||||
@click.stop.prevent="$emit('select')"
|
||||
>
|
||||
<span class="inline-block w-3 h-3 rounded-full" :style="{ backgroundColor: color.hex }" />
|
||||
</UButton>
|
||||
</UTooltip>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineProps<{ color: { value: string, hex: string }, selected: { value: string} }>()
|
||||
defineEmits(['select'])
|
||||
</script>
|
||||
@@ -1,33 +0,0 @@
|
||||
<template>
|
||||
<component
|
||||
:is="to ? NuxtLink : 'div'"
|
||||
:to="to"
|
||||
class="block pl-4 pr-6 py-3 rounded-md !border !border-gray-200 dark:!border-gray-700 bg-gray-50 dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:text-gray-800 dark:hover:text-gray-200 text-sm leading-6 my-5 last:mb-0 font-normal group relative"
|
||||
:class="[to ? 'hover:!border-primary-500 dark:hover:!border-primary-400 hover:text-primary-500 dark:hover:text-primary-400 border-dashed' : '']"
|
||||
>
|
||||
<UIcon v-if="!!to" name="i-heroicons-link-20-solid" class="w-3 h-3 absolute right-2 top-2 text-gray-400 dark:text-gray-500 group-hover:text-primary-500 dark:group-hover:text-primary-400" />
|
||||
|
||||
<UIcon v-if="icon" :name="icon" class="w-4 h-4 mr-2 inline-flex items-center align-text-top" :class="color" />
|
||||
|
||||
<ContentSlot :use="$slots.default" unwrap="p" />
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const NuxtLink = resolveComponent('NuxtLink')
|
||||
|
||||
defineProps({
|
||||
icon: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: 'text-primary-500 dark:text-primary-400'
|
||||
},
|
||||
to: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
</script>
|
||||
@@ -1,18 +0,0 @@
|
||||
<template>
|
||||
<UKbd class="!my-0 align-text-top">
|
||||
{{ shortcut }}
|
||||
</UKbd>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const { metaSymbol } = useShortcuts()
|
||||
|
||||
const shortcut = computed(() => props.value === 'meta' ? metaSymbol.value : props.value)
|
||||
</script>
|
||||
@@ -1,53 +0,0 @@
|
||||
<template>
|
||||
<div :selected-index="selectedIndex" @change="changeTab">
|
||||
<div class="flex border border-gray-200 dark:border-gray-700 border-b-0 rounded-t-md overflow-hidden -mb-px">
|
||||
<div
|
||||
v-for="(tab, index) in tabs"
|
||||
:key="index"
|
||||
as="template"
|
||||
@click="selectedIndex = index"
|
||||
>
|
||||
<button
|
||||
class="px-4 py-2 focus:outline-none text-sm border-r border-r-gray-200 dark:border-r-gray-700 transition-colors"
|
||||
tabindex="-1"
|
||||
:class="[selectedIndex === index ? 'font-medium text-primary-500 dark:text-primary-400 bg-gray-50 dark:bg-gray-800' : 'hover:bg-gray-50 dark:hover:bg-gray-800']"
|
||||
>
|
||||
{{ tab.label }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="[&>div>pre]:!rounded-t-none">
|
||||
<component :is="selectedTab.component" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const slots = useSlots()
|
||||
|
||||
const selectedIndex = ref(0)
|
||||
|
||||
// Computed
|
||||
|
||||
const tabs = computed(() => slots.default?.().map((slot, index) => {
|
||||
return {
|
||||
label: slot.props?.filename || slot.props?.label || `${index}`,
|
||||
component: slot
|
||||
}
|
||||
}) || [])
|
||||
|
||||
const selectedTab = computed(() => tabs.value.find((_, index) => index === selectedIndex.value))
|
||||
|
||||
// Methods
|
||||
|
||||
function changeTab (index) {
|
||||
selectedIndex.value = index
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
inheritAttrs: false
|
||||
}
|
||||
</script>
|
||||
28
docs/components/content/ColorModeButton.vue
Normal file
28
docs/components/content/ColorModeButton.vue
Normal file
@@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<ClientOnly>
|
||||
<UButton
|
||||
:icon="isDark ? 'i-heroicons-moon-20-solid' : 'i-heroicons-sun-20-solid'"
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
aria-label="Theme"
|
||||
@click="isDark = !isDark"
|
||||
/>
|
||||
|
||||
<template #fallback>
|
||||
<div class="w-8 h-8" />
|
||||
</template>
|
||||
</ClientOnly>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const colorMode = useColorMode()
|
||||
|
||||
const isDark = computed({
|
||||
get () {
|
||||
return colorMode.value === 'dark'
|
||||
},
|
||||
set () {
|
||||
colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark'
|
||||
}
|
||||
})
|
||||
</script>
|
||||
@@ -2,53 +2,63 @@
|
||||
<div>
|
||||
<div v-if="propsToSelect.length" class="relative flex border border-gray-200 dark:border-gray-700 rounded-t-md overflow-hidden not-prose">
|
||||
<div v-for="prop in propsToSelect" :key="prop.name" class="flex flex-col gap-0.5 justify-between py-1.5 font-medium bg-gray-50 dark:bg-gray-800 border-r border-r-gray-200 dark:border-r-gray-700">
|
||||
<label :for="prop.name" class="block text-xs px-3 font-medium text-gray-400 dark:text-gray-500 -my-px">{{ prop.label }}</label>
|
||||
<label :for="`prop-${prop.name}`" class="block text-xs px-2.5 font-medium text-gray-400 dark:text-gray-500 -my-px">{{ prop.label }}</label>
|
||||
<UCheckbox
|
||||
v-if="prop.type === 'boolean'"
|
||||
v-if="prop.type.startsWith('boolean')"
|
||||
v-model="componentProps[prop.name]"
|
||||
:name="prop.name"
|
||||
appearance="none"
|
||||
:name="`prop-${prop.name}`"
|
||||
tabindex="-1"
|
||||
class="justify-center"
|
||||
/>
|
||||
<USelectMenu
|
||||
v-else-if="prop.type === 'string' && prop.options.length"
|
||||
v-else-if="prop.options.length && prop.name !== 'label'"
|
||||
v-model="componentProps[prop.name]"
|
||||
:options="prop.options"
|
||||
:name="prop.name"
|
||||
:label="componentProps[prop.name]"
|
||||
appearance="none"
|
||||
:name="`prop-${prop.name}`"
|
||||
variant="none"
|
||||
class="inline-flex"
|
||||
:ui="{ width: 'w-32 !-mt-px', rounded: 'rounded-b-md' }"
|
||||
:ui-select="{ custom: '!py-0' }"
|
||||
:ui-menu="{ width: 'w-32 !-mt-px', rounded: 'rounded-t-none' }"
|
||||
select-class="py-0"
|
||||
tabindex="-1"
|
||||
:popper="{ strategy: 'fixed', placement: 'bottom-start' }"
|
||||
/>
|
||||
<UInput
|
||||
v-else
|
||||
:model-value="componentProps[prop.name]"
|
||||
:type="prop.type === 'number' ? 'number' : 'text'"
|
||||
:name="prop.name"
|
||||
appearance="none"
|
||||
:name="`prop-${prop.name}`"
|
||||
variant="none"
|
||||
autocomplete="off"
|
||||
:ui="{ custom: '!py-0' }"
|
||||
input-class="py-0"
|
||||
tabindex="-1"
|
||||
@update:model-value="val => componentProps[prop.name] = prop.type === 'number' ? Number(val) : val"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex border border-b-0 border-gray-200 dark:border-gray-700 relative not-prose" :class="[{ 'p-4': padding }, propsToSelect.length ? 'border-t-0' : 'rounded-t-md', backgroundClass]">
|
||||
<div class="flex border border-b-0 border-gray-200 dark:border-gray-700 relative not-prose" :class="[{ 'p-4': padding }, propsToSelect.length ? 'border-t-0' : 'rounded-t-md', backgroundClass, overflowClass]">
|
||||
<component :is="name" v-model="vModel" v-bind="fullProps">
|
||||
<ContentSlot v-if="$slots.default" :use="$slots.default" />
|
||||
|
||||
<template v-for="slot in Object.keys(slots || {})" :key="slot" #[slot]>
|
||||
<ContentSlot :name="slot" />
|
||||
</template>
|
||||
</component>
|
||||
</div>
|
||||
|
||||
<ContentRenderer :value="ast" class="[&>div>pre]:!rounded-t-none" />
|
||||
<ContentRenderer v-if="!previewOnly" :value="ast" class="[&>div>pre]:!rounded-t-none [&>div>pre]:!mt-0" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// @ts-expect-error
|
||||
import { transformContent } from '@nuxt/content/transformers'
|
||||
// @ts-ignore
|
||||
import { useShikiHighlighter } from '@nuxtjs/mdc/runtime'
|
||||
import { upperFirst, camelCase, kebabCase } from 'scule'
|
||||
import * as config from '#ui/ui.config'
|
||||
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const props = defineProps({
|
||||
slug: {
|
||||
type: String,
|
||||
@@ -66,6 +76,10 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
slots: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
baseProps: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
@@ -78,28 +92,42 @@ const props = defineProps({
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
extraColors: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
backgroundClass: {
|
||||
type: String,
|
||||
default: 'bg-white dark:bg-gray-900'
|
||||
},
|
||||
overflowClass: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
previewOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const baseProps = reactive({ ...props.baseProps })
|
||||
const componentProps = reactive({ ...props.props })
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const route = useRoute()
|
||||
const slug = props.slug || route.params.slug[1]
|
||||
const camelName = useCamelCase(slug)
|
||||
const name = `U${useUpperFirst(camelName)}`
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const slug = props.slug || route.params.slug[route.params.slug.length - 1]
|
||||
const camelName = camelCase(slug)
|
||||
const name = `U${upperFirst(camelName)}`
|
||||
|
||||
const meta = await fetchComponentMeta(name)
|
||||
|
||||
// Computed
|
||||
|
||||
const ui = computed(() => ({ ...appConfig.ui[camelName], ...props.ui }))
|
||||
const ui = computed(() => ({ ...config[camelName], ...props.ui }))
|
||||
|
||||
const fullProps = computed(() => ({ ...props.baseProps, ...componentProps }))
|
||||
const fullProps = computed(() => ({ ...baseProps, ...componentProps }))
|
||||
const vModel = computed({
|
||||
get: () => baseProps.modelValue,
|
||||
set: (value) => {
|
||||
@@ -113,21 +141,23 @@ const propsToSelect = computed(() => Object.keys(componentProps).map((key) => {
|
||||
}
|
||||
|
||||
const prop = meta?.meta?.props?.find((prop: any) => prop.name === key)
|
||||
const dottedKey = useKebabCase(key).replaceAll('-', '.')
|
||||
const keys = useGet(ui.value, dottedKey, {})
|
||||
const dottedKey = kebabCase(key).replaceAll('-', '.')
|
||||
const keys = ui.value[dottedKey] ?? {}
|
||||
let options = typeof keys === 'object' && Object.keys(keys)
|
||||
if (key.toLowerCase().endsWith('color')) {
|
||||
options = appConfig.ui.colors
|
||||
// @ts-ignore
|
||||
options = [...appConfig.ui.colors, ...props.extraColors]
|
||||
}
|
||||
|
||||
return {
|
||||
type: prop?.type || 'string',
|
||||
name: key,
|
||||
label: key === 'modelValue' ? 'value' : useCamelCase(key),
|
||||
label: key === 'modelValue' ? 'value' : camelCase(key),
|
||||
options
|
||||
}
|
||||
}).filter(Boolean))
|
||||
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const code = computed(() => {
|
||||
let code = `\`\`\`html
|
||||
<${name}`
|
||||
@@ -136,11 +166,16 @@ const code = computed(() => {
|
||||
continue
|
||||
}
|
||||
|
||||
const prop = meta?.meta?.props?.find((prop: any) => prop.name === key)
|
||||
|
||||
code += ` ${(prop?.type === 'boolean' && value !== true) || typeof value === 'object' ? ':' : ''}${key === 'modelValue' ? 'value' : useKebabCase(key)}${prop?.type === 'boolean' && !!value && key !== 'modelValue' ? '' : `="${typeof value === 'object' ? renderObject(value) : value}"`}`
|
||||
code += ` ${(typeof value === 'boolean' && value !== true) || typeof value === 'object' || typeof value === 'number' ? ':' : ''}${key === 'modelValue' ? 'value' : kebabCase(key)}${typeof value === 'boolean' && !!value && key !== 'modelValue' ? '' : `="${typeof value === 'object' ? renderObject(value) : value}"`}`
|
||||
}
|
||||
if (props.code) {
|
||||
|
||||
if (props.slots) {
|
||||
code += `>
|
||||
${Object.entries(props.slots).map(([key, value]) => `<template #${key}>
|
||||
${value}
|
||||
</template>`).join('\n ')}
|
||||
</${name}>`
|
||||
} else if (props.code) {
|
||||
const lineBreaks = (props.code.match(/\n/g) || []).length
|
||||
if (lineBreaks > 1) {
|
||||
code += `>
|
||||
@@ -173,11 +208,17 @@ function renderObject (obj: any) {
|
||||
return obj
|
||||
}
|
||||
|
||||
const { data: ast } = await useAsyncData(`${name}-ast-${JSON.stringify(componentProps)}`, () => transformContent('content:_markdown.md', code.value, {
|
||||
highlight: {
|
||||
theme: {
|
||||
light: 'material-lighter',
|
||||
dark: 'material-palenight'
|
||||
const shikiHighlighter = useShikiHighlighter({})
|
||||
const codeHighlighter = async (code: string, lang: string, theme: any, highlights: number[]) => shikiHighlighter.getHighlightedAST(code, lang, theme, { highlights })
|
||||
const { data: ast } = await useAsyncData(`${name}-ast-${JSON.stringify({ props: componentProps, slots: props.slots })}`, () => transformContent('content:_markdown.md', code.value, {
|
||||
markdown: {
|
||||
highlight: {
|
||||
highlighter: codeHighlighter,
|
||||
theme: {
|
||||
light: 'material-theme-lighter',
|
||||
default: 'material-theme',
|
||||
dark: 'material-theme-palenight'
|
||||
}
|
||||
}
|
||||
}
|
||||
}), { watch: [code] })
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="[&>div>pre]:!rounded-t-none">
|
||||
<div class="flex border border-gray-200 dark:border-gray-700 relative not-prose rounded-t-md" :class="[{ 'p-4': padding, 'rounded-b-md': !$slots.code, 'border-b-0': !!$slots.code }, backgroundClass]">
|
||||
<div class="[&>div>pre]:!rounded-t-none [&>div>pre]:!mt-0">
|
||||
<div class="flex border border-gray-200 dark:border-gray-700 relative not-prose rounded-t-md" :class="[{ 'p-4': padding, 'rounded-b-md': !$slots.code, 'border-b-0': !!$slots.code }, backgroundClass, overflowClass]">
|
||||
<ContentSlot v-if="$slots.default" :use="$slots.default" />
|
||||
</div>
|
||||
|
||||
@@ -17,6 +17,10 @@ defineProps({
|
||||
backgroundClass: {
|
||||
type: String,
|
||||
default: 'bg-white dark:bg-gray-900'
|
||||
},
|
||||
overflowClass: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
<script setup lang="ts">
|
||||
// @ts-expect-error
|
||||
import { transformContent } from '@nuxt/content/transformers'
|
||||
import { upperFirst, camelCase } from 'scule'
|
||||
import * as config from '#ui/ui.config'
|
||||
|
||||
const props = defineProps({
|
||||
slug: {
|
||||
@@ -13,13 +15,13 @@ const props = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const route = useRoute()
|
||||
const slug = props.slug || route.params.slug[1]
|
||||
const camelName = useCamelCase(slug)
|
||||
const name = `U${useUpperFirst(camelName)}`
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const slug = props.slug || route.params.slug[route.params.slug.length - 1]
|
||||
const camelName = camelCase(slug)
|
||||
const name = `U${upperFirst(camelName)}`
|
||||
|
||||
const preset = appConfig.ui[camelName]
|
||||
const preset = config[camelName]
|
||||
|
||||
const { data: ast } = await useAsyncData(`${name}-preset`, () => transformContent('content:_markdown.md', `
|
||||
\`\`\`json
|
||||
@@ -28,8 +30,9 @@ ${JSON.stringify(preset, null, 2)}
|
||||
`, {
|
||||
highlight: {
|
||||
theme: {
|
||||
light: 'material-lighter',
|
||||
dark: 'material-palenight'
|
||||
light: 'material-theme-lighter',
|
||||
default: 'material-theme',
|
||||
dark: 'material-theme-palenight'
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
@@ -1,40 +1,14 @@
|
||||
<template>
|
||||
<div>
|
||||
<table class="table-fixed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="w-[25%]">
|
||||
Prop
|
||||
</th>
|
||||
<th class="w-[50%]">
|
||||
Default
|
||||
</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="prop in metaProps" :key="prop.name">
|
||||
<td class="relative flex-shrink-0">
|
||||
<code>{{ prop.name }}</code><span v-if="prop.required" class="font-bold text-red-500 dark:text-red-400 absolute top-0 ml-1">*</span>
|
||||
</td>
|
||||
<td>
|
||||
<code v-if="prop.default">{{ prop.default }}</code>
|
||||
</td>
|
||||
<td>
|
||||
<a v-if="prop.name === 'ui'" href="#preset">
|
||||
<code>{{ prop.type }}</code>
|
||||
</a>
|
||||
<code v-else class="break-all">
|
||||
{{ prop.type }}
|
||||
</code>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<FieldGroup>
|
||||
<ComponentPropsField v-for="prop in meta?.meta?.props" :key="prop.name" :prop="prop" />
|
||||
</FieldGroup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { upperFirst, camelCase } from 'scule'
|
||||
|
||||
const props = defineProps({
|
||||
slug: {
|
||||
type: String,
|
||||
@@ -43,13 +17,10 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
const slug = props.slug || route.params.slug[1]
|
||||
const camelName = useCamelCase(slug)
|
||||
const name = `U${useUpperFirst(camelName)}`
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const slug = props.slug || route.params.slug[route.params.slug.length - 1]
|
||||
const camelName = camelCase(slug)
|
||||
const name = `U${upperFirst(camelName)}`
|
||||
|
||||
const meta = await fetchComponentMeta(name)
|
||||
|
||||
const metaProps = computed(() => useSortBy(meta?.meta?.props || [], [
|
||||
prop => ['string', 'number', 'boolean', 'any'].indexOf(prop.type)
|
||||
]))
|
||||
</script>
|
||||
|
||||
43
docs/components/content/ComponentPropsField.vue
Normal file
43
docs/components/content/ComponentPropsField.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<Field v-bind="prop">
|
||||
<code v-if="prop.default">{{ prop.default }}</code>
|
||||
|
||||
<Collapsible v-if="prop.schema?.kind === 'array' && prop.schema?.schema?.filter(schema => schema.kind === 'object').length">
|
||||
<FieldGroup v-for="schema in prop.schema.schema" :key="schema.name" class="!mt-0">
|
||||
<ComponentPropsField v-for="subProp in Object.values(schema.schema)" :key="(subProp as any).name" :prop="subProp" />
|
||||
</FieldGroup>
|
||||
</Collapsible>
|
||||
<Collapsible v-else-if="prop.schema?.kind === 'array' && prop.schema?.schema?.filter(schema => schema.kind === 'array').length">
|
||||
<FieldGroup v-for="schema in prop.schema.schema" :key="schema.name" class="!mt-0">
|
||||
<template v-for="subSchema in schema.schema" :key="subSchema.name">
|
||||
<ComponentPropsField v-for="subProp in Object.values(subSchema.schema)" :key="(subProp as any).name" :prop="subProp" />
|
||||
</template>
|
||||
</FieldGroup>
|
||||
</Collapsible>
|
||||
<Collapsible v-else-if="prop.schema?.kind === 'object' && prop.schema.type !== 'Function' && Object.values(prop.schema.schema)?.length">
|
||||
<FieldGroup class="!mt-0">
|
||||
<ComponentPropsField v-for="subProp in Object.values(prop.schema.schema)" :key="(subProp as any).name" :prop="subProp" />
|
||||
</FieldGroup>
|
||||
</Collapsible>
|
||||
<div v-else-if="prop.schema?.kind === 'enum' && prop.schema.type !== 'boolean' && startsWithCapital(prop.schema.type) && !prop.schema.type.startsWith(prop.schema.schema[0])" class="space-x-1 leading-7 -my-1">
|
||||
<code v-for="value in prop.schema.schema.filter(value => typeof value === 'string')" :key="value" class="whitespace-pre-wrap break-words">{{ value }}</code>
|
||||
</div>
|
||||
</Field>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineProps({
|
||||
prop: {
|
||||
type: Object as PropType<any>,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
|
||||
function startsWithCapital (word) {
|
||||
if (word.charAt(0).startsWith('"')) {
|
||||
return false
|
||||
}
|
||||
|
||||
return word.charAt(0) === word.charAt(0).toUpperCase()
|
||||
}
|
||||
</script>
|
||||
@@ -18,6 +18,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { upperFirst, camelCase } from 'scule'
|
||||
|
||||
const props = defineProps({
|
||||
slug: {
|
||||
type: String,
|
||||
@@ -26,9 +28,10 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
const slug = props.slug || route.params.slug[1]
|
||||
const camelName = useCamelCase(slug)
|
||||
const name = `U${useUpperFirst(camelName)}`
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const slug = props.slug || route.params.slug[route.params.slug.length - 1]
|
||||
const camelName = camelCase(slug)
|
||||
const name = `U${upperFirst(camelName)}`
|
||||
|
||||
const meta = await fetchComponentMeta(name)
|
||||
</script>
|
||||
|
||||
@@ -11,6 +11,7 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const colorMode = useColorMode()
|
||||
|
||||
const src = computed(() => `https://volta.net/embed/${props.token}?gray=${appConfig.ui.gray}&primary=${appConfig.ui.primary}`)
|
||||
const src = computed(() => `https://volta.net/embed/${props.token}?theme=${colorMode.value}&gray=${appConfig.ui.gray}&primary=${appConfig.ui.primary}`)
|
||||
</script>
|
||||
|
||||
33
docs/components/content/examples/AccordionExampleBasic.vue
Normal file
33
docs/components/content/examples/AccordionExampleBasic.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<script setup>
|
||||
const items = [{
|
||||
label: 'Getting Started',
|
||||
icon: 'i-heroicons-information-circle',
|
||||
defaultOpen: true,
|
||||
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate.'
|
||||
}, {
|
||||
label: 'Installation',
|
||||
icon: 'i-heroicons-arrow-down-tray',
|
||||
disabled: true,
|
||||
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate.'
|
||||
}, {
|
||||
label: 'Theming',
|
||||
icon: 'i-heroicons-eye-dropper',
|
||||
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate.'
|
||||
}, {
|
||||
label: 'Layouts',
|
||||
icon: 'i-heroicons-rectangle-group',
|
||||
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate.'
|
||||
}, {
|
||||
label: 'Components',
|
||||
icon: 'i-heroicons-square-3-stack-3d',
|
||||
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate.'
|
||||
}, {
|
||||
label: 'Utilities',
|
||||
icon: 'i-heroicons-wrench-screwdriver',
|
||||
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate.'
|
||||
}]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UAccordion :items="items" />
|
||||
</template>
|
||||
@@ -0,0 +1,52 @@
|
||||
<script setup>
|
||||
const items = [{
|
||||
label: 'Getting Started',
|
||||
icon: 'i-heroicons-information-circle',
|
||||
defaultOpen: true,
|
||||
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate.'
|
||||
}, {
|
||||
label: 'Installation',
|
||||
icon: 'i-heroicons-arrow-down-tray',
|
||||
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate.'
|
||||
}, {
|
||||
label: 'Theming',
|
||||
icon: 'i-heroicons-eye-dropper',
|
||||
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate.'
|
||||
}, {
|
||||
label: 'Layouts',
|
||||
icon: 'i-heroicons-rectangle-group',
|
||||
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate.'
|
||||
}, {
|
||||
label: 'Components',
|
||||
icon: 'i-heroicons-square-3-stack-3d',
|
||||
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate.'
|
||||
}, {
|
||||
label: 'Utilities',
|
||||
icon: 'i-heroicons-wrench-screwdriver',
|
||||
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate.'
|
||||
}]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UAccordion :items="items" :ui="{ wrapper: 'flex flex-col w-full' }">
|
||||
<template #default="{ item, index, open }">
|
||||
<UButton color="gray" variant="ghost" class="border-b border-gray-200 dark:border-gray-700" :ui="{ rounded: 'rounded-none', padding: { sm: 'p-3' } }">
|
||||
<template #leading>
|
||||
<div class="w-6 h-6 rounded-full bg-primary-500 dark:bg-primary-400 flex items-center justify-center -my-1">
|
||||
<UIcon :name="item.icon" class="w-4 h-4 text-white dark:text-gray-900" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<span class="truncate">{{ index + 1 }}. {{ item.label }}</span>
|
||||
|
||||
<template #trailing>
|
||||
<UIcon
|
||||
name="i-heroicons-chevron-right-20-solid"
|
||||
class="w-5 h-5 ms-auto transform transition-transform duration-200"
|
||||
:class="[open && 'rotate-90']"
|
||||
/>
|
||||
</template>
|
||||
</UButton>
|
||||
</template>
|
||||
</UAccordion>
|
||||
</template>
|
||||
@@ -0,0 +1,70 @@
|
||||
<script setup>
|
||||
const items = [{
|
||||
label: 'Getting Started',
|
||||
icon: 'i-heroicons-information-circle',
|
||||
defaultOpen: true,
|
||||
slot: 'getting-started'
|
||||
}, {
|
||||
label: 'Installation',
|
||||
icon: 'i-heroicons-arrow-down-tray',
|
||||
defaultOpen: true,
|
||||
slot: 'installation'
|
||||
}, {
|
||||
label: 'Theming',
|
||||
icon: 'i-heroicons-eye-dropper',
|
||||
defaultOpen: true,
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate.'
|
||||
}, {
|
||||
label: 'Layouts',
|
||||
icon: 'i-heroicons-rectangle-group',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate.'
|
||||
}, {
|
||||
label: 'Components',
|
||||
icon: 'i-heroicons-square-3-stack-3d',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate.'
|
||||
}, {
|
||||
label: 'Utilities',
|
||||
icon: 'i-heroicons-wrench-screwdriver',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate.'
|
||||
}]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UAccordion :items="items">
|
||||
<template #item="{ item }">
|
||||
<p class="italic text-gray-900 dark:text-white text-center">
|
||||
{{ item.description }}
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<template #getting-started>
|
||||
<div class="text-gray-900 dark:text-white text-center">
|
||||
<Logo class="w-auto h-8 mx-auto" />
|
||||
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400 mt-2">
|
||||
Fully styled and customizable components for Nuxt.
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #installation="{ description }">
|
||||
<div class="flex flex-col justify-center items-center gap-1 mb-4">
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white">
|
||||
Installation
|
||||
</h3>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">
|
||||
Install <code>@nuxt/ui</code> dependency to your project:
|
||||
</p>
|
||||
<p>
|
||||
{{ description }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col items-center">
|
||||
<code>$ npm i @nuxt/ui</code>
|
||||
<code>$ yarn add @nuxt/ui</code>
|
||||
<code>$ pnpm add @nuxt/ui</code>
|
||||
</div>
|
||||
</template>
|
||||
</UAccordion>
|
||||
</template>
|
||||
12
docs/components/content/examples/AlertExampleHtml.vue
Normal file
12
docs/components/content/examples/AlertExampleHtml.vue
Normal file
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<UAlert title="Heads <i>up</i>!" icon="i-heroicons-command-line">
|
||||
<template #title="{ title }">
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<span v-html="title" />
|
||||
</template>
|
||||
|
||||
<template #description>
|
||||
You can add <b>components</b> to your app using the <u>cli</u>.
|
||||
</template>
|
||||
</UAlert>
|
||||
</template>
|
||||
7
docs/components/content/examples/CheckboxExample.vue
Normal file
7
docs/components/content/examples/CheckboxExample.vue
Normal file
@@ -0,0 +1,7 @@
|
||||
<script setup>
|
||||
const selected = ref(true)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UCheckbox v-model="selected" name="notifications" label="Notifications" />
|
||||
</template>
|
||||
@@ -8,7 +8,7 @@ const groups = computed(() => {
|
||||
return []
|
||||
}
|
||||
|
||||
const users = await $fetch(`https://jsonplaceholder.typicode.com/users`, { params: { q } })
|
||||
const users = await $fetch('https://jsonplaceholder.typicode.com/users', { params: { q } })
|
||||
|
||||
return users.map(user => ({ id: user.id, label: user.name, suffix: user.email }))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<template>
|
||||
<UCommandPalette>
|
||||
<template #empty-state>
|
||||
<div class="flex flex-col items-center justify-center py-6 gap-3">
|
||||
<span class="italic text-sm">Nothing here!</span>
|
||||
<UButton label="Add item" />
|
||||
</div>
|
||||
</template>
|
||||
</UCommandPalette>
|
||||
</template>
|
||||
@@ -1,34 +1,34 @@
|
||||
<script setup>
|
||||
const router = useRouter()
|
||||
const toast = useToast()
|
||||
|
||||
const commandPaletteRef = ref()
|
||||
|
||||
const users = [
|
||||
{ id: 'benjamincanac', label: 'benjamincanac', href: 'https://github.com/benjamincanac', target: '_blank', avatar: { src: 'https://avatars.githubusercontent.com/u/739984?v=4' } },
|
||||
{ id: 'Atinux', label: 'Atinux', href: 'https://github.com/Atinux', target: '_blank', avatar: { src: 'https://avatars.githubusercontent.com/u/904724?v=4' } },
|
||||
{ id: 'smarroufin', label: 'smarroufin', href: 'https://github.com/smarroufin', target: '_blank', avatar: { src: 'https://avatars.githubusercontent.com/u/7547335?v=4' } }
|
||||
{ id: 'benjamincanac', label: 'benjamincanac', href: 'https://github.com/benjamincanac', target: '_blank', avatar: { src: 'https://ipx.nuxt.com/s_16x16/gh_avatar/benjamincanac', srcset: 'https://ipx.nuxt.com/s_32x32/gh_avatar/benjamincanac 2x', loading: 'lazy' } },
|
||||
{ id: 'Atinux', label: 'Atinux', href: 'https://github.com/Atinux', target: '_blank', avatar: { src: 'https://ipx.nuxt.com/s_16x16/gh_avatar/Atinux', srcset: 'https://ipx.nuxt.com/s_32x32/gh_avatar/Atinux 2x', loading: 'lazy' } },
|
||||
{ id: 'smarroufin', label: 'smarroufin', href: 'https://github.com/smarroufin', target: '_blank', avatar: { src: 'https://ipx.nuxt.com/s_16x16/gh_avatar/smarroufin', srcset: 'https://ipx.nuxt.com/s_32x32/gh_avatar/smarroufin 2x', loading: 'lazy' } }
|
||||
]
|
||||
|
||||
const actions = [
|
||||
{ id: 'new-file', label: 'Add new file', icon: 'i-heroicons-document-plus', click: () => alert('New file'), shortcuts: ['⌘', 'N'] },
|
||||
{ id: 'new-folder', label: 'Add new folder', icon: 'i-heroicons-folder-plus', click: () => alert('New folder'), shortcuts: ['⌘', 'F'] },
|
||||
{ id: 'hashtag', label: 'Add hashtag', icon: 'i-heroicons-hashtag', click: () => alert('Add hashtag'), shortcuts: ['⌘', 'H'] },
|
||||
{ id: 'label', label: 'Add label', icon: 'i-heroicons-tag', click: () => alert('Add label'), shortcuts: ['⌘', 'L'] }
|
||||
{ id: 'new-file', label: 'Add new file', icon: 'i-heroicons-document-plus', click: () => toast.add({ title: 'New file added!' }), shortcuts: ['⌘', 'N'] },
|
||||
{ id: 'new-folder', label: 'Add new folder', icon: 'i-heroicons-folder-plus', click: () => toast.add({ title: 'New folder added!' }), shortcuts: ['⌘', 'F'] },
|
||||
{ id: 'hashtag', label: 'Add hashtag', icon: 'i-heroicons-hashtag', click: () => toast.add({ title: 'Hashtag added!' }), shortcuts: ['⌘', 'H'] },
|
||||
{ id: 'label', label: 'Add label', icon: 'i-heroicons-tag', click: () => toast.add({ title: 'Label added!' }), shortcuts: ['⌘', 'L'] }
|
||||
]
|
||||
|
||||
const groups = computed(() => commandPaletteRef.value?.query
|
||||
? [{
|
||||
key: 'users',
|
||||
commands: users
|
||||
}]
|
||||
: [{
|
||||
key: 'recent',
|
||||
label: 'Recent searches',
|
||||
commands: users.slice(0, 1)
|
||||
}, {
|
||||
key: 'actions',
|
||||
commands: actions
|
||||
}])
|
||||
const groups = computed(() =>
|
||||
[commandPaletteRef.value?.query ? {
|
||||
key: 'users',
|
||||
commands: users
|
||||
} : {
|
||||
key: 'recent',
|
||||
label: 'Recent searches',
|
||||
commands: users.slice(0, 1)
|
||||
}, {
|
||||
key: 'actions',
|
||||
commands: actions
|
||||
}].filter(Boolean))
|
||||
|
||||
function onSelect (option) {
|
||||
if (option.click) {
|
||||
|
||||
16
docs/components/content/examples/DatePickerExample.vue
Normal file
16
docs/components/content/examples/DatePickerExample.vue
Normal file
@@ -0,0 +1,16 @@
|
||||
<script setup>
|
||||
const date = ref(new Date())
|
||||
|
||||
const label = computed(() => date.value.toLocaleDateString('en-us', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric' })
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UPopover :popper="{ placement: 'bottom-start' }">
|
||||
<UButton icon="i-heroicons-calendar-days-20-solid" :label="label" />
|
||||
|
||||
<template #panel="{ close }">
|
||||
<LazyDatePicker v-model="date" @close="close" />
|
||||
</template>
|
||||
</UPopover>
|
||||
</template>
|
||||
@@ -8,11 +8,15 @@ const items = [
|
||||
}], [{
|
||||
label: 'Edit',
|
||||
icon: 'i-heroicons-pencil-square-20-solid',
|
||||
shortcuts: ['E']
|
||||
shortcuts: ['E'],
|
||||
click: () => {
|
||||
console.log('Edit')
|
||||
}
|
||||
}, {
|
||||
label: 'Duplicate',
|
||||
icon: 'i-heroicons-document-duplicate-20-solid',
|
||||
shortcuts: ['D']
|
||||
shortcuts: ['D'],
|
||||
disabled: true
|
||||
}], [{
|
||||
label: 'Archive',
|
||||
icon: 'i-heroicons-archive-box-20-solid'
|
||||
16
docs/components/content/examples/DropdownExampleMode.vue
Normal file
16
docs/components/content/examples/DropdownExampleMode.vue
Normal file
@@ -0,0 +1,16 @@
|
||||
<script setup>
|
||||
const items = [
|
||||
[{
|
||||
label: 'Profile',
|
||||
avatar: {
|
||||
src: 'https://avatars.githubusercontent.com/u/739984?v=4'
|
||||
}
|
||||
}]
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UDropdown :items="items" mode="hover" :popper="{ placement: 'bottom-start' }">
|
||||
<UButton color="white" label="Options" trailing-icon="i-heroicons-chevron-down-20-solid" />
|
||||
</UDropdown>
|
||||
</template>
|
||||
47
docs/components/content/examples/DropdownExampleSlot.vue
Normal file
47
docs/components/content/examples/DropdownExampleSlot.vue
Normal file
@@ -0,0 +1,47 @@
|
||||
<script setup>
|
||||
const items = [
|
||||
[{
|
||||
label: 'ben@example.com',
|
||||
slot: 'account',
|
||||
disabled: true
|
||||
}], [{
|
||||
label: 'Settings',
|
||||
icon: 'i-heroicons-cog-8-tooth'
|
||||
}], [{
|
||||
label: 'Documentation',
|
||||
icon: 'i-heroicons-book-open'
|
||||
}, {
|
||||
label: 'Changelog',
|
||||
icon: 'i-heroicons-megaphone'
|
||||
}, {
|
||||
label: 'Status',
|
||||
icon: 'i-heroicons-signal'
|
||||
}], [{
|
||||
label: 'Sign out',
|
||||
icon: 'i-heroicons-arrow-left-on-rectangle'
|
||||
}]
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UDropdown :items="items" :ui="{ item: { disabled: 'cursor-text select-text' } }" :popper="{ placement: 'bottom-start' }">
|
||||
<UAvatar src="https://avatars.githubusercontent.com/u/739984?v=4" />
|
||||
|
||||
<template #account="{ item }">
|
||||
<div class="text-left">
|
||||
<p>
|
||||
Signed in as
|
||||
</p>
|
||||
<p class="truncate font-medium text-gray-900 dark:text-white">
|
||||
{{ item.label }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #item="{ item }">
|
||||
<span class="truncate">{{ item.label }}</span>
|
||||
|
||||
<UIcon :name="item.icon" class="flex-shrink-0 h-4 w-4 text-gray-400 dark:text-gray-500 ms-auto" />
|
||||
</template>
|
||||
</UDropdown>
|
||||
</template>
|
||||
41
docs/components/content/examples/FormExampleBasic.vue
Normal file
41
docs/components/content/examples/FormExampleBasic.vue
Normal file
@@ -0,0 +1,41 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import type { FormError, FormSubmitEvent } from '@nuxt/ui/dist/runtime/types'
|
||||
|
||||
const state = ref({
|
||||
email: undefined,
|
||||
password: undefined
|
||||
})
|
||||
|
||||
const validate = (state: any): FormError[] => {
|
||||
const errors = []
|
||||
if (!state.email) errors.push({ path: 'email', message: 'Required' })
|
||||
if (!state.password) errors.push({ path: 'password', message: 'Required' })
|
||||
return errors
|
||||
}
|
||||
|
||||
async function submit (event: FormSubmitEvent<any>) {
|
||||
// Do something with data
|
||||
console.log(event.data)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UForm
|
||||
:validate="validate"
|
||||
:state="state"
|
||||
@submit="submit"
|
||||
>
|
||||
<UFormGroup label="Email" name="email">
|
||||
<UInput v-model="state.email" />
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup label="Password" name="password">
|
||||
<UInput v-model="state.password" type="password" />
|
||||
</UFormGroup>
|
||||
|
||||
<UButton type="submit">
|
||||
Submit
|
||||
</UButton>
|
||||
</UForm>
|
||||
</template>
|
||||
104
docs/components/content/examples/FormExampleElements.vue
Normal file
104
docs/components/content/examples/FormExampleElements.vue
Normal file
@@ -0,0 +1,104 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { z } from 'zod'
|
||||
import type { FormSubmitEvent } from '@nuxt/ui/dist/runtime/types'
|
||||
|
||||
const options = [
|
||||
{ label: 'Option 1', value: 'option-1' },
|
||||
{ label: 'Option 2', value: 'option-2' },
|
||||
{ label: 'Option 3', value: 'option-3' }
|
||||
]
|
||||
|
||||
const state = ref({
|
||||
input: undefined,
|
||||
textarea: undefined,
|
||||
select: undefined,
|
||||
selectMenu: undefined,
|
||||
checkbox: undefined,
|
||||
toggle: undefined,
|
||||
radio: undefined,
|
||||
switch: undefined,
|
||||
range: undefined
|
||||
})
|
||||
|
||||
const schema = z.object({
|
||||
input: z.string().min(10),
|
||||
textarea: z.string().min(10),
|
||||
select: z.string().refine(value => value === 'option-2', {
|
||||
message: 'Select Option 2'
|
||||
}),
|
||||
selectMenu: z.any().refine(option => option?.value === 'option-2', {
|
||||
message: 'Select Option 2'
|
||||
}),
|
||||
toggle: z.boolean().refine(value => value === true, {
|
||||
message: 'Toggle me'
|
||||
}),
|
||||
checkbox: z.boolean().refine(value => value === true, {
|
||||
message: 'Check me'
|
||||
}),
|
||||
radio: z.string().refine(value => value === 'option-2', {
|
||||
message: 'Select Option 2'
|
||||
}),
|
||||
range: z.number().max(20, { message: 'Must be less than 20' })
|
||||
})
|
||||
|
||||
type Schema = z.infer<typeof schema>
|
||||
|
||||
const form = ref()
|
||||
|
||||
async function submit (event: FormSubmitEvent<Schema>) {
|
||||
// Do something with event.data
|
||||
console.log(event.data)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UForm
|
||||
ref="form"
|
||||
:schema="schema"
|
||||
:state="state"
|
||||
@submit="submit"
|
||||
>
|
||||
<UFormGroup name="input" label="Input">
|
||||
<UInput v-model="state.input" />
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup name="textarea" label="Textarea">
|
||||
<UTextarea v-model="state.textarea" />
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup name="select" label="Select">
|
||||
<USelect v-model="state.select" placeholder="Select..." :options="options" />
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup name="selectMenu" label="Select Menu">
|
||||
<USelectMenu v-model="state.selectMenu" placeholder="Select..." :options="options" />
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup name="toggle" label="Toggle">
|
||||
<UToggle v-model="state.toggle" />
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup name="checkbox" label="Checkbox">
|
||||
<UCheckbox v-model="state.checkbox" label="Check me" />
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup name="radio" label="Radio">
|
||||
<URadio v-for="option in options" :key="option.value" v-model="state.radio" v-bind="option">
|
||||
{{ option.label }}
|
||||
</URadio>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup name="range" label="Range">
|
||||
<URange v-model="state.range" />
|
||||
</UFormGroup>
|
||||
|
||||
<UButton type="submit">
|
||||
Submit
|
||||
</UButton>
|
||||
|
||||
<UButton variant="outline" class="ml-2" @click="form.clear()">
|
||||
Clear
|
||||
</UButton>
|
||||
</UForm>
|
||||
</template>
|
||||
42
docs/components/content/examples/FormExampleJoi.vue
Normal file
42
docs/components/content/examples/FormExampleJoi.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import Joi from 'joi'
|
||||
import type { FormSubmitEvent } from '@nuxt/ui/dist/runtime/types'
|
||||
|
||||
const schema = Joi.object({
|
||||
email: Joi.string().required(),
|
||||
password: Joi.string()
|
||||
.min(8)
|
||||
.required()
|
||||
})
|
||||
|
||||
const state = ref({
|
||||
email: undefined,
|
||||
password: undefined
|
||||
})
|
||||
|
||||
async function submit (event: FormSubmitEvent<any>) {
|
||||
// Do something with event.data
|
||||
console.log(event.data)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UForm
|
||||
:schema="schema"
|
||||
:state="state"
|
||||
@submit="submit"
|
||||
>
|
||||
<UFormGroup label="Email" name="email">
|
||||
<UInput v-model="state.email" />
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup label="Password" name="password">
|
||||
<UInput v-model="state.password" type="password" />
|
||||
</UFormGroup>
|
||||
|
||||
<UButton type="submit">
|
||||
Submit
|
||||
</UButton>
|
||||
</UForm>
|
||||
</template>
|
||||
42
docs/components/content/examples/FormExampleValibot.vue
Normal file
42
docs/components/content/examples/FormExampleValibot.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { string, objectAsync, email, minLength, Input } from 'valibot'
|
||||
import type { FormSubmitEvent } from '@nuxt/ui/dist/runtime/types'
|
||||
|
||||
const schema = objectAsync({
|
||||
email: string([email('Invalid email')]),
|
||||
password: string([minLength(8, 'Must be at least 8 characters')])
|
||||
})
|
||||
|
||||
type Schema = Input<typeof schema>
|
||||
|
||||
const state = ref({
|
||||
email: undefined,
|
||||
password: undefined
|
||||
})
|
||||
|
||||
async function submit (event: FormSubmitEvent<Schema>) {
|
||||
// Do something with event.data
|
||||
console.log(event.data)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UForm
|
||||
:schema="schema"
|
||||
:state="state"
|
||||
@submit="submit"
|
||||
>
|
||||
<UFormGroup label="Email" name="email">
|
||||
<UInput v-model="state.email" />
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup label="Password" name="password">
|
||||
<UInput v-model="state.password" type="password" />
|
||||
</UFormGroup>
|
||||
|
||||
<UButton type="submit">
|
||||
Submit
|
||||
</UButton>
|
||||
</UForm>
|
||||
</template>
|
||||
44
docs/components/content/examples/FormExampleYup.vue
Normal file
44
docs/components/content/examples/FormExampleYup.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { object, string, InferType } from 'yup'
|
||||
import type { FormSubmitEvent } from '@nuxt/ui/dist/runtime/types'
|
||||
|
||||
const schema = object({
|
||||
email: string().email('Invalid email').required('Required'),
|
||||
password: string()
|
||||
.min(8, 'Must be at least 8 characters')
|
||||
.required('Required')
|
||||
})
|
||||
|
||||
type Schema = InferType<typeof schema>
|
||||
|
||||
const state = ref({
|
||||
email: undefined,
|
||||
password: undefined
|
||||
})
|
||||
|
||||
async function submit (event: FormSubmitEvent<Schema>) {
|
||||
// Do something with event.data
|
||||
console.log(event.data)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UForm
|
||||
:schema="schema"
|
||||
:state="state"
|
||||
@submit="submit"
|
||||
>
|
||||
<UFormGroup label="Email" name="email">
|
||||
<UInput v-model="state.email" />
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup label="Password" name="password">
|
||||
<UInput v-model="state.password" type="password" />
|
||||
</UFormGroup>
|
||||
|
||||
<UButton type="submit">
|
||||
Submit
|
||||
</UButton>
|
||||
</UForm>
|
||||
</template>
|
||||
42
docs/components/content/examples/FormExampleZod.vue
Normal file
42
docs/components/content/examples/FormExampleZod.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { z } from 'zod'
|
||||
import type { FormSubmitEvent } from '@nuxt/ui/dist/runtime/types'
|
||||
|
||||
const schema = z.object({
|
||||
email: z.string().email('Invalid email'),
|
||||
password: z.string().min(8, 'Must be at least 8 characters')
|
||||
})
|
||||
|
||||
type Schema = z.output<typeof schema>
|
||||
|
||||
const state = ref({
|
||||
email: undefined,
|
||||
password: undefined
|
||||
})
|
||||
|
||||
async function submit (event: FormSubmitEvent<Schema>) {
|
||||
// Do something with data
|
||||
console.log(event.data)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UForm
|
||||
:schema="schema"
|
||||
:state="state"
|
||||
@submit="submit"
|
||||
>
|
||||
<UFormGroup label="Email" name="email">
|
||||
<UInput v-model="state.email" />
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup label="Password" name="password">
|
||||
<UInput v-model="state.password" type="password" />
|
||||
</UFormGroup>
|
||||
|
||||
<UButton type="submit">
|
||||
Submit
|
||||
</UButton>
|
||||
</UForm>
|
||||
</template>
|
||||
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<UFormGroup v-slot="{ error }" label="Email" :error="!email && 'You must enter an email'" help="This is a nice email!">
|
||||
<UInput v-model="email" type="email" placeholder="Enter email" :trailing-icon="error ? 'i-heroicons-exclamation-triangle-20-solid' : undefined" />
|
||||
</UFormGroup>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const email = ref('')
|
||||
</script>
|
||||
@@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<UFormGroup label="Email" :error="!email && 'You must enter an email'" help="This is a nice email!">
|
||||
<template #default="{ error }">
|
||||
<UInput v-model="email" type="email" placeholder="Enter email" :trailing-icon="error ? 'i-heroicons-exclamation-triangle-20-solid' : undefined" />
|
||||
</template>
|
||||
|
||||
<template #error="{ error }">
|
||||
<UAlert v-if="error" icon="i-heroicons-exclamation-triangle-20-solid" :title="error" color="red" />
|
||||
<UAlert v-else icon="i-heroicons-check-circle-20-solid" title="Your email is valid" color="green" />
|
||||
</template>
|
||||
</UFormGroup>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const email = ref('')
|
||||
</script>
|
||||
7
docs/components/content/examples/InputExample.vue
Normal file
7
docs/components/content/examples/InputExample.vue
Normal file
@@ -0,0 +1,7 @@
|
||||
<script setup>
|
||||
const value = ref('')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UInput v-model="value" />
|
||||
</template>
|
||||
25
docs/components/content/examples/InputExampleClearable.vue
Normal file
25
docs/components/content/examples/InputExampleClearable.vue
Normal file
@@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<UInput
|
||||
v-model="q"
|
||||
name="q"
|
||||
placeholder="Search..."
|
||||
icon="i-heroicons-magnifying-glass-20-solid"
|
||||
autocomplete="off"
|
||||
:ui="{ icon: { trailing: { pointer: '' } } }"
|
||||
>
|
||||
<template #trailing>
|
||||
<UButton
|
||||
v-show="q !== ''"
|
||||
color="gray"
|
||||
variant="link"
|
||||
icon="i-heroicons-x-mark-20-solid"
|
||||
:padded="false"
|
||||
@click="q = ''"
|
||||
/>
|
||||
</template>
|
||||
</UInput>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const q = ref('')
|
||||
</script>
|
||||
@@ -0,0 +1,15 @@
|
||||
<script setup>
|
||||
const isOpen = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<UModal v-model="isOpen" :overlay="false">
|
||||
<div class="p-4">
|
||||
<Placeholder class="h-48" />
|
||||
</div>
|
||||
</UModal>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,15 @@
|
||||
<script setup>
|
||||
const isOpen = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<UModal v-model="isOpen" :transition="false">
|
||||
<div class="p-4">
|
||||
<Placeholder class="h-48" />
|
||||
</div>
|
||||
</UModal>
|
||||
</div>
|
||||
</template>
|
||||
33
docs/components/content/examples/ModalExampleFullscreen.vue
Normal file
33
docs/components/content/examples/ModalExampleFullscreen.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<script setup>
|
||||
const isOpen = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<UModal v-model="isOpen" fullscreen>
|
||||
<UCard
|
||||
:ui="{
|
||||
base: 'h-full flex flex-col',
|
||||
rounded: '',
|
||||
divide: 'divide-y divide-gray-100 dark:divide-gray-800',
|
||||
body: {
|
||||
base: 'grow'
|
||||
}
|
||||
}"
|
||||
>
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">
|
||||
Modal
|
||||
</h3>
|
||||
<UButton color="gray" variant="ghost" icon="i-heroicons-x-mark-20-solid" class="-my-1" @click="isOpen = false" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<Placeholder class="h-full" />
|
||||
</UCard>
|
||||
</UModal>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,24 @@
|
||||
<script setup>
|
||||
const isOpen = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<UModal v-model="isOpen" prevent-close>
|
||||
<UCard :ui="{ ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">
|
||||
Modal
|
||||
</h3>
|
||||
<UButton color="gray" variant="ghost" icon="i-heroicons-x-mark-20-solid" class="-my-1" @click="isOpen = false" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<Placeholder class="h-32" />
|
||||
</UCard>
|
||||
</UModal>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,7 @@
|
||||
<script setup>
|
||||
const toast = useToast()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UButton label="Show toast" @click="toast.add({ title: 'Notification <i>italic</i>', description: 'This is an <u>underlined</u> and <b>bold</b> notification.' })" />
|
||||
</template>
|
||||
@@ -0,0 +1,8 @@
|
||||
<script setup>
|
||||
const page = ref(1)
|
||||
const items = ref(Array(55))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UPagination v-model="page" :page-count="5" :total="items.length" />
|
||||
</template>
|
||||
@@ -0,0 +1,20 @@
|
||||
<script setup>
|
||||
const page = ref(1)
|
||||
const items = ref(Array(55))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UPagination v-model="page" :total="items.length" :ui="{ rounded: 'first-of-type:rounded-s-md last-of-type:rounded-e-md' }">
|
||||
<template #prev="{ onClick }">
|
||||
<UTooltip text="Previous page">
|
||||
<UButton icon="i-heroicons-arrow-small-left-20-solid" color="primary" :ui="{ rounded: 'rounded-full' }" class="rtl:[&_span:first-child]:rotate-180 me-2" @click="onClick" />
|
||||
</UTooltip>
|
||||
</template>
|
||||
|
||||
<template #next="{ onClick }">
|
||||
<UTooltip text="Next page">
|
||||
<UButton icon="i-heroicons-arrow-small-right-20-solid" color="primary" :ui="{ rounded: 'rounded-full' }" class="rtl:[&_span:last-child]:rotate-180 ms-2" @click="onClick" />
|
||||
</UTooltip>
|
||||
</template>
|
||||
</UPagination>
|
||||
</template>
|
||||
68
docs/components/content/examples/PaginationExampleRTL.vue
Normal file
68
docs/components/content/examples/PaginationExampleRTL.vue
Normal file
@@ -0,0 +1,68 @@
|
||||
<script setup>
|
||||
const page = ref(1)
|
||||
const items = ref(Array(55))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full divide-y divide-gray-200 dark:divide-gray-700 space-y-4">
|
||||
<div class="flex flex-wrap gap-1 justify-between w-full">
|
||||
<div dir="ltr">
|
||||
<UInput
|
||||
icon="i-heroicons-magnifying-glass-20-solid"
|
||||
size="sm"
|
||||
color="white"
|
||||
placeholder="Search..."
|
||||
:trailing="false"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div dir="rtl">
|
||||
<UInput
|
||||
icon="i-heroicons-magnifying-glass-20-solid"
|
||||
size="sm"
|
||||
color="white"
|
||||
placeholder="ابحث..."
|
||||
:trailing="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap gap-1 justify-between w-full pt-4">
|
||||
<div dir="ltr">
|
||||
<UPagination
|
||||
v-model="page"
|
||||
:total="items.length"
|
||||
:prev-button="{
|
||||
icon: 'i-heroicons-arrow-small-left-20-solid',
|
||||
label: 'Prev',
|
||||
color: 'gray'
|
||||
}"
|
||||
:next-button="{
|
||||
icon: 'i-heroicons-arrow-small-right-20-solid',
|
||||
trailing: true,
|
||||
label: 'Next',
|
||||
color: 'gray'
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div dir="rtl">
|
||||
<UPagination
|
||||
v-model="page"
|
||||
:total="items.length"
|
||||
:prev-button="{
|
||||
icon: 'i-heroicons-arrow-small-left-20-solid',
|
||||
label: 'السابق',
|
||||
color: 'gray'
|
||||
}"
|
||||
:next-button="{
|
||||
icon: 'i-heroicons-arrow-small-right-20-solid',
|
||||
trailing: true,
|
||||
label: 'التالي',
|
||||
color: 'gray'
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
11
docs/components/content/examples/PopoverExampleMode.vue
Normal file
11
docs/components/content/examples/PopoverExampleMode.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<UPopover mode="hover">
|
||||
<UButton color="white" label="Open" trailing-icon="i-heroicons-chevron-down-20-solid" />
|
||||
|
||||
<template #panel>
|
||||
<div class="p-4">
|
||||
<Placeholder class="h-20 w-48" />
|
||||
</div>
|
||||
</template>
|
||||
</UPopover>
|
||||
</template>
|
||||
23
docs/components/content/examples/RadioExample.vue
Normal file
23
docs/components/content/examples/RadioExample.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<script setup>
|
||||
const methods = [{
|
||||
name: 'email',
|
||||
value: 'email',
|
||||
label: 'Email'
|
||||
}, {
|
||||
name: 'sms',
|
||||
value: 'sms',
|
||||
label: 'Phone (SMS)'
|
||||
}, {
|
||||
name: 'push',
|
||||
value: 'push',
|
||||
label: 'Push notification'
|
||||
}]
|
||||
|
||||
const selected = ref('sms')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="space-y-1">
|
||||
<URadio v-for="method of methods" :key="method.name" v-model="selected" v-bind="method" />
|
||||
</div>
|
||||
</template>
|
||||
8
docs/components/content/examples/RangeExample.vue
Normal file
8
docs/components/content/examples/RangeExample.vue
Normal file
@@ -0,0 +1,8 @@
|
||||
<script setup>
|
||||
const value = ref(50)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<label for="range" class="sr-only" />
|
||||
<URange id="range" v-model="value" name="range" />
|
||||
</template>
|
||||
9
docs/components/content/examples/SelectExample.vue
Normal file
9
docs/components/content/examples/SelectExample.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<script setup>
|
||||
const countries = ['United States', 'Canada', 'Mexico']
|
||||
|
||||
const country = ref(countries[0])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<USelect v-model="country" :options="countries" />
|
||||
</template>
|
||||
19
docs/components/content/examples/SelectExampleObjects.vue
Normal file
19
docs/components/content/examples/SelectExampleObjects.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<script setup>
|
||||
const countries = [{
|
||||
name: 'United States',
|
||||
value: 'US'
|
||||
}, {
|
||||
name: 'Canada',
|
||||
value: 'CA',
|
||||
disabled: true
|
||||
}, {
|
||||
name: 'Mexico',
|
||||
value: 'MX'
|
||||
}]
|
||||
|
||||
const country = ref('CA')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<USelect v-model="country" :options="countries" option-attribute="name" />
|
||||
</template>
|
||||
@@ -0,0 +1,19 @@
|
||||
<script setup>
|
||||
const search = async (q) => {
|
||||
const users = await $fetch('https://jsonplaceholder.typicode.com/users', { params: { q } })
|
||||
|
||||
return users.map(user => ({ id: user.id, label: user.name, suffix: user.email })).filter(Boolean)
|
||||
}
|
||||
|
||||
const selected = ref([])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<USelectMenu
|
||||
v-model="selected"
|
||||
:searchable="search"
|
||||
placeholder="Search for a user..."
|
||||
multiple
|
||||
by="id"
|
||||
/>
|
||||
</template>
|
||||
@@ -6,10 +6,10 @@ const selected = ref(people[3])
|
||||
|
||||
<template>
|
||||
<USelectMenu v-slot="{ open }" v-model="selected" :options="people">
|
||||
<UButton>
|
||||
<UButton color="gray" class="flex-1 justify-between">
|
||||
{{ selected }}
|
||||
|
||||
<UIcon name="i-heroicons-chevron-right-20-solid" class="w-5 h-5 transition-transform" :class="[open && 'transform rotate-90']" />
|
||||
<UIcon name="i-heroicons-chevron-right-20-solid" class="w-5 h-5 transition-transform text-gray-400 dark:text-gray-500" :class="[open && 'transform rotate-90']" />
|
||||
</UButton>
|
||||
</USelectMenu>
|
||||
</template>
|
||||
|
||||
100
docs/components/content/examples/SelectMenuExampleCreatable.vue
Normal file
100
docs/components/content/examples/SelectMenuExampleCreatable.vue
Normal file
@@ -0,0 +1,100 @@
|
||||
<script setup>
|
||||
const options = ref([
|
||||
{ id: 1, name: 'bug', color: 'd73a4a' },
|
||||
{ id: 2, name: 'documentation', color: '0075ca' },
|
||||
{ id: 3, name: 'duplicate', color: 'cfd3d7' },
|
||||
{ id: 4, name: 'enhancement', color: 'a2eeef' },
|
||||
{ id: 5, name: 'good first issue', color: '7057ff' },
|
||||
{ id: 6, name: 'help wanted', color: '008672' },
|
||||
{ id: 7, name: 'invalid', color: 'e4e669' },
|
||||
{ id: 8, name: 'question', color: 'd876e3' },
|
||||
{ id: 9, name: 'wontfix', color: 'ffffff' }
|
||||
])
|
||||
|
||||
const selected = ref([])
|
||||
|
||||
const labels = computed({
|
||||
get: () => selected.value,
|
||||
set: async (labels) => {
|
||||
const promises = labels.map(async (label) => {
|
||||
if (label.id) {
|
||||
return label
|
||||
}
|
||||
|
||||
// In a real app, you would make an API call to create the label
|
||||
const response = {
|
||||
name: label.name,
|
||||
color: generateColorFromString(label.name)
|
||||
}
|
||||
|
||||
options.value.push(response)
|
||||
|
||||
return response
|
||||
})
|
||||
|
||||
selected.value = await Promise.all(promises)
|
||||
}
|
||||
})
|
||||
|
||||
function hashCode (str) {
|
||||
let hash = 0
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
hash = str.charCodeAt(i) + ((hash << 5) - hash)
|
||||
}
|
||||
return hash
|
||||
}
|
||||
|
||||
function intToRGB (i) {
|
||||
const c = (i & 0x00FFFFFF)
|
||||
.toString(16)
|
||||
.toUpperCase()
|
||||
|
||||
return '00000'.substring(0, 6 - c.length) + c
|
||||
}
|
||||
|
||||
function generateColorFromString (str) {
|
||||
return intToRGB(hashCode(str))
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<USelectMenu
|
||||
v-model="labels"
|
||||
by="id"
|
||||
name="labels"
|
||||
:options="options"
|
||||
option-attribute="name"
|
||||
multiple
|
||||
searchable
|
||||
creatable
|
||||
>
|
||||
<template #label>
|
||||
<template v-if="labels.length">
|
||||
<span class="flex items-center -space-x-1">
|
||||
<span v-for="label of labels" :key="label.id" class="flex-shrink-0 w-2 h-2 mt-px rounded-full" :style="{ background: `#${label.color}` }" />
|
||||
</span>
|
||||
<span>{{ labels.length }} label{{ labels.length > 1 ? 's' : '' }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="text-gray-500 dark:text-gray-400 truncate">Select labels</span>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template #option="{ option }">
|
||||
<span
|
||||
class="flex-shrink-0 w-2 h-2 mt-px rounded-full"
|
||||
:style="{ background: `#${option.color}` }"
|
||||
/>
|
||||
<span class="truncate">{{ option.name }}</span>
|
||||
</template>
|
||||
|
||||
<template #option-create="{ option }">
|
||||
<span class="flex-shrink-0">New label:</span>
|
||||
<span
|
||||
class="flex-shrink-0 w-2 h-2 mt-px rounded-full -mx-1"
|
||||
:style="{ background: `#${generateColorFromString(option.name)}` }"
|
||||
/>
|
||||
<span class="block truncate">{{ option.name }}</span>
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</template>
|
||||
@@ -5,10 +5,5 @@ const selected = ref([])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<USelectMenu v-model="selected" :options="people" multiple>
|
||||
<template #label>
|
||||
<span v-if="selected.length" class="font-medium truncate">{{ selected.join(', ') }}</span>
|
||||
<span v-else class="block truncate text-gray-400 dark:text-gray-500">Select people</span>
|
||||
</template>
|
||||
</USelectMenu>
|
||||
<USelectMenu v-model="selected" :options="people" multiple placeholder="Select people" />
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<script setup>
|
||||
const people = ['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']
|
||||
|
||||
const selected = ref([])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<USelectMenu v-model="selected" :options="people" multiple>
|
||||
<template #label>
|
||||
<span v-if="selected.length" class="truncate">{{ selected.join(', ') }}</span>
|
||||
<span v-else>Select people</span>
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</template>
|
||||
@@ -5,22 +5,19 @@ const people = [{
|
||||
href: 'https://github.com/benjamincanac',
|
||||
target: '_blank',
|
||||
avatar: { src: 'https://avatars.githubusercontent.com/u/739984?v=4' }
|
||||
},
|
||||
{
|
||||
}, {
|
||||
id: 'Atinux',
|
||||
label: 'Atinux',
|
||||
href: 'https://github.com/Atinux',
|
||||
target: '_blank',
|
||||
avatar: { src: 'https://avatars.githubusercontent.com/u/904724?v=4' }
|
||||
},
|
||||
{
|
||||
}, {
|
||||
id: 'smarroufin',
|
||||
label: 'smarroufin',
|
||||
href: 'https://github.com/smarroufin',
|
||||
target: '_blank',
|
||||
avatar: { src: 'https://avatars.githubusercontent.com/u/7547335?v=4' }
|
||||
},
|
||||
{
|
||||
}, {
|
||||
id: 'nobody',
|
||||
label: 'Nobody',
|
||||
icon: 'i-heroicons-user-circle'
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<script setup>
|
||||
const people = [{
|
||||
id: 1,
|
||||
name: 'Wade Cooper'
|
||||
}, {
|
||||
id: 2,
|
||||
name: 'Arlene Mccoy'
|
||||
}, {
|
||||
id: 3,
|
||||
name: 'Devon Webb'
|
||||
}, {
|
||||
id: 4,
|
||||
name: 'Tom Cook'
|
||||
}]
|
||||
|
||||
const selected = ref(people[0].id)
|
||||
|
||||
const current = computed(() => people.find(person => person.id === selected.value))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<USelectMenu
|
||||
v-model="selected"
|
||||
:options="people"
|
||||
placeholder="Select people"
|
||||
value-attribute="id"
|
||||
option-attribute="name"
|
||||
>
|
||||
<template #label>
|
||||
{{ current.name }}
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</template>
|
||||
@@ -0,0 +1,13 @@
|
||||
<script setup>
|
||||
const people = ['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']
|
||||
|
||||
const selected = ref(people[0])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<USelectMenu v-model="selected" :options="people" searchable>
|
||||
<template #option-empty="{ query }">
|
||||
<q>{{ query }}</q> not found
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</template>
|
||||
@@ -0,0 +1,30 @@
|
||||
<script setup>
|
||||
const people = [
|
||||
{ name: 'Wade Cooper', online: true },
|
||||
{ name: 'Arlene Mccoy', online: false },
|
||||
{ name: 'Devon Webb', online: false },
|
||||
{ name: 'Tom Cook', online: true },
|
||||
{ name: 'Tanya Fox', online: false },
|
||||
{ name: 'Hellen Schmidt', online: true },
|
||||
{ name: 'Caroline Schultz', online: true },
|
||||
{ name: 'Mason Heaney', online: false },
|
||||
{ name: 'Claudie Smitham', online: true },
|
||||
{ name: 'Emil Schaefer', online: false }
|
||||
]
|
||||
|
||||
const selected = ref(people[3])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<USelectMenu v-model="selected" :options="people" option-attribute="name">
|
||||
<template #label>
|
||||
<span :class="[selected.online ? 'bg-green-400' : 'bg-gray-200', 'inline-block h-2 w-2 flex-shrink-0 rounded-full']" aria-hidden="true" />
|
||||
<span class="truncate">{{ selected.name }}</span>
|
||||
</template>
|
||||
|
||||
<template #option="{ option: person }">
|
||||
<span :class="[person.online ? 'bg-green-400' : 'bg-gray-200', 'inline-block h-2 w-2 flex-shrink-0 rounded-full']" aria-hidden="true" />
|
||||
<span class="truncate">{{ person.name }}</span>
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</template>
|
||||
@@ -7,8 +7,8 @@ const isOpen = ref(false)
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<USlideover v-model="isOpen">
|
||||
<div class="p-4 h-full">
|
||||
<Placeholder class="w-full h-full" />
|
||||
<div class="p-4 flex-1">
|
||||
<Placeholder class="h-full" />
|
||||
</div>
|
||||
</USlideover>
|
||||
</div>
|
||||
23
docs/components/content/examples/SlideoverExampleCard.vue
Normal file
23
docs/components/content/examples/SlideoverExampleCard.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<script setup>
|
||||
const isOpen = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<USlideover v-model="isOpen">
|
||||
<UCard class="flex flex-col flex-1" :ui="{ body: { base: 'flex-1' }, ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
|
||||
<template #header>
|
||||
<Placeholder class="h-8" />
|
||||
</template>
|
||||
|
||||
<Placeholder class="h-full" />
|
||||
|
||||
<template #footer>
|
||||
<Placeholder class="h-8" />
|
||||
</template>
|
||||
</UCard>
|
||||
</USlideover>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,15 @@
|
||||
<script setup>
|
||||
const isOpen = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<USlideover v-model="isOpen" :overlay="false">
|
||||
<div class="p-4 flex-1">
|
||||
<Placeholder class="h-full" />
|
||||
</div>
|
||||
</USlideover>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,15 @@
|
||||
<script setup>
|
||||
const isOpen = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<USlideover v-model="isOpen" :transition="false">
|
||||
<div class="p-4 flex-1">
|
||||
<Placeholder class="h-full" />
|
||||
</div>
|
||||
</USlideover>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,24 @@
|
||||
<script setup>
|
||||
const isOpen = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<USlideover v-model="isOpen" prevent-close>
|
||||
<UCard class="flex flex-col flex-1" :ui="{ body: { base: 'flex-1' }, ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">
|
||||
Slideover
|
||||
</h3>
|
||||
<UButton color="gray" variant="ghost" icon="i-heroicons-x-mark-20-solid" class="-my-1" @click="isOpen = false" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<Placeholder class="h-full" />
|
||||
</UCard>
|
||||
</USlideover>
|
||||
</div>
|
||||
</template>
|
||||
246
docs/components/content/examples/TableExampleAdvanced.vue
Normal file
246
docs/components/content/examples/TableExampleAdvanced.vue
Normal file
@@ -0,0 +1,246 @@
|
||||
<script lang="ts" setup>
|
||||
// Columns
|
||||
const columns = [{
|
||||
key: 'id',
|
||||
label: '#',
|
||||
sortable: true
|
||||
}, {
|
||||
key: 'title',
|
||||
label: 'Title',
|
||||
sortable: true
|
||||
}, {
|
||||
key: 'completed',
|
||||
label: 'Status',
|
||||
sortable: true
|
||||
}, {
|
||||
key: 'actions',
|
||||
label: 'Actions',
|
||||
sortable: false
|
||||
}]
|
||||
|
||||
const selectedColumns = ref(columns)
|
||||
const columnsTable = computed(() => columns.filter((column) => selectedColumns.value.includes(column)))
|
||||
|
||||
// Selected Rows
|
||||
const selectedRows = ref([])
|
||||
|
||||
function select (row) {
|
||||
const index = selectedRows.value.findIndex((item) => item.id === row.id)
|
||||
if (index === -1) {
|
||||
selectedRows.value.push(row)
|
||||
} else {
|
||||
selectedRows.value.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// Actions
|
||||
const actions = [
|
||||
[{
|
||||
key: 'completed',
|
||||
label: 'Completed',
|
||||
icon: 'i-heroicons-check'
|
||||
}], [{
|
||||
key: 'uncompleted',
|
||||
label: 'In Progress',
|
||||
icon: 'i-heroicons-arrow-path'
|
||||
}]
|
||||
]
|
||||
|
||||
// Filters
|
||||
const todoStatus = [{
|
||||
key: 'uncompleted',
|
||||
label: 'In Progress',
|
||||
value: false
|
||||
}, {
|
||||
key: 'completed',
|
||||
label: 'Completed',
|
||||
value: true
|
||||
}]
|
||||
|
||||
const search = ref('')
|
||||
const selectedStatus = ref([])
|
||||
const searchStatus = computed(() => {
|
||||
if (selectedStatus.value?.length === 0) {
|
||||
return ''
|
||||
}
|
||||
|
||||
if (selectedStatus?.value?.length > 1) {
|
||||
return `?completed=${selectedStatus.value[0].value}&completed=${selectedStatus.value[1].value}`
|
||||
}
|
||||
|
||||
return `?completed=${selectedStatus.value[0].value}`
|
||||
})
|
||||
|
||||
const resetFilters = () => {
|
||||
search.value = ''
|
||||
selectedStatus.value = []
|
||||
}
|
||||
|
||||
// Pagination
|
||||
const page = ref(1)
|
||||
const pageCount = ref(10)
|
||||
const pageTotal = ref(200) // This value should be dynamic coming from the API
|
||||
const pageFrom = computed(() => (page.value - 1) * pageCount.value + 1)
|
||||
const pageTo = computed(() => Math.min(page.value * pageCount.value, pageTotal.value))
|
||||
|
||||
// Data
|
||||
const { data: todos, pending } = await useLazyAsyncData('todos', () => $fetch<{
|
||||
id: number
|
||||
title: string
|
||||
completed: string
|
||||
}[]>(`https://jsonplaceholder.typicode.com/todos${searchStatus.value}`, {
|
||||
query: {
|
||||
q: search.value,
|
||||
'_page': page.value,
|
||||
'_limit': pageCount.value
|
||||
}
|
||||
}), {
|
||||
default: () => [],
|
||||
watch: [page, search, searchStatus, pageCount]
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UCard
|
||||
class="w-full"
|
||||
:ui="{
|
||||
base: '',
|
||||
ring: '',
|
||||
divide: 'divide-y divide-gray-200 dark:divide-gray-700',
|
||||
header: { padding: 'px-4 py-5' },
|
||||
body: { padding: '', base: 'divide-y divide-gray-200 dark:divide-gray-700' },
|
||||
footer: { padding: 'p-4' }
|
||||
}"
|
||||
>
|
||||
<template #header>
|
||||
<h2 class="font-semibold text-xl text-gray-900 dark:text-white leading-tight">
|
||||
Todos
|
||||
</h2>
|
||||
</template>
|
||||
|
||||
<!-- Filters -->
|
||||
<div class="flex items-center justify-between gap-3 px-4 py-3">
|
||||
<UInput v-model="search" icon="i-heroicons-magnifying-glass-20-solid" placeholder="Search..." />
|
||||
|
||||
<USelectMenu v-model="selectedStatus" :options="todoStatus" multiple placeholder="Status" class="w-40" />
|
||||
</div>
|
||||
|
||||
<!-- Header and Action buttons -->
|
||||
<div class="flex justify-between items-center w-full px-4 py-3">
|
||||
<div class="flex items-center gap-1.5">
|
||||
<span class="text-sm leading-5">Rows per page:</span>
|
||||
|
||||
<USelect
|
||||
v-model="pageCount"
|
||||
:options="[3, 5, 10, 20, 30, 40]"
|
||||
class="me-2 w-20"
|
||||
size="xs"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-1.5 items-center">
|
||||
<UDropdown v-if="selectedRows.length > 1" :items="actions" :ui="{ width: 'w-36' }">
|
||||
<UButton
|
||||
icon="i-heroicons-chevron-down"
|
||||
trailing
|
||||
color="gray"
|
||||
size="xs"
|
||||
>
|
||||
Mark as
|
||||
</UButton>
|
||||
</UDropdown>
|
||||
|
||||
<USelectMenu v-model="selectedColumns" :options="columns" multiple>
|
||||
<UButton
|
||||
icon="i-heroicons-view-columns"
|
||||
color="gray"
|
||||
size="xs"
|
||||
>
|
||||
Columns
|
||||
</UButton>
|
||||
</USelectMenu>
|
||||
|
||||
<UButton
|
||||
icon="i-heroicons-funnel"
|
||||
color="gray"
|
||||
size="xs"
|
||||
:disabled="search === '' && selectedStatus.length === 0"
|
||||
@click="resetFilters"
|
||||
>
|
||||
Reset
|
||||
</UButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Table -->
|
||||
<UTable
|
||||
v-model="selectedRows"
|
||||
:rows="todos"
|
||||
:columns="columnsTable"
|
||||
:loading="pending"
|
||||
sort-asc-icon="i-heroicons-arrow-up"
|
||||
sort-desc-icon="i-heroicons-arrow-down"
|
||||
class="w-full"
|
||||
:ui="{ td: { base: 'max-w-[0] truncate' } }"
|
||||
@select="select"
|
||||
>
|
||||
<template #completed-data="{ row }">
|
||||
<UBadge size="xs" :label="row.completed ? 'Completed' : 'In Progress'" :color="row.completed ? 'emerald' : 'orange'" variant="subtle" />
|
||||
</template>
|
||||
|
||||
<template #actions-data="{ row }">
|
||||
<UButton
|
||||
v-if="!row.completed"
|
||||
icon="i-heroicons-check"
|
||||
size="2xs"
|
||||
color="emerald"
|
||||
variant="outline"
|
||||
:ui="{ rounded: 'rounded-full' }"
|
||||
square
|
||||
/>
|
||||
|
||||
<UButton
|
||||
v-else
|
||||
icon="i-heroicons-arrow-path"
|
||||
size="2xs"
|
||||
color="orange"
|
||||
variant="outline"
|
||||
:ui="{ rounded: 'rounded-full' }"
|
||||
square
|
||||
/>
|
||||
</template>
|
||||
</UTable>
|
||||
|
||||
<!-- Number of rows & Pagination -->
|
||||
<template #footer>
|
||||
<div class="flex flex-wrap justify-between items-center">
|
||||
<div>
|
||||
<span class="text-sm leading-5">
|
||||
Showing
|
||||
<span class="font-medium">{{ pageFrom }}</span>
|
||||
to
|
||||
<span class="font-medium">{{ pageTo }}</span>
|
||||
of
|
||||
<span class="font-medium">{{ pageTotal }}</span>
|
||||
results
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<UPagination
|
||||
v-model="page"
|
||||
:page-count="pageCount"
|
||||
:total="pageTotal"
|
||||
:ui="{
|
||||
wrapper: 'flex items-center gap-1',
|
||||
rounded: '!rounded-full min-w-[32px] justify-center',
|
||||
default: {
|
||||
activeButton: {
|
||||
variant: 'outline'
|
||||
}
|
||||
}
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</UCard>
|
||||
</template>
|
||||
43
docs/components/content/examples/TableExampleBasic.vue
Normal file
43
docs/components/content/examples/TableExampleBasic.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<script setup>
|
||||
const people = [{
|
||||
id: 1,
|
||||
name: 'Lindsay Walton',
|
||||
title: 'Front-end Developer',
|
||||
email: 'lindsay.walton@example.com',
|
||||
role: 'Member'
|
||||
}, {
|
||||
id: 2,
|
||||
name: 'Courtney Henry',
|
||||
title: 'Designer',
|
||||
email: 'courtney.henry@example.com',
|
||||
role: 'Admin'
|
||||
}, {
|
||||
id: 3,
|
||||
name: 'Tom Cook',
|
||||
title: 'Director of Product',
|
||||
email: 'tom.cook@example.com',
|
||||
role: 'Member'
|
||||
}, {
|
||||
id: 4,
|
||||
name: 'Whitney Francis',
|
||||
title: 'Copywriter',
|
||||
email: 'whitney.francis@example.com',
|
||||
role: 'Admin'
|
||||
}, {
|
||||
id: 5,
|
||||
name: 'Leonard Krasner',
|
||||
title: 'Senior Designer',
|
||||
email: 'leonard.krasner@example.com',
|
||||
role: 'Owner'
|
||||
}, {
|
||||
id: 6,
|
||||
name: 'Floyd Miles',
|
||||
title: 'Principal Designer',
|
||||
email: 'floyd.miles@example.com',
|
||||
role: 'Member'
|
||||
}]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UTable :rows="people" />
|
||||
</template>
|
||||
48
docs/components/content/examples/TableExampleClickable.vue
Normal file
48
docs/components/content/examples/TableExampleClickable.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<script setup>
|
||||
const people = [{
|
||||
id: 1,
|
||||
name: 'Lindsay Walton',
|
||||
title: 'Front-end Developer',
|
||||
email: 'lindsay.walton@example.com',
|
||||
role: 'Member'
|
||||
}, {
|
||||
id: 2,
|
||||
name: 'Courtney Henry',
|
||||
title: 'Designer',
|
||||
email: 'courtney.henry@example.com',
|
||||
role: 'Admin'
|
||||
}, {
|
||||
id: 3,
|
||||
name: 'Tom Cook',
|
||||
title: 'Director of Product',
|
||||
email: 'tom.cook@example.com',
|
||||
role: 'Member'
|
||||
}, {
|
||||
id: 4,
|
||||
name: 'Whitney Francis',
|
||||
title: 'Copywriter',
|
||||
email: 'whitney.francis@example.com',
|
||||
role: 'Admin'
|
||||
}, {
|
||||
id: 5,
|
||||
name: 'Leonard Krasner',
|
||||
title: 'Senior Designer',
|
||||
email: 'leonard.krasner@example.com',
|
||||
role: 'Owner'
|
||||
}]
|
||||
|
||||
function select (row) {
|
||||
const index = selected.value.findIndex((item) => item.id === row.id)
|
||||
if (index === -1) {
|
||||
selected.value.push(row)
|
||||
} else {
|
||||
selected.value.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
const selected = ref([people[1]])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UTable v-model="selected" :rows="people" @select="select" />
|
||||
</template>
|
||||
59
docs/components/content/examples/TableExampleColumns.vue
Normal file
59
docs/components/content/examples/TableExampleColumns.vue
Normal file
@@ -0,0 +1,59 @@
|
||||
<script setup>
|
||||
const columns = [{
|
||||
key: 'id',
|
||||
label: 'ID'
|
||||
}, {
|
||||
key: 'name',
|
||||
label: 'User name'
|
||||
}, {
|
||||
key: 'title',
|
||||
label: 'Job position'
|
||||
}, {
|
||||
key: 'email',
|
||||
label: 'Email'
|
||||
}, {
|
||||
key: 'role'
|
||||
}]
|
||||
|
||||
const people = [{
|
||||
id: 1,
|
||||
name: 'Lindsay Walton',
|
||||
title: 'Front-end Developer',
|
||||
email: 'lindsay.walton@example.com',
|
||||
role: 'Member'
|
||||
}, {
|
||||
id: 2,
|
||||
name: 'Courtney Henry',
|
||||
title: 'Designer',
|
||||
email: 'courtney.henry@example.com',
|
||||
role: 'Admin'
|
||||
}, {
|
||||
id: 3,
|
||||
name: 'Tom Cook',
|
||||
title: 'Director of Product',
|
||||
email: 'tom.cook@example.com',
|
||||
role: 'Member'
|
||||
}, {
|
||||
id: 4,
|
||||
name: 'Whitney Francis',
|
||||
title: 'Copywriter',
|
||||
email: 'whitney.francis@example.com',
|
||||
role: 'Admin'
|
||||
}, {
|
||||
id: 5,
|
||||
name: 'Leonard Krasner',
|
||||
title: 'Senior Designer',
|
||||
email: 'leonard.krasner@example.com',
|
||||
role: 'Owner'
|
||||
}, {
|
||||
id: 6,
|
||||
name: 'Floyd Miles',
|
||||
title: 'Principal Designer',
|
||||
email: 'floyd.miles@example.com',
|
||||
role: 'Member'
|
||||
}]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UTable :columns="columns" :rows="people" />
|
||||
</template>
|
||||
@@ -0,0 +1,68 @@
|
||||
<script setup>
|
||||
const columns = [{
|
||||
key: 'id',
|
||||
label: 'ID'
|
||||
}, {
|
||||
key: 'name',
|
||||
label: 'Name'
|
||||
}, {
|
||||
key: 'title',
|
||||
label: 'Title'
|
||||
}, {
|
||||
key: 'email',
|
||||
label: 'Email'
|
||||
}, {
|
||||
key: 'role',
|
||||
label: 'Role'
|
||||
}]
|
||||
|
||||
const selectedColumns = ref([...columns])
|
||||
|
||||
const people = [{
|
||||
id: 1,
|
||||
name: 'Lindsay Walton',
|
||||
title: 'Front-end Developer',
|
||||
email: 'lindsay.walton@example.com',
|
||||
role: 'Member'
|
||||
}, {
|
||||
id: 2,
|
||||
name: 'Courtney Henry',
|
||||
title: 'Designer',
|
||||
email: 'courtney.henry@example.com',
|
||||
role: 'Admin'
|
||||
}, {
|
||||
id: 3,
|
||||
name: 'Tom Cook',
|
||||
title: 'Director of Product',
|
||||
email: 'tom.cook@example.com',
|
||||
role: 'Member'
|
||||
}, {
|
||||
id: 4,
|
||||
name: 'Whitney Francis',
|
||||
title: 'Copywriter',
|
||||
email: 'whitney.francis@example.com',
|
||||
role: 'Admin'
|
||||
}, {
|
||||
id: 5,
|
||||
name: 'Leonard Krasner',
|
||||
title: 'Senior Designer',
|
||||
email: 'leonard.krasner@example.com',
|
||||
role: 'Owner'
|
||||
}, {
|
||||
id: 6,
|
||||
name: 'Floyd Miles',
|
||||
title: 'Principal Designer',
|
||||
email: 'floyd.miles@example.com',
|
||||
role: 'Member'
|
||||
}]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="flex px-3 py-3.5 border-b border-gray-200 dark:border-gray-700">
|
||||
<USelectMenu v-model="selectedColumns" :options="columns" multiple placeholder="Columns" />
|
||||
</div>
|
||||
|
||||
<UTable :columns="selectedColumns" :rows="people" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,64 @@
|
||||
<script setup>
|
||||
const columns = [{
|
||||
key: 'id',
|
||||
label: 'ID'
|
||||
}, {
|
||||
key: 'name',
|
||||
label: 'Name',
|
||||
sortable: true
|
||||
}, {
|
||||
key: 'title',
|
||||
label: 'Title',
|
||||
sortable: true
|
||||
}, {
|
||||
key: 'email',
|
||||
label: 'Email',
|
||||
sortable: true,
|
||||
direction: 'desc'
|
||||
}, {
|
||||
key: 'role',
|
||||
label: 'Role'
|
||||
}]
|
||||
|
||||
const people = [{
|
||||
id: 1,
|
||||
name: 'Lindsay Walton',
|
||||
title: 'Front-end Developer',
|
||||
email: 'lindsay.walton@example.com',
|
||||
role: 'Member'
|
||||
}, {
|
||||
id: 2,
|
||||
name: 'Courtney Henry',
|
||||
title: 'Designer',
|
||||
email: 'courtney.henry@example.com',
|
||||
role: 'Admin'
|
||||
}, {
|
||||
id: 3,
|
||||
name: 'Tom Cook',
|
||||
title: 'Director of Product',
|
||||
email: 'tom.cook@example.com',
|
||||
role: 'Member'
|
||||
}, {
|
||||
id: 4,
|
||||
name: 'Whitney Francis',
|
||||
title: 'Copywriter',
|
||||
email: 'whitney.francis@example.com',
|
||||
role: 'Admin'
|
||||
}, {
|
||||
id: 5,
|
||||
name: 'Leonard Krasner',
|
||||
title: 'Senior Designer',
|
||||
email: 'leonard.krasner@example.com',
|
||||
role: 'Owner'
|
||||
}, {
|
||||
id: 6,
|
||||
name: 'Floyd Miles',
|
||||
title: 'Principal Designer',
|
||||
email: 'floyd.miles@example.com',
|
||||
role: 'Member'
|
||||
}]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UTable :columns="columns" :rows="people" :sort="{ column: 'title' }" />
|
||||
</template>
|
||||
30
docs/components/content/examples/TableExampleEmptySlot.vue
Normal file
30
docs/components/content/examples/TableExampleEmptySlot.vue
Normal file
@@ -0,0 +1,30 @@
|
||||
<script setup>
|
||||
const columns = [{
|
||||
key: 'name',
|
||||
label: 'Name'
|
||||
}, {
|
||||
key: 'title',
|
||||
label: 'Title'
|
||||
}, {
|
||||
key: 'email',
|
||||
label: 'Email'
|
||||
}, {
|
||||
key: 'role',
|
||||
label: 'Role'
|
||||
}, {
|
||||
key: 'actions'
|
||||
}]
|
||||
|
||||
const people = []
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UTable :rows="people" :columns="columns">
|
||||
<template #empty-state>
|
||||
<div class="flex flex-col items-center justify-center py-6 gap-3">
|
||||
<span class="italic text-sm">No one here!</span>
|
||||
<UButton label="Add people" />
|
||||
</div>
|
||||
</template>
|
||||
</UTable>
|
||||
</template>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user