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
384 changed files with 15642 additions and 22798 deletions

1
.github/CODEOWNERS vendored
View File

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

View File

@@ -5,12 +5,12 @@ body:
- type: markdown - type: markdown
attributes: attributes:
value: | 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 - type: textarea
id: env id: env
attributes: attributes:
label: Environment label: Environment
description: You can use `npx nuxt info` to fill this section description: You can use `npx nuxi info` to fill this section
placeholder: | placeholder: |
- Operating System: `Darwin` - Operating System: `Darwin`
- Node Version: `v18.16.0` - Node Version: `v18.16.0`
@@ -44,7 +44,7 @@ body:
id: reproduction id: reproduction
attributes: attributes:
label: Reproduction 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 placeholder: https://github.com/my/reproduction
validations: validations:
required: true required: true

View File

@@ -10,7 +10,7 @@ body:
id: env id: env
attributes: attributes:
label: Environment label: Environment
description: You can use `npx nuxt info` to fill this section description: You can use `npx nuxi info` to fill this section
placeholder: | placeholder: |
- Operating System: `Darwin` - Operating System: `Darwin`
- Node Version: `v18.16.0` - Node Version: `v18.16.0`

View File

@@ -5,7 +5,7 @@ body:
- type: markdown - type: markdown
attributes: attributes:
value: | 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 - type: textarea
id: description id: description
attributes: attributes:

View File

@@ -5,7 +5,7 @@ body:
- type: markdown - type: markdown
attributes: attributes:
value: | 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 - type: textarea
id: description id: description
attributes: 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

@@ -6,6 +6,10 @@ jobs:
deploy: deploy:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
environment:
name: ${{ github.ref == 'refs/heads/v3' && 'production' || 'preview' }}
url: ${{ steps.deploy.outputs.deployment-url }}
permissions: permissions:
contents: read contents: read
id-token: write id-token: write
@@ -36,10 +40,14 @@ jobs:
- name: Prepare build - name: Prepare build
run: pnpm run dev:prepare run: pnpm run dev:prepare
- name: Deploy to NuxtHub - name: Build application
uses: nuxt-hub/action@v2 run: pnpm run docs:build
env: env:
NODE_OPTIONS: '--max-old-space-size=8192' NODE_OPTIONS: '--max-old-space-size=8192'
- name: Deploy to NuxtHub
uses: nuxt-hub/action@v1
id: deploy
with: with:
project-key: ui-7eg3 project-key: ui-7eg3
directory: docs directory: docs/dist

View File

@@ -69,53 +69,6 @@ jobs:
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
run: pnpx pkg-pr-new publish --compact --no-template --pnpm 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.event.pull_request.head.sha || github.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 nuxt prepare
- name: Typecheck
run: pnpm run typecheck
starter-nuxt: starter-nuxt:
needs: build needs: build
@@ -138,7 +91,7 @@ jobs:
- name: Store commit SHA - name: Store commit SHA
run: | run: |
echo "COMMIT_SHA=$(echo ${{ github.event.pull_request.head.sha || github.sha }} | cut -c1-7)" >> $GITHUB_ENV echo "COMMIT_SHA=$(echo ${{ github.workflow_sha }} | cut -c1-7)" >> $GITHUB_ENV
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4
@@ -183,7 +136,7 @@ jobs:
- name: Store commit SHA - name: Store commit SHA
run: | run: |
echo "COMMIT_SHA=$(echo ${{ github.event.pull_request.head.sha || github.sha }} | cut -c1-7)" >> $GITHUB_ENV echo "COMMIT_SHA=$(echo ${{ github.workflow_sha }} | cut -c1-7)" >> $GITHUB_ENV
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4
@@ -235,7 +188,7 @@ jobs:
- name: Store commit SHA - name: Store commit SHA
run: | run: |
echo "COMMIT_SHA=$(echo ${{ github.event.pull_request.head.sha || github.sha }} | cut -c1-7)" >> $GITHUB_ENV echo "COMMIT_SHA=$(echo ${{ github.workflow_sha }} | cut -c1-7)" >> $GITHUB_ENV
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4

View File

@@ -9,6 +9,10 @@ jobs:
deploy: deploy:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
environment:
name: ${{ github.ref == 'refs/heads/v3' && 'production' || 'preview' }}
url: ${{ steps.deploy.outputs.deployment-url }}
permissions: permissions:
contents: read contents: read
id-token: write id-token: write
@@ -36,10 +40,14 @@ jobs:
- name: Prepare build - name: Prepare build
run: pnpm run dev:prepare run: pnpm run dev:prepare
- name: Deploy to NuxtHub - name: Build application
uses: nuxt-hub/action@v2 run: pnpm run dev:build
env: env:
NODE_OPTIONS: '--max-old-space-size=8192' NITRO_PRESET: cloudflare-pages
- name: Deploy to NuxtHub
uses: nuxt-hub/action@v1
id: deploy
with: with:
project-key: ui3-playground-pb9b project-key: ui3-playground-pb9b
directory: playground directory: playground/dist

View File

@@ -1,27 +0,0 @@
name: reproduction
on:
workflow_dispatch:
schedule:
- cron: '30 1 * * *'
jobs:
reproduction:
runs-on: ubuntu-latest
permissions:
actions: write
issues: write
steps:
- uses: actions/stale@v9
with:
days-before-stale: -1 # Issues and PR will never be flagged stale automatically.
stale-issue-label: 'needs reproduction' # Label that flags an issue as stale.
only-labels: 'needs reproduction' # Only process these issues
days-before-issue-close: 7
ignore-updates: true
remove-stale-when-updated: false
close-issue-message: This issue was closed because it was open for 7 days without a reproduction.
close-issue-label: closed-by-bot
operations-per-run: 300 #default 30

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,7 +1,6 @@
name: stale name: stale
on: on:
workflow_dispatch:
schedule: schedule:
- cron: '30 1 * * *' - cron: '30 1 * * *'
@@ -10,28 +9,17 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
actions: write
issues: write issues: write
steps: steps:
- uses: actions/stale@4c023f01d613e60293d8004f251a18bfb9bbd71d - uses: actions/stale@v9
with: with:
days-before-pr-stale: -1 days-before-stale: -1 # Issues and PR will never be flagged stale automatically.
days-before-stale: 60 stale-issue-label: 'needs reproduction' # Label that flags an issue as stale.
days-before-close: 7 only-labels: 'needs reproduction' # Only process these issues
stale-issue-label: 'stale' days-before-issue-close: 7
close-issue-label: 'closed-by-bot' ignore-updates: true
close-issue-message: | remove-stale-when-updated: false
Hi! 👋 close-issue-message: This issue was closed because it was open for 7 days without a reproduction.
close-issue-label: closed-by-bot
This issue has been automatically **closed** due to prolonged inactivity. operations-per-run: 300 #default 30
We're a small team and can't address every report, but we appreciate your feedback and contributions.
If this issue is still relevant with the latest version of Nuxt UI, please feel free to reopen or create a new issue with updated details.
Thank you for your understanding and support!
— Nuxt UI Team
exempt-issue-labels: 'feature,announcement'
operations-per-run: 300

View File

@@ -1,103 +1,5 @@
# Changelog # 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) ## [3.1.0](https://github.com/nuxt/ui/compare/v3.0.2...v3.1.0) (2025-04-24)
### ⚠ BREAKING CHANGES ### ⚠ BREAKING CHANGES

View File

