mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-15 12:39:35 +01:00
Compare commits
164 Commits
v3.0.0-alp
...
v3.0.0-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d54fd3e2d | ||
|
|
f85b0985bd | ||
|
|
c902a40f7c | ||
|
|
1a54ab231b | ||
|
|
9d0f8617b2 | ||
|
|
23493af406 | ||
|
|
582fe87d70 | ||
|
|
c957bbf9a1 | ||
|
|
965e1aacaf | ||
|
|
1ba2e185b2 | ||
|
|
53afc40481 | ||
|
|
5c2c55ff08 | ||
|
|
39a3d2592c | ||
|
|
ee4c33cb1a | ||
|
|
d5dba0ebc9 | ||
|
|
a3dbf7c27d | ||
|
|
a3cf25f5cd | ||
|
|
02c8988a7a | ||
|
|
046785359e | ||
|
|
85b8553893 | ||
|
|
5288f87e0b | ||
|
|
25a71aa3ae | ||
|
|
a3bae03a20 | ||
|
|
01ce7e2d14 | ||
|
|
11a3f03a7f | ||
|
|
0531211ee5 | ||
|
|
039788a044 | ||
|
|
9aa6812423 | ||
|
|
3107039b56 | ||
|
|
c79acc15b0 | ||
|
|
15b411de4a | ||
|
|
410b7db201 | ||
|
|
5a443944ae | ||
|
|
82ade16fd0 | ||
|
|
af736b0c6a | ||
|
|
30ba53e20b | ||
|
|
4e482750cb | ||
|
|
01bf99eec8 | ||
|
|
446a9f7d31 | ||
|
|
638808c32c | ||
|
|
6a81db2b9c | ||
|
|
1f71d74899 | ||
|
|
cc50ef6ccd | ||
|
|
4344e36664 | ||
|
|
cc523a3d23 | ||
|
|
d7981ab2d5 | ||
|
|
697994e15d | ||
|
|
18b2c51282 | ||
|
|
a68f57c5d2 | ||
|
|
2050bed050 | ||
|
|
9bf93575a7 | ||
|
|
5c19c79350 | ||
|
|
fd5a529565 | ||
|
|
61389b8b5a | ||
|
|
ef7ecd242f | ||
|
|
41dc11ceef | ||
|
|
00b3c86584 | ||
|
|
8c88912a8f | ||
|
|
0128c1c9e0 | ||
|
|
254bf3a65f | ||
|
|
5ac25b5a84 | ||
|
|
71e98a4024 | ||
|
|
561fcd0b19 | ||
|
|
1c4bae8c86 | ||
|
|
0903e80b03 | ||
|
|
fae9895836 | ||
|
|
f19308d401 | ||
|
|
2f19136fd8 | ||
|
|
0201a3de75 | ||
|
|
c770ae124e | ||
|
|
a18ad84edf | ||
|
|
64f85a029f | ||
|
|
d4653e3c02 | ||
|
|
546a82c4c9 | ||
|
|
e878115a73 | ||
|
|
91da9aa83a | ||
|
|
9759320438 | ||
|
|
4f05b1aac9 | ||
|
|
ffba108291 | ||
|
|
5550d184bb | ||
|
|
c8cd06e92d | ||
|
|
b326a14fb0 | ||
|
|
5183582a90 | ||
|
|
ac54c7523c | ||
|
|
4c0bdf38fc | ||
|
|
c223281763 | ||
|
|
7f09299de5 | ||
|
|
6510e1e47d | ||
|
|
2202d05119 | ||
|
|
7eea62899c | ||
|
|
f66e272b63 | ||
|
|
23550c2263 | ||
|
|
d6179912de | ||
|
|
78be40a286 | ||
|
|
c2d777625f | ||
|
|
e1d385a175 | ||
|
|
1b3c919222 | ||
|
|
0f37aca317 | ||
|
|
7f64198a70 | ||
|
|
6f8087f44b | ||
|
|
6974f23645 | ||
|
|
f3f4edae28 | ||
|
|
7302a846a9 | ||
|
|
2c99bb80c7 | ||
|
|
607792ea25 | ||
|
|
1b6dda1ea9 | ||
|
|
6520790ff7 | ||
|
|
ad8db69990 | ||
|
|
242ff3b0ed | ||
|
|
e931880671 | ||
|
|
82d63446a1 | ||
|
|
9b4694f8d9 | ||
|
|
4c5a4fb526 | ||
|
|
6fb426fc17 | ||
|
|
fdaff6630f | ||
|
|
0285bf33fa | ||
|
|
5efae599b6 | ||
|
|
908f2b569a | ||
|
|
52b561dbed | ||
|
|
34ec90c974 | ||
|
|
194f3b6f03 | ||
|
|
2e17fb68de | ||
|
|
babfcdcb02 | ||
|
|
2fc43d66d5 | ||
|
|
d9967f5e28 | ||
|
|
cef16cd49d | ||
|
|
0b86f4315e | ||
|
|
bfb9b5200c | ||
|
|
aa3b38fc39 | ||
|
|
ae33adb900 | ||
|
|
f97d2e3b88 | ||
|
|
473194fbaf | ||
|
|
33fb2cad0b | ||
|
|
8d3f0fdc39 | ||
|
|
3167fda517 | ||
|
|
7ebd8d813d | ||
|
|
b40b73129c | ||
|
|
93ea5b958e | ||
|
|
76db00db7a | ||
|
|
3445078cab | ||
|
|
f179f8588a | ||
|
|
5a6a165a8d | ||
|
|
7ee733e82b | ||
|
|
a0b8b93a5a | ||
|
|
52e2a4d68f | ||
|
|
efd104a10f | ||
|
|
d8d56d909b | ||
|
|
d5f9cc27a4 | ||
|
|
db9ac5778f | ||
|
|
e73f38d1d1 | ||
|
|
206366a70e | ||
|
|
88a5a7055d | ||
|
|
b2f68dcf81 | ||
|
|
edad9b7f5c | ||
|
|
c5a8914483 | ||
|
|
57f4d613e6 | ||
|
|
c186169562 | ||
|
|
31b8c56ff7 | ||
|
|
cc1e32edf5 | ||
|
|
9fc42bab2e | ||
|
|
1acf99390d | ||
|
|
bf45094f89 | ||
|
|
eaddb8cb33 | ||
|
|
51de839aca |
@@ -2,11 +2,6 @@ name: "🐛 Bug report (v3)"
|
||||
description: Report a bug to help us improve the module (v3 only).
|
||||
labels: ["triage", "bug", "v3"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
> [!IMPORTANT]
|
||||
> As Nuxt UI v3 is currently in alpha, we recommend thorough testing before using it in production environments. We're actively working on stabilization and welcome feedback from early adopters to improve the library.
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
@@ -49,7 +44,7 @@ body:
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Reproduction
|
||||
description: Please provide a reproduction link. 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.
|
||||
description: Please provide a reproduction link using the Nuxt template https://codesandbox.io/p/devbox/nuxt-ui3-n3sxks or the Vue template https://codesandbox.io/p/devbox/nuxt-ui3-vue-4h5gqn. 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://github.com/my/reproduction
|
||||
validations:
|
||||
required: true
|
||||
2
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -28,7 +28,7 @@ body:
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
placeholder: v2.8.0
|
||||
placeholder: v2.20.0
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
||||
20
.github/ISSUE_TEMPLATE/feature-request-v3.yml
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature-request-v3.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
name: "🚀 Feature request (v3)"
|
||||
description: Suggest an idea or enhancement for the module (v3 only).
|
||||
labels: ["triage", "enhancement", "v3"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before requesting a feature, please make sure that you have read through our [v3 documentation](https://ui3.nuxt.dev/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
|
||||
- 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.
|
||||
9
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
9
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
@@ -6,15 +6,6 @@ body:
|
||||
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: dropdown
|
||||
id: version
|
||||
attributes:
|
||||
label: For what version of Nuxt UI are you suggesting this?
|
||||
options:
|
||||
- v2.x
|
||||
- v3.0.0-alpha.x
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
|
||||
14
.github/ISSUE_TEMPLATE/question-v3.yml
vendored
Normal file
14
.github/ISSUE_TEMPLATE/question-v3.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
name: "💬 Question (v3)"
|
||||
description: Ask a question about the module (v3 only).
|
||||
labels: ["question", "v3"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before asking a question, please make sure that you have read through our [v3 documentation](https://ui3.nuxt.dev/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
validations:
|
||||
required: true
|
||||
9
.github/ISSUE_TEMPLATE/question.yml
vendored
9
.github/ISSUE_TEMPLATE/question.yml
vendored
@@ -6,15 +6,6 @@ body:
|
||||
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: dropdown
|
||||
id: version
|
||||
attributes:
|
||||
label: For what version of Nuxt UI are you asking this question?
|
||||
options:
|
||||
- v2.x
|
||||
- v3.0.0-alpha.x
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
|
||||
57
.github/workflows/docs.yml
vendored
Normal file
57
.github/workflows/docs.yml
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
name: docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- v3
|
||||
pull_request:
|
||||
branches:
|
||||
- v3
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
environment:
|
||||
name: ${{ github.ref == 'refs/heads/v3' && 'production' || 'preview' }}
|
||||
url: ${{ steps.deploy.outputs.deployment-url }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest] # macos-latest, windows-latest
|
||||
node: [22]
|
||||
|
||||
env:
|
||||
NUXT_GITHUB_TOKEN: ${{ secrets.NUXT_GITHUB_TOKEN }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Install node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
cache: pnpm
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Prepare build
|
||||
run: pnpm run dev:prepare
|
||||
|
||||
- name: Build application
|
||||
run: pnpm run docs:build
|
||||
|
||||
- name: Deploy to NuxtHub
|
||||
uses: nuxt-hub/action@v1
|
||||
id: deploy
|
||||
with:
|
||||
project-key: ui-7eg3
|
||||
directory: docs/dist
|
||||
@@ -1,4 +1,4 @@
|
||||
name: ci-v3
|
||||
name: module
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -9,7 +9,7 @@ on:
|
||||
- v3
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
permissions:
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest] # macos-latest, windows-latest
|
||||
node: [20]
|
||||
node: [22]
|
||||
|
||||
env:
|
||||
NUXT_GITHUB_TOKEN: ${{ secrets.NUXT_GITHUB_TOKEN }}
|
||||
53
.github/workflows/playground.yml
vendored
Normal file
53
.github/workflows/playground.yml
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
name: playground
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- v3
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
environment:
|
||||
name: ${{ github.ref == 'refs/heads/v3' && 'production' || 'preview' }}
|
||||
url: ${{ steps.deploy.outputs.deployment-url }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest] # macos-latest, windows-latest
|
||||
node: [22]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Install node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
cache: pnpm
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Prepare build
|
||||
run: pnpm run dev:prepare
|
||||
|
||||
- name: Build application
|
||||
run: pnpm run dev:build
|
||||
env:
|
||||
NITRO_PRESET: cloudflare-pages
|
||||
|
||||
- name: Deploy to NuxtHub
|
||||
uses: nuxt-hub/action@v1
|
||||
id: deploy
|
||||
with:
|
||||
project-key: ui3-playground-pb9b
|
||||
directory: playground/dist
|
||||
52
CHANGELOG.md
52
CHANGELOG.md
@@ -1,5 +1,57 @@
|
||||
# Changelog
|
||||
|
||||
## [3.0.0-alpha.11](https://github.com/nuxt/ui/compare/v3.0.0-alpha.10...v3.0.0-alpha.11) (2025-01-13)
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **Modal/Popover/Slideover:** rename `prevent-close` to `dismissible` + uniformize docs
|
||||
|
||||
### Features
|
||||
|
||||
* **Badge:** rework sizes ([d9967f5](https://github.com/nuxt/ui/commit/d9967f5e282d41f4000d5451efed7254b4c1608c))
|
||||
* **CommandPalette:** add `autofocus` prop ([#2942](https://github.com/nuxt/ui/issues/2942)) ([1b3c919](https://github.com/nuxt/ui/commit/1b3c919222a4002d84dd968f93bcf9d615e412bc))
|
||||
* **locale:** add Danish language ([#2952](https://github.com/nuxt/ui/issues/2952)) ([e1d385a](https://github.com/nuxt/ui/commit/e1d385a17545f8091c8d2459842fe4c39b8c9399))
|
||||
* **locale:** add Estonian language ([#3036](https://github.com/nuxt/ui/issues/3036)) ([01bf99e](https://github.com/nuxt/ui/commit/01bf99eec8c2fd0e3dbe1271be152844e401287a))
|
||||
* **locale:** add Finnish language ([#3013](https://github.com/nuxt/ui/issues/3013)) ([c770ae1](https://github.com/nuxt/ui/commit/c770ae124e626682935475dc6a164aacd1408c01))
|
||||
* **locale:** add Greek language ([#2975](https://github.com/nuxt/ui/issues/2975)) ([b326a14](https://github.com/nuxt/ui/commit/b326a14fb0e62edc8e55599c16f934f54f95aa42))
|
||||
* **locale:** add Indonesian language ([#3024](https://github.com/nuxt/ui/issues/3024)) ([a18ad84](https://github.com/nuxt/ui/commit/a18ad84edfe6b3f444d379f24defeecb63e5cdb9))
|
||||
* **locale:** add Swedish language ([#3012](https://github.com/nuxt/ui/issues/3012)) ([0201a3d](https://github.com/nuxt/ui/commit/0201a3de757db426c877ef2761de8e9d7493983e))
|
||||
* **locale:** add Thai language ([#2980](https://github.com/nuxt/ui/issues/2980)) ([c8cd06e](https://github.com/nuxt/ui/commit/c8cd06e92dab208271ab7b7f6806793eea1e8969))
|
||||
* **locale:** add Ukrainian language ([#2908](https://github.com/nuxt/ui/issues/2908)) ([5efae59](https://github.com/nuxt/ui/commit/5efae599b642e65ec8ccaf2361b69abe993a0173))
|
||||
* **locale:** add Viet language ([#2986](https://github.com/nuxt/ui/issues/2986)) ([ffba108](https://github.com/nuxt/ui/commit/ffba108291f321471650ca9060ea264f41482648))
|
||||
* **module:** allow `tv` customization through `app.config` ([#2938](https://github.com/nuxt/ui/issues/2938)) ([30ba53e](https://github.com/nuxt/ui/commit/30ba53e20b3b91909c2c8162f35b13b6ad305d13))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Accordion/Collapsible/NavigationMenu/Tabs:** define `unmountOnHide` default ([4344e36](https://github.com/nuxt/ui/commit/4344e366647e9618c21fe800b43d2b4ae2611226))
|
||||
* **Avatar:** bind `$attrs` on `AvatarFallback` ([#2933](https://github.com/nuxt/ui/issues/2933)) ([7f64198](https://github.com/nuxt/ui/commit/7f64198a70104436f39f2f9d8527df0508fd84f6))
|
||||
* **Badge:** reduce radius on `sm` size ([f97d2e3](https://github.com/nuxt/ui/commit/f97d2e3b88d1ba9be5f7e2916c6502e38ac4d4c1))
|
||||
* **CommandPalette/SelectMenu:** missing translations ([#3057](https://github.com/nuxt/ui/issues/3057)) ([d5dba0e](https://github.com/nuxt/ui/commit/d5dba0ebc98594906ef1d9428da11d44317b70fc))
|
||||
* **components:** enable pointer events on menus ([#2881](https://github.com/nuxt/ui/issues/2881)) ([f85b098](https://github.com/nuxt/ui/commit/f85b0985bdd6f51aff41acc6f86dd02db9832b24))
|
||||
* **defineShortcuts:** handle extract when using `onSelect` or `onClick` ([#2896](https://github.com/nuxt/ui/issues/2896)) ([2e17fb6](https://github.com/nuxt/ui/commit/2e17fb68dee7e7bb27750c816d27b62249a1247b))
|
||||
* **DropdownMenu/ContextMenu:** correct bindings of `checkbox` items ([#2921](https://github.com/nuxt/ui/issues/2921)) ([4c5a4fb](https://github.com/nuxt/ui/commit/4c5a4fb5265c36a39e551b8ee43b86e9ebd3d064))
|
||||
* **FormField:** restore `eager-validation` prop behavior ([#3031](https://github.com/nuxt/ui/issues/3031)) ([41dc11c](https://github.com/nuxt/ui/commit/41dc11ceefd8f505fbc5214fe61f12483b0da4a2))
|
||||
* **InputMenu:** removing `tag` does not change `modelValue` ([#3054](https://github.com/nuxt/ui/issues/3054)) ([5a44394](https://github.com/nuxt/ui/commit/5a443944ae622c8f4a893e0a18a80026ea9c1fe0))
|
||||
* **locale:** improve Traditional Chinese translation ([#3051](https://github.com/nuxt/ui/issues/3051)) ([5c2c55f](https://github.com/nuxt/ui/commit/5c2c55ff08fbc16c869ad382e5fe5ac9fcc791de))
|
||||
* **Modal/Popover/Slideover:** rename `prevent-close` to `dismissible` + uniformize docs ([6fb426f](https://github.com/nuxt/ui/commit/6fb426fc17d6d524e7d0503c2c8f3610f60b954d))
|
||||
* **NavigationMenu:** `arrow` styles after `reka-ui` migration ([9759320](https://github.com/nuxt/ui/commit/97593204384669c479b85932024317a300ce29d8))
|
||||
* **NavigationMenu:** highlight border on children only with `vertical` orientation ([e931880](https://github.com/nuxt/ui/commit/e93188067172d357a7724f937aeec70a0dabe611))
|
||||
* **NavigationMenu:** remove `w-full` on root slot ([ef7ecd2](https://github.com/nuxt/ui/commit/ef7ecd242f4550838dbe3a45e33855afff89f506)), closes [#3000](https://github.com/nuxt/ui/issues/3000)
|
||||
* **NavigationMenu:** unbind link on collapsible trigger with `vertical` orientation ([82d6344](https://github.com/nuxt/ui/commit/82d63446a12445accbca9131a83806994631761b))
|
||||
* **SelectMenu:** handle `resetSearchTermOnBlur` manually ([#3082](https://github.com/nuxt/ui/issues/3082)) ([c902a40](https://github.com/nuxt/ui/commit/c902a40f7c0ce5ceb4624bbe2bbdfa09c87f7c75))
|
||||
* **Stepper:** correct item `value` type ([4f05b1a](https://github.com/nuxt/ui/commit/4f05b1aac9af096cdc9404395d25d2261522a1db))
|
||||
* **Stepper:** wrong `item` in `title` & `description` slots ([473194f](https://github.com/nuxt/ui/commit/473194fbaf2a9d21e2acb67d16715c412528d7d2)), closes [#2888](https://github.com/nuxt/ui/issues/2888)
|
||||
* **templates:** allow any string in colors autocomplete ([5183582](https://github.com/nuxt/ui/commit/5183582a90c0d86bd986ef0f280bc58e740c6458)), closes [#2143](https://github.com/nuxt/ui/issues/2143)
|
||||
* **templates:** infer variants types in generated theme ([2c99bb8](https://github.com/nuxt/ui/commit/2c99bb80c72fdbde9cd2ff3ad7caae0be632b864))
|
||||
* **unplugin:** invalid url schema on windows ([#2899](https://github.com/nuxt/ui/issues/2899)) ([9b4694f](https://github.com/nuxt/ui/commit/9b4694f8d9b0fc244e805a7bfb2795d5131f7d18))
|
||||
* **vue:** head injection ([#2929](https://github.com/nuxt/ui/issues/2929)) ([7302a84](https://github.com/nuxt/ui/commit/7302a846a9c394373c47def12dca00274e58f269))
|
||||
|
||||
### Reverts
|
||||
|
||||
* Revert "chore(deps): update `typescript`" ([3107039](https://github.com/nuxt/ui/commit/3107039b560cef973c117a251e4407ca5e615a72))
|
||||
* Revert "chore(deps): update `@nuxt/module-builder`" ([c79acc1](https://github.com/nuxt/ui/commit/c79acc15b00f23b189821ebe2f4430e900cac34f))
|
||||
* Revert "build: remove `cjs` support" ([15b411d](https://github.com/nuxt/ui/commit/15b411de4a6a7d322a3dea5703a5a5464c4e709a))
|
||||
|
||||
## [3.0.0-alpha.10](https://github.com/nuxt/ui/compare/v3.0.0-alpha.9...v3.0.0-alpha.10) (2024-12-09)
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
We're thrilled to introduce Nuxt UI v3, a significant upgrade to our UI library that delivers extensive improvements and robust new capabilities. This major update harnesses the combined strengths of [Reka UI](https://reka-ui.com/), [Tailwind CSS v4](https://tailwindcss.com/docs/v4-beta), and [Tailwind Variants](https://www.tailwind-variants.org/) to offer developers an unparalleled set of tools for creating sophisticated, accessible, and highly performant user interfaces.
|
||||
|
||||
> [!NOTE]
|
||||
> You are on the `v3` development branch, check out the [dev branch](https://github.com/nuxt/ui) for Nuxt UI v2.
|
||||
> You are on the `v3` development branch, check out the [dev branch](https://github.com/nuxt/ui/tree/dev) for Nuxt UI v2.
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -74,11 +74,18 @@ export default defineConfig({
|
||||
|
||||
```ts [main.ts]
|
||||
import { createApp } from 'vue'
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import ui from '@nuxt/ui/vue-plugin'
|
||||
import App from './App.vue'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
const router = createRouter({
|
||||
routes: [],
|
||||
history: createWebHistory()
|
||||
})
|
||||
|
||||
app.use(router)
|
||||
app.use(ui)
|
||||
|
||||
app.mount('#app')
|
||||
|
||||
@@ -32,6 +32,10 @@ export default defineCommand({
|
||||
content: {
|
||||
type: 'boolean',
|
||||
description: 'Create a content component (with --pro).'
|
||||
},
|
||||
template: {
|
||||
type: 'string',
|
||||
description: 'Only generate template.'
|
||||
}
|
||||
},
|
||||
async setup({ args }) {
|
||||
@@ -53,6 +57,10 @@ export default defineCommand({
|
||||
const path = resolve('.')
|
||||
|
||||
for (const template of Object.keys(templates)) {
|
||||
if (args.template && template !== args.template) {
|
||||
continue
|
||||
}
|
||||
|
||||
const { filename, contents } = templates[template](args)
|
||||
if (!contents) {
|
||||
continue
|
||||
@@ -70,6 +78,10 @@ export default defineCommand({
|
||||
consola.success(`🪄 Generated ${filePath}!`)
|
||||
}
|
||||
|
||||
if (args.template) {
|
||||
return
|
||||
}
|
||||
|
||||
const themePath = resolve(path, `src/theme/${args.prose ? 'prose/' : ''}${args.content ? 'content/' : ''}index.ts`)
|
||||
await appendFile(themePath, `export { default as ${camelCase(name)} } from './${kebabCase(name)}'`)
|
||||
await sortFile(themePath)
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"citty": "^0.1.6",
|
||||
"consola": "^3.2.3",
|
||||
"pathe": "^1.1.2",
|
||||
"consola": "^3.3.3",
|
||||
"pathe": "^2.0.1",
|
||||
"scule": "^1.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,10 +30,10 @@ const component = ({ name, primitive, pro, prose, content }) => {
|
||||
contents: primitive
|
||||
? `
|
||||
<script lang="ts">
|
||||
import { tv } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/${path}/${prose ? 'prose/' : ''}${content ? 'content/' : ''}${kebabName}'
|
||||
import { tv } from ${pro ? '#ui/utils/tv' : '../utils/tv'}
|
||||
|
||||
const appConfig = _appConfig as AppConfig & { ${key}: { ${prose ? 'prose: { ' : ''}${camelName}: Partial<typeof theme> } }${prose ? ' }' : ''}
|
||||
|
||||
@@ -57,7 +57,7 @@ export interface ${upperName}Slots {
|
||||
<script setup lang="ts">
|
||||
import { Primitive } from 'reka-ui'
|
||||
|
||||
const props = withDefaults(defineProps<${upperName}Props>(), { as: 'div' })
|
||||
const props = defineProps<${upperName}Props>()
|
||||
defineSlots<${upperName}Slots>()
|
||||
|
||||
const ui = ${camelName}()
|
||||
@@ -71,11 +71,12 @@ const ui = ${camelName}()
|
||||
`
|
||||
: `
|
||||
<script lang="ts">
|
||||
import { tv, type VariantProps } from 'tailwind-variants'
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { ${upperName}RootProps, ${upperName}RootEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/${path}/${prose ? 'prose/' : ''}${content ? 'content/' : ''}${kebabName}'
|
||||
import { tv } from ${pro ? '#ui/utils/tv' : '../utils/tv'}
|
||||
|
||||
const appConfig = _appConfig as AppConfig & { ${key}: { ${prose ? 'prose: { ' : ''}${camelName}: Partial<typeof theme> } }${prose ? ' }' : ''}
|
||||
|
||||
@@ -163,15 +164,19 @@ describe('${upperName}', () => {
|
||||
}
|
||||
}
|
||||
|
||||
const doc = ({ name, pro }) => {
|
||||
const docs = ({ name, pro, primitive }) => {
|
||||
const kebabName = kebabCase(name)
|
||||
const upperName = splitByCase(name).map(p => upperFirst(p)).join('')
|
||||
|
||||
return {
|
||||
filename: `docs/content/${pro ? 'pro' : '3.components'}/${kebabName}.md`,
|
||||
filename: `docs/content/3.components/${kebabName}.md`,
|
||||
contents: `---
|
||||
description:
|
||||
links: ${pro
|
||||
title: ${upperName}
|
||||
description: ''${pro
|
||||
? `
|
||||
module: ui-pro`
|
||||
: ''}
|
||||
links:${primitive
|
||||
? ''
|
||||
: `
|
||||
- label: ${upperName}
|
||||
@@ -190,19 +195,19 @@ links: ${pro
|
||||
|
||||
### Props
|
||||
|
||||
:component-props
|
||||
:component-props${pro ? '{pro}' : ''}
|
||||
|
||||
### Slots
|
||||
|
||||
:component-slots
|
||||
:component-slots${pro ? '{pro}' : ''}
|
||||
|
||||
### Emits
|
||||
|
||||
:component-emits
|
||||
:component-emits${pro ? '{pro}' : ''}
|
||||
|
||||
## Theme
|
||||
|
||||
:component-theme
|
||||
:component-theme${pro ? '{pro}' : ''}
|
||||
`
|
||||
}
|
||||
}
|
||||
@@ -212,5 +217,5 @@ export default {
|
||||
component,
|
||||
theme,
|
||||
test,
|
||||
doc
|
||||
docs
|
||||
}
|
||||
|
||||
@@ -43,9 +43,9 @@ const code = computed(() => {
|
||||
|
||||
const slotsTemplate = props.themeSlots
|
||||
? genPropValue(Object.keys(props.themeSlots).filter(key => key !== 'base').reduce((acc, key) => {
|
||||
acc[key] = genPropValue(props.themeSlots?.[key])
|
||||
return acc
|
||||
}, {} as Record<string, string>))
|
||||
acc[key] = genPropValue(props.themeSlots?.[key])
|
||||
return acc
|
||||
}, {} as Record<string, string>))
|
||||
: undefined
|
||||
|
||||
const extraTemplate = [
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { z } from 'zod'
|
||||
import * as z from 'zod'
|
||||
|
||||
export const arrayInputSchema = z.object({
|
||||
kind: z.literal('array'),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { z } from 'zod'
|
||||
import * as z from 'zod'
|
||||
|
||||
export const booleanInputSchema = z.literal('boolean').or(z.object({
|
||||
kind: z.literal('enum'),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { z } from 'zod'
|
||||
import * as z from 'zod'
|
||||
|
||||
export const numberInputSchema = z.literal('number')
|
||||
export type NumberInputSchema = z.infer<typeof numberInputSchema>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { z } from 'zod'
|
||||
import * as z from 'zod'
|
||||
|
||||
export const objectInputSchema = z.object({
|
||||
kind: z.literal('object'),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { z } from 'zod'
|
||||
import * as z from 'zod'
|
||||
|
||||
export const stringEnumInputSchema = z.object({
|
||||
kind: z.literal('enum'),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { z } from 'zod'
|
||||
import * as z from 'zod'
|
||||
|
||||
export const stringInputSchema = z.literal('string').or(z.string().transform(t => t.split('|').find(s => s.trim() === 'string')).pipe(z.string()))
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxt/ui": "latest",
|
||||
"knitwork": "^1.1.0",
|
||||
"nuxt": "^3.14.1592",
|
||||
"knitwork": "^1.2.0",
|
||||
"nuxt": "^3.15.1",
|
||||
"prettier": "^3.4.2",
|
||||
"zod": "^3.23.8"
|
||||
"zod": "^3.24.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,4 +151,6 @@ html[data-module="ui-pro"] .ui-only,
|
||||
html[data-module="ui"] .ui-pro-only {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Safelist (do not remove): [&>div]:*:my-0 [&>div]:*:w-full */
|
||||
</style>
|
||||
|
||||
@@ -18,6 +18,7 @@ onMounted(() => {
|
||||
indicator: 'bg-[var(--ui-bg)]',
|
||||
trigger: 'px-1 data-[state=active]:text-[var(--ui-text-highlighted)]'
|
||||
}"
|
||||
size="sm"
|
||||
@update:model-value="(framework = $event as string)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -12,16 +12,10 @@ const { module } = useSharedData()
|
||||
const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
|
||||
|
||||
const items = computed(() => props.links.map(({ icon, ...link }) => link))
|
||||
|
||||
defineShortcuts({
|
||||
meta_g: () => {
|
||||
window.open('https://github.com/nuxt/ui/tree/v3', '_blank')
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UHeader :ui="{ left: 'min-w-0', toggle: '-mr-1.5' }" mode="drawer" :menu="{ shouldScaleBackground: true }">
|
||||
<UHeader :ui="{ left: 'min-w-0' }" mode="drawer" :menu="{ shouldScaleBackground: true }">
|
||||
<template #left>
|
||||
<NuxtLink to="/" class="flex items-end gap-2 font-bold text-xl text-[var(--ui-text-highlighted)] min-w-0 focus-visible:outline-[var(--ui-primary)] shrink-0" aria-label="Nuxt UI">
|
||||
<LogoPro class="w-auto h-6 shrink-0 ui-pro-only" />
|
||||
@@ -62,7 +56,7 @@ defineShortcuts({
|
||||
<UButton
|
||||
color="neutral"
|
||||
variant="ghost"
|
||||
to="https://github.com/nuxt/ui"
|
||||
:to="`https://github.com/nuxt/${module}`"
|
||||
target="_blank"
|
||||
icon="i-simple-icons-github"
|
||||
aria-label="GitHub"
|
||||
@@ -76,11 +70,19 @@ defineShortcuts({
|
||||
<USeparator type="dashed" class="mt-4 mb-6" />
|
||||
|
||||
<div class="flex flex-col gap-2 w-[calc(100%+1.25rem)] mb-5.5 -mx-2.5">
|
||||
<ModuleSelect />
|
||||
<FrameworkSelect />
|
||||
<ModuleSelect />
|
||||
</div>
|
||||
|
||||
<UContentNavigation :navigation="navigation" highlight />
|
||||
<UContentNavigation :navigation="navigation" highlight :ui="{ linkTrailingBadge: 'font-semibold uppercase' }">
|
||||
<template #link-title="{ link }">
|
||||
<span class="inline-flex items-center gap-0.5">
|
||||
{{ link.title }}
|
||||
|
||||
<sup v-if="link.module === 'ui-pro' && link.path.startsWith('/components')" class="text-[8px] font-medium text-(--ui-primary)">PRO</sup>
|
||||
</span>
|
||||
</template>
|
||||
</UContentNavigation>
|
||||
</template>
|
||||
</UHeader>
|
||||
</template>
|
||||
|
||||
@@ -14,7 +14,11 @@ onMounted(() => {
|
||||
:items="modules"
|
||||
:content="false"
|
||||
color="neutral"
|
||||
:ui="{ indicator: 'bg-[var(--ui-bg)]', trigger: 'px-1 data-[state=active]:text-[var(--ui-text-highlighted)]' }"
|
||||
:ui="{
|
||||
indicator: 'bg-[var(--ui-bg)]',
|
||||
trigger: 'px-1 data-[state=active]:text-[var(--ui-text-highlighted)]'
|
||||
}"
|
||||
size="sm"
|
||||
@update:model-value="(module = $event as string)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { upperFirst, camelCase, kebabCase } from 'scule'
|
||||
import { hash } from 'ohash'
|
||||
import { CalendarDate } from '@internationalized/date'
|
||||
import * as theme from '#build/ui'
|
||||
import * as themePro from '#build/ui-pro'
|
||||
import { get, set } from '#ui/utils'
|
||||
|
||||
interface Cast {
|
||||
@@ -40,6 +41,9 @@ const castMap: Record<string, Cast> = {
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
pro?: boolean
|
||||
prose?: boolean
|
||||
prefix?: string
|
||||
/** Override the slug taken from the route */
|
||||
slug?: string
|
||||
class?: any
|
||||
@@ -71,14 +75,32 @@ const props = defineProps<{
|
||||
* A list of line numbers to highlight in the code block
|
||||
*/
|
||||
highlights?: number[]
|
||||
/**
|
||||
* Whether to add overflow-hidden to wrapper
|
||||
*/
|
||||
overflowHidden?: boolean
|
||||
}>()
|
||||
|
||||
const route = useRoute()
|
||||
const { $prettier } = useNuxtApp()
|
||||
|
||||
const camelName = camelCase(props.slug ?? route.params.slug?.[route.params.slug.length - 1] ?? '')
|
||||
const name = `U${upperFirst(camelName)}`
|
||||
const component = defineAsyncComponent(() => import(`#ui/components/${upperFirst(camelName)}.vue`))
|
||||
const name = `${props.prose ? 'Prose' : 'U'}${upperFirst(camelName)}`
|
||||
const component = defineAsyncComponent(() => {
|
||||
if (props.pro) {
|
||||
if (props.prefix) {
|
||||
return import(`#ui-pro/components/${props.prefix}/${upperFirst(camelName)}.vue`)
|
||||
}
|
||||
|
||||
if (props.prose) {
|
||||
return import(`#ui-pro/components/prose/${upperFirst(camelName)}.vue`)
|
||||
}
|
||||
|
||||
return import(`#ui-pro/components/${upperFirst(camelName)}.vue`)
|
||||
}
|
||||
|
||||
return import(`#ui/components/${upperFirst(camelName)}.vue`)
|
||||
})
|
||||
|
||||
const componentProps = reactive({
|
||||
...Object.fromEntries(Object.entries(props.props || {}).map(([key, value]) => {
|
||||
@@ -104,7 +126,7 @@ function setComponentProp(name: string, value: any) {
|
||||
set(componentProps, name, value)
|
||||
}
|
||||
|
||||
const componentTheme = (theme as any)[camelName]
|
||||
const componentTheme = ((props.pro ? props.prose ? themePro.prose : themePro : theme) as any)[camelName]
|
||||
const meta = await fetchComponentMeta(name as any)
|
||||
|
||||
function mapKeys(obj: object, parentKey = ''): any {
|
||||
@@ -127,16 +149,18 @@ const options = computed(() => {
|
||||
const propItems = get(props.items, key, [])
|
||||
const items = propItems.length
|
||||
? propItems.map((item: any) => ({
|
||||
value: item,
|
||||
label: item
|
||||
}))
|
||||
value: item,
|
||||
label: String(item)
|
||||
}))
|
||||
: prop?.type === 'boolean' || prop?.type === 'boolean | undefined'
|
||||
? [{ value: true, label: 'true' }, { value: false, label: 'false' }]
|
||||
: Object.keys(componentTheme?.variants?.[key] || {}).map(variant => ({
|
||||
value: variant,
|
||||
label: variant,
|
||||
chip: key.toLowerCase().endsWith('color') ? { color: variant } : undefined
|
||||
}))
|
||||
: Object.keys(componentTheme?.variants?.[key] || {}).filter((variant) => {
|
||||
return variant !== 'true' && variant !== 'false'
|
||||
}).map(variant => ({
|
||||
value: variant,
|
||||
label: variant,
|
||||
chip: key.toLowerCase().endsWith('color') ? { color: variant } : undefined
|
||||
}))
|
||||
|
||||
return {
|
||||
name: key,
|
||||
@@ -150,6 +174,30 @@ const options = computed(() => {
|
||||
const code = computed(() => {
|
||||
let code = ''
|
||||
|
||||
if (props.prose) {
|
||||
code += `\`\`\`mdc
|
||||
::${camelName}`
|
||||
|
||||
const proseProps = Object.entries(componentProps).map(([key, value]) => {
|
||||
if (value === undefined || value === null || value === '' || props.hide?.includes(key)) {
|
||||
return
|
||||
}
|
||||
|
||||
return `${key}="${value}"`
|
||||
}).filter(Boolean).join(' ')
|
||||
|
||||
if (proseProps.length) {
|
||||
code += `{${proseProps}}`
|
||||
}
|
||||
|
||||
code += `
|
||||
${props.slots?.default}
|
||||
::
|
||||
\`\`\``
|
||||
|
||||
return code
|
||||
}
|
||||
|
||||
if (props.collapse) {
|
||||
code += `::code-collapse
|
||||
`
|
||||
@@ -191,23 +239,23 @@ const code = computed(() => {
|
||||
}
|
||||
|
||||
const prop = meta?.meta?.props?.find((prop: any) => prop.name === key)
|
||||
const propDefault = prop && (prop.default ?? prop.tags?.find(tag => tag.name === 'defaultValue')?.text ?? componentTheme?.defaultVariants?.[prop.name])
|
||||
const name = kebabCase(key)
|
||||
|
||||
if (typeof value === 'boolean') {
|
||||
if (value && prop?.default === 'true') {
|
||||
if (value && (propDefault === 'true' || propDefault === '`true`' || propDefault === true)) {
|
||||
continue
|
||||
}
|
||||
if (!value && (!prop?.default || prop.default === 'false')) {
|
||||
if (!value && (!propDefault || propDefault === 'false' || propDefault === '`false`' || propDefault === false)) {
|
||||
continue
|
||||
}
|
||||
|
||||
code += value ? ` ${name}` : ` :${key}="false"`
|
||||
code += value ? ` ${name}` : ` :${name}="false"`
|
||||
} else if (typeof value === 'object') {
|
||||
const parsedValue = !props.external?.includes(key) ? json5.stringify(value, null, 2).replace(/,([ |\t\n]+[}|\])])/g, '$1') : key
|
||||
|
||||
code += ` :${name}="${parsedValue}"`
|
||||
} else {
|
||||
const propDefault = prop && (prop.default ?? prop.tags?.find(tag => tag.name === 'defaultValue')?.text ?? componentTheme?.defaultVariants?.[prop.name])
|
||||
if (propDefault === value) {
|
||||
continue
|
||||
}
|
||||
@@ -225,7 +273,7 @@ const code = computed(() => {
|
||||
code += `
|
||||
<template #${key}>
|
||||
${value}
|
||||
</template>`
|
||||
</template>\n`
|
||||
}
|
||||
}
|
||||
code += (Object.keys(props.slots).length > 1 ? '\n' : '') + `</${name}>`
|
||||
@@ -305,7 +353,7 @@ const { data: ast } = await useAsyncData(`component-code-${name}-${hash({ props:
|
||||
</USelect>
|
||||
<UInput
|
||||
v-else
|
||||
:type="option.type?.includes('number') ? 'number' : 'text'"
|
||||
:type="option.type?.includes('number') && typeof getComponentProp(option.name) === 'number' ? 'number' : 'text'"
|
||||
:model-value="getComponentProp(option.name)"
|
||||
color="neutral"
|
||||
variant="soft"
|
||||
@@ -316,7 +364,7 @@ const { data: ast } = await useAsyncData(`component-code-${name}-${hash({ props:
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div v-if="component" class="flex justify-center border border-b-0 border-[var(--ui-border-muted)] relative p-4 z-[1]" :class="[!options.length && 'rounded-t-[calc(var(--ui-radius)*1.5)]', props.class]">
|
||||
<div v-if="component" class="flex justify-center border border-b-0 border-[var(--ui-border-muted)] relative p-4 z-[1]" :class="[!options.length && 'rounded-t-[calc(var(--ui-radius)*1.5)]', props.class, { 'overflow-hidden': props.overflowHidden }]">
|
||||
<component :is="component" v-bind="{ ...componentProps, ...componentEvents }">
|
||||
<template v-for="slot in Object.keys(slots || {})" :key="slot" #[slot]>
|
||||
<slot :name="slot" mdc-unwrap="p">
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import { upperFirst, camelCase } from 'scule'
|
||||
|
||||
const props = defineProps<{
|
||||
prose?: boolean
|
||||
}>()
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const camelName = camelCase(route.params.slug?.[route.params.slug.length - 1] ?? '')
|
||||
const name = `U${upperFirst(camelName)}`
|
||||
const name = props.prose ? `Prose${upperFirst(camelName)}` : `U${upperFirst(camelName)}`
|
||||
|
||||
const meta = await fetchComponentMeta(name as any)
|
||||
</script>
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
import { camelCase } from 'scule'
|
||||
import { useElementSize } from '@vueuse/core'
|
||||
import { get, set } from '#ui/utils'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
name: string
|
||||
class?: any
|
||||
/**
|
||||
* Whether to render the component in an iframe
|
||||
* @defaultValue false
|
||||
*/
|
||||
iframe?: boolean | { [key: string]: any }
|
||||
/**
|
||||
* Whether to display the component in a mobile-sized iframe viewport
|
||||
* @defaultValue false
|
||||
*/
|
||||
iframeMobile?: boolean
|
||||
props?: { [key: string]: any }
|
||||
/**
|
||||
* Whether to format the code with Prettier
|
||||
@@ -42,6 +53,10 @@ const props = withDefaults(defineProps<{
|
||||
* A list of line numbers to highlight in the code block
|
||||
*/
|
||||
highlights?: number[]
|
||||
/**
|
||||
* Whether to add overflow-hidden to wrapper
|
||||
*/
|
||||
overflowHidden?: boolean
|
||||
}>(), {
|
||||
preview: true,
|
||||
source: true
|
||||
@@ -49,9 +64,13 @@ const props = withDefaults(defineProps<{
|
||||
|
||||
const slots = defineSlots<{
|
||||
options(props?: {}): any
|
||||
code(props?: {}): any
|
||||
}>()
|
||||
|
||||
const el = ref<HTMLElement | null>(null)
|
||||
|
||||
const { $prettier } = useNuxtApp()
|
||||
const { width } = useElementSize(el)
|
||||
|
||||
const camelName = camelCase(props.name)
|
||||
|
||||
@@ -112,12 +131,18 @@ const optionsValues = ref(props.options?.reduce((acc, option) => {
|
||||
}
|
||||
return acc
|
||||
}, {} as Record<string, any>) || {})
|
||||
|
||||
const urlSearchParams = computed(() => new URLSearchParams({
|
||||
...optionsValues.value,
|
||||
...componentProps,
|
||||
width: Math.round(width.value).toString()
|
||||
}).toString())
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="my-5">
|
||||
<div ref="el" class="my-5">
|
||||
<template v-if="preview">
|
||||
<div class="border border-[var(--ui-border-muted)] relative z-[1]" :class="[{ 'border-b-0 rounded-t-[calc(var(--ui-radius)*1.5)]': props.source, 'rounded-[calc(var(--ui-radius)*1.5)]': !props.source }]">
|
||||
<div class="border border-[var(--ui-border-muted)] relative z-[1]" :class="[{ 'border-b-0 rounded-t-[calc(var(--ui-radius)*1.5)]': props.source, 'rounded-[calc(var(--ui-radius)*1.5)]': !props.source, 'overflow-hidden': props.overflowHidden }]">
|
||||
<div v-if="props.options?.length || !!slots.options" class="flex gap-4 p-4 border-b border-[var(--ui-border-muted)]">
|
||||
<slot name="options" />
|
||||
|
||||
@@ -169,12 +194,24 @@ const optionsValues = ref(props.options?.reduce((acc, option) => {
|
||||
</UFormField>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-center p-4" :class="props.class">
|
||||
<iframe
|
||||
v-if="iframe"
|
||||
v-bind="typeof iframe === 'object' ? iframe : {}"
|
||||
:src="`/examples/${name}?${urlSearchParams}`"
|
||||
class="relative w-full"
|
||||
:class="[props.class, !iframeMobile && 'lg:left-1/2 lg:-translate-x-1/2 lg:w-[1024px]']"
|
||||
/>
|
||||
<div v-else class="flex justify-center p-4" :class="props.class">
|
||||
<component :is="camelName" v-bind="{ ...componentProps, ...optionsValues }" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<MDCRenderer v-if="ast && props.source" :body="ast.body" :data="ast.data" class="[&_pre]:!rounded-t-none [&_div.my-5]:!mt-0" />
|
||||
<template v-if="props.source">
|
||||
<div v-if="!!slots.code" class="[&_pre]:!rounded-t-none [&_div.my-5]:!mt-0">
|
||||
<slot name="code" />
|
||||
</div>
|
||||
<MDCRenderer v-else-if="ast" :body="ast.body" :data="ast.data" class="[&_pre]:!rounded-t-none [&_div.my-5]:!mt-0" />
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -5,8 +5,10 @@ import * as theme from '#build/ui'
|
||||
import * as themePro from '#build/ui-pro'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
name?: string
|
||||
ignore?: string[]
|
||||
pro?: boolean
|
||||
prose?: boolean
|
||||
}>(), {
|
||||
ignore: () => [
|
||||
'activeClass',
|
||||
@@ -25,17 +27,18 @@ const props = withDefaults(defineProps<{
|
||||
'exactQuery',
|
||||
'exactHash',
|
||||
'external',
|
||||
'onClick'
|
||||
'onClick',
|
||||
'viewTransition'
|
||||
]
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const camelName = camelCase(route.params.slug?.[route.params.slug.length - 1] ?? '')
|
||||
const name = `U${upperFirst(camelName)}`
|
||||
const camelName = camelCase(props.name ?? route.params.slug?.[route.params.slug.length - 1] ?? '')
|
||||
const componentName = props.prose ? `Prose${upperFirst(camelName)}` : `U${upperFirst(camelName)}`
|
||||
|
||||
const componentTheme = ((props.pro ? themePro : theme) as any)[camelName]
|
||||
const meta = await fetchComponentMeta(name as any)
|
||||
const componentTheme = ((props.pro ? props.prose ? themePro.prose : themePro : theme) as any)[camelName]
|
||||
const meta = await fetchComponentMeta(componentName as any)
|
||||
|
||||
const metaProps: ComputedRef<ComponentMeta['props']> = computed(() => {
|
||||
if (!meta?.meta?.props?.length) {
|
||||
@@ -45,7 +48,17 @@ const metaProps: ComputedRef<ComponentMeta['props']> = computed(() => {
|
||||
return meta.meta.props.filter((prop) => {
|
||||
return !props.ignore?.includes(prop.name)
|
||||
}).map((prop) => {
|
||||
prop.default = prop.default ?? prop.tags?.find(tag => tag.name === 'defaultValue')?.text ?? componentTheme?.defaultVariants?.[prop.name]
|
||||
if (prop.default) {
|
||||
prop.default = prop.default.replace(' as never', '').replace(/^"(.*)"$/, '\'$1\'')
|
||||
} else {
|
||||
const tag = prop.tags?.find(tag => tag.name === 'defaultValue')?.text
|
||||
if (tag) {
|
||||
prop.default = tag
|
||||
} else if (componentTheme?.defaultVariants?.[prop.name]) {
|
||||
prop.default = typeof componentTheme?.defaultVariants?.[prop.name] === 'string' ? `'${componentTheme?.defaultVariants?.[prop.name]}'` : componentTheme?.defaultVariants?.[prop.name]
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error - Type is not correct
|
||||
prop.type = !prop.type.startsWith('boolean') && prop.schema?.kind === 'enum' && Object.keys(prop.schema.schema)?.length ? Object.values(prop.schema.schema).map(schema => schema?.type ? schema.type : schema).join(' | ') : prop.type
|
||||
return prop
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import { upperFirst, camelCase } from 'scule'
|
||||
|
||||
const props = defineProps<{
|
||||
prose?: boolean
|
||||
}>()
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const camelName = camelCase(route.params.slug?.[route.params.slug.length - 1] ?? '')
|
||||
const name = `U${upperFirst(camelName)}`
|
||||
const name = props.prose ? `Prose${upperFirst(camelName)}` : `U${upperFirst(camelName)}`
|
||||
|
||||
const meta = await fetchComponentMeta(name as any)
|
||||
</script>
|
||||
|
||||
@@ -6,18 +6,23 @@ import * as themePro from '#build/ui-pro'
|
||||
|
||||
const props = defineProps<{
|
||||
pro?: boolean
|
||||
prose?: boolean
|
||||
slug?: string
|
||||
extra?: string[]
|
||||
}>()
|
||||
|
||||
const route = useRoute()
|
||||
const { framework } = useSharedData()
|
||||
|
||||
const name = camelCase(route.params.slug?.[route.params.slug.length - 1] ?? '')
|
||||
const name = camelCase(props.slug ?? route.params.slug?.[route.params.slug.length - 1] ?? '')
|
||||
|
||||
const strippedCompoundVariants = ref(false)
|
||||
|
||||
const computedTheme = computed(() => props.pro ? props.prose ? themePro.prose : themePro : theme)
|
||||
|
||||
const strippedTheme = computed(() => {
|
||||
const strippedTheme = {
|
||||
...((props.pro ? themePro : theme) as any)[name]
|
||||
...(computedTheme.value as any)[name]
|
||||
}
|
||||
|
||||
if (strippedTheme?.compoundVariants) {
|
||||
@@ -54,10 +59,21 @@ const strippedTheme = computed(() => {
|
||||
})
|
||||
|
||||
const component = computed(() => {
|
||||
const baseKey = props.pro ? 'uiPro' : 'ui'
|
||||
|
||||
const content = props.prose
|
||||
? { prose: { [name]: strippedTheme.value } }
|
||||
: { [name]: strippedTheme.value }
|
||||
|
||||
if (props.extra?.length) {
|
||||
props.extra.forEach((extra) => {
|
||||
const target = props.prose ? content.prose! : content
|
||||
target[extra as keyof typeof target] = computedTheme.value[extra as keyof typeof computedTheme.value]
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
[props.pro ? 'uiPro' : 'ui']: {
|
||||
[name]: strippedTheme.value
|
||||
}
|
||||
[baseKey]: content
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -8,28 +8,26 @@ const props = withDefaults(defineProps<{
|
||||
})
|
||||
|
||||
function getEmojiFlag(locale: string): string {
|
||||
// Map language codes to default country codes
|
||||
const languageToCountry: Record<string, string> = {
|
||||
en: 'gb',
|
||||
ar: 'sa',
|
||||
cs: 'cz',
|
||||
zh: 'cn',
|
||||
da: 'dk',
|
||||
el: 'gr',
|
||||
en: 'gb',
|
||||
ja: 'jp',
|
||||
ko: 'kr'
|
||||
ko: 'kr',
|
||||
sv: 'se',
|
||||
uk: 'ua',
|
||||
vi: 'vn',
|
||||
zh: 'cn'
|
||||
}
|
||||
|
||||
// Get base language code before any region specifier
|
||||
const baseLanguage = locale.split('-')[0]?.toLowerCase() || locale
|
||||
|
||||
// Use mapped country code or extract from locale if it contains a region
|
||||
const countryCode = languageToCountry[baseLanguage] || locale.replace(/^.*-/, '').slice(0, 2)
|
||||
|
||||
return countryCode
|
||||
return countryCode.toUpperCase()
|
||||
.split('')
|
||||
.map((char: string) => {
|
||||
const codePoint = char.toUpperCase().codePointAt(0)
|
||||
return codePoint ? String.fromCodePoint(0x1F1A5 + codePoint) : ''
|
||||
})
|
||||
.map(char => String.fromCodePoint(0x1F1A5 + char.charCodeAt(0)))
|
||||
.join('')
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
const open = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UDrawer v-model:open="open" :dismissible="false" :ui="{ header: 'flex items-center justify-between' }">
|
||||
<UButton label="Open" color="neutral" variant="subtle" trailing-icon="i-lucide-chevron-up" />
|
||||
|
||||
<template #header>
|
||||
<h2 class="text-[var(--ui-text-highlighted)] font-semibold">
|
||||
Drawer non-dismissible
|
||||
</h2>
|
||||
|
||||
<UButton color="neutral" variant="ghost" icon="i-lucide-x" @click="open = false" />
|
||||
</template>
|
||||
|
||||
<template #body>
|
||||
<Placeholder class="h-48" />
|
||||
</template>
|
||||
</UDrawer>
|
||||
</template>
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { z } from 'zod'
|
||||
import * as z from 'zod'
|
||||
import type { FormSubmitEvent } from '@nuxt/ui'
|
||||
|
||||
const schema = z.object({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { z } from 'zod'
|
||||
import * as z from 'zod'
|
||||
import type { FormSubmitEvent } from '@nuxt/ui'
|
||||
|
||||
const schema = z.object({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { z } from 'zod'
|
||||
import * as z from 'zod'
|
||||
import type { FormSubmitEvent } from '@nuxt/ui'
|
||||
|
||||
const schema = z.object({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { z } from 'zod'
|
||||
import * as z from 'zod'
|
||||
import type { FormSubmitEvent } from '#ui/types'
|
||||
|
||||
const schema = z.object({
|
||||
|
||||
@@ -59,7 +59,7 @@ const items = [
|
||||
<template>
|
||||
<UNavigationMenu
|
||||
:items="items"
|
||||
class="justify-center"
|
||||
class="w-full justify-center"
|
||||
:ui="{
|
||||
viewport: 'sm:w-[var(--reka-navigation-menu-viewport-width)]',
|
||||
childList: 'sm:w-96',
|
||||
|
||||
@@ -19,7 +19,7 @@ const items = [
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UNavigationMenu :items="items" class="justify-center">
|
||||
<UNavigationMenu :items="items" class="w-full justify-center">
|
||||
<template #components-trailing>
|
||||
<UBadge label="44" variant="subtle" size="sm" />
|
||||
</template>
|
||||
|
||||
@@ -111,5 +111,5 @@ defineShortcuts({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UNavigationMenu v-model="active" :items="items" class="justify-center" />
|
||||
<UNavigationMenu v-model="active" :items="items" class="w-full justify-center" />
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
const open = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UPopover v-model:open="open" :dismissible="false" :ui="{ content: 'p-4' }">
|
||||
<UButton label="Open" color="neutral" variant="subtle" />
|
||||
|
||||
<template #content>
|
||||
<div class="flex items-center gap-4 mb-4">
|
||||
<h2 class="text-[var(--ui-text-highlighted)] font-semibold">
|
||||
Popover non-dismissible
|
||||
</h2>
|
||||
|
||||
<UButton color="neutral" variant="ghost" icon="i-lucide-x" @click="open = false" />
|
||||
</div>
|
||||
|
||||
<Placeholder class="size-full min-h-48" />
|
||||
</template>
|
||||
</UPopover>
|
||||
</template>
|
||||
@@ -15,13 +15,13 @@ export function useSharedData() {
|
||||
|
||||
const module = useCookie('nuxt-ui-module', { default: () => 'ui' })
|
||||
const modules = computed(() => [{
|
||||
label: 'nuxt/ui',
|
||||
label: 'UI',
|
||||
icon: 'i-lucide-box',
|
||||
value: 'ui',
|
||||
onSelect: () => module.value = 'ui'
|
||||
}, {
|
||||
label: 'nuxt/ui-pro',
|
||||
icon: 'i-lucide-boxes',
|
||||
label: 'UI Pro',
|
||||
icon: 'i-lucide-panels-top-left',
|
||||
value: 'ui-pro',
|
||||
disabled: framework.value === 'vue',
|
||||
onSelect: () => module.value = 'ui-pro'
|
||||
|
||||
@@ -12,12 +12,20 @@ const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
|
||||
<UPageAside>
|
||||
<template #top>
|
||||
<div class="flex flex-col gap-2 w-[calc(100%+1.25rem)] -mx-2.5">
|
||||
<ModuleSelect />
|
||||
<FrameworkSelect />
|
||||
<ModuleSelect />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<UContentNavigation :navigation="navigation" highlight />
|
||||
<UContentNavigation :navigation="navigation" highlight :ui="{ linkTrailingBadge: 'font-semibold uppercase' }">
|
||||
<template #link-title="{ link }">
|
||||
<span class="inline-flex items-center gap-0.5">
|
||||
{{ link.title }}
|
||||
|
||||
<sup v-if="link.module === 'ui-pro'" class="text-[8px] font-medium text-(--ui-primary)">PRO</sup>
|
||||
</span>
|
||||
</template>
|
||||
</UContentNavigation>
|
||||
</UPageAside>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -63,10 +63,11 @@ watch(page, () => {
|
||||
}
|
||||
}, { immediate: true })
|
||||
|
||||
const type = page.value?.path.includes('components') ? 'Vue Component ' : page.value?.path.includes('composables') ? 'Vue Composable ' : ''
|
||||
useSeoMeta({
|
||||
titleTemplate: `%s - Nuxt UI ${page.value.module === 'ui-pro' ? 'Pro' : ''} v3${page.value.framework === 'vue' ? ' for Vue' : ''}`,
|
||||
titleTemplate: `%s ${type}- Nuxt UI ${page.value.module === 'ui-pro' ? 'Pro' : ''} v3${page.value.framework === 'vue' ? ' for Vue' : ''}`,
|
||||
title: page.value.navigation?.title ? page.value.navigation.title : page.value.title,
|
||||
ogTitle: `${page.value.navigation?.title ? page.value.navigation.title : page.value.title} - Nuxt UI ${page.value.module === 'ui-pro' ? 'Pro' : ''} v3${page.value.framework === 'vue' ? ' for Vue' : ''}`,
|
||||
ogTitle: `${page.value.navigation?.title ? page.value.navigation.title : page.value.title} ${type}- Nuxt UI ${page.value.module === 'ui-pro' ? 'Pro' : ''} v3${page.value.framework === 'vue' ? ' for Vue' : ''}`,
|
||||
description: page.value.description,
|
||||
ogDescription: page.value.description
|
||||
})
|
||||
@@ -78,12 +79,12 @@ defineOgImageComponent('Docs', {
|
||||
const communityLinks = computed(() => [{
|
||||
icon: 'i-lucide-file-pen',
|
||||
label: 'Edit this page',
|
||||
to: `https://github.com/nuxt/ui/edit/v3/docs/content/${page?.value?.stem}.md`,
|
||||
to: `https://github.com/nuxt/${page.value?.module === 'ui-pro' ? 'ui-pro' : 'ui'}/edit/v3/docs/content/${page?.value?.stem}.md`,
|
||||
target: '_blank'
|
||||
}, {
|
||||
icon: 'i-lucide-star',
|
||||
label: 'Star on GitHub',
|
||||
to: 'https://github.com/nuxt/ui',
|
||||
to: `https://github.com/nuxt/${page.value?.module === 'ui-pro' ? 'ui-pro' : 'ui'}`,
|
||||
target: '_blank'
|
||||
}])
|
||||
|
||||
@@ -122,7 +123,7 @@ const communityLinks = computed(() => [{
|
||||
:key="link.label"
|
||||
color="neutral"
|
||||
variant="outline"
|
||||
target="_blank"
|
||||
:target="link.to.startsWith('http') ? '_blank' : undefined"
|
||||
v-bind="link"
|
||||
>
|
||||
<template v-if="link.avatar" #leading>
|
||||
|
||||
@@ -2,10 +2,20 @@
|
||||
const route = useRoute()
|
||||
|
||||
const name = route.params.slug?.[0]
|
||||
|
||||
const width = computed(() => route.query.width && Number.parseInt(route.query.width as string) > 0 ? `${Number.parseInt(route.query.width as string) - 2}px` : '864px')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="p-4 flex flex-col justify-center h-screen overflow-auto">
|
||||
<component :is="name" />
|
||||
<div class="example flex flex-col items-center h-screen">
|
||||
<component :is="name" v-bind="route.query" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@media (min-width: 1024px) {
|
||||
.example {
|
||||
--ui-container: v-bind(width);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -28,7 +28,7 @@ Nuxt UI v3 integrates the latest Tailwind CSS v4 beta (released Nov 21, 2024), b
|
||||
- **CSS-first configuration**: A reimagined developer experience where you customize and extend the framework directly in CSS instead of a JavaScript configuration file.
|
||||
- **Designed for the modern web**: Built on native cascade layers, wide-gamut colors, and including first-class support for modern CSS features like container queries, @starting-style, popovers, and more.
|
||||
|
||||
::note{to="https://tailwindcss.com/docs/v4-beta" target="_blank"}
|
||||
::note{to="https://tailwindcss.com/docs/v4-beta" target="_blank" aria-label="Tailwind CSS v4 beta documentation"}
|
||||
For a comprehensive overview of Tailwind CSS v4 beta features, read the **prerelease documentation**.
|
||||
::
|
||||
|
||||
@@ -58,7 +58,7 @@ Nuxt UI v3 offers significantly improved TypeScript integration, providing a sup
|
||||
- Leveraging Tailwind Variants for type-safe styling options
|
||||
- Customizable types for extended theme configurations
|
||||
|
||||
::note{to="/components/accordion#with-custom-slot"}
|
||||
::note{to="/components/accordion#with-custom-slot" aria-label="Accordion component with custom slot"}
|
||||
Check out an example of the Accordion component with auto-completion for props and slots.
|
||||
::
|
||||
|
||||
@@ -70,7 +70,7 @@ You can now use Nuxt UI in any Vue project without Nuxt by adding the Vite and V
|
||||
- **Theming System**: Full theming support with customizable colors, sizes, variants and more
|
||||
- **Developer Experience**: Complete TypeScript support with IntelliSense and auto-completion
|
||||
|
||||
::tip{to="/getting-started/installation/vue"}
|
||||
::tip{to="/getting-started/installation/vue" aria-label="Vue installation guide"}
|
||||
Learn how to install and configure Nuxt UI in a Vue project in the **Vue installation guide**.
|
||||
::
|
||||
|
||||
@@ -79,6 +79,7 @@ Learn how to install and configure Nuxt UI in a Vue project in the **Vue install
|
||||
We want to be transparent: migrating from Nuxt UI v2 to v3 will require significant effort. While we've maintained core concepts and components, Nuxt UI v3 has been rebuilt from the ground up, resulting in a new library with enhanced capabilities.
|
||||
|
||||
Key points to consider:
|
||||
|
||||
- A comprehensive migration guide will be available in the coming weeks.
|
||||
- Review the new documentation and components carefully before attempting to upgrade.
|
||||
- If you encounter any issues, please report them on our [GitHub repository](https://github.com/nuxt/ui/issues).
|
||||
|
||||
@@ -3,6 +3,10 @@ title: Installation
|
||||
description: 'Learn how to install and configure Nuxt UI in your Nuxt application.'
|
||||
framework: nuxt
|
||||
module: ui
|
||||
links:
|
||||
- label: Playground
|
||||
to: https://codesandbox.io/p/devbox/nuxt-ui3-n3sxks
|
||||
icon: i-lucide-codesandbox
|
||||
---
|
||||
|
||||
::callout{to="/getting-started/installation/vue" icon="i-logos-vue" class="hidden"}
|
||||
@@ -65,12 +69,13 @@ export default defineNuxtConfig({
|
||||
css: ['~/assets/css/main.css']
|
||||
})
|
||||
```
|
||||
|
||||
::
|
||||
|
||||
::callout{icon="i-simple-icons-visualstudiocode"}
|
||||
It's recommended to install the [Tailwind CSS IntelliSense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss) extension for VSCode and add the following settings:
|
||||
|
||||
```json [settings.json]
|
||||
```json [.vscode/settings.json]
|
||||
"files.associations": {
|
||||
"*.css": "tailwindcss"
|
||||
},
|
||||
@@ -99,12 +104,12 @@ The `App` component provides global configurations and is required for **Toast**
|
||||
|
||||
### Use our Nuxt Starter
|
||||
|
||||
Start your project with a Nuxt template with Nuxt UI v3 pre-configured by using our [Nuxt UI Starter](https://github.com/nuxt/starter/tree/ui3).
|
||||
Start your project using the [nuxt/starter#ui3](https://github.com/nuxt/starter/tree/ui3) template with Nuxt UI v3 pre-configured.
|
||||
|
||||
Create a new project locally by running the following command:
|
||||
|
||||
```bash [Terminal]
|
||||
npx nuxi@latest init -t ui3 <my-app>
|
||||
npx nuxi init -t ui3 <my-app>
|
||||
```
|
||||
|
||||
::note
|
||||
|
||||
@@ -3,6 +3,10 @@ title: Installation
|
||||
description: 'Learn how to install and configure Nuxt UI in your Vue application.'
|
||||
framework: vue
|
||||
module: ui
|
||||
links:
|
||||
- label: Playground
|
||||
to: https://codesandbox.io/p/devbox/nuxt-ui3-vue-4h5gqn
|
||||
icon: i-lucide-codesandbox
|
||||
---
|
||||
|
||||
::callout{to="/getting-started/installation/nuxt" icon="i-logos-nuxt-icon" class="hidden"}
|
||||
@@ -11,6 +15,8 @@ Looking for the **Nuxt** version?
|
||||
|
||||
## Setup
|
||||
|
||||
### Add to a Vue project
|
||||
|
||||
::steps{level="4"}
|
||||
|
||||
#### Install the Nuxt UI v3 alpha package
|
||||
@@ -68,17 +74,25 @@ Nuxt UI registers `unplugin-auto-import` and `unplugin-vue-components`, which wi
|
||||
auto-imports.d.ts
|
||||
components.d.ts
|
||||
```
|
||||
|
||||
::
|
||||
|
||||
#### Use the Nuxt UI Vue plugin in your `main.ts`
|
||||
|
||||
```ts [main.ts]{2,7}
|
||||
```ts [main.ts]{3,14}
|
||||
import { createApp } from 'vue'
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import ui from '@nuxt/ui/vue-plugin'
|
||||
import App from './App.vue'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
const router = createRouter({
|
||||
routes: [],
|
||||
history: createWebHistory()
|
||||
})
|
||||
|
||||
app.use(router)
|
||||
app.use(ui)
|
||||
|
||||
app.mount('#app')
|
||||
@@ -98,21 +112,29 @@ Import the CSS file in your `main.ts`.
|
||||
import './assets/main.css'
|
||||
|
||||
import { createApp } from 'vue'
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import ui from '@nuxt/ui/vue-plugin'
|
||||
import App from './App.vue'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
const router = createRouter({
|
||||
routes: [],
|
||||
history: createWebHistory()
|
||||
})
|
||||
|
||||
app.use(router)
|
||||
app.use(ui)
|
||||
|
||||
app.mount('#app')
|
||||
```
|
||||
|
||||
::
|
||||
|
||||
::callout{icon="i-simple-icons-visualstudiocode"}
|
||||
It's recommended to install the [Tailwind CSS IntelliSense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss) extension for VSCode and add the following settings:
|
||||
|
||||
```json [settings.json]
|
||||
```json [.vscode/settings.json]
|
||||
"files.associations": {
|
||||
"*.css": "tailwindcss"
|
||||
},
|
||||
@@ -139,6 +161,27 @@ The `App` component provides global configurations and is required for **Toast**
|
||||
|
||||
::
|
||||
|
||||
### Use our Vue starter
|
||||
|
||||
Start your project using the [nuxtlabs/nuxt-ui3-vue-starter](https://github.com/nuxtlabs/nuxt-ui3-vue-starter) template with Nuxt UI v3 pre-configured.
|
||||
|
||||
Create a new project locally by running the following command:
|
||||
|
||||
```bash [Terminal]
|
||||
npx nuxi init -t github:nuxtlabs/nuxt-ui3-vue-starter <my-app>
|
||||
```
|
||||
|
||||
::note
|
||||
The `<my-app>` argument is the name of the directory where the project will be created, replace it with your project name.
|
||||
::
|
||||
|
||||
Once the installation is complete, navigate into your project and start the development server:
|
||||
|
||||
```bash [Terminal]
|
||||
cd <my-app>
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
You can customize Nuxt UI by providing options in your `vite.config.ts`.
|
||||
|
||||
@@ -14,6 +14,7 @@ Tailwind CSS v4 takes a CSS-first configuration approach, you now customize your
|
||||
::module-only
|
||||
#ui
|
||||
:::div
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
@@ -36,10 +37,12 @@ Tailwind CSS v4 takes a CSS-first configuration approach, you now customize your
|
||||
--color-green-950: #052E16;
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
#ui-pro
|
||||
:::div
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui-pro";
|
||||
@@ -62,6 +65,7 @@ Tailwind CSS v4 takes a CSS-first configuration approach, you now customize your
|
||||
--color-green-950: #052E16;
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::
|
||||
|
||||
@@ -80,22 +84,26 @@ This can be useful when writing Tailwind classes in markdown files with [`@nuxt/
|
||||
::module-only
|
||||
#ui
|
||||
:::div
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
|
||||
@source "../content";
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
#ui-pro
|
||||
:::div
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui-pro";
|
||||
|
||||
@source "../content";
|
||||
```
|
||||
|
||||
:::
|
||||
::
|
||||
|
||||
@@ -110,22 +118,26 @@ You can use the `@plugin` directive to import Tailwind CSS plugins.
|
||||
::module-only
|
||||
#ui
|
||||
:::div
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
|
||||
@plugin "@tailwindcss/typography";
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
#ui-pro
|
||||
:::div
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui-pro";
|
||||
|
||||
@plugin "@tailwindcss/typography";
|
||||
```
|
||||
|
||||
:::
|
||||
::
|
||||
|
||||
@@ -172,6 +184,7 @@ export default defineAppConfig({
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
::
|
||||
|
||||
#vue
|
||||
@@ -197,6 +210,7 @@ export default defineConfig({
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
::
|
||||
|
||||
::
|
||||
@@ -240,6 +254,7 @@ export default defineNuxtConfig({
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
#vue
|
||||
@@ -267,6 +282,7 @@ export default defineConfig({
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
:::
|
||||
::
|
||||
|
||||
@@ -277,7 +293,8 @@ However, you can generate these classes using Tailwind's `@theme` directive, all
|
||||
|
||||
::module-only
|
||||
#ui
|
||||
:::div
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
@@ -296,10 +313,12 @@ However, you can generate these classes using Tailwind's `@theme` directive, all
|
||||
--color-primary-950: var(--ui-color-primary-950);
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
#ui-pro
|
||||
:::div
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui-pro";
|
||||
@@ -318,6 +337,7 @@ However, you can generate these classes using Tailwind's `@theme` directive, all
|
||||
--color-primary-950: var(--ui-color-primary-950);
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::
|
||||
|
||||
@@ -366,7 +386,8 @@ You can change which shade is used for each color on light and dark mode:
|
||||
|
||||
::module-only
|
||||
#ui
|
||||
:::div
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
@@ -379,10 +400,12 @@ You can change which shade is used for each color on light and dark mode:
|
||||
--ui-primary: var(--ui-color-primary-200);
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
#ui-pro
|
||||
:::div
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui-pro";
|
||||
@@ -395,6 +418,7 @@ You can change which shade is used for each color on light and dark mode:
|
||||
--ui-primary: var(--ui-color-primary-200);
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::
|
||||
|
||||
@@ -486,6 +510,7 @@ body {
|
||||
@apply antialiased text-[var(--ui-text)] bg-[var(--ui-bg)];
|
||||
}
|
||||
```
|
||||
|
||||
::
|
||||
|
||||
::tip
|
||||
@@ -493,7 +518,8 @@ You can customize these CSS variables to tailor the appearance of your applicati
|
||||
|
||||
::module-only
|
||||
#ui
|
||||
:::div
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
@@ -508,10 +534,12 @@ You can customize these CSS variables to tailor the appearance of your applicati
|
||||
--ui-border: var(--ui-color-neutral-900);
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
#ui-pro
|
||||
:::div
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui-pro";
|
||||
@@ -526,6 +554,7 @@ You can customize these CSS variables to tailor the appearance of your applicati
|
||||
--ui-border: var(--ui-color-neutral-900);
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::
|
||||
|
||||
@@ -550,7 +579,8 @@ You can customize the default radius value using the default Tailwind CSS variab
|
||||
|
||||
::module-only
|
||||
#ui
|
||||
:::div
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
@@ -559,10 +589,12 @@ You can customize the default radius value using the default Tailwind CSS variab
|
||||
--ui-radius: var(--radius-sm);
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
#ui-pro
|
||||
:::div
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui-pro";
|
||||
@@ -571,6 +603,7 @@ You can customize the default radius value using the default Tailwind CSS variab
|
||||
--ui-radius: var(--radius-sm);
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::
|
||||
|
||||
@@ -591,7 +624,8 @@ You can customize the default container width using the default Tailwind CSS var
|
||||
|
||||
::module-only
|
||||
#ui
|
||||
:::div
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
@@ -604,10 +638,12 @@ You can customize the default container width using the default Tailwind CSS var
|
||||
--ui-container: var(--container-8xl);
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
#ui-pro
|
||||
:::div
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui-pro";
|
||||
@@ -620,6 +656,7 @@ You can customize the default container width using the default Tailwind CSS var
|
||||
--ui-container: var(--container-8xl);
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::
|
||||
|
||||
@@ -758,6 +795,7 @@ You can explore the theme for each component in two ways:
|
||||
|
||||
- Check the `Theme` section in the documentation of each individual component.
|
||||
- Browse the source code directly in the GitHub repository at [`v3/src/theme`](https://github.com/nuxt/ui/tree/v3/src/theme).
|
||||
|
||||
::
|
||||
|
||||
### Config
|
||||
@@ -780,6 +818,7 @@ export default defineAppConfig({
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
::
|
||||
|
||||
#vue
|
||||
@@ -808,6 +847,7 @@ export default defineConfig({
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
::
|
||||
|
||||
::
|
||||
|
||||
@@ -34,7 +34,7 @@ props:
|
||||
::
|
||||
|
||||
::note
|
||||
You can use any name from the https://icones.js.org collection.
|
||||
You can use any name from the <https://icones.js.org> collection.
|
||||
::
|
||||
|
||||
### Component Props
|
||||
|
||||
@@ -28,7 +28,7 @@ props:
|
||||
::
|
||||
|
||||
::note
|
||||
You can use any name from the https://icones.js.org collection.
|
||||
You can use any name from the <https://icones.js.org> collection.
|
||||
::
|
||||
|
||||
### Component Props
|
||||
|
||||
@@ -16,6 +16,7 @@ Nuxt UI automatically registers the [`@nuxt/fonts`](https://github.com/nuxt/font
|
||||
::module-only
|
||||
#ui
|
||||
:::div
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
@@ -24,10 +25,12 @@ Nuxt UI automatically registers the [`@nuxt/fonts`](https://github.com/nuxt/font
|
||||
--font-sans: 'Public Sans', sans-serif;
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
#ui-pro
|
||||
:::div
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui-pro";
|
||||
@@ -36,6 +39,7 @@ Nuxt UI automatically registers the [`@nuxt/fonts`](https://github.com/nuxt/font
|
||||
--font-sans: 'Public Sans', sans-serif;
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::
|
||||
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
badge: New
|
||||
shadow: true
|
||||
|
||||
@@ -55,8 +55,10 @@ const locale = defineLocale({
|
||||
|
||||
::tip
|
||||
Look at the `code` parameter, there you need to pass the iso code of the language. Example:
|
||||
|
||||
* `hi` Hindi (language)
|
||||
* `de-AT`: German (language) as used in Austria (region)
|
||||
|
||||
::
|
||||
|
||||
### Dynamic locale
|
||||
|
||||
@@ -57,8 +57,10 @@ const locale = defineLocale({
|
||||
|
||||
::tip
|
||||
Look at the `code` parameter, there you need to pass the iso code of the language. Example:
|
||||
|
||||
* `hi` Hindi (language)
|
||||
* `de-AT`: German (language) as used in Austria (region)
|
||||
|
||||
::
|
||||
|
||||
### Dynamic locale
|
||||
@@ -91,12 +93,20 @@ bun add vue-i18n@10
|
||||
|
||||
#### Use the Vue I18n plugin in your `main.ts`
|
||||
|
||||
```ts [main.ts]{2,6-18,22}
|
||||
```ts [main.ts]{3,14-26,29}
|
||||
import { createApp } from 'vue'
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import { createI18n } from 'vue-i18n'
|
||||
import ui from '@nuxt/ui/vue-plugin'
|
||||
import App from './App.vue'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
const router = createRouter({
|
||||
routes: [],
|
||||
history: createWebHistory()
|
||||
})
|
||||
|
||||
const i18n = createI18n({
|
||||
legacy: false,
|
||||
locale: 'en',
|
||||
@@ -111,8 +121,7 @@ const i18n = createI18n({
|
||||
}
|
||||
})
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(router)
|
||||
app.use(i18n)
|
||||
app.use(ui)
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ props:
|
||||
---
|
||||
::
|
||||
|
||||
You can also pass all the props of the [Button](/components/button) component to customize it.
|
||||
You can pass any property from the [Button](/components/button) component to customize it.
|
||||
|
||||
::component-code
|
||||
---
|
||||
|
||||
@@ -11,13 +11,15 @@ links:
|
||||
|
||||
## Usage
|
||||
|
||||
::tip
|
||||
The Avatar uses the `NuxtImg` component when [`@nuxt/image`](https://github.com/nuxt/image) is installed, falling back to `img` otherwise.
|
||||
The Avatar uses the `<NuxtImg>` component when [`@nuxt/image`](https://github.com/nuxt/image) is installed, falling back to `img` otherwise.
|
||||
|
||||
::note
|
||||
You can pass any property from the HTML `<img>` element such as `alt`, `loading`, etc.
|
||||
::
|
||||
|
||||
### Src
|
||||
|
||||
Use the `src` prop to set the image URL. You can pass any property from HTML `<img>` element such as `alt`, `loading`, etc.
|
||||
Use the `src` prop to set the image URL.
|
||||
|
||||
::component-code
|
||||
---
|
||||
|
||||
@@ -62,7 +62,7 @@ Use the `size` prop to change the size of the Badge.
|
||||
::component-code
|
||||
---
|
||||
props:
|
||||
size: lg
|
||||
size: xl
|
||||
slots:
|
||||
default: Badge
|
||||
---
|
||||
|
||||
@@ -18,7 +18,7 @@ Use the `items` prop as an array of objects with the following properties:
|
||||
- `class?: any`{lang="ts-type"}
|
||||
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
|
||||
|
||||
You can also pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
|
||||
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
|
||||
|
||||
::component-code
|
||||
---
|
||||
|
||||
@@ -358,7 +358,7 @@ props:
|
||||
---
|
||||
::
|
||||
|
||||
You can also pass all the props of the [Button](/components/button) component to customize it.
|
||||
You can pass any property from the [Button](/components/button) component to customize it.
|
||||
|
||||
::component-code
|
||||
---
|
||||
|
||||
@@ -32,7 +32,7 @@ Use the `items` prop as an array of objects with the following properties:
|
||||
- `onSelect?(e: Event): void`{lang="ts-type"}
|
||||
- [`onUpdateChecked?(checked: boolean): void`{lang="ts-type"}](#with-checkbox-items)
|
||||
|
||||
You can also pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
|
||||
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
|
||||
|
||||
::component-code
|
||||
---
|
||||
@@ -104,7 +104,7 @@ slots:
|
||||
::
|
||||
|
||||
::note
|
||||
You can pass an array of arrays to the `items` prop to create separated groups of items.
|
||||
You can also pass an array of arrays to the `items` prop to create separated groups of items.
|
||||
::
|
||||
|
||||
::tip
|
||||
|
||||
@@ -243,6 +243,7 @@ export default defineNuxtConfig({
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
::
|
||||
|
||||
## Examples
|
||||
@@ -266,6 +267,21 @@ In this example, leveraging [`defineShortcuts`](/composables/define-shortcuts),
|
||||
This allows you to move the trigger outside of the Drawer or remove it entirely.
|
||||
::
|
||||
|
||||
### Prevent closing
|
||||
|
||||
Set the `dismissible` prop to `false` to prevent the Drawer from being closed when clicking outside of it or pressing escape.
|
||||
|
||||
::component-example
|
||||
---
|
||||
prettier: true
|
||||
name: 'drawer-dismissible-example'
|
||||
---
|
||||
::
|
||||
|
||||
::note
|
||||
In this example, the `header` slot is used to add a close button which is not done by default.
|
||||
::
|
||||
|
||||
### With footer slot
|
||||
|
||||
Use the `#footer` slot to add content after the Drawer's body.
|
||||
|
||||
@@ -32,7 +32,7 @@ Use the `items` prop as an array of objects with the following properties:
|
||||
- `onSelect?(e: Event): void`{lang="ts-type"}
|
||||
- [`onUpdateChecked?(checked: boolean): void`{lang="ts-type"}](#with-checkbox-items)
|
||||
|
||||
You can also pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
|
||||
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
|
||||
|
||||
::component-code
|
||||
---
|
||||
@@ -103,7 +103,7 @@ slots:
|
||||
::
|
||||
|
||||
::note
|
||||
You can pass an array of arrays to the `items` prop to create separated groups of items.
|
||||
You can also pass an array of arrays to the `items` prop to create separated groups of items.
|
||||
::
|
||||
|
||||
::tip
|
||||
|
||||
@@ -8,21 +8,30 @@ links:
|
||||
|
||||
## Usage
|
||||
|
||||
Use the Form component to validate form data using schema libraries such as [Zod](https://github.com/colinhacks/zod), [Yup](https://github.com/jquense/yup), [Joi](https://github.com/hapijs/joi), [Valibot](https://github.com/fabian-hiller/valibot), [Superstruct](https://github.com/ianstormtaylor/superstruct) or your own validation logic.
|
||||
Use the Form component to validate form data using schema libraries such as [Valibot](https://github.com/fabian-hiller/valibot), [Zod](https://github.com/colinhacks/zod), [Yup](https://github.com/jquense/yup), [Joi](https://github.com/hapijs/joi), [Superstruct](https://github.com/ianstormtaylor/superstruct) or your own validation logic.
|
||||
|
||||
It works with the [FormField](/components/form-field) component to display error messages around form elements automatically.
|
||||
|
||||
### Schema Validation
|
||||
|
||||
It requires two props:
|
||||
|
||||
- `state` - a reactive object holding the form's state.
|
||||
- `schema` - a schema object from a validation library like [Zod](https://github.com/colinhacks/zod), [Yup](https://github.com/jquense/yup), [Joi](https://github.com/hapijs/joi), [Valibot](https://github.com/fabian-hiller/valibot) or [Superstruct](https://github.com/ianstormtaylor/superstruct).
|
||||
- `schema` - a schema object from a validation library like [Valibot](https://github.com/fabian-hiller/valibot), [Zod](https://github.com/colinhacks/zod), [Yup](https://github.com/jquense/yup), [Joi](https://github.com/hapijs/joi) or [Superstruct](https://github.com/ianstormtaylor/superstruct).
|
||||
|
||||
::warning
|
||||
**No validation library is included** by default, ensure you **install the one you need**.
|
||||
::
|
||||
|
||||
::tabs
|
||||
::component-example{label="Valibot"}
|
||||
---
|
||||
name: 'form-example-valibot'
|
||||
props:
|
||||
class: 'w-60'
|
||||
---
|
||||
::
|
||||
|
||||
::component-example{label="Zod"}
|
||||
---
|
||||
name: 'form-example-zod'
|
||||
@@ -47,14 +56,6 @@ It requires two props:
|
||||
---
|
||||
::
|
||||
|
||||
::component-example{label="Valibot"}
|
||||
---
|
||||
name: 'form-example-valibot'
|
||||
props:
|
||||
class: 'w-60'
|
||||
---
|
||||
::
|
||||
|
||||
::component-example{label="Superstruct"}
|
||||
---
|
||||
name: 'form-example-superstruct'
|
||||
@@ -73,6 +74,7 @@ Nested validation rules are handled using dot notation. For example, a rule like
|
||||
Use the `validate` prop to apply your own validation logic.
|
||||
|
||||
The validation function must return a list of errors with the following attributes:
|
||||
|
||||
- `message` - the error message to display.
|
||||
- `name` - the `name` of the `FormField` to send the error to.
|
||||
|
||||
@@ -91,6 +93,7 @@ props:
|
||||
### Input Events
|
||||
|
||||
The Form component automatically triggers validation when an input emits an `input`, `change`, or `blur` event.
|
||||
|
||||
- Validation on `input` occurs **as you type**.
|
||||
- Validation on `change` occurs when you **commit to a value**.
|
||||
- Validation on `blur` happens when an input **loses focus**.
|
||||
|
||||
@@ -8,7 +8,6 @@ links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/InputNumber.vue
|
||||
navigation.badge: New
|
||||
---
|
||||
|
||||
::note
|
||||
|
||||
@@ -13,7 +13,7 @@ The Link component is a wrapper around [`<NuxtLink>`](https://nuxt.com/docs/api/
|
||||
- `inactive-class` prop to set a class when the link is inactive, `active-class` is used when active.
|
||||
- `exact` prop to style with `active-class` when the link is active and the route is exactly the same as the current route.
|
||||
- `exact-query` and `exact-hash` props to style with `active-class` when the link is active and the query or hash is exactly the same as the current query or hash.
|
||||
- use `exact-query="partial"` to style with `active-class` when the link is active and the query partially match the current query.
|
||||
- use `exact-query="partial"` to style with `active-class` when the link is active and the query partially match the current query.
|
||||
|
||||
The incentive behind this is to provide the same API as NuxtLink back in Nuxt 2 / Vue 2. You can read more about it in the Vue Router [migration from Vue 2](https://router.vuejs.org/guide/migration/#removal-of-the-exact-prop-in-router-link) guide.
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ slots:
|
||||
|
||||
Use the `close` prop to customize or hide the close button (with `false` value) displayed in the Modal's header.
|
||||
|
||||
You can pass all the props of the [Button](/components/button) component to customize it.
|
||||
You can pass any property from the [Button](/components/button) component to customize it.
|
||||
|
||||
::component-code
|
||||
---
|
||||
@@ -253,35 +253,6 @@ slots:
|
||||
:placeholder{class="h-full"}
|
||||
::
|
||||
|
||||
### Prevent close
|
||||
|
||||
Use the `prevent-close` prop to prevent the Modal from being closed when clicking outside of it.
|
||||
|
||||
::component-code
|
||||
---
|
||||
prettier: true
|
||||
ignore:
|
||||
- title
|
||||
- preventClose
|
||||
props:
|
||||
preventClose: true
|
||||
title: 'Modal prevent close'
|
||||
slots:
|
||||
default: |
|
||||
|
||||
<UButton label="Open" color="neutral" variant="subtle" />
|
||||
|
||||
body: |
|
||||
|
||||
<Placeholder class="h-48" />
|
||||
---
|
||||
|
||||
:u-button{label="Open" color="neutral" variant="subtle"}
|
||||
|
||||
#body
|
||||
:placeholder{class="h-48"}
|
||||
::
|
||||
|
||||
## Examples
|
||||
|
||||
### Control open state
|
||||
@@ -302,6 +273,35 @@ In this example, leveraging [`defineShortcuts`](/composables/define-shortcuts),
|
||||
This allows you to move the trigger outside of the Modal or remove it entirely.
|
||||
::
|
||||
|
||||
### Prevent closing
|
||||
|
||||
Set the `dismissible` prop to `false` to prevent the Modal from being closed when clicking outside of it or pressing escape.
|
||||
|
||||
::component-code
|
||||
---
|
||||
prettier: true
|
||||
ignore:
|
||||
- title
|
||||
- dismissible
|
||||
props:
|
||||
dismissible: false
|
||||
title: 'Modal non-dismissible'
|
||||
slots:
|
||||
default: |
|
||||
|
||||
<UButton label="Open" color="neutral" variant="subtle" />
|
||||
|
||||
body: |
|
||||
|
||||
<Placeholder class="h-48" />
|
||||
---
|
||||
|
||||
:u-button{label="Open" color="neutral" variant="subtle"}
|
||||
|
||||
#body
|
||||
:placeholder{class="h-48"}
|
||||
::
|
||||
|
||||
### Programmatic usage
|
||||
|
||||
You can use the [`useModal`](/composables/use-modal) composable to open a Modal programatically.
|
||||
|
||||
@@ -27,7 +27,7 @@ Use the `items` prop as an array of objects with the following properties:
|
||||
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
|
||||
- `onSelect?(e: Event): void`{lang="ts-type"}
|
||||
|
||||
You can also pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
|
||||
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
|
||||
|
||||
::component-code
|
||||
---
|
||||
@@ -115,12 +115,12 @@ props:
|
||||
- label: Help
|
||||
icon: i-lucide-circle-help
|
||||
disabled: true
|
||||
class: 'justify-center'
|
||||
class: 'w-full justify-center'
|
||||
---
|
||||
::
|
||||
|
||||
::note
|
||||
You can pass an array of arrays to the `items` prop to display groups of items.
|
||||
You can also pass an array of arrays to the `items` prop to display groups of items.
|
||||
::
|
||||
|
||||
::tip
|
||||
@@ -131,6 +131,7 @@ Each item can take a `children` array of objects with the following properties t
|
||||
- `icon?: string`
|
||||
- `class?: any`
|
||||
- `onSelect?(e: Event): void`
|
||||
|
||||
::
|
||||
|
||||
### Orientation
|
||||
@@ -152,7 +153,6 @@ props:
|
||||
items:
|
||||
- - label: Guide
|
||||
icon: i-lucide-book-open
|
||||
defaultOpen: true
|
||||
children:
|
||||
- label: Introduction
|
||||
description: Fully styled and customizable components for Nuxt.
|
||||
@@ -190,7 +190,9 @@ props:
|
||||
to: /composables/use-toast
|
||||
- label: Components
|
||||
icon: i-lucide-box
|
||||
to: /components
|
||||
active: true
|
||||
defaultOpen: true
|
||||
children:
|
||||
- label: Link
|
||||
icon: i-lucide-file-text
|
||||
@@ -240,10 +242,10 @@ Use the `highlight-color` prop to change the color of the border. It defaults to
|
||||
|
||||
::component-code
|
||||
---
|
||||
collapse: true
|
||||
prettier: true
|
||||
ignore:
|
||||
- items
|
||||
- highlight
|
||||
- class
|
||||
external:
|
||||
- items
|
||||
@@ -254,25 +256,89 @@ props:
|
||||
items:
|
||||
- - label: Guide
|
||||
icon: i-lucide-book-open
|
||||
to: /getting-started
|
||||
children:
|
||||
- label: Introduction
|
||||
description: Fully styled and customizable components for Nuxt.
|
||||
icon: i-lucide-house
|
||||
- label: Installation
|
||||
description: Learn how to install and configure Nuxt UI in your application.
|
||||
icon: i-lucide-cloud-download
|
||||
- label: 'Icons'
|
||||
icon: 'i-lucide-smile'
|
||||
description: 'You have nothing to do, @nuxt/icon will handle it automatically.'
|
||||
- label: 'Colors'
|
||||
icon: 'i-lucide-swatch-book'
|
||||
description: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
|
||||
- label: 'Theme'
|
||||
icon: 'i-lucide-cog'
|
||||
description: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
|
||||
- label: Composables
|
||||
icon: i-lucide-database
|
||||
to: /composables
|
||||
children:
|
||||
- label: defineShortcuts
|
||||
icon: i-lucide-file-text
|
||||
description: Define shortcuts for your application.
|
||||
to: /composables/define-shortcuts
|
||||
- label: useModal
|
||||
icon: i-lucide-file-text
|
||||
description: Display a modal within your application.
|
||||
to: /composables/use-modal
|
||||
- label: useSlideover
|
||||
icon: i-lucide-file-text
|
||||
description: Display a slideover within your application.
|
||||
to: /composables/use-slideover
|
||||
- label: useToast
|
||||
icon: i-lucide-file-text
|
||||
description: Display a toast within your application.
|
||||
to: /composables/use-toast
|
||||
- label: Components
|
||||
icon: i-lucide-box
|
||||
to: /components
|
||||
active: true
|
||||
defaultOpen: true
|
||||
children:
|
||||
- label: Link
|
||||
icon: i-lucide-file-text
|
||||
description: Use NuxtLink with superpowers.
|
||||
to: /components/link
|
||||
- label: Modal
|
||||
icon: i-lucide-file-text
|
||||
description: Display a modal within your application.
|
||||
to: /components/modal
|
||||
- label: NavigationMenu
|
||||
icon: i-lucide-file-text
|
||||
description: Display a list of links.
|
||||
to: /components/navigation-menu
|
||||
- label: Pagination
|
||||
icon: i-lucide-file-text
|
||||
description: Display a list of pages.
|
||||
to: /components/pagination
|
||||
- label: Popover
|
||||
icon: i-lucide-file-text
|
||||
description: Display a non-modal dialog that floats around a trigger element.
|
||||
to: /components/popover
|
||||
- label: Progress
|
||||
icon: i-lucide-file-text
|
||||
description: Show a horizontal bar to indicate task progression.
|
||||
to: /components/progress
|
||||
- - label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
badge: 3.8k
|
||||
to: https://github.com/nuxt/ui
|
||||
target: _blank
|
||||
class: 'data-[orientation=horizontal]:border-b data-[orientation=vertical]:border-l border-[var(--ui-border)]'
|
||||
- label: Help
|
||||
icon: i-lucide-circle-help
|
||||
disabled: true
|
||||
class: 'data-[orientation=horizontal]:border-b border-[var(--ui-border)] data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-48'
|
||||
---
|
||||
::
|
||||
|
||||
::note
|
||||
In this example, the `border-l` and `border-b` classes are applied to display a border, this is not done by default to let you have a clean slate to work with.
|
||||
In this example, the `border-b` class is applied to display a border in `horizontal` orientation, this is not done by default to let you have a clean slate to work with.
|
||||
::
|
||||
|
||||
::caution
|
||||
In `vertical` orientation, the `highlight` prop only highlights the border of active children.
|
||||
::
|
||||
|
||||
### Color
|
||||
@@ -283,6 +349,7 @@ Use the `color` prop to change the color of the NavigationMenu.
|
||||
---
|
||||
ignore:
|
||||
- items
|
||||
- class
|
||||
external:
|
||||
- items
|
||||
props:
|
||||
@@ -303,6 +370,7 @@ props:
|
||||
badge: 3.8k
|
||||
to: https://github.com/nuxt/ui
|
||||
target: _blank
|
||||
class: 'w-full'
|
||||
---
|
||||
::
|
||||
|
||||
@@ -314,6 +382,7 @@ Use the `variant` prop to change the variant of the NavigationMenu.
|
||||
---
|
||||
ignore:
|
||||
- items
|
||||
- class
|
||||
external:
|
||||
- items
|
||||
props:
|
||||
@@ -336,6 +405,7 @@ props:
|
||||
badge: 3.8k
|
||||
to: https://github.com/nuxt/ui
|
||||
target: _blank
|
||||
class: 'w-full'
|
||||
---
|
||||
::
|
||||
|
||||
@@ -430,7 +500,7 @@ props:
|
||||
icon: i-lucide-file-text
|
||||
description: Show a horizontal bar to indicate task progression.
|
||||
to: /components/progress
|
||||
class: 'justify-center'
|
||||
class: 'w-full justify-center'
|
||||
---
|
||||
::
|
||||
|
||||
@@ -530,7 +600,7 @@ props:
|
||||
icon: i-lucide-file-text
|
||||
description: Show a horizontal bar to indicate task progression.
|
||||
to: /components/progress
|
||||
class: 'justify-center'
|
||||
class: 'w-full justify-center'
|
||||
---
|
||||
::
|
||||
|
||||
@@ -622,7 +692,7 @@ props:
|
||||
icon: i-lucide-file-text
|
||||
description: Show a horizontal bar to indicate task progression.
|
||||
to: /components/progress
|
||||
class: 'justify-center'
|
||||
class: 'w-full justify-center'
|
||||
---
|
||||
::
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/PinInput.vue
|
||||
navigation.badge: New
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -180,6 +180,16 @@ name: 'popover-open-example'
|
||||
In this example, leveraging [`defineShortcuts`](/composables/define-shortcuts), you can toggle the Popover by pressing :kbd{value="O"}.
|
||||
::
|
||||
|
||||
### Prevent closing
|
||||
|
||||
Set the `dismissible` prop to `false` to prevent the Popover from being closed when clicking outside of it or pressing escape.
|
||||
|
||||
::component-example
|
||||
---
|
||||
name: 'popover-dismissible-example'
|
||||
---
|
||||
::
|
||||
|
||||
### With command palette
|
||||
|
||||
You can use a [CommandPalette](/components/command-palette) component inside the Popover's content.
|
||||
|
||||
@@ -202,7 +202,7 @@ props:
|
||||
|
||||
Use the `search-input` prop to customize or hide the search input (with `false` value).
|
||||
|
||||
You can pass all the props of the [Input](/components/input) component to customize it.
|
||||
You can pass any property from the [Input](/components/input) component to customize it.
|
||||
|
||||
::component-code
|
||||
---
|
||||
|
||||
@@ -93,7 +93,7 @@ slots:
|
||||
|
||||
Use the `close` prop to customize or hide the close button (with `false` value) displayed in the Slideover's header.
|
||||
|
||||
You can pass all the props of the [Button](/components/button) component to customize it.
|
||||
You can pass any property from the [Button](/components/button) component to customize it.
|
||||
|
||||
::component-code
|
||||
---
|
||||
@@ -252,35 +252,6 @@ slots:
|
||||
:placeholder{class="h-full"}
|
||||
::
|
||||
|
||||
### Prevent close
|
||||
|
||||
Use the `prevent-close` prop to prevent the Slideover from being closed when clicking outside of it.
|
||||
|
||||
::component-code
|
||||
---
|
||||
prettier: true
|
||||
ignore:
|
||||
- title
|
||||
- preventClose
|
||||
props:
|
||||
preventClose: true
|
||||
title: 'Slideover prevent close'
|
||||
slots:
|
||||
default: |
|
||||
|
||||
<UButton label="Open" color="neutral" variant="subtle" />
|
||||
|
||||
body: |
|
||||
|
||||
<Placeholder class="h-full" />
|
||||
---
|
||||
|
||||
:u-button{label="Open" color="neutral" variant="subtle"}
|
||||
|
||||
#body
|
||||
:placeholder{class="h-full"}
|
||||
::
|
||||
|
||||
## Examples
|
||||
|
||||
### Control open state
|
||||
@@ -301,6 +272,35 @@ In this example, leveraging [`defineShortcuts`](/composables/define-shortcuts),
|
||||
This allows you to move the trigger outside of the Slideover or remove it entirely.
|
||||
::
|
||||
|
||||
### Prevent closing
|
||||
|
||||
Set the `dismissible` prop to `false` to prevent the Slideover from being closed when clicking outside of it or pressing escape.
|
||||
|
||||
::component-code
|
||||
---
|
||||
prettier: true
|
||||
ignore:
|
||||
- title
|
||||
- dismissible
|
||||
props:
|
||||
dismissible: false
|
||||
title: 'Slideover non-dismissible'
|
||||
slots:
|
||||
default: |
|
||||
|
||||
<UButton label="Open" color="neutral" variant="subtle" />
|
||||
|
||||
body: |
|
||||
|
||||
<Placeholder class="h-full" />
|
||||
---
|
||||
|
||||
:u-button{label="Open" color="neutral" variant="subtle"}
|
||||
|
||||
#body
|
||||
:placeholder{class="h-full"}
|
||||
::
|
||||
|
||||
### Programmatic usage
|
||||
|
||||
You can use the [`useSlideover`](/composables/use-slideover) composable to open a Slideover programatically.
|
||||
|
||||
@@ -110,10 +110,6 @@ export default defineNuxtConfig({
|
||||
}
|
||||
},
|
||||
|
||||
hub: {
|
||||
cache: true
|
||||
},
|
||||
|
||||
componentMeta: {
|
||||
exclude: [
|
||||
'@nuxt/content',
|
||||
@@ -125,7 +121,7 @@ export default defineNuxtConfig({
|
||||
'nuxt/dist',
|
||||
'nuxt-og-image',
|
||||
resolve('./app/components'),
|
||||
process.env.NUXT_UI_PRO_PATH ? resolve(process.env.NUXT_UI_PRO_PATH, 'docs', 'components') : '.c12'
|
||||
process.env.NUXT_UI_PRO_PATH ? resolve(process.env.NUXT_UI_PRO_PATH, 'docs', 'app', 'components') : '.c12'
|
||||
],
|
||||
metaFields: {
|
||||
type: false,
|
||||
@@ -150,5 +146,9 @@ export default defineNuxtConfig({
|
||||
|
||||
image: {
|
||||
provider: 'ipx'
|
||||
},
|
||||
|
||||
uiPro: {
|
||||
license: 'oss'
|
||||
}
|
||||
})
|
||||
|
||||
@@ -3,31 +3,31 @@
|
||||
"name": "@nuxt/ui-docs",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@iconify-json/logos": "^1.2.3",
|
||||
"@iconify-json/lucide": "^1.2.18",
|
||||
"@iconify-json/simple-icons": "^1.2.14",
|
||||
"@iconify-json/vscode-icons": "^1.2.3",
|
||||
"@nuxt/content": "https://pkg.pr.new/@nuxt/content@c5b1a4f",
|
||||
"@nuxt/image": "^1.8.1",
|
||||
"@iconify-json/logos": "^1.2.4",
|
||||
"@iconify-json/lucide": "^1.2.22",
|
||||
"@iconify-json/simple-icons": "^1.2.19",
|
||||
"@iconify-json/vscode-icons": "^1.2.10",
|
||||
"@nuxt/content": "https://pkg.pr.new/@nuxt/content@164ffb0",
|
||||
"@nuxt/image": "^1.9.0",
|
||||
"@nuxt/ui": "latest",
|
||||
"@nuxt/ui-pro": "https://pkg.pr.new/@nuxt/ui-pro@3fcaf55",
|
||||
"@nuxthub/core": "^0.8.7",
|
||||
"@nuxt/ui-pro": "https://pkg.pr.new/@nuxt/ui-pro@7676093",
|
||||
"@nuxthub/core": "^0.8.11",
|
||||
"@nuxtjs/plausible": "^1.2.0",
|
||||
"@octokit/rest": "^21.0.2",
|
||||
"@vueuse/nuxt": "^12.0.0",
|
||||
"@octokit/rest": "^21.1.0",
|
||||
"@vueuse/nuxt": "^12.4.0",
|
||||
"joi": "^17.13.3",
|
||||
"nuxt": "^3.14.1592",
|
||||
"nuxt": "^3.15.1",
|
||||
"nuxt-component-meta": "^0.9.0",
|
||||
"nuxt-og-image": "^3.1.1",
|
||||
"nuxt-og-image": "^4.0.2",
|
||||
"prettier": "^3.4.2",
|
||||
"shiki-transformer-color-highlight": "^0.2.0",
|
||||
"superstruct": "^2.0.2",
|
||||
"ufo": "^1.5.4",
|
||||
"valibot": "^0.42.1",
|
||||
"yup": "^1.5.0",
|
||||
"zod": "^3.23.8"
|
||||
"yup": "^1.6.1",
|
||||
"zod": "^3.24.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"wrangler": "^3.93.0"
|
||||
"wrangler": "^3.101.0"
|
||||
}
|
||||
}
|
||||
|
||||
93
package.json
93
package.json
@@ -1,21 +1,21 @@
|
||||
{
|
||||
"name": "@nuxt/ui",
|
||||
"description": "A UI Library for Modern Web Apps, powered by Vue & Tailwind CSS.",
|
||||
"version": "3.0.0-alpha.10",
|
||||
"packageManager": "pnpm@9.15.0",
|
||||
"version": "3.0.0-alpha.11",
|
||||
"packageManager": "pnpm@9.15.3",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/nuxt/ui.git"
|
||||
},
|
||||
"homepage": "https://ui.nuxt.com",
|
||||
"homepage": "https://ui3.nuxt.dev",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/module.d.ts",
|
||||
"style": "./dist/runtime/index.css",
|
||||
"import": "./dist/module.mjs",
|
||||
"require": "./dist/module.cjs",
|
||||
"style": "./dist/runtime/index.css"
|
||||
"require": "./dist/module.cjs"
|
||||
},
|
||||
"./unplugin": {
|
||||
"types": "./dist/unplugin.d.ts",
|
||||
@@ -73,81 +73,86 @@
|
||||
"release": "release-it --preRelease=alpha --npm.tag=next"
|
||||
},
|
||||
"dependencies": {
|
||||
"@iconify/vue": "^4.2.0",
|
||||
"@iconify/vue": "^4.3.0",
|
||||
"@internationalized/date": "^3.6.0",
|
||||
"@internationalized/number": "^3.6.0",
|
||||
"@nuxt/devtools-kit": "^1.6.3",
|
||||
"@nuxt/devtools-kit": "^1.7.0",
|
||||
"@nuxt/fonts": "^0.10.3",
|
||||
"@nuxt/icon": "^1.9.1",
|
||||
"@nuxt/kit": "^3.14.1592",
|
||||
"@nuxt/schema": "^3.14.1592",
|
||||
"@nuxt/icon": "^1.10.3",
|
||||
"@nuxt/kit": "^3.15.1",
|
||||
"@nuxt/schema": "^3.15.1",
|
||||
"@nuxtjs/color-mode": "^3.5.2",
|
||||
"@tailwindcss/postcss": "4.0.0-beta.6",
|
||||
"@tailwindcss/vite": "4.0.0-beta.6",
|
||||
"@tailwindcss/postcss": "4.0.0-beta.9",
|
||||
"@tailwindcss/vite": "4.0.0-beta.9",
|
||||
"@tanstack/vue-table": "^8.20.5",
|
||||
"@types/color": "^4.2.0",
|
||||
"@unhead/vue": "^1.11.13",
|
||||
"@vueuse/core": "^12.0.0",
|
||||
"@vueuse/integrations": "^12.0.0",
|
||||
"@unhead/vue": "^1.11.16",
|
||||
"@vueuse/core": "^12.4.0",
|
||||
"@vueuse/integrations": "^12.4.0",
|
||||
"color": "^4.2.3",
|
||||
"consola": "^3.2.3",
|
||||
"consola": "^3.3.3",
|
||||
"defu": "^6.1.4",
|
||||
"embla-carousel-auto-height": "^8.5.1",
|
||||
"embla-carousel-auto-scroll": "^8.5.1",
|
||||
"embla-carousel-autoplay": "^8.5.1",
|
||||
"embla-carousel-class-names": "^8.5.1",
|
||||
"embla-carousel-fade": "^8.5.1",
|
||||
"embla-carousel-vue": "^8.5.1",
|
||||
"embla-carousel-auto-height": "^8.5.2",
|
||||
"embla-carousel-auto-scroll": "^8.5.2",
|
||||
"embla-carousel-autoplay": "^8.5.2",
|
||||
"embla-carousel-class-names": "^8.5.2",
|
||||
"embla-carousel-fade": "^8.5.2",
|
||||
"embla-carousel-vue": "^8.5.2",
|
||||
"embla-carousel-wheel-gestures": "^8.0.1",
|
||||
"fuse.js": "^7.0.0",
|
||||
"get-port-please": "^3.1.2",
|
||||
"knitwork": "^1.1.0",
|
||||
"magic-string": "^0.30.14",
|
||||
"mlly": "^1.7.3",
|
||||
"knitwork": "^1.2.0",
|
||||
"magic-string": "^0.30.17",
|
||||
"mlly": "^1.7.4",
|
||||
"ohash": "^1.1.4",
|
||||
"reka-ui": "1.0.0-alpha.6",
|
||||
"pathe": "^1.1.2",
|
||||
"reka-ui": "1.0.0-alpha.8",
|
||||
"pathe": "^2.0.1",
|
||||
"scule": "^1.3.0",
|
||||
"sirv": "^3.0.0",
|
||||
"tailwind-variants": "^0.3.0",
|
||||
"tailwindcss": "4.0.0-beta.6",
|
||||
"tailwindcss": "4.0.0-beta.9",
|
||||
"tinyglobby": "^0.2.10",
|
||||
"unplugin": "^1.16.0",
|
||||
"unplugin-auto-import": "^0.18.6",
|
||||
"unplugin-vue-components": "^0.27.5",
|
||||
"unplugin": "^2.1.2",
|
||||
"unplugin-auto-import": "^19.0.0",
|
||||
"unplugin-vue-components": "^28.0.0",
|
||||
"vaul-vue": "^0.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxt/eslint-config": "^0.7.2",
|
||||
"@nuxt/eslint-config": "^0.7.5",
|
||||
"@nuxt/module-builder": "^0.8.4",
|
||||
"@nuxt/test-utils": "^3.15.1",
|
||||
"@release-it/conventional-changelog": "^9.0.3",
|
||||
"@standard-schema/spec": "1.0.0-beta.4",
|
||||
"@nuxt/test-utils": "^3.15.4",
|
||||
"@release-it/conventional-changelog": "^10.0.0",
|
||||
"@standard-schema/spec": "1.0.0-rc.0",
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"embla-carousel": "^8.5.1",
|
||||
"eslint": "^9.16.0",
|
||||
"embla-carousel": "^8.5.2",
|
||||
"eslint": "^9.18.0",
|
||||
"happy-dom": "^15.7.4",
|
||||
"joi": "^17.13.3",
|
||||
"knitwork": "^1.1.0",
|
||||
"nuxt": "^3.14.1592",
|
||||
"knitwork": "^1.2.0",
|
||||
"nuxt": "^3.15.1",
|
||||
"nuxt-component-meta": "^0.9.0",
|
||||
"release-it": "^17.10.0",
|
||||
"release-it": "^18.1.1",
|
||||
"superstruct": "^2.0.2",
|
||||
"valibot": "^0.42.1",
|
||||
"vitest": "^2.1.8",
|
||||
"vitest-environment-nuxt": "^1.0.1",
|
||||
"vue-tsc": "^2.1.10",
|
||||
"yup": "^1.5.0",
|
||||
"zod": "^3.23.8"
|
||||
"vue-tsc": "^2.2.0",
|
||||
"yup": "^1.6.1",
|
||||
"zod": "^3.24.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5.6.3"
|
||||
},
|
||||
"resolutions": {
|
||||
"@nuxt/ui": "workspace:*",
|
||||
"chokidar": "3.6.0",
|
||||
"debug": "4.3.7",
|
||||
"happy-dom": "14.12.3",
|
||||
"rollup": "^4.24.0",
|
||||
"typescript": "5.6.3",
|
||||
"chokidar": "3.6.0"
|
||||
"unimport": "3.14.5",
|
||||
"unplugin": "^2.1.2",
|
||||
"vite": "^6.0.7",
|
||||
"vue-tsc": "^2.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"typescript": "^5.7.2",
|
||||
"unplugin-auto-import": "^0.18.6",
|
||||
"unplugin-vue-components": "^0.27.5",
|
||||
"vite": "^5.4.11",
|
||||
"vue-tsc": "^2.1.10"
|
||||
"unplugin-auto-import": "^19.0.0",
|
||||
"unplugin-vue-components": "^28.0.0",
|
||||
"vite": "^6.0.7",
|
||||
"vue-tsc": "^2.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { z } from 'zod'
|
||||
import * as z from 'zod'
|
||||
import type { FormSubmitEvent } from '@nuxt/ui'
|
||||
import FormExampleElements from '../../../../docs/app/components/content/examples/form/FormExampleElements.vue'
|
||||
import FormExampleNestedList from '../../../../docs/app/components/content/examples/form/FormExampleNestedList.vue'
|
||||
|
||||
@@ -16,7 +16,6 @@ const items = [
|
||||
label: 'Documentation',
|
||||
icon: 'i-lucide-book-open',
|
||||
badge: 10,
|
||||
defaultOpen: true,
|
||||
children: [{
|
||||
label: 'Introduction',
|
||||
description: 'Fully styled and customizable components for Nuxt.',
|
||||
@@ -38,6 +37,7 @@ const items = [
|
||||
label: 'Components',
|
||||
icon: 'i-lucide-box',
|
||||
active: true,
|
||||
defaultOpen: true,
|
||||
children: [{
|
||||
label: 'Link',
|
||||
icon: 'i-lucide-file',
|
||||
@@ -101,7 +101,8 @@ const items = [
|
||||
:orientation="orientation"
|
||||
:highlight="highlight"
|
||||
:highlight-color="highlightColor"
|
||||
:class="highlight && 'data-[orientation=horizontal]:border-b data-[orientation=vertical]:border-s border-[var(--ui-border)]'"
|
||||
:class="highlight && 'data-[orientation=horizontal]:border-b border-[var(--ui-border)]'"
|
||||
class="data-[orientation=vertical]:w-48"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -3,9 +3,14 @@ import { createResolver } from '@nuxt/kit'
|
||||
const { resolve } = createResolver(import.meta.url)
|
||||
|
||||
export default defineNuxtConfig({
|
||||
modules: ['../src/module'],
|
||||
modules: [
|
||||
'../src/module',
|
||||
'@nuxthub/core'
|
||||
],
|
||||
|
||||
devtools: { enabled: true },
|
||||
devtools: {
|
||||
enabled: true
|
||||
},
|
||||
|
||||
ui: {
|
||||
fonts: false
|
||||
|
||||
@@ -8,9 +8,10 @@
|
||||
"generate": "nuxi generate"
|
||||
},
|
||||
"dependencies": {
|
||||
"@iconify-json/lucide": "^1.2.18",
|
||||
"@iconify-json/simple-icons": "^1.2.14",
|
||||
"@iconify-json/lucide": "^1.2.22",
|
||||
"@iconify-json/simple-icons": "^1.2.19",
|
||||
"@nuxt/ui": "latest",
|
||||
"nuxt": "^3.14.1592"
|
||||
"@nuxthub/core": "^0.8.11",
|
||||
"nuxt": "^3.15.1"
|
||||
}
|
||||
}
|
||||
|
||||
7322
pnpm-lock.yaml
generated
7322
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,8 @@
|
||||
"happy-dom",
|
||||
"valibot30",
|
||||
"valibot31",
|
||||
"typescript"
|
||||
"typescript",
|
||||
"vue-tsc"
|
||||
],
|
||||
"baseBranches": ["dev", "v3"],
|
||||
"packageRules": [{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { UnpluginOptions } from 'unplugin'
|
||||
import { join, normalize } from 'pathe'
|
||||
import { normalize } from 'pathe'
|
||||
import { resolvePathSync } from 'mlly'
|
||||
import MagicString from 'magic-string'
|
||||
|
||||
@@ -9,7 +9,7 @@ import { runtimeDir } from '../unplugin'
|
||||
* This plugin normalises Nuxt environment (#imports) and `import.meta.client` within the Nuxt UI components.
|
||||
*/
|
||||
export default function NuxtEnvironmentPlugin() {
|
||||
const stubPath = resolvePathSync(join(runtimeDir, 'vue/stubs'), { extensions: ['.ts', '.mjs', '.js'] })
|
||||
const stubPath = resolvePathSync('../runtime/vue/stubs', { extensions: ['.ts', '.mjs', '.js'], url: import.meta.url })
|
||||
|
||||
return {
|
||||
name: 'nuxt:ui',
|
||||
|
||||
@@ -15,9 +15,9 @@ import type { UnpluginOptions } from 'unplugin'
|
||||
export default function PluginsPlugin(options: NuxtUIOptions) {
|
||||
const plugins = globSync(['**/*', '!*.d.ts'], { cwd: join(runtimeDir, 'plugins'), absolute: true })
|
||||
|
||||
plugins.unshift(resolvePathSync(join(runtimeDir, 'vue/plugins/head'), { extensions: ['.ts', '.mjs', '.js'] }))
|
||||
plugins.unshift(resolvePathSync('../runtime/vue/plugins/head', { extensions: ['.ts', '.mjs', '.js'], url: import.meta.url }))
|
||||
if (options.colorMode) {
|
||||
plugins.push(resolvePathSync(join(runtimeDir, 'vue/plugins/color-mode'), { extensions: ['.ts', '.mjs', '.js'] }))
|
||||
plugins.push(resolvePathSync('../runtime/vue/plugins/color-mode', { extensions: ['.ts', '.mjs', '.js'], url: import.meta.url }))
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { tv } from 'tailwind-variants'
|
||||
import type { AccordionRootProps, AccordionRootEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/accordion'
|
||||
import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { DynamicSlots } from '../types/utils'
|
||||
|
||||
const appConfig = _appConfig as AppConfig & { ui: { accordion: Partial<typeof theme> } }
|
||||
@@ -98,6 +98,7 @@ import UIcon from './Icon.vue'
|
||||
const props = withDefaults(defineProps<AccordionProps<T>>(), {
|
||||
type: 'single',
|
||||
collapsible: true,
|
||||
unmountOnHide: true,
|
||||
labelKey: 'label'
|
||||
})
|
||||
const emits = defineEmits<AccordionEmits>()
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { tv, type VariantProps } from 'tailwind-variants'
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/alert'
|
||||
import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps, ButtonProps } from '../types'
|
||||
|
||||
const appConfig = _appConfig as AppConfig & { ui: { alert: Partial<typeof theme> } }
|
||||
@@ -34,7 +35,7 @@ export interface AlertProps {
|
||||
/**
|
||||
* Display a close button to dismiss the alert.
|
||||
* `{ size: 'md', color: 'neutral', variant: 'link' }`{lang="ts-type"}
|
||||
* @emits `close`
|
||||
* @emits 'update:open'
|
||||
* @defaultValue false
|
||||
*/
|
||||
close?: ButtonProps | boolean
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { tv, type VariantProps } from 'tailwind-variants'
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AvatarFallbackProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/avatar'
|
||||
import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const appConfig = _appConfig as AppConfig & { ui: { avatar: Partial<typeof theme> } }
|
||||
|
||||
@@ -83,10 +84,10 @@ const sizePx = computed(() => ({
|
||||
:class="ui.image({ class: props.ui?.image })"
|
||||
/>
|
||||
|
||||
<AvatarFallback as-child v-bind="fallbackProps">
|
||||
<AvatarFallback as-child v-bind="{ ...fallbackProps, ...$attrs }">
|
||||
<slot>
|
||||
<UIcon v-if="icon" :name="icon" :class="ui.icon({ class: props.ui?.icon })" />
|
||||
<span v-else :class="ui.fallback({ class: props.ui?.fallback })">{{ fallback }}</span>
|
||||
<span v-else :class="ui.fallback({ class: props.ui?.fallback })">{{ fallback || ' ' }}</span>
|
||||
</slot>
|
||||
</AvatarFallback>
|
||||
</AvatarRoot>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { tv, type VariantProps } from 'tailwind-variants'
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/avatar-group'
|
||||
import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const appConfig = _appConfig as AppConfig & { ui: { avatarGroup: Partial<typeof theme> } }
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { tv, type VariantProps } from 'tailwind-variants'
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/badge'
|
||||
import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
|
||||
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps } from '../types'
|
||||
|
||||
const appConfig = _appConfig as AppConfig & { ui: { badge: Partial<typeof theme> } }
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { tv } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/breadcrumb'
|
||||
import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps, LinkProps } from '../types'
|
||||
import type { DynamicSlots, PartialString } from '../types/utils'
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { tv, type VariantProps } from 'tailwind-variants'
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/button'
|
||||
import type { LinkProps } from './Link.vue'
|
||||
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
||||
import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps } from '../types'
|
||||
import type { PartialString } from '../types/utils'
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { tv, type VariantProps } from 'tailwind-variants'
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/button-group'
|
||||
import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const appConfig = _appConfig as AppConfig & { ui: { buttonGroup: Partial<typeof theme> } }
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { tv, type VariantProps } from 'tailwind-variants'
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { CalendarRootProps, CalendarRootEmits, RangeCalendarRootEmits, DateRange, CalendarCellTriggerProps } from 'reka-ui'
|
||||
import type { DateValue } from '@internationalized/date'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/calendar'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const appConfig = _appConfig as AppConfig & { ui: { calendar: Partial<typeof theme> } }
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { tv } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/card'
|
||||
import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const appConfig = _appConfig as AppConfig & { ui: { card: Partial<typeof theme> } }
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { tv, type VariantProps } from 'tailwind-variants'
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import type { AcceptableValue } from 'reka-ui'
|
||||
import type { EmblaCarouselType, EmblaOptionsType, EmblaPluginType } from 'embla-carousel'
|
||||
@@ -12,6 +12,7 @@ import type { WheelGesturesPluginOptions } from 'embla-carousel-wheel-gestures'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/carousel'
|
||||
import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ButtonProps } from '../types'
|
||||
import type { PartialString } from '../types/utils'
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { tv, type VariantProps } from 'tailwind-variants'
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { CheckboxRootProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/checkbox'
|
||||
import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const appConfig = _appConfig as AppConfig & { ui: { checkbox: Partial<typeof theme> } }
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { tv, type VariantProps } from 'tailwind-variants'
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/chip'
|
||||
import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const appConfig = _appConfig as AppConfig & { ui: { chip: Partial<typeof theme> } }
|
||||
|
||||
@@ -22,7 +23,7 @@ export interface ChipProps {
|
||||
color?: ChipVariants['color']
|
||||
size?: ChipVariants['size']
|
||||
position?: ChipVariants['position']
|
||||
/** When `true`, translate the chip at the edge for non rounded elements. */
|
||||
/** When `true`, keep the chip inside the component for rounded elements. */
|
||||
inset?: boolean
|
||||
/** When `true`, render the chip relatively to the parent. */
|
||||
standalone?: boolean
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { tv } from 'tailwind-variants'
|
||||
import type { CollapsibleRootProps, CollapsibleRootEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/collapsible'
|
||||
import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const appConfig = _appConfig as AppConfig & { ui: { collapsible: Partial<typeof theme> } }
|
||||
|
||||
@@ -34,7 +34,9 @@ extendDevtoolsMeta({ example: 'CollapsibleExample' })
|
||||
import { CollapsibleRoot, CollapsibleTrigger, CollapsibleContent, useForwardPropsEmits } from 'reka-ui'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
|
||||
const props = defineProps<CollapsibleProps>()
|
||||
const props = withDefaults(defineProps<CollapsibleProps>(), {
|
||||
unmountOnHide: true
|
||||
})
|
||||
const emits = defineEmits<CollapsibleEmits>()
|
||||
const slots = defineSlots<CollapsibleSlots>()
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { tv, type VariantProps } from 'tailwind-variants'
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { MaybeRefOrGetter } from '@vueuse/shared'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/color-picker'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const appConfig = _appConfig as AppConfig & { ui: { colorPicker: Partial<typeof theme> } }
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user