Compare commits

..

1 Commits

Author SHA1 Message Date
Sandros94
c2216c8c28 chore(package): simplify files array in package.json 2025-04-25 00:20:03 +02:00
301 changed files with 14576 additions and 19270 deletions

1
.github/CODEOWNERS vendored
View File

@@ -1 +0,0 @@
* @benjamincanac

View File

@@ -5,7 +5,7 @@ body:
- type: markdown
attributes:
value: |
Before reporting a bug, please make sure that you have read through our [documentation](https://ui.nuxt.com/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
Before reporting a bug, please make sure that you have read through our [v3 documentation](https://ui.nuxt.com/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
- type: textarea
id: env
attributes:
@@ -44,7 +44,7 @@ body:
id: reproduction
attributes:
label: Reproduction
description: Please provide a reproduction link using the Nuxt template https://codesandbox.io/p/devbox/nuxt-ui3-n3sxks or the Vue template https://codesandbox.io/p/devbox/nuxt-ui3-vue-4h5gqn. A minimal [reproduction is required](https://antfu.me/posts/why-reproductions-are-required) unless you are absolutely sure that the issue is obvious and the provided information is enough to understand the problem. If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a "needs reproduction" label. If no reproduction is provided, it will be closed automatically after a while.
description: Please provide a reproduction link using the Nuxt template https://codesandbox.io/p/devbox/nuxt-ui3-n3sxks or the Vue template https://codesandbox.io/p/devbox/nuxt-ui3-vue-4h5gqn. A minimal [reproduction is required](https://antfu.me/posts/why-reproductions-are-required) unless you are absolutely sure that the issue is obvious and the provided information is enough to understand the problem. If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a "needs reproduction" label. If no reproduction is provided we might close it.
placeholder: https://github.com/my/reproduction
validations:
required: true

View File

@@ -5,7 +5,7 @@ body:
- type: markdown
attributes:
value: |
Before requesting a feature, please make sure that you have read through our [documentation](https://ui.nuxt.com/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
Before requesting a feature, please make sure that you have read through our [v3 documentation](https://ui.nuxt.com/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
- type: textarea
id: description
attributes:

View File

@@ -5,7 +5,7 @@ body:
- type: markdown
attributes:
value: |
Before asking a question, please make sure that you have read through our [documentation](https://ui.nuxt.com/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
Before asking a question, please make sure that you have read through our [v3 documentation](https://ui.nuxt.com/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
- type: textarea
id: description
attributes:

View File

@@ -1,30 +0,0 @@
Would you be able to provide a [reproduction](https://nuxt.com/docs/community/reporting-bugs/#create-a-minimal-reproduction)? 🙏
<details>
<summary>More info</summary>
### Why do I need to provide a reproduction?
Reproductions make it possible for us to triage and fix issues quickly with a relatively small team. It helps us discover the source of the problem, and also can reveal assumptions you or we might be making.
### What will happen?
If you've provided a reproduction, we'll remove the label and try to reproduce the issue. If we can, we'll mark it as a bug and prioritise it based on its severity and how many people we think it might affect.
If `needs reproduction` labeled issues don't receive any substantial activity (e.g., new comments featuring a reproduction link), they will be closed automatically after a while. That's not because we don't care! At any point, feel free to comment with a reproduction and we'll reopen it.
### How can I create a reproduction?
We have templates to create a minimal reproduction:
* **Nuxt**: https://codesandbox.io/p/devbox/nuxt-ui3-n3sxks
* **Vue**: https://codesandbox.io/p/devbox/nuxt-ui3-vue-4h5gqn
Please ensure that the reproduction is as **minimal** as possible. See more details [in our guide](https://nuxt.com/docs/community/reporting-bugs/#create-a-minimal-reproduction).
You might also find these other articles interesting and/or helpful:
- [The Importance of Reproductions](https://antfu.me/posts/why-reproductions-are-required)
- [How to Generate a Minimal, Complete, and Verifiable Example](https://stackoverflow.com/help/mcve)
</details>

View File

@@ -69,53 +69,6 @@ jobs:
if: matrix.os == 'ubuntu-latest'
run: pnpx pkg-pr-new publish --compact --no-template --pnpm
playground:
needs: build
runs-on: ${{ matrix.os }}
defaults:
run:
working-directory: ./playground
permissions:
contents: read
pull-requests: read
strategy:
matrix:
os: [ubuntu-latest] # macos-latest, windows-latest
node: [22]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Store commit SHA
run: |
echo "COMMIT_SHA=$(echo ${{ github.workflow_sha }} | cut -c1-7)" >> $GITHUB_ENV
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Install node
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- name: Install latest nuxt/ui
run: pnpm install https://pkg.pr.new/@nuxt/ui@${{ env.COMMIT_SHA }} --lockfile-only
- name: Install dependencies
run: pnpm install --ignore-workspace
- name: Prepare
run: pnpm nuxi prepare
- name: Typecheck
run: pnpm run typecheck
starter-nuxt:
needs: build

View File

@@ -1,17 +0,0 @@
name: reproduire
on:
issues:
types: [labeled]
permissions:
issues: write
jobs:
reproduire:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: Hebilicious/reproduire@4b686ae9cbb72dad60f001d278b6e3b2ce40a9ac # v0.0.9-mp
with:
label: needs reproduction

View File

@@ -1,103 +1,5 @@
# Changelog
## [3.1.3](https://github.com/nuxt/ui/compare/v3.1.2...v3.1.3) (2025-05-26)
### ⚠ BREAKING CHANGES
* **NavigationMenu:** revert new `collapsible` field
### Features
* **locale:** add Kyrgyz language ([#4189](https://github.com/nuxt/ui/issues/4189)) ([4053047](https://github.com/nuxt/ui/commit/405304775e4b2b4e8b37a2364f3e5ee34b46036e))
* **locale:** add Lithuanian language ([#4171](https://github.com/nuxt/ui/issues/4171)) ([d86956e](https://github.com/nuxt/ui/commit/d86956e1d57482b3e98eef2d34bff13544284b0b))
* **locale:** add Malay language ([#4160](https://github.com/nuxt/ui/issues/4160)) ([c00f6e8](https://github.com/nuxt/ui/commit/c00f6e8cdfd88eeba58812b78d94a2326c13f164))
* **locale:** add Mongolian language ([#4214](https://github.com/nuxt/ui/issues/4214)) ([44ea02c](https://github.com/nuxt/ui/commit/44ea02c0d64322ef0cfda63b234369c00d3d0180))
* **Modal/Slideover:** add `after:enter` event ([#4187](https://github.com/nuxt/ui/issues/4187)) ([d9e9fea](https://github.com/nuxt/ui/commit/d9e9fea35e4b22d68324c9e85b3aa221a7987d0f))
* **NavigationMenu:** add `tooltip` and `popover` props ([f2682fd](https://github.com/nuxt/ui/commit/f2682fd2ae8abb7807977727fc22ef34cb5752e5)), closes [#4186](https://github.com/nuxt/ui/issues/4186)
* **NavigationMenu:** add `trigger` type in items ([9cf9f25](https://github.com/nuxt/ui/commit/9cf9f25f4424447691e03e9034155d1541badd43))
* **NavigationMenu:** handle `vertical` orientation with Accordion instead of Collapsible ([1e2a10b](https://github.com/nuxt/ui/commit/1e2a10b4bdebaef12316ac60f98a956dad21c1ec)), closes [#4072](https://github.com/nuxt/ui/issues/4072) [#3911](https://github.com/nuxt/ui/issues/3911)
* **Popover:** add `anchor` slot ([#4119](https://github.com/nuxt/ui/issues/4119)) ([473513c](https://github.com/nuxt/ui/commit/473513c2460d4329d7d2e0a0ea69bf1310a072d1))
### Bug Fixes
* **CheckboxGroup/RadioGroup:** variant `table` borders in RTL mode ([#4192](https://github.com/nuxt/ui/issues/4192)) ([43d281f](https://github.com/nuxt/ui/commit/43d281f6d1d8b0017ed61d929c5e311fb5b03447))
* **CommandPalette:** add `presentation` role to viewport ([2ba94db](https://github.com/nuxt/ui/commit/2ba94db09e1ba86020d5d289f1ca1e24ef706299))
* **ContextMenu/DropdownMenu:** wrap groups in a viewport ([dcf34a7](https://github.com/nuxt/ui/commit/dcf34a7ac236b96b1302ec2eae155b8f2d3784ef)), closes [#3315](https://github.com/nuxt/ui/issues/3315)
* **Drawer:** improve title & description accessibility ([41087d4](https://github.com/nuxt/ui/commit/41087d4c9569eb00c04bd748e055cd151c2f762c)), closes [#4199](https://github.com/nuxt/ui/issues/4199)
* **icons:** update `loading` icon ([#4163](https://github.com/nuxt/ui/issues/4163)) ([fe4e1f8](https://github.com/nuxt/ui/commit/fe4e1f859d42aa3c32bb7b75302e84a280abe525))
* **Input/Textarea:** define model modifiers types ([#4195](https://github.com/nuxt/ui/issues/4195)) ([3243fb8](https://github.com/nuxt/ui/commit/3243fb88f71c5475824bfdc4d7c4f303b2d6790b))
* **InputMenu/Select/SelectMenu:** manual viewport to display scrollbars ([f95abf8](https://github.com/nuxt/ui/commit/f95abf8d1d7b9149e400d7dc6f96f93f5154da7a)), closes [#4069](https://github.com/nuxt/ui/issues/4069)
* **NavigationMenu:** incorrect hover when disabled and active ([d0be599](https://github.com/nuxt/ui/commit/d0be59946bfe30c79a6f75476385ab8538aa51b8))
* **NavigationMenu:** only display `tooltip` when collapsed ([44f536f](https://github.com/nuxt/ui/commit/44f536fd0034facb3550d910fae71d4f9442ed19))
* **NavigationMenu:** remove `font-medium` in popover children ([0236399](https://github.com/nuxt/ui/commit/02363994d66d3c2d11b9913f31167fa25f5c5de2))
* **NavigationMenu:** revert new `collapsible` field ([3c78e2f](https://github.com/nuxt/ui/commit/3c78e2fd983f19b5cec65b4a94a8a8b14e548e5e))
* **Textarea:** missing imports ([#4207](https://github.com/nuxt/ui/issues/4207)) ([6aab62e](https://github.com/nuxt/ui/commit/6aab62ec30e266c5f0da0cd24aefbb7c53f447ac))
* **theme:** define `old-neutral` color as static ([#4193](https://github.com/nuxt/ui/issues/4193)) ([dae9f0b](https://github.com/nuxt/ui/commit/dae9f0b8631b3b9fb60ef47753f7aded0c36c4a2))
* **Tooltip:** increase padding for consistency ([0634a75](https://github.com/nuxt/ui/commit/0634a756a496f5131841abafd218ae7e4aaa61e5))
## [3.1.2](https://github.com/nuxt/ui/compare/v3.1.1...v3.1.2) (2025-05-15)
### Features
* **Badge:** add `square` prop ([#4008](https://github.com/nuxt/ui/issues/4008)) ([894e8a6](https://github.com/nuxt/ui/commit/894e8a61b6fea3618fc863bd77678385e9d021c2))
* **CheckboxGroup:** add `table` variant ([#3997](https://github.com/nuxt/ui/issues/3997)) ([1b6ab27](https://github.com/nuxt/ui/commit/1b6ab271ea3875a7c77ffe9367c7c341083dd53c))
* **components:** add `ui` field in items ([#4060](https://github.com/nuxt/ui/issues/4060)) ([b9adc83](https://github.com/nuxt/ui/commit/b9adc83e787db02507e6e7bb1aabc684eccc197b))
* **InputNumber:** add `increment-disabled` / `decrement-disabled` props ([#4141](https://github.com/nuxt/ui/issues/4141)) ([c7fba2e](https://github.com/nuxt/ui/commit/c7fba2e0ebfb7153f3bfb727165d653bbd3dbe54))
* **locale:** add Slovenian language ([#4140](https://github.com/nuxt/ui/issues/4140)) ([e86dc79](https://github.com/nuxt/ui/commit/e86dc79e51b2773a77ada5f12d4f0964fbc83354))
* **NavigationMenu:** add `collapsible` field in items ([2be60cd](https://github.com/nuxt/ui/commit/2be60cddfe10fd1e2466900fd53e21ee0c877227)), closes [#3353](https://github.com/nuxt/ui/issues/3353) [#3911](https://github.com/nuxt/ui/issues/3911)
* **NavigationMenu:** handle `tooltip` in items ([46c2987](https://github.com/nuxt/ui/commit/46c2987ebfd30b2b071a96a745b7270e852e96de)), closes [#4050](https://github.com/nuxt/ui/issues/4050)
* **Slider:** handle `tooltip` around thumbs ([d140acc](https://github.com/nuxt/ui/commit/d140acc608c6ae11c0a0531fe443588776ea7807)), closes [#1469](https://github.com/nuxt/ui/issues/1469)
* **Toast:** add `progress` prop to hide progress bar ([#4125](https://github.com/nuxt/ui/issues/4125)) ([92632e9](https://github.com/nuxt/ui/commit/92632e969eaa11521a166e50e346753929b7f523))
### Bug Fixes
* **Badge/Button:** handle zero value in label correctly ([#4108](https://github.com/nuxt/ui/issues/4108)) ([f244d15](https://github.com/nuxt/ui/commit/f244d15b96d97cd8ba34ba9c18f23965e17e3cef))
* **ButtonGroup:** add `z-index` on focused element ([204953b](https://github.com/nuxt/ui/commit/204953b780bde08dbfde230fc8887674449227b7))
* **Calendar:** wrong color for today date with `neutral` color ([7d51a9e](https://github.com/nuxt/ui/commit/7d51a9e479cb6105ea37759c5cd67ff9f7702c49)), closes [#4084](https://github.com/nuxt/ui/issues/4084) [#3629](https://github.com/nuxt/ui/issues/3629)
* **Checkbox/RadioGroup:** render correct element without `variant` ([f2fd778](https://github.com/nuxt/ui/commit/f2fd778c0a604f2d65aec9f3fe2d54b6d4e8c3a2)), closes [#3998](https://github.com/nuxt/ui/issues/3998)
* **CheckboxGroup:** relative `UCheckbox` import ([7551a85](https://github.com/nuxt/ui/commit/7551a85ad2d92b59e2909396affb862403d5b27a)), closes [#4090](https://github.com/nuxt/ui/issues/4090)
* **ColorPicker:** make thumb touch draggable ([#4101](https://github.com/nuxt/ui/issues/4101)) ([cc20a26](https://github.com/nuxt/ui/commit/cc20a26f07268d19119ab4c7c254033143bb63f4))
* **components:** `class` should have priority over `ui` prop ([e6e510b](https://github.com/nuxt/ui/commit/e6e510b848d995a286a51d50a120d67483e11232))
* **FormField:** block form field injection after use ([#4150](https://github.com/nuxt/ui/issues/4150)) ([d79da9d](https://github.com/nuxt/ui/commit/d79da9d7b60c9972af64acd8e6eef4ae7d6bc3eb))
* **FormField:** use `div` for `error` and `help` slots ([459a041](https://github.com/nuxt/ui/commit/459a0410ab729fde60865e84632b36903465f57e))
* **inertia:** link always render as anchor tag ([#3989](https://github.com/nuxt/ui/issues/3989)) ([e81464a](https://github.com/nuxt/ui/commit/e81464a43ede4e63ce3dc92429bbfef48614f731))
* **inertia:** make `useAppConfig` reactive ([12303a8](https://github.com/nuxt/ui/commit/12303a87be62dae84ef774e3a9795deb0ac90cc7))
* **Input/Textarea:** handle generic types ([3c8d6cd](https://github.com/nuxt/ui/commit/3c8d6cd01dfafed5844c376f52adbdda0c814420)), closes [nuxt/ui-pro#887](https://github.com/nuxt/ui-pro/issues/887)
* **InputNumber:** handle inside button group ([2e4c308](https://github.com/nuxt/ui/commit/2e4c3082a1e66fa597086dc3431fec37fa29ef62)), closes [#4155](https://github.com/nuxt/ui/issues/4155)
* **Link:** consistent behavior between nuxt, vue and inertia ([#4134](https://github.com/nuxt/ui/issues/4134)) ([67da90a](https://github.com/nuxt/ui/commit/67da90a2f638124f640c4271d3376c5ff3fab6a1))
* **module:** configure `@nuxt/fonts` with default weights ([276268d](https://github.com/nuxt/ui/commit/276268d311f57715cec47bc600a0ccc3d3885682))
* **NavigationMenu:** arrow position conflict ([#4137](https://github.com/nuxt/ui/issues/4137)) ([0dc4678](https://github.com/nuxt/ui/commit/0dc4678c68e4b500be49c38336dc75b73843e38d))
* **Select:** support more primitive types in `value` field ([#4105](https://github.com/nuxt/ui/issues/4105)) ([09b4699](https://github.com/nuxt/ui/commit/09b4699aeadaa195ea081509f8e237bb2c346238))
* **Slider:** handle generic types ([d7a4d02](https://github.com/nuxt/ui/commit/d7a4d029b77d2dfa0b8efcd2755d482fa5e31fd3))
* **Stepper:** use `div` tag for `title` & `description` ([a57844e](https://github.com/nuxt/ui/commit/a57844e41676c13ed1af861424961b88cee7b4da)), closes [#4096](https://github.com/nuxt/ui/issues/4096)
* **Tabs:** prevent trigger truncate without parent width ([06e5689](https://github.com/nuxt/ui/commit/06e5689da80b36205d0548d5d6b58510938e4a6e)), closes [#4056](https://github.com/nuxt/ui/issues/4056)
* **Tabs:** set `focus:outline-none` with `link` variant ([999a0f8](https://github.com/nuxt/ui/commit/999a0f84671fad20fa3dc50c6774af2e0200b32e))
* **templates:** dont write unused variants in theme files ([d3df3bb](https://github.com/nuxt/ui/commit/d3df3bb929fe6732f27b182d1664213884a662ec))
* **Toaster:** allow `base` slot override ([c63d2f3](https://github.com/nuxt/ui/commit/c63d2f380aac16f1d1e812516df3dca7fa7c8034))
* **vue:** make `useAppConfig` reactive ([869c070](https://github.com/nuxt/ui/commit/869c0708bd351c7be44e5e430c348b19dd316db9)), closes [#3952](https://github.com/nuxt/ui/issues/3952)
## [3.1.1](https://github.com/nuxt/ui/compare/v3.1.0...v3.1.1) (2025-05-02)
### Features
* **useOverlay:** add `closeAll` method ([#3984](https://github.com/nuxt/ui/issues/3984)) ([ac4c194](https://github.com/nuxt/ui/commit/ac4c1946ec399aec59b4bce9d538e3ff67868abf))
* **useOverlay:** add `isOpen` method to check overlay state ([#4041](https://github.com/nuxt/ui/issues/4041)) ([a4f3f6d](https://github.com/nuxt/ui/commit/a4f3f6d531f9c0281f99085a6688d296f8f13f2f))
### Bug Fixes
* **Calendar:** add `place-items-center` to grid row ([#4034](https://github.com/nuxt/ui/issues/4034)) ([8dfdd63](https://github.com/nuxt/ui/commit/8dfdd63ce3b3a0e904f7c013c774cf9aaf46b240))
* **defineShortcuts:** bring back `meta` to `ctrl` convert on non macos platforms ([f3b8b17](https://github.com/nuxt/ui/commit/f3b8b17dc5f43936ef7ffb11c1ed7f9a5f94d0bb)), closes [#3869](https://github.com/nuxt/ui/issues/3869) [#3318](https://github.com/nuxt/ui/issues/3318)
* **module:** support `nuxt-nightly` ([#3996](https://github.com/nuxt/ui/issues/3996)) ([bc0a296](https://github.com/nuxt/ui/commit/bc0a296f9d68ca72cd991b11cd3489b63c7b13db))
* **NavigationMenu:** remove `sm:w-auto` from content slot ([aebf0b3](https://github.com/nuxt/ui/commit/aebf0b3dca50c51c093cb6abf16c4fd995fc1b39)), closes [#3987](https://github.com/nuxt/ui/issues/3987)
* **RadioGroup:** improve items `value` field type ([#3995](https://github.com/nuxt/ui/issues/3995)) ([195773e](https://github.com/nuxt/ui/commit/195773ec7dac12ccc3a0a67867751e8ca634cc04))
* **templates:** put back args to watch in dev ([#4033](https://github.com/nuxt/ui/issues/4033)) ([c5bdec0](https://github.com/nuxt/ui/commit/c5bdec0f64963ef602975270a09a1ee795cdacf9))
* **theme:** add missing `border-bg` / `divide-bg` utilities ([82b5f32](https://github.com/nuxt/ui/commit/82b5f322ebd8a08e63588122bd4ef567dcb8ba8c))
* **theme:** add missing `ring-offset-*` utilities ([#3992](https://github.com/nuxt/ui/issues/3992)) ([e5df026](https://github.com/nuxt/ui/commit/e5df0269935be59df759fe0e1378acb2b0d9014a))
* **theme:** define default shades for named tailwindcss colors ([8acf3c5](https://github.com/nuxt/ui/commit/8acf3c51db6c2f9443d04be6ba7d9f062c5cf8ab)), closes [#3977](https://github.com/nuxt/ui/issues/3977)
* **theme:** improve app config types for `ui` object ([591d59f](https://github.com/nuxt/ui/commit/591d59fe89f1d9bf016c121bf9160f73fe0a290d)), closes [#3579](https://github.com/nuxt/ui/issues/3579)
* **theme:** use `[@theme](https://github.com/theme) inline` to properly reference css variables ([6131871](https://github.com/nuxt/ui/commit/6131871a0d124c5942d60dc5dff20981e8542e51)), closes [#4018](https://github.com/nuxt/ui/issues/4018)
* **useOverlay:** improve types and docs ([#4012](https://github.com/nuxt/ui/issues/4012)) ([39e29fc](https://github.com/nuxt/ui/commit/39e29fccf1840c723a13237d65002501b2829b70))
## [3.1.0](https://github.com/nuxt/ui/compare/v3.0.2...v3.1.0) (2025-04-24)
### ⚠ BREAKING CHANGES

View File

@@ -11,7 +11,7 @@ export default defineBuildConfig({
delimiters: ['', ''],
values: {
// Used in development to import directly from theme
'process.argv.includes(\'--uiDev\')': 'false'
'const isUiDev = true': 'const isUiDev = false'
}
}
},

View File

@@ -66,7 +66,7 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.${camelName}
</script>
<template>
<Primitive :as="as" :class="ui.root({ class: [props.ui?.root, props.class] })">
<Primitive :as="as" :class="ui.root({ class: [props.class, props.ui?.root] })">
<slot />
</Primitive>
</template>
@@ -109,7 +109,7 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.${camelName}
</script>
<template>
<${upperName}Root v-bind="rootProps" :class="ui.root({ class: [props.ui?.root, props.class] })" />
<${upperName}Root v-bind="rootProps" :class="ui.root({ class: [props.class, props.ui?.root] })" />
</template>
`
}

View File

@@ -53,7 +53,7 @@ provide('navigation', mappedNavigation)
<NuxtLoadingIndicator color="var(--ui-primary)" :height="2" />
<template v-if="!route.path.startsWith('/examples')">
<!-- <Banner /> -->
<Banner />
<Header :links="links" />
</template>

View File

@@ -20,7 +20,7 @@ watch(framework, () => {
color="neutral"
:ui="{
indicator: 'bg-default',
trigger: 'px-1 data-[state=active]:text-highlighted w-full'
trigger: 'px-1 data-[state=active]:text-highlighted'
}"
size="xs"
@update:model-value="(framework = $event as string)"

View File

@@ -20,7 +20,7 @@ watch(module, () => {
color="neutral"
:ui="{
indicator: 'bg-default',
trigger: 'px-1 data-[state=active]:text-highlighted w-full'
trigger: 'px-1 data-[state=active]:text-highlighted'
}"
size="xs"
@update:model-value="(module = $event as string)"

View File

@@ -38,7 +38,7 @@ const schemaProps = computed(() => {
</script>
<template>
<ProseCollapsible v-if="schemaProps?.length" class="mt-1 mb-0">
<ProseCollapsible v-if="schemaProps?.length" class="mt-1">
<ProseUl>
<ProseLi v-for="schemaProp in schemaProps" :key="schemaProp.name">
<HighlightInlineType :type="`${schemaProp.name}${schemaProp.required === false ? '?' : ''}: ${schemaProp.type}`" />

View File

@@ -25,10 +25,7 @@ function getEmojiFlag(locale: string): string {
kk: 'kz', // Kazakh -> Kazakhstan
km: 'kh', // Khmer -> Cambodia
ko: 'kr', // Korean -> South Korea
ky: 'kg', // Kyrgyz -> Kyrgyzstan
ms: 'my', // Malay -> Malaysia
nb: 'no', // Norwegian Bokmål -> Norway
sl: 'si', // Slovenian -> Slovenia
sv: 'se', // Swedish -> Sweden
uk: 'ua', // Ukrainian -> Ukraine
ur: 'pk', // Urdu -> Pakistan

View File

@@ -17,11 +17,8 @@ function onClickPrev() {
function onClickNext() {
activeIndex.value++
}
function onSelect(index: number) {
activeIndex.value = index
}
function select(index: number) {
function onSelect(index: number) {
activeIndex.value = index
carousel.value?.emblaApi?.scrollTo(index)
@@ -38,7 +35,6 @@ function select(index: number) {
:prev="{ onClick: onClickPrev }"
:next="{ onClick: onClickNext }"
class="w-full max-w-xs mx-auto"
@select="onSelect"
>
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
@@ -49,7 +45,7 @@ function select(index: number) {
:key="index"
class="size-11 opacity-25 hover:opacity-100 transition-opacity"
:class="{ 'opacity-100': activeIndex === index }"
@click="select(index)"
@click="onSelect(index)"
>
<img :src="item" width="44" height="44" class="rounded-lg">
</div>

View File

@@ -1,10 +1,9 @@
<script setup lang="ts">
import { refDebounced } from '@vueuse/core'
const searchTerm = ref('')
const searchTermDebounced = refDebounced(searchTerm, 200)
const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', {
key: 'command-palette-users',
params: { q: searchTermDebounced },
transform: (data: { id: number, name: string, email: string }[]) => {
return data?.map(user => ({ id: user.id, label: user.name, suffix: user.email, avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` } })) || []

View File

@@ -28,7 +28,7 @@ const items = [
</template>
<template #refresh-trailing>
<UIcon v-if="loading" name="i-lucide-loader-circle" class="shrink-0 size-5 text-primary animate-spin" />
<UIcon v-if="loading" name="i-lucide-refresh-cw" class="shrink-0 size-5 text-primary animate-spin" />
</template>
</UContextMenu>
</template>

View File

@@ -3,7 +3,7 @@ const open = ref(false)
</script>
<template>
<UDrawer v-model:open="open" :dismissible="false" :handle="false" :ui="{ header: 'flex items-center justify-between' }">
<UDrawer v-model:open="open" :dismissible="false" :ui="{ header: 'flex items-center justify-between' }">
<UButton label="Open" color="neutral" variant="subtle" trailing-icon="i-lucide-chevron-up" />
<template #header>

View File

@@ -1,28 +0,0 @@
<script setup lang="ts">
const open = ref(false)
</script>
<template>
<UDrawer
v-model:open="open"
:dismissible="false"
:overlay="false"
:handle="false"
:modal="false"
:ui="{ header: 'flex items-center justify-between' }"
>
<UButton label="Open" color="neutral" variant="subtle" trailing-icon="i-lucide-chevron-up" />
<template #header>
<h2 class="text-highlighted font-semibold">
Drawer non-dismissible
</h2>
<UButton color="neutral" variant="ghost" icon="i-lucide-x" @click="open = false" />
</template>
<template #body>
<Placeholder class="h-48" />
</template>
</UDrawer>
</template>

View File

@@ -15,9 +15,6 @@ const schema = z.object({
select: z.string().refine(value => value === 'option-2', {
message: 'Select Option 2'
}),
selectMultiple: z.array(z.string()).refine(values => values.includes('option-2'), {
message: 'Include Option 2'
}),
selectMenu: z.any().refine(option => option?.value === 'option-2', {
message: 'Select Option 2'
}),
@@ -84,10 +81,6 @@ async function onSubmit(event: FormSubmitEvent<Schema>) {
<USelect v-model="state.select" :items="items" class="w-full" />
</UFormField>
<UFormField name="selectMultiple" label="Select (Multiple)">
<USelect v-model="state.selectMultiple" multiple :items="items" class="w-full" />
</UFormField>
<UFormField name="selectMenu" label="Select Menu">
<USelectMenu v-model="state.selectMenu" :items="items" class="w-full" />
</UFormField>

View File

@@ -1,11 +1,11 @@
<script setup lang="ts">
import { refDebounced } from '@vueuse/core'
import type { AvatarProps } from '@nuxt/ui'
const searchTerm = ref('')
const searchTermDebounced = refDebounced(searchTerm, 200)
const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', {
key: 'typicode-users',
params: { q: searchTermDebounced },
transform: (data: { id: number, name: string }[]) => {
return data?.map(user => ({

View File

@@ -10,7 +10,7 @@ const domain = ref(domains[0])
v-model="value"
placeholder="nuxt"
:ui="{
base: 'pl-14.5',
base: 'pl-[57px]',
leading: 'pointer-events-none'
}"
>

View File

@@ -10,8 +10,8 @@ const open = ref(false)
<Placeholder class="h-48" />
</template>
<template #footer="{ close }">
<UButton label="Cancel" color="neutral" variant="outline" @click="close" />
<template #footer>
<UButton label="Cancel" color="neutral" variant="outline" @click="open = false" />
<UButton label="Submit" color="neutral" />
</template>
</UModal>

View File

@@ -13,9 +13,7 @@ const modal = overlay.create(LazyModalExample, {
})
async function open() {
const instance = modal.open()
const shouldIncrement = await instance.result
const shouldIncrement = await modal.open()
if (shouldIncrement) {
count.value++

View File

@@ -65,7 +65,6 @@ const items = [
class="w-full justify-center"
:ui="{
viewport: 'sm:w-(--reka-navigation-menu-viewport-width)',
content: 'sm:w-auto',
childList: 'sm:w-96',
childLinkDescription: 'text-balance line-clamp-2'
}"

View File

@@ -1,19 +0,0 @@
<script lang="ts" setup>
const open = ref(false)
</script>
<template>
<UPopover
v-model:open="open"
:dismissible="false"
:ui="{ content: 'w-(--reka-popper-anchor-width) p-4' }"
>
<template #anchor>
<UInput placeholder="Focus to open" @focus="open = true" @blur="open = false" />
</template>
<template #content>
<Placeholder class="w-full aspect-square" />
</template>
</UPopover>
</template>

View File

@@ -1,11 +1,11 @@
<script setup lang="ts">
import { refDebounced } from '@vueuse/core'
import type { AvatarProps } from '@nuxt/ui'
const searchTerm = ref('')
const searchTermDebounced = refDebounced(searchTerm, 200)
const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', {
key: 'typicode-users',
params: { q: searchTermDebounced },
transform: (data: { id: number, name: string }[]) => {
return data?.map(user => ({

View File

@@ -10,8 +10,8 @@ const open = ref(false)
<Placeholder class="h-full" />
</template>
<template #footer="{ close }">
<UButton label="Cancel" color="neutral" variant="outline" @click="close" />
<template #footer>
<UButton label="Cancel" color="neutral" variant="outline" @click="open = false" />
<UButton label="Submit" color="neutral" />
</template>
</USlideover>

View File

@@ -13,9 +13,7 @@ const slideover = overlay.create(LazySlideoverExample, {
})
async function open() {
const instance = slideover.open()
const shouldIncrement = await instance.result
const shouldIncrement = await slideover.open()
if (shouldIncrement) {
count.value++

View File

@@ -1,203 +0,0 @@
<script setup lang="ts">
import { h, resolveComponent } from 'vue'
import type { TableColumn } from '@nuxt/ui'
import { getGroupedRowModel, type GroupingOptions } from '@tanstack/vue-table'
const UBadge = resolveComponent('UBadge')
type Account = {
id: string
name: string
}
type PaymentStatus = 'paid' | 'failed' | 'refunded'
type Payment = {
id: string
date: string
status: PaymentStatus
email: string
amount: number
account: Account
}
const getColorByStatus = (status: PaymentStatus) => {
return {
paid: 'success',
failed: 'error',
refunded: 'neutral'
}[status]
}
const data = ref<Payment[]>([
{
id: '4600',
date: '2024-03-11T15:30:00',
status: 'paid',
email: 'james.anderson@example.com',
amount: 594,
account: {
id: '1',
name: 'Account 1'
}
},
{
id: '4599',
date: '2024-03-11T10:10:00',
status: 'failed',
email: 'mia.white@example.com',
amount: 276,
account: {
id: '2',
name: 'Account 2'
}
},
{
id: '4598',
date: '2024-03-11T08:50:00',
status: 'refunded',
email: 'william.brown@example.com',
amount: 315,
account: {
id: '1',
name: 'Account 1'
}
},
{
id: '4597',
date: '2024-03-10T19:45:00',
status: 'paid',
email: 'emma.davis@example.com',
amount: 529,
account: {
id: '2',
name: 'Account 2'
}
},
{
id: '4596',
date: '2024-03-10T15:55:00',
status: 'paid',
email: 'ethan.harris@example.com',
amount: 639,
account: {
id: '1',
name: 'Account 1'
}
}
])
const columns: TableColumn<Payment>[] = [
{
id: 'title',
header: 'Item'
},
{
id: 'account_id',
accessorKey: 'account.id'
},
{
accessorKey: 'id',
header: '#',
cell: ({ row }) =>
row.getIsGrouped()
? `${row.getValue('id')} records`
: `#${row.getValue('id')}`,
aggregationFn: 'count'
},
{
accessorKey: 'date',
header: 'Date',
cell: ({ row }) => {
return new Date(row.getValue('date')).toLocaleString('en-US', {
day: 'numeric',
month: 'short',
hour: '2-digit',
minute: '2-digit',
hour12: false
})
},
aggregationFn: 'max'
},
{
accessorKey: 'status',
header: 'Status'
},
{
accessorKey: 'email',
header: 'Email',
meta: {
class: {
td: 'w-full'
}
},
cell: ({ row }) =>
row.getIsGrouped()
? `${row.getValue('email')} customers`
: row.getValue('email'),
aggregationFn: 'uniqueCount'
},
{
accessorKey: 'amount',
header: () => h('div', { class: 'text-right' }, 'Amount'),
cell: ({ row }) => {
const amount = Number.parseFloat(row.getValue('amount'))
const formatted = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'EUR'
}).format(amount)
return h('div', { class: 'text-right font-medium' }, formatted)
},
aggregationFn: 'sum'
}
]
const grouping_options = ref<GroupingOptions>({
groupedColumnMode: 'remove',
getGroupedRowModel: getGroupedRowModel()
})
</script>
<template>
<UTable
:data="data"
:columns="columns"
:grouping="['account_id', 'status']"
:grouping-options="grouping_options"
:ui="{
root: 'min-w-full',
td: 'empty:p-0' // helps with the colspaned row added for expand slot
}"
>
<template #title-cell="{ row }">
<div v-if="row.getIsGrouped()" class="flex items-center">
<span
class="inline-block"
:style="{ width: `calc(${row.depth} * 1rem)` }"
/>
<UButton
variant="outline"
color="neutral"
class="mr-2"
size="xs"
:icon="row.getIsExpanded() ? 'i-lucide-minus' : 'i-lucide-plus'"
@click="row.toggleExpanded()"
/>
<strong v-if="row.groupingColumnId === 'account_id'">{{
row.original.account.name
}}</strong>
<UBadge
v-else-if="row.groupingColumnId === 'status'"
:color="getColorByStatus(row.original.status)"
class="capitalize"
variant="subtle"
>
{{ row.original.status }}
</UBadge>
</div>
</template>
</UTable>
</template>

View File

@@ -26,7 +26,7 @@ const state = reactive({
</script>
<template>
<UTabs :items="items" variant="link" class="gap-4 w-full" :ui="{ trigger: 'grow' }">
<UTabs :items="items" variant="link" class="gap-4 w-full" :ui="{ trigger: 'flex-1' }">
<template #account="{ item }">
<p class="text-muted mb-4">
{{ item.description }}

View File

@@ -1,32 +1,22 @@
<script setup lang="ts">
import type { TabsItem } from '@nuxt/ui'
const route = useRoute()
const router = useRouter()
const items: TabsItem[] = [
{
label: 'Account',
value: 'account'
label: 'Account'
},
{
label: 'Password',
value: 'password'
label: 'Password'
}
]
const active = computed({
get() {
return (route.query.tab as string) || 'account'
},
set(tab) {
// Hash is specified here to prevent the page from scrolling to the top
router.push({
path: '/components/tabs',
query: { tab },
hash: '#control-active-item'
})
}
const active = ref('0')
// Note: This is for demonstration purposes only. Don't do this at home.
onMounted(() => {
setInterval(() => {
active.value = String((Number(active.value) + 1) % items.length)
}, 2000)
})
</script>

View File

@@ -1,34 +0,0 @@
<script setup lang="ts">
import type { TimelineItem } from '@nuxt/ui'
const items: TimelineItem[] = [{
date: 'Mar 15, 2025',
title: 'Project Kickoff',
icon: 'i-lucide-rocket',
value: 'kickoff'
}, {
date: 'Mar 22, 2025',
title: 'Design Phase',
icon: 'i-lucide-palette',
value: 'design'
}, {
date: 'Mar 29, 2025',
title: 'Development Sprint',
icon: 'i-lucide-code',
value: 'development'
}, {
date: 'Apr 5, 2025',
title: 'Testing & Deployment',
icon: 'i-lucide-check-circle',
value: 'deployment'
}]
</script>
<template>
<UTimeline
:items="items"
:ui="{ item: 'even:flex-row-reverse even:-translate-x-[calc(100%-2rem)] even:text-right' }"
:default-value="2"
class="w-full translate-x-[calc(50%-2rem)]"
/>
</template>

View File

@@ -1,52 +0,0 @@
<script setup lang="ts">
import type { TimelineItem } from '@nuxt/ui'
const items = [{
date: 'Mar 15, 2025',
title: 'Project Kickoff',
subtitle: 'Project Initiation',
description: 'Kicked off the project with team alignment. Set up project milestones and allocated resources.',
icon: 'i-lucide-rocket',
value: 'kickoff'
}, {
date: 'Mar 22, 2025',
title: 'Design Phase',
description: 'User research and design workshops. Created wireframes and prototypes for user testing.',
icon: 'i-lucide-palette',
value: 'design'
}, {
date: 'Mar 29, 2025',
title: 'Development Sprint',
description: 'Frontend and backend development. Implemented core features and integrated with APIs.',
icon: 'i-lucide-code',
value: 'development',
slot: 'development' as const,
developers: [
{
src: 'https://github.com/J-Michalek.png'
}, {
src: 'https://github.com/benjamincanac.png'
}
]
}, {
date: 'Apr 5, 2025',
title: 'Testing & Deployment',
description: 'QA testing and performance optimization. Deployed the application to production.',
icon: 'i-lucide-check-circle',
value: 'deployment'
}] satisfies TimelineItem[]
</script>
<template>
<UTimeline :items="items" :default-value="2" class="w-96">
<template #development-title="{ item }">
<div class="flex items-center gap-1">
<span>{{ item.title }}</span>
<UAvatarGroup size="2xs">
<UAvatar v-for="(developer, index) of item.developers" :key="index" v-bind="developer" />
</UAvatarGroup>
</div>
</template>
</UTimeline>
</template>

View File

@@ -1,42 +0,0 @@
<script setup lang="ts">
import type { TimelineItem } from '@nuxt/ui'
const items: TimelineItem[] = [{
date: 'Mar 15, 2025',
title: 'Project Kickoff',
description: 'Kicked off the project with team alignment. Set up project milestones and allocated resources.',
icon: 'i-lucide-rocket',
value: 'kickoff'
}, {
date: 'Mar 22, 2025',
title: 'Design Phase',
description: 'User research and design workshops. Created wireframes and prototypes for user testing.',
icon: 'i-lucide-palette',
value: 'design'
}, {
date: 'Mar 29, 2025',
title: 'Development Sprint',
description: 'Frontend and backend development. Implemented core features and integrated with APIs.',
icon: 'i-lucide-code',
value: 'development'
}, {
date: 'Apr 5, 2025',
title: 'Testing & Deployment',
description: 'QA testing and performance optimization. Deployed the application to production.',
icon: 'i-lucide-check-circle',
value: 'deployment'
}]
const active = ref(0)
// Note: This is for demonstration purposes only. Don't do this at home.
onMounted(() => {
setInterval(() => {
active.value = (active.value + 1) % items.length
}, 2000)
})
</script>
<template>
<UTimeline v-model="active" :items="items" class="w-96" />
</template>

View File

@@ -1,60 +0,0 @@
<script lang="ts" setup>
import type { TimelineItem } from '@nuxt/ui'
import { useTimeAgo } from '@vueuse/core'
const items = [{
username: 'J-Michalek',
date: '2025-05-24T14:58:55Z',
action: 'opened this',
avatar: {
src: 'https://github.com/J-Michalek.png'
}
}, {
username: 'J-Michalek',
date: '2025-05-26T19:30:14+02:00',
action: 'marked this pull request as ready for review',
icon: 'i-lucide-check-circle'
}, {
username: 'benjamincanac',
date: '2025-05-27T11:01:20Z',
action: 'commented on this',
description: 'I\'ve made a few changes, let me know what you think! Basically I updated the design, removed unnecessary divs, used Avatar component for the indicator since it supports icon already.',
avatar: {
src: 'https://github.com/benjamincanac.png'
}
}, {
username: 'J-Michalek',
date: '2025-05-27T11:01:20Z',
action: 'commented on this',
description: 'Looks great! Good job on cleaning it up.',
avatar: {
src: 'https://github.com/J-Michalek.png'
}
}, {
username: 'benjamincanac',
date: '2025-05-27T11:01:20Z',
action: 'merged this',
icon: 'i-lucide-git-merge'
}] satisfies TimelineItem[]
</script>
<template>
<UTimeline
:items="items"
size="xs"
class="w-96"
:ui="{
date: 'float-end ms-1',
description: 'px-3 py-2 ring ring-default mt-2 rounded-md text-default'
}"
>
<template #title="{ item }">
<span>{{ item.username }}</span>
<span class="font-normal text-muted">&nbsp;{{ item.action }}</span>
</template>
<template #date="{ item }">
{{ useTimeAgo(new Date(item.date)) }}
</template>
</UTimeline>
</template>

View File

@@ -98,7 +98,7 @@ export function useLinks() {
label: 'Raycast Extension',
description: 'Access Nuxt UI components without leaving your editor.',
icon: 'i-simple-icons-raycast',
to: 'https://www.raycast.com/HugoRCD/nuxt',
to: 'https://www.raycast.com/HugoRCD/nuxt-ui',
target: '_blank'
}, {
label: 'Figma to Code',

View File

@@ -59,7 +59,7 @@ provide('navigation', mappedNavigation)
<UApp>
<NuxtLoadingIndicator color="#FFF" />
<!-- <Banner /> -->
<Banner />
<Header :links="links" />

View File

@@ -65,17 +65,13 @@ if (!import.meta.prerender) {
})
}
const title = page.value?.navigation?.title ? page.value.navigation.title : page.value?.title
const prefix = page.value?.path.includes('components') || page.value?.path.includes('composables') ? 'Vue ' : ''
const suffix = page.value?.path.includes('components') ? 'Component ' : page.value?.path.includes('composables') ? 'Composable ' : ''
const description = page.value?.description
const type = page.value?.path.includes('components') ? 'Vue Component ' : page.value?.path.includes('composables') ? 'Vue Composable ' : ''
useSeoMeta({
titleTemplate: `${prefix}%s ${suffix}- Nuxt UI ${page.value?.module === 'ui-pro' ? 'Pro' : ''} ${page.value?.framework === 'vue' ? ' for Vue' : ''}`,
title,
ogTitle: `${prefix}${title} ${suffix}- Nuxt UI ${page.value?.module === 'ui-pro' ? 'Pro' : ''} ${page.value?.framework === 'vue' ? ' for Vue' : ''}`,
description,
ogDescription: description
titleTemplate: `%s ${type}- Nuxt UI ${page.value.module === 'ui-pro' ? 'Pro' : ''} ${page.value.framework === 'vue' ? ' for Vue' : ''}`,
title: page.value.navigation?.title ? page.value.navigation.title : page.value.title,
ogTitle: `${page.value.navigation?.title ? page.value.navigation.title : page.value.title} ${type}- Nuxt UI ${page.value.module === 'ui-pro' ? 'Pro' : ''} ${page.value.framework === 'vue' ? ' for Vue' : ''}`,
description: page.value.description,
ogDescription: page.value.description
})
if (route.path.startsWith('/components')) {

View File

@@ -1,20 +1,8 @@
<script setup lang="ts">
const route = useRoute()
const colorMode = useColorMode()
const appConfig = useAppConfig()
const name = route.params.slug?.[0]
if (route.query.theme) {
colorMode.preference = route.query.theme === 'light' ? 'light' : 'dark'
}
if (route.query.neutral) {
appConfig.ui.colors.neutral = route.query.neutral as string
}
if (route.query.primary) {
appConfig.ui.colors.primary = route.query.primary as string
}
const width = computed(() => route.query.width && Number.parseInt(route.query.width as string) > 0 ? `${Number.parseInt(route.query.width as string) - 2}px` : '864px')
</script>

View File

@@ -24,41 +24,32 @@ onMounted(async () => {
const nuxtWordPosition = document.querySelector('#nuxt')?.getBoundingClientRect()
const initialScrollX = window.scrollX
const initialScrollY = window.scrollY
if (figmaWordPosition && nuxtWordPosition) {
const cursor1Sequence = async () => {
await animate('#cursor1', { left: Math.round(Math.random() * window.outerWidth), top: Math.round(Math.random() * window.outerHeight) }, { duration: 0.1 }).finished
await animate('#cursor1', { opacity: 1 }, { duration: 0.3 }).finished
await animate('#cursor1', {
left: Math.round(figmaWordPosition.left + initialScrollX + figmaWordPosition.width / 2),
top: Math.round(figmaWordPosition.top + initialScrollY - figmaWordPosition.height / 4)
}, { duration: 1.5, delay: 0.2, ease: 'easeInOut' }).finished
await animate('#cursor1', { scale: 0.8 }, { duration: 0.1, ease: 'easeOut' }).finished
await animate('#cursor1', { scale: 1 }, { duration: 0.1, ease: 'easeOut' }).finished
await animate('#figma', { color: 'var(--ui-info)' }, { duration: 0.3, ease: 'easeOut' }).finished
await animate('#cursor1', {
left: Math.round(figmaWordPosition.left + initialScrollX + figmaWordPosition.width),
top: Math.round(figmaWordPosition.top + initialScrollY)
}, { duration: 0.6, ease: 'easeInOut' }).finished
}
animate('#cursor1', { left: Math.round(Math.random() * window.outerWidth), top: Math.round(Math.random() * window.outerHeight) }, { duration: 0.1 })
.then(() => animate('#cursor1', { opacity: 1 }, { duration: 0.3 }))
.then(() => {
return animate('#cursor1', {
left: Math.round(figmaWordPosition.left + initialScrollX + figmaWordPosition.width / 2),
top: Math.round(figmaWordPosition.top + initialScrollY - figmaWordPosition.height / 4)
}, { duration: 1.5, delay: 0.2, ease: 'easeInOut' })
})
.then(() => animate('#cursor1', { scale: 0.8 }, { duration: 0.1, ease: 'easeOut' }))
.then(() => animate('#cursor1', { scale: 1 }, { duration: 0.1, ease: 'easeOut' }))
.then(() => animate('#figma', { color: 'var(--ui-info)' }, { duration: 0.3, ease: 'easeOut' }))
.then(() => animate('#cursor1', { left: Math.round(figmaWordPosition.left + initialScrollX + figmaWordPosition.width), top: Math.round(figmaWordPosition.top + initialScrollY) }, { duration: 0.6, ease: 'easeInOut' }))
const cursor2Sequence = async () => {
await animate('#cursor2', { left: Math.round(Math.random() * window.outerWidth), top: Math.round(Math.random() * window.outerHeight) }, { duration: 0.1, delay: 0.6 }).finished
await animate('#cursor2', { opacity: 1 }, { duration: 0.3 }).finished
await animate('#cursor2', {
left: Math.round(nuxtWordPosition.left + initialScrollX + nuxtWordPosition.width / 2),
top: Math.round(nuxtWordPosition.top + initialScrollY - nuxtWordPosition.height / 4)
}, { duration: 1.5, delay: 0.2, ease: 'easeInOut' }).finished
await animate('#cursor2', { scale: 0.8 }, { duration: 0.1, ease: 'easeOut' }).finished
await animate('#cursor2', { scale: 1 }, { duration: 0.1, ease: 'easeOut' }).finished
await animate('#nuxt', { color: 'var(--ui-success)' }, { duration: 0.3, ease: 'easeOut' }).finished
await animate('#cursor2', {
left: Math.round(nuxtWordPosition.left + initialScrollX + nuxtWordPosition.width),
top: Math.round(nuxtWordPosition.top + initialScrollY)
}, { duration: 0.6, ease: 'easeInOut' }).finished
}
await Promise.all([cursor1Sequence(), cursor2Sequence()])
animate('#cursor2', { left: Math.round(Math.random() * window.outerWidth), top: Math.round(Math.random() * window.outerHeight) }, { duration: 0.1, delay: 0.6 })
.then(() => animate('#cursor2', { opacity: 1 }, { duration: 0.3 }))
.then(() => {
return animate('#cursor2', {
left: Math.round(nuxtWordPosition.left + initialScrollX + nuxtWordPosition.width / 2),
top: Math.round(nuxtWordPosition.top + initialScrollY - nuxtWordPosition.height / 4)
}, { duration: 1.5, delay: 0.2, ease: 'easeInOut' })
})
.then(() => animate('#cursor2', { scale: 0.8 }, { duration: 0.1, ease: 'easeOut' }))
.then(() => animate('#cursor2', { scale: 1 }, { duration: 0.1, ease: 'easeOut' }))
.then(() => animate('#nuxt', { color: 'var(--ui-success)' }, { duration: 0.3, ease: 'easeOut' }))
.then(() => animate('#cursor2', { left: Math.round(nuxtWordPosition.left + initialScrollX + nuxtWordPosition.width), top: Math.round(nuxtWordPosition.top + initialScrollY) }, { duration: 0.6, ease: 'easeInOut' }))
}
})
</script>

View File

@@ -239,7 +239,7 @@ useIntersectionObserver(contributorsRef, ([entry]) => {
<li>
<NuxtLink to="https://github.com/nuxt/ui/graphs/contributors" target="_blank" class="min-w-0">
<p class="text-4xl font-semibold text-highlighted truncate">
200+
175+
</p>
<p class="text-muted text-sm truncate">Contributors</p>
</NuxtLink>

View File

@@ -16,32 +16,6 @@ links:
variant: outline
trailingIcon: i-lucide-arrow-right
templates:
- title: 'Portfolio'
description: "A sleek, modern portfolio template to showcase your work, skills, blog posts, speaking engagements, and provide contact information. Which can customized easily from the `content/` directory."
icon: i-lucide-user
thumbnail:
dark: https://assets.hub.nuxt.com/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL3BvcnRmb2xpby10ZW1wbGF0ZS5udXh0LmRldiIsImlhdCI6MTc0NTkzNDczMX0.XDWnQoyVy3XVtKQD6PLQ8RFUwr4yr1QnVwPxRrjCrro.jpg?theme=dark
light: https://assets.hub.nuxt.com/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL3BvcnRmb2xpby10ZW1wbGF0ZS5udXh0LmRldiIsImlhdCI6MTc0NTkzNDczMX0.XDWnQoyVy3XVtKQD6PLQ8RFUwr4yr1QnVwPxRrjCrro.jpg?theme=light
features:
- title: Sections for Projects, Blog, Speaking & About
icon: i-lucide-layout-list
- title: Easily editable content via Markdown & YAML
icon: i-simple-icons-markdown
- title: Fully responsive design
icon: i-lucide-smartphone
links:
- label: Preview
to: https://portfolio-template.nuxt.dev
target: _blank
leadingIcon: i-logos-nuxt-icon
trailingIcon: i-lucide-arrow-up-right
color: neutral
- label: Nuxt Template
to: https://github.com/nuxt-ui-pro/portfolio
target: _blank
icon: i-simple-icons-github
color: neutral
variant: outline
- title: 'Chat'
description: "An AI chatbot template designed to help you build your own chatbot with Nuxt UI Pro components and deployed on [NuxtHub](https://hub.nuxt.com)."
icon: i-lucide-message-circle

View File

@@ -67,6 +67,17 @@ defineOgImageComponent('Docs', {
</li>
</ul>
</div>
<div class="flex justify-center -mb-[36px]">
<UButton
label="Submit your project"
trailing-icon="i-lucide-plus"
color="neutral"
size="lg"
to="https://github.com/nuxt/ui/edit/v3/docs/content/showcase.yml"
target="_blank"
/>
</div>
</UPageHero>
</UMain>
</template>

View File

@@ -48,14 +48,13 @@ const icons = {
</UPageHero>
<UPageSection :ui="{ container: '!pt-0' }">
<UPageGrid class="xl:grid-cols-5">
<UPageGrid class="xl:grid-cols-4">
<UPageCard
v-for="(user, index) in module?.team"
:key="index"
:title="user.name"
:description="[user.pronouns, user.location].filter(Boolean).join(' ・ ')"
:ui="{
wrapper: 'items-center',
container: 'gap-y-4 lg:p-8',
leading: 'flex justify-center',
title: 'text-center',
@@ -124,7 +123,6 @@ const icons = {
:key="contributor.username"
:title="contributor.username"
:ui="{
wrapper: 'items-center',
container: 'gap-y-2',
leading: 'flex justify-center',
title: 'text-center',

View File

@@ -504,7 +504,7 @@ const count = ref(0)
</script>
```
Closing a modal is now done through the `close` event. The `modal.open` method now returns an instance that can be used to await for the result of the modal whenever the modal is closed:
Closing a modal is now done through the `close` event. The `modal.open` method now returns a promise that resolves to the result of the modal whenever the modal is close:
```diff
<script setup lang="ts">
@@ -523,12 +523,10 @@ import { ModalExampleComponent } from '#components'
- })
- }
+ async function openModal() {
+ const instance = modal.open(ModalExampleComponent, {
+ const result = await modal.open(ModalExampleComponent, {
+ count: count.value
+ })
+
+ const result = await instance.result
+
+ if (result) {
+ toast.add({ title: 'Success!' })
+ }

View File

@@ -229,10 +229,6 @@ export default defineConfig({
::
::caution
When configuring your theme colors, you must use either color names from the [default Tailwind palette](https://tailwindcss.com/docs/colors) (like 'blue', 'green', etc.) or reference custom colors that you've previously defined in your [CSS file](#theme).
::
### Extend colors
::framework-only
@@ -731,22 +727,15 @@ This is how the `@theme` is generated for each design token:
--border-color-muted: var(--ui-border-muted);
--border-color-accented: var(--ui-border-accented);
--border-color-inverted: var(--ui-border-inverted);
--border-color-bg: var(--ui-bg);
--ring-color-default: var(--ui-border);
--ring-color-muted: var(--ui-border-muted);
--ring-color-accented: var(--ui-border-accented);
--ring-color-inverted: var(--ui-border-inverted);
--ring-color-bg: var(--ui-bg);
--ring-offset-color-default: var(--ui-border);
--ring-offset-color-muted: var(--ui-border-muted);
--ring-offset-color-accented: var(--ui-border-accented);
--ring-offset-color-inverted: var(--ui-border-inverted);
--ring-offset-color-bg: var(--ui-bg);
--divide-color-default: var(--ui-border);
--divide-color-muted: var(--ui-border-muted);
--divide-color-accented: var(--ui-border-accented);
--divide-color-inverted: var(--ui-border-inverted);
--divide-color-bg: var(--ui-bg);
--outline-color-default: var(--ui-border);
--outline-color-inverted: var(--ui-border-inverted);
--stroke-color-default: var(--ui-border);
@@ -977,7 +966,7 @@ export default {
```vue [src/runtime/components/Card.vue]
<template>
<div :class="ui.root({ class: [props.ui?.root, props.class] })">
<div :class="ui.root({ class: [props.class, props.ui?.root] })">
<div :class="ui.header({ class: props.ui?.header })">
<slot name="header" />
</div>

View File

@@ -16,7 +16,7 @@ Here's an overview of the key directories and files in the Nuxt UI project struc
### Documentation
The documentation lives in the `docs` folder as a Nuxt app using `@nuxt/content` v3 to generate pages from Markdown files. See the [Nuxt Content documentation](https://content.nuxt.com/docs/getting-started) for details on how it works. Here's a breakdown of its structure:
The documentation lives in the `docs` folder as a Nuxt app using `@nuxt/content` v3 to generate pages from Markdown files. See the [Content v3 Docs](https://content3.nuxt.dev/docs/getting-started) for details on how it works. Here's a breakdown of its structure:
```bash
├── app/
@@ -225,7 +225,7 @@ pnpm run test:vue # for Vue
```
::tip
If you have to update the snapshots, press `u` after the tests have finished running.
If you have to update the snapshots, press `u` when running the tests.
::
### Commit Conventions

View File

@@ -19,7 +19,6 @@ defineShortcuts({
</script>
```
- Shortcuts are automatically adjusted for non-macOS platforms, converting `meta` to `ctrl`.
- The composable uses VueUse's [`useEventListener`](https://vueuse.org/core/useEventListener/) to handle keydown events.
- For a complete list of available shortcut keys, refer to the [`KeyboardEvent.key`](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values) API documentation. Note that the key should be written in lowercase.
@@ -47,7 +46,7 @@ Shortcuts are defined using the following format:
#### Modifiers
- `meta`: Represents `⌘ Command` on macOS and `Ctrl` on other platforms
- `meta`: Represents `⌘ Command` on macOS and `⊞ Windows` on Windows
- `ctrl`: Represents `Ctrl` on all platforms
- `shift`: Used for alphabetic keys when Shift is required

View File

@@ -22,14 +22,14 @@ async function openModal() {
- The `useOverlay` composable is created using `createSharedComposable`, ensuring that the same overlay state is shared across your entire application.
::note
In order to return a value from the overlay, the `overlay.open().instance.result` can be awaited. In order for this to work, however, the **overlay component must emit a `close` event**. See example below for details.
In order to return a value from the overlay, the `overlay.open()` can be awaited. In order for this to work, however, the **overlay component must emit a `close` event**. See example below for details.
::
## API
### `create(component: T, options: OverlayOptions): OverlayInstance`
Creates an overlay, and returns a factory instance
Creates an overlay, and returns its instance
- Parameters:
- `component`: The overlay component
@@ -38,7 +38,7 @@ Creates an overlay, and returns a factory instance
- `props?: ComponentProps`: An optional object of props to pass to the rendered component.
- `destroyOnClose?: boolean` Removes the overlay from memory when closed `default: false`
### `open(id: symbol, props?: ComponentProps<T>): OpenedOverlay<T>`
### `open(id: symbol, props?: ComponentProps<T>): Promise<any>`
Opens the overlay using its `id`
@@ -66,13 +66,6 @@ Update an overlay using its `id`
Removes the overlay from the DOM using its `id`
- Parameters:
- `id`: The identifier of the overlay
### `isOpen(id: symbol): boolean`
Checks if an overlay its open using its `id`
- Parameters:
- `id`: The identifier of the overlay
@@ -82,7 +75,7 @@ In-memory list of overlays that were created
## Overlay Instance API
### `open(props?: ComponentProps<T>): Promise<OpenedOverlay<T>>`
### `open(props?: ComponentProps<T>): Promise<any>`
Opens the overlay
@@ -145,7 +138,7 @@ const overlay = useOverlay()
// Create with default props
const modalA = overlay.create(ModalA, { title: 'Welcome' })
const modalB = overlay.create(ModalB)
const modalB = overlay.create(modalB)
const slideoverA = overlay.create(SlideoverA)
@@ -156,9 +149,7 @@ const openModalA = () => {
const openModalB = async () => {
// Open modalB, and wait for its result
const modalBInstance = modalB.open()
const input = await modalBInstance.result
const input = await modalB.open()
// Pass the result from modalB to the slideover, and open it.
slideoverA.open({ input })

View File

@@ -23,8 +23,6 @@ Use the `items` prop as an array of objects with the following properties:
- `value?: string`{lang="ts-type"}
- `disabled?: boolean`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, header?: ClassNameValue, trigger?: ClassNameValue, leadingIcon?: ClassNameValue, label?: ClassNameValue, trailingIcon?: ClassNameValue, content?: ClassNameValue, body?: ClassNameValue }`{lang="ts-type"}
::component-code
---

View File

@@ -16,9 +16,8 @@ Use the `items` prop as an array of objects with the following properties:
- `label?: string`{lang="ts-type"}
- `icon?: string`{lang="ts-type"}
- `avatar?: AvatarProps`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, link?: ClassNameValue, linkLeadingIcon?: ClassNameValue, linkLeadingAvatar?: ClassNameValue, linkLabel?: ClassNameValue, separator?: ClassNameValue, separatorIcon?: ClassNameValue }`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.

View File

@@ -258,13 +258,13 @@ This also works with the [Form](/components/form) component.
### Loading Icon
Use the `loading-icon` prop to customize the loading icon. Defaults to `i-lucide-loader-circle`.
Use the `loading-icon` prop to customize the loading icon. Defaults to `i-lucide-refresh-cw`.
::component-code
---
props:
loading: true
loadingIcon: 'i-lucide-loader'
loadingIcon: 'i-lucide-repeat-2'
slots:
default: Button
---

View File

@@ -27,11 +27,6 @@ class: 'p-8'
---
::
You can also pass an array of objects with the following properties:
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue }`{lang="ts-type"}
You can control how many items are visible by using the [`basis`](https://tailwindcss.com/docs/flex-basis) / [`width`](https://tailwindcss.com/docs/width) utility classes on the `item`:
::component-example

View File

@@ -49,8 +49,6 @@ You can also pass an array of objects with the following properties:
- `description?: string`{lang="ts-type"}
- [`value?: string`{lang="ts-type"}](#value-key)
- `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, container?: ClassNameValue, base?: ClassNameValue, 'indicator'?: ClassNameValue, icon?: ClassNameValue, wrapper?: ClassNameValue, label?: ClassNameValue, description?: ClassNameValue }`{lang="ts-type"}
::component-code
---
@@ -201,7 +199,6 @@ items:
variant:
- list
- card
- table
props:
color: 'primary'
variant: 'card'
@@ -232,7 +229,6 @@ items:
variant:
- list
- card
- table
props:
size: 'xl'
variant: 'list'
@@ -263,7 +259,6 @@ items:
variant:
- list
- card
- table
props:
orientation: 'horizontal'
variant: 'list'
@@ -298,7 +293,6 @@ items:
variant:
- list
- card
- table
props:
indicator: 'end'
variant: 'card'

View File

@@ -7,9 +7,9 @@ links:
icon: i-custom-fuse-js
to: https://fusejs.io/
target: _blank
- label: Listbox
- label: Combobox
icon: i-custom-reka-ui
to: https://reka-ui.com/docs/components/listbox
to: https://reka-ui.com/docs/components/combobox
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/CommandPalette.vue
@@ -53,8 +53,6 @@ Each group contains an `items` array of objects that define the commands. Each i
- `disabled?: boolean`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `onSelect?(e?: Event): void`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLeadingChipSize?: ClassNameValue, itemLeadingChip?: ClassNameValue, itemLabel?: ClassNameValue, itemLabelPrefix?: ClassNameValue, itemLabelBase?: ClassNameValue, itemLabelSuffix?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingKbds?: ClassNameValue, itemTrailingKbdsSize?: ClassNameValue, itemTrailingHighlightedIcon?: ClassNameValue, itemTrailingIcon?: ClassNameValue,}`{lang="ts-type"}
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
@@ -279,7 +277,7 @@ props:
### Loading Icon
Use the `loading-icon` prop to customize the loading icon. Defaults to `i-lucide-loader-circle`.
Use the `loading-icon` prop to customize the loading icon. Defaults to `i-lucide-refresh-cw`.
::component-code
---
@@ -295,7 +293,7 @@ class: '!p-0'
props:
autofocus: false
loading: true
loadingIcon: 'i-lucide-loader'
loadingIcon: 'i-lucide-repeat-2'
groups:
- id: 'apps'
items:

View File

@@ -28,12 +28,11 @@ Use the `items` prop as an array of objects with the following properties:
- [`color?: "error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"`{lang="ts-type"}](#with-color-items)
- [`checked?: boolean`{lang="ts-type"}](#with-checkbox-items)
- `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `onSelect?(e: Event): void`{lang="ts-type"}
- [`onUpdateChecked?(checked: boolean): void`{lang="ts-type"}](#with-checkbox-items)
- `children?: ContextMenuItem[] | ContextMenuItem[][]`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, label?: ClassNameValue, separator?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLabel?: ClassNameValue, itemLabelExternalIcon?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue, itemTrailingKbds?: ClassNameValue, itemTrailingKbdsSize?: ClassNameValue }`{lang="ts-type"}
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.

View File

@@ -291,7 +291,7 @@ In this example, leveraging [`defineShortcuts`](/composables/define-shortcuts),
This allows you to move the trigger outside of the Drawer or remove it entirely.
::
### Disable dismissal
### Prevent closing
Set the `dismissible` prop to `false` to prevent the Drawer from being closed when clicking outside of it or pressing escape.
@@ -306,17 +306,6 @@ name: 'drawer-dismissible-example'
In this example, the `header` slot is used to add a close button which is not done by default.
::
### With interactive background
Set the `overlay` and `modal` props to `false` alongside the `dismissible` prop to make the Drawer's background interactive without closing the Drawer.
::component-example
---
prettier: true
name: 'drawer-modal-example'
---
::
### Responsive drawer
You can render a [Modal](/components/modal) component on desktop and a Drawer on mobile for example.

View File

@@ -28,12 +28,11 @@ Use the `items` prop as an array of objects with the following properties:
- [`color?: "error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"`{lang="ts-type"}](#with-color-items)
- [`checked?: boolean`{lang="ts-type"}](#with-checkbox-items)
- `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `onSelect?(e: Event): void`{lang="ts-type"}
- [`onUpdateChecked?(checked: boolean): void`{lang="ts-type"}](#with-checkbox-items)
- `children?: DropdownMenuItem[] | DropdownMenuItem[][]`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, label?: ClassNameValue, separator?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLabel?: ClassNameValue, itemLabelExternalIcon?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue, itemTrailingKbds?: ClassNameValue, itemTrailingKbdsSize?: ClassNameValue }`{lang="ts-type"}
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.

View File

@@ -34,7 +34,7 @@ slots:
The label `for` attribute and the form control are associated with a unique `id` if not provided.
::
When using the `required` prop, an asterisk is added next to the label.
When using the `required` prop, an asterisk is be added next to the label.
::component-code
---

View File

@@ -24,7 +24,7 @@ It requires two props:
**No validation library is included** by default, ensure you **install the one you need**.
::
::tabs{class="gap-0"}
::tabs
::component-example{label="Valibot"}
---
name: 'form-example-valibot'

View File

@@ -55,8 +55,6 @@ You can also pass an array of objects with the following properties:
- [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items)
- `disabled?: boolean`{lang="ts-type"}
- `onSelect?(e: Event): void`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { tagsItem?: ClassNameValue, tagsItemText?: ClassNameValue, tagsItemDelete?: ClassNameValue, tagsItemDeleteIcon?: ClassNameValue, label?: ClassNameValue, separator?: ClassNameValue, item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLeadingChip?: ClassNameValue, itemLeadingChipSize?: ClassNameValue, itemLabel?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue }`{lang="ts-type"}
::component-code
---
@@ -518,7 +516,7 @@ props:
### Loading Icon
Use the `loading-icon` prop to customize the loading icon. Defaults to `i-lucide-loader-circle`.
Use the `loading-icon` prop to customize the loading icon. Defaults to `i-lucide-refresh-cw`.
::component-code
---
@@ -532,7 +530,7 @@ external:
props:
modelValue: 'Backlog'
loading: true
loadingIcon: 'i-lucide-loader'
loadingIcon: 'i-lucide-repeat-2'
items:
- Backlog
- Todo
@@ -612,7 +610,7 @@ props:
---
::
### With icon in items
### With icons in items
You can use the `icon` property to display an [Icon](/components/icon) inside the items.

View File

@@ -3,9 +3,9 @@ title: InputNumber
description: Input numerical values with a customizable range.
category: form
links:
- label: NumberField
- label: Number Field
icon: i-custom-reka-ui
to: https://www.reka-ui.com/docs/components/number-field
to: https://www.reka-ui.com/components/input-number
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/InputNumber.vue

View File

@@ -172,7 +172,7 @@ props:
### Loading Icon
Use the `loading-icon` prop to customize the loading icon. Defaults to `i-lucide-loader-circle`.
Use the `loading-icon` prop to customize the loading icon. Defaults to `i-lucide-refresh-cw`.
::component-code
---
@@ -180,7 +180,7 @@ ignore:
- placeholder
props:
loading: true
loadingIcon: 'i-lucide-loader'
loadingIcon: 'i-lucide-repeat-2'
placeholder: 'Search...'
---
::

View File

@@ -1,11 +1,13 @@
---
title: Kbd
title: Keyboard Key
description: A kbd element to display a keyboard key.
category: element
links:
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/Kbd.vue
navigation:
title: Kbd
---
## Usage
@@ -30,7 +32,7 @@ props:
---
::
You can pass special keys to the `value` prop that goes through the [`useKbd`](https://github.com/nuxt/ui/blob/v3/src/runtime/composables/useKbd.ts) composable. For example, the `meta` key displays as `⌘` on macOS and `Ctrl` on other platforms.
You can pass special keys to the `value` prop that goes through the [`useKbd`](https://github.com/nuxt/ui/blob/v3/src/runtime/composables/useKbd.ts) composable. For example, the `meta` key displays as `⌘` on macOS and `` on other platforms.
::component-code
---

View File

@@ -274,7 +274,7 @@ In this example, leveraging [`defineShortcuts`](/composables/define-shortcuts),
This allows you to move the trigger outside of the Modal or remove it entirely.
::
### Disable dismissal
### Prevent closing
Set the `dismissible` prop to `false` to prevent the Modal from being closed when clicking outside of it or pressing escape. A `close:prevent` event will be emitted when the user tries to close it.
@@ -305,13 +305,13 @@ slots:
### Programmatic usage
You can use the [`useOverlay`](/composables/use-overlay) composable to open a Modal programmatically.
You can use the [`useOverlay`](/composables/use-overlay) composable to open a Modal programatically.
::warning
Make sure to wrap your app with the [`App`](/components/app) component which uses the [`OverlayProvider`](https://github.com/nuxt/ui/blob/v3/src/runtime/components/OverlayProvider.vue) component.
::
First, create a modal component that will be opened programmatically:
First, create a modal component that will be opened programatically:
::component-example
---

View File

@@ -21,18 +21,14 @@ Use the `items` prop as an array of objects with the following properties:
- `icon?: string`{lang="ts-type"}
- `avatar?: AvatarProps`{lang="ts-type"}
- `badge?: string | number | BadgeProps`{lang="ts-type"}
- `tooltip?: TooltipProps`{lang="ts-type"}
- `trailingIcon?: string`{lang="ts-type"}
- `type?: 'label' | 'trigger' | 'link'`{lang="ts-type"}
- `defaultOpen?: boolean`{lang="ts-type"}
- `open?: boolean`{lang="ts-type"}
- `type?: 'label' | 'link'`{lang="ts-type"}
- `value?: string`{lang="ts-type"}
- `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `onSelect?(e: Event): void`{lang="ts-type"}
- `children?: NavigationMenuChildItem[]`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { linkLeadingAvatarSize?: ClassNameValue, linkLeadingAvatar?: ClassNameValue, linkLeadingIcon?: ClassNameValue, linkLabel?: ClassNameValue, linkLabelExternalIcon?: ClassNameValue, linkTrailing?: ClassNameValue, linkTrailingBadgeSize?: ClassNameValue, linkTrailingBadge?: ClassNameValue, linkTrailingIcon?: ClassNameValue, label?: ClassNameValue, link?: ClassNameValue, content?: ClassNameValue, childList?: ClassNameValue, childLabel?: ClassNameValue, childItem?: ClassNameValue, childLink?: ClassNameValue, childLinkIcon?: ClassNameValue, childLinkWrapper?: ClassNameValue, childLinkLabel?: ClassNameValue, childLinkLabelExternalIcon?: ClassNameValue, childLinkDescription?: ClassNameValue }`{lang="ts-type"}
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
@@ -134,8 +130,8 @@ Each item can take a `children` array of objects with the following properties t
- `label: string`
- `description?: string`
- `icon?: string`
- `onSelect?(e: Event): void`
- `class?: any`
- `onSelect?(e: Event): void`
::
@@ -144,7 +140,7 @@ Each item can take a `children` array of objects with the following properties t
Use the `orientation` prop to change the orientation of the NavigationMenu.
::note
When orientation is `vertical`, an [Accordion](/components/accordion) component is used to display each group. You can control the open state of each item using the `open` and `defaultOpen` properties and change the behavior using the [`collapsible`](/components/accordion#collapsible) and [`type`](/components/accordion#multiple) props.
When orientation is `vertical`, a [Collapsible](/components/collapsible) component is used to display children. You can control the open state of each item using the `open` and `defaultOpen` properties.
::
::component-code
@@ -241,113 +237,6 @@ props:
Groups will be spaced when orientation is `horizontal` and separated when orientation is `vertical`.
::
### Collapsed
In `vertical` orientation, use the `collapsed` prop to collapse the NavigationMenu, this can be useful in a sidebar for example.
::note
You can use the [`tooltip`](#with-tooltip-in-items) and [`popover`](#with-popover-in-items) props to display more information on the collapsed items.
::
::component-code
---
collapse: true
ignore:
- items
- orientation
- class
external:
- items
externalTypes:
- NavigationMenuItem[][]
items:
tooltip:
- true
- false
popover:
- true
- false
props:
collapsed: true
tooltip: false
popover: false
orientation: 'vertical'
items:
- - label: Links
type: 'label'
- label: Guide
icon: i-lucide-book-open
children:
- label: Introduction
description: Fully styled and customizable components for Nuxt.
icon: i-lucide-house
- label: Installation
description: Learn how to install and configure Nuxt UI in your application.
icon: i-lucide-cloud-download
- label: 'Icons'
icon: 'i-lucide-smile'
description: 'You have nothing to do, @nuxt/icon will handle it automatically.'
- label: 'Colors'
icon: 'i-lucide-swatch-book'
description: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
- label: 'Theme'
icon: 'i-lucide-cog'
description: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
- label: Composables
icon: i-lucide-database
children:
- label: defineShortcuts
icon: i-lucide-file-text
description: Define shortcuts for your application.
to: /composables/define-shortcuts
- label: useOverlay
icon: i-lucide-file-text
description: Display a modal/slideover within your application.
to: /composables/use-overlay
- label: useToast
icon: i-lucide-file-text
description: Display a toast within your application.
to: /composables/use-toast
- label: Components
icon: i-lucide-box
to: /components
active: true
children:
- label: Link
icon: i-lucide-file-text
description: Use NuxtLink with superpowers.
to: /components/link
- label: Modal
icon: i-lucide-file-text
description: Display a modal within your application.
to: /components/modal
- label: NavigationMenu
icon: i-lucide-file-text
description: Display a list of links.
to: /components/navigation-menu
- label: Pagination
icon: i-lucide-file-text
description: Display a list of pages.
to: /components/pagination
- label: Popover
icon: i-lucide-file-text
description: Display a non-modal dialog that floats around a trigger element.
to: /components/popover
- label: Progress
icon: i-lucide-file-text
description: Show a horizontal bar to indicate task progression.
to: /components/progress
- - label: GitHub
icon: i-simple-icons-github
badge: 3.8k
to: https://github.com/nuxt/ui
target: _blank
- label: Help
icon: i-lucide-circle-help
disabled: true
---
::
### Highlight
Use the `highlight` prop to display a highlighted border for the active item.
@@ -889,222 +778,6 @@ You can inspect the DOM to see each item's content being rendered.
## Examples
### With tooltip in items :badge{label="New" class="align-text-top"}
When orientation is `vertical` and the menu is `collapsed`, you can set the `tooltip` prop to `true` to display a [Tooltip](/components/tooltip) around items with their label but you can also use the `tooltip` property on each item to override the default tooltip.
You can pass any property from the [Tooltip](/components/tooltip) component globally or on each item.
::component-code
---
collapse: true
ignore:
- items
- orientation
- class
external:
- items
externalTypes:
- NavigationMenuItem[][]
items:
tooltip:
- true
- false
props:
tooltip: true
collapsed: true
orientation: 'vertical'
items:
- - label: Links
type: 'label'
- label: Guide
icon: i-lucide-book-open
children:
- label: Introduction
description: Fully styled and customizable components for Nuxt.
icon: i-lucide-house
- label: Installation
description: Learn how to install and configure Nuxt UI in your application.
icon: i-lucide-cloud-download
- label: 'Icons'
icon: 'i-lucide-smile'
description: 'You have nothing to do, @nuxt/icon will handle it automatically.'
- label: 'Colors'
icon: 'i-lucide-swatch-book'
description: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
- label: 'Theme'
icon: 'i-lucide-cog'
description: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
- label: Composables
icon: i-lucide-database
children:
- label: defineShortcuts
icon: i-lucide-file-text
description: Define shortcuts for your application.
to: /composables/define-shortcuts
- label: useOverlay
icon: i-lucide-file-text
description: Display a modal/slideover within your application.
to: /composables/use-overlay
- label: useToast
icon: i-lucide-file-text
description: Display a toast within your application.
to: /composables/use-toast
- label: Components
icon: i-lucide-box
to: /components
active: true
children:
- label: Link
icon: i-lucide-file-text
description: Use NuxtLink with superpowers.
to: /components/link
- label: Modal
icon: i-lucide-file-text
description: Display a modal within your application.
to: /components/modal
- label: NavigationMenu
icon: i-lucide-file-text
description: Display a list of links.
to: /components/navigation-menu
- label: Pagination
icon: i-lucide-file-text
description: Display a list of pages.
to: /components/pagination
- label: Popover
icon: i-lucide-file-text
description: Display a non-modal dialog that floats around a trigger element.
to: /components/popover
- label: Progress
icon: i-lucide-file-text
description: Show a horizontal bar to indicate task progression.
to: /components/progress
- - label: GitHub
icon: i-simple-icons-github
badge: 3.8k
to: https://github.com/nuxt/ui
target: _blank
tooltip:
text: 'Open on GitHub'
kbds:
- 3.8k
- label: Help
icon: i-lucide-circle-help
disabled: true
---
::
### With popover in items :badge{label="New" class="align-text-top"}
When orientation is `vertical` and the menu is `collapsed`, you can set the `popover` prop to `true` to display a [Popover](/components/popover) around items with their children but you can also use the `popover` property on each item to override the default popover.
You can pass any property from the [Popover](/components/popover) component globally or on each item.
::component-code
---
collapse: true
ignore:
- items
- orientation
- class
external:
- items
externalTypes:
- NavigationMenuItem[][]
items:
popover:
- true
- false
props:
popover: true
collapsed: true
orientation: 'vertical'
items:
- - label: Links
type: 'label'
- label: Guide
icon: i-lucide-book-open
children:
- label: Introduction
description: Fully styled and customizable components for Nuxt.
icon: i-lucide-house
- label: Installation
description: Learn how to install and configure Nuxt UI in your application.
icon: i-lucide-cloud-download
- label: 'Icons'
icon: 'i-lucide-smile'
description: 'You have nothing to do, @nuxt/icon will handle it automatically.'
- label: 'Colors'
icon: 'i-lucide-swatch-book'
description: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
- label: 'Theme'
icon: 'i-lucide-cog'
description: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
- label: Composables
icon: i-lucide-database
popover:
mode: 'click'
children:
- label: defineShortcuts
icon: i-lucide-file-text
description: Define shortcuts for your application.
to: /composables/define-shortcuts
- label: useOverlay
icon: i-lucide-file-text
description: Display a modal/slideover within your application.
to: /composables/use-overlay
- label: useToast
icon: i-lucide-file-text
description: Display a toast within your application.
to: /composables/use-toast
- label: Components
icon: i-lucide-box
to: /components
active: true
children:
- label: Link
icon: i-lucide-file-text
description: Use NuxtLink with superpowers.
to: /components/link
- label: Modal
icon: i-lucide-file-text
description: Display a modal within your application.
to: /components/modal
- label: NavigationMenu
icon: i-lucide-file-text
description: Display a list of links.
to: /components/navigation-menu
- label: Pagination
icon: i-lucide-file-text
description: Display a list of pages.
to: /components/pagination
- label: Popover
icon: i-lucide-file-text
description: Display a non-modal dialog that floats around a trigger element.
to: /components/popover
- label: Progress
icon: i-lucide-file-text
description: Show a horizontal bar to indicate task progression.
to: /components/progress
- - label: GitHub
icon: i-simple-icons-github
badge: 3.8k
to: https://github.com/nuxt/ui
target: _blank
tooltip:
text: 'Open on GitHub'
kbds:
- 3.8k
- label: Help
icon: i-lucide-circle-help
disabled: true
---
::
::tip{to="#with-content-slot"}
You can use the `#content` slot to customize the content of the popover in the `vertical` orientation.
::
### Control active item
You can control the active item by using the `default-value` prop or the `v-model` directive with the index of the item.
@@ -1152,7 +825,6 @@ Use the `#item-content` slot or the `slot` property (`#{{ item.slot }}-content`)
::component-example
---
collapse: true
name: 'navigation-menu-content-slot-example'
---
::

View File

@@ -3,9 +3,6 @@ title: PinInput
description: An input element to enter a pin.
category: form
links:
- label: PinInput
icon: i-custom-reka-ui
to: https://reka-ui.com/docs/components/pin-input
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/PinInput.vue

View File

@@ -181,7 +181,7 @@ name: 'popover-open-example'
In this example, leveraging [`defineShortcuts`](/composables/define-shortcuts), you can toggle the Popover by pressing :kbd{value="O"}.
::
### Disable dismissal
### Prevent closing
Set the `dismissible` prop to `false` to prevent the Popover from being closed when clicking outside of it or pressing escape. A `close:prevent` event will be emitted when the user tries to close it.
@@ -202,21 +202,6 @@ name: 'popover-command-palette-example'
---
::
### With anchor slot :badge{label="New" class="align-text-top"}
You can use the `#anchor` slot to position the Popover against a custom element.
::warning
This slot only works when `mode` is `click`.
::
::component-example
---
collapse: true
name: 'popover-anchor-slot-example'
---
::
## API
### Props

View File

@@ -46,8 +46,6 @@ You can also pass an array of objects with the following properties:
- `description?: string`{lang="ts-type"}
- [`value?: string`{lang="ts-type"}](#value-key)
- `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, container?: ClassNameValue, base?: ClassNameValue, 'indicator'?: ClassNameValue, wrapper?: ClassNameValue, label?: ClassNameValue, description?: ClassNameValue }`{lang="ts-type"}
::component-code
---

View File

@@ -57,8 +57,6 @@ You can also pass an array of objects with the following properties:
- [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items)
- `disabled?: boolean`{lang="ts-type"}
- `onSelect?(e: Event): void`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { label?: ClassNameValue, separator?: ClassNameValue, item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLeadingChipSize?: ClassNameValue, itemLeadingChip?: ClassNameValue, itemLabel?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue }`{lang="ts-type"}
::component-code
---
@@ -555,7 +553,7 @@ props:
### Loading Icon
Use the `loading-icon` prop to customize the loading icon. Defaults to `i-lucide-loader-circle`.
Use the `loading-icon` prop to customize the loading icon. Defaults to `i-lucide-refresh-cw`.
::component-code
---
@@ -570,7 +568,7 @@ external:
props:
modelValue: 'Backlog'
loading: true
loadingIcon: 'i-lucide-loader'
loadingIcon: 'i-lucide-repeat-2'
items:
- Backlog
- Todo
@@ -655,7 +653,7 @@ props:
---
::
### With icon in items
### With icons in items
You can use the `icon` property to display an [Icon](/components/icon) inside the items.

View File

@@ -48,8 +48,6 @@ You can also pass an array of objects with the following properties:
- [`avatar?: AvatarProps`{lang="ts-type"}](#with-avatar-in-items)
- [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items)
- `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { label?: ClassNameValue, separator?: ClassNameValue, item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLeadingChipSize?: ClassNameValue, itemLeadingChip?: ClassNameValue, itemLabel?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue }`{lang="ts-type"}
::component-code
---
@@ -507,7 +505,7 @@ props:
### Loading Icon
Use the `loading-icon` prop to customize the loading icon. Defaults to `i-lucide-loader-circle`.
Use the `loading-icon` prop to customize the loading icon. Defaults to `i-lucide-refresh-cw`.
::component-code
---
@@ -522,7 +520,7 @@ external:
props:
modelValue: 'Backlog'
loading: true
loadingIcon: 'i-lucide-loader'
loadingIcon: 'i-lucide-repeat-2'
items:
- Backlog
- Todo
@@ -607,7 +605,7 @@ props:
---
::
### With icon in items
### With icons in items
You can use the `icon` property to display an [Icon](/components/icon) inside the items.

View File

@@ -273,7 +273,7 @@ In this example, leveraging [`defineShortcuts`](/composables/define-shortcuts),
This allows you to move the trigger outside of the Slideover or remove it entirely.
::
### Disable dismissal
### Prevent closing
Set the `dismissible` prop to `false` to prevent the Slideover from being closed when clicking outside of it or pressing escape. A `close:prevent` event will be emitted when the user tries to close it.
@@ -304,13 +304,13 @@ slots:
### Programmatic usage
You can use the [`useOverlay`](/composables/use-overlay) composable to open a Slideover programmatically.
You can use the [`useOverlay`](/composables/use-overlay) composable to open a Slideover programatically.
::warning
Make sure to wrap your app with the [`App`](/components/app) component which uses the [`OverlayProvider`](https://github.com/nuxt/ui/blob/v3/src/runtime/components/OverlayProvider.vue) component.
::
First, create a slideover component that will be opened programmatically:
First, create a slideover component that will be opened programatically:
::component-example
---

View File

@@ -136,21 +136,6 @@ props:
---
::
### Tooltip :badge{label="New" class="align-text-top"}
Use the `tooltip` prop to display a [Tooltip](/components/tooltip) around the Slider thumbs with the current value. You can set it to `true` for default behavior or pass an object to customize it with any property from the [Tooltip](/components/tooltip#props) component.
::component-code
---
ignore:
- defaultValue
- tooltip
props:
defaultValue: 50
tooltip: true
---
::
### Disabled
Use the `disabled` prop to disable the Slider.

View File

@@ -23,8 +23,6 @@ Use the `items` prop as an array of objects with the following properties:
- `value?: string | number`{lang="ts-type"}
- `disabled?: boolean`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, container?: ClassNameValue, trigger?: ClassNameValue, indicator?: ClassNameValue, icon?: ClassNameValue, separator?: ClassNameValue, wrapper?: ClassNameValue, title?: ClassNameValue, description?: ClassNameValue }`{lang="ts-type"}
::component-code
---
@@ -200,10 +198,6 @@ Use the `#content` slot to customize the content of each item.
Use the `slot` property to customize a specific item.
You will have access to the following slots:
- `#{{ item.slot }}`{lang="ts-type"}
:component-example{name="stepper-custom-slot-example"}
## API

View File

@@ -47,7 +47,7 @@ props:
---
::
When using the `required` prop, an asterisk is added next to the label.
When using the `required` prop, an asterisk is be added next to the label.
::component-code
---
@@ -109,7 +109,7 @@ props:
### Loading Icon
Use the `loading-icon` prop to customize the loading icon. Defaults to `i-lucide-loader-circle`.
Use the `loading-icon` prop to customize the loading icon. Defaults to `i-lucide-refresh-cw`.
::component-code
---
@@ -118,7 +118,7 @@ ignore:
- defaultValue
props:
loading: true
loadingIcon: 'i-lucide-loader'
loadingIcon: 'i-lucide-repeat-2'
defaultValue: true
label: Check me
---

View File

@@ -260,30 +260,6 @@ You can use the `expanded` prop to control the expandable state of the rows (can
You could also add this action to the [`DropdownMenu`](/components/dropdown-menu) component inside the `actions` column.
::
### With grouped rows
You can group rows based on a given column value and show/hide sub rows via some button added to the cell using the TanStack Table [Grouping APIs](https://tanstack.com/table/latest/docs/api/features/grouping).
#### Important parts:
* Add prop `grouping` to `UTable` component with an array of column ids you want to group by.
* Add prop `grouping-options` to `UTable`. It must include `getGroupedRowModel`, you can import it from `@tanstack/vue-table` or implement your own.
* Expand rows via `row.toggleExpanded()` method on any cell of the row. Keep in mind, it also toggles `#expanded` slot.
* Use `aggregateFn` on column definition to define how to aggregate the rows.
* `agregatedCell` renderer on column definition only works if there is no `cell` renderer.
::component-example
---
prettier: true
collapse: true
name: 'table-grouped-rows-example'
highlights:
- 159
- 169
class: '!p-0'
---
::
### With row selection
You can add a new column that renders a [Checkbox](/components/checkbox) component inside the `header` and `cell` to select rows using the TanStack Table [Row Selection APIs](https://tanstack.com/table/latest/docs/api/features/row-selection).

View File

@@ -23,8 +23,6 @@ Use the `items` prop as an array of objects with the following properties:
- `value?: string | number`{lang="ts-type"}
- `disabled?: boolean`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `class?: any`{lang="ts-type"}
- `ui?: { trigger?: ClassNameValue, leadingIcon?: ClassNameValue, leadingAvatar?: ClassNameValue, label?: ClassNameValue, content?: ClassNameValue }`{lang="ts-type"}
::component-code
---
@@ -212,6 +210,10 @@ You can control the active item by using the `default-value` prop or the `v-mode
:component-example{name="tabs-model-value-example"}
::tip
You can also pass the `value` of one of the items if provided.
::
### With content slot
Use the `#content` slot to customize the content of each item.
@@ -222,10 +224,6 @@ Use the `#content` slot to customize the content of each item.
Use the `slot` property to customize a specific item.
You will have access to the following slots:
- `#{{ item.slot }}`{lang="ts-type"}
:component-example{name="tabs-custom-slot-example"}
## API

View File

@@ -194,7 +194,7 @@ props:
### Loading Icon :badge{label="New" class="align-text-top"}
Use the `loading-icon` prop to customize the loading icon. Defaults to `i-lucide-loader-circle`.
Use the `loading-icon` prop to customize the loading icon. Defaults to `i-lucide-refresh-cw`.
::component-code
---
@@ -202,7 +202,7 @@ ignore:
- placeholder
props:
loading: true
loadingIcon: 'i-lucide-loader'
loadingIcon: 'i-lucide-repeat-2'
placeholder: 'Search...'
rows: 1
---

View File

@@ -1,228 +0,0 @@
---
title: Timeline
description: 'A component that displays a sequence of events with dates, titles, icons or avatars.'
category: data
links:
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/Timeline.vue
navigation.badge: Soon
---
## Usage
### Items
Use the `items` prop as an array of objects with the following properties:
- `date?: string`{lang="ts-type"}
- `title?: string`{lang="ts-type"}
- `description?: AvatarProps`{lang="ts-type"}
- `icon?: string`{lang="ts-type"}
- `avatar?: AvatarProps`{lang="ts-type"}
- `value?: string | number`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, container?: ClassNameValue, indicator?: ClassNameValue, separator?: ClassNameValue, wrapper?: ClassNameValue, separator?: ClassNameValue, date?: ClassNameValue, title?: ClassNameValue, description?: ClassNameValue }`{lang="ts-type"}
::component-code
---
ignore:
- items
- class
- defaultValue
external:
- items
externalTypes:
- TimelineItem[]
props:
defaultValue: 2
items:
- date: 'Mar 15, 2025'
title: 'Project Kickoff'
description: 'Kicked off the project with team alignment. Set up project milestones and allocated resources.'
icon: 'i-lucide-rocket'
- date: 'Mar 22 2025'
title: 'Design Phase'
description: 'User research and design workshops. Created wireframes and prototypes for user testing.'
icon: 'i-lucide-palette'
- date: 'Mar 29 2025'
title: 'Development Sprint'
description: 'Frontend and backend development. Implemented core features and integrated with APIs.'
icon: 'i-lucide-code'
- date: 'Apr 5 2025'
title: 'Testing & Deployment'
description: 'QA testing and performance optimization. Deployed the application to production.'
icon: 'i-lucide-check-circle'
class: 'w-96'
---
::
### Color
Use the `color` prop to change the color of the active items in a Timeline.
::component-code
---
ignore:
- items
- class
- defaultValue
external:
- items
externalTypes:
- TimelineItem[]
props:
color: neutral
defaultValue: 2
items:
- date: 'Mar 15, 2025'
title: 'Project Kickoff'
description: 'Kicked off the project with team alignment. Set up project milestones and allocated resources.'
icon: 'i-lucide-rocket'
- date: 'Mar 22 2025'
title: 'Design Phase'
description: 'User research and design workshops. Created wireframes and prototypes for user testing.'
icon: 'i-lucide-palette'
- date: 'Mar 29 2025'
title: 'Development Sprint'
description: 'Frontend and backend development. Implemented core features and integrated with APIs.'
icon: 'i-lucide-code'
- date: 'Apr 5 2025'
title: 'Testing & Deployment'
description: 'QA testing and performance optimization. Deployed the application to production.'
icon: 'i-lucide-check-circle'
class: 'w-96'
---
::
### Size
Use the `size` prop to change the size of the Timeline.
::component-code
---
ignore:
- items
- class
- defaultValue
external:
- items
externalTypes:
- TimelineItem[]
props:
size: xs
defaultValue: 2
items:
- date: 'Mar 15, 2025'
title: 'Project Kickoff'
description: 'Kicked off the project with team alignment. Set up project milestones and allocated resources.'
icon: 'i-lucide-rocket'
- date: 'Mar 22 2025'
title: 'Design Phase'
description: 'User research and design workshops. Created wireframes and prototypes for user testing.'
icon: 'i-lucide-palette'
- date: 'Mar 29 2025'
title: 'Development Sprint'
description: 'Frontend and backend development. Implemented core features and integrated with APIs.'
icon: 'i-lucide-code'
- date: 'Apr 5 2025'
title: 'Testing & Deployment'
description: 'QA testing and performance optimization. Deployed the application to production.'
icon: 'i-lucide-check-circle'
class: 'w-96'
---
::
### Orientation
Use the `orientation` prop to change the orientation of the Timeline. Defaults to `vertical`.
::component-code
---
ignore:
- items
- class
- defaultValue
external:
- items
externalTypes:
- TimelineItem[]
props:
orientation: 'horizontal'
defaultValue: 2
items:
- date: 'Mar 15, 2025'
title: 'Project Kickoff'
description: 'Kicked off the project with team alignment.'
icon: 'i-lucide-rocket'
- date: 'Mar 22 2025'
title: 'Design Phase'
description: 'User research and design workshops.'
icon: 'i-lucide-palette'
- date: 'Mar 29 2025'
title: 'Development Sprint'
description: 'Frontend and backend development.'
icon: 'i-lucide-code'
- date: 'Apr 5 2025'
title: 'Testing & Deployment'
description: 'QA testing and performance optimization.'
icon: 'i-lucide-check-circle'
class: 'w-full'
---
::
## Examples
### Control active item
You can control the active item by using the `default-value` prop or the `v-model` directive with the index of the item.
:component-example{name="timeline-model-value-example" prettier}
::tip
You can also pass the `value` of one of the items if provided.
::
### With alternating layout
Use the `ui` prop to create a Timeline with alternating layout.
:component-example{name="timeline-alternating-layout-example" prettier}
### With custom slot
Use the `slot` property to customize a specific item.
You will have access to the following slots:
- `#{{ item.slot }}-indicator`{lang="ts-type"}
- `#{{ item.slot }}-date`{lang="ts-type"}
- `#{{ item.slot }}-title`{lang="ts-type"}
- `#{{ item.slot }}-description`{lang="ts-type"}
:component-example{name="timeline-custom-slot-example" prettier}
### With slots
Use the available slots to create a more complex Timeline.
:component-example{name="timeline-slots-example" prettier}
## API
### Props
:component-props
### Slots
:component-slots
### Emits
:component-emits
## Theme
:component-theme

View File

@@ -188,7 +188,7 @@ name: 'toast-example'
:toaster-position-example
::
::note{to="https://github.com/nuxt/ui/blob/v3/docs/app/app.config.ts#L3"}
::note{to="https://github.com/nuxt/ui/blob/v3/docs/app/app.vue#L77"}
In this example, we use the `AppConfig` to configure the `position` prop of the `Toaster` component globally.
::
@@ -206,7 +206,7 @@ name: 'toast-example'
:toaster-duration-example
::
::note{to="https://github.com/nuxt/ui/blob/v3/docs/app/app.config.ts#L5"}
::note{to="https://github.com/nuxt/ui/blob/v3/docs/app/app.vue#L77"}
In this example, we use the `AppConfig` to configure the `duration` prop of the `Toaster` component globally.
::
@@ -228,7 +228,7 @@ name: 'toast-example'
:toaster-expand-example
::
::note{to="https://github.com/nuxt/ui/blob/v3/docs/app/app.config.ts#L4"}
::note{to="https://github.com/nuxt/ui/blob/v3/docs/app/app.vue#L77"}
In this example, we use the `AppConfig` to configure the `expand` prop of the `Toaster` component globally.
::

View File

@@ -26,8 +26,6 @@ Use the `items` prop as an array of objects with the following properties:
- `children?: TreeItem[]`{lang="ts-type"}
- `onToggle?(e: Event): void`{lang="ts-type"}
- `onSelect?(e?: Event): void`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, itemWithChildren?: ClassNameValue, link?: ClassNameValue, linkLeadingIcon?: ClassNameValue, linkLabel?: ClassNameValue, linkTrailing?: ClassNameValue, linkTrailingIcon?: ClassNameValue, listWithChildren?: ClassNameValue }`{lang="ts-type"}
::note
A unique identifier is required for each item. The component will use the `value` prop as identifier, falling back to `label` if `value` is not provided. One of these must be provided for the component to work properly.
@@ -407,14 +405,7 @@ This lets you select a parent item without expanding or collapsing its children.
### With custom slot
Use the `slot` property to customize a specific item.
You will have access to the following slots:
- `#{{ item.slot }}`{lang="ts-type"}
- `#{{ item.slot }}-leading`{lang="ts-type"}
- `#{{ item.slot }}-label`{lang="ts-type"}
- `#{{ item.slot }}-trailing`{lang="ts-type"}
Use the `item.slot` property to customize a specific item.
::component-example
---

View File

@@ -3,40 +3,40 @@
"name": "@nuxt/ui-docs",
"type": "module",
"dependencies": {
"@ai-sdk/vue": "^1.2.12",
"@ai-sdk/vue": "^1.2.8",
"@iconify-json/logos": "^1.2.4",
"@iconify-json/lucide": "^1.2.44",
"@iconify-json/simple-icons": "^1.2.35",
"@iconify-json/vscode-icons": "^1.2.21",
"@iconify-json/lucide": "^1.2.38",
"@iconify-json/simple-icons": "^1.2.33",
"@iconify-json/vscode-icons": "^1.2.19",
"@nuxt/content": "^3.5.1",
"@nuxt/image": "^1.10.0",
"@nuxt/ui": "latest",
"@nuxt/ui-pro": "https://pkg.pr.new/@nuxt/ui-pro@f06b49c",
"@nuxthub/core": "^0.8.27",
"@nuxt/ui-pro": "^3.1.0",
"@nuxthub/core": "^0.8.25",
"@nuxtjs/plausible": "^1.2.0",
"@octokit/rest": "^22.0.0",
"@octokit/rest": "^21.1.1",
"@rollup/plugin-yaml": "^4.1.2",
"@vueuse/integrations": "^13.2.0",
"@vueuse/nuxt": "^13.2.0",
"ai": "^4.3.16",
"@vueuse/integrations": "^13.1.0",
"@vueuse/nuxt": "^13.1.0",
"ai": "^4.3.9",
"capture-website": "^4.2.0",
"joi": "^17.13.3",
"motion-v": "^1.1.1",
"nuxt": "^3.17.4",
"motion-v": "^0.13.1",
"nuxt": "^3.16.2",
"nuxt-component-meta": "^0.11.0",
"nuxt-llms": "^0.1.2",
"nuxt-og-image": "^5.1.4",
"nuxt-og-image": "^5.1.2",
"prettier": "^3.5.3",
"shiki-transformer-color-highlight": "^1.0.0",
"sortablejs": "^1.15.6",
"superstruct": "^2.0.2",
"ufo": "^1.6.1",
"valibot": "^1.1.0",
"workers-ai-provider": "^0.5.2",
"valibot": "^1.0.0",
"workers-ai-provider": "^0.3.0",
"yup": "^1.6.1",
"zod": "^3.25.28"
"zod": "^3.24.3"
},
"devDependencies": {
"wrangler": "^4.16.1"
"wrangler": "^4.13.0"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -46,33 +46,11 @@ const parseBoolean = (value?: string): boolean => value === 'true'
function getComponentMeta(componentName: string) {
const pascalCaseName = componentName.charAt(0).toUpperCase() + componentName.slice(1)
const strategies = [
`U${pascalCaseName}`,
`Prose${pascalCaseName}`,
pascalCaseName
]
let componentMeta: any
let finalMetaComponentName: string = pascalCaseName
for (const nameToTry of strategies) {
finalMetaComponentName = nameToTry
const metaAttempt = (meta as Record<string, any>)[nameToTry]?.meta
if (metaAttempt) {
componentMeta = metaAttempt
break
}
}
if (!componentMeta) {
console.warn(`[getComponentMeta] Metadata not found for ${pascalCaseName} using strategies: U, Prose, or no prefix. Last tried: ${finalMetaComponentName}`)
}
const metaComponentName = `U${pascalCaseName}`
return {
pascalCaseName,
metaComponentName: finalMetaComponentName,
componentMeta
metaComponentName,
componentMeta: (meta as Record<string, any>)[metaComponentName]?.meta
}
}
@@ -190,7 +168,6 @@ function emitItemHandler(event: any): string {
const generateThemeConfig = ({ pro, prose, componentName }: ThemeConfig) => {
const computedTheme = pro ? (prose ? themePro.prose : themePro) : theme
const componentTheme = computedTheme[componentName as keyof typeof computedTheme]
return {
[pro ? 'uiPro' : 'ui']: prose
? { prose: { [componentName]: componentTheme } }
@@ -307,14 +284,10 @@ export default defineNitroPlugin((nitroApp) => {
const componentName = camelCase(doc.title)
visitAndReplace(doc, 'component-theme', (node) => {
const attributes = node[1] as Record<string, string>
const mdcSpecificName = attributes?.slug
const finalComponentName = mdcSpecificName ? camelCase(mdcSpecificName) : componentName
const attributes = node[1] as ComponentAttributes
const pro = parseBoolean(attributes[':pro'])
const prose = parseBoolean(attributes[':prose'])
const appConfig = generateThemeConfig({ pro, prose, componentName: finalComponentName })
const appConfig = generateThemeConfig({ pro, prose, componentName })
replaceNodeWithPre(
node,
@@ -349,23 +322,14 @@ export default defineNitroPlugin((nitroApp) => {
})
visitAndReplace(doc, 'component-props', (node) => {
const attributes = node[1] as Record<string, string>
const mdcSpecificName = attributes?.name
const isProse = parseBoolean(attributes[':prose'])
const finalComponentName = mdcSpecificName ? camelCase(mdcSpecificName) : componentName
const { pascalCaseName, componentMeta } = getComponentMeta(finalComponentName)
const { pascalCaseName, componentMeta } = getComponentMeta(componentName)
if (!componentMeta?.props) return
const interfaceName = isProse ? `Prose${pascalCaseName}Props` : `${pascalCaseName}Props`
const interfaceCode = generateTSInterface(
interfaceName,
`${pascalCaseName}Props`,
Object.values(componentMeta.props),
propItemHandler,
`Props for the ${isProse ? 'Prose' : ''}${pascalCaseName} component`
`Props for the ${pascalCaseName} component`
)
replaceNodeWithPre(node, 'ts', interfaceCode)
})

View File

@@ -1,8 +1,8 @@
{
"name": "@nuxt/ui",
"description": "A UI Library for Modern Web Apps, powered by Vue & Tailwind CSS.",
"version": "3.1.3",
"packageManager": "pnpm@10.11.0",
"version": "3.1.0",
"packageManager": "pnpm@10.9.0",
"repository": {
"type": "git",
"url": "git+https://github.com/nuxt/ui.git"
@@ -87,21 +87,17 @@
"style": "./dist/runtime/index.css",
"main": "./dist/module.mjs",
"files": [
".nuxt/ui",
".nuxt/ui.css",
"dist",
"cli",
"vue-plugin.d.ts"
"dist"
],
"scripts": {
"build": "nuxt-module-build build",
"prepack": "pnpm build",
"dev": "nuxi dev playground --uiDev",
"dev": "nuxi dev playground",
"dev:build": "nuxi build playground",
"dev:vue": "vite playground-vue -- --uiDev",
"dev:vue": "vite playground-vue",
"dev:vue:build": "vite build playground-vue",
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground && nuxi prepare docs && vite build playground-vue",
"docs": "nuxi dev docs --uiDev",
"docs": "nuxi dev docs",
"docs:build": "nuxi build docs",
"docs:prepare": "nuxt-component-meta docs",
"lint": "eslint .",
@@ -112,21 +108,21 @@
"release": "release-it"
},
"dependencies": {
"@iconify/vue": "^5.0.0",
"@internationalized/date": "^3.8.1",
"@internationalized/number": "^3.6.2",
"@nuxt/fonts": "^0.11.4",
"@nuxt/icon": "^1.13.0",
"@nuxt/kit": "^3.17.4",
"@nuxt/schema": "^3.17.4",
"@iconify/vue": "^4.3.0",
"@internationalized/date": "^3.8.0",
"@internationalized/number": "^3.6.1",
"@nuxt/fonts": "^0.11.1",
"@nuxt/icon": "^1.12.0",
"@nuxt/kit": "^3.16.2",
"@nuxt/schema": "^3.16.2",
"@nuxtjs/color-mode": "^3.5.2",
"@standard-schema/spec": "^1.0.0",
"@tailwindcss/postcss": "^4.1.7",
"@tailwindcss/vite": "^4.1.7",
"@tailwindcss/postcss": "^4.1.4",
"@tailwindcss/vite": "^4.1.4",
"@tanstack/vue-table": "^8.21.3",
"@unhead/vue": "^2.0.10",
"@vueuse/core": "^13.2.0",
"@vueuse/integrations": "^13.2.0",
"@unhead/vue": "^2.0.8",
"@vueuse/core": "^13.1.0",
"@vueuse/integrations": "^13.1.0",
"colortranslator": "^4.1.0",
"consola": "^3.4.2",
"defu": "^6.1.4",
@@ -144,31 +140,30 @@
"mlly": "^1.7.4",
"ohash": "^2.0.11",
"pathe": "^2.0.3",
"reka-ui": "^2.3.0",
"reka-ui": "^2.2.0",
"scule": "^1.3.0",
"tailwind-variants": "^1.0.0",
"tailwindcss": "^4.1.7",
"tinyglobby": "^0.2.14",
"unplugin": "^2.3.4",
"unplugin-auto-import": "^19.3.0",
"unplugin-vue-components": "^28.7.0",
"vaul-vue": "^0.4.1",
"vue-component-type-helpers": "^2.2.10"
"tailwindcss": "^4.1.4",
"tinyglobby": "^0.2.13",
"unplugin": "^2.3.2",
"unplugin-auto-import": "^19.1.2",
"unplugin-vue-components": "^28.5.0",
"vaul-vue": "^0.4.1"
},
"devDependencies": {
"@nuxt/eslint-config": "^1.4.1",
"@nuxt/eslint-config": "^1.3.0",
"@nuxt/module-builder": "^1.0.1",
"@nuxt/test-utils": "^3.19.1",
"@nuxt/test-utils": "^3.17.2",
"@release-it/conventional-changelog": "^10.0.1",
"@vue/test-utils": "^2.4.6",
"embla-carousel": "^8.6.0",
"eslint": "^9.27.0",
"happy-dom": "^17.4.7",
"nuxt": "^3.17.4",
"release-it": "^19.0.2",
"vitest": "^3.1.4",
"eslint": "^9.25.1",
"happy-dom": "^17.4.4",
"nuxt": "^3.16.2",
"release-it": "^19.0.1",
"vitest": "^3.1.2",
"vitest-environment-nuxt": "^1.0.1",
"vue-tsc": "^2.2.10"
"vue-tsc": "^2.2.0"
},
"peerDependencies": {
"@inertiajs/vue3": "^2.0.7",
@@ -208,8 +203,8 @@
"chokidar": "3.6.0",
"debug": "4.3.7",
"rollup": "4.34.9",
"unimport": "4.1.1",
"unplugin": "^2.3.4"
"unplugin": "^2.3.2",
"vue-tsc": "2.2.0"
},
"pnpm": {
"onlyBuiltDependencies": [

View File

@@ -4,8 +4,6 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=public-sans:400,500,600,700" rel="stylesheet" />
<title>Nuxt UI - Vue Playground</title>
</head>
<body>

View File

@@ -11,14 +11,14 @@
},
"dependencies": {
"@nuxt/ui": "latest",
"vue": "^3.5.15",
"vue-router": "^4.5.1",
"zod": "^3.25.28"
"vue": "^3.5.13",
"vue-router": "^4.5.0",
"zod": "^3.24.3"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.2.4",
"@vitejs/plugin-vue": "^5.2.3",
"typescript": "^5.8.3",
"vite": "^6.3.5",
"vue-tsc": "^2.2.10"
"vite": "^6.3.3",
"vue-tsc": "^2.2.0"
}
}

View File

@@ -61,7 +61,6 @@ const components = [
'tabs',
'table',
'textarea',
'timeline',
'toast',
'tooltip',
'tree'

View File

@@ -1,9 +1,15 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'
import ui from '../src/vite'
// https://vitejs.dev/config/
export default defineConfig({
server: {
fs: {
allow: ['..']
}
},
plugins: [
vue(),
ui({

View File

@@ -61,7 +61,6 @@ const components = [
'tabs',
'table',
'textarea',
'timeline',
'toast',
'tooltip',
'tree'

View File

@@ -36,27 +36,14 @@ const variants = Object.keys(theme.variants.variant) as Array<keyof typeof theme
color="neutral"
/>
</div>
<div class="flex items-center gap-2 ms-[-90px]">
<div class="flex items-center gap-2 ms-[-56px]">
<UBadge v-for="size in sizes" :key="size" label="Badge" :size="size" />
</div>
<div class="flex items-center gap-2 ms-[-122px]">
<div class="flex items-center gap-2 ms-[-86px]">
<UBadge v-for="size in sizes" :key="size" icon="i-lucide-rocket" label="Badge" :size="size" />
</div>
<div class="flex items-center gap-2 ms-[-130px]">
<div class="flex items-center gap-2 ms-[-86px]">
<UBadge v-for="size in sizes" :key="size" :avatar="{ src: 'https://github.com/benjamincanac.png' }" label="Badge" :size="size" />
</div>
<div class="flex items-center gap-2 ms-[-52px]">
<UBadge v-for="size in sizes" :key="size" icon="i-lucide-rocket" :size="size" />
</div>
<div class="flex items-center gap-2 ms-[-60px]">
<UBadge
v-for="size in sizes"
:key="size"
:avatar="{ src: 'https://github.com/benjamincanac.png' }"
:size="size"
color="neutral"
variant="outline"
/>
</div>
</div>
</template>

View File

@@ -2,23 +2,19 @@
import { CalendarDate } from '@internationalized/date'
const singleValue = shallowRef(new CalendarDate(2022, 1, 10))
const multipleValue = shallowRef([new CalendarDate(2022, 1, 10), new CalendarDate(2022, 1, 20)])
const rangeValue = shallowRef({
const multipleValue = shallowRef({
start: new CalendarDate(2022, 1, 10),
end: new CalendarDate(2022, 1, 20)
})
</script>
<template>
<div class="flex gap-4">
<div class="flex flex-col gap-4">
<div class="flex justify-center gap-2">
<UCalendar v-model="singleValue" />
</div>
<div class="flex justify-center gap-2">
<UCalendar v-model="multipleValue" multiple />
</div>
<div class="flex justify-center gap-2">
<UCalendar v-model="rangeValue" range />
<UCalendar v-model="multipleValue" range />
</div>
</div>
</template>

View File

@@ -28,12 +28,7 @@ const bind = computed(() => ({
dots: dots.value
}))
const items = Array.from({ length: 6 }).map((_, index) => ({
id: index,
title: `Item ${index + 1}`,
description: `Description for item ${index + 1}`,
src: `https://picsum.photos/640/640?v=${index}`
}))
const items = Array.from({ length: 6 }).map((_, index) => index)
</script>
<template>
@@ -65,23 +60,23 @@ const items = Array.from({ length: 6 }).map((_, index) => ({
</div>
<template v-if="classNames">
<UCarousel v-slot="{ item }" v-bind="bind" :items="items" :ui="{ item: 'basis-[70%] transition-opacity ease-in-out [&:not(.is-snapped)]:opacity-10', container: 'h-[352px]' }" class="w-full max-w-xl mx-auto">
<img :src="item.src" class="rounded-lg">
<UCarousel v-slot="{ index }" v-bind="bind" :items="items" :ui="{ item: 'basis-[70%] transition-opacity ease-in-out [&:not(.is-snapped)]:opacity-10', container: 'h-[352px]' }" class="w-full max-w-xl mx-auto">
<img :src="`https://picsum.photos/600/350?v=${index}`" class="rounded-lg">
</UCarousel>
</template>
<template v-else-if="autoHeight">
<UCarousel v-slot="{ item }" v-bind="bind" :items="items" :ui="{ container: 'transition-[height] duration-200' }" class="w-full max-w-md mx-auto">
<img :src="item.src" class="rounded-lg">
<UCarousel v-slot="{ index }" v-bind="bind" :items="items" :ui="{ container: 'transition-[height] duration-200' }" class="w-full max-w-md mx-auto">
<img :src="`https://picsum.photos/600/${index % 2 === 0 ? 350 : 450}?v=${index}`" :class="index % 2 === 0 ? 'h-[350px]' : 'h-[450px]'" class="rounded-lg">
</UCarousel>
</template>
<template v-else>
<UCarousel v-slot="{ item }" v-bind="bind" :items="items" class="w-[320px] mx-auto" :ui="{ container: 'h-[336px]' }">
<img :src="item.src" class="rounded-lg">
<UCarousel v-slot="{ index }" v-bind="bind" :items="items" class="w-[320px] mx-auto" :ui="{ container: 'h-[336px]' }">
<img :src="`https://picsum.photos/640/640?v=${index}`" class="rounded-lg">
</UCarousel>
<template v-if="orientation === 'horizontal'">
<UCarousel v-slot="{ item }" v-bind="bind" :items="items" :ui="{ item: 'basis-1/3' }" class="w-full max-w-xs mx-auto">
<img :src="item.src" class="rounded-lg">
<UCarousel v-slot="{ index }" v-bind="bind" :items="items" :ui="{ item: 'basis-1/3' }" class="w-full max-w-xs mx-auto">
<img :src="`https://picsum.photos/320/320?v=${index}`" class="rounded-lg">
</UCarousel>
</template>
</template>

View File

@@ -1,8 +1,9 @@
<script setup lang="ts">
import themeCheckbox from '#build/ui/checkbox'
import theme from '#build/ui/checkbox-group'
const sizes = Object.keys(theme.variants.size) as Array<keyof typeof theme.variants.size>
const variants = Object.keys(theme.variants.variant)
const variants = Object.keys(themeCheckbox.variants.variant)
const variant = ref('list' as const)
const literalOptions = [

View File

@@ -47,7 +47,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
<template>
<div class="flex flex-col items-center gap-4">
<div class="flex flex-col gap-4 w-48">
<UInputMenu :items="items" autofocus placeholder="Search..." default-value="Apple" />
<UInputMenu :items="items" autofocus placeholder="Search..." />
</div>
<div class="flex items-center gap-2">
<UInputMenu

View File

@@ -69,13 +69,5 @@ function openModal() {
</UModal>
<UButton label="Open programmatically" color="neutral" variant="outline" @click="openModal" />
<UModal title="First modal">
<UButton color="neutral" variant="outline" label="Close with scoped slot close" />
<template #footer="{ close }">
<UButton label="Close with scoped slot close" @click="close" />
</template>
</UModal>
</div>
</template>

View File

@@ -1,5 +1,4 @@
<script setup lang="ts">
import type { NavigationMenuItem } from '@nuxt/ui'
import theme from '#build/ui/navigation-menu'
const colors = Object.keys(theme.variants.color)
@@ -14,9 +13,6 @@ const orientation = ref('horizontal' as const)
const contentOrientation = ref('horizontal' as const)
const highlight = ref(true)
const collapsed = ref(false)
const tooltip = ref(false)
const popover = ref(false)
const arrow = ref(false)
const items = [
[{
@@ -46,8 +42,7 @@ const items = [
}, {
label: 'Components',
icon: 'i-lucide-box',
to: '/components/navigation-menu',
type: 'trigger',
to: '/components',
active: true,
defaultOpen: true,
children: [{
@@ -92,7 +87,7 @@ const items = [
icon: 'i-lucide-circle-help',
disabled: true
}]
] satisfies NavigationMenuItem[][]
]
</script>
<template>
@@ -105,15 +100,10 @@ const items = [
<USwitch v-model="collapsed" label="Collapsed" />
<USwitch v-model="highlight" label="Highlight" />
<USelect v-model="highlightColor" :items="colors" placeholder="Highlight color" />
<USwitch v-model="tooltip" label="Tooltip" />
<USwitch v-model="popover" label="Popover" />
<USwitch v-model="arrow" label="Arrow" />
</div>
<UNavigationMenu
:arrow="arrow"
:tooltip="tooltip"
:popover="popover"
arrow
:collapsed="collapsed"
:items="items"
:color="color"

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