mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-15 12:39:35 +01:00
Compare commits
262 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6736d1efd | ||
|
|
f6e695ffc8 | ||
|
|
e8898d15a6 | ||
|
|
f65aefb706 | ||
|
|
9b9ccdb59e | ||
|
|
688232215d | ||
|
|
ebfb835033 | ||
|
|
838d6c832f | ||
|
|
e7c2f7856c | ||
|
|
1d5bd89d58 | ||
|
|
6c124bb1ac | ||
|
|
49174b7628 | ||
|
|
50ad14f9df | ||
|
|
6e2678d1d8 | ||
|
|
831c560a96 | ||
|
|
06990beabf | ||
|
|
3ebff4d133 | ||
|
|
d66cfa9d7d | ||
|
|
75c0d9e31f | ||
|
|
6033872ef8 | ||
|
|
838cb7212a | ||
|
|
c8dd71c4f5 | ||
|
|
4f0d00f7a6 | ||
|
|
3b975634e8 | ||
|
|
249bbd49dc | ||
|
|
3c1602af37 | ||
|
|
e1ca6e0cde | ||
|
|
3b3bd16afe | ||
|
|
fab9cbebd8 | ||
|
|
581b470cc7 | ||
|
|
24d30cd1f3 | ||
|
|
cc52bffccf | ||
|
|
eb2601d4da | ||
|
|
f726b5f094 | ||
|
|
37ce62acb9 | ||
|
|
f97b728968 | ||
|
|
7e6ba78681 | ||
|
|
ed5c74dc17 | ||
|
|
bb3ea40218 | ||
|
|
821e15b696 | ||
|
|
bd3fa8658f | ||
|
|
82d619b2a7 | ||
|
|
8d9d9736ba | ||
|
|
3fca66857d | ||
|
|
4853520eb3 | ||
|
|
5481dab53d | ||
|
|
6f60fa9a98 | ||
|
|
cba9ad78db | ||
|
|
bbc8f4e6ac | ||
|
|
ed3a3babdb | ||
|
|
4415d4111e | ||
|
|
c75c0152ce | ||
|
|
993bb89e02 | ||
|
|
9f01145bc6 | ||
|
|
c1d9e0ecd4 | ||
|
|
f610c96a0b | ||
|
|
8b546600db | ||
|
|
f08471ccda | ||
|
|
d19d7077e4 | ||
|
|
07a4d13c0f | ||
|
|
9e90d1768b | ||
|
|
91e5002050 | ||
|
|
eb68d0d453 | ||
|
|
2bdb5d2b42 | ||
|
|
b62cd7905d | ||
|
|
58faa1053b | ||
|
|
e909884d03 | ||
|
|
5e84fd0570 | ||
|
|
98c0f567fc | ||
|
|
379d20fc3c | ||
|
|
c12f94653e | ||
|
|
2392b4aa40 | ||
|
|
36055ba978 | ||
|
|
73541f2d4f | ||
|
|
03030ab1db | ||
|
|
c98d6e31c0 | ||
|
|
49b73aa024 | ||
|
|
bd8b737642 | ||
|
|
dd8a122933 | ||
|
|
0b799e4300 | ||
|
|
8517897c34 | ||
|
|
72889535e7 | ||
|
|
878f7078a2 | ||
|
|
bd8118c124 | ||
|
|
3d5ffe76ef | ||
|
|
c49f8999d3 | ||
|
|
cc62e345eb | ||
|
|
ae58d5c2b9 | ||
|
|
92e736213b | ||
|
|
7d6b5c358f | ||
|
|
f854746bd8 | ||
|
|
e1e05af0ba | ||
|
|
224ec3c1fb | ||
|
|
c3ac4badbf | ||
|
|
398c5d5dcd | ||
|
|
e7697595c8 | ||
|
|
b0ecac563c | ||
|
|
5cb45c52c2 | ||
|
|
0453af65fa | ||
|
|
53cfea40a4 | ||
|
|
386e51d159 | ||
|
|
eb8eec09c5 | ||
|
|
4a4ddbd5cb | ||
|
|
a563d8fed4 | ||
|
|
7658211537 | ||
|
|
e736ecafff | ||
|
|
cee3e126a4 | ||
|
|
f4a48f6016 | ||
|
|
877b22c294 | ||
|
|
8cc8e45b4f | ||
|
|
3f67b9209c | ||
|
|
a2b8b700df | ||
|
|
80cc59375f | ||
|
|
2bb911023c | ||
|
|
ab355a3576 | ||
|
|
6c02d1c704 | ||
|
|
66c3631b3d | ||
|
|
435ef30f26 | ||
|
|
17a96416f0 | ||
|
|
4378268117 | ||
|
|
622aef5ffe | ||
|
|
174af36000 | ||
|
|
2d64b50559 | ||
|
|
272c19de70 | ||
|
|
6a1142b403 | ||
|
|
9937951fb7 | ||
|
|
002129c299 | ||
|
|
0c2f655a27 | ||
|
|
fb16735dec | ||
|
|
aa6e523780 | ||
|
|
bfd15c1818 | ||
|
|
027d85402b | ||
|
|
99b9467dc2 | ||
|
|
70bf4a7392 | ||
|
|
b50fbcf760 | ||
|
|
b74bf9f666 | ||
|
|
c0feca136a | ||
|
|
0a4a9e3d2c | ||
|
|
0b29dd4ca5 | ||
|
|
9cce4456d0 | ||
|
|
ca4f06a313 | ||
|
|
7dd9ee528e | ||
|
|
cdf6ff7152 | ||
|
|
9c2104d947 | ||
|
|
d1c8026a1e | ||
|
|
14efa81986 | ||
|
|
b3314dc16b | ||
|
|
06135f38ae | ||
|
|
dbbab8ded0 | ||
|
|
6e77f1d514 | ||
|
|
4b6e80e364 | ||
|
|
8a1b112727 | ||
|
|
961f0ae27b | ||
|
|
e819656a34 | ||
|
|
024e03acc9 | ||
|
|
462d7729c9 | ||
|
|
df857fd541 | ||
|
|
9b208bf297 | ||
|
|
5af9da4d3c | ||
|
|
1d995136a5 | ||
|
|
ba15add4db | ||
|
|
0aca478c57 | ||
|
|
0ee4f2b75b | ||
|
|
6e53cb6281 | ||
|
|
de715304dc | ||
|
|
81854112e3 | ||
|
|
87526b9ec5 | ||
|
|
f79187825f | ||
|
|
0443ac2c9d | ||
|
|
d2c51e3667 | ||
|
|
d15d7fa01d | ||
|
|
df32b3131b | ||
|
|
d96d17d7e6 | ||
|
|
b6c69441f5 | ||
|
|
33f3372c6b | ||
|
|
613ba2db64 | ||
|
|
9f352976ce | ||
|
|
f83cff7095 | ||
|
|
433c09a9f3 | ||
|
|
930337bf88 | ||
|
|
81e48ba9fd | ||
|
|
cb2fd1e940 | ||
|
|
6d4eac0dec | ||
|
|
f4f6a8fcc1 | ||
|
|
920070cce0 | ||
|
|
d12b00c005 | ||
|
|
3a142896c3 | ||
|
|
58682cec0c | ||
|
|
37ef7a4e4f | ||
|
|
5266591c88 | ||
|
|
d4b6147fcc | ||
|
|
31232d4d72 | ||
|
|
3fe35217cb | ||
|
|
04ef47376d | ||
|
|
aa2b1cae88 | ||
|
|
e545b6f0a1 | ||
|
|
db42d9cab7 | ||
|
|
b11c773f32 | ||
|
|
c34df13e65 | ||
|
|
a55a08a91e | ||
|
|
c488b28c3c | ||
|
|
300861a49e | ||
|
|
09a8e2d8c2 | ||
|
|
7eba5b539a | ||
|
|
19d15b42f0 | ||
|
|
e23d4aaf53 | ||
|
|
e1fb8e438d | ||
|
|
f682905b26 | ||
|
|
f5fa9fe163 | ||
|
|
627a44bb1f | ||
|
|
ade99a8f05 | ||
|
|
3295954247 | ||
|
|
4f532dbb72 | ||
|
|
ee0a8f01af | ||
|
|
b8936070f9 | ||
|
|
6f29c620ab | ||
|
|
98a2d0f1af | ||
|
|
e08601900e | ||
|
|
cf818fba47 | ||
|
|
0c8a649035 | ||
|
|
843a978644 | ||
|
|
cbeede66bb | ||
|
|
a506cbbcb0 | ||
|
|
bb40c31031 | ||
|
|
34adcc1c04 | ||
|
|
ac42ec106f | ||
|
|
c3ed940ac2 | ||
|
|
7c74c2f22a | ||
|
|
d0f4530e85 | ||
|
|
f8b296fc60 | ||
|
|
882247e5f4 | ||
|
|
a297c3b41e | ||
|
|
45121916d0 | ||
|
|
6b82429e30 | ||
|
|
707753a743 | ||
|
|
10db14475f | ||
|
|
4a5f7b06cf | ||
|
|
f643e7b316 | ||
|
|
5a5b284e96 | ||
|
|
6699a0519d | ||
|
|
8b08edeee7 | ||
|
|
41ecd2a3d5 | ||
|
|
f36158133e | ||
|
|
f0ee1893ee | ||
|
|
f455dbdd22 | ||
|
|
27c71fa40e | ||
|
|
be37daec56 | ||
|
|
9676f51512 | ||
|
|
f8ada8042a | ||
|
|
89e15b90b1 | ||
|
|
5b008b789b | ||
|
|
25d35cf465 | ||
|
|
ee662986ab | ||
|
|
946a39c739 | ||
|
|
412cd75edd | ||
|
|
d0471f66ea | ||
|
|
a12f37e4d2 | ||
|
|
b741b42c64 | ||
|
|
7f8c625b0e | ||
|
|
83b6b04eea | ||
|
|
aac6fb4334 | ||
|
|
ca9f47d7c0 |
2
.github/workflows/ci-dev.yml
vendored
2
.github/workflows/ci-dev.yml
vendored
@@ -53,7 +53,7 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
- uses: dorny/paths-filter@v2
|
||||
- uses: dorny/paths-filter@v3
|
||||
id: changes
|
||||
with:
|
||||
filters: |
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -9,3 +9,4 @@ dist
|
||||
.vercel
|
||||
.idea
|
||||
.env
|
||||
.data
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"git": {
|
||||
"commitMessage": "chore(release): ${version}"
|
||||
"commitMessage": "chore(release): v${version}",
|
||||
"tagName": "v${version}"
|
||||
},
|
||||
"npm": {
|
||||
"publish": false
|
||||
@@ -11,7 +12,7 @@
|
||||
"web": true
|
||||
},
|
||||
"hooks": {
|
||||
"before:init": ["pnpm lint"]
|
||||
"before:init": ["pnpm lint", "pnpm typecheck"]
|
||||
},
|
||||
"plugins": {
|
||||
"@release-it/conventional-changelog": {
|
||||
|
||||
171
CHANGELOG.md
171
CHANGELOG.md
@@ -1,5 +1,176 @@
|
||||
# Changelog
|
||||
|
||||
## [2.17.0](https://github.com/nuxt/ui/compare/v2.16.0...v2.17.0) (2024-06-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Alert:** add `actions` slot ([#1785](https://github.com/nuxt/ui/issues/1785)) ([c8dd71c](https://github.com/nuxt/ui/commit/c8dd71c4f5a5239811b07b50f1dc802101af07d5))
|
||||
* **Form:** update and migrate `valibot` to v0.31.0 ([#1848](https://github.com/nuxt/ui/issues/1848)) ([1d5bd89](https://github.com/nuxt/ui/commit/1d5bd89d5881163fc6dc917e138b9d8304dff6c4))
|
||||
* **Notification:** allow ring customization with `{color}` ([#1830](https://github.com/nuxt/ui/issues/1830)) ([3ebff4d](https://github.com/nuxt/ui/commit/3ebff4d133372e339e2c4c439576e9e192b29cc3))
|
||||
* **Slideover:** handle `top` and `bottom` side ([#1834](https://github.com/nuxt/ui/issues/1834)) ([50ad14f](https://github.com/nuxt/ui/commit/50ad14f9dffe4f76bef888cd10d30b417c75bca5))
|
||||
* **Tabs:** add `content` prop to avoid the render of the HTML markup ([#1831](https://github.com/nuxt/ui/issues/1831)) ([6e2678d](https://github.com/nuxt/ui/commit/6e2678d1d8a498322eb3eff909ccbba55e40a2b7))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Alert/Notification:** use `div` for description ([e8898d1](https://github.com/nuxt/ui/commit/e8898d15a667ba66e78828315e3cc4e92845cd3f)), closes [#1551](https://github.com/nuxt/ui/issues/1551)
|
||||
* **Alert:** base style not applied on icon ([#1859](https://github.com/nuxt/ui/issues/1859)) ([f65aefb](https://github.com/nuxt/ui/commit/f65aefb7067c1c64c1355b5d699129e716ef1281))
|
||||
* **Breadcrumb:** allow `aria-current` to be overrideable ([ebfb835](https://github.com/nuxt/ui/commit/ebfb8350339725c0a6f88c73f16bff01d61538c2)), closes [#1856](https://github.com/nuxt/ui/issues/1856)
|
||||
* **Carousel:** prevent mouse click when dragging ([#1781](https://github.com/nuxt/ui/issues/1781)) ([4f0d00f](https://github.com/nuxt/ui/commit/4f0d00f7a6eebf05adceaf1e7c2869ad91949cf3))
|
||||
* **CommandPalette:** hide `empty-state` when `null` ([249bbd4](https://github.com/nuxt/ui/commit/249bbd49dc8420603e8d561543d237abeb400908)), closes [#1787](https://github.com/nuxt/ui/issues/1787)
|
||||
* **Form:** maintain other errors when using `setErrors` with a path ([#1818](https://github.com/nuxt/ui/issues/1818)) ([06990be](https://github.com/nuxt/ui/commit/06990beabf67f668322b4d3fb2ec93cc4f3bdcd4))
|
||||
* **Input:** hide wrapper when type is `hidden` ([#1797](https://github.com/nuxt/ui/issues/1797)) ([e7c2f78](https://github.com/nuxt/ui/commit/e7c2f7856c05ed96f48c83d64d8e1d3f41ab58fe))
|
||||
* **Link:** typo in `exactHash` type ([581b470](https://github.com/nuxt/ui/commit/581b470cc79c2315bb2d56e02a7c134a7861c616)), closes [#1767](https://github.com/nuxt/ui/issues/1767)
|
||||
* **SelectMenu:** wrong placeholder color when `modelValue` is an empty string ([9b9ccdb](https://github.com/nuxt/ui/commit/9b9ccdb59e98fed096dd18809af646b10de46b9f)), closes [#1862](https://github.com/nuxt/ui/issues/1862)
|
||||
* **Select:** remove defaults for `value` and `text` ([6c124bb](https://github.com/nuxt/ui/commit/6c124bb1ac2fef116161da56a3a8e5f92144ce3a)), closes [#1702](https://github.com/nuxt/ui/issues/1702)
|
||||
|
||||
## [2.16.0](https://github.com/nuxt/ui/compare/v2.15.2...v2.16.0) (2024-05-07)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **Input:** redesign `file` type without absolute positioning (#1712)
|
||||
|
||||
### Features
|
||||
|
||||
* **InputMenu/SelectMenu:** allow lazy search ([#1705](https://github.com/nuxt/ui/issues/1705)) ([7e6ba78](https://github.com/nuxt/ui/commit/7e6ba786816516ab5007a2ff15fc974cfdd796ab))
|
||||
* **module:** HMR support with `@nuxtjs/tailwindcss` ([#1665](https://github.com/nuxt/ui/issues/1665)) ([821e15b](https://github.com/nuxt/ui/commit/821e15b696b03d0f5e20e001d39f86a8b3cec426))
|
||||
* **Table:** allow providing a `<caption>` ([#1680](https://github.com/nuxt/ui/issues/1680)) ([3fca668](https://github.com/nuxt/ui/commit/3fca66857d3616bf24a1b0579c90179a7883869d))
|
||||
* **useToast:** allow clearing all notifications ([#1695](https://github.com/nuxt/ui/issues/1695)) ([82d619b](https://github.com/nuxt/ui/commit/82d619b2a75b9d08f3f5b314d37c30d77d8341e9))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Breadcrumb:** pass `click` event to `ULink` ([5481dab](https://github.com/nuxt/ui/commit/5481dab53dbe0b28188b4a16811f3e8816d93edf))
|
||||
* **Input:** redesign `file` type without absolute positioning ([#1712](https://github.com/nuxt/ui/issues/1712)) ([ed5c74d](https://github.com/nuxt/ui/commit/ed5c74dc17df784485eabc39c83e62ada9210a49))
|
||||
* **Notification:** update timer when timeout prop changes ([#1673](https://github.com/nuxt/ui/issues/1673)) ([cba9ad7](https://github.com/nuxt/ui/commit/cba9ad78db58cb9228bb9c96f0469d43bde2bf3e))
|
||||
* **Slideover:** export and clean types ([#1692](https://github.com/nuxt/ui/issues/1692)) ([bd3fa86](https://github.com/nuxt/ui/commit/bd3fa8658f84fb7bd96d322968462c5eaa987b86))
|
||||
* **Table:** provide `aria-sort` for sortable table headings ([#1675](https://github.com/nuxt/ui/issues/1675)) ([6f60fa9](https://github.com/nuxt/ui/commit/6f60fa9a980020f6a5afc2916e699a7f9a47e8ce))
|
||||
|
||||
## [2.15.2](https://github.com/nuxt/ui/compare/v2.15.1...v2.15.2) (2024-04-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Accordion:** add `unmount` prop to allow lazy mounting for heavy components ([#1590](https://github.com/nuxt/ui/issues/1590)) ([91e5002](https://github.com/nuxt/ui/commit/91e50020507ac66992dfb52b3e0ad1a1ae5614b5))
|
||||
* **Table:** add `checkbox` ui config ([#1409](https://github.com/nuxt/ui/issues/1409)) ([8b54660](https://github.com/nuxt/ui/commit/8b546600dbfbff187d9c5be1b35ea1772e94f83f))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Breadcrumb:** missing `min-w-0` on wrapper to truncate ([9f01145](https://github.com/nuxt/ui/commit/9f01145bc674378371ff34d7110f3235b57d2459)), closes [#1650](https://github.com/nuxt/ui/issues/1650)
|
||||
* **Carousel:** next and prev buttons disabled ([#1619](https://github.com/nuxt/ui/issues/1619)) ([e909884](https://github.com/nuxt/ui/commit/e909884d0327bfd7b4d5551382123f8998beff6a))
|
||||
* **Popover/Dropdown:** prevent unintended closure on touchstart in mobile devices ([#1609](https://github.com/nuxt/ui/issues/1609)) ([2392b4a](https://github.com/nuxt/ui/commit/2392b4aa405430fc22766f130448a7cc5ced9a3a))
|
||||
* **Slideover:** remove dynamic component when closing ([#1615](https://github.com/nuxt/ui/issues/1615)) ([58faa10](https://github.com/nuxt/ui/commit/58faa1053b9be3f627c3fcff1bcaa14850bb9e7f))
|
||||
* **Slideover:** wait for transition to complete to reset state ([#1624](https://github.com/nuxt/ui/issues/1624)) ([07a4d13](https://github.com/nuxt/ui/commit/07a4d13c0fcb05c87fb42e02a3a2d6c5c52ccf09))
|
||||
|
||||
## [2.15.1](https://github.com/nuxt/ui/compare/v2.15.0...v2.15.1) (2024-04-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Avatar:** add `as` prop to use `NuxtImg` underneath ([49b73aa](https://github.com/nuxt/ui/commit/49b73aa024be14a9aa150a2804f4dcb18542fa49)), closes [#1577](https://github.com/nuxt/ui/issues/1577)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Checkbox:** `[@change](https://github.com/change)` event value ([#1580](https://github.com/nuxt/ui/issues/1580)) ([c98d6e3](https://github.com/nuxt/ui/commit/c98d6e31c0e3f46b97957d5cf3de7f9da1f70c58))
|
||||
* **Divider:** add `w-full` only on horizontal wrapper ([#1565](https://github.com/nuxt/ui/issues/1565)) ([bd8b737](https://github.com/nuxt/ui/commit/bd8b737642280e6a83b67f9a27dd7a823a77e963))
|
||||
* **Dropdown:** missing `mouseenter` event on container ([7288953](https://github.com/nuxt/ui/commit/72889535e7e9763e7ebf59498f22c39bf09d6477))
|
||||
* **Input/SelectMenu:** handle `file` type and `change` events ([#1570](https://github.com/nuxt/ui/issues/1570)) ([878f707](https://github.com/nuxt/ui/commit/878f7078a28c5e70a662682d1293db466d518c7d))
|
||||
* **Popover:** missing `mouseenter` event on container ([8517897](https://github.com/nuxt/ui/commit/8517897c34adaa9e3624f867b43106deb59fcbe8)), closes [#1564](https://github.com/nuxt/ui/issues/1564)
|
||||
|
||||
## [2.15.0](https://github.com/nuxt/ui/compare/v2.14.2...v2.15.0) (2024-03-26)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **forms:** normalize input emits (#1560)
|
||||
|
||||
### Features
|
||||
|
||||
* **Accordion:** emit `open` event with index ([#1559](https://github.com/nuxt/ui/issues/1559)) ([224ec3c](https://github.com/nuxt/ui/commit/224ec3c1fbfb9875398d3af60e5fe49e47ce55b1))
|
||||
* **Alert:** add `icon` & `avatar` slots ([#1401](https://github.com/nuxt/ui/issues/1401)) ([cee3e12](https://github.com/nuxt/ui/commit/cee3e126a472735c0e484de315868bb28287164f))
|
||||
* **Slideover:** open programmatically ([#1465](https://github.com/nuxt/ui/issues/1465)) ([e769759](https://github.com/nuxt/ui/commit/e7697595c8769ceea61690f6c2f294206de50972))
|
||||
* **Toggle:** add `loading` prop ([#1546](https://github.com/nuxt/ui/issues/1546)) ([e1e05af](https://github.com/nuxt/ui/commit/e1e05af0bafd1e5d1b91f374562ed8d389fb0cae))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ButtonGroup:** nested group elements ([#1530](https://github.com/nuxt/ui/issues/1530)) ([7658211](https://github.com/nuxt/ui/commit/765821153753d1a49276421511224336aebcdd2f))
|
||||
* **Carousel:** add tab-based ARIA roles ([#1516](https://github.com/nuxt/ui/issues/1516)) ([e736eca](https://github.com/nuxt/ui/commit/e736ecafff59f9d4eb88b366ef1e9d26449b8ca3))
|
||||
* **Checkbox:** bind `data-n-ids` to root element ([#1495](https://github.com/nuxt/ui/issues/1495)) ([a2b8b70](https://github.com/nuxt/ui/commit/a2b8b700df6ad0907a5d4d622d178d1345b55b83))
|
||||
* **forms:** normalize input emits ([#1560](https://github.com/nuxt/ui/issues/1560)) ([92e7362](https://github.com/nuxt/ui/commit/92e736213b221d5ec8cfb8881fda4fc65ce7dfa0))
|
||||
* **InputMenu:** trigger alignement on safari ([f4a48f6](https://github.com/nuxt/ui/commit/f4a48f6016ede664e4f46741e7811b0dbe0acfbe)), closes [#1505](https://github.com/nuxt/ui/issues/1505)
|
||||
* opt in to `import.meta.*` properties ([#1561](https://github.com/nuxt/ui/issues/1561)) ([cc62e34](https://github.com/nuxt/ui/commit/cc62e345eb96a632730bed796c77afe7ecdadf2a))
|
||||
* **Popover/Dropdown:** use `[@touchstart](https://github.com/touchstart).passive` instead of `[@touchstart](https://github.com/touchstart).prevent` ([#1520](https://github.com/nuxt/ui/issues/1520)) ([a563d8f](https://github.com/nuxt/ui/commit/a563d8fed44535107080fee094995d87ca5dc2b6))
|
||||
* **SelectMenu:** `filteredOptions` might be undefined ([#1541](https://github.com/nuxt/ui/issues/1541)) ([b0ecac5](https://github.com/nuxt/ui/commit/b0ecac563c5702fe40cf42a8861b1d2d1366d423))
|
||||
* **SelectMenu:** handle `Boolean` type as model value ([#1550](https://github.com/nuxt/ui/issues/1550)) ([c49f899](https://github.com/nuxt/ui/commit/c49f8999d319ec487672ebd68e8b3f0031843cd6))
|
||||
|
||||
## [2.14.2](https://github.com/nuxt/ui/compare/v2.14.1...v2.14.2) (2024-03-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Alert:** improve `description` alignment when no title provided ([ca4f06a](https://github.com/nuxt/ui/commit/ca4f06a313314af5813007878a9b6c8f1003c6d1)), closes [#1408](https://github.com/nuxt/ui/issues/1408)
|
||||
* **Checkbox:** label interaction without `FormGroup` ([#1427](https://github.com/nuxt/ui/issues/1427)) ([6e77f1d](https://github.com/nuxt/ui/commit/6e77f1d5144d7d87b0c76b43ecf3d731166c808b))
|
||||
* **Dropdown:** active/inactive dropdown links ([#1407](https://github.com/nuxt/ui/issues/1407)) ([6a1142b](https://github.com/nuxt/ui/commit/6a1142b4032150def78c69080df455f7d2a25e7b))
|
||||
* **Dropdown:** improve `hover` mode on touch devices ([70bf4a7](https://github.com/nuxt/ui/commit/70bf4a73921f47fcd41599874b595a6eed947f5a))
|
||||
* **HorizontalNavigation:** add `relative` class to icon ([0a4a9e3](https://github.com/nuxt/ui/commit/0a4a9e3d2c4a7584570e4ab7ae6fe8265c960a33))
|
||||
* **Modal:** remove `overflow-hidden` ([#1460](https://github.com/nuxt/ui/issues/1460)) ([002129c](https://github.com/nuxt/ui/commit/002129c29926df5a816288b916194ab28cf4c8a4))
|
||||
* **Notification:** improve `description` alignment when no title provided ([9cce445](https://github.com/nuxt/ui/commit/9cce4456d03c52daca4d7347e60cbcd7f501317a))
|
||||
* **Popover:** improve `hover` mode on touch devices ([b50fbcf](https://github.com/nuxt/ui/commit/b50fbcf760e908579e81f6e57234f2080e2bf035))
|
||||
* **RadioGroup:** add missing `fieldset` config ([2d64b50](https://github.com/nuxt/ui/commit/2d64b50559946b166c02cfe921e63d746cdc09d4)), closes [#1472](https://github.com/nuxt/ui/issues/1472)
|
||||
* **SelectMenu:** check `null` model value ([4b6e80e](https://github.com/nuxt/ui/commit/4b6e80e3646e263a83614830d9ec6adb0edf2ede)), closes [#1421](https://github.com/nuxt/ui/issues/1421)
|
||||
* **Tooltip:** arrow not hidden on mobile ([272c19d](https://github.com/nuxt/ui/commit/272c19de708144b1b132b98a7287254974f4e144)), closes [#1470](https://github.com/nuxt/ui/issues/1470)
|
||||
* **VerticalNavigation:** add `relative` class to icon ([0b29dd4](https://github.com/nuxt/ui/commit/0b29dd4ca560cac7d151132e086eab17c0498a5c)), closes [#1245](https://github.com/nuxt/ui/issues/1245)
|
||||
|
||||
## [2.14.1](https://github.com/nuxt/ui/compare/v2.14.0...v2.14.1) (2024-02-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **module:** revert tailwind config from [#1272](https://github.com/nuxt/ui/issues/1272) ([#1404](https://github.com/nuxt/ui/issues/1404)) ([ba15add](https://github.com/nuxt/ui/commit/ba15add4db5d2f84e987819628cbbf88edcbad57))
|
||||
|
||||
## [2.14.0](https://github.com/nuxt/ui/compare/v2.13.0...v2.14.0) (2024-02-22)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Carousel:** expose methods to allow autoplay ([41ecd2a](https://github.com/nuxt/ui/commit/41ecd2a3d553886db3e32d9f48a477268d93f3c6)), closes [#1300](https://github.com/nuxt/ui/issues/1300)
|
||||
* **Divider:** handle `size` prop ([#1307](https://github.com/nuxt/ui/issues/1307)) ([cbeede6](https://github.com/nuxt/ui/commit/cbeede66bb3bd7778e03c19ebbf55bf7bd753cb8))
|
||||
* **Form:** use nuxt `useId` to bind input labels ([#1211](https://github.com/nuxt/ui/issues/1211)) ([27c71fa](https://github.com/nuxt/ui/commit/27c71fa40ecb9f8524fee7f3d17a384bc8812d25))
|
||||
* **Input:** handle type `file` ([946a39c](https://github.com/nuxt/ui/commit/946a39c73990dc352cf7b9a77bfaec339cdcab34)), closes [#563](https://github.com/nuxt/ui/issues/563)
|
||||
* **Modal:** open programmatically ([#1319](https://github.com/nuxt/ui/issues/1319)) ([6f29c62](https://github.com/nuxt/ui/commit/6f29c620ab758e27be63f8af53674828b59fb6ed))
|
||||
* **Table:** display progress bar when `loading` ([#1362](https://github.com/nuxt/ui/issues/1362)) ([3fe3521](https://github.com/nuxt/ui/commit/3fe35217cbc0cef7f41550c175e4e7ea2cc939a8))
|
||||
* **Tabs:** add `unmount` prop as `false` by default ([843a978](https://github.com/nuxt/ui/commit/843a9786445f6170c1380e3b404151da52b5a154)), closes [#663](https://github.com/nuxt/ui/issues/663)
|
||||
* **Textarea:** add `maxrows` prop to restrict autoresize ([#1302](https://github.com/nuxt/ui/issues/1302)) ([f643e7b](https://github.com/nuxt/ui/commit/f643e7b316639a79cf03da25250ab0fa85f466d5))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Accordion:** style disclosure `div` after [#1199](https://github.com/nuxt/ui/issues/1199) ([882247e](https://github.com/nuxt/ui/commit/882247e5f40bf41fdfdffea501de5c898a7fb0b2))
|
||||
* **Alert:** remove `required` title to prevent warning when using slot ([e545b6f](https://github.com/nuxt/ui/commit/e545b6f0a128475166dcea3c1028798b106805f3))
|
||||
* **Card:** prevent `body` padding without default slot ([f682905](https://github.com/nuxt/ui/commit/f682905b26a22546634e9adc4b838a7741dbd7c9))
|
||||
* **components:** hydration attribute mismatch with vue `3.4` ([#1199](https://github.com/nuxt/ui/issues/1199)) ([10db144](https://github.com/nuxt/ui/commit/10db14475f7a527180be3fcf33cc5d3af52452c9))
|
||||
* **Form:** improve `validate` path type ([#1370](https://github.com/nuxt/ui/issues/1370)) ([5266591](https://github.com/nuxt/ui/commit/5266591c886422d5265e46e08e1276913d12bed1))
|
||||
* **Form:** return false when silent validation fails ([#1371](https://github.com/nuxt/ui/issues/1371)) ([d4b6147](https://github.com/nuxt/ui/commit/d4b6147fcceb7ff9cebe1586bb3094b10f50acb5))
|
||||
* **Link:** check `disabled` prop before navigating ([#1321](https://github.com/nuxt/ui/issues/1321)) ([ac42ec1](https://github.com/nuxt/ui/commit/ac42ec106ff259e1d44515e5fb3b5236559ac713))
|
||||
* **Meter:** missing import of `Icon` component ([f8b296f](https://github.com/nuxt/ui/commit/f8b296fc60b93c4656fd397f8eb6b06b4a1dcd93)), closes [#1328](https://github.com/nuxt/ui/issues/1328)
|
||||
* **module:** prevent tailwind warn with `bun` ([bb40c31](https://github.com/nuxt/ui/commit/bb40c3103174a039f65b31c65fcc5d40cb29ce6b)), closes [#809](https://github.com/nuxt/ui/issues/809)
|
||||
* **module:** put back `all` option in icons plugin ([412cd75](https://github.com/nuxt/ui/commit/412cd75eddb6140d7d9b3358b04df1e61f22b481)), closes [#1237](https://github.com/nuxt/ui/issues/1237)
|
||||
* **Notification:** remove `required` title to prevent warning when using slot ([aa2b1ca](https://github.com/nuxt/ui/commit/aa2b1cae8881dece9a629dc95a8f9df88f9bbd27))
|
||||
* **Progress:** prevent `NaN` percent display when indeterminate ([a55a08a](https://github.com/nuxt/ui/commit/a55a08a91eca6f4c7ff3ad40ee566b6445d2dfd0))
|
||||
* **RadioGroup:** pass `help` prop to radio children ([5a5b284](https://github.com/nuxt/ui/commit/5a5b284e967ca9cdb6c7df9809ed4f4569a65cfa)), closes [#1313](https://github.com/nuxt/ui/issues/1313)
|
||||
* **SelectMenu:** revert component `is` after [#1199](https://github.com/nuxt/ui/issues/1199) ([d0f4530](https://github.com/nuxt/ui/commit/d0f4530e8572a08d544041dec1f24a51bbc3b1e8))
|
||||
* **utils:** prevent merge of `popper` key ([9f35297](https://github.com/nuxt/ui/commit/9f352976ced5845a5fad00a6630d0166941a8a13)), closes [#1393](https://github.com/nuxt/ui/issues/1393)
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* Revert "docs: add missing `overflow-hidden` on components" ([b893607](https://github.com/nuxt/ui/commit/b8936070f9e1f866a21d39f6c45140f86efebec4))
|
||||
|
||||
## [2.13.0](https://github.com/nuxt/ui/compare/v2.12.3...v2.13.0) (2024-01-30)
|
||||
|
||||
|
||||
|
||||
25
README.md
25
README.md
@@ -1,4 +1,4 @@
|
||||
[](https://ui.nuxt.com)
|
||||
[](https://ui.nuxt.com)
|
||||
|
||||
# Nuxt UI
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
[![License][license-src]][license-href]
|
||||
[![Nuxt][nuxt-src]][nuxt-href]
|
||||
|
||||
Nuxt UI provides everything related to UI when building Nuxt applications: components, icons, colors, dark mode and also keyboard shortcuts.
|
||||
Nuxt UI is a module that provides a set of Vue components and composables built with [Tailwind CSS](https://tailwindcss.com/) and [Headless UI](https://headlessui.dev/) to help you build beautiful and accessible user interfaces.
|
||||
|
||||
Is has been developed by [NuxtLabs](https://nuxtlabs.com/) for [Volta](https://volta.net), [Nuxt Studio](https://nuxt.studio/) and the Nuxt community.
|
||||
Its goal is to provide everything related to UI when building a Nuxt app. This includes components, icons, colors, dark mode but also keyboard shortcuts.
|
||||
|
||||
## Features
|
||||
|
||||
@@ -27,24 +27,7 @@ Read more on [ui.nuxt.com](https://ui.nuxt.com)
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# Using npm
|
||||
npm install @nuxt/ui
|
||||
|
||||
# Using yarn
|
||||
yarn add @nuxt/ui
|
||||
|
||||
# Using pnpm
|
||||
pnpm add @nuxt/ui
|
||||
```
|
||||
|
||||
Then, register the module in your `nuxt.config.ts`:
|
||||
|
||||
```js
|
||||
export default defineNuxtConfig({
|
||||
modules: [
|
||||
'@nuxt/ui'
|
||||
]
|
||||
})
|
||||
npx nuxi@latest module add ui
|
||||
```
|
||||
|
||||
If you want latest updates, please use `@nuxt/ui-edge` in your `package.json`:
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
imports.autoImport=true
|
||||
12
docs/app.vue
12
docs/app.vue
@@ -3,6 +3,8 @@
|
||||
<div>
|
||||
<NuxtLoadingIndicator />
|
||||
|
||||
<Banner v-if="!$route.path.startsWith('/examples')" />
|
||||
|
||||
<Header v-if="!$route.path.startsWith('/examples')" :links="links" />
|
||||
|
||||
<NuxtLayout>
|
||||
@@ -12,7 +14,7 @@
|
||||
<Footer v-if="!$route.path.startsWith('/examples')" />
|
||||
|
||||
<ClientOnly>
|
||||
<LazyUDocsSearch ref="searchRef" :files="files" :navigation="navigation" :links="links" :fuse="{ resultLimit: 1000 }" />
|
||||
<LazyUContentSearch ref="searchRef" :files="files" :navigation="navigation" :links="links" :fuse="{ resultLimit: 42 }" />
|
||||
</ClientOnly>
|
||||
|
||||
<UNotifications>
|
||||
@@ -20,6 +22,8 @@
|
||||
<span v-html="title" />
|
||||
</template>
|
||||
</UNotifications>
|
||||
<UModals />
|
||||
<USlideovers />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -50,7 +54,7 @@ const navigation = computed(() => {
|
||||
]
|
||||
}
|
||||
|
||||
return nav.value.filter(item => item._path !== '/dev')
|
||||
return nav.value?.filter(item => item._path !== '/dev') || []
|
||||
})
|
||||
|
||||
const color = computed(() => colorMode.value === 'dark' ? '#18181b' : 'white')
|
||||
@@ -65,10 +69,10 @@ const links = computed(() => {
|
||||
label: 'Pro',
|
||||
icon: 'i-heroicons-square-3-stack-3d',
|
||||
to: '/pro',
|
||||
active: route.path.startsWith('/pro/getting-started') || route.path.startsWith('/pro/components')
|
||||
active: route.path.startsWith('/pro/getting-started') || route.path.startsWith('/pro/components') || route.path.startsWith('/pro/prose')
|
||||
}, {
|
||||
label: 'Pricing',
|
||||
icon: 'i-heroicons-credit-card',
|
||||
icon: 'i-heroicons-ticket',
|
||||
to: '/pro/pricing'
|
||||
}, {
|
||||
label: 'Templates',
|
||||
|
||||
58
docs/components/Banner.vue
Normal file
58
docs/components/Banner.vue
Normal file
@@ -0,0 +1,58 @@
|
||||
<script setup lang="ts">
|
||||
const id = 'nuxt-ui-banner-1'
|
||||
const to = '/pro/pricing'
|
||||
|
||||
const hideBanner = () => {
|
||||
localStorage.setItem(id, 'true')
|
||||
|
||||
document.querySelector('html')?.classList.add('hide-banner')
|
||||
}
|
||||
|
||||
if (process.server) {
|
||||
useHead({
|
||||
script: [{
|
||||
key: 'prehydrate-template-banner',
|
||||
innerHTML: `
|
||||
if (localStorage.getItem('${id}') === 'true') {
|
||||
document.querySelector('html').classList.add('hide-banner')
|
||||
}`.replace(/\s+/g, ' '),
|
||||
type: 'text/javascript'
|
||||
}]
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="relative bg-primary hover:bg-primary/90 transition-[background] backdrop-blur z-50 app-banner">
|
||||
<UContainer class="py-2">
|
||||
<NuxtLink v-if="to" :to="to" class="focus:outline-none" aria-label="Nuxt UI Pro pricing" tabindex="-1">
|
||||
<span class="absolute inset-0 " aria-hidden="true" />
|
||||
</NuxtLink>
|
||||
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<div class="lg:flex-1 hidden lg:flex items-center" />
|
||||
|
||||
<p class="text-sm font-medium text-white dark:text-gray-900">
|
||||
<UIcon name="i-heroicons-rocket-launch" class="w-5 h-5 align-top flex-shrink-0 pointer-events-none mr-2" />
|
||||
<span class="font-semibold">Nuxt UI Pro v1.0</span> is out with dashboard components!
|
||||
</p>
|
||||
|
||||
<div class="flex items-center justify-end lg:flex-1">
|
||||
<button
|
||||
class="p-1.5 rounded-md inline-flex hover:bg-primary/90"
|
||||
aria-label="Close banner"
|
||||
@click.prevent="hideBanner"
|
||||
>
|
||||
<UIcon name="i-heroicons-x-mark-20-solid" class="w-5 h-5 text-white dark:text-gray-900" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</UContainer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.hide-banner .app-banner {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
@@ -28,7 +28,7 @@
|
||||
const links = [{
|
||||
icon: 'i-simple-icons-figma',
|
||||
label: 'Figma Kit',
|
||||
to: 'https://www.figma.com/community/file/1288455405058138934/nuxt-ui',
|
||||
to: 'https://www.figma.com/community/file/1288455405058138934',
|
||||
target: '_blank'
|
||||
}, {
|
||||
label: 'Playground',
|
||||
|
||||
@@ -11,14 +11,15 @@
|
||||
<Logo class="w-auto h-6" />
|
||||
|
||||
<UBadge v-if="$route.path.startsWith('/pro')" label="Pro" variant="subtle" size="xs" class="-mb-[2px] rounded font-semibold" />
|
||||
<UBadge v-if="$route.path.startsWith('/dev')" label="Edge" variant="subtle" size="xs" class="-mb-[2px] rounded font-semibold" />
|
||||
</NuxtLink>
|
||||
</template>
|
||||
|
||||
<template #right>
|
||||
<ColorPicker />
|
||||
|
||||
<UTooltip text="Search" :shortcuts="[metaSymbol, 'K']">
|
||||
<UDocsSearchButton :label="null" />
|
||||
<UTooltip text="Search" :shortcuts="[metaSymbol, 'K']" :popper="{ strategy: 'absolute' }">
|
||||
<UContentSearchButton :label="null" />
|
||||
</UTooltip>
|
||||
|
||||
<UColorModeButton />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<UPopover mode="hover">
|
||||
<UPopover mode="hover" :popper="{ strategy: 'absolute' }" :ui="{ width: 'w-[156px]' }">
|
||||
<template #default="{ open }">
|
||||
<UButton color="gray" variant="ghost" square :class="[open && 'bg-gray-50 dark:bg-gray-800']" aria-label="Color picker">
|
||||
<UIcon name="i-heroicons-swatch-20-solid" class="w-5 h-5 text-primary-500 dark:text-primary-400" />
|
||||
|
||||
@@ -51,11 +51,9 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// @ts-expect-error
|
||||
import { transformContent } from '@nuxt/content/transformers'
|
||||
// @ts-ignore
|
||||
import { useShikiHighlighter } from '@nuxtjs/mdc/runtime'
|
||||
import { upperFirst, camelCase, kebabCase } from 'scule'
|
||||
import { useShikiHighlighter } from '~/composables/useShikiHighlighter'
|
||||
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const props = defineProps({
|
||||
@@ -124,6 +122,7 @@ const componentProps = reactive({ ...props.props })
|
||||
const { $prettier } = useNuxtApp()
|
||||
const appConfig = useAppConfig()
|
||||
const route = useRoute()
|
||||
const highlighter = useShikiHighlighter()
|
||||
|
||||
let name = props.slug || `U${upperFirst(camelCase(route.params.slug[route.params.slug.length - 1]))}`
|
||||
|
||||
@@ -269,8 +268,6 @@ function renderObject (obj: any) {
|
||||
return obj
|
||||
}
|
||||
|
||||
const shikiHighlighter = useShikiHighlighter({})
|
||||
const codeHighlighter = async (code: string, lang: string, theme: any, highlights: number[]) => shikiHighlighter.getHighlightedAST(code, lang, theme, { highlights })
|
||||
const { data: ast } = await useAsyncData(
|
||||
`${name}-ast-${JSON.stringify({ props: componentProps, slots: props.slots, code: props.code })}`,
|
||||
async () => {
|
||||
@@ -284,7 +281,7 @@ const { data: ast } = await useAsyncData(
|
||||
return transformContent('content:_markdown.md', formatted, {
|
||||
markdown: {
|
||||
highlight: {
|
||||
highlighter: codeHighlighter,
|
||||
highlighter,
|
||||
theme: {
|
||||
light: 'material-theme-lighter',
|
||||
default: 'material-theme',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div class="[&>div>pre]:!rounded-t-none [&>div>pre]:!mt-0">
|
||||
<div
|
||||
v-if="hasPreview"
|
||||
class="flex border border-gray-200 dark:border-gray-700 relative rounded-t-md"
|
||||
:class="[{ 'p-4': padding, 'rounded-b-md': !hasCode, 'border-b-0': hasCode, 'not-prose': !prose }, backgroundClass, extraClass]"
|
||||
>
|
||||
@@ -21,10 +22,8 @@
|
||||
<script setup lang="ts">
|
||||
import { camelCase } from 'scule'
|
||||
import { fetchContentExampleCode } from '~/composables/useContentExamplesCode'
|
||||
// @ts-expect-error
|
||||
import { transformContent } from '@nuxt/content/transformers'
|
||||
// @ts-ignore
|
||||
import { useShikiHighlighter } from '@nuxtjs/mdc/runtime'
|
||||
import { useShikiHighlighter } from '~/composables/useShikiHighlighter'
|
||||
|
||||
const props = defineProps({
|
||||
component: {
|
||||
@@ -39,6 +38,10 @@ const props = defineProps({
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
hiddenPreview: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hiddenCode: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
@@ -78,15 +81,15 @@ if (['command-palette-theme-algolia', 'command-palette-theme-raycast', 'vertical
|
||||
const instance = getCurrentInstance()
|
||||
const camelName = camelCase(component)
|
||||
const data = await fetchContentExampleCode(camelName)
|
||||
const highlighter = useShikiHighlighter()
|
||||
|
||||
const hasCode = computed(() => !props.hiddenCode && (data?.code || instance.slots.code))
|
||||
const hasPreview = computed(() => !props.hiddenPreview && (props.component || instance.slots.default))
|
||||
|
||||
const shikiHighlighter = useShikiHighlighter({})
|
||||
const codeHighlighter = async (code: string, lang: string, theme: any, highlights: number[]) => shikiHighlighter.getHighlightedAST(code, lang, theme, { highlights })
|
||||
const { data: ast } = await useAsyncData(`content-example-${camelName}-ast`, () => transformContent('content:_markdown.md', `\`\`\`vue\n${data?.code ?? ''}\n\`\`\``, {
|
||||
markdown: {
|
||||
highlight: {
|
||||
highlighter: codeHighlighter,
|
||||
highlighter,
|
||||
theme: {
|
||||
light: 'material-theme-lighter',
|
||||
default: 'material-theme',
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// @ts-expect-error
|
||||
import { transformContent } from '@nuxt/content/transformers'
|
||||
import { upperFirst, camelCase } from 'scule'
|
||||
import json5 from 'json5'
|
||||
import { useShikiHighlighter } from '~/composables/useShikiHighlighter'
|
||||
import * as config from '#ui/ui.config'
|
||||
|
||||
const props = defineProps({
|
||||
@@ -16,6 +17,7 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
const highlighter = useShikiHighlighter()
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const slug = props.slug || route.params.slug[route.params.slug.length - 1]
|
||||
const camelName = camelCase(slug)
|
||||
@@ -24,15 +26,18 @@ const name = `U${upperFirst(camelName)}`
|
||||
const preset = config[camelName]
|
||||
|
||||
const { data: ast } = await useAsyncData(`${name}-preset`, () => transformContent('content:_markdown.md', `
|
||||
\`\`\`json
|
||||
${JSON.stringify(preset, null, 2)}
|
||||
\`\`\`yml
|
||||
${json5.stringify(preset, null, 2)}
|
||||
\`\`\`\
|
||||
`, {
|
||||
highlight: {
|
||||
theme: {
|
||||
light: 'material-theme-lighter',
|
||||
default: 'material-theme',
|
||||
dark: 'material-theme-palenight'
|
||||
markdown: {
|
||||
highlight: {
|
||||
highlighter,
|
||||
theme: {
|
||||
light: 'material-theme-lighter',
|
||||
default: 'material-theme',
|
||||
dark: 'material-theme-palenight'
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
@@ -61,9 +61,7 @@ const items = [{
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col items-center">
|
||||
<code>$ npm i @nuxt/ui</code>
|
||||
<code>$ yarn add @nuxt/ui</code>
|
||||
<code>$ pnpm add @nuxt/ui</code>
|
||||
<code>$ npx nuxi@latest module add ui</code>
|
||||
</div>
|
||||
</template>
|
||||
</UAccordion>
|
||||
|
||||
20
docs/components/content/examples/AlertExampleAvatar.vue
Normal file
20
docs/components/content/examples/AlertExampleAvatar.vue
Normal file
@@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<UAlert
|
||||
title="Customize Alert Avatar"
|
||||
description="Insert custom content into the avatar slot!"
|
||||
:avatar="{
|
||||
src: 'https://avatars.githubusercontent.com/u/739984?v=4',
|
||||
alt: 'Avatar'
|
||||
}"
|
||||
>
|
||||
<template #avatar="{ avatar }">
|
||||
<UAvatar
|
||||
v-bind="avatar"
|
||||
chip-color="primary"
|
||||
chip-text=""
|
||||
chip-position="top-right"
|
||||
/>
|
||||
</template>
|
||||
</UAlert>
|
||||
</template>
|
||||
|
||||
10
docs/components/content/examples/AlertExampleIcon.vue
Normal file
10
docs/components/content/examples/AlertExampleIcon.vue
Normal file
@@ -0,0 +1,10 @@
|
||||
<template>
|
||||
<UAlert title="Customize Alert Icon" description="Insert custom content into the icon slot!" icon="i-heroicons-command-line">
|
||||
<template #icon="{ icon }">
|
||||
<UBadge size="sm">
|
||||
<UIcon :name="icon" />
|
||||
</UBadge>
|
||||
</template>
|
||||
</UAlert>
|
||||
</template>
|
||||
|
||||
@@ -12,7 +12,7 @@ const links = [{
|
||||
<template>
|
||||
<UBreadcrumb :links="links">
|
||||
<template #default="{ link, isActive, index }">
|
||||
<UBadge :color="isActive ? 'primary' : 'gray'" class="rounded-full">
|
||||
<UBadge :color="isActive ? 'primary' : 'gray'" class="rounded-full truncate">
|
||||
{{ index + 1 }}. {{ link.label }}
|
||||
</UBadge>
|
||||
</template>
|
||||
|
||||
@@ -11,6 +11,6 @@ const items = [
|
||||
|
||||
<template>
|
||||
<UCarousel v-slot="{ item }" :items="items">
|
||||
<img :src="item" width="300" height="400">
|
||||
<img :src="item" width="300" height="400" draggable="false">
|
||||
</UCarousel>
|
||||
</template>
|
||||
|
||||
@@ -11,6 +11,6 @@ const items = [
|
||||
|
||||
<template>
|
||||
<UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'basis-full' }" class="rounded-lg overflow-hidden" arrows>
|
||||
<img :src="item" class="w-full">
|
||||
<img :src="item" class="w-full" draggable="false">
|
||||
</UCarousel>
|
||||
</template>
|
||||
|
||||
@@ -30,6 +30,6 @@ const items = [
|
||||
arrows
|
||||
class="w-64 mx-auto"
|
||||
>
|
||||
<img :src="item" class="w-full">
|
||||
<img :src="item" class="w-full" draggable="false">
|
||||
</UCarousel>
|
||||
</template>
|
||||
|
||||
37
docs/components/content/examples/CarouselExampleAutoplay.vue
Normal file
37
docs/components/content/examples/CarouselExampleAutoplay.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<script setup lang="ts">
|
||||
const items = [
|
||||
'https://picsum.photos/1920/1080?random=1',
|
||||
'https://picsum.photos/1920/1080?random=2',
|
||||
'https://picsum.photos/1920/1080?random=3',
|
||||
'https://picsum.photos/1920/1080?random=4',
|
||||
'https://picsum.photos/1920/1080?random=5',
|
||||
'https://picsum.photos/1920/1080?random=6'
|
||||
]
|
||||
|
||||
const carouselRef = ref()
|
||||
|
||||
onMounted(() => {
|
||||
setInterval(() => {
|
||||
if (!carouselRef.value) return
|
||||
|
||||
if (carouselRef.value.page === carouselRef.value.pages) {
|
||||
return carouselRef.value.select(0)
|
||||
}
|
||||
|
||||
carouselRef.value.next()
|
||||
}, 3000)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UCarousel
|
||||
ref="carouselRef"
|
||||
v-slot="{ item }"
|
||||
:items="items"
|
||||
:ui="{ item: 'basis-full' }"
|
||||
class="rounded-lg overflow-hidden"
|
||||
indicators
|
||||
>
|
||||
<img :src="item" class="w-full" draggable="false">
|
||||
</UCarousel>
|
||||
</template>
|
||||
@@ -11,6 +11,6 @@ const items = [
|
||||
|
||||
<template>
|
||||
<UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'basis-full' }" class="rounded-lg overflow-hidden" indicators>
|
||||
<img :src="item" class="w-full">
|
||||
<img :src="item" class="w-full" draggable="false">
|
||||
</UCarousel>
|
||||
</template>
|
||||
|
||||
@@ -11,6 +11,6 @@ const items = [
|
||||
|
||||
<template>
|
||||
<UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'basis-full md:basis-1/2 lg:basis-1/3' }" indicators class="rounded-lg overflow-hidden">
|
||||
<img :src="item" class="w-full">
|
||||
<img :src="item" class="w-full" draggable="false">
|
||||
</UCarousel>
|
||||
</template>
|
||||
|
||||
@@ -11,6 +11,6 @@ const items = [
|
||||
|
||||
<template>
|
||||
<UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'basis-full md:basis-1/2 lg:basis-1/3' }">
|
||||
<img :src="item" class="w-full">
|
||||
<img :src="item" class="w-full" draggable="false">
|
||||
</UCarousel>
|
||||
</template>
|
||||
|
||||
@@ -11,6 +11,6 @@ const items = [
|
||||
|
||||
<template>
|
||||
<UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'basis-full' }" class="w-64 mx-auto rounded-lg overflow-hidden">
|
||||
<img :src="item" class="w-full">
|
||||
<img :src="item" class="w-full" draggable="false">
|
||||
</UCarousel>
|
||||
</template>
|
||||
|
||||
@@ -11,6 +11,6 @@ const items = [
|
||||
|
||||
<template>
|
||||
<UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'basis-full' }" class="rounded-lg overflow-hidden">
|
||||
<img :src="item" class="w-full">
|
||||
<img :src="item" class="w-full" draggable="false">
|
||||
</UCarousel>
|
||||
</template>
|
||||
|
||||
@@ -19,15 +19,13 @@ const items = [{
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UCarousel :items="items" :ui="{ item: 'w-full' }">
|
||||
<template #default="{ item, index }">
|
||||
<div class="text-center mx-auto">
|
||||
<img :src="item.avatar.src" :alt="item.name" class="rounded-full w-48 h-48 mb-2">
|
||||
<UCarousel v-slot="{ item, index }" :items="items" :ui="{ item: 'w-full' }">
|
||||
<div class="text-center mx-auto">
|
||||
<img :src="item.avatar.src" :alt="item.name" class="rounded-full w-48 h-48 mb-2" draggable="false">
|
||||
|
||||
<p class="font-semibold">
|
||||
{{ index + 1 }}. {{ item.name }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
<p class="font-semibold">
|
||||
{{ index + 1 }}. {{ item.name }}
|
||||
</p>
|
||||
</div>
|
||||
</UCarousel>
|
||||
</template>
|
||||
|
||||
@@ -23,11 +23,11 @@ const items = [
|
||||
class="w-64 mx-auto"
|
||||
>
|
||||
<template #default="{ item }">
|
||||
<img :src="item" class="w-full">
|
||||
<img :src="item" class="w-full" draggable="false">
|
||||
</template>
|
||||
|
||||
<template #indicator="{ onClick, index, active }">
|
||||
<UButton :label="String(index)" :variant="active ? 'solid' : 'outline'" size="2xs" class="rounded-full min-w-6 justify-center" @click="onClick(index)" />
|
||||
<template #indicator="{ onClick, page, active }">
|
||||
<UButton :label="String(page)" :variant="active ? 'solid' : 'outline'" size="2xs" class="rounded-full min-w-6 justify-center" @click="onClick(page)" />
|
||||
</template>
|
||||
</UCarousel>
|
||||
</template>
|
||||
|
||||
@@ -20,7 +20,7 @@ const items = [
|
||||
class="w-64 mx-auto"
|
||||
>
|
||||
<template #default="{ item }">
|
||||
<img :src="item" class="w-full">
|
||||
<img :src="item" class="w-full" draggable="false">
|
||||
</template>
|
||||
|
||||
<template #prev="{ onClick, disabled }">
|
||||
@@ -30,7 +30,7 @@ const items = [
|
||||
</template>
|
||||
|
||||
<template #next="{ onClick, disabled }">
|
||||
<button :disabled="disabled" class="" @click="onClick">
|
||||
<button :disabled="disabled" @click="onClick">
|
||||
Next
|
||||
</button>
|
||||
</template>
|
||||
|
||||
@@ -11,6 +11,6 @@ const items = [
|
||||
|
||||
<template>
|
||||
<UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'snap-end' }">
|
||||
<img :src="item" width="200" height="300">
|
||||
<img :src="item" width="200" height="300" draggable="false">
|
||||
</UCarousel>
|
||||
</template>
|
||||
|
||||
@@ -11,6 +11,6 @@ const items = [
|
||||
|
||||
<template>
|
||||
<UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'snap-start' }">
|
||||
<img :src="item" width="200" height="300">
|
||||
<img :src="item" width="200" height="300" draggable="false">
|
||||
</UCarousel>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useMouse, useWindowScroll } from '@vueuse/core'
|
||||
|
||||
const { x, y } = useMouse()
|
||||
const { y: windowY } = useWindowScroll()
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useMouse, useWindowScroll } from '@vueuse/core'
|
||||
|
||||
const { x, y } = useMouse()
|
||||
const { y: windowY } = useWindowScroll()
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useMouse, useWindowScroll } from '@vueuse/core'
|
||||
|
||||
const { x, y } = useMouse()
|
||||
const { y: windowY } = useWindowScroll()
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useMouse, useWindowScroll } from '@vueuse/core'
|
||||
|
||||
const { x, y } = useMouse()
|
||||
const { y: windowY } = useWindowScroll()
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ const date = ref(new Date())
|
||||
<UButton icon="i-heroicons-calendar-days-20-solid" :label="format(date, 'd MMM, yyy')" />
|
||||
|
||||
<template #panel="{ close }">
|
||||
<DatePicker v-model="date" @close="close" />
|
||||
<DatePicker v-model="date" is-required @close="close" />
|
||||
</template>
|
||||
</UPopover>
|
||||
</template>
|
||||
|
||||
@@ -27,8 +27,8 @@ function selectRange (duration: Duration) {
|
||||
</UButton>
|
||||
|
||||
<template #panel="{ close }">
|
||||
<div class="flex items-center divide-x divide-gray-200 dark:divide-gray-800">
|
||||
<div class="flex flex-col py-4">
|
||||
<div class="flex items-center sm:divide-x divide-gray-200 dark:divide-gray-800">
|
||||
<div class="hidden sm:flex flex-col py-4">
|
||||
<UButton
|
||||
v-for="(range, index) in ranges"
|
||||
:key="index"
|
||||
@@ -37,6 +37,7 @@ function selectRange (duration: Duration) {
|
||||
variant="ghost"
|
||||
class="rounded-none px-6"
|
||||
:class="[isRangeSelected(range.duration) ? 'bg-gray-100 dark:bg-gray-800' : 'hover:bg-gray-50 dark:hover:bg-gray-800/50']"
|
||||
truncate
|
||||
@click="selectRange(range.duration)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
import { string, objectAsync, email, minLength, type Input } from 'valibot'
|
||||
import * as v from 'valibot'
|
||||
import type { FormSubmitEvent } from '#ui/types'
|
||||
|
||||
const schema = objectAsync({
|
||||
email: string([email('Invalid email')]),
|
||||
password: string([minLength(8, 'Must be at least 8 characters')])
|
||||
const schema = v.object({
|
||||
email: v.pipe(v.string(), v.email('Invalid email')),
|
||||
password: v.pipe(v.string(), v.minLength(8, 'Must be at least 8 characters'))
|
||||
})
|
||||
|
||||
type Schema = Input<typeof schema>
|
||||
type Schema = v.InferOutput<typeof schema>
|
||||
|
||||
const state = reactive({
|
||||
email: undefined,
|
||||
password: undefined
|
||||
email: '',
|
||||
password: ''
|
||||
})
|
||||
|
||||
async function onSubmit (event: FormSubmitEvent<Schema>) {
|
||||
@@ -21,7 +21,7 @@ async function onSubmit (event: FormSubmitEvent<Schema>) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
|
||||
<UForm :schema="v.safeParser(schema)" :state="state" class="space-y-4" @submit="onSubmit">
|
||||
<UFormGroup label="Email" name="email">
|
||||
<UInput v-model="state.email" />
|
||||
</UFormGroup>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
const route = useRoute()
|
||||
|
||||
const links = [{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
const route = useRoute()
|
||||
|
||||
const links = [{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
const route = useRoute()
|
||||
|
||||
const links = [
|
||||
|
||||
@@ -31,8 +31,8 @@ const selected = ref(people[0])
|
||||
<template>
|
||||
<UInputMenu v-model="selected" :options="people">
|
||||
<template #leading>
|
||||
<UIcon v-if="selected.icon" :name="(selected.icon as string)" class="w-4 h-4 mx-0.5" />
|
||||
<UAvatar v-else-if="selected.avatar" v-bind="(selected.avatar as Avatar)" size="3xs" class="mx-0.5" />
|
||||
<UIcon v-if="selected.icon" :name="(selected.icon as string)" class="w-5 h-5" />
|
||||
<UAvatar v-else-if="selected.avatar" v-bind="(selected.avatar as Avatar)" size="2xs" />
|
||||
</template>
|
||||
</UInputMenu>
|
||||
</template>
|
||||
|
||||
28
docs/components/content/examples/ModalExampleComponent.vue
Normal file
28
docs/components/content/examples/ModalExampleComponent.vue
Normal file
@@ -0,0 +1,28 @@
|
||||
<script lang="ts" setup>
|
||||
defineProps({
|
||||
count: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['success'])
|
||||
|
||||
function onSuccess () {
|
||||
emit('success')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UModal>
|
||||
<UCard>
|
||||
<div class="space-y-2">
|
||||
<p>This modal was opened programmatically !</p>
|
||||
<p>Count: {{ count }}</p>
|
||||
<UButton @click="onSuccess">
|
||||
Click to emit a success event
|
||||
</UButton>
|
||||
</div>
|
||||
</UCard>
|
||||
</UModal>
|
||||
</template>
|
||||
24
docs/components/content/examples/ModalExampleComposable.vue
Normal file
24
docs/components/content/examples/ModalExampleComposable.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<script setup lang="ts">
|
||||
import { ModalExampleComponent } from '#components'
|
||||
|
||||
const toast = useToast()
|
||||
const modal = useModal()
|
||||
const count = ref(0)
|
||||
|
||||
function openModal () {
|
||||
count.value += 1
|
||||
modal.open(ModalExampleComponent, {
|
||||
count: count.value,
|
||||
onSuccess () {
|
||||
toast.add({
|
||||
title: 'Success !',
|
||||
id: 'modal-success'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UButton label="Reveal modal" @click="openModal" />
|
||||
</template>
|
||||
17
docs/components/content/examples/PaginationExampleTo.vue
Normal file
17
docs/components/content/examples/PaginationExampleTo.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
const page = ref(1)
|
||||
const items = ref(Array(50))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UPagination
|
||||
v-model="page"
|
||||
:page-count="5"
|
||||
:total="items.length"
|
||||
:to="(page: number) => ({
|
||||
query: { page },
|
||||
// Hash is specified here to prevent the page from scrolling to the top
|
||||
hash: '#links',
|
||||
})"
|
||||
/>
|
||||
</template>
|
||||
@@ -3,5 +3,5 @@ const value = ref(50)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<URange v-model="value" name="range" />
|
||||
<URange v-model="value" />
|
||||
</template>
|
||||
|
||||
@@ -31,8 +31,8 @@ const selected = ref(people[0])
|
||||
<template>
|
||||
<USelectMenu v-model="selected" :options="people">
|
||||
<template #leading>
|
||||
<UIcon v-if="selected.icon" :name="(selected.icon as string)" class="w-4 h-4 mx-0.5" />
|
||||
<UAvatar v-else-if="selected.avatar" v-bind="(selected.avatar as Avatar)" size="3xs" class="mx-0.5" />
|
||||
<UIcon v-if="selected.icon" :name="(selected.icon as string)" class="w-5 h-5" />
|
||||
<UAvatar v-else-if="selected.avatar" v-bind="(selected.avatar as Avatar)" size="2xs" />
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</template>
|
||||
|
||||
@@ -8,6 +8,16 @@ const isOpen = ref(false)
|
||||
|
||||
<USlideover v-model="isOpen">
|
||||
<div class="p-4 flex-1">
|
||||
<UButton
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
icon="i-heroicons-x-mark-20-solid"
|
||||
class="flex sm:hidden absolute end-5 top-5 z-10"
|
||||
square
|
||||
padded
|
||||
@click="isOpen = false"
|
||||
/>
|
||||
<Placeholder class="h-full" />
|
||||
</div>
|
||||
</USlideover>
|
||||
|
||||
@@ -7,8 +7,22 @@ const isOpen = ref(false)
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<USlideover v-model="isOpen">
|
||||
<UCard class="flex flex-col flex-1" :ui="{ body: { base: 'flex-1' }, ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
|
||||
<UCard
|
||||
class="flex flex-col flex-1"
|
||||
:ui="{ body: { base: 'flex-1' }, ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }"
|
||||
>
|
||||
<template #header>
|
||||
<UButton
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
icon="i-heroicons-x-mark-20-solid"
|
||||
class="flex sm:hidden absolute end-5 top-5 z-10"
|
||||
square
|
||||
padded
|
||||
@click="isOpen = false"
|
||||
/>
|
||||
|
||||
<Placeholder class="h-8" />
|
||||
</template>
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<script lang="ts" setup>
|
||||
|
||||
const props = defineProps({
|
||||
count: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
})
|
||||
|
||||
const emits = defineEmits<{
|
||||
close: [];
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<USlideover>
|
||||
<UCard class="flex flex-col flex-1" :ui="{ body: { base: 'flex-1' }, ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">
|
||||
Opened programmatically: {{ props.count }} times
|
||||
</h3>
|
||||
<UButton color="gray" variant="ghost" icon="i-heroicons-x-mark-20-solid" class="-my-1" @click="emits('close')" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<Placeholder class="h-full" />
|
||||
</UCard>
|
||||
</USlideover>
|
||||
</template>
|
||||
@@ -0,0 +1,16 @@
|
||||
<script setup lang="ts">
|
||||
import { SlideoverExampleComponent } from '#components'
|
||||
const slideover = useSlideover()
|
||||
const count = ref(0)
|
||||
function openSlideover () {
|
||||
count.value += 1
|
||||
slideover.open(SlideoverExampleComponent, {
|
||||
count: count.value,
|
||||
onClose: slideover.close
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UButton label="Reveal slideover" @click="openSlideover" />
|
||||
</template>
|
||||
@@ -8,6 +8,17 @@ const isOpen = ref(false)
|
||||
|
||||
<USlideover v-model="isOpen" :overlay="false">
|
||||
<div class="p-4 flex-1">
|
||||
<UButton
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
icon="i-heroicons-x-mark-20-solid"
|
||||
class="flex sm:hidden absolute end-5 top-5 z-10"
|
||||
square
|
||||
padded
|
||||
@click="isOpen = false"
|
||||
/>
|
||||
|
||||
<Placeholder class="h-full" />
|
||||
</div>
|
||||
</USlideover>
|
||||
|
||||
@@ -8,6 +8,17 @@ const isOpen = ref(false)
|
||||
|
||||
<USlideover v-model="isOpen" :transition="false">
|
||||
<div class="p-4 flex-1">
|
||||
<UButton
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
icon="i-heroicons-x-mark-20-solid"
|
||||
class="flex sm:hidden absolute end-5 top-5 z-10"
|
||||
square
|
||||
padded
|
||||
@click="isOpen = false"
|
||||
/>
|
||||
|
||||
<Placeholder class="h-full" />
|
||||
</div>
|
||||
</USlideover>
|
||||
|
||||
@@ -186,7 +186,7 @@ const { data: todos, pending } = await useLazyAsyncData<{
|
||||
sort-desc-icon="i-heroicons-arrow-down"
|
||||
sort-mode="manual"
|
||||
class="w-full"
|
||||
:ui="{ td: { base: 'max-w-[0] truncate' } }"
|
||||
:ui="{ td: { base: 'max-w-[0] truncate' }, default: { checkbox: { color: 'gray' } } }"
|
||||
@select="select"
|
||||
>
|
||||
<template #completed-data="{ row }">
|
||||
|
||||
63
docs/components/content/examples/TableExampleCaptionSlot.vue
Normal file
63
docs/components/content/examples/TableExampleCaptionSlot.vue
Normal file
@@ -0,0 +1,63 @@
|
||||
<script setup lang="ts">
|
||||
const columns = [{
|
||||
key: 'name',
|
||||
label: 'Name'
|
||||
}, {
|
||||
key: 'title',
|
||||
label: 'Title'
|
||||
}, {
|
||||
key: 'email',
|
||||
label: 'Email'
|
||||
}, {
|
||||
key: 'role',
|
||||
label: 'Role'
|
||||
}, {
|
||||
key: 'actions'
|
||||
}]
|
||||
|
||||
const people = [{
|
||||
id: 1,
|
||||
name: 'Lindsay Walton',
|
||||
title: 'Front-end Developer',
|
||||
email: 'lindsay.walton@example.com',
|
||||
role: 'Member'
|
||||
}, {
|
||||
id: 2,
|
||||
name: 'Courtney Henry',
|
||||
title: 'Designer',
|
||||
email: 'courtney.henry@example.com',
|
||||
role: 'Admin'
|
||||
}, {
|
||||
id: 3,
|
||||
name: 'Tom Cook',
|
||||
title: 'Director of Product',
|
||||
email: 'tom.cook@example.com',
|
||||
role: 'Member'
|
||||
}, {
|
||||
id: 4,
|
||||
name: 'Whitney Francis',
|
||||
title: 'Copywriter',
|
||||
email: 'whitney.francis@example.com',
|
||||
role: 'Admin'
|
||||
}, {
|
||||
id: 5,
|
||||
name: 'Leonard Krasner',
|
||||
title: 'Senior Designer',
|
||||
email: 'leonard.krasner@example.com',
|
||||
role: 'Owner'
|
||||
}, {
|
||||
id: 6,
|
||||
name: 'Floyd Miles',
|
||||
title: 'Principal Designer',
|
||||
email: 'floyd.miles@example.com',
|
||||
role: 'Member'
|
||||
}]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UTable :rows="people" :columns="columns">
|
||||
<template #caption>
|
||||
<caption>Employees of ACME</caption>
|
||||
</template>
|
||||
</UTable>
|
||||
</template>
|
||||
@@ -32,13 +32,7 @@ const links = [{
|
||||
<template>
|
||||
<UVerticalNavigation :links="links">
|
||||
<template #avatar="{ link }">
|
||||
<UAvatar
|
||||
v-if="link.avatar"
|
||||
v-bind="link.avatar"
|
||||
size="3xs"
|
||||
loading="lazy"
|
||||
/>
|
||||
<UIcon v-else name="i-heroicons-user-circle-20-solid" class="text-lg" />
|
||||
<UAvatar v-bind="link.avatar" size="2xs" loading="lazy" />
|
||||
</template>
|
||||
</UVerticalNavigation>
|
||||
</template>
|
||||
|
||||
@@ -19,7 +19,7 @@ const links = [{
|
||||
:links="links"
|
||||
:ui="{
|
||||
wrapper: 'border-s border-gray-200 dark:border-gray-800 space-y-2',
|
||||
base: 'group block border-s -ms-px lg:leading-6 before:hidden',
|
||||
base: 'group block border-s -ms-px leading-6 before:hidden',
|
||||
padding: 'p-0 ps-4',
|
||||
rounded: '',
|
||||
font: '',
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { useBreakpoints, breakpointsTailwind } from '@vueuse/core'
|
||||
import { DatePicker as VCalendarDatePicker } from 'v-calendar'
|
||||
// @ts-ignore
|
||||
import type { DatePickerDate, DatePickerRangeObject } from 'v-calendar/dist/types/src/use/datePicker'
|
||||
import 'v-calendar/dist/style.css'
|
||||
|
||||
@@ -24,6 +26,10 @@ const date = computed({
|
||||
}
|
||||
})
|
||||
|
||||
const breakpoints = useBreakpoints(breakpointsTailwind)
|
||||
|
||||
const smallerThanSm = breakpoints.smaller('sm')
|
||||
|
||||
const attrs = {
|
||||
transparent: true,
|
||||
borderless: true,
|
||||
@@ -34,7 +40,7 @@ const attrs = {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCalendarDatePicker v-if="date && (date as DatePickerRangeObject)?.start && (date as DatePickerRangeObject)?.end" v-model.range="date" :columns="2" v-bind="{ ...attrs, ...$attrs }" />
|
||||
<VCalendarDatePicker v-if="date && (date as DatePickerRangeObject)?.start && (date as DatePickerRangeObject)?.end" v-model.range="date" :columns="smallerThanSm ? 1 : 2" :rows="smallerThanSm ? 2 : 1" v-bind="{ ...attrs, ...$attrs }" />
|
||||
<VCalendarDatePicker v-else v-model="date" v-bind="{ ...attrs, ...$attrs }" />
|
||||
</template>
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
import { useElementSize } from '@vueuse/core'
|
||||
|
||||
const el = ref(null)
|
||||
|
||||
@@ -12,7 +12,7 @@ export async function fetchComponentMeta (name: string) {
|
||||
// Store promise to avoid multiple calls
|
||||
|
||||
// add to nitro prerender
|
||||
if (process.server) {
|
||||
if (import.meta.server) {
|
||||
const event = useRequestEvent()
|
||||
event.node.res.setHeader(
|
||||
'x-nitro-prerender',
|
||||
|
||||
@@ -11,7 +11,7 @@ export async function fetchContentExampleCode (name?: string) {
|
||||
if (state.value[name]) { return state.value[name] }
|
||||
|
||||
// add to nitro prerender
|
||||
if (process.server) {
|
||||
if (import.meta.server) {
|
||||
const event = useRequestEvent()
|
||||
event.node.res.setHeader(
|
||||
'x-nitro-prerender',
|
||||
|
||||
31
docs/composables/useShikiHighlighter.ts
Normal file
31
docs/composables/useShikiHighlighter.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { createShikiHighlighter } from '@nuxtjs/mdc/runtime/highlighter/shiki'
|
||||
import MaterialTheme from 'shiki/themes/material-theme.mjs'
|
||||
import MaterialThemeLighter from 'shiki/themes/material-theme-lighter.mjs'
|
||||
import MaterialThemePalenight from 'shiki/themes/material-theme-palenight.mjs'
|
||||
import HtmlLang from 'shiki/langs/html.mjs'
|
||||
import MdcLang from 'shiki/langs/mdc.mjs'
|
||||
import VueLang from 'shiki/langs/vue.mjs'
|
||||
import YamlLang from 'shiki/langs/yaml.mjs'
|
||||
import PostcssLang from 'shiki/langs/postcss.mjs'
|
||||
|
||||
let highlighter
|
||||
export const useShikiHighlighter = () => {
|
||||
if (!highlighter) {
|
||||
highlighter = createShikiHighlighter({
|
||||
bundledThemes: {
|
||||
'material-theme': MaterialTheme,
|
||||
'material-theme-lighter': MaterialThemeLighter,
|
||||
'material-theme-palenight': MaterialThemePalenight
|
||||
},
|
||||
bundledLangs: {
|
||||
html: HtmlLang,
|
||||
mdc: MdcLang,
|
||||
vue: VueLang,
|
||||
yml: YamlLang,
|
||||
postcss: PostcssLang
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return highlighter
|
||||
}
|
||||
@@ -5,7 +5,7 @@ description: 'Fully styled and customizable components for Nuxt.'
|
||||
|
||||
Nuxt UI is a module that provides a set of Vue components and composables built with [Tailwind CSS](https://tailwindcss.com/) and [Headless UI](https://headlessui.dev/) to help you build beautiful and accessible user interfaces.
|
||||
|
||||
Its goal is to provide everything related to UI when building a Nuxt app. This includes components, icons, colors, dark mode but also keyboard shortcuts.
|
||||
Its goal is to provide everything related to UI when building a Nuxt app. This includes components, icons, colors, dark mode as well as keyboard shortcuts.
|
||||
|
||||
## Features
|
||||
|
||||
|
||||
@@ -5,29 +5,15 @@ description: 'Learn how to install and configure Nuxt UI in your application.'
|
||||
|
||||
## Setup
|
||||
|
||||
1. Install `@nuxt/ui` dependency to your project:
|
||||
### Add to a Nuxt project
|
||||
|
||||
::code-group
|
||||
1. Add `@nuxt/ui` module to your project:
|
||||
|
||||
```bash [pnpm]
|
||||
pnpm add @nuxt/ui
|
||||
```bash
|
||||
npx nuxi@latest module add ui
|
||||
```
|
||||
|
||||
```bash [yarn]
|
||||
yarn add @nuxt/ui
|
||||
```
|
||||
|
||||
```bash [npm]
|
||||
npm install @nuxt/ui
|
||||
```
|
||||
|
||||
```bash [bun]
|
||||
bun add @nuxt/ui
|
||||
```
|
||||
|
||||
::
|
||||
|
||||
2. Add it to your `modules` section in your `nuxt.config`:
|
||||
2. Add it to the `modules` section in your `nuxt.config.ts`:
|
||||
|
||||
```ts [nuxt.config.ts]
|
||||
export default defineNuxtConfig({
|
||||
@@ -37,6 +23,19 @@ export default defineNuxtConfig({
|
||||
|
||||
That's it! You can now use all the components and composables in your Nuxt app ✨
|
||||
|
||||
### Use Nuxt starter
|
||||
|
||||
[Nuxt Starter](https://nuxt.new/) template makes it easy to get started with Nuxt UI.
|
||||
The Nuxt Starter template is available from the `nuxi init` command.
|
||||
|
||||
```bash
|
||||
npx nuxi@latest init -t ui
|
||||
```
|
||||
|
||||
|
||||
|
||||
Please check [nuxt/starter](https://github.com/nuxt/starter/tree/ui) for details.
|
||||
|
||||
## Modules
|
||||
|
||||
Nuxt UI will automatically install the [@nuxtjs/tailwindcss](https://tailwindcss.nuxtjs.org/), [@nuxtjs/color-mode](https://color-mode.nuxtjs.org/) and [nuxt-icon](https://github.com/nuxt-modules/icon) modules for you.
|
||||
@@ -194,7 +193,7 @@ To enable these two features, you can add the following to your `.vscode/setting
|
||||
{
|
||||
"tailwindCSS.experimental.classRegex": [
|
||||
["ui:\\s*{([^)]*)\\s*}", "[\"'`]([^\"'`]*).*?[\"'`]"],
|
||||
["/\\*ui\\*/\\s*{([^;]*)}", ":\\s*[\"'`]([^\"'`]*).*?[\"'`]"]
|
||||
["/\\*\\s?ui\\s?\\*/\\s*{([^;]*)}", ":\\s*[\"'`]([^\"'`]*).*?[\"'`]"]
|
||||
]
|
||||
}
|
||||
```
|
||||
@@ -206,8 +205,8 @@ An example SFC using IntelliSense (note the `/*ui*/` prefix, also works with `re
|
||||
<UCard :ui="ui" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const ui = /*ui*/ {
|
||||
<script setup lang="ts">
|
||||
const ui = /* ui */ {
|
||||
background: 'bg-white dark:bg-slate-900'
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -25,7 +25,7 @@ Try to change the `primary` and `gray` colors by clicking on the :u-icon{name="i
|
||||
|
||||
As this module uses Tailwind CSS under the hood, you can use any of the [Tailwind CSS colors](https://tailwindcss.com/docs/customizing-colors#color-palette-reference) or your own custom colors. By default, the `primary` color is `green` and the `gray` color is `cool`.
|
||||
|
||||
When [using custom colors](https://tailwindcss.com/docs/customizing-colors#using-custom-colors) or [adding additional colors](https://tailwindcss.com/docs/customizing-colors#adding-additional-colors) through the `extend` key in your `tailwind.config.ts`, you'll need to make sure to define all the shades from `50` to `950` as most of them are used in the components config defined in [`ui.config.ts`](https://github.com/nuxt/ui/blob/dev/src/runtime/ui.config.ts). You can [generate your colors](https://tailwindcss.com/docs/customizing-colors#generating-colors) using tools such as https://uicolors.app/ for example.
|
||||
When [using custom colors](https://tailwindcss.com/docs/customizing-colors#using-custom-colors) or [adding additional colors](https://tailwindcss.com/docs/customizing-colors#adding-additional-colors) through the `extend` key in your `tailwind.config.ts`, you'll need to make sure to define all the shades from `50` to `950` as most of them are used in the components config defined in [`ui.config/`](https://github.com/nuxt/ui/tree/dev/src/runtime/ui.config) directory. You can [generate your colors](https://tailwindcss.com/docs/customizing-colors#generating-colors) using tools such as https://uicolors.app/ for example.
|
||||
|
||||
```ts [tailwind.config.ts]
|
||||
import type { Config } from 'tailwindcss'
|
||||
@@ -106,7 +106,7 @@ This can also happen when you bind a dynamic color to a component: `<UBadge :col
|
||||
|
||||
### `app.config.ts`
|
||||
|
||||
Components are styled with Tailwind CSS but classes are all defined in the default [ui.config.ts](https://github.com/nuxt/ui/blob/dev/src/runtime/ui.config.ts) file. You can override those in your own `app.config.ts`.
|
||||
You can find the config of each component in the [`ui.config/`](https://github.com/nuxt/ui/tree/dev/src/runtime/ui.config) directory. You can override those classes in your own `app.config.ts`.
|
||||
|
||||
```ts [app.config.ts]
|
||||
export default defineAppConfig({
|
||||
@@ -247,7 +247,7 @@ You can easily build a color mode button by using the `useColorMode` composable
|
||||
|
||||
#code
|
||||
```vue
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
const colorMode = useColorMode()
|
||||
const isDark = computed({
|
||||
get () {
|
||||
|
||||
@@ -130,7 +130,7 @@ defineShortcuts({
|
||||
To display shortcuts in your app according to the user's OS, you can use the `useShortcuts` composable.
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
const { metaSymbol } = useShortcuts()
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
---
|
||||
description: Display togglable accordion panels.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Accordion.vue
|
||||
- label: Disclosure
|
||||
icon: i-simple-icons-headlessui
|
||||
to: 'https://headlessui.com/vue/disclosure'
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Accordion.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -163,6 +163,22 @@ This can be handy when you want to display HTML content. To achieve this, you ca
|
||||
|
||||
:component-example{component="alert-example-html"}
|
||||
|
||||
### `icon` :u-badge{label="New" class="align-middle ml-2 !rounded-full" variant="subtle"}
|
||||
|
||||
Use the `#icon` slot to customize the displayed icon.
|
||||
|
||||
:component-example{component="alert-example-icon"}
|
||||
|
||||
### `avatar` :u-badge{label="New" class="align-middle ml-2 !rounded-full" variant="subtle"}
|
||||
|
||||
Use the `#avatar` slot to customize the displayable avatar.
|
||||
|
||||
:component-example{component="alert-example-avatar"}
|
||||
|
||||
### `actions` :u-badge{label="New" class="align-middle ml-2 !rounded-full" variant="subtle"}
|
||||
|
||||
Use the `#actions` slot to add custom user interaction elements.
|
||||
|
||||
## Props
|
||||
|
||||
:component-props
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
---
|
||||
title: Breadcrumb
|
||||
description: A list of links that indicate the current page's location within a navigational hierarchy.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/navigation/Breadcrumb.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -336,7 +336,7 @@ Use the `#leading` slot to set the content of the leading icon.
|
||||
::component-card
|
||||
---
|
||||
slots:
|
||||
leading: <UAvatar src="https://avatars.githubusercontent.com/u/739984?v=4" size="3xs" />
|
||||
leading: <UAvatar src="https://avatars.githubusercontent.com/u/739984?v=4" size="2xs" />
|
||||
baseProps:
|
||||
color: 'gray'
|
||||
props:
|
||||
@@ -347,7 +347,7 @@ excludedProps:
|
||||
---
|
||||
|
||||
#leading
|
||||
:u-avatar{src="https://avatars.githubusercontent.com/u/739984?v=4" size="3xs"}
|
||||
:u-avatar{src="https://avatars.githubusercontent.com/u/739984?v=4" size="2xs"}
|
||||
::
|
||||
|
||||
### `trailing`
|
||||
@@ -357,7 +357,7 @@ Use the `#trailing` slot to set the content of the trailing icon.
|
||||
::component-card
|
||||
---
|
||||
slots:
|
||||
trailing: <UIcon name="i-heroicons-arrow-right-20-solid" />
|
||||
trailing: <UIcon name="i-heroicons-arrow-right-20-solid" class="w-5 h-5" />
|
||||
props:
|
||||
label: Button
|
||||
color: 'gray'
|
||||
@@ -366,7 +366,7 @@ excludedProps:
|
||||
---
|
||||
|
||||
#trailing
|
||||
:u-icon{name="i-heroicons-arrow-right-20-solid"}
|
||||
:u-icon{name="i-heroicons-arrow-right-20-solid" class="w-5 h-5"}
|
||||
::
|
||||
|
||||
## Props
|
||||
|
||||
@@ -4,8 +4,6 @@ links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Carousel.vue
|
||||
navigation:
|
||||
badge: New
|
||||
---
|
||||
|
||||
## Usage
|
||||
@@ -100,6 +98,12 @@ The number of indicators will be automatically generated based on the number of
|
||||
|
||||
:component-example{component="carousel-example-indicators-size"}
|
||||
|
||||
## Autoplay :u-badge{label="New" class="align-middle ml-2 !rounded-full" variant="subtle"}
|
||||
|
||||
You can easily implement an autoplay behavior using the exposed [API](#api) through a template ref.
|
||||
|
||||
:component-example{component="carousel-example-autoplay"}
|
||||
|
||||
## Slots
|
||||
|
||||
### `default`
|
||||
@@ -120,7 +124,7 @@ You can customize the position of the buttons through `ui.arrows.wrapper`.
|
||||
|
||||
### `indicator`
|
||||
|
||||
With the `indicators` prop enabled, use the `#indicator` slot to set the content of the indicators. You will have access to the `active`, `index` properties and `on-click` method in the slot scope.
|
||||
With the `indicators` prop enabled, use the `#indicator` slot to set the content of the indicators. You will have access to the `active`, `page` properties and `on-click` method in the slot scope.
|
||||
|
||||
:component-example{component="carousel-example-slots-indicator"}
|
||||
|
||||
@@ -132,6 +136,28 @@ You can customize the position of the buttons through `ui.indicators.wrapper`.
|
||||
|
||||
:component-props
|
||||
|
||||
## API
|
||||
|
||||
When accessing the component via a template ref, you can use the following:
|
||||
|
||||
::field-group
|
||||
::field{name="page" type="number"}
|
||||
The current page.
|
||||
::
|
||||
::field{name="pages" type="number"}
|
||||
The total number of pages.
|
||||
::
|
||||
::field{name="select (page)"}
|
||||
Go to a specific page.
|
||||
::
|
||||
::field{name="next ()"}
|
||||
Go to the next page.
|
||||
::
|
||||
::field{name="prev ()"}
|
||||
Go to the previous page.
|
||||
::
|
||||
::
|
||||
|
||||
## Config
|
||||
|
||||
:component-preset
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
title: CommandPalette
|
||||
description: Add a customizable command palette to your app.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/navigation/CommandPalette.vue
|
||||
- label: 'Combobox'
|
||||
icon: i-simple-icons-headlessui
|
||||
to: 'https://headlessui.com/vue/combobox'
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/navigation/CommandPalette.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -16,15 +16,15 @@ Let's start by installing the `v-calendar` and `date-fns` dependency:
|
||||
::code-group
|
||||
|
||||
```bash [pnpm]
|
||||
pnpm add v-calendar
|
||||
pnpm add v-calendar@next date-fns
|
||||
```
|
||||
|
||||
```bash [yarn]
|
||||
yarn add v-calendar
|
||||
yarn add v-calendar@next date-fns
|
||||
```
|
||||
|
||||
```bash [npm]
|
||||
npm install v-calendar
|
||||
npm install v-calendar@next date-fns
|
||||
```
|
||||
|
||||
::
|
||||
|
||||
@@ -66,21 +66,17 @@ excludedProps:
|
||||
---
|
||||
::
|
||||
|
||||
### Size
|
||||
### Size :u-badge{label="New" class="align-middle ml-2 !rounded-full" variant="subtle"}
|
||||
|
||||
You can change the size of the divider by using the `ui` prop
|
||||
Use the `size` prop to change the size of the divider.
|
||||
|
||||
::component-card
|
||||
---
|
||||
props:
|
||||
label: Nuxt UI
|
||||
ui:
|
||||
border:
|
||||
size:
|
||||
horizontal: border-t-2
|
||||
size: sm
|
||||
excludedProps:
|
||||
- label
|
||||
- ui
|
||||
---
|
||||
::
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
---
|
||||
description: Display a list of actions in a dropdown menu.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Dropdown.vue
|
||||
- label: Menu
|
||||
icon: i-simple-icons-headlessui
|
||||
to: https://headlessui.com/vue/menu
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Dropdown.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -196,7 +196,7 @@ Use the `#description` slot to set the custom content for description.
|
||||
::component-card
|
||||
---
|
||||
slots:
|
||||
description: Write only valid email address <UIcon name="i-heroicons-arrow-right-20-solid" />
|
||||
description: Write only valid email address <UIcon name="i-heroicons-information-circle" />
|
||||
default: <UInput model-value="benjamincanac" placeholder="you@example.com" />
|
||||
props:
|
||||
label: 'Email'
|
||||
@@ -236,7 +236,7 @@ Use the `#help` slot to set the custom content for help.
|
||||
::component-card
|
||||
---
|
||||
slots:
|
||||
help: Here are some examples <UIcon name="i-heroicons-arrow-right-20-solid" />
|
||||
help: Here are some examples <UIcon name="i-heroicons-information-circle" />
|
||||
default: <UInput model-value="benjamincanac" placeholder="you@example.com" />
|
||||
props:
|
||||
label: 'Email'
|
||||
|
||||
@@ -8,14 +8,63 @@ links:
|
||||
|
||||
## Usage
|
||||
|
||||
Use the Form component to validate form data using schema libraries such as [Yup](https://github.com/jquense/yup), [Zod](https://github.com/colinhacks/zod), [Joi](https://github.com/hapijs/joi), [Valibot](https://valibot.dev/) or your own validation logic. It works seamlessly with the FormGroup component to automatically display error messages around form elements.
|
||||
Use the Form component to validate form data using schema libraries such as [Yup](https://github.com/jquense/yup), [Zod](https://github.com/colinhacks/zod), [Joi](https://github.com/hapijs/joi), [Valibot](https://valibot.dev/), or your own validation logic.
|
||||
|
||||
The Form component requires the `validate` and `state` props for form validation.
|
||||
It works with the [FormGroup](/components/form-group) component to display error messages around form elements automatically.
|
||||
|
||||
- `state` - a reactive object that holds the current state of the form.
|
||||
- `validate` - a function that takes the form's state as input and returns an array of `FormError` objects with the following fields:
|
||||
- `message` - the error message to display.
|
||||
- `path` - the path to the form element matching the `name`.
|
||||
The form component requires two props:
|
||||
- `state` - a reactive object holding the form's state.
|
||||
- `schema` - a schema object from [Yup](#yup), [Zod](#zod), [Joi](#joi), or [Valibot](#valibot).
|
||||
|
||||
::callout{icon="i-heroicons-light-bulb"}
|
||||
Note that **no validation library is included** by default, so ensure you **install the one you need**.
|
||||
::
|
||||
|
||||
::tabs
|
||||
::component-example{label="Yup"}
|
||||
---
|
||||
component: 'form-example-yup'
|
||||
componentProps:
|
||||
class: 'w-60'
|
||||
---
|
||||
::
|
||||
|
||||
::component-example{label="Zod"}
|
||||
---
|
||||
component: 'form-example-zod'
|
||||
componentProps:
|
||||
class: 'w-60'
|
||||
---
|
||||
::
|
||||
|
||||
::component-example{label="Joi"}
|
||||
---
|
||||
component: 'form-example-joi'
|
||||
componentProps:
|
||||
class: 'w-60'
|
||||
---
|
||||
::
|
||||
|
||||
::component-example{label="Valibot"}
|
||||
---
|
||||
component: 'form-example-valibot'
|
||||
componentProps:
|
||||
class: 'w-60'
|
||||
---
|
||||
::
|
||||
::
|
||||
|
||||
## Custom validation
|
||||
|
||||
Use the `validate` prop to apply your own validation logic.
|
||||
|
||||
The validation function must return a list of errors with the following attributes:
|
||||
- `message` - Error message for display.
|
||||
- `path` - Path to the form element corresponding to the `name` attribute.
|
||||
|
||||
::callout{icon="i-heroicons-light-bulb"}
|
||||
Note that it can be used alongside the `schema` prop to handle complex use cases.
|
||||
::
|
||||
|
||||
::component-example
|
||||
---
|
||||
@@ -25,55 +74,7 @@ componentProps:
|
||||
---
|
||||
::
|
||||
|
||||
## Schema
|
||||
|
||||
You can provide a schema from [Yup](#yup), [Zod](#zod) or [Joi](#joi), [Valibot](#valibot) through the `schema` prop to validate the state. It's important to note that **none of these libraries are included** by default, so make sure to **install the one you need**.
|
||||
|
||||
### Yup
|
||||
|
||||
::component-example
|
||||
---
|
||||
component: 'form-example-yup'
|
||||
componentProps:
|
||||
class: 'w-60'
|
||||
---
|
||||
::
|
||||
|
||||
### Zod
|
||||
|
||||
::component-example
|
||||
---
|
||||
component: 'form-example-zod'
|
||||
componentProps:
|
||||
class: 'w-60'
|
||||
---
|
||||
::
|
||||
|
||||
### Joi
|
||||
|
||||
::component-example
|
||||
---
|
||||
component: 'form-example-joi'
|
||||
componentProps:
|
||||
class: 'w-60'
|
||||
---
|
||||
::
|
||||
|
||||
### Valibot
|
||||
|
||||
::component-example
|
||||
---
|
||||
component: 'form-example-valibot'
|
||||
componentProps:
|
||||
class: 'w-60'
|
||||
---
|
||||
::
|
||||
|
||||
## Other libraries
|
||||
|
||||
For other validation libraries, you can define your own component with custom validation logic.
|
||||
|
||||
Here is an example with [Vuelidate](https://github.com/vuelidate/vuelidate):
|
||||
This can also be used to integrate with other validation libraries. Here is an example with [Vuelidate](https://github.com/vuelidate/vuelidate):
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
@@ -132,9 +133,11 @@ async function onSubmit (event: FormSubmitEvent<any>) {
|
||||
// ...
|
||||
} catch (err) {
|
||||
if (err.statusCode === 422) {
|
||||
form.value.setErrors(err.data.errors.map((err) => {
|
||||
form.value.setErrors(err.data.errors.map((err) => ({
|
||||
// Map validation errors to { path: string, message: string }
|
||||
}))
|
||||
message: err.message,
|
||||
path: err.path,
|
||||
})))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,10 +159,11 @@ async function onSubmit (event: FormSubmitEvent<any>) {
|
||||
</UForm>
|
||||
</template>
|
||||
```
|
||||
|
||||
## Input events
|
||||
|
||||
The Form component automatically triggers validation upon `submit`, `input`, `blur` or `change` events. This ensures that any errors are displayed as soon as the user interacts with the form elements. You can control when validation happens this using the `validate-on` prop.
|
||||
The Form component automatically triggers validation upon `submit`, `input`, `blur` or `change` events.
|
||||
|
||||
This ensures that any errors are displayed as soon as the user interacts with the form elements. You can control when validation happens this using the `validate-on` prop.
|
||||
|
||||
::callout{icon="i-heroicons-light-bulb"}
|
||||
Note that the `input` event is not triggered until after the initial `blur` event. This is to prevent the form from being validated as the user is typing. You can override this behavior by setting the [`eager-validation`](/components/form-group#eager-validation) prop on [`FormGroup`](/components/form-group) to `true`.
|
||||
@@ -180,13 +184,13 @@ Take a look at the component!
|
||||
|
||||
## Error event
|
||||
|
||||
You can listen to the `@error` event to handle errors. This event is triggered when the form is validated and contains an array of `FormError` objects with the following fields:
|
||||
You can listen to the `@error` event to handle errors. This event is triggered when the form is submitted and contains an array of `FormError` objects with the following fields:
|
||||
|
||||
- `id` - the identifier of the form element.
|
||||
- `path` - the path to the form element matching the `name`.
|
||||
- `message` - the error message to display.
|
||||
|
||||
Here is an example of how to focus the first form element with an error:
|
||||
Here's an example that focuses the first input element with an error after the form is submitted:
|
||||
|
||||
::component-example
|
||||
---
|
||||
|
||||
@@ -5,8 +5,6 @@ links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/navigation/HorizontalNavigation.vue
|
||||
navigation:
|
||||
badge: New
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -18,7 +18,11 @@ props:
|
||||
::
|
||||
|
||||
::callout{icon="i-heroicons-exclamation-triangle"}
|
||||
You won't be able to use any icon in the `name` prop here as icons are bundled using [egoist/tailwindcss-icons](https://github.com/egoist/tailwindcss-icons), read more about this in [Theming](/getting-started/theming#icons).
|
||||
You won't be able to use all icons in the `name` prop here as icons are bundled using [egoist/tailwindcss-icons](https://github.com/egoist/tailwindcss-icons).
|
||||
::
|
||||
|
||||
::callout{icon="i-heroicons-light-bulb"}
|
||||
Don't forget to install and specify the icon collections you need in your `nuxt.config.ts`, read more about this in [Theming](/getting-started/theming#icons).
|
||||
::
|
||||
|
||||
### Dynamic
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
title: InputMenu
|
||||
description: Display an autocomplete input with real-time suggestions.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/InputMenu.vue
|
||||
- label: 'Combobox'
|
||||
icon: i-simple-icons-headlessui
|
||||
to: 'https://headlessui.com/vue/combobox'
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/InputMenu.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
@@ -130,6 +130,8 @@ Pass a function to the `search` prop to customize the search behavior and filter
|
||||
|
||||
Use the `debounce` prop to adjust the delay of the function.
|
||||
|
||||
Use the `searchLazy` prop to control the immediacy of data requests. :u-badge{label="New" class="!rounded-full" variant="subtle"}
|
||||
|
||||
::component-example
|
||||
---
|
||||
component: 'input-menu-example-search-async'
|
||||
|
||||
@@ -71,12 +71,22 @@ props:
|
||||
|
||||
Use the `type` prop to change the input type, the default `type` is set to `text`, you can check all the available types at [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#input_types).
|
||||
|
||||
We have improved the implementation of certain types such as [Checkbox](/components/checkbox), [Radio](/components/radio-group), etc.
|
||||
Some types have been implemented in their own components, such as [Checkbox](/components/checkbox), [Radio](/components/radio-group), etc. and others have been styled like `file` for example. :u-badge{label="New" class="!rounded-full" variant="subtle"}
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
icon: 'i-heroicons-folder'
|
||||
props:
|
||||
type: 'password'
|
||||
type: 'file'
|
||||
size: sm
|
||||
options:
|
||||
- name: type
|
||||
restriction: included
|
||||
values:
|
||||
- file
|
||||
- password
|
||||
- number
|
||||
---
|
||||
::
|
||||
|
||||
@@ -172,13 +182,13 @@ Use the `#leading` slot to set the content of the leading icon.
|
||||
::component-card
|
||||
---
|
||||
slots:
|
||||
leading: <UAvatar src="https://avatars.githubusercontent.com/u/739984?v=4" size="3xs" class="mx-0.5" />
|
||||
leading: <UAvatar src="https://avatars.githubusercontent.com/u/739984?v=4" size="2xs" />
|
||||
baseProps:
|
||||
placeholder: 'Search...'
|
||||
---
|
||||
|
||||
#leading
|
||||
:u-avatar{src="https://avatars.githubusercontent.com/u/739984?v=4" size="3xs" class="mx-0.5"}
|
||||
:u-avatar{src="https://avatars.githubusercontent.com/u/739984?v=4" size="2xs"}
|
||||
::
|
||||
|
||||
### `trailing`
|
||||
|
||||
@@ -33,6 +33,18 @@ It also renders an `<a>` tag when a `to` prop is provided, otherwise it defaults
|
||||
|
||||
It is used underneath by the [Button](/components/button), [Dropdown](/components/dropdown) and [VerticalNavigation](/components/vertical-navigation) components.
|
||||
|
||||
## IntelliSense
|
||||
If you're using VSCode and wish to get autocompletion for the classes `active-class` and `inactive-class`, you can add the following settings to your `.vscode/settings.json`:
|
||||
|
||||
```json [.vscode/settings.json]
|
||||
{
|
||||
"tailwindCSS.classAttributes": [
|
||||
"active-class",
|
||||
"inactive-class"
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
:component-props
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
---
|
||||
description: Display a modal within your application.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/Modal.vue
|
||||
- label: 'Dialog'
|
||||
icon: i-simple-icons-headlessui
|
||||
to: 'https://headlessui.com/vue/dialog'
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/Modal.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
@@ -40,7 +40,7 @@ Use the `prevent-close` prop to disable the outside click alongside the `esc` ke
|
||||
You can still handle the `esc` shortcut yourself by using our [defineShortcuts](/getting-started/shortcuts#defineshortcuts) composable.
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
const isOpen = ref(false)
|
||||
|
||||
defineShortcuts({
|
||||
@@ -59,6 +59,34 @@ Set the `fullscreen` prop to `true` to enable it.
|
||||
|
||||
:component-example{component="modal-example-fullscreen"}
|
||||
|
||||
### Control programmatically :u-badge{label="New" class="align-middle ml-2 !rounded-full" variant="subtle"}
|
||||
|
||||
First of all, add the `Modals` component to your app, preferably inside `app.vue`.
|
||||
|
||||
```vue [app.vue]
|
||||
<template>
|
||||
<div>
|
||||
<UContainer>
|
||||
<NuxtPage />
|
||||
</UContainer>
|
||||
|
||||
<UModals />
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
Then, you can use the `useModal` composable to control your modals within your app.
|
||||
|
||||
<!-- For prerendering -->
|
||||
:component-example{component="modal-example-component" hiddenCode hiddenPreview }
|
||||
|
||||
::code-group{class="[&>div:last-child>div:first-child]:!rounded-t-none"}
|
||||
:component-example{component="modal-example-composable" label="app.vue" }
|
||||
:component-example{component="modal-example-component" hiddenPreview label="modal.vue" }
|
||||
::
|
||||
|
||||
Additionally, you can close the modal within the modal component by calling `modal.close()`.
|
||||
|
||||
## Props
|
||||
|
||||
:component-props
|
||||
|
||||
@@ -42,7 +42,7 @@ Then, you can use the `useToast` composable to add notifications to your app:
|
||||
When using `toast.add`, this will push a new notification to the stack displayed in `<UNotifications />`. All the props of the `Notification` component can be passed to `toast.add`.
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
const toast = useToast()
|
||||
|
||||
onMounted(() => {
|
||||
@@ -289,8 +289,14 @@ Slots defined in the `<UNotifications />` component are automatically passed dow
|
||||
|
||||
## Props
|
||||
|
||||
:component-props
|
||||
::tabs
|
||||
:component-props{label="Notification"}
|
||||
:component-props{label="Notifications" slug="UNotifications"}
|
||||
::
|
||||
|
||||
## Config
|
||||
|
||||
:component-preset
|
||||
::tabs
|
||||
:component-preset{label="Notification"}
|
||||
:component-preset{label="Notifications" slug="Notifications"}
|
||||
::
|
||||
|
||||
@@ -46,6 +46,12 @@ props:
|
||||
---
|
||||
::
|
||||
|
||||
### Links
|
||||
|
||||
Use the `to` property to transform buttons into links. Note that it must be a function that receives the page number and returns a route destination.
|
||||
|
||||
:component-example{component="pagination-example-to"}
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` prop to disable all the buttons.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
---
|
||||
description: Display a non-modal dialog that floats around a trigger element.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/Popover.vue
|
||||
- label: 'Popover'
|
||||
icon: i-simple-icons-headlessui
|
||||
to: 'https://headlessui.com/vue/popover'
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/Popover.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
title: SelectMenu
|
||||
description: Display a select menu with advanced features.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/SelectMenu.vue
|
||||
- label: 'Listbox'
|
||||
icon: i-simple-icons-headlessui
|
||||
to: 'https://headlessui.com/vue/listbox'
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/SelectMenu.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
@@ -50,7 +50,7 @@ componentProps:
|
||||
---
|
||||
::
|
||||
|
||||
If you only want to select a single object property rather than the whole object as value, you can set the `value-attribute` property. This prop defaults to `null`.
|
||||
If you only want to select a single object property rather than the whole object as value, you can set the `value-attribute` property. This prop defaults to `null`.The value of the `value-attribute` field in options must be unique.
|
||||
|
||||
::component-example
|
||||
---
|
||||
@@ -150,6 +150,8 @@ Pass a function to the `searchable` prop to customize the search behavior and fi
|
||||
|
||||
Use the `debounce` prop to adjust the delay of the function.
|
||||
|
||||
Use the `searchableLazy` prop to control the immediacy of data requests. :u-badge{label="New" class="!rounded-full" variant="subtle"}
|
||||
|
||||
::component-example
|
||||
---
|
||||
component: 'select-menu-example-search-async'
|
||||
@@ -257,7 +259,7 @@ componentProps:
|
||||
Use the `#option-create` slot to customize the content displayed when the `creatable` prop is `true` and there is no options. You will have access to the `query` property in the slot scope.
|
||||
|
||||
::callout{icon="i-heroicons-light-bulb"}
|
||||
An example is available in the [Create option](#create-option) section.
|
||||
An example is available in the [Creatable](#creatable) section.
|
||||
::
|
||||
|
||||
### `empty`
|
||||
|
||||
@@ -203,7 +203,7 @@ Use the `#leading` slot to set the content of the leading icon.
|
||||
::component-card
|
||||
---
|
||||
slots:
|
||||
leading: <UAvatar src="https://avatars.githubusercontent.com/u/739984?v=4" size="3xs" class="mx-0.5" />
|
||||
leading: <UIcon name="i-heroicons-flag" class="w-5 h-5" />
|
||||
baseProps:
|
||||
options:
|
||||
- 'United States'
|
||||
@@ -213,7 +213,7 @@ baseProps:
|
||||
---
|
||||
|
||||
#leading
|
||||
:u-avatar{src="https://avatars.githubusercontent.com/u/739984?v=4" size="3xs" class="mx-0.5"}
|
||||
:u-icon{name="i-heroicons-flag" class="w-5 h-5"}
|
||||
::
|
||||
|
||||
### `trailing`
|
||||
@@ -223,13 +223,13 @@ Use the `#trailing` slot to set the content of the trailing icon.
|
||||
::component-card
|
||||
---
|
||||
slots:
|
||||
trailing: <UIcon name="i-heroicons-arrows-up-down-20-solid" />
|
||||
trailing: <UIcon name="i-heroicons-arrows-up-down-20-solid" class="w-5 h-5" />
|
||||
baseProps:
|
||||
placeholder: 'Search...'
|
||||
---
|
||||
|
||||
#trailing
|
||||
:u-icon{name="i-heroicons-arrows-up-down-20-solid"}
|
||||
:u-icon{name="i-heroicons-arrows-up-down-20-solid" class="w-5 h-5"}
|
||||
::
|
||||
|
||||
## Props
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
---
|
||||
description: Display a dialog that slides in from the edge of the screen.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/Slideover.vue
|
||||
- label: 'Dialog'
|
||||
icon: i-simple-icons-headlessui
|
||||
to: 'https://headlessui.com/vue/dialog'
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/Slideover.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
@@ -33,14 +33,14 @@ Set the `transition` prop to `false` to disable it.
|
||||
|
||||
### Prevent close
|
||||
|
||||
Use the `prevent-close` prop to disable the outside click alongside the `esc` keyboard shortcut. A `close-prevented` event will be emitted when the user tries to close the modal.
|
||||
Use the `prevent-close` prop to disable the outside click alongside the `esc` keyboard shortcut. A `close-prevented` event will be emitted when the user tries to close the slideover.
|
||||
|
||||
:component-example{component="slideover-example-prevent-close"}
|
||||
|
||||
You can still handle the `esc` shortcut yourself by using our [defineShortcuts](/getting-started/shortcuts#defineshortcuts) composable.
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
const isOpen = ref(false)
|
||||
|
||||
defineShortcuts({
|
||||
@@ -53,6 +53,24 @@ defineShortcuts({
|
||||
</script>
|
||||
```
|
||||
|
||||
### Control programmatically :u-badge{label="New" class="align-middle ml-2 !rounded-full" variant="subtle"}
|
||||
|
||||
First of all, add the `USlideovers` component to your app, preferably inside `app.vue`.
|
||||
|
||||
```vue [app.vue]
|
||||
<template>
|
||||
<div>
|
||||
<UContainer>
|
||||
<NuxtPage />
|
||||
</UContainer>
|
||||
<USlideovers />
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
Then, you can use the `useSlideover` composable to control your slideovers within your app.
|
||||
|
||||
:component-example{component="slideover-example-composable"}
|
||||
## Props
|
||||
|
||||
:component-props
|
||||
|
||||
@@ -12,6 +12,7 @@ Use the `rows` prop to set the data to display in the table. By default, the tab
|
||||
|
||||
::component-example{class="grid"}
|
||||
---
|
||||
extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
component: 'table-example-basic'
|
||||
componentProps:
|
||||
@@ -32,6 +33,7 @@ Use the `columns` prop to configure which columns to display. It's an array of o
|
||||
|
||||
::component-example{class="grid"}
|
||||
---
|
||||
extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
component: 'table-example-columns'
|
||||
componentProps:
|
||||
@@ -43,10 +45,11 @@ You can easily use the [SelectMenu](/components/select-menu) component to change
|
||||
|
||||
::component-example{class="grid"}
|
||||
---
|
||||
extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
component: 'table-example-columns-selectable'
|
||||
componentProps:
|
||||
class: 'flex-1'
|
||||
class: 'flex-1 flex-col overflow-hidden'
|
||||
---
|
||||
::
|
||||
|
||||
@@ -56,6 +59,7 @@ Also, you can apply styles to `th` elements by passing a `class` to columns.
|
||||
|
||||
::component-example{class="grid"}
|
||||
---
|
||||
extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
component: 'table-example-style'
|
||||
componentProps:
|
||||
@@ -71,6 +75,7 @@ You may specify the default direction of each column through the `direction` pro
|
||||
|
||||
::component-example{class="grid"}
|
||||
---
|
||||
extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
component: 'table-example-columns-sortable'
|
||||
componentProps:
|
||||
@@ -88,7 +93,7 @@ You can specify a default sort for the table through the `sort` prop. It's an ob
|
||||
This will set the default sort and will work even if no column is set as `sortable`.
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
const sort = ref({
|
||||
column: 'name',
|
||||
direction: 'desc'
|
||||
@@ -129,7 +134,7 @@ When fetching data from an API, we can take advantage of the [`useFetch`](https:
|
||||
When doing so, you might want to set the `sort-mode` prop to `manual` to disable the automatic sorting and return the rows as is.
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
// Ensure it uses `ref` instead of `reactive`.
|
||||
const sort = ref({
|
||||
column: 'name',
|
||||
@@ -151,7 +156,7 @@ const { data, pending } = await useLazyFetch(() => `/api/users?orderBy=${sort.va
|
||||
```
|
||||
|
||||
::callout{icon="i-heroicons-light-bulb" to="https://nuxt.com/docs/api/composables/use-fetch#params" target="_blank"}
|
||||
We pass a function to `useLazyFetch` here make the url reactive but you can use the `query` / `params` options alongside `watch`.
|
||||
We pass a function to `useLazyFetch` here to make the url reactive but you can use the `query` / `params` options alongside `watch`.
|
||||
::
|
||||
|
||||
#### Custom sorting
|
||||
@@ -160,6 +165,7 @@ Use the `sort-button` prop to customize the sort button in the header. You can p
|
||||
|
||||
::component-card{class="grid"}
|
||||
---
|
||||
extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
baseProps:
|
||||
class: 'w-full'
|
||||
@@ -240,6 +246,7 @@ Use a `v-model` to make the table selectable. The `v-model` will be an array of
|
||||
|
||||
::component-example{class="grid"}
|
||||
---
|
||||
extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
component: 'table-example-selectable'
|
||||
componentProps:
|
||||
@@ -257,6 +264,7 @@ You can use this to navigate to a page, open a modal or even to select the row m
|
||||
|
||||
::component-example{class="grid"}
|
||||
---
|
||||
extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
component: 'table-example-clickable'
|
||||
componentProps:
|
||||
@@ -270,10 +278,11 @@ You can easily use the [Input](/components/input) component to filter the rows.
|
||||
|
||||
::component-example{class="grid"}
|
||||
---
|
||||
extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
component: 'table-example-searchable'
|
||||
componentProps:
|
||||
class: 'flex-1'
|
||||
class: 'flex-1 flex-col overflow-hidden'
|
||||
---
|
||||
::
|
||||
|
||||
@@ -283,23 +292,25 @@ You can easily use the [Pagination](/components/pagination) component to paginat
|
||||
|
||||
::component-example{class="grid"}
|
||||
---
|
||||
extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
component: 'table-example-paginable'
|
||||
componentProps:
|
||||
class: 'flex-1'
|
||||
class: 'flex-1 flex-col overflow-hidden'
|
||||
---
|
||||
::
|
||||
|
||||
### Loading
|
||||
|
||||
Use the `loading` prop to display a loading state.
|
||||
Use the `loading` prop to indicate that data is currently loading with an indeterminate [Progress](/components/progress#indeterminate) bar.
|
||||
|
||||
Use the `loading-state` prop to customize the `icon` and `label` or change them globally in `ui.table.default.loadingState`.
|
||||
You can use the `progress` prop to customize the `color` and `animation` of the progress bar or change them globally in `ui.table.default.progress` (you can set it to `null` to hide the progress bar).
|
||||
|
||||
You can also set it to `null` to hide the loading state.
|
||||
If there is no rows provided, a loading state will also be displayed. You can use the `loading-state` prop to customize the `icon` and `label` or change them globally in `ui.table.default.loadingState` (you can set it to `null` to hide the loading state).
|
||||
|
||||
::component-card
|
||||
---
|
||||
extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
baseProps:
|
||||
class: 'w-full'
|
||||
@@ -319,15 +330,19 @@ props:
|
||||
loadingState:
|
||||
icon: 'i-heroicons-arrow-path-20-solid'
|
||||
label: "Loading..."
|
||||
progress:
|
||||
color: 'primary'
|
||||
animation: 'carousel'
|
||||
excludedProps:
|
||||
- loadingState
|
||||
- progress
|
||||
---
|
||||
::
|
||||
|
||||
This can be easily used with Nuxt `useAsyncData` composable.
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
const columns = [...]
|
||||
|
||||
const { pending, data: people } = await useLazyAsyncData('people', () => $fetch('/api/people'))
|
||||
@@ -348,6 +363,7 @@ You can also set it to `null` to hide the empty state.
|
||||
|
||||
::component-card
|
||||
---
|
||||
extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
baseProps:
|
||||
class: 'w-full'
|
||||
@@ -398,6 +414,7 @@ You can for example create an extra column for actions with a [Dropdown](/compon
|
||||
|
||||
::component-example{class="grid"}
|
||||
---
|
||||
extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
component: 'table-example-slots'
|
||||
componentProps:
|
||||
@@ -411,6 +428,7 @@ Use the `#loading-state` slot to customize the loading state.
|
||||
|
||||
::component-example{class="grid"}
|
||||
---
|
||||
extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
component: 'table-example-loading-slot'
|
||||
componentProps:
|
||||
@@ -424,6 +442,7 @@ Use the `#empty-state` slot to customize the empty state.
|
||||
|
||||
::component-example{class="grid"}
|
||||
---
|
||||
extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
component: 'table-example-empty-slot'
|
||||
componentProps:
|
||||
@@ -431,6 +450,19 @@ componentProps:
|
||||
---
|
||||
::
|
||||
|
||||
### `caption`
|
||||
|
||||
Use the `#caption` slot to customize the table's caption.
|
||||
|
||||
::component-example
|
||||
---
|
||||
padding: false
|
||||
component: 'table-example-caption-slot'
|
||||
componentProps:
|
||||
class: 'flex-1'
|
||||
---
|
||||
::
|
||||
|
||||
## Props
|
||||
|
||||
:component-props
|
||||
@@ -443,7 +475,16 @@ componentProps:
|
||||
|
||||
Here is an example of a Table component with all its features implemented.
|
||||
|
||||
:component-example{component="table-example-advanced" hiddenCode :padding="false" }
|
||||
::component-example
|
||||
---
|
||||
extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
component: 'table-example-advanced'
|
||||
componentProps:
|
||||
class: 'flex-1'
|
||||
hiddenCode: true
|
||||
---
|
||||
::
|
||||
|
||||
::callout{icon="i-simple-icons-github" to="https://github.com/nuxt/ui/blob/dev/docs/components/content/examples/TableExampleAdvanced.vue" target="_blank"}
|
||||
Take a look at the component!
|
||||
|
||||
@@ -63,6 +63,8 @@ componentProps:
|
||||
---
|
||||
::
|
||||
|
||||
You can use the `content` prop and set it to `false` to avoid the rendering of the HTML content if you don't need it.
|
||||
|
||||
### Control the selected index
|
||||
|
||||
Use a `v-model` to control the selected index.
|
||||
|
||||
@@ -119,6 +119,19 @@ props:
|
||||
---
|
||||
::
|
||||
|
||||
Use the `maxrows` prop to set a maximum number of rows when autoresizing. If set to `0`, the Textarea will infinitely grow up. :u-badge{label="New" class="!rounded-full" variant="subtle"}
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
placeholder: 'Search...'
|
||||
modelValue: 'Here is an autoresize Textarea, write new lines to make the Textarea grow up at a maximum of 5 rows...'
|
||||
props:
|
||||
autoresize: true
|
||||
maxrows: 5
|
||||
---
|
||||
::
|
||||
|
||||
### Resize
|
||||
|
||||
Use the `resize` prop to enable the resize control.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
---
|
||||
description: Display a toggle field.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/Toggle.vue
|
||||
- label: 'Switch'
|
||||
icon: i-simple-icons-headlessui
|
||||
to: 'https://headlessui.com/vue/switch'
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/Toggle.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
@@ -52,6 +52,19 @@ excludedProps:
|
||||
---
|
||||
::
|
||||
|
||||
### Loading :u-badge{label="New" class="align-middle ml-2 !rounded-full" variant="subtle"}
|
||||
|
||||
Use the `loading` prop to show a loading icon and disable the Toggle.
|
||||
|
||||
Use the `loading-icon` prop to set a different icon or change it globally in `ui.toggle.default.loadingIcon`. Defaults to `i-heroicons-arrow-path-20-solid`.
|
||||
|
||||
::component-card
|
||||
---
|
||||
props:
|
||||
loading: true
|
||||
---
|
||||
::
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` prop to disable the Toggle.
|
||||
|
||||
@@ -79,10 +79,10 @@ pro:
|
||||
title: Upgrade to <span class="text-primary">Nuxt UI Pro</span>
|
||||
description: 'Nuxt UI Pro is a collection of premium Vue components built on top of Nuxt UI to create beautiful & responsive Nuxt applications in minutes.<br>It includes all primitives to build landing pages, documentations, blogs, dashboards or entire SaaS products.'
|
||||
links:
|
||||
- label: View plans
|
||||
- label: Buy now
|
||||
to: /pro/pricing
|
||||
color: gray
|
||||
icon: i-heroicons-credit-card
|
||||
color: black
|
||||
trailingIcon: i-heroicons-arrow-right-20-solid
|
||||
size: lg
|
||||
- label: Explore templates
|
||||
to: /pro/templates
|
||||
@@ -178,7 +178,7 @@ pro:
|
||||
</UPageBody>
|
||||
|
||||
<template #right>
|
||||
<UDocsToc :links="page.body.toc.links" />
|
||||
<UContentToc :links="page.body.toc.links" />
|
||||
</template>
|
||||
</UPage>
|
||||
</template>
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
navigation: false
|
||||
title: Releases
|
||||
description: Follow the latest releases and updates of Nuxt UI.
|
||||
title: '<span class="text-primary">Nuxt UI</span> Releases'
|
||||
head.title: Releases
|
||||
description: Follow the latest releases and updates happening on the nuxt/ui repository.
|
||||
links:
|
||||
- label: Get Started
|
||||
trailingIcon: i-heroicons-arrow-right-20-solid
|
||||
to: /getting-started
|
||||
size: md
|
||||
color: black
|
||||
- label: View on GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/releases
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<template>
|
||||
<div>
|
||||
<NuxtLoadingIndicator />
|
||||
@@ -12,11 +13,18 @@
|
||||
</UMain>
|
||||
</UContainer>
|
||||
|
||||
<Footer />
|
||||
|
||||
<ClientOnly>
|
||||
<LazyUDocsSearch :files="files" :navigation="navigation" :links="links" :fuse="{ resultLimit: 1000 }" />
|
||||
<LazyUContentSearch :files="files" :navigation="navigation" :links="links" :fuse="{ resultLimit: 42 }" />
|
||||
</ClientOnly>
|
||||
|
||||
<UNotifications />
|
||||
<UNotifications>
|
||||
<template #title="{ title }">
|
||||
<span v-html="title" />
|
||||
</template>
|
||||
</UNotifications>
|
||||
<UModals />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -34,6 +42,7 @@ defineProps<{
|
||||
}>()
|
||||
|
||||
const route = useRoute()
|
||||
const colorMode = useColorMode()
|
||||
const { branch } = useContentSource()
|
||||
|
||||
const { data: nav } = await useAsyncData('navigation', () => fetchContentNavigation())
|
||||
@@ -52,9 +61,11 @@ const navigation = computed(() => {
|
||||
]
|
||||
}
|
||||
|
||||
return nav.value.filter(item => item._path !== '/dev')
|
||||
return nav.value?.filter(item => item._path !== '/dev') || []
|
||||
})
|
||||
|
||||
const color = computed(() => colorMode.value === 'dark' ? '#18181b' : 'white')
|
||||
|
||||
const links = computed(() => {
|
||||
return [{
|
||||
label: 'Docs',
|
||||
@@ -65,10 +76,10 @@ const links = computed(() => {
|
||||
label: 'Pro',
|
||||
icon: 'i-heroicons-square-3-stack-3d',
|
||||
to: '/pro',
|
||||
active: route.path.startsWith('/pro/getting-started') || route.path.startsWith('/pro/components')
|
||||
active: route.path.startsWith('/pro/getting-started') || route.path.startsWith('/pro/components') || route.path.startsWith('/pro/prose')
|
||||
}, {
|
||||
label: 'Pricing',
|
||||
icon: 'i-heroicons-credit-card',
|
||||
icon: 'i-heroicons-ticket',
|
||||
to: '/pro/pricing'
|
||||
}, {
|
||||
label: 'Templates',
|
||||
@@ -81,6 +92,21 @@ const links = computed(() => {
|
||||
}].filter(Boolean)
|
||||
})
|
||||
|
||||
// Head
|
||||
|
||||
useHead({
|
||||
meta: [
|
||||
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
|
||||
{ key: 'theme-color', name: 'theme-color', content: color }
|
||||
],
|
||||
link: [
|
||||
{ rel: 'icon', type: 'image/svg+xml', href: '/icon.svg' }
|
||||
],
|
||||
htmlAttrs: {
|
||||
lang: 'en'
|
||||
}
|
||||
})
|
||||
|
||||
// Provide
|
||||
|
||||
provide('navigation', navigation)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createResolver } from '@nuxt/kit'
|
||||
import colors from 'tailwindcss/colors'
|
||||
import module from '../src/module'
|
||||
import { excludeColors } from '../src/colors'
|
||||
import { excludeColors } from '../src/runtime/utils/colors'
|
||||
import pkg from '../package.json'
|
||||
|
||||
const { resolve } = createResolver(import.meta.url)
|
||||
@@ -17,12 +17,10 @@ export default defineNuxtConfig({
|
||||
].filter(Boolean),
|
||||
modules: [
|
||||
'@nuxt/content',
|
||||
'@nuxt/fonts',
|
||||
'@nuxt/image',
|
||||
'nuxt-og-image',
|
||||
// '@nuxthq/studio',
|
||||
module,
|
||||
'@nuxtjs/fontaine',
|
||||
'@nuxtjs/google-fonts',
|
||||
'@nuxtjs/plausible',
|
||||
'@vueuse/nuxt',
|
||||
'nuxt-component-meta',
|
||||
@@ -40,6 +38,12 @@ export default defineNuxtConfig({
|
||||
safelistColors: excludeColors(colors)
|
||||
},
|
||||
content: {
|
||||
highlight: {
|
||||
langs: [
|
||||
'postcss',
|
||||
'mdc'
|
||||
]
|
||||
},
|
||||
sources: {
|
||||
dev: {
|
||||
prefix: '/dev',
|
||||
@@ -67,15 +71,8 @@ export default defineNuxtConfig({
|
||||
} : undefined
|
||||
}
|
||||
},
|
||||
fontMetrics: {
|
||||
fonts: ['DM Sans']
|
||||
},
|
||||
googleFonts: {
|
||||
display: 'swap',
|
||||
download: true,
|
||||
families: {
|
||||
'DM+Sans': [400, 500, 600, 700]
|
||||
}
|
||||
image: {
|
||||
provider: 'ipx'
|
||||
},
|
||||
nitro: {
|
||||
prerender: {
|
||||
|
||||
@@ -1,36 +1,32 @@
|
||||
{
|
||||
"name": "@nuxt/ui-docs",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@nuxt/ui": "workspace:latest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify-json/heroicons": "^1.1.19",
|
||||
"@iconify-json/simple-icons": "^1.1.90",
|
||||
"@nuxt/content": "^2.11.0",
|
||||
"@nuxt/devtools": "^1.0.8",
|
||||
"@nuxt/eslint-config": "^0.2.0",
|
||||
"@nuxt/image": "^1.3.0",
|
||||
"@nuxt/ui-pro": "npm:@nuxt/ui-pro-edge@0.7.3-28443525.f773d8f",
|
||||
"@nuxthq/studio": "^1.0.10",
|
||||
"@nuxtjs/fontaine": "^0.4.1",
|
||||
"@nuxtjs/google-fonts": "^3.1.3",
|
||||
"@nuxtjs/plausible": "^0.2.4",
|
||||
"@octokit/rest": "^20.0.2",
|
||||
"@vueuse/nuxt": "^10.7.2",
|
||||
"date-fns": "^3.3.1",
|
||||
"eslint": "^8.56.0",
|
||||
"joi": "^17.11.1",
|
||||
"nuxt": "^3.9.3",
|
||||
"@iconify-json/heroicons": "^1.1.21",
|
||||
"@iconify-json/simple-icons": "^1.1.105",
|
||||
"@nuxt/content": "^2.12.1",
|
||||
"@nuxt/eslint-config": "^0.3.13",
|
||||
"@nuxt/fonts": "^0.7.0",
|
||||
"@nuxt/image": "^1.7.0",
|
||||
"@nuxt/ui": "latest",
|
||||
"@nuxt/ui-pro": "npm:@nuxt/ui-pro-edge@1.2.0-28637819.42c6d9b",
|
||||
"@nuxtjs/plausible": "^1.0.0",
|
||||
"@octokit/rest": "^20.1.1",
|
||||
"@vueuse/nuxt": "^10.11.0",
|
||||
"date-fns": "^3.6.0",
|
||||
"eslint": "^8.57.0",
|
||||
"joi": "^17.13.1",
|
||||
"nuxt": "^3.12.1",
|
||||
"nuxt-cloudflare-analytics": "^1.0.8",
|
||||
"nuxt-component-meta": "^0.6.3",
|
||||
"nuxt-component-meta": "^0.6.4",
|
||||
"nuxt-og-image": "^2.2.4",
|
||||
"prettier": "^3.2.4",
|
||||
"typescript": "^5.3.3",
|
||||
"ufo": "^1.3.2",
|
||||
"prettier": "^3.3.2",
|
||||
"typescript": "^5.4.5",
|
||||
"ufo": "^1.5.3",
|
||||
"v-calendar": "^3.1.2",
|
||||
"valibot": "^0.25.0",
|
||||
"yup": "^1.3.3",
|
||||
"zod": "^3.22.4"
|
||||
"valibot": "^0.31.1",
|
||||
"yup": "^1.4.0",
|
||||
"zod": "^3.23.8"
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user