@@ -11,7 +11,7 @@ export default defineBuildConfig({
delimiters: ['', ''], delimiters: ['', ''],
values: { values: {
// Used in development to import directly from theme // 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> </script>
<template> <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 /> <slot />
</Primitive> </Primitive>
</template> </template>
@@ -109,7 +109,7 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.${camelName}
</script> </script>
<template> <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> </template>
` `
} }

View File

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

View File

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

View File

@@ -22,7 +22,9 @@ onMounted(() => {
const navigation = inject<Ref<ContentNavigationItem[]>>('navigation') const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
const githubLink = computed(() => `https://github.com/nuxt/${value.value}`) const githubLink = computed(() => {
return `https://github.com/nuxt/${value.value}`
})
const desktopLinks = computed(() => props.links.map(({ icon, ...link }) => link)) const desktopLinks = computed(() => props.links.map(({ icon, ...link }) => link))
const mobileLinks = computed(() => [ const mobileLinks = computed(() => [
@@ -34,16 +36,6 @@ const mobileLinks = computed(() => [
target: '_blank' target: '_blank'
} }
]) ])
const items = computed(() => {
const ui2 = { label: 'v2.22.0', to: 'https://ui2.nuxt.com' }
const uiPro1 = { label: 'v1.8.0', to: 'https://ui2.nuxt.com/pro' }
return [
{ label: `v${config.version}`, active: true, color: 'primary' as const, checked: true, type: 'checkbox' as const },
route.path === '/' ? ui2 : route.path.startsWith('/pro') ? uiPro1 : module.value === 'ui-pro' ? uiPro1 : ui2
]
})
</script> </script>
<template> <template>
@@ -61,7 +53,7 @@ const items = computed(() => {
<UDropdownMenu <UDropdownMenu
v-slot="{ open }" v-slot="{ open }"
:modal="false" :modal="false"
:items="items" :items="[{ label: `v${config.version}`, active: true, color: 'primary', checked: true, type: 'checkbox' }, { label: module === 'ui-pro' ? 'v1.7.1' : 'v2.21.1', to: module === 'ui-pro' ? 'https://ui2.nuxt.com/pro' : 'https://ui2.nuxt.com' }]"
:ui="{ content: 'w-(--reka-dropdown-menu-trigger-width) min-w-0' }" :ui="{ content: 'w-(--reka-dropdown-menu-trigger-width) min-w-0' }"
size="xs" size="xs"
> >

View File

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

View File

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

View File

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

View File

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

View File

@@ -83,7 +83,7 @@ const groups = [
</template> </template>
<template #billing-label="{ item }"> <template #billing-label="{ item }">
<span class="font-medium text-primary">{{ item.label }}</span> {{ item.label }}
<UBadge variant="subtle" size="sm"> <UBadge variant="subtle" size="sm">
50% off 50% off

View File

@@ -1,10 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { refDebounced } from '@vueuse/core'
const searchTerm = ref('') const searchTerm = ref('')
const searchTermDebounced = refDebounced(searchTerm, 200) const searchTermDebounced = refDebounced(searchTerm, 200)
const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', { const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', {
key: 'command-palette-users',
params: { q: searchTermDebounced }, params: { q: searchTermDebounced },
transform: (data: { id: number, name: string, email: string }[]) => { 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}` } })) || [] 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

@@ -1,119 +0,0 @@
<script setup lang="ts">
const toast = useToast()
const groups = [{
id: 'actions',
label: 'Actions',
items: [{
label: 'Create new',
icon: 'i-lucide-plus',
children: [{
label: 'New file',
icon: 'i-lucide-file-plus',
suffix: 'Create a new file in the current directory',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'New file created!' })
},
kbds: ['meta', 'N']
}, {
label: 'New folder',
icon: 'i-lucide-folder-plus',
suffix: 'Create a new folder in the current directory',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'New folder created!' })
},
kbds: ['meta', 'F']
}, {
label: 'New project',
icon: 'i-lucide-folder-git',
suffix: 'Create a new project from a template',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'New project created!' })
},
kbds: ['meta', 'P']
}]
}, {
label: 'Share',
icon: 'i-lucide-share',
children: [{
label: 'Copy link',
icon: 'i-lucide-link',
suffix: 'Copy a link to the current item',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'Link copied to clipboard!' })
},
kbds: ['meta', 'L']
}, {
label: 'Share via email',
icon: 'i-lucide-mail',
suffix: 'Share the current item via email',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'Share via email dialog opened!' })
}
}, {
label: 'Share on social',
icon: 'i-lucide-share-2',
suffix: 'Share the current item on social media',
children: [{
label: 'Twitter',
icon: 'i-simple-icons-twitter',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'Shared on Twitter!' })
}
}, {
label: 'LinkedIn',
icon: 'i-simple-icons-linkedin',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'Shared on LinkedIn!' })
}
}, {
label: 'Facebook',
icon: 'i-simple-icons-facebook',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'Shared on Facebook!' })
}
}]
}]
}, {
label: 'Settings',
icon: 'i-lucide-settings',
children: [{
label: 'General',
icon: 'i-lucide-sliders',
suffix: 'Configure general settings',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'General settings opened!' })
}
}, {
label: 'Appearance',
icon: 'i-lucide-palette',
suffix: 'Customize the appearance',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'Appearance settings opened!' })
}
}, {
label: 'Security',
icon: 'i-lucide-shield',
suffix: 'Manage security settings',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'Security settings opened!' })
}
}]
}]
}]
</script>
<template>
<UCommandPalette :groups="groups" class="flex-1" />
</template>

View File

@@ -28,7 +28,7 @@ const items = [
</template> </template>
<template #refresh-trailing> <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> </template>
</UContextMenu> </UContextMenu>
</template> </template>

View File

@@ -3,7 +3,7 @@ const open = ref(false)
</script> </script>
<template> <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" /> <UButton label="Open" color="neutral" variant="subtle" trailing-icon="i-lucide-chevron-up" />
<template #header> <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', { select: z.string().refine(value => value === 'option-2', {
message: 'Select 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', { selectMenu: z.any().refine(option => option?.value === 'option-2', {
message: 'Select 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" /> <USelect v-model="state.select" :items="items" class="w-full" />
</UFormField> </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"> <UFormField name="selectMenu" label="Select Menu">
<USelectMenu v-model="state.selectMenu" :items="items" class="w-full" /> <USelectMenu v-model="state.selectMenu" :items="items" class="w-full" />
</UFormField> </UFormField>

View File

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

View File

@@ -1,9 +0,0 @@
<script setup lang="ts">
const tags = ref(['Vue'])
</script>
<template>
<UFormField label="Tags" required>
<UInputTags v-model="tags" placeholder="Enter tags..." />
</UFormField>
</template>

View File

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

View File

@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
const value = ref('npx nuxt module add ui') const value = ref('npx nuxi module add ui')
const copied = ref(false) const copied = ref(false)
function copy() { function copy() {

View File

@@ -1,14 +0,0 @@
<script setup lang="ts">
import { vMaska } from 'maska/vue'
</script>
<template>
<div class="flex flex-col gap-2">
<UInput v-maska="'#### #### #### ####'" placeholder="4242 4242 4242 4242" icon="i-lucide-credit-card" />
<div class="flex items-center gap-2">
<UInput v-maska="'##/##'" placeholder="MM/YY" icon="i-lucide-calendar" />
<UInput v-maska="'###'" placeholder="CVC" />
</div>
</div>
</template>

View File

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

View File

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

View File

@@ -65,7 +65,6 @@ const items = [
class="w-full justify-center" class="w-full justify-center"
:ui="{ :ui="{
viewport: 'sm:w-(--reka-navigation-menu-viewport-width)', viewport: 'sm:w-(--reka-navigation-menu-viewport-width)',
content: 'sm:w-auto',
childList: 'sm:w-96', childList: 'sm:w-96',
childLinkDescription: 'text-balance line-clamp-2' 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"> <script setup lang="ts">
import { refDebounced } from '@vueuse/core'
import type { AvatarProps } from '@nuxt/ui' import type { AvatarProps } from '@nuxt/ui'
const searchTerm = ref('') const searchTerm = ref('')
const searchTermDebounced = refDebounced(searchTerm, 200) const searchTermDebounced = refDebounced(searchTerm, 200)
const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', { const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', {
key: 'typicode-users',
params: { q: searchTermDebounced }, params: { q: searchTermDebounced },
transform: (data: { id: number, name: string }[]) => { transform: (data: { id: number, name: string }[]) => {
return data?.map(user => ({ return data?.map(user => ({

View File

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

View File

@@ -13,9 +13,7 @@ const slideover = overlay.create(LazySlideoverExample, {
}) })
async function open() { async function open() {
const instance = slideover.open() const shouldIncrement = await slideover.open()
const shouldIncrement = await instance.result
if (shouldIncrement) { if (shouldIncrement) {
count.value++ 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> </script>
<template> <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 }"> <template #account="{ item }">
<p class="text-muted mb-4"> <p class="text-muted mb-4">
{{ item.description }} {{ item.description }}

View File

@@ -1,32 +1,22 @@
<script setup lang="ts"> <script setup lang="ts">
import type { TabsItem } from '@nuxt/ui' import type { TabsItem } from '@nuxt/ui'
const route = useRoute()
const router = useRouter()
const items: TabsItem[] = [ const items: TabsItem[] = [
{ {
label: 'Account', label: 'Account'
value: 'account'
}, },
{ {
label: 'Password', label: 'Password'
value: 'password'
} }
] ]
const active = computed({ const active = ref('0')
get() {
return (route.query.tab as string) || 'account' // Note: This is for demonstration purposes only. Don't do this at home.
}, onMounted(() => {
set(tab) { setInterval(() => {
// Hash is specified here to prevent the page from scrolling to the top active.value = String((Number(active.value) + 1) % items.length)
router.push({ }, 2000)
path: '/components/tabs',
query: { tab },
hash: '#control-active-item'
})
}
}) })
</script> </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="translate-x-[calc(50%-1rem)]"
/>
</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', label: 'Raycast Extension',
description: 'Access Nuxt UI components without leaving your editor.', description: 'Access Nuxt UI components without leaving your editor.',
icon: 'i-simple-icons-raycast', icon: 'i-simple-icons-raycast',
to: 'https://www.raycast.com/HugoRCD/nuxt', to: 'https://www.raycast.com/HugoRCD/nuxt-ui',
target: '_blank' target: '_blank'
}, { }, {
label: 'Figma to Code', label: 'Figma to Code',

View File

@@ -59,7 +59,7 @@ provide('navigation', mappedNavigation)
<UApp> <UApp>
<NuxtLoadingIndicator color="#FFF" /> <NuxtLoadingIndicator color="#FFF" />
<!-- <Banner /> --> <Banner />
<Header :links="links" /> <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 type = page.value?.path.includes('components') ? 'Vue Component ' : page.value?.path.includes('composables') ? 'Vue Composable ' : ''
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
useSeoMeta({ useSeoMeta({
titleTemplate: `${prefix}%s ${suffix}- Nuxt UI ${page.value?.module === 'ui-pro' ? 'Pro' : ''} ${page.value?.framework === 'vue' ? ' for Vue' : ''}`, titleTemplate: `%s ${type}- Nuxt UI ${page.value.module === 'ui-pro' ? 'Pro' : ''} ${page.value.framework === 'vue' ? ' for Vue' : ''}`,
title, title: page.value.navigation?.title ? page.value.navigation.title : page.value.title,
ogTitle: `${prefix}${title} ${suffix}- Nuxt UI ${page.value?.module === 'ui-pro' ? 'Pro' : ''} ${page.value?.framework === 'vue' ? ' for Vue' : ''}`, ogTitle: `${page.value.navigation?.title ? page.value.navigation.title : page.value.title} ${type}- Nuxt UI ${page.value.module === 'ui-pro' ? 'Pro' : ''} ${page.value.framework === 'vue' ? ' for Vue' : ''}`,
description, description: page.value.description,
ogDescription: description ogDescription: page.value.description
}) })
if (route.path.startsWith('/components')) { if (route.path.startsWith('/components')) {

View File

@@ -1,20 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
const route = useRoute() const route = useRoute()
const colorMode = useColorMode()
const appConfig = useAppConfig()
const name = route.params.slug?.[0] 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') 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> </script>

View File

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

View File

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

View File

@@ -16,32 +16,6 @@ links:
variant: outline variant: outline
trailingIcon: i-lucide-arrow-right trailingIcon: i-lucide-arrow-right
templates: 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' - 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)." 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 icon: i-lucide-message-circle

View File

@@ -67,6 +67,17 @@ defineOgImageComponent('Docs', {
</li> </li>
</ul> </ul>
</div> </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> </UPageHero>
</UMain> </UMain>
</template> </template>

View File

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

View File

@@ -84,7 +84,7 @@ You can play with Nuxt UI components as well as your app components directly fro
Install the module to your Nuxt application with one command: Install the module to your Nuxt application with one command:
```bash [Terminal] ```bash [Terminal]
npx nuxt module add compodium npx nuxi module add compodium
``` ```
:: ::

View File

@@ -115,7 +115,7 @@ Start your project using the [nuxt/starter#ui](https://github.com/nuxt/starter/t
Create a new project locally by running the following command: Create a new project locally by running the following command:
```bash [Terminal] ```bash [Terminal]
npm create nuxt@latest -- -t ui npx nuxi init -t ui <my-app>
``` ```
::note ::note

View File

@@ -78,22 +78,6 @@ components.d.ts
:: ::
::tip
Internally, Nuxt UI relies on custom alias to resolve the theme types. If you're using TypeScript, you should add an alias to your `tsconfig` to enable auto-completion in your `vite.config.ts`.
```json [tsconfig.node.json]
{
"compilerOptions": {
"paths": {
"#build/ui": [
"./node_modules/@nuxt/ui/.nuxt/ui"
]
}
}
}
```
::
#### Use the Nuxt UI Vue plugin in your `main.ts` #### Use the Nuxt UI Vue plugin in your `main.ts`
```ts [main.ts]{3,14} ```ts [main.ts]{3,14}
@@ -195,7 +179,7 @@ Start your project using the [nuxtlabs/nuxt-ui-vue-starter](https://github.com/n
Create a new project locally by running the following command: Create a new project locally by running the following command:
```bash [Terminal] ```bash [Terminal]
npm create nuxt@latest -- -t github:nuxtlabs/nuxt-ui-vue-starter npx nuxi init -t github:nuxtlabs/nuxt-ui-vue-starter <my-app>
``` ```
::note ::note

View File

@@ -504,7 +504,7 @@ const count = ref(0)
</script> </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 ```diff
<script setup lang="ts"> <script setup lang="ts">
@@ -523,12 +523,10 @@ import { ModalExampleComponent } from '#components'
- }) - })
- } - }
+ async function openModal() { + async function openModal() {
+ const instance = modal.open(ModalExampleComponent, { + const result = await modal.open(ModalExampleComponent, {
+ count: count.value + count: count.value
+ }) + })
+ +
+ const result = await instance.result
+
+ if (result) { + if (result) {
+ toast.add({ title: 'Success!' }) + 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 ### Extend colors
::framework-only ::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-muted: var(--ui-border-muted);
--border-color-accented: var(--ui-border-accented); --border-color-accented: var(--ui-border-accented);
--border-color-inverted: var(--ui-border-inverted); --border-color-inverted: var(--ui-border-inverted);
--border-color-bg: var(--ui-bg);
--ring-color-default: var(--ui-border); --ring-color-default: var(--ui-border);
--ring-color-muted: var(--ui-border-muted); --ring-color-muted: var(--ui-border-muted);
--ring-color-accented: var(--ui-border-accented); --ring-color-accented: var(--ui-border-accented);
--ring-color-inverted: var(--ui-border-inverted); --ring-color-inverted: var(--ui-border-inverted);
--ring-color-bg: var(--ui-bg); --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-default: var(--ui-border);
--divide-color-muted: var(--ui-border-muted); --divide-color-muted: var(--ui-border-muted);
--divide-color-accented: var(--ui-border-accented); --divide-color-accented: var(--ui-border-accented);
--divide-color-inverted: var(--ui-border-inverted); --divide-color-inverted: var(--ui-border-inverted);
--divide-color-bg: var(--ui-bg);
--outline-color-default: var(--ui-border); --outline-color-default: var(--ui-border);
--outline-color-inverted: var(--ui-border-inverted); --outline-color-inverted: var(--ui-border-inverted);
--stroke-color-default: var(--ui-border); --stroke-color-default: var(--ui-border);
@@ -977,7 +966,7 @@ export default {
```vue [src/runtime/components/Card.vue] ```vue [src/runtime/components/Card.vue]
<template> <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 })"> <div :class="ui.header({ class: props.ui?.header })">
<slot name="header" /> <slot name="header" />
</div> </div>

View File

@@ -60,7 +60,7 @@ import { fr } from '@nuxt/ui-pro/locale'
### Custom locale ### Custom locale
You can create your own locale using the `defineLocale` composable: You also have the option to add your own locale using `defineLocale`:
::module-only ::module-only
@@ -125,65 +125,6 @@ Look at the `code` parameter, there you need to pass the iso code of the languag
:: ::
### Extend locale :badge{label="Soon" class="align-text-top"}
You can customize an existing locale by overriding its `messages` or `code` using the `extendLocale` composable:
::module-only
#ui
:::div
```vue [app.vue]
<script setup lang="ts">
import { en } from '@nuxt/ui/locale'
const locale = extendLocale(en, {
code: 'en-GB',
messages: {
commandPalette: {
placeholder: 'Search a component...'
}
}
})
</script>
<template>
<UApp :locale="locale">
<NuxtPage />
</UApp>
</template>
```
:::
#ui-pro
:::div
```vue [app.vue]
<script setup lang="ts">
import { en } from '@nuxt/ui-pro/locale'
const locale = extendLocale(en, {
code: 'en-GB',
messages: {
commandPalette: {
placeholder: 'Search a component...'
}
}
})
</script>
<template>
<UApp :locale="locale">
<NuxtPage />
</UApp>
</template>
```
:::
::
### Dynamic locale ### Dynamic locale
To dynamically switch between languages, you can use the [Nuxt I18n](https://i18n.nuxtjs.org/) module. To dynamically switch between languages, you can use the [Nuxt I18n](https://i18n.nuxtjs.org/) module.

View File

@@ -60,7 +60,7 @@ import { fr } from '@nuxt/ui-pro/locale'
### Custom locale ### Custom locale
You can create your own locale using the `defineLocale` composable: You also have the option to add your locale using `defineLocale`:
::module-only ::module-only
@@ -127,67 +127,6 @@ Look at the `code` parameter, there you need to pass the iso code of the languag
:: ::
### Extend locale :badge{label="Soon" class="align-text-top"}
You can customize an existing locale by overriding its `messages` or `code` using the `extendLocale` composable:
::module-only
#ui
:::div
```vue [App.vue]
<script setup lang="ts">
import { en } from '@nuxt/ui/locale'
import { extendLocale } from '@nuxt/ui/composables/defineLocale.js'
const locale = extendLocale(en, {
code: 'en-GB',
messages: {
commandPalette: {
placeholder: 'Search a component...'
}
}
})
</script>
<template>
<UApp :locale="locale">
<RouterView />
</UApp>
</template>
```
:::
#ui-pro
:::div
```vue [App.vue]
<script setup lang="ts">
import { en } from '@nuxt/ui-pro/locale'
import { extendLocale } from '@nuxt/ui/composables/defineLocale.js'
const locale = extendLocale(en, {
code: 'en-GB',
messages: {
commandPalette: {
placeholder: 'Search a component...'
}
}
})
</script>
<template>
<UApp :locale="locale">
<RouterView />
</UApp>
</template>
```
:::
::
### Dynamic locale ### Dynamic locale
To dynamically switch between languages, you can use the [Vue I18n](https://vue-i18n.intlify.dev/) plugin. To dynamically switch between languages, you can use the [Vue I18n](https://vue-i18n.intlify.dev/) plugin.

View File

@@ -16,7 +16,7 @@ Here's an overview of the key directories and files in the Nuxt UI project struc
### Documentation ### 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 ```bash
├── app/ ├── app/
@@ -225,7 +225,7 @@ pnpm run test:vue # for Vue
``` ```
::tip ::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 ### Commit Conventions

View File

@@ -19,7 +19,6 @@ defineShortcuts({
</script> </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. - 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. - 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 #### 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 - `ctrl`: Represents `Ctrl` on all platforms
- `shift`: Used for alphabetic keys when Shift is required - `shift`: Used for alphabetic keys when Shift is required

View File

@@ -1,6 +1,6 @@
--- ---
title: useOverlay title: useOverlay
description: 'A composable to programmatically control overlays.' description: "A composable to programmatically control overlays."
--- ---
## Usage ## Usage
@@ -9,11 +9,9 @@ Use the auto-imported `useOverlay` composable to programmatically control [Modal
```vue ```vue
<script setup lang="ts"> <script setup lang="ts">
import { LazyModalExample } from '#components'
const overlay = useOverlay() const overlay = useOverlay()
const modal = overlay.create(LazyModalExample) const modal = overlay.create(MyModal)
async function openModal() { async function openModal() {
modal.open() modal.open()
@@ -24,80 +22,71 @@ async function openModal() {
- The `useOverlay` composable is created using `createSharedComposable`, ensuring that the same overlay state is shared across your entire application. - The `useOverlay` composable is created using `createSharedComposable`, ensuring that the same overlay state is shared across your entire application.
::note ::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 ## API
### `create(component: T, options: OverlayOptions): OverlayInstance` ### `create(component: T, options: OverlayOptions): OverlayInstance`
Create an overlay, and return a factory instance. Creates an overlay, and returns its instance
- Parameters: - Parameters:
- `component`: The overlay component. - `component`: The overlay component
- `options`: - `options` The overlay options
- `defaultOpen?: boolean` Open the overlay immediately after being created. Defaults to `false`. - `defaultOpen?: boolean` Opens the overlay immediately after being created `default: false`
- `props?: ComponentProps`: An optional object of props to pass to the rendered component. - `props?: ComponentProps`: An optional object of props to pass to the rendered component.
- `destroyOnClose?: boolean` Removes the overlay from memory when closed. Defaults to `false`. - `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>`
Open an overlay by its `id`. Opens the overlay using its `id`
- Parameters: - Parameters:
- `id`: The identifier of the overlay. - `id`: The identifier of the overlay
- `props`: An optional object of props to pass to the rendered component. - `props`: An optional object of props to pass to the rendered component.
### `close(id: symbol, value?: any): void` ### `close(id: symbol, value?: any): void`
Close an overlay by its `id`. Close an overlay using its `id`
- Parameters: - Parameters:
- `id`: The identifier of the overlay. - `id`: The identifier of the overlay
- `value`: A value to resolve the overlay promise with. - `value`: A value to resolve the overlay promise with
### `patch(id: symbol, props: ComponentProps<T>): void` ### `patch(id: symbol, props: ComponentProps<T>): void`
Update an overlay by its `id`. Update an overlay using its `id`
- Parameters: - Parameters:
- `id`: The identifier of the overlay. - `id`: The identifier of the overlay
- `props`: An object of props to update on the rendered component. - `props`: An object of props to update on the rendered component.
### `unmount(id: symbol): void` ### `unmount(id: symbol): void`
Remove an overlay from the DOM by its `id`. Removes the overlay from the DOM using its `id`
- Parameters: - Parameters:
- `id`: The identifier of the overlay. - `id`: The identifier of the overlay
### `isOpen(id: symbol): boolean`
Check if an overlay is open using its `id`.
- Parameters:
- `id`: The identifier of the overlay.
### `overlays: Overlay[]` ### `overlays: Overlay[]`
In-memory list of all overlays that were created. In-memory list of overlays that were created
## Instance API ## Overlay Instance API
### `open(props?: ComponentProps<T>): Promise<OpenedOverlay<T>>` ### `open(props?: ComponentProps<T>): Promise<any>`
Open the overlay. Opens the overlay
- Parameters: - Parameters:
- `props`: An optional object of props to pass to the rendered component. - `props`: An optional object of props to pass to the rendered component.
```vue ```vue
<script setup lang="ts"> <script setup lang="ts">
import { LazyModalExample } from '#components'
const overlay = useOverlay() const overlay = useOverlay()
const modal = overlay.create(LazyModalExample) const modal = overlay.create(MyModalContent)
function openModal() { function openModal() {
modal.open({ modal.open({
@@ -109,25 +98,23 @@ function openModal() {
### `close(value?: any): void` ### `close(value?: any): void`
Close the overlay. Close the overlay
- Parameters: - Parameters:
- `value`: A value to resolve the overlay promise with. - `value`: A value to resolve the overlay promise with
### `patch(props: ComponentProps<T>)` ### `patch(props: ComponentProps<T>)`
Update the props of the overlay. Updates the props of the overlay.
- Parameters: - Parameters:
- `props`: An object of props to update on the rendered component. - `props`: An object of props to update on the rendered component.
```vue ```vue
<script setup lang="ts"> <script setup lang="ts">
import { LazyModalExample } from '#components'
const overlay = useOverlay() const overlay = useOverlay()
const modal = overlay.create(LazyModalExample, { const modal = overlay.create(MyModal, {
title: 'Welcome' title: 'Welcome'
}) })
@@ -147,58 +134,33 @@ Here's a complete example of how to use the `useOverlay` composable:
```vue ```vue
<script setup lang="ts"> <script setup lang="ts">
import { ModalA, ModalB, SlideoverA } from '#components'
const overlay = useOverlay() const overlay = useOverlay()
// Create with default props // Create with default props
const modalA = overlay.create(ModalA, { title: 'Welcome' }) const modalA = overlay.create(ModalA, { title: 'Welcome' })
const modalB = overlay.create(ModalB) const modalB = overlay.create(modalB)
const slideoverA = overlay.create(SlideoverA) const slideoverA = overlay.create(SlideoverA)
const openModalA = () => { const openModalA = () => {
// Open modalA, but override the title prop // Open Modal A, but override the title prop
modalA.open({ title: 'Hello' }) modalA.open({ title: 'Hello' })
} }
const openModalB = async () => { const openModalB = async () => {
// Open modalB, and wait for its result // Open modalB, and wait for its result
const modalBInstance = modalB.open() const input = await modalB.open()
const input = await modalBInstance.result // Pass the result from modalB to the slideover, and open it.
// Pass the result from modalB to the slideover, and open it
slideoverA.open({ input }) slideoverA.open({ input })
} }
</script> </script>
<template> <template>
<button @click="openModalA">Open Modal</button> <div>
<button @click="openModal">Open Modal</button>
</div>
</template> </template>
``` ```
In this example, we're using the `useOverlay` composable to control multiple modals and slideovers. In this example, we're using the `useOverlay` composable to control multiple modals and slideovers.
## Caveats
### Provide / Inject
When opening overlays programmatically (e.g. modals, slideovers, etc), the overlay component can only access injected values from the component containing `UApp` (typically `app.vue` or layout components). This is because overlays are mounted outside of the page context by the `UApp` component.
As such, using `provide()` in pages or parent components isn't supported directly. To pass provided values to overlays, the recommended approach is to use props instead:
```vue
<script setup lang="ts">
import { LazyModalExample } from '#components'
const providedValue = inject('valueProvidedInPage')
const modal = overlay.create(LazyModalExample, {
props: {
providedValue,
otherData: someValue
}
})
</script>
```

View File

@@ -23,8 +23,6 @@ Use the `items` prop as an array of objects with the following properties:
- `value?: string`{lang="ts-type"} - `value?: string`{lang="ts-type"}
- `disabled?: boolean`{lang="ts-type"} - `disabled?: boolean`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot) - [`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 ::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"} - `label?: string`{lang="ts-type"}
- `icon?: string`{lang="ts-type"} - `icon?: string`{lang="ts-type"}
- `avatar?: AvatarProps`{lang="ts-type"} - `avatar?: AvatarProps`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `class?: any`{lang="ts-type"} - `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. 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 ### 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 ::component-code
--- ---
props: props:
loading: true loading: true
loadingIcon: 'i-lucide-loader' loadingIcon: 'i-lucide-repeat-2'
slots: slots:
default: Button 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`: 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 ::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"} - `description?: string`{lang="ts-type"}
- [`value?: string`{lang="ts-type"}](#value-key) - [`value?: string`{lang="ts-type"}](#value-key)
- `disabled?: boolean`{lang="ts-type"} - `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 ::component-code
--- ---
@@ -201,7 +199,6 @@ items:
variant: variant:
- list - list
- card - card
- table
props: props:
color: 'primary' color: 'primary'
variant: 'card' variant: 'card'
@@ -232,7 +229,6 @@ items:
variant: variant:
- list - list
- card - card
- table
props: props:
size: 'xl' size: 'xl'
variant: 'list' variant: 'list'
@@ -263,7 +259,6 @@ items:
variant: variant:
- list - list
- card - card
- table
props: props:
orientation: 'horizontal' orientation: 'horizontal'
variant: 'list' variant: 'list'
@@ -298,7 +293,6 @@ items:
variant: variant:
- list - list
- card - card
- table
props: props:
indicator: 'end' indicator: 'end'
variant: 'card' variant: 'card'

View File

@@ -7,9 +7,9 @@ links:
icon: i-custom-fuse-js icon: i-custom-fuse-js
to: https://fusejs.io/ to: https://fusejs.io/
target: _blank target: _blank
- label: Listbox - label: Combobox
icon: i-custom-reka-ui icon: i-custom-reka-ui
to: https://reka-ui.com/docs/components/listbox to: https://reka-ui.com/docs/components/combobox
- label: GitHub - label: GitHub
icon: i-simple-icons-github icon: i-simple-icons-github
to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/CommandPalette.vue to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/CommandPalette.vue
@@ -52,11 +52,7 @@ Each group contains an `items` array of objects that define the commands. Each i
- `loading?: boolean`{lang="ts-type"} - `loading?: boolean`{lang="ts-type"}
- `disabled?: boolean`{lang="ts-type"} - `disabled?: boolean`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot) - [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `placeholder?: string`{lang="ts-type"} :badge{label="Soon"}
- `children?: CommandPaletteItem[]`{lang="ts-type"} :badge{label="Soon"}
- `onSelect?(e?: Event): void`{lang="ts-type"} - `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. You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
@@ -112,10 +108,6 @@ props:
--- ---
:: ::
::tip{to="#with-children-in-items"}
Each item can take a `children` array of objects with the following properties to create submenus:
::
### Multiple ### Multiple
Use the `multiple` prop to allow multiple selections. Use the `multiple` prop to allow multiple selections.
@@ -252,128 +244,6 @@ You can customize this icon globally in your `vite.config.ts` under `ui.icons.se
::: :::
:: ::
### Selected Icon
Use the `selected-icon` prop to customize the selected item [Icon](/components/icon). Defaults to `i-lucide-check`.
::component-code
---
collapse: true
hide:
- autofocus
ignore:
- groups
- modelValue
- multiple
- class
external:
- groups
- modelValue
class: '!p-0'
props:
multiple: true
autofocus: false
modelValue:
- label: 'Benjamin Canac'
suffix: 'benjamincanac'
avatar:
src: 'https://github.com/benjamincanac.png'
selectedIcon: 'i-lucide-circle-check'
groups:
- id: 'users'
label: 'Users'
items:
- label: 'Benjamin Canac'
suffix: 'benjamincanac'
avatar:
src: 'https://github.com/benjamincanac.png'
- label: 'Sylvain Marroufin'
suffix: 'smarroufin'
avatar:
src: 'https://github.com/smarroufin.png'
- label: 'Sébastien Chopin'
suffix: 'atinux'
avatar:
src: 'https://github.com/atinux.png'
- label: 'Romain Hamel'
suffix: 'romhml'
avatar:
src: 'https://github.com/romhml.png'
- label: 'Haytham A. Salama'
suffix: 'Haythamasalama'
avatar:
src: 'https://github.com/Haythamasalama.png'
- label: 'Daniel Roe'
suffix: 'danielroe'
avatar:
src: 'https://github.com/danielroe.png'
- label: 'Neil Richter'
suffix: 'noook'
avatar:
src: 'https://github.com/noook.png'
class: 'flex-1'
---
::
::framework-only
#nuxt
:::tip{to="/getting-started/icons/nuxt#theme"}
You can customize this icon globally in your `app.config.ts` under `ui.icons.check` key.
:::
#vue
:::tip{to="/getting-started/icons/vue#theme"}
You can customize this icon globally in your `vite.config.ts` under `ui.icons.check` key.
:::
::
### Trailing Icon :badge{label="Soon" class="align-text-top"}
Use the `trailing-icon` prop to customize the trailing [Icon](/components/icon) when an item has children. Defaults to `i-lucide-chevron-right`.
::component-code
---
collapse: true
prettier: true
hide:
- autofocus
ignore:
- groups
- class
external:
- groups
class: '!p-0'
props:
autofocus: false
trailingIcon: 'i-lucide-arrow-right'
groups:
- id: 'actions'
items:
- label: 'Share'
icon: 'i-lucide-share'
children:
- label: 'Email'
icon: 'i-lucide-mail'
- label: 'Copy'
icon: 'i-lucide-copy'
- label: 'Link'
icon: 'i-lucide-link'
class: 'flex-1'
---
::
::framework-only
#nuxt
:::tip{to="/getting-started/icons/nuxt#theme"}
You can customize this icon globally in your `app.config.ts` under `ui.icons.chevronRight` key.
:::
#vue
:::tip{to="/getting-started/icons/vue#theme"}
You can customize this icon globally in your `vite.config.ts` under `ui.icons.chevronRight` key.
:::
::
### Loading ### Loading
Use the `loading` prop to show a loading icon on the CommandPalette. Use the `loading` prop to show a loading icon on the CommandPalette.
@@ -407,7 +277,7 @@ props:
### Loading Icon ### 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 ::component-code
--- ---
@@ -423,7 +293,7 @@ class: '!p-0'
props: props:
autofocus: false autofocus: false
loading: true loading: true
loadingIcon: 'i-lucide-loader' loadingIcon: 'i-lucide-repeat-2'
groups: groups:
- id: 'apps' - id: 'apps'
items: items:
@@ -449,6 +319,37 @@ You can customize this icon globally in your `vite.config.ts` under `ui.icons.lo
::: :::
:: ::
### Disabled
Use the `disabled` prop to disable the CommandPalette.
::component-code
---
collapse: true
hide:
- autofocus
ignore:
- groups
- class
external:
- groups
class: '!p-0'
props:
autofocus: false
disabled: true
groups:
- id: 'apps'
items:
- label: 'Calendar'
icon: 'i-lucide-calendar'
- label: 'Music'
icon: 'i-lucide-music'
- label: 'Maps'
icon: 'i-lucide-map'
class: 'flex-1'
---
::
### Close ### Close
Use the `close` prop to display a [Button](/components/button) to dismiss the CommandPalette. Use the `close` prop to display a [Button](/components/button) to dismiss the CommandPalette.
@@ -565,124 +466,6 @@ You can customize this icon globally in your `vite.config.ts` under `ui.icons.cl
::: :::
:: ::
### Back :badge{label="Soon" class="align-text-top"}
Use the `back` prop to customize or hide the back button (with `false` value) displayed when navigating into a submenu.
You can pass any property from the [Button](/components/button) component to customize it.
::component-code
---
collapse: true
prettier: true
hide:
- autofocus
ignore:
- back.color
- groups
- class
external:
- groups
class: '!p-0'
props:
autofocus: false
back:
color: primary
groups:
- id: 'actions'
items:
- label: 'Share'
icon: 'i-lucide-share'
children:
- label: 'Email'
icon: 'i-lucide-mail'
- label: 'Copy'
icon: 'i-lucide-copy'
- label: 'Link'
icon: 'i-lucide-link'
class: 'flex-1'
---
::
### Back Icon :badge{label="Soon" class="align-text-top"}
Use the `back-icon` prop to customize the back button [Icon](/components/icon). Defaults to `i-lucide-arrow-left`.
::component-code
---
collapse: true
hide:
- autofocus
ignore:
- class
- groups
- back
external:
- groups
class: '!p-0'
props:
autofocus: false
back: true
backIcon: 'i-lucide-house'
groups:
- id: 'actions'
items:
- label: 'Share'
icon: 'i-lucide-share'
children:
- label: 'Email'
icon: 'i-lucide-mail'
- label: 'Copy'
icon: 'i-lucide-copy'
- label: 'Link'
icon: 'i-lucide-link'
class: 'flex-1'
---
::
::framework-only
#nuxt
:::tip{to="/getting-started/icons/nuxt#theme"}
You can customize this icon globally in your `app.config.ts` under `ui.icons.arrowLeft` key.
:::
#vue
:::tip{to="/getting-started/icons/vue#theme"}
You can customize this icon globally in your `vite.config.ts` under `ui.icons.arrowLeft` key.
:::
::
### Disabled
Use the `disabled` prop to disable the CommandPalette.
::component-code
---
collapse: true
hide:
- autofocus
ignore:
- groups
- class
external:
- groups
class: '!p-0'
props:
autofocus: false
disabled: true
groups:
- id: 'apps'
items:
- label: 'Calendar'
icon: 'i-lucide-calendar'
- label: 'Music'
icon: 'i-lucide-music'
- label: 'Maps'
icon: 'i-lucide-map'
class: 'flex-1'
---
::
## Examples ## Examples
### Control selected item(s) ### Control selected item(s)
@@ -717,28 +500,6 @@ props:
This example uses the `@update:model-value` event to reset the search term when an item is selected. This example uses the `@update:model-value` event to reset the search term when an item is selected.
:: ::
### With children in items :badge{label="Soon" class="align-text-top"}
You can create hierarchical menus by using the `children` property in items. When an item has children, it will automatically display a chevron icon and enable navigation into a submenu.
::component-example
---
collapse: true
prettier: true
name: 'command-palette-items-children-example'
class: '!p-0'
props:
autofocus: false
---
::
::note
When navigating into a submenu:
- The search term is reset
- A back button appears in the input
- You can go back to the previous group by pressing the :kbd{value="backspace"} key
::
### With fetched items ### With fetched items
You can fetch items from an API and use them in the CommandPalette. You can fetch items from an API and use them in the CommandPalette.
@@ -895,7 +656,6 @@ You will have access to the following slots:
::component-example ::component-example
--- ---
collapse: true
name: 'command-palette-custom-slot-example' name: 'command-palette-custom-slot-example'
class: '!p-0' class: '!p-0'
props: props:

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) - [`color?: "error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"`{lang="ts-type"}](#with-color-items)
- [`checked?: boolean`{lang="ts-type"}](#with-checkbox-items) - [`checked?: boolean`{lang="ts-type"}](#with-checkbox-items)
- `disabled?: boolean`{lang="ts-type"} - `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot) - [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `onSelect?(e: Event): void`{lang="ts-type"} - `onSelect?(e: Event): void`{lang="ts-type"}
- [`onUpdateChecked?(checked: boolean): void`{lang="ts-type"}](#with-checkbox-items) - [`onUpdateChecked?(checked: boolean): void`{lang="ts-type"}](#with-checkbox-items)
- `children?: ContextMenuItem[] | ContextMenuItem[][]`{lang="ts-type"} - `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. 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. 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. 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. 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 ### Responsive drawer
You can render a [Modal](/components/modal) component on desktop and a Drawer on mobile for example. 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) - [`color?: "error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"`{lang="ts-type"}](#with-color-items)
- [`checked?: boolean`{lang="ts-type"}](#with-checkbox-items) - [`checked?: boolean`{lang="ts-type"}](#with-checkbox-items)
- `disabled?: boolean`{lang="ts-type"} - `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot) - [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `onSelect?(e: Event): void`{lang="ts-type"} - `onSelect?(e: Event): void`{lang="ts-type"}
- [`onUpdateChecked?(checked: boolean): void`{lang="ts-type"}](#with-checkbox-items) - [`onUpdateChecked?(checked: boolean): void`{lang="ts-type"}](#with-checkbox-items)
- `children?: DropdownMenuItem[] | DropdownMenuItem[][]`{lang="ts-type"} - `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. 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. 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 ::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**. **No validation library is included** by default, ensure you **install the one you need**.
:: ::
::tabs{class="gap-0"} ::tabs
::component-example{label="Valibot"} ::component-example{label="Valibot"}
--- ---
name: 'form-example-valibot' name: 'form-example-valibot'
@@ -98,7 +98,6 @@ The Form component automatically triggers validation when an input emits an `inp
- Validation on `input` occurs **as you type**. - Validation on `input` occurs **as you type**.
- Validation on `change` occurs when you **commit to a value**. - Validation on `change` occurs when you **commit to a value**.
- Validation on `blur` happens when an input **loses focus**. - Validation on `blur` happens when an input **loses focus**.
- Validation on `error-input` happens when as you type on an input with an error.
You can control when validation happens this using the `validate-on` prop. You can control when validation happens this using the `validate-on` prop.

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) - [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items)
- `disabled?: boolean`{lang="ts-type"} - `disabled?: boolean`{lang="ts-type"}
- `onSelect?(e: Event): void`{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 ::component-code
--- ---
@@ -135,7 +133,7 @@ props:
### Multiple ### Multiple
Use the `multiple` prop to allow multiple selections, the selected items will be displayed as tags. Use the `multiple` prop to allow multiple selections, the selected items will be displayed as badges.
::component-code ::component-code
--- ---
@@ -166,7 +164,7 @@ Ensure to pass an array to the `default-value` prop or the `v-model` directive.
### Delete Icon ### Delete Icon
With `multiple`, use the `delete-icon` prop to customize the delete [Icon](/components/icon) in the tags. Defaults to `i-lucide-x`. With `multiple`, use the `delete-icon` prop to customize the delete [Icon](/components/icon) in the badges. Defaults to `i-lucide-x`.
::component-code ::component-code
--- ---
@@ -518,7 +516,7 @@ props:
### Loading Icon ### 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 ::component-code
--- ---
@@ -532,7 +530,7 @@ external:
props: props:
modelValue: 'Backlog' modelValue: 'Backlog'
loading: true loading: true
loadingIcon: 'i-lucide-loader' loadingIcon: 'i-lucide-repeat-2'
items: items:
- Backlog - Backlog
- Todo - 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. You can use the `icon` property to display an [Icon](/components/icon) inside the items.
@@ -782,14 +780,6 @@ name: 'input-menu-countries-example'
:component-emits :component-emits
### Expose
When accessing the component via a template ref, you can use the following:
| Name | Type |
| ---- | ---- |
| `inputRef`{lang="ts-type"} | `Ref<InstanceType<typeof ComboboxTrigger> \| null>`{lang="ts-type"} |
## Theme ## Theme
:component-theme :component-theme

View File

@@ -1,11 +1,11 @@
--- ---
title: InputNumber title: InputNumber
description: An input for numerical values with a customizable range. description: Input numerical values with a customizable range.
category: form category: form
links: links:
- label: NumberField - label: Number Field
icon: i-custom-reka-ui 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 - label: GitHub
icon: i-simple-icons-github icon: i-simple-icons-github
to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/InputNumber.vue to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/InputNumber.vue
@@ -287,8 +287,8 @@ name: 'input-number-slots-example'
When accessing the component via a template ref, you can use the following: When accessing the component via a template ref, you can use the following:
| Name | Type | | Name | Type |
| -------------------------- | ----------------------------------------------- | |----------------------------|-------------------------------------------------|
| `inputRef`{lang="ts-type"} | `Ref<InstanceType<typeof NumberFieldInput> \| null>`{lang="ts-type"} | | `inputRef`{lang="ts-type"} | `Ref<HTMLInputElement \| null>`{lang="ts-type"} |
## Theme ## Theme

View File

@@ -1,285 +0,0 @@
---
title: InputTags
description: An input element that displays interactive tags.
category: form
links:
- label: InputTags
icon: i-custom-reka-ui
to: https://reka-ui.com/docs/components/tags-input
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/InputTags.vue
navigation.badge: Soon
---
## Usage
Use the `v-model` directive to control the value of the InputTags.
::component-code
---
prettier: true
ignore:
- modelValue
external:
- modelValue
props:
modelValue: ['Vue']
---
::
Use the `default-value` prop to set the initial value when you do not need to control its state.
::component-code
---
prettier: true
ignore:
- defaultValue
props:
defaultValue: ['Vue']
---
::
### Placeholder
Use the `placeholder` prop to set a placeholder text.
::component-code
---
props:
placeholder: 'Enter tags...'
---
::
### Color
Use the `color` prop to change the ring color when the InputTags is focused.
::component-code
---
prettier: true
ignore:
- modelValue
external:
- modelValue
props:
modelValue: ['Vue']
color: neutral
highlight: true
---
::
::note
The `highlight` prop is used here to show the focus state. It's used internally when a validation error occurs.
::
### Variants
Use the `variant` prop to change the appearance of the InputTags.
::component-code
---
prettier: true
ignore:
- modelValue
external:
- modelValue
props:
modelValue: ['Vue']
variant: subtle
color: neutral
highlight: false
---
::
### Sizes
Use the `size` prop to adjust the size of the InputTags.
::component-code
---
prettier: true
ignore:
- modelValue
external:
- modelValue
props:
modelValue: ['Vue']
size: xl
---
::
### Icon
Use the `icon` prop to show an [Icon](/components/icon) inside the InputTags.
::component-code
---
prettier: true
ignore:
- modelValue
external:
- modelValue
props:
modelValue: ['Vue']
icon: 'i-lucide-search'
size: md
variant: outline
---
::
::note
Use the `leading` and `trailing` props to set the icon position or the `leading-icon` and `trailing-icon` props to set a different icon for each position.
::
### Avatar
Use the `avatar` prop to show an [Avatar](/components/avatar) inside the InputTags.
::component-code
---
prettier: true
ignore:
- modelValue
external:
- modelValue
props:
modelValue: ['Vue']
avatar:
src: 'https://github.com/vuejs.png'
size: md
variant: outline
---
::
### Delete Icon
Use the `delete-icon` prop to customize the delete [Icon](/components/icon) in the tags. Defaults to `i-lucide-x`.
::component-code
---
prettier: true
ignore:
- modelValue
external:
- modelValue
props:
modelValue: ['Vue']
deleteIcon: 'i-lucide-trash'
---
::
::framework-only
#nuxt
:::tip{to="/getting-started/icons/nuxt#theme"}
You can customize this icon globally in your `app.config.ts` under `ui.icons.close` key.
:::
#vue
:::tip{to="/getting-started/icons/vue#theme"}
You can customize this icon globally in your `vite.config.ts` under `ui.icons.close` key.
:::
::
### Loading
Use the `loading` prop to show a loading icon on the InputTags.
::component-code
---
prettier: true
ignore:
- modelValue
external:
- modelValue
props:
modelValue: ['Vue']
loading: true
trailing: false
---
::
### Loading Icon
Use the `loading-icon` prop to customize the loading icon. Defaults to `i-lucide-loader-circle`.
::component-code
---
prettier: true
ignore:
- modelValue
external:
- modelValue
props:
modelValue: ['Vue']
loading: true
loadingIcon: 'i-lucide-loader'
---
::
::framework-only
#nuxt
:::tip{to="/getting-started/icons/nuxt#theme"}
You can customize this icon globally in your `app.config.ts` under `ui.icons.loading` key.
:::
#vue
:::tip{to="/getting-started/icons/vue#theme"}
You can customize this icon globally in your `vite.config.ts` under `ui.icons.loading` key.
:::
::
### Disabled
Use the `disabled` prop to disable the InputTags.
::component-code
---
prettier: true
ignore:
- modelValue
external:
- modelValue
props:
modelValue: ['Vue']
disabled: true
---
::
## Examples
### Within a FormField
You can use the InputTags within a [FormField](/components/form-field) component to display a label, help text, required indicator, etc.
::component-example
---
name: 'input-tags-form-field-example'
---
::
## API
### Props
:component-props
### Slots
:component-slots
### Emits
:component-emits
### Expose
When accessing the component via a template ref, you can use the following:
| Name | Type |
| -------------------------- | ----------------------------------------------- |
| `inputRef`{lang="ts-type"} | `Ref<InstanceType<typeof TagsInputInput> \| null>`{lang="ts-type"} |
## Theme
:component-theme

View File

@@ -172,7 +172,7 @@ props:
### Loading Icon ### 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 ::component-code
--- ---
@@ -180,7 +180,7 @@ ignore:
- placeholder - placeholder
props: props:
loading: true loading: true
loadingIcon: 'i-lucide-loader' loadingIcon: 'i-lucide-repeat-2'
placeholder: 'Search...' placeholder: 'Search...'
--- ---
:: ::
@@ -278,16 +278,6 @@ name: 'input-kbd-example'
This example uses the `defineShortcuts` composable to focus the Input when the :kbd{value="/"} key is pressed. This example uses the `defineShortcuts` composable to focus the Input when the :kbd{value="/"} key is pressed.
:: ::
### With mask
There's no built-in support for masks, but you can use libraries like [maska](https://github.com/beholdr/maska) to mask the Input.
::component-example
---
name: 'input-mask-example'
---
::
### With floating label ### With floating label
You can use the `#default` slot to add a floating label to the Input. You can use the `#default` slot to add a floating label to the Input.

View File

@@ -1,11 +1,13 @@
--- ---
title: Kbd title: Keyboard Key
description: A kbd element to display a keyboard key. description: A kbd element to display a keyboard key.
category: element category: element
links: links:
- label: GitHub - label: GitHub
icon: i-simple-icons-github icon: i-simple-icons-github
to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/Kbd.vue to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/Kbd.vue
navigation:
title: Kbd
--- ---
## Usage ## 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 ::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. 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. 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 ### 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 ::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. 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 ::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"} - `icon?: string`{lang="ts-type"}
- `avatar?: AvatarProps`{lang="ts-type"} - `avatar?: AvatarProps`{lang="ts-type"}
- `badge?: string | number | BadgeProps`{lang="ts-type"} - `badge?: string | number | BadgeProps`{lang="ts-type"}
- `tooltip?: TooltipProps`{lang="ts-type"}
- `trailingIcon?: string`{lang="ts-type"} - `trailingIcon?: string`{lang="ts-type"}
- `type?: 'label' | 'trigger' | 'link'`{lang="ts-type"} - `type?: 'label' | 'link'`{lang="ts-type"}
- `defaultOpen?: boolean`{lang="ts-type"}
- `open?: boolean`{lang="ts-type"}
- `value?: string`{lang="ts-type"} - `value?: string`{lang="ts-type"}
- `disabled?: boolean`{lang="ts-type"} - `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot) - [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `onSelect?(e: Event): void`{lang="ts-type"} - `onSelect?(e: Event): void`{lang="ts-type"}
- `children?: NavigationMenuChildItem[]`{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. 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` - `label: string`
- `description?: string` - `description?: string`
- `icon?: string` - `icon?: string`
- `onSelect?(e: Event): void`
- `class?: any` - `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. Use the `orientation` prop to change the orientation of the NavigationMenu.
::note ::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 ::component-code
@@ -241,113 +237,6 @@ props:
Groups will be spaced when orientation is `horizontal` and separated when orientation is `vertical`. 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 ### Highlight
Use the `highlight` prop to display a highlighted border for the active item. 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 ## 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 ### 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. 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 ::component-example
--- ---
collapse: true
name: 'navigation-menu-content-slot-example' name: 'navigation-menu-content-slot-example'
--- ---
:: ::

View File

@@ -3,9 +3,6 @@ title: PinInput
description: An input element to enter a pin. description: An input element to enter a pin.
category: form category: form
links: links:
- label: PinInput
icon: i-custom-reka-ui
to: https://reka-ui.com/docs/components/pin-input
- label: GitHub - label: GitHub
icon: i-simple-icons-github icon: i-simple-icons-github
to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/PinInput.vue to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/PinInput.vue
@@ -180,8 +177,6 @@ props:
:component-emits :component-emits
### Expose
When accessing the component via a template ref, you can use the following: When accessing the component via a template ref, you can use the following:
| Name | Type | | Name | Type |

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"}. 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. 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 ## API
### Props ### Props

View File

@@ -46,8 +46,6 @@ You can also pass an array of objects with the following properties:
- `description?: string`{lang="ts-type"} - `description?: string`{lang="ts-type"}
- [`value?: string`{lang="ts-type"}](#value-key) - [`value?: string`{lang="ts-type"}](#value-key)
- `disabled?: boolean`{lang="ts-type"} - `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 ::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) - [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items)
- `disabled?: boolean`{lang="ts-type"} - `disabled?: boolean`{lang="ts-type"}
- `onSelect?(e: Event): void`{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 ::component-code
--- ---
@@ -555,7 +553,7 @@ props:
### Loading Icon ### 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 ::component-code
--- ---
@@ -570,7 +568,7 @@ external:
props: props:
modelValue: 'Backlog' modelValue: 'Backlog'
loading: true loading: true
loadingIcon: 'i-lucide-loader' loadingIcon: 'i-lucide-repeat-2'
items: items:
- Backlog - Backlog
- Todo - 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. You can use the `icon` property to display an [Icon](/components/icon) inside the items.
@@ -815,14 +813,6 @@ name: 'select-menu-countries-example'
:component-emits :component-emits
### Expose
When accessing the component via a template ref, you can use the following:
| Name | Type |
| ---- | ---- |
| `triggerRef`{lang="ts-type"} | `Ref<InstanceType<typeof ComboboxTrigger> \| null>`{lang="ts-type"} |
## Theme ## Theme
:component-theme :component-theme

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) - [`avatar?: AvatarProps`{lang="ts-type"}](#with-avatar-in-items)
- [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items) - [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items)
- `disabled?: boolean`{lang="ts-type"} - `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 ::component-code
--- ---
@@ -507,7 +505,7 @@ props:
### Loading Icon ### 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 ::component-code
--- ---
@@ -522,7 +520,7 @@ external:
props: props:
modelValue: 'Backlog' modelValue: 'Backlog'
loading: true loading: true
loadingIcon: 'i-lucide-loader' loadingIcon: 'i-lucide-repeat-2'
items: items:
- Backlog - Backlog
- Todo - 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. You can use the `icon` property to display an [Icon](/components/icon) inside the items.
@@ -709,14 +707,6 @@ collapse: true
:component-emits :component-emits
### Expose
When accessing the component via a template ref, you can use the following:
| Name | Type |
| ---- | ---- |
| `triggerRef`{lang="ts-type"} | `Ref<InstanceType<typeof SelectTrigger> \| null>`{lang="ts-type"} |
## Theme ## Theme
:component-theme :component-theme

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. 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. 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 ### 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 ::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. 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 ::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 ### Disabled
Use the `disabled` prop to disable the Slider. 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"} - `value?: string | number`{lang="ts-type"}
- `disabled?: boolean`{lang="ts-type"} - `disabled?: boolean`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot) - [`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 ::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. 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"} :component-example{name="stepper-custom-slot-example"}
## API ## 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 ::component-code
--- ---
@@ -109,7 +109,7 @@ props:
### Loading Icon ### 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 ::component-code
--- ---
@@ -118,7 +118,7 @@ ignore:
- defaultValue - defaultValue
props: props:
loading: true loading: true
loadingIcon: 'i-lucide-loader' loadingIcon: 'i-lucide-repeat-2'
defaultValue: true defaultValue: true
label: Check me 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. 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 ### 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). 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"} - `value?: string | number`{lang="ts-type"}
- `disabled?: boolean`{lang="ts-type"} - `disabled?: boolean`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot) - [`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 ::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"} :component-example{name="tabs-model-value-example"}
::tip
You can also pass the `value` of one of the items if provided.
::
### With content slot ### With content slot
Use the `#content` slot to customize the content of each item. 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. 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"} :component-example{name="tabs-custom-slot-example"}
## API ## API
@@ -242,14 +240,6 @@ You will have access to the following slots:
:component-emits :component-emits
### Expose
When accessing the component via a template ref, you can use the following:
| Name | Type |
| ---- | ---- |
| `triggersRef`{lang="ts-type"} | `Ref<ComponentPublicInstance[]>`{lang="ts-type"} |
## Theme ## Theme
:component-theme :component-theme

View File

@@ -194,7 +194,7 @@ props:
### Loading Icon :badge{label="New" class="align-text-top"} ### 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 ::component-code
--- ---
@@ -202,7 +202,7 @@ ignore:
- placeholder - placeholder
props: props:
loading: true loading: true
loadingIcon: 'i-lucide-loader' loadingIcon: 'i-lucide-repeat-2'
placeholder: 'Search...' placeholder: 'Search...'
rows: 1 rows: 1
--- ---

View File

@@ -1,269 +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, 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'
class: 'overflow-x-auto'
---
::
### Reverse
Use the reverse prop to reverse the direction of the Timeline.
::component-code
---
ignore:
- items
- class
- defaultValue
external:
- items
externalTypes:
- TimelineItem[]
props:
reverse: true
modelValue: 2
orientation: 'vertical'
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'
class: 'overflow-x-auto'
---
::
## 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 :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. 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 :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. 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 :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. 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"} - `children?: TreeItem[]`{lang="ts-type"}
- `onToggle?(e: Event): void`{lang="ts-type"} - `onToggle?(e: Event): void`{lang="ts-type"}
- `onSelect?(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 ::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. 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 ### With custom slot
Use the `slot` property to customize a specific item. Use the `item.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"}
::component-example ::component-example
--- ---

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