Compare commits

..

3 Commits

Author SHA1 Message Date
Benjamin Canac
723065afa7 up 2025-03-07 15:19:38 +01:00
Benjamin Canac
e67305e412 up 2025-03-07 15:11:17 +01:00
Benjamin Canac
33ed3935a3 fix(vue): stub vue-router 2025-03-07 15:00:10 +01:00
662 changed files with 27571 additions and 44401 deletions

1
.github/CODEOWNERS vendored
View File

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

View File

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

View File

@@ -5,12 +5,12 @@ body:
- type: markdown
attributes:
value: |
Before reporting a bug, please make sure that you have read through our [documentation](https://ui2.nuxt.com) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
Before reporting a bug, please make sure that you have read through our [documentation](https://ui.nuxt.com) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
- type: textarea
id: env
attributes:
label: Environment
description: You can use `npx nuxt info` to fill this section
description: You can use `npx nuxi info` to fill this section
placeholder: |
- Operating System: `Darwin`
- Node Version: `v18.16.0`

View File

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

View File

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

View File

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

View File

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

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

View File

@@ -18,7 +18,7 @@ jobs:
strategy:
matrix:
os: ${{ github.event_name == 'pull_request' && fromJSON('["ubuntu-latest"]') || fromJSON('["ubuntu-latest", "windows-latest"]') }} # macos-latest
os: [ubuntu-latest] # macos-latest, windows-latest
node: [22]
env:
@@ -50,213 +50,16 @@ jobs:
run: pnpm run typecheck
- name: Test
run: pnpm run test run
run: pnpm run test
- name: Test (vue)
run: pnpm run test:vue run
run: pnpm run test:vue
- name: Build
run: pnpm run build
- name: Build playground
run: pnpm run dev:build
- name: Build playground (vue)
run: pnpm run dev:vue:build
- name: Build vue fixture
run: pnpm run test:vue:build
- name: Publish
# Only publish preview package on ubuntu during PRs
if: matrix.os == 'ubuntu-latest'
run: pnpx pkg-pr-new publish --compact --no-template --pnpm
playground:
needs: build
runs-on: ${{ matrix.os }}
defaults:
run:
working-directory: ./playground
permissions:
contents: read
pull-requests: read
strategy:
matrix:
os: [ubuntu-latest] # macos-latest, windows-latest
node: [22]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Store commit SHA
run: |
echo "COMMIT_SHA=$(echo ${{ github.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:
needs: build
runs-on: ${{ matrix.os }}
permissions:
contents: read
pull-requests: read
strategy:
matrix:
os: [ubuntu-latest] # macos-latest, windows-latest
node: [22]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
repository: nuxtlabs/nuxt-ui-starter
- 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
- name: Typecheck
run: pnpm run typecheck
- name: Build
run: pnpm run build
starter-vue:
needs: build
runs-on: ${{ matrix.os }}
permissions:
contents: read
pull-requests: read
strategy:
matrix:
os: [ubuntu-latest] # macos-latest, windows-latest
node: [22]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
repository: nuxtlabs/nuxt-ui-vue-starter
- 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
- name: Typecheck
run: pnpm run typecheck
- name: Build
run: pnpm run build
nuxt-ui-pro:
needs: build
# Only run this job if not a fork PR (when push event or PR from same repo)
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
runs-on: ${{ matrix.os }}
permissions:
contents: read
pull-requests: read
strategy:
matrix:
os: [ubuntu-latest] # macos-latest, windows-latest
node: [22]
env:
NUXT_UI_PRO_LICENSE: ${{ secrets.NUXT_UI_PRO_LICENSE }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
repository: nuxt/ui-pro
token: ${{ secrets.NUXT_GITHUB_TOKEN }}
- 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
- name: Prepare
run: pnpm run dev:prepare
- name: Typecheck
run: pnpm run typecheck
- name: Build
run: pnpm run build

View File

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

View File

@@ -1,54 +0,0 @@
name: release
on:
push:
tags:
- 'v3*'
jobs:
publish:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest] # macos-latest, windows-latest
node: [22]
env:
NUXT_GITHUB_TOKEN: ${{ secrets.NUXT_GITHUB_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Install node
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: pnpm
- name: Install dependencies
run: pnpm install
- name: Prepare
run: pnpm run dev:prepare
- name: Lint
run: pnpm run lint
- name: Typecheck
run: pnpm run typecheck
- name: Test
run: pnpm run test run
- name: Test (vue)
run: pnpm run test:vue run
- name: Publish
run: ./scripts/release.sh
env:
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}

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
on:
workflow_dispatch:
schedule:
- cron: '30 1 * * *'
@@ -10,28 +9,15 @@ jobs:
runs-on: ubuntu-latest
permissions:
actions: write
issues: write
pull-requests: write
steps:
- uses: actions/stale@4c023f01d613e60293d8004f251a18bfb9bbd71d
- uses: actions/stale@v9
with:
days-before-pr-stale: -1
days-before-stale: 60
days-before-close: 7
stale-issue-label: 'stale'
close-issue-label: 'closed-by-bot'
close-issue-message: |
Hi! 👋
This issue has been automatically **closed** due to prolonged inactivity.
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
exempt-issue-labels: triage,v3
stale-issue-message: 'This issue is stale because it has been open for 30 days with no activity.'
stale-issue-label: stale
stale-pr-label: stale
days-before-stale: 30
days-before-close: -1

1
.npmrc
View File

@@ -1,3 +1,4 @@
shamefully-hoist=true
auto-install-peers=true
ignore-workspace-root-check=true
shell-emulator=true

View File

@@ -3,9 +3,6 @@
"commitMessage": "chore(release): v${version}",
"tagName": "v${version}"
},
"npm": {
"publish": false
},
"github": {
"release": true,
"releaseName": "v${version}",

View File

@@ -1,269 +1,5 @@
# Changelog
## [3.1.3](https://github.com/nuxt/ui/compare/v3.1.2...v3.1.3) (2025-05-26)
### ⚠ BREAKING CHANGES
* **NavigationMenu:** revert new `collapsible` field
### Features
* **locale:** add Kyrgyz language ([#4189](https://github.com/nuxt/ui/issues/4189)) ([4053047](https://github.com/nuxt/ui/commit/405304775e4b2b4e8b37a2364f3e5ee34b46036e))
* **locale:** add Lithuanian language ([#4171](https://github.com/nuxt/ui/issues/4171)) ([d86956e](https://github.com/nuxt/ui/commit/d86956e1d57482b3e98eef2d34bff13544284b0b))
* **locale:** add Malay language ([#4160](https://github.com/nuxt/ui/issues/4160)) ([c00f6e8](https://github.com/nuxt/ui/commit/c00f6e8cdfd88eeba58812b78d94a2326c13f164))
* **locale:** add Mongolian language ([#4214](https://github.com/nuxt/ui/issues/4214)) ([44ea02c](https://github.com/nuxt/ui/commit/44ea02c0d64322ef0cfda63b234369c00d3d0180))
* **Modal/Slideover:** add `after:enter` event ([#4187](https://github.com/nuxt/ui/issues/4187)) ([d9e9fea](https://github.com/nuxt/ui/commit/d9e9fea35e4b22d68324c9e85b3aa221a7987d0f))
* **NavigationMenu:** add `tooltip` and `popover` props ([f2682fd](https://github.com/nuxt/ui/commit/f2682fd2ae8abb7807977727fc22ef34cb5752e5)), closes [#4186](https://github.com/nuxt/ui/issues/4186)
* **NavigationMenu:** add `trigger` type in items ([9cf9f25](https://github.com/nuxt/ui/commit/9cf9f25f4424447691e03e9034155d1541badd43))
* **NavigationMenu:** handle `vertical` orientation with Accordion instead of Collapsible ([1e2a10b](https://github.com/nuxt/ui/commit/1e2a10b4bdebaef12316ac60f98a956dad21c1ec)), closes [#4072](https://github.com/nuxt/ui/issues/4072) [#3911](https://github.com/nuxt/ui/issues/3911)
* **Popover:** add `anchor` slot ([#4119](https://github.com/nuxt/ui/issues/4119)) ([473513c](https://github.com/nuxt/ui/commit/473513c2460d4329d7d2e0a0ea69bf1310a072d1))
### Bug Fixes
* **CheckboxGroup/RadioGroup:** variant `table` borders in RTL mode ([#4192](https://github.com/nuxt/ui/issues/4192)) ([43d281f](https://github.com/nuxt/ui/commit/43d281f6d1d8b0017ed61d929c5e311fb5b03447))
* **CommandPalette:** add `presentation` role to viewport ([2ba94db](https://github.com/nuxt/ui/commit/2ba94db09e1ba86020d5d289f1ca1e24ef706299))
* **ContextMenu/DropdownMenu:** wrap groups in a viewport ([dcf34a7](https://github.com/nuxt/ui/commit/dcf34a7ac236b96b1302ec2eae155b8f2d3784ef)), closes [#3315](https://github.com/nuxt/ui/issues/3315)
* **Drawer:** improve title & description accessibility ([41087d4](https://github.com/nuxt/ui/commit/41087d4c9569eb00c04bd748e055cd151c2f762c)), closes [#4199](https://github.com/nuxt/ui/issues/4199)
* **icons:** update `loading` icon ([#4163](https://github.com/nuxt/ui/issues/4163)) ([fe4e1f8](https://github.com/nuxt/ui/commit/fe4e1f859d42aa3c32bb7b75302e84a280abe525))
* **Input/Textarea:** define model modifiers types ([#4195](https://github.com/nuxt/ui/issues/4195)) ([3243fb8](https://github.com/nuxt/ui/commit/3243fb88f71c5475824bfdc4d7c4f303b2d6790b))
* **InputMenu/Select/SelectMenu:** manual viewport to display scrollbars ([f95abf8](https://github.com/nuxt/ui/commit/f95abf8d1d7b9149e400d7dc6f96f93f5154da7a)), closes [#4069](https://github.com/nuxt/ui/issues/4069)
* **NavigationMenu:** incorrect hover when disabled and active ([d0be599](https://github.com/nuxt/ui/commit/d0be59946bfe30c79a6f75476385ab8538aa51b8))
* **NavigationMenu:** only display `tooltip` when collapsed ([44f536f](https://github.com/nuxt/ui/commit/44f536fd0034facb3550d910fae71d4f9442ed19))
* **NavigationMenu:** remove `font-medium` in popover children ([0236399](https://github.com/nuxt/ui/commit/02363994d66d3c2d11b9913f31167fa25f5c5de2))
* **NavigationMenu:** revert new `collapsible` field ([3c78e2f](https://github.com/nuxt/ui/commit/3c78e2fd983f19b5cec65b4a94a8a8b14e548e5e))
* **Textarea:** missing imports ([#4207](https://github.com/nuxt/ui/issues/4207)) ([6aab62e](https://github.com/nuxt/ui/commit/6aab62ec30e266c5f0da0cd24aefbb7c53f447ac))
* **theme:** define `old-neutral` color as static ([#4193](https://github.com/nuxt/ui/issues/4193)) ([dae9f0b](https://github.com/nuxt/ui/commit/dae9f0b8631b3b9fb60ef47753f7aded0c36c4a2))
* **Tooltip:** increase padding for consistency ([0634a75](https://github.com/nuxt/ui/commit/0634a756a496f5131841abafd218ae7e4aaa61e5))
## [3.1.2](https://github.com/nuxt/ui/compare/v3.1.1...v3.1.2) (2025-05-15)
### Features
* **Badge:** add `square` prop ([#4008](https://github.com/nuxt/ui/issues/4008)) ([894e8a6](https://github.com/nuxt/ui/commit/894e8a61b6fea3618fc863bd77678385e9d021c2))
* **CheckboxGroup:** add `table` variant ([#3997](https://github.com/nuxt/ui/issues/3997)) ([1b6ab27](https://github.com/nuxt/ui/commit/1b6ab271ea3875a7c77ffe9367c7c341083dd53c))
* **components:** add `ui` field in items ([#4060](https://github.com/nuxt/ui/issues/4060)) ([b9adc83](https://github.com/nuxt/ui/commit/b9adc83e787db02507e6e7bb1aabc684eccc197b))
* **InputNumber:** add `increment-disabled` / `decrement-disabled` props ([#4141](https://github.com/nuxt/ui/issues/4141)) ([c7fba2e](https://github.com/nuxt/ui/commit/c7fba2e0ebfb7153f3bfb727165d653bbd3dbe54))
* **locale:** add Slovenian language ([#4140](https://github.com/nuxt/ui/issues/4140)) ([e86dc79](https://github.com/nuxt/ui/commit/e86dc79e51b2773a77ada5f12d4f0964fbc83354))
* **NavigationMenu:** add `collapsible` field in items ([2be60cd](https://github.com/nuxt/ui/commit/2be60cddfe10fd1e2466900fd53e21ee0c877227)), closes [#3353](https://github.com/nuxt/ui/issues/3353) [#3911](https://github.com/nuxt/ui/issues/3911)
* **NavigationMenu:** handle `tooltip` in items ([46c2987](https://github.com/nuxt/ui/commit/46c2987ebfd30b2b071a96a745b7270e852e96de)), closes [#4050](https://github.com/nuxt/ui/issues/4050)
* **Slider:** handle `tooltip` around thumbs ([d140acc](https://github.com/nuxt/ui/commit/d140acc608c6ae11c0a0531fe443588776ea7807)), closes [#1469](https://github.com/nuxt/ui/issues/1469)
* **Toast:** add `progress` prop to hide progress bar ([#4125](https://github.com/nuxt/ui/issues/4125)) ([92632e9](https://github.com/nuxt/ui/commit/92632e969eaa11521a166e50e346753929b7f523))
### Bug Fixes
* **Badge/Button:** handle zero value in label correctly ([#4108](https://github.com/nuxt/ui/issues/4108)) ([f244d15](https://github.com/nuxt/ui/commit/f244d15b96d97cd8ba34ba9c18f23965e17e3cef))
* **ButtonGroup:** add `z-index` on focused element ([204953b](https://github.com/nuxt/ui/commit/204953b780bde08dbfde230fc8887674449227b7))
* **Calendar:** wrong color for today date with `neutral` color ([7d51a9e](https://github.com/nuxt/ui/commit/7d51a9e479cb6105ea37759c5cd67ff9f7702c49)), closes [#4084](https://github.com/nuxt/ui/issues/4084) [#3629](https://github.com/nuxt/ui/issues/3629)
* **Checkbox/RadioGroup:** render correct element without `variant` ([f2fd778](https://github.com/nuxt/ui/commit/f2fd778c0a604f2d65aec9f3fe2d54b6d4e8c3a2)), closes [#3998](https://github.com/nuxt/ui/issues/3998)
* **CheckboxGroup:** relative `UCheckbox` import ([7551a85](https://github.com/nuxt/ui/commit/7551a85ad2d92b59e2909396affb862403d5b27a)), closes [#4090](https://github.com/nuxt/ui/issues/4090)
* **ColorPicker:** make thumb touch draggable ([#4101](https://github.com/nuxt/ui/issues/4101)) ([cc20a26](https://github.com/nuxt/ui/commit/cc20a26f07268d19119ab4c7c254033143bb63f4))
* **components:** `class` should have priority over `ui` prop ([e6e510b](https://github.com/nuxt/ui/commit/e6e510b848d995a286a51d50a120d67483e11232))
* **FormField:** block form field injection after use ([#4150](https://github.com/nuxt/ui/issues/4150)) ([d79da9d](https://github.com/nuxt/ui/commit/d79da9d7b60c9972af64acd8e6eef4ae7d6bc3eb))
* **FormField:** use `div` for `error` and `help` slots ([459a041](https://github.com/nuxt/ui/commit/459a0410ab729fde60865e84632b36903465f57e))
* **inertia:** link always render as anchor tag ([#3989](https://github.com/nuxt/ui/issues/3989)) ([e81464a](https://github.com/nuxt/ui/commit/e81464a43ede4e63ce3dc92429bbfef48614f731))
* **inertia:** make `useAppConfig` reactive ([12303a8](https://github.com/nuxt/ui/commit/12303a87be62dae84ef774e3a9795deb0ac90cc7))
* **Input/Textarea:** handle generic types ([3c8d6cd](https://github.com/nuxt/ui/commit/3c8d6cd01dfafed5844c376f52adbdda0c814420)), closes [nuxt/ui-pro#887](https://github.com/nuxt/ui-pro/issues/887)
* **InputNumber:** handle inside button group ([2e4c308](https://github.com/nuxt/ui/commit/2e4c3082a1e66fa597086dc3431fec37fa29ef62)), closes [#4155](https://github.com/nuxt/ui/issues/4155)
* **Link:** consistent behavior between nuxt, vue and inertia ([#4134](https://github.com/nuxt/ui/issues/4134)) ([67da90a](https://github.com/nuxt/ui/commit/67da90a2f638124f640c4271d3376c5ff3fab6a1))
* **module:** configure `@nuxt/fonts` with default weights ([276268d](https://github.com/nuxt/ui/commit/276268d311f57715cec47bc600a0ccc3d3885682))
* **NavigationMenu:** arrow position conflict ([#4137](https://github.com/nuxt/ui/issues/4137)) ([0dc4678](https://github.com/nuxt/ui/commit/0dc4678c68e4b500be49c38336dc75b73843e38d))
* **Select:** support more primitive types in `value` field ([#4105](https://github.com/nuxt/ui/issues/4105)) ([09b4699](https://github.com/nuxt/ui/commit/09b4699aeadaa195ea081509f8e237bb2c346238))
* **Slider:** handle generic types ([d7a4d02](https://github.com/nuxt/ui/commit/d7a4d029b77d2dfa0b8efcd2755d482fa5e31fd3))
* **Stepper:** use `div` tag for `title` & `description` ([a57844e](https://github.com/nuxt/ui/commit/a57844e41676c13ed1af861424961b88cee7b4da)), closes [#4096](https://github.com/nuxt/ui/issues/4096)
* **Tabs:** prevent trigger truncate without parent width ([06e5689](https://github.com/nuxt/ui/commit/06e5689da80b36205d0548d5d6b58510938e4a6e)), closes [#4056](https://github.com/nuxt/ui/issues/4056)
* **Tabs:** set `focus:outline-none` with `link` variant ([999a0f8](https://github.com/nuxt/ui/commit/999a0f84671fad20fa3dc50c6774af2e0200b32e))
* **templates:** dont write unused variants in theme files ([d3df3bb](https://github.com/nuxt/ui/commit/d3df3bb929fe6732f27b182d1664213884a662ec))
* **Toaster:** allow `base` slot override ([c63d2f3](https://github.com/nuxt/ui/commit/c63d2f380aac16f1d1e812516df3dca7fa7c8034))
* **vue:** make `useAppConfig` reactive ([869c070](https://github.com/nuxt/ui/commit/869c0708bd351c7be44e5e430c348b19dd316db9)), closes [#3952](https://github.com/nuxt/ui/issues/3952)
## [3.1.1](https://github.com/nuxt/ui/compare/v3.1.0...v3.1.1) (2025-05-02)
### Features
* **useOverlay:** add `closeAll` method ([#3984](https://github.com/nuxt/ui/issues/3984)) ([ac4c194](https://github.com/nuxt/ui/commit/ac4c1946ec399aec59b4bce9d538e3ff67868abf))
* **useOverlay:** add `isOpen` method to check overlay state ([#4041](https://github.com/nuxt/ui/issues/4041)) ([a4f3f6d](https://github.com/nuxt/ui/commit/a4f3f6d531f9c0281f99085a6688d296f8f13f2f))
### Bug Fixes
* **Calendar:** add `place-items-center` to grid row ([#4034](https://github.com/nuxt/ui/issues/4034)) ([8dfdd63](https://github.com/nuxt/ui/commit/8dfdd63ce3b3a0e904f7c013c774cf9aaf46b240))
* **defineShortcuts:** bring back `meta` to `ctrl` convert on non macos platforms ([f3b8b17](https://github.com/nuxt/ui/commit/f3b8b17dc5f43936ef7ffb11c1ed7f9a5f94d0bb)), closes [#3869](https://github.com/nuxt/ui/issues/3869) [#3318](https://github.com/nuxt/ui/issues/3318)
* **module:** support `nuxt-nightly` ([#3996](https://github.com/nuxt/ui/issues/3996)) ([bc0a296](https://github.com/nuxt/ui/commit/bc0a296f9d68ca72cd991b11cd3489b63c7b13db))
* **NavigationMenu:** remove `sm:w-auto` from content slot ([aebf0b3](https://github.com/nuxt/ui/commit/aebf0b3dca50c51c093cb6abf16c4fd995fc1b39)), closes [#3987](https://github.com/nuxt/ui/issues/3987)
* **RadioGroup:** improve items `value` field type ([#3995](https://github.com/nuxt/ui/issues/3995)) ([195773e](https://github.com/nuxt/ui/commit/195773ec7dac12ccc3a0a67867751e8ca634cc04))
* **templates:** put back args to watch in dev ([#4033](https://github.com/nuxt/ui/issues/4033)) ([c5bdec0](https://github.com/nuxt/ui/commit/c5bdec0f64963ef602975270a09a1ee795cdacf9))
* **theme:** add missing `border-bg` / `divide-bg` utilities ([82b5f32](https://github.com/nuxt/ui/commit/82b5f322ebd8a08e63588122bd4ef567dcb8ba8c))
* **theme:** add missing `ring-offset-*` utilities ([#3992](https://github.com/nuxt/ui/issues/3992)) ([e5df026](https://github.com/nuxt/ui/commit/e5df0269935be59df759fe0e1378acb2b0d9014a))
* **theme:** define default shades for named tailwindcss colors ([8acf3c5](https://github.com/nuxt/ui/commit/8acf3c51db6c2f9443d04be6ba7d9f062c5cf8ab)), closes [#3977](https://github.com/nuxt/ui/issues/3977)
* **theme:** improve app config types for `ui` object ([591d59f](https://github.com/nuxt/ui/commit/591d59fe89f1d9bf016c121bf9160f73fe0a290d)), closes [#3579](https://github.com/nuxt/ui/issues/3579)
* **theme:** use `[@theme](https://github.com/theme) inline` to properly reference css variables ([6131871](https://github.com/nuxt/ui/commit/6131871a0d124c5942d60dc5dff20981e8542e51)), closes [#4018](https://github.com/nuxt/ui/issues/4018)
* **useOverlay:** improve types and docs ([#4012](https://github.com/nuxt/ui/issues/4012)) ([39e29fc](https://github.com/nuxt/ui/commit/39e29fccf1840c723a13237d65002501b2829b70))
## [3.1.0](https://github.com/nuxt/ui/compare/v3.0.2...v3.1.0) (2025-04-24)
### ⚠ BREAKING CHANGES
* **OverlayProvider:** return an overlay instance from `.open()` (#3829)
### Features
* **App:** add global `portal` prop ([#3688](https://github.com/nuxt/ui/issues/3688)) ([29fa462](https://github.com/nuxt/ui/commit/29fa46276d6bf69b5b87880c476c6f778c2820bf))
* **Carousel:** add `select` event ([#3678](https://github.com/nuxt/ui/issues/3678)) ([22edfd7](https://github.com/nuxt/ui/commit/22edfd708ae3eeadbd4ff6c830cdfd5632948286))
* **CheckboxGroup:** new component ([#3862](https://github.com/nuxt/ui/issues/3862)) ([9c3d53a](https://github.com/nuxt/ui/commit/9c3d53a02d6254f6b5c90e5fed826b8aefcdb042))
* **components:** add new `content-top` and `content-bottom` slots ([#3886](https://github.com/nuxt/ui/issues/3886)) ([1a46394](https://github.com/nuxt/ui/commit/1a463946681e152aa18372118d0fef4a7d8055a5))
* **Form:** add `attach` prop to opt-out of nested form attachement ([#3939](https://github.com/nuxt/ui/issues/3939)) ([1a0d7a3](https://github.com/nuxt/ui/commit/1a0d7a3103cf7591b019ef3ad685e2f3786ef6f2))
* **Form:** export loading state ([#3861](https://github.com/nuxt/ui/issues/3861)) ([fdee252](https://github.com/nuxt/ui/commit/fdee2522bb9d8361ff3e9fdd4aa2350be8e49b05))
* **InputMenu/SelectMenu:** handle `resetSearchTermOnSelect` ([cea881a](https://github.com/nuxt/ui/commit/cea881abdc139b39df89b503cf2ab872f4246c8f)), closes [#3782](https://github.com/nuxt/ui/issues/3782)
* **InputNumber:** add support for `stepSnapping` & `disableWheelChange` props ([#3731](https://github.com/nuxt/ui/issues/3731)) ([f5e6284](https://github.com/nuxt/ui/commit/f5e62849c9313063396ab0e3a9b7d22d98ef69bc))
* **locale:** add Bulgarian language ([#3783](https://github.com/nuxt/ui/issues/3783)) ([a0c9731](https://github.com/nuxt/ui/commit/a0c9731f634020e76aa98a9a68d673591d35e8c9))
* **locale:** add Kazakh language ([#3875](https://github.com/nuxt/ui/issues/3875)) ([43153c4](https://github.com/nuxt/ui/commit/43153c4e91034b728059e7a9bed05888e48f8890))
* **locale:** add Tajik language ([#3850](https://github.com/nuxt/ui/issues/3850)) ([f42a79b](https://github.com/nuxt/ui/commit/f42a79b5efe8dc65430a83799ebb0ee737773820))
* **locale:** add Uyghur language ([#3878](https://github.com/nuxt/ui/issues/3878)) ([b7fc69b](https://github.com/nuxt/ui/commit/b7fc69baa718ff65b3988d0fa9f143306fa8fac4))
* **Modal/Popover/Slideover:** add `close:prevent` event ([#3958](https://github.com/nuxt/ui/issues/3958)) ([f486423](https://github.com/nuxt/ui/commit/f4864233812eac0ed37e0a2d076a95c285a22c01))
* **module:** define default color shades ([#3916](https://github.com/nuxt/ui/issues/3916)) ([7ac7aa9](https://github.com/nuxt/ui/commit/7ac7aa9ba73b6aca1bc29b0de2e95c60b2700135))
* **module:** define neutral utilities ([#3629](https://github.com/nuxt/ui/issues/3629)) ([d49e0da](https://github.com/nuxt/ui/commit/d49e0dadeea2a58e05e60b2c461b29ce1d334d2b))
* **module:** dynamic `rounded-*` utilities ([#3906](https://github.com/nuxt/ui/issues/3906)) ([f9737c8](https://github.com/nuxt/ui/commit/f9737c8f401bf8bc5307674fad6defe2aeeeb907))
* **OverlayProvider:** return an overlay instance from `.open()` ([#3829](https://github.com/nuxt/ui/issues/3829)) ([f3098df](https://github.com/nuxt/ui/commit/f3098df84a3b7f58f7ccc1233bc8b45eab99ee10))
* **PinInput:** add `autofocus` / `autofocus-delay` props ([0456670](https://github.com/nuxt/ui/commit/0456670dac1153340220603c8c116e3b71f72ae7)), closes [#3717](https://github.com/nuxt/ui/issues/3717)
* **RadioGroup:** add `card` and `table` variants ([#3178](https://github.com/nuxt/ui/issues/3178)) ([4d138ad](https://github.com/nuxt/ui/commit/4d138ad6719a074f5f994006d12745ca05bec9c4))
* **Select:** handle `onSelect` field in items ([8640831](https://github.com/nuxt/ui/commit/864083156a79dfb5d0be868658b7f9fc77570178))
* **Table:** conditionally apply classes to `tr` and `td` ([#3866](https://github.com/nuxt/ui/issues/3866)) ([80dfa88](https://github.com/nuxt/ui/commit/80dfa88ea442571ee1dc673317cc7baa8cacd8a3))
* **Tabs:** add `list-leading` and `list-trailing` slots ([#3837](https://github.com/nuxt/ui/issues/3837)) ([3447a06](https://github.com/nuxt/ui/commit/3447a062b636a469089d6e9bdcfcb3dce9063ee5))
* **Textarea:** add `autoresize-delay` prop ([06414d3](https://github.com/nuxt/ui/commit/06414d344b151ad6e1a3225a9f5f1f76d58d319c)), closes [#3730](https://github.com/nuxt/ui/issues/3730)
* **Textarea:** add `icon`, `loading`, etc. props to match Input ([cb193f1](https://github.com/nuxt/ui/commit/cb193f1d25b5c73ca03dcf10864800350dd1c290))
* **Textarea:** add `resize-none` class with `autoresize` prop ([ffafd81](https://github.com/nuxt/ui/commit/ffafd81e1ed25074430668c792e5e1c6afc22bd0))
* **unplugin:** routing support for inertia ([#3845](https://github.com/nuxt/ui/issues/3845)) ([d059efc](https://github.com/nuxt/ui/commit/d059efca258da7ae5116e829189a492824ac1d87))
### Bug Fixes
* **Accordion:** use `div` instead of `h3` for header tag ([75e4792](https://github.com/nuxt/ui/commit/75e4792f7f00c55229253289c4f806f2b6fc9854)), closes [#3963](https://github.com/nuxt/ui/issues/3963)
* **Alert/Toast:** display actions when using slots ([5086363](https://github.com/nuxt/ui/commit/50863635d653c8083772046ddc5b828fba7047d0)), closes [#3950](https://github.com/nuxt/ui/issues/3950)
* **Carousel:** move arrows inside container on mobile ([d339dcb](https://github.com/nuxt/ui/commit/d339dcbfb8fe244bd198d247d8448e3ef856dfef)), closes [#3813](https://github.com/nuxt/ui/issues/3813)
* **CheckboxGroup:** proxy slots & `ui` prop ([bc06185](https://github.com/nuxt/ui/commit/bc061852822edd2dfb832a46dd6388123ec5771e))
* **CommandPalette:** consistent alignement with other components ([d25265c](https://github.com/nuxt/ui/commit/d25265c8b7d34e01af8827d9af5eccb98bf30e9e))
* **CommandPalette:** increase input font size to avoid zoom ([d227a10](https://github.com/nuxt/ui/commit/d227a105d8d409ea0753153afaecf639ddb80fed))
* **CommandPalette:** prevent hover background on disabled items ([ba534f1](https://github.com/nuxt/ui/commit/ba534f18b94383c97b2654d892ee4b8b024b3fab))
* **components:** refactor types after `@nuxt/module-builder` upgrade ([#3855](https://github.com/nuxt/ui/issues/3855)) ([39c861a](https://github.com/nuxt/ui/commit/39c861a64bbd452256ebd1a14a257b94c35855d4))
* **components:** respect `transform-origin` in popper content ([#3919](https://github.com/nuxt/ui/issues/3919)) ([01d8dc7](https://github.com/nuxt/ui/commit/01d8dc72adb0b32ad68bb4a98bf24b17f435a89c))
* **ContextMenu/DropdownMenu:** handle RTL mode ([#3744](https://github.com/nuxt/ui/issues/3744)) ([1ae5cc0](https://github.com/nuxt/ui/commit/1ae5cc09cb2eca6b6f53eb04db9dcc731b696cae))
* **ContextMenuContent/DropdownMenuContent:** remove unwanted `any` ([#3741](https://github.com/nuxt/ui/issues/3741)) ([97274f1](https://github.com/nuxt/ui/commit/97274f15b8bfe457e7e206f81b32e3febf0f875d))
* **Form:** input and output type inference ([#3938](https://github.com/nuxt/ui/issues/3938)) ([f429498](https://github.com/nuxt/ui/commit/f42949820be9be9fca41abc653dc12c033e1eeec))
* **Form:** loses focus on submit ([#3796](https://github.com/nuxt/ui/issues/3796)) ([8e78eb1](https://github.com/nuxt/ui/commit/8e78eb15c85beef1c814206c4a192d4eb00a7e86))
* **InputMenu/Select/SelectMenu:** add `min-w-fit` to `content` slot ([#3922](https://github.com/nuxt/ui/issues/3922)) ([f6b3761](https://github.com/nuxt/ui/commit/f6b376110c8bee2c41ae3137bb972aad402ebff1))
* **InputMenu/SelectMenu:** correctly call `onSelect` events ([#3735](https://github.com/nuxt/ui/issues/3735)) ([f25fed5](https://github.com/nuxt/ui/commit/f25fed58e988b304e79cdb536d544d257395cf89))
* **InputMenu/SelectMenu:** prevent `disabled` items to be selected ([8435a0f](https://github.com/nuxt/ui/commit/8435a0fe1622eb5b6863b6e4751c9d2d1be36db9)), closes [#3474](https://github.com/nuxt/ui/issues/3474)
* **InputMenu/SelectMenu:** remove `valueKey` string case ([9ca213b](https://github.com/nuxt/ui/commit/9ca213bd3340492d7503a34bd142e1f79a697050)), closes [#3949](https://github.com/nuxt/ui/issues/3949) [#3331](https://github.com/nuxt/ui/issues/3331)
* **InputMenu/SelectMenu:** support arbitrary `value` ([#3779](https://github.com/nuxt/ui/issues/3779)) ([52a97e2](https://github.com/nuxt/ui/commit/52a97e2df7903f91e3134931eb0d6bd4c528f71f))
* **InputMenu:** emit `change` on multiple item removal ([9d2fed1](https://github.com/nuxt/ui/commit/9d2fed125013e3bbfbf9435678729cd05254a5e8)), closes [#3756](https://github.com/nuxt/ui/issues/3756)
* **Link:** proxy `download` property ([#3879](https://github.com/nuxt/ui/issues/3879)) ([47cdc2e](https://github.com/nuxt/ui/commit/47cdc2e1d8cd9803ebc954ccae110d62b9a08779))
* **NavigationMenu:** add `sm:w-auto` content slot ([abe0859](https://github.com/nuxt/ui/commit/abe0859691e06564f68335bd82dcd121e976408e)), closes [#3788](https://github.com/nuxt/ui/issues/3788)
* **Skeleton:** improve accessibility ([#3613](https://github.com/nuxt/ui/issues/3613)) ([3484832](https://github.com/nuxt/ui/commit/3484832822015a224ce6fbeae5132018875557e6))
* **Stepper:** ui prop override on `icon` and `content` slots ([1d45980](https://github.com/nuxt/ui/commit/1d459803dc052a16b8966ee89c71646bf6ef1c16)), closes [#3785](https://github.com/nuxt/ui/issues/3785)
* **Table:** improve `data` reactivity ([#3967](https://github.com/nuxt/ui/issues/3967)) ([6e27304](https://github.com/nuxt/ui/commit/6e27304d8ca459a04667bac404084264a8cf58fd))
* **Table:** pass header `colspan` to `th` ([#3926](https://github.com/nuxt/ui/issues/3926)) ([122e8ac](https://github.com/nuxt/ui/commit/122e8ac8f41ba093cd350c3ce642263263f77296))
* **Tree:** simplify reusable template types ([#3836](https://github.com/nuxt/ui/issues/3836)) ([3deed4c](https://github.com/nuxt/ui/commit/3deed4c271cad4adc2a4c47d5dd02e95a14ce11a))
* **types:** allow color identifiers with dashes ([#3896](https://github.com/nuxt/ui/issues/3896)) ([e5a1e26](https://github.com/nuxt/ui/commit/e5a1e26f9db763b54caed4ca313f44d1b5fe269d))
* **types:** handle `ClassValue` in `ui` prop ([eea1415](https://github.com/nuxt/ui/commit/eea14155aa612649bc969d806ec5df4295945c70)), closes [#3860](https://github.com/nuxt/ui/issues/3860)
* **types:** improve dynamic slots ([#3857](https://github.com/nuxt/ui/issues/3857)) ([8dd9d08](https://github.com/nuxt/ui/commit/8dd9d08209e47a7d9a5654db4fb936b4cbcfc021))
* **usePortal:** adjust portal target resolution logic ([#3954](https://github.com/nuxt/ui/issues/3954)) ([db11db6](https://github.com/nuxt/ui/commit/db11db6ff1ce4b27a66aaa03f07870ba36426181))
* **vite:** vitest skipping nuxt imports transformations ([#3925](https://github.com/nuxt/ui/issues/3925)) ([c31bffa](https://github.com/nuxt/ui/commit/c31bffad1b8afeda584bca8c73bb7f790eb12a9f))
## [3.0.2](https://github.com/nuxt/ui/compare/v3.0.1...v3.0.2) (2025-03-28)
### Features
* **Calendar:** allow year and month buttons styling ([#3672](https://github.com/nuxt/ui/issues/3672)) ([4a2b77d](https://github.com/nuxt/ui/commit/4a2b77d86c28806234002340eda39de4dc78cce0))
* **locale:** add Armenian language ([#3664](https://github.com/nuxt/ui/issues/3664)) ([c76f590](https://github.com/nuxt/ui/commit/c76f5900970e3f5c451192b1207ccea04771e8b3))
* **Table:** add `empty` prop ([afff54f](https://github.com/nuxt/ui/commit/afff54fecd31497238461e0a44abd8668ed734c3))
### Bug Fixes
* **Avatar:** proxy `$attrs` to default slot ([#3712](https://github.com/nuxt/ui/issues/3712)) ([88f349d](https://github.com/nuxt/ui/commit/88f349d0d74eb1c2ce5066818731759c25a9e83e))
* **Button:** use `focus:outline-none` instead of `focus:outline-hidden` ([c231fe5](https://github.com/nuxt/ui/commit/c231fe5f26ca7614df46a7ec8a5ce7f4ec8884e7)), closes [#3658](https://github.com/nuxt/ui/issues/3658)
* **CommandPalette:** use `group.id` as key ([bc61d29](https://github.com/nuxt/ui/commit/bc61d29cce531715a6279444845f02a002a22af7))
* **components:** improve generic types ([#3331](https://github.com/nuxt/ui/issues/3331)) ([b998354](https://github.com/nuxt/ui/commit/b9983549a4b743724ea3ef99cc4a243f5ca41e53))
* **Container:** add `w-full` class ([df00149](https://github.com/nuxt/ui/commit/df001495980647cab1e67fd16154f1bc778de5e2))
* **defineLocale/defineShortcuts:** remove `@__NO_SIDE_EFFECTS__` ([82e2665](https://github.com/nuxt/ui/commit/82e26655a40782555299516f32a76046fa0dbd3a))
* **Drawer:** remove `fadeFromIndex` prop proxy ([f7604e5](https://github.com/nuxt/ui/commit/f7604e565f717001a4d4c2974cf23559a3f01c21))
* **Form:** clear dirty state after submit ([#3692](https://github.com/nuxt/ui/issues/3692)) ([3dd88ba](https://github.com/nuxt/ui/commit/3dd88bacecb2945efba8cc3cb4fe59fcbc056e9a))
* **FormField:** add `help` to `aria-describedby` attribute ([#3691](https://github.com/nuxt/ui/issues/3691)) ([20c3392](https://github.com/nuxt/ui/commit/20c33920d005332db3c83f33a8c54c7c227ce0a0))
* **InputMenu/SelectMenu:** empty search results ([94b6e52](https://github.com/nuxt/ui/commit/94b6e520f5ccf011204e953421fcc5b44b637e51))
* **InputMenu:** reset `searchTerm` on `update:open` ([3074632](https://github.com/nuxt/ui/commit/3074632523e67fa6a0ad3d9a71e5692c285bdc3a)), closes [#3620](https://github.com/nuxt/ui/issues/3620)
* **Link:** handle `aria-current` like `NuxtLink` / `RouterLink` ([c531d02](https://github.com/nuxt/ui/commit/c531d0248be7863980a1f676643c2dea8301c009))
* **Link:** prevent `active="true"` binding on html ([d73768b](https://github.com/nuxt/ui/commit/d73768b70453d60dd4186a996c1cf808b0294bf6))
* **Link:** properly pick all `aria-*` & `data-*` attrs ([ade16b7](https://github.com/nuxt/ui/commit/ade16b76cf535924a8d0f402b4d5d65cb67a55eb))
* **Link:** proxy `onClick` ([370054b](https://github.com/nuxt/ui/commit/370054b20c0201c9dba84ddfcd1e916594619b93)), closes [#3631](https://github.com/nuxt/ui/issues/3631)
* **NavigationMenu:** add `z-index` on viewport ([0095d89](https://github.com/nuxt/ui/commit/0095d8916bf361c0c89972e2f86b79850510c6a9)), closes [#3654](https://github.com/nuxt/ui/issues/3654)
* **Switch:** prevent transition on focus outline ([68787b2](https://github.com/nuxt/ui/commit/68787b26fdf2bd5f9d9e812e5bfddb19abe45d1d))
* **Table:** wrong condition on `caption` slot ([4ebb94c](https://github.com/nuxt/ui/commit/4ebb94cd7ef909b3547bce0922f75fe3ff74de4c))
* **Tabs:** remove `focus:outline-hidden` class ([1769d5e](https://github.com/nuxt/ui/commit/1769d5ed6ea46b1f7eafdc48cb6456512229f98b))
* **types:** add missing export for ButtonGroup ([#3709](https://github.com/nuxt/ui/issues/3709)) ([e7e6745](https://github.com/nuxt/ui/commit/e7e674559981177ad08be42418746060d7737df9))
* **useOverlay:** refine `open` method type to infer close emit return type ([#3716](https://github.com/nuxt/ui/issues/3716)) ([bd99c2d](https://github.com/nuxt/ui/commit/bd99c2d850d57baccc51e049c0b578a6fc6ab431))
* **vue:** mock `nuxtApp.hooks` & `useRuntimeHook` ([23bfeb9](https://github.com/nuxt/ui/commit/23bfeb937004d619187a67fb43e4c76b13d00069))
## [3.0.1](https://github.com/nuxt/ui/compare/v3.0.0...v3.0.1) (2025-03-21)
### ⚠ BREAKING CHANGES
* **Form:** drop explicit support for `zod` and `valibot` (#3617)
### Features
* **components:** handle events in `content` prop ([5dec0e1](https://github.com/nuxt/ui/commit/5dec0e16e28549b8833aaab17a87fada63d6598c))
* **locale:** add Catalan language ([#3550](https://github.com/nuxt/ui/issues/3550)) ([53cf1b4](https://github.com/nuxt/ui/commit/53cf1b4c14a2a0e076e1e77688852e6bd0a28a74))
* **locale:** add Central Kurdish language ([#3566](https://github.com/nuxt/ui/issues/3566)) ([b2034cc](https://github.com/nuxt/ui/commit/b2034ccc91eec6a2842c6f83d159e5aa6fd5f2fd))
* **locale:** add Romanian language ([#3587](https://github.com/nuxt/ui/issues/3587)) ([0229b0f](https://github.com/nuxt/ui/commit/0229b0fd4644a97db7eb3154c3c87a26634dcfbb))
* **locale:** add Urdu language ([#3611](https://github.com/nuxt/ui/issues/3611)) ([126ba23](https://github.com/nuxt/ui/commit/126ba2326f8153e155e1013db92c6ee417117610))
* **locale:** add Uzbek language ([#3548](https://github.com/nuxt/ui/issues/3548)) ([302e04b](https://github.com/nuxt/ui/commit/302e04bd77ae8b165046b264c8d23626e92f8fb5))
### Bug Fixes
* **Calendar:** grey out days outside of displayed month ([#3639](https://github.com/nuxt/ui/issues/3639)) ([a516866](https://github.com/nuxt/ui/commit/a5168666b7dff08e714d57f497737e7a670f457c))
* **ContextMenu/DropdownMenu:** remove `any` from `proxySlots` ([#3623](https://github.com/nuxt/ui/issues/3623)) ([764c41a](https://github.com/nuxt/ui/commit/764c41a0c60dd1c12d39a86af9f5f11b9e6cdc8c))
* **Modal/Slideover/Toast:** prevent unnecessary close instantiation ([f4c417d](https://github.com/nuxt/ui/commit/f4c417d9ef5409b52084bdf9d8cbccee3139709f))
* **module:** handle tailwindcss import without `theme(static)` ([#3630](https://github.com/nuxt/ui/issues/3630)) ([ecff9ab](https://github.com/nuxt/ui/commit/ecff9abc720bdda3a279d5bcfb7b477ff885f2e4))
* **module:** mark functions used in exports as pure ([#3604](https://github.com/nuxt/ui/issues/3604)) ([57efc78](https://github.com/nuxt/ui/commit/57efc78a3b3fa4a54bcd13df47d570a18fba2bc4))
* **RadioGroup:** handle `disabled` on items ([fe0bd83](https://github.com/nuxt/ui/commit/fe0bd83d11b0dfa53b58d423bc917f8e21d73444)), closes [nuxt/ui-pro#911](https://github.com/nuxt/ui-pro/issues/911)
* **Table:** allow links to be opened when [@select](https://github.com/select) is used ([#3580](https://github.com/nuxt/ui/issues/3580)) ([e80cc15](https://github.com/nuxt/ui/commit/e80cc1592fb244dd7692486a4c1ca5b1c2008112))
* **types:** add missing export for Icon ([#3568](https://github.com/nuxt/ui/issues/3568)) ([5e62493](https://github.com/nuxt/ui/commit/5e624933216db95cbfd1b8034b2eb0f13846ae55))
* **unplugin:** include `@compodium/examples` in auto-imports paths ([#3585](https://github.com/nuxt/ui/issues/3585)) ([cc504b8](https://github.com/nuxt/ui/commit/cc504b8a4b69dd76b49659d5c206ef23dcb9e475))
* **useLocale:** unique symbol to use in `@nuxt/ui-pro` ([#3603](https://github.com/nuxt/ui/issues/3603)) ([dec2730](https://github.com/nuxt/ui/commit/dec2730aaea1327434837cfa022ea04056757cbf))
* **vue:** missing unhead context ([#3589](https://github.com/nuxt/ui/issues/3589)) ([0897e9e](https://github.com/nuxt/ui/commit/0897e9ef05fbee4f021f317bb7c2d0b7007f1b75))
### Code Refactoring
* **Form:** drop explicit support for `zod` and `valibot` ([#3617](https://github.com/nuxt/ui/issues/3617)) ([9a4bb34](https://github.com/nuxt/ui/commit/9a4bb34d7d14add0a3199103f4b583e8307d1d6d))
## [3.0.0](https://github.com/nuxt/ui/compare/v3.0.0-beta.4...v3.0.0) (2025-03-12)
## [3.0.0-beta.4](https://github.com/nuxt/ui/compare/v3.0.0-beta.3...v3.0.0-beta.4) (2025-03-12)
### Features
* **Form:** global errors ([#3482](https://github.com/nuxt/ui/issues/3482)) ([6e03d9c](https://github.com/nuxt/ui/commit/6e03d9c6efc8f4cfc306813e733d7d3e03706323))
* **Input/Textarea:** allow `null` value in model ([#3415](https://github.com/nuxt/ui/issues/3415)) ([cfe9b2e](https://github.com/nuxt/ui/commit/cfe9b2ecf34827bc11a5281a069988ab96030047))
* **useLocale:** handle generic messages ([#3100](https://github.com/nuxt/ui/issues/3100)) ([a9c8eb3](https://github.com/nuxt/ui/commit/a9c8eb3f60a10d1a71632991c9db594716b0fba1))
### Bug Fixes
* **Button:** missing import ([21dbf01](https://github.com/nuxt/ui/commit/21dbf01888a161a9d8ac6eb0d957c1342f6cc30d)), closes [nuxt/ui#3417](https://github.com/nuxt/ui/issues/3417)
* **Form:** input blur validation on submit ([#3504](https://github.com/nuxt/ui/issues/3504)) ([97c8098](https://github.com/nuxt/ui/commit/97c8098d4a35c392719ae179d36aa008d6f8f78a))
* **vue:** prevent calling `useHead` in colors ([5ecd227](https://github.com/nuxt/ui/commit/5ecd2271ca86087cb805548397d75c38763ad412))
## [3.0.0-beta.3](https://github.com/nuxt/ui/compare/v3.0.0-beta.2...v3.0.0-beta.3) (2025-03-07)
### Features
* **Button:** handle `active` state ([bd2d484](https://github.com/nuxt/ui/commit/bd2d4848d246a3d5930f8059913f5a1a0abe29fd)), closes [#3417](https://github.com/nuxt/ui/issues/3417)
* **Table:** add `loading` slot ([99e531d](https://github.com/nuxt/ui/commit/99e531d8dfb7954322b7ab7feda3d8814c6d8d02)), closes [#3444](https://github.com/nuxt/ui/issues/3444)
### Bug Fixes
* **InputMenu/SelectMenu:** proxy `required` in root props ([60b7e2d](https://github.com/nuxt/ui/commit/60b7e2d69e80afa7e221855dcec46479d0ca5c6c))
* **InputMenu:** wrong `required` in multiple mode ([01fa230](https://github.com/nuxt/ui/commit/01fa230eae4b6623c5fd71cc218d114d9f6f0f25)), closes [#2741](https://github.com/nuxt/ui/issues/2741)
* **Pagination:** add missing slots ([a47c5ff](https://github.com/nuxt/ui/commit/a47c5ff46616eafee3158cb9801183965f5f9874)), closes [#3441](https://github.com/nuxt/ui/issues/3441)
* **Pagination:** wrong next link ([e823022](https://github.com/nuxt/ui/commit/e823022b19bb172d2e5fabb9144b4a4286a25a5f)), closes [#3008](https://github.com/nuxt/ui/issues/3008)
* **templates:** prevent overriding existing colors ([ccbd89c](https://github.com/nuxt/ui/commit/ccbd89c908fe8af54c7d723dd12da5b7f3906c8f)), closes [#3426](https://github.com/nuxt/ui/issues/3426)
## [3.0.0-beta.2](https://github.com/nuxt/ui/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2025-02-28)
### Bug Fixes

View File

@@ -11,35 +11,31 @@
[![License][license-src]][license-href]
[![Nuxt][nuxt-src]][nuxt-href]
Nuxt UI harnesses the combined strengths of [Reka UI](https://reka-ui.com/), [Tailwind CSS](https://tailwindcss.com/), and [Tailwind Variants](https://www.tailwind-variants.org/) to offer developers an unparalleled set of tools for creating sophisticated, accessible, and highly performant user interfaces.
We're thrilled to introduce Nuxt UI v3, a significant upgrade to our UI library that delivers extensive improvements and robust new capabilities. This major update harnesses the combined strengths of [Reka UI](https://reka-ui.com/), [Tailwind CSS v4](https://tailwindcss.com/), and [Tailwind Variants](https://www.tailwind-variants.org/) to offer developers an unparalleled set of tools for creating sophisticated, accessible, and highly performant user interfaces.
> [!NOTE]
> You are on the `v3` development branch, check out the [v2 branch](https://github.com/nuxt/ui/tree/v2) for Nuxt UI v2.
> [!TIP]
> **Looking for more components ?**
> Check out [Nuxt UI Pro](https://ui.nuxt.com/pro), a collection of premium Vue components, composables, and utilities built on top of Nuxt UI for faster and more powerful app development.
> You are on the `v3` development branch, check out the [dev branch](https://github.com/nuxt/ui/tree/dev) for Nuxt UI v2.
## Documentation
Visit https://ui.nuxt.com to explore the documentation.
Visit https://ui3.nuxt.dev to explore the documentation.
## Installation
```bash [pnpm]
pnpm add @nuxt/ui
pnpm add @nuxt/ui@next
```
```bash [yarn]
yarn add @nuxt/ui
yarn add @nuxt/ui@next
```
```bash [npm]
npm install @nuxt/ui
npm install @nuxt/ui@next
```
```bash [bun]
bun add @nuxt/ui
bun add @nuxt/ui@next
```
### Nuxt
@@ -55,11 +51,11 @@ export default defineNuxtConfig({
2. Import Tailwind CSS and Nuxt UI in your CSS:
```css [assets/css/main.css]
@import "tailwindcss";
@import "tailwindcss" theme(static);
@import "@nuxt/ui";
```
Learn more in the [installation guide](https://ui.nuxt.com/getting-started/installation/nuxt).
Learn more in the [installation guide](https://ui3.nuxt.dev/getting-started/installation/nuxt).
### Vue
@@ -102,22 +98,11 @@ app.mount('#app')
3. Import Tailwind CSS and Nuxt UI in your CSS:
```css [assets/main.css]
@import "tailwindcss";
@import "tailwindcss" theme(static);
@import "@nuxt/ui";
```
Learn more in the [installation guide](https://ui.nuxt.com/getting-started/installation/vue).
## Contribution
Thank you for considering contributing to Nuxt UI. Here are a few ways you can get involved:
- Reporting Bugs: If you come across any bugs or issues, please check out the reporting bugs guide to learn how to submit a bug report.
- Suggestions: Have any thoughts to enhance Nuxt UI? We'd love to hear them! Check out the [contribution guide](https://ui.nuxt.com/getting-started/contribution) to share your suggestions.
## Local Development
Follow the docs to [set up your local development environment](https://ui.nuxt.com/getting-started/contribution#local-development) and contribute.
Learn more in the [installation guide](https://ui3.nuxt.dev/getting-started/installation/vue).
## Credits
@@ -134,7 +119,7 @@ Follow the docs to [set up your local development environment](https://ui.nuxt.c
Licensed under the [MIT license](https://github.com/nuxt/ui/blob/v3/LICENSE.md).
<!-- Badges -->
[npm-version-src]: https://img.shields.io/npm/v/@nuxt/ui/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
[npm-version-src]: https://img.shields.io/npm/v/@nuxt/ui/next.svg?style=flat&colorA=18181B&colorB=28CF8D
[npm-version-href]: https://npmjs.com/package/@nuxt/ui
[npm-downloads-src]: https://img.shields.io/npm/dm/@nuxt/ui.svg?style=flat&colorA=18181B&colorB=28CF8D

View File

@@ -7,13 +7,10 @@ export default defineBuildConfig({
'./src/vite'
],
rollup: {
replace: {
delimiters: ['', ''],
values: {
// Used in development to import directly from theme
'process.argv.includes(\'--uiDev\')': 'false'
}
}
emitCJS: true
},
replace: {
'process.env.DEV': 'false'
},
hooks: {
'mkdist:entry:options'(ctx, entry, options) {

View File

@@ -6,7 +6,7 @@
},
"dependencies": {
"citty": "^0.1.6",
"consola": "^3.4.2",
"consola": "^3.4.0",
"pathe": "^2.0.3",
"scule": "^1.3.0"
}

View File

@@ -31,10 +31,13 @@ const component = ({ name, primitive, pro, prose, content }) => {
? `
<script lang="ts">
import type { AppConfig } from '@nuxt/schema'
import _appConfig from '#build/app.config'
import theme from '#build/${path}/${prose ? 'prose/' : ''}${content ? 'content/' : ''}${kebabName}'
import type { ComponentConfig } from '../types/utils'
import { tv } from '${pro ? '#ui/utils/tv' : '../utils/tv'}'
type ${upperName} = ComponentConfig<typeof theme, AppConfig, ${upperName}${pro ? `, '${key}'` : ''}>
const appConfig${camelName} = _appConfig as AppConfig & { ${key}: { ${prose ? 'prose: { ' : ''}${camelName}: Partial<typeof theme> } }${prose ? ' }' : ''}
const ${camelName} = tv({ extend: tv(theme), ...(appConfig${camelName}.${key}?.${prose ? 'prose?.' : ''}${camelName} || {}) })
export interface ${upperName}Props {
/**
@@ -43,7 +46,7 @@ export interface ${upperName}Props {
*/
as?: any
class?: any
ui?: ${upperName}['slots']
ui?: Partial<typeof ${camelName}.slots>
}
export interface ${upperName}Slots {
@@ -52,37 +55,38 @@ export interface ${upperName}Slots {
</script>
<script setup lang="ts">
import { computed } from 'vue'
import { Primitive } from 'reka-ui'
import { useAppConfig } from '#imports'
import { tv } from '../utils/tv'
const props = defineProps<${upperName}Props>()
defineSlots<${upperName}Slots>()
const appConfig = useAppConfig() as ${upperName}['AppConfig']
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.${camelName} || {}) })())
const ui = ${camelName}()
</script>
<template>
<Primitive :as="as" :class="ui.root({ class: [props.ui?.root, props.class] })">
<Primitive :as="as" :class="ui.root({ class: [props.class, props.ui?.root] })">
<slot />
</Primitive>
</template>
`
: `
<script lang="ts">
import type { VariantProps } from 'tailwind-variants'
import type { ${upperName}RootProps, ${upperName}RootEmits } from 'reka-ui'
import type { AppConfig } from '@nuxt/schema'
import _appConfig from '#build/app.config'
import theme from '#build/${path}/${prose ? 'prose/' : ''}${content ? 'content/' : ''}${kebabName}'
import type { ComponentConfig } from '../types/utils'
import { tv } from '${pro ? '#ui/utils/tv' : '../utils/tv'}'
type ${upperName} = ComponentConfig<typeof theme, AppConfig, ${upperName}${pro ? `, '${key}'` : ''}>
const appConfig${camelName} = _appConfig as AppConfig & { ${key}: { ${prose ? 'prose: { ' : ''}${camelName}: Partial<typeof theme> } }${prose ? ' }' : ''}
const ${camelName} = tv({ extend: tv(theme), ...(appConfig${camelName}.${key}?.${prose ? 'prose?.' : ''}${camelName} || {}) })
type ${upperName}Variants = VariantProps<typeof ${camelName}>
export interface ${upperName}Props extends Pick<${upperName}RootProps> {
class?: any
ui?: ${upperName}['slots']
ui?: Partial<typeof ${camelName}.slots>
}
export interface ${upperName}Emits extends ${upperName}RootEmits {}
@@ -91,25 +95,20 @@ export interface ${upperName}Slots {}
</script>
<script setup lang="ts">
import { computed } from 'vue'
import { ${upperName}Root, useForwardPropsEmits } from 'reka-ui'
import { reactivePick } from '@vueuse/core'
import { useAppConfig } from '#imports'
import { tv } from '../utils/tv'
const props = defineProps<${upperName}Props>()
const emits = defineEmits<${upperName}Emits>()
const slots = defineSlots<${upperName}Slots>()
const appConfig = useAppConfig() as ${upperName}['AppConfig']
const rootProps = useForwardPropsEmits(reactivePick(props), emits)
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.${camelName} || {}) })())
const ui = ${camelName}()
</script>
<template>
<${upperName}Root v-bind="rootProps" :class="ui.root({ class: [props.ui?.root, props.class] })" />
<${upperName}Root v-bind="rootProps" :class="ui.root({ class: [props.class, props.ui?.root] })" />
</template>
`
}

View File

@@ -1,6 +1,7 @@
<script setup lang="ts">
import { withoutTrailingSlash } from 'ufo'
// import { withoutTrailingSlash } from 'ufo'
import colors from 'tailwindcss/colors'
// import { debounce } from 'perfect-debounce'
const route = useRoute()
const appConfig = useAppConfig()
@@ -11,8 +12,17 @@ const { data: files } = useLazyAsyncData('search', () => queryCollectionSearchSe
server: false
})
const searchTerm = ref('')
// watch(searchTerm, debounce((query: string) => {
// if (!query) {
// return
// }
// useTrackEvent('Search', { props: { query: `${query} - ${searchTerm.value?.commandPaletteRef.results.length} results` } })
// }, 500))
const links = useLinks()
const searchLinks = useSearchLinks()
const color = computed(() => colorMode.value === 'dark' ? (colors as any)[appConfig.ui.colors.neutral][900] : 'white')
const radius = computed(() => `:root { --ui-radius: ${appConfig.theme.radius}rem; }`)
const blackAsPrimary = computed(() => appConfig.theme.blackAsPrimary ? `:root { --ui-primary: black; } .dark { --ui-primary: white; }` : ':root {}')
@@ -23,8 +33,8 @@ useHead({
{ key: 'theme-color', name: 'theme-color', content: color }
],
link: [
// { rel: 'icon', type: 'image/svg+xml', href: '/icon.svg' },
{ rel: 'canonical', href: `https://ui.nuxt.com${withoutTrailingSlash(route.path)}` }
{ rel: 'icon', type: 'image/svg+xml', href: '/icon.svg' }
// { rel: 'canonical', href: `https://ui.nuxt.com${withoutTrailingSlash(route.path)}` }
],
style: [
{ innerHTML: radius, id: 'nuxt-ui-radius', tagPriority: -2 },
@@ -40,8 +50,6 @@ useServerSeoMeta({
twitterCard: 'summary_large_image'
})
useFaviconFromTheme()
const { frameworks, modules } = useSharedData()
const { mappedNavigation, filteredNavigation } = useContentNavigation(navigation)
@@ -67,7 +75,7 @@ provide('navigation', mappedNavigation)
<ClientOnly>
<LazyUContentSearch
:links="searchLinks"
v-model:search-term="searchTerm"
:files="files"
:groups="[{
id: 'framework',
@@ -87,5 +95,5 @@ provide('navigation', mappedNavigation)
</template>
<style>
/* Safelist (do not remove): [&>div]:*:my-0 [&>div]:*:w-full h-64 !px-0 !py-0 !pt-0 !pb-0 !p-0 !justify-start !justify-end !min-h-96 h-136 max-h-[341px] */
/* Safelist (do not remove): [&>div]:*:my-0 [&>div]:*:w-full h-64 !px-0 !py-0 !pt-0 !pb-0 !p-0 !justify-start !min-h-96 h-136 */
</style>

View File

@@ -1,7 +1,7 @@
@import "tailwindcss" theme(static) source("../../../..");
@import "@nuxt/ui-pro";
@source "../../../content/**/*";
@source "../../../content";
@source "../../../node_modules/.c12";
@theme static {

View File

@@ -1,50 +0,0 @@
<script setup lang="ts">
const el = ref<HTMLDivElement | null>(null)
onMounted(() => {
if (!el.value) {
return
}
const script = document.createElement('script')
script.setAttribute('type', 'text/javascript')
script.setAttribute('src', 'https://cdn.carbonads.com/carbon.js?serve=CWYIVK3E&placement=uinuxtcom')
script.setAttribute('id', '_carbonads_js')
el.value?.appendChild(script)
})
</script>
<template>
<div ref="el" class="carbon" />
</template>
<style scoped>
@reference "../assets/css/main.css";
.carbon :deep(#carbonads) {
@apply relative border border-default rounded-md hover:bg-elevated/50 w-full transition-colors min-h-[220px] p-2;
.carbon-img {
@apply flex justify-center w-full;
& > img {
@apply !max-w-full w-full rounded-sm;
}
}
.carbon-text {
@apply text-sm text-muted transition-colors text-center text-pretty flex pt-2;
}
.carbon-poweredby {
@apply block text-xs text-center text-muted pt-2;
}
&:hover {
.carbon-text {
@apply text-default;
}
}
}
</style>

View File

@@ -1,18 +1,7 @@
<template>
<UBanner
id="ui3-launch"
icon="i-lucide-rocket"
:actions="[
{
label: 'Discover Nuxt UI Pro',
to: '/pro/pricing',
trailingIcon: 'i-lucide-arrow-right'
}
]"
close
>
<UBanner icon="i-lucide-construction" :actions="[{ label: 'Go to Nuxt UI v2', to: 'https://ui.nuxt.com', trailingIcon: 'i-lucide-arrow-right' }]" :close="false">
<template #title>
<span class="font-semibold">Nuxt UI v3</span> is officially released.
You're looking at the documentation for <span class="font-semibold">Nuxt UI v3</span>!
</template>
</UBanner>
</template>

View File

@@ -1,51 +0,0 @@
<script setup lang="ts">
const endDate = new Date('2025-03-14T23:59:59Z')
const second = 1000
const minute = second * 60
const hour = minute * 60
const day = hour * 24
function getCountdown() {
const distance = Math.floor((endDate.getTime() - Date.now()))
return {
day: Math.floor(distance / day),
hour: Math.floor((distance % (day)) / (hour)),
minute: Math.floor((distance % (hour)) / (minute)),
second: Math.floor((distance % (minute)) / (second)),
distance
}
}
const countdown = ref(getCountdown())
let interval: any
if (countdown.value.distance > 0) {
onMounted(() => {
interval = setInterval(() => {
countdown.value = getCountdown()
if (countdown.value.distance <= 0) {
clearInterval(interval)
}
}, 1000)
})
}
const plural = (value: number) => (value === 1 ? '' : 's')
const double = (value: number) => (value < 10 ? `0${value}` : value)
</script>
<template>
<div>
<p class="font-semibold text-gray-900 dark:text-white text-sm mb-3">
Nuxt UI v3 launch offer ends in:
</p>
<div class="flex items-center justify-center gap-2 text-center">
<template v-for="(value, key) in countdown" :key="key">
<div v-if="key !== 'distance'" class="flex flex-col items-center gap-2">
<UBadge color="primary" class="w-14 h-14 font-bold text-2xl flex items-center justify-center tabular-nums" variant="subtle">
{{ double(value) }}
</UBadge>
<span class="text-[10px] font-semibold text-gray-900 dark:text-white tracking-wide tabular-nums uppercase">{{ key }}{{ plural(value) }}</span>
</div>
</template>
</div>
</div>
</template>

View File

@@ -2,8 +2,8 @@
const route = useRoute()
const links = [{
label: 'Team',
to: '/team'
label: 'Figma',
to: '/figma'
}, {
label: 'Roadmap',
to: '/roadmap'
@@ -22,8 +22,8 @@ const links = [{
<UFooter>
<template #left>
<NuxtLink to="https://github.com/nuxt/ui" target="_blank" class="text-sm text-muted">
Published under <span class="text-highlighted">MIT License</span>
<NuxtLink to="https://github.com/nuxt/ui" target="_blank" class="text-sm text-(--ui-text-muted)">
Published under <span class="text-(--ui-text-highlighted)">MIT License</span>
</NuxtLink>
</template>

View File

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

View File

@@ -22,34 +22,14 @@ onMounted(() => {
const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
const githubLink = computed(() => `https://github.com/nuxt/${value.value}`)
const desktopLinks = computed(() => props.links.map(({ icon, ...link }) => link))
const mobileLinks = computed(() => [
...props.links.map(link => ({ ...link, defaultOpen: link.children && route.path.startsWith(link.to as string) })),
{
label: 'Open on GitHub',
to: githubLink.value,
icon: 'i-simple-icons-github',
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
]
})
const mobileLinks = computed(() => props.links.map(link => ({ ...link, defaultOpen: link.children && route.path.startsWith(link.to as string) })))
</script>
<template>
<UHeader :ui="{ left: 'min-w-0' }" :menu="{ shouldScaleBackground: true }">
<template #left>
<NuxtLink to="/" class="flex items-end gap-2 font-bold text-xl text-highlighted min-w-0 focus-visible:outline-primary shrink-0" aria-label="Nuxt UI">
<NuxtLink to="/" class="flex items-end gap-2 font-bold text-xl text-(--ui-text-highlighted) min-w-0 focus-visible:outline-(--ui-primary) shrink-0" aria-label="Nuxt UI">
<Logo v-if="route.path === '/'" class="w-auto h-6 shrink-0" />
<LogoPro v-else-if="route.path.startsWith('/pro')" class="w-auto h-6 shrink-0" />
<template v-else>
@@ -61,7 +41,7 @@ const items = computed(() => {
<UDropdownMenu
v-slot="{ open }"
:modal="false"
:items="items"
:items="[{ label: `v${config.version}`, active: true, color: 'primary', checked: true, type: 'checkbox' }, { label: module === 'ui-pro' ? 'v1.5' : 'v2.19', to: module === 'ui-pro' ? 'https://ui.nuxt.com/pro' : 'https://ui.nuxt.com' }]"
:ui="{ content: 'w-(--reka-dropdown-menu-trigger-width) min-w-0' }"
size="xs"
>
@@ -71,7 +51,7 @@ const items = computed(() => {
trailing-icon="i-lucide-chevron-down"
size="xs"
class="-mb-[6px] font-semibold rounded-full truncate"
:class="[open && 'bg-primary/15 ']"
:class="[open && 'bg-(--ui-primary)/15 ']"
:ui="{
trailingIcon: ['transition-transform duration-200', open ? 'rotate-180' : undefined].filter(Boolean).join(' ')
}"
@@ -93,7 +73,7 @@ const items = computed(() => {
:key="value"
color="neutral"
variant="ghost"
:to="githubLink"
:to="`https://github.com/nuxt/${value}`"
target="_blank"
icon="i-simple-icons-github"
aria-label="GitHub"
@@ -102,7 +82,7 @@ const items = computed(() => {
</template>
<template #body>
<UNavigationMenu orientation="vertical" :items="mobileLinks" class="-mx-2.5" />
<UNavigationMenu orientation="vertical" :items="mobileLinks" class="-mx-2.5" default-open />
<USeparator type="dashed" class="mt-4 mb-6" />
@@ -116,7 +96,7 @@ const items = computed(() => {
<span class="inline-flex items-center gap-0.5">
{{ link.title }}
<sup v-if="link.module === 'ui-pro'" class="text-[8px] font-medium text-primary">PRO</sup>
<sup v-if="link.module === 'ui-pro'" class="text-[8px] font-medium text-(--ui-primary)">PRO</sup>
</span>
</template>
</UContentNavigation>

View File

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

View File

@@ -1,6 +1,4 @@
<script setup lang="ts">
import { kebabCase } from 'scule'
interface Star {
x: number
y: number
@@ -14,7 +12,6 @@ const props = withDefaults(defineProps<{
color?: string
size?: { min: number, max: number }
speed?: 'slow' | 'normal' | 'fast'
isIndex?: boolean
}>(), {
starCount: 50,
color: 'var(--ui-primary)',
@@ -22,12 +19,9 @@ const props = withDefaults(defineProps<{
min: 1,
max: 3
}),
speed: 'normal',
isIndex: false
speed: 'normal'
})
const route = useRoute()
// Generate random stars
const generateStars = (count: number): Star[] => {
return Array.from({ length: count }, () => {
@@ -41,7 +35,7 @@ const generateStars = (count: number): Star[] => {
}
// Generate all stars
const stars = useState<Star[]>(`${kebabCase(route.path)}-sky`, () => generateStars(props.starCount))
const stars = ref<Star[]>(generateStars(props.starCount))
// Compute twinkle animation duration based on speed
const twinkleDuration = computed(() => {
@@ -55,21 +49,23 @@ const twinkleDuration = computed(() => {
</script>
<template>
<div class="absolute pointer-events-none z-[-1] overflow-hidden" :class="isIndex ? 'inset-y-0 left-4 right-4 lg:right-[50%]' : 'inset-0'">
<div
v-for="star in stars"
:key="star.id"
class="star absolute"
:style="{
'left': `${star.x}%`,
'top': `${star.y}%`,
'transform': 'translate(-50%, -50%)',
'--star-size': `${star.size}px`,
'--star-color': color,
'--twinkle-delay': `${star.twinkleDelay}s`,
'--twinkle-duration': twinkleDuration
}"
/>
<div class="absolute pointer-events-none z-[-1] inset-y-0 left-4 right-4 lg:right-[50%] overflow-hidden">
<ClientOnly>
<div
v-for="star in stars"
:key="star.id"
class="star absolute"
:style="{
'left': `${star.x}%`,
'top': `${star.y}%`,
'transform': 'translate(-50%, -50%)',
'--star-size': `${star.size}px`,
'--star-color': color,
'--twinkle-delay': `${star.twinkleDelay}s`,
'--twinkle-duration': twinkleDuration
}"
/>
</ClientOnly>
</div>
</template>

View File

@@ -1,12 +1,4 @@
<script setup lang="ts">
import { kebabCase } from 'scule'
interface Star {
x: number
y: number
size: number
}
const props = withDefaults(defineProps<{
starCount?: number
color?: string
@@ -22,10 +14,8 @@ const props = withDefaults(defineProps<{
})
})
const route = useRoute()
// Generate random star positions and sizes
const generateStars = (count: number): Star[] => {
const generateStars = (count: number) => {
return Array.from({ length: count }, () => ({
x: Math.floor(Math.random() * 2000),
y: Math.floor(Math.random() * 2000),
@@ -35,58 +25,52 @@ const generateStars = (count: number): Star[] => {
}))
}
// Define speed configurations once
const speedMap = {
slow: { duration: 200, opacity: 0.5, ratio: 0.3 },
normal: { duration: 150, opacity: 0.75, ratio: 0.3 },
fast: { duration: 100, opacity: 1, ratio: 0.4 }
}
// Use a more efficient approach to generate and store stars
const stars = useState<{ slow: Star[], normal: Star[], fast: Star[] }>(`${kebabCase(route.path)}-stars`, () => {
return {
slow: generateStars(Math.floor(props.starCount * speedMap.slow.ratio)),
normal: generateStars(Math.floor(props.starCount * speedMap.normal.ratio)),
fast: generateStars(Math.floor(props.starCount * speedMap.fast.ratio))
}
})
// Compute star layers with different speeds and opacities
const starLayers = computed(() => [
{ stars: stars.value.fast, ...speedMap.fast },
{ stars: stars.value.normal, ...speedMap.normal },
{ stars: stars.value.slow, ...speedMap.slow }
])
const starLayers = computed(() => {
const speedMap = {
slow: { duration: 200, opacity: 0.5 },
normal: { duration: 150, opacity: 0.75 },
fast: { duration: 100, opacity: 1 }
}
return [
{ stars: generateStars(props.starCount), ...speedMap.fast },
{ stars: generateStars(Math.floor(props.starCount * 0.6)), ...speedMap.normal },
{ stars: generateStars(Math.floor(props.starCount * 0.3)), ...speedMap.slow }
]
})
</script>
<template>
<div class="absolute pointer-events-none z-[-1] inset-y-0 inset-x-5 sm:inset-x-7 lg:inset-x-9 overflow-hidden">
<div class="stars size-full absolute inset-x-0 top-0">
<div
v-for="(layer, index) in starLayers"
:key="index"
class="star-layer"
:style="{
'--star-duration': `${layer.duration}s`,
'--star-opacity': layer.opacity,
'--star-color': color
}"
>
<ClientOnly>
<div class="stars size-full absolute inset-x-0 top-0">
<div
v-for="(star, starIndex) in layer.stars"
:key="starIndex"
class="star absolute rounded-full"
v-for="(layer, index) in starLayers"
:key="index"
class="star-layer"
:style="{
left: `${star.x}px`,
top: `${star.y}px`,
width: `${star.size}px`,
height: `${star.size}px`,
backgroundColor: 'var(--star-color)',
opacity: 'var(--star-opacity)'
'--star-duration': `${layer.duration}s`,
'--star-opacity': layer.opacity,
'--star-color': color
}"
/>
>
<div
v-for="(star, starIndex) in layer.stars"
:key="starIndex"
class="star absolute rounded-full"
:style="{
left: `${star.x}px`,
top: `${star.y}px`,
width: `${star.size}px`,
height: `${star.size}px`,
backgroundColor: 'var(--star-color)',
opacity: 'var(--star-opacity)'
}"
/>
</div>
</div>
</div>
</ClientOnly>
</div>
</template>

View File

@@ -1,6 +1,5 @@
<!-- eslint-disable no-useless-escape -->
<script setup lang="ts">
import type { ChipProps } from '@nuxt/ui'
import json5 from 'json5'
import { upperFirst, camelCase, kebabCase } from 'scule'
import { hash } from 'ohash'
@@ -54,8 +53,6 @@ const props = defineProps<{
hide?: string[]
/** List of props to externalize in script setup */
external?: string[]
/** The types of the externalized props */
externalTypes?: string[]
/** List of props to use with `v-model` */
model?: string[]
/** List of props to cast from code and selection */
@@ -153,8 +150,7 @@ const options = computed(() => {
const items = propItems.length
? propItems.map((item: any) => ({
value: item,
label: String(item),
chip: key.toLowerCase().endsWith('color') ? { color: item } : undefined
label: String(item)
}))
: prop?.type === 'boolean' || prop?.type === 'boolean | undefined'
? [{ value: true, label: 'true' }, { value: false, label: 'false' }]
@@ -213,21 +209,11 @@ ${props.slots?.default}
code += `
<script setup lang="ts">
`
if (props.externalTypes?.length) {
const removeArrayBrackets = (type: string): string => type.endsWith('[]') ? removeArrayBrackets(type.slice(0, -2)) : type
const types = props.externalTypes.map(type => removeArrayBrackets(type))
code += `import type { ${types.join(', ')} } from '@nuxt/ui${props.pro ? '-pro' : ''}'
`
}
for (const [i, key] of props.external.entries()) {
for (const key of props.external) {
const cast = props.cast?.[key]
const value = cast ? castMap[cast]!.template(componentProps[key]) : json5.stringify(componentProps[key], null, 2)?.replace(/,([ |\t\n]+[}|\]])/g, '$1')
const type = props.externalTypes?.[i] ? `<${props.externalTypes[i]}>` : ''
code += `const ${key === 'modelValue' ? 'value' : key} = ref${type}(${value})
code += `const ${key === 'modelValue' ? 'value' : key} = ref(${value})
`
}
code += `<\/script>
@@ -329,16 +315,16 @@ const { data: ast } = await useAsyncData(`component-code-${name}-${hash({ props:
<template>
<div class="my-5">
<div class="relative">
<div v-if="options.length" class="flex flex-wrap items-center gap-2.5 border border-muted border-b-0 relative rounded-t-md px-4 py-2.5 overflow-x-auto">
<div>
<div v-if="options.length" class="flex flex-wrap items-center gap-2.5 border border-(--ui-border-muted) border-b-0 relative rounded-t-[calc(var(--ui-radius)*1.5)] px-4 py-2.5 overflow-x-auto">
<template v-for="option in options" :key="option.name">
<UFormField
:label="option.label"
size="sm"
class="inline-flex ring ring-accented rounded-sm"
class="inline-flex ring ring-(--ui-border-accented) rounded-(--ui-radius)"
:ui="{
wrapper: 'bg-elevated/50 rounded-l-sm flex border-r border-accented',
label: 'text-muted px-2 py-1.5',
wrapper: 'bg-(--ui-bg-elevated)/50 rounded-l-(--ui-radius) flex border-r border-(--ui-border-accented)',
label: 'text-(--ui-text-muted) px-2 py-1.5',
container: 'mt-0'
}"
>
@@ -349,7 +335,7 @@ const { data: ast } = await useAsyncData(`component-code-${name}-${hash({ props:
value-key="value"
color="neutral"
variant="soft"
class="rounded-sm rounded-l-none min-w-12"
class="rounded-(--ui-radius) rounded-l-none min-w-12"
:class="[option.name.toLowerCase().endsWith('color') && 'pl-6']"
:ui="{ itemLeadingChip: 'size-2' }"
@update:model-value="setComponentProp(option.name, $event)"
@@ -360,7 +346,7 @@ const { data: ast } = await useAsyncData(`component-code-${name}-${hash({ props:
inset
standalone
:color="(modelValue as any)"
:size="(ui.itemLeadingChipSize() as ChipProps['size'])"
:size="ui.itemLeadingChipSize()"
class="size-2"
/>
</template>
@@ -371,14 +357,14 @@ const { data: ast } = await useAsyncData(`component-code-${name}-${hash({ props:
:model-value="getComponentProp(option.name)"
color="neutral"
variant="soft"
:ui="{ base: 'rounded-sm rounded-l-none min-w-12' }"
:ui="{ base: 'rounded-(--ui-radius) rounded-l-none min-w-12' }"
@update:model-value="setComponentProp(option.name, $event)"
/>
</UFormField>
</template>
</div>
<div v-if="component" class="flex justify-center border border-b-0 border-muted relative p-4 z-[1]" :class="[!options.length && 'rounded-t-md', props.class, { 'overflow-hidden': props.overflowHidden }]">
<div v-if="component" class="flex justify-center border border-b-0 border-(--ui-border-muted) relative p-4 z-[1]" :class="[!options.length && 'rounded-t-[calc(var(--ui-radius)*1.5)]', props.class, { 'overflow-hidden': props.overflowHidden }]">
<component :is="component" v-bind="{ ...componentProps, ...componentEvents }">
<template v-for="slot in Object.keys(slots || {})" :key="slot" #[slot]>
<slot :name="slot" mdc-unwrap="p">

View File

@@ -1,5 +1,4 @@
<script setup lang="ts">
import type { ChipProps } from '@nuxt/ui'
import { camelCase } from 'scule'
import { useElementSize } from '@vueuse/core'
import { get, set } from '#ui/utils'
@@ -150,8 +149,8 @@ const urlSearchParams = computed(() => {
<template>
<div ref="el" class="my-5">
<template v-if="preview">
<div class="border border-muted relative z-[1]" :class="[{ 'border-b-0 rounded-t-md': props.source, 'rounded-md': !props.source, 'overflow-hidden': props.overflowHidden }]">
<div v-if="props.options?.length || !!slots.options" class="flex gap-4 p-4 border-b border-muted">
<div class="border border-(--ui-border-muted) relative z-[1]" :class="[{ 'border-b-0 rounded-t-[calc(var(--ui-radius)*1.5)]': props.source, 'rounded-[calc(var(--ui-radius)*1.5)]': !props.source, 'overflow-hidden': props.overflowHidden }]">
<div v-if="props.options?.length || !!slots.options" class="flex gap-4 p-4 border-b border-(--ui-border-muted)">
<slot name="options" />
<UFormField
@@ -160,10 +159,10 @@ const urlSearchParams = computed(() => {
:label="option.label"
:name="option.name"
size="sm"
class="inline-flex ring ring-accented rounded-sm"
class="inline-flex ring ring-(--ui-border-accented) rounded-(--ui-radius)"
:ui="{
wrapper: 'bg-elevated/50 rounded-l-sm flex border-r border-accented',
label: 'text-muted px-2 py-1.5',
wrapper: 'bg-(--ui-bg-elevated)/50 rounded-l-(--ui-radius) flex border-r border-(--ui-border-accented)',
label: 'text-(--ui-text-muted) px-2 py-1.5',
container: 'mt-0'
}"
>
@@ -175,7 +174,7 @@ const urlSearchParams = computed(() => {
:value-key="option.name.toLowerCase().endsWith('color') ? 'value' : undefined"
color="neutral"
variant="soft"
class="rounded-sm rounded-l-none min-w-12"
class="rounded-(--ui-radius) rounded-l-none min-w-12"
:multiple="option.multiple"
:class="[option.name.toLowerCase().endsWith('color') && 'pl-6']"
:ui="{ itemLeadingChip: 'size-2' }"
@@ -186,7 +185,7 @@ const urlSearchParams = computed(() => {
inset
standalone
:color="(modelValue as any)"
:size="(ui.itemLeadingChipSize() as ChipProps['size'])"
:size="ui.itemLeadingChipSize()"
class="size-2"
/>
</template>
@@ -196,7 +195,7 @@ const urlSearchParams = computed(() => {
:model-value="get(optionsValues, option.name)"
color="neutral"
variant="soft"
:ui="{ base: 'rounded-sm rounded-l-none min-w-12' }"
:ui="{ base: 'rounded-(--ui-radius) rounded-l-none min-w-12' }"
@update:model-value="set(optionsValues, option.name, $event)"
/>
</UFormField>

View File

@@ -112,7 +112,7 @@ const metaProps: ComputedRef<ComponentMeta['props']> = computed(() => {
<ProseTd>
<HighlightInlineType v-if="prop.type" :type="prop.type" />
<MDC v-if="prop.description" :value="prop.description" class="text-toned mt-1" :cache-key="`${kebabCase(route.path)}-${prop.name}-description`" />
<MDC v-if="prop.description" :value="prop.description" class="text-(--ui-text-toned) mt-1" :cache-key="`${kebabCase(route.path)}-${prop.name}-description`" />
<ComponentPropsLinks v-if="prop.tags?.length" :prop="prop" />
<ComponentPropsSchema v-if="prop.schema" :prop="prop" :ignore="ignore" />

View File

@@ -38,12 +38,12 @@ const schemaProps = computed(() => {
</script>
<template>
<ProseCollapsible v-if="schemaProps?.length" class="mt-1 mb-0">
<ProseCollapsible v-if="schemaProps?.length" class="mt-1">
<ProseUl>
<ProseLi v-for="schemaProp in schemaProps" :key="schemaProp.name">
<HighlightInlineType :type="`${schemaProp.name}${schemaProp.required === false ? '?' : ''}: ${schemaProp.type}`" />
<MDC v-if="schemaProp.description" :value="schemaProp.description" class="text-muted my-1" :cache-key="`${kebabCase(route.path)}-${prop.name}-${schemaProp.name}-description`" />
<MDC v-if="schemaProp.description" :value="schemaProp.description" class="text-(--ui-text-muted) my-1" :cache-key="`${kebabCase(route.path)}-${prop.name}-${schemaProp.name}-description`" />
</ProseLi>
</ProseUl>
</ProseCollapsible>

View File

@@ -36,7 +36,7 @@ const meta = await fetchComponentMeta(name as any)
<ProseTd>
<HighlightInlineType v-if="slot.type" :type="slot.type" />
<MDC v-if="slot.description" :value="slot.description" class="text-toned mt-1" :cache-key="`${kebabCase(route.path)}-${slot.name}-description`" />
<MDC v-if="slot.description" :value="slot.description" class="text-(--ui-text-toned) mt-1" :cache-key="`${kebabCase(route.path)}-${slot.name}-description`" />
</ProseTd>
</ProseTr>
</ProseTbody>

View File

@@ -1,6 +1,6 @@
<template>
<div class="relative overflow-hidden rounded-sm border border-dashed border-accented opacity-75 px-4 flex items-center justify-center">
<svg class="absolute inset-0 h-full w-full stroke-inverted/10" fill="none">
<div class="relative overflow-hidden rounded-(--ui-radius) border border-dashed border-(--ui-border-accented) opacity-75 px-4 flex items-center justify-center">
<svg class="absolute inset-0 h-full w-full stroke-(--ui-border-inverted)/10" fill="none">
<defs>
<pattern
id="pattern-5c1e4f0e-62d5-498b-8ff0-cf77bb448c8e"

View File

@@ -11,28 +11,19 @@ function getEmojiFlag(locale: string): string {
const languageToCountry: Record<string, string> = {
ar: 'sa', // Arabic -> Saudi Arabia
bn: 'bd', // Bengali -> Bangladesh
ca: 'es', // Catalan -> Spain
ckb: 'iq', // Central Kurdish -> Iraq
cs: 'cz', // Czech -> Czech Republic (note: modern country code is actually 'cz')
da: 'dk', // Danish -> Denmark
el: 'gr', // Greek -> Greece
en: 'gb', // English -> Great Britain
et: 'ee', // Estonian -> Estonia
en: 'gb', // English -> Great Britain
he: 'il', // Hebrew -> Israel
hi: 'in', // Hindi -> India
hy: 'am', // Armenian -> Armenia
ja: 'jp', // Japanese -> Japan
kk: 'kz', // Kazakh -> Kazakhstan
km: 'kh', // Khmer -> Cambodia
ko: 'kr', // Korean -> South Korea
ky: 'kg', // Kyrgyz -> Kyrgyzstan
lb: 'lu', // Luxembourgish -> Luxembourg
ms: 'my', // Malay -> Malaysia
nb: 'no', // Norwegian Bokmål -> Norway
sl: 'si', // Slovenian -> Slovenia
sv: 'se', // Swedish -> Sweden
uk: 'ua', // Ukrainian -> Ukraine
ur: 'pk', // Urdu -> Pakistan
vi: 'vn' // Vietnamese -> Vietnam
}

View File

@@ -1,7 +1,5 @@
<script setup lang="ts">
import type { AccordionItem } from '@nuxt/ui'
const items: AccordionItem[] = [
const items = [
{
label: 'Icons',
icon: 'i-lucide-smile'

View File

@@ -1,7 +1,5 @@
<script setup lang="ts">
import type { AccordionItem } from '@nuxt/ui'
const items: AccordionItem[] = [
const items = [
{
label: 'Icons',
icon: 'i-lucide-smile'
@@ -20,7 +18,7 @@ const items: AccordionItem[] = [
<template>
<UAccordion :items="items">
<template #content="{ item }">
<p class="pb-3.5 text-sm text-muted">
<p class="pb-3.5 text-sm text-(--ui-text-muted)">
This is the {{ item.label }} panel.
</p>
</template>

View File

@@ -1,6 +1,4 @@
<script setup lang="ts">
import type { AccordionItem } from '@nuxt/ui'
const items = [
{
label: 'Icons',
@@ -10,7 +8,7 @@ const items = [
{
label: 'Colors',
icon: 'i-lucide-swatch-book',
slot: 'colors' as const,
slot: 'colors',
content: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
},
{
@@ -18,13 +16,13 @@ const items = [
icon: 'i-lucide-box',
content: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
}
] satisfies AccordionItem[]
]
</script>
<template>
<UAccordion :items="items">
<template #colors="{ item }">
<p class="text-sm pb-3.5 text-primary">
<p class="text-sm pb-3.5 text-(--ui-primary)">
{{ item.content }}
</p>
</template>

View File

@@ -1,32 +0,0 @@
<script setup lang="ts">
import type { AccordionItem } from '@nuxt/ui'
import { useSortable } from '@vueuse/integrations/useSortable'
const items = shallowRef<AccordionItem[]>([
{
label: 'Icons',
icon: 'i-lucide-smile',
content: 'You have nothing to do, @nuxt/icon will handle it automatically.'
},
{
label: 'Colors',
icon: 'i-lucide-swatch-book',
content: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
},
{
label: 'Components',
icon: 'i-lucide-box',
content: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
}
])
const accordion = useTemplateRef<HTMLElement>('accordion')
useSortable(accordion, items, {
animation: 150
})
</script>
<template>
<UAccordion ref="accordion" :items="items" />
</template>

View File

@@ -1,7 +1,5 @@
<script setup lang="ts">
import type { AccordionItem } from '@nuxt/ui'
const items: AccordionItem[] = [
const items = [
{
label: 'Icons',
icon: 'i-lucide-smile',

View File

@@ -3,7 +3,7 @@
<ULink
to="https://github.com/benjamincanac"
target="_blank"
class="hover:ring-primary transition"
class="hover:ring-(--ui-primary) transition"
raw
>
<UAvatar
@@ -15,7 +15,7 @@
<ULink
to="https://github.com/romhml"
target="_blank"
class="hover:ring-primary transition"
class="hover:ring-(--ui-primary) transition"
raw
>
<UAvatar
@@ -27,7 +27,7 @@
<ULink
to="https://github.com/noook"
target="_blank"
class="hover:ring-primary transition"
class="hover:ring-(--ui-primary) transition"
raw
>
<UAvatar

View File

@@ -1,35 +1,24 @@
<script setup lang="ts">
import type { BreadcrumbItem } from '@nuxt/ui'
const items = [
{
label: 'Home',
to: '/'
},
{
slot: 'dropdown' as const,
icon: 'i-lucide-ellipsis',
children: [
{
label: 'Documentation'
},
{
label: 'Themes'
},
{
label: 'GitHub'
}
]
},
{
label: 'Components',
to: '/components'
},
{
label: 'Breadcrumb',
to: '/components/breadcrumb'
}
] satisfies BreadcrumbItem[]
const items = [{
label: 'Home',
to: '/'
}, {
slot: 'dropdown',
icon: 'i-lucide-ellipsis',
children: [{
label: 'Documentation'
}, {
label: 'Themes'
}, {
label: 'GitHub'
}]
}, {
label: 'Components',
to: '/components'
}, {
label: 'Breadcrumb',
to: '/components/breadcrumb'
}]
</script>
<template>

View File

@@ -1,26 +1,20 @@
<script setup lang="ts">
import type { BreadcrumbItem } from '@nuxt/ui'
const items: BreadcrumbItem[] = [
{
label: 'Home',
to: '/'
},
{
label: 'Components',
to: '/components'
},
{
label: 'Breadcrumb',
to: '/components/breadcrumb'
}
]
const items = [{
label: 'Home',
to: '/'
}, {
label: 'Components',
to: '/components'
}, {
label: 'Breadcrumb',
to: '/components/breadcrumb'
}]
</script>
<template>
<UBreadcrumb :items="items">
<template #separator>
<span class="mx-2 text-muted">/</span>
<span class="mx-2 text-(--ui-text-muted)">/</span>
</template>
</UBreadcrumb>
</template>

View File

@@ -1,30 +1,21 @@
<script setup lang="ts">
import type { DropdownMenuItem } from '@nuxt/ui'
const items: DropdownMenuItem[] = [
{
label: 'Team',
icon: 'i-lucide-users'
},
{
label: 'Invite users',
icon: 'i-lucide-user-plus',
children: [
{
label: 'Invite by email',
icon: 'i-lucide-send-horizontal'
},
{
label: 'Invite by link',
icon: 'i-lucide-link'
}
]
},
{
label: 'New team',
icon: 'i-lucide-plus'
}
]
const items = [{
label: 'Team',
icon: 'i-lucide-users'
}, {
label: 'Invite users',
icon: 'i-lucide-user-plus',
children: [{
label: 'Invite by email',
icon: 'i-lucide-send-horizontal'
}, {
label: 'Invite by link',
icon: 'i-lucide-link'
}]
}, {
label: 'New team',
icon: 'i-lucide-plus'
}]
</script>
<template>

View File

@@ -1,21 +0,0 @@
<script setup lang="ts">
import { CalendarDate } from '@internationalized/date'
const date = shallowRef(new CalendarDate(2025, 4, 2))
</script>
<template>
<div class="flex flex-col gap-4">
<UCalendar v-model="date" :month-controls="false" :year-controls="false" />
<div class="flex justify-between gap-4">
<UButton color="neutral" variant="outline" @click="date = date.subtract({ months: 1 })">
Prev
</UButton>
<UButton color="neutral" variant="outline" @click="date = date.add({ months: 1 })">
Next
</UButton>
</div>
</div>
</template>

View File

@@ -1,58 +0,0 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
const carousel = useTemplateRef('carousel')
const activeIndex = ref(0)
function onClickPrev() {
activeIndex.value--
}
function onClickNext() {
activeIndex.value++
}
function onSelect(index: number) {
activeIndex.value = index
}
function select(index: number) {
activeIndex.value = index
carousel.value?.emblaApi?.scrollTo(index)
}
</script>
<template>
<div class="flex-1 w-full">
<UCarousel
ref="carousel"
v-slot="{ item }"
arrows
:items="items"
:prev="{ onClick: onClickPrev }"
:next="{ onClick: onClickNext }"
class="w-full max-w-xs mx-auto"
@select="onSelect"
>
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
<div class="flex gap-1 justify-between pt-4 max-w-xs mx-auto">
<div
v-for="(item, index) in items"
:key="index"
class="size-11 opacity-25 hover:opacity-100 transition-opacity"
:class="{ 'opacity-100': activeIndex === index }"
@click="select(index)"
>
<img :src="item" width="44" height="44" class="rounded-lg">
</div>
</div>
</div>
</template>

View File

@@ -1,79 +1,76 @@
<script setup lang="ts">
const groups = [
{
id: 'settings',
items: [
{
label: 'Profile',
icon: 'i-lucide-user',
kbds: ['meta', 'P']
},
{
label: 'Billing',
icon: 'i-lucide-credit-card',
kbds: ['meta', 'B'],
slot: 'billing' as const
},
{
label: 'Notifications',
icon: 'i-lucide-bell'
},
{
label: 'Security',
icon: 'i-lucide-lock'
}
]
},
{
id: 'users',
label: 'Users',
slot: 'users' as const,
items: [
{
label: 'Benjamin Canac',
suffix: 'benjamincanac',
to: 'https://github.com/benjamincanac',
target: '_blank'
},
{
label: 'Sylvain Marroufin',
suffix: 'smarroufin',
to: 'https://github.com/smarroufin',
target: '_blank'
},
{
label: 'Sébastien Chopin',
suffix: 'atinux',
to: 'https://github.com/atinux',
target: '_blank'
},
{
label: 'Romain Hamel',
suffix: 'romhml',
to: 'https://github.com/romhml',
target: '_blank'
},
{
label: 'Haytham A. Salama',
suffix: 'Haythamasalama',
to: 'https://github.com/Haythamasalama',
target: '_blank'
},
{
label: 'Daniel Roe',
suffix: 'danielroe',
to: 'https://github.com/danielroe',
target: '_blank'
},
{
label: 'Neil Richter',
suffix: 'noook',
to: 'https://github.com/noook',
target: '_blank'
}
]
}
]
const groups = [{
id: 'settings',
items: [
{
label: 'Profile',
icon: 'i-lucide-user',
kbds: ['meta', 'P']
},
{
label: 'Billing',
icon: 'i-lucide-credit-card',
kbds: ['meta', 'B'],
slot: 'billing'
},
{
label: 'Notifications',
icon: 'i-lucide-bell'
},
{
label: 'Security',
icon: 'i-lucide-lock'
}
]
}, {
id: 'users',
label: 'Users',
slot: 'users',
items: [
{
label: 'Benjamin Canac',
suffix: 'benjamincanac',
to: 'https://github.com/benjamincanac',
target: '_blank'
},
{
label: 'Sylvain Marroufin',
suffix: 'smarroufin',
to: 'https://github.com/smarroufin',
target: '_blank'
},
{
label: 'Sébastien Chopin',
suffix: 'atinux',
to: 'https://github.com/atinux',
target: '_blank'
},
{
label: 'Romain Hamel',
suffix: 'romhml',
to: 'https://github.com/romhml',
target: '_blank'
},
{
label: 'Haytham A. Salama',
suffix: 'Haythamasalama',
to: 'https://github.com/Haythamasalama',
target: '_blank'
},
{
label: 'Daniel Roe',
suffix: 'danielroe',
to: 'https://github.com/danielroe',
target: '_blank'
},
{
label: 'Neil Richter',
suffix: 'noook',
to: 'https://github.com/noook',
target: '_blank'
}
]
}]
</script>
<template>
@@ -83,7 +80,7 @@ const groups = [
</template>
<template #billing-label="{ item }">
<span class="font-medium text-primary">{{ item.label }}</span>
{{ item.label }}
<UBadge variant="subtle" size="sm">
50% off

View File

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

View File

@@ -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

@@ -1,10 +1,8 @@
<script setup lang="ts">
import type { ContextMenuItem } from '@nuxt/ui'
const showSidebar = ref(true)
const showToolbar = ref(false)
const items = computed<ContextMenuItem[]>(() => [{
const items = computed(() => [{
label: 'View',
type: 'label' as const
}, {
@@ -35,7 +33,7 @@ const items = computed<ContextMenuItem[]>(() => [{
<template>
<UContextMenu :items="items" :ui="{ content: 'w-48' }">
<div class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72">
<div class="flex items-center justify-center rounded-md border border-dashed border-(--ui-border-accented) text-sm aspect-video w-72">
Right click here
</div>
</UContextMenu>

View File

@@ -1,7 +1,5 @@
<script setup lang="ts">
import type { ContextMenuItem } from '@nuxt/ui'
const items: ContextMenuItem[][] = [
const items = [
[
{
label: 'View',
@@ -28,7 +26,7 @@ const items: ContextMenuItem[][] = [
<template>
<UContextMenu :items="items" :ui="{ content: 'w-48' }">
<div class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72">
<div class="flex items-center justify-center rounded-md border border-dashed border-(--ui-border-accented) text-sm aspect-video w-72">
Right click here
</div>
</UContextMenu>

View File

@@ -1,25 +1,19 @@
<script setup lang="ts">
import type { ContextMenuItem } from '@nuxt/ui'
const loading = ref(true)
const items = [
{
label: 'Refresh the Page',
slot: 'refresh' as const
},
{
label: 'Clear Cookies and Refresh'
},
{
label: 'Clear Cache and Refresh'
}
] satisfies ContextMenuItem[]
const items = [{
label: 'Refresh the Page',
slot: 'refresh'
}, {
label: 'Clear Cookies and Refresh'
}, {
label: 'Clear Cache and Refresh'
}]
</script>
<template>
<UContextMenu :items="items" :ui="{ content: 'w-48' }">
<div class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72">
<div class="flex items-center justify-center rounded-md border border-dashed border-(--ui-border-accented) text-sm aspect-video w-72">
Right click here
</div>
@@ -28,7 +22,7 @@ const items = [
</template>
<template #refresh-trailing>
<UIcon v-if="loading" name="i-lucide-loader-circle" class="shrink-0 size-5 text-primary animate-spin" />
<UIcon v-if="loading" name="i-lucide-refresh-cw" class="shrink-0 size-5 text-(--ui-primary) animate-spin" />
</template>
</UContextMenu>
</template>

View File

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

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

@@ -1,43 +0,0 @@
<script lang="ts" setup>
import { createReusableTemplate, useMediaQuery } from '@vueuse/core'
const [DefineFormTemplate, ReuseFormTemplate] = createReusableTemplate()
const isDesktop = useMediaQuery('(min-width: 768px)')
const open = ref(false)
const state = reactive({
email: undefined
})
const title = 'Edit profile'
const description = 'Make changes to your profile here. Click save when you\'re done.'
</script>
<template>
<DefineFormTemplate>
<UForm :state="state" class="space-y-4">
<UFormField label="Email" name="email" required>
<UInput v-model="state.email" placeholder="shadcn@example.com" required />
</UFormField>
<UButton label="Save changes" type="submit" />
</UForm>
</DefineFormTemplate>
<UModal v-if="isDesktop" v-model:open="open" :title="title" :description="description">
<UButton label="Edit profile" color="neutral" variant="outline" />
<template #body>
<ReuseFormTemplate />
</template>
</UModal>
<UDrawer v-else v-model:open="open" :title="title" :description="description">
<UButton label="Edit profile" color="neutral" variant="outline" />
<template #body>
<ReuseFormTemplate />
</template>
</UDrawer>
</template>

View File

@@ -1,6 +1,4 @@
<script setup lang="ts">
import type { DropdownMenuItem } from '@nuxt/ui'
const showBookmarks = ref(true)
const showHistory = ref(false)
const showDownloads = ref(false)
@@ -38,7 +36,7 @@ const items = computed(() => [{
onUpdateChecked(checked: boolean) {
showDownloads.value = checked
}
}] satisfies DropdownMenuItem[])
}])
</script>
<template>

View File

@@ -1,7 +1,5 @@
<script setup lang="ts">
import type { DropdownMenuItem } from '@nuxt/ui'
const items: DropdownMenuItem[][] = [
const items = [
[
{
label: 'View',
@@ -19,7 +17,7 @@ const items: DropdownMenuItem[][] = [
[
{
label: 'Delete',
color: 'error',
color: 'error' as const,
icon: 'i-lucide-trash'
}
]
@@ -29,5 +27,9 @@ const items: DropdownMenuItem[][] = [
<template>
<UDropdownMenu :items="items" :ui="{ content: 'w-48' }">
<UButton label="Open" color="neutral" variant="outline" icon="i-lucide-menu" />
<template #profile-trailing>
<UIcon name="i-lucide-badge-check" class="shrink-0 size-5 text-(--ui-primary)" />
</template>
</UDropdownMenu>
</template>

View File

@@ -1,19 +1,15 @@
<script setup lang="ts">
import type { DropdownMenuItem } from '@nuxt/ui'
const items = [
{
label: 'Profile',
icon: 'i-lucide-user',
slot: 'profile' as const
}, {
label: 'Billing',
icon: 'i-lucide-credit-card'
}, {
label: 'Settings',
icon: 'i-lucide-cog'
}
] satisfies DropdownMenuItem[]
const items = [{
label: 'Profile',
icon: 'i-lucide-user',
slot: 'profile'
}, {
label: 'Billing',
icon: 'i-lucide-credit-card'
}, {
label: 'Settings',
icon: 'i-lucide-cog'
}]
</script>
<template>
@@ -21,7 +17,7 @@ const items = [
<UButton label="Open" color="neutral" variant="outline" icon="i-lucide-menu" />
<template #profile-trailing>
<UIcon name="i-lucide-badge-check" class="shrink-0 size-5 text-primary" />
<UIcon name="i-lucide-badge-check" class="shrink-0 size-5 text-(--ui-primary)" />
</template>
</UDropdownMenu>
</template>

View File

@@ -1,24 +1,20 @@
<script setup lang="ts">
import type { DropdownMenuItem } from '@nuxt/ui'
const open = ref(false)
defineShortcuts({
o: () => open.value = !open.value
})
const items: DropdownMenuItem[] = [
{
label: 'Profile',
icon: 'i-lucide-user'
}, {
label: 'Billing',
icon: 'i-lucide-credit-card'
}, {
label: 'Settings',
icon: 'i-lucide-cog'
}
]
const items = [{
label: 'Profile',
icon: 'i-lucide-user'
}, {
label: 'Billing',
icon: 'i-lucide-credit-card'
}, {
label: 'Settings',
icon: 'i-lucide-cog'
}]
</script>
<template>

View File

@@ -14,7 +14,7 @@ const validate = (state: any): FormError[] => {
}
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<typeof state>) {
async function onSubmit(event: FormSubmitEvent<any>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}

View File

@@ -15,9 +15,6 @@ const schema = z.object({
select: z.string().refine(value => value === 'option-2', {
message: 'Select Option 2'
}),
selectMultiple: z.array(z.string()).refine(values => values.includes('option-2'), {
message: 'Include Option 2'
}),
selectMenu: z.any().refine(option => option?.value === 'option-2', {
message: 'Select Option 2'
}),
@@ -33,9 +30,6 @@ const schema = z.object({
radioGroup: z.string().refine(value => value === 'option-2', {
message: 'Select Option 2'
}),
checkboxGroup: z.any().refine(values => !!values?.find((option: any) => option === 'option-2'), {
message: 'Include Option 2'
}),
slider: z.number().max(20, { message: 'Must be less than 20' }),
pin: z.string().regex(/^\d$/).array().length(5)
})
@@ -53,7 +47,7 @@ const items = [
]
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
async function onSubmit(event: FormSubmitEvent<any>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
@@ -84,10 +78,6 @@ async function onSubmit(event: FormSubmitEvent<Schema>) {
<USelect v-model="state.select" :items="items" class="w-full" />
</UFormField>
<UFormField name="selectMultiple" label="Select (Multiple)">
<USelect v-model="state.selectMultiple" multiple :items="items" class="w-full" />
</UFormField>
<UFormField name="selectMenu" label="Select Menu">
<USelectMenu v-model="state.selectMenu" :items="items" class="w-full" />
</UFormField>
@@ -111,14 +101,11 @@ async function onSubmit(event: FormSubmitEvent<Schema>) {
<UFormField label="Textarea" name="textarea">
<UTextarea v-model="state.textarea" class="w-full" />
</UFormField>
<div class="flex gap-4">
<UFormField name="radioGroup">
<URadioGroup v-model="state.radioGroup" legend="Radio group" :items="items" />
</UFormField>
<UFormField name="checkboxGroup">
<UCheckboxGroup v-model="state.checkboxGroup" legend="Checkbox group" :items="items" />
</UFormField>
</div>
<UFormField name="radioGroup">
<URadioGroup v-model="state.radioGroup" legend="Radio group" :items="items" />
</UFormField>
<UFormField name="pin" label="Pin Input" :error-pattern="/(pin)\..*/">
<UPinInput v-model="state.pin" />
</UFormField>

View File

@@ -15,7 +15,7 @@ const state = reactive({
})
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<typeof state>) {
async function onSubmit(event: FormSubmitEvent<any>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}

View File

@@ -18,7 +18,7 @@ type NestedSchema = z.output<typeof nestedSchema>
const state = reactive<Partial<Schema & NestedSchema>>({ })
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
async function onSubmit(event: FormSubmitEvent<any>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
@@ -39,7 +39,7 @@ async function onSubmit(event: FormSubmitEvent<Schema>) {
<UCheckbox v-model="state.news" name="news" label="Register to our newsletter" @update:model-value="state.email = undefined" />
</div>
<UForm v-if="state.news" :state="state" :schema="nestedSchema" attach>
<UForm v-if="state.news" :state="state" :schema="nestedSchema">
<UFormField label="Email" name="email">
<UInput v-model="state.email" placeholder="john@lennon.com" />
</UFormField>

View File

@@ -34,7 +34,7 @@ function removeItem() {
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
async function onSubmit(event: FormSubmitEvent<any>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
@@ -51,14 +51,7 @@ async function onSubmit(event: FormSubmitEvent<Schema>) {
<UInput v-model="state.customer" placeholder="Wonka Industries" />
</UFormField>
<UForm
v-for="item, count in state.items"
:key="count"
:state="item"
:schema="itemSchema"
attach
class="flex gap-2"
>
<UForm v-for="item, count in state.items" :key="count" :state="item" :schema="itemSchema" class="flex gap-2">
<UFormField :label="!count ? 'Description' : undefined" name="description">
<UInput v-model="item.description" />
</UFormField>

View File

@@ -14,7 +14,7 @@ const validate = (state: any): FormError[] => {
}
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<typeof state>) {
async function onSubmit(event: FormSubmitEvent<any>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}

View File

@@ -22,7 +22,7 @@ async function onSubmit(event: FormSubmitEvent<Schema>) {
</script>
<template>
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
<UForm :schema="v.safeParser(schema)" :state="state" class="space-y-4" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>

View File

@@ -16,7 +16,7 @@ function onOpen() {
<template>
<UInputMenu
:items="countries"
:items="countries || []"
:loading="status === 'pending'"
label-key="name"
:search-input="{ icon: 'i-lucide-search' }"

View File

@@ -1,6 +1,4 @@
<script setup lang="ts">
import type { AvatarProps } from '@nuxt/ui'
const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', {
key: 'typicode-users',
transform: (data: { id: number, name: string }[]) => {
@@ -8,7 +6,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
label: user.name,
value: String(user.id),
avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` }
}))
})) || []
},
lazy: true
})
@@ -16,7 +14,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
<template>
<UInputMenu
:items="users"
:items="users || []"
:loading="status === 'pending'"
icon="i-lucide-user"
placeholder="Select user"
@@ -25,7 +23,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
<UAvatar
v-if="modelValue"
v-bind="modelValue.avatar"
:size="(ui.leadingAvatarSize() as AvatarProps['size'])"
:size="ui.leadingAvatarSize()"
:class="ui.leadingAvatar()"
/>
</template>

View File

@@ -1,6 +1,4 @@
<script setup lang="ts">
import type { AvatarProps } from '@nuxt/ui'
const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', {
key: 'typicode-users-email',
transform: (data: { id: number, name: string, email: string }[]) => {
@@ -9,7 +7,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
email: user.email,
value: String(user.id),
avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` }
}))
})) || []
},
lazy: true
})
@@ -17,7 +15,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
<template>
<UInputMenu
:items="users"
:items="users || []"
:loading="status === 'pending'"
:filter-fields="['label', 'email']"
icon="i-lucide-user"
@@ -28,7 +26,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
<UAvatar
v-if="modelValue"
v-bind="modelValue.avatar"
:size="(ui.leadingAvatarSize() as AvatarProps['size'])"
:size="ui.leadingAvatarSize()"
:class="ui.leadingAvatar()"
/>
</template>
@@ -36,7 +34,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
<template #item-label="{ item }">
{{ item.label }}
<span class="text-muted">
<span class="text-(--ui-text-muted)">
{{ item.email }}
</span>
</template>

View File

@@ -1,18 +1,16 @@
<script setup lang="ts">
import { refDebounced } from '@vueuse/core'
import type { AvatarProps } from '@nuxt/ui'
const searchTerm = ref('')
const searchTermDebounced = refDebounced(searchTerm, 200)
const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', {
key: 'typicode-users',
params: { q: searchTermDebounced },
transform: (data: { id: number, name: string }[]) => {
return data?.map(user => ({
label: user.name,
value: String(user.id),
avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` }
}))
})) || []
},
lazy: true
})
@@ -21,7 +19,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
<template>
<UInputMenu
v-model:search-term="searchTerm"
:items="users"
:items="users || []"
:loading="status === 'pending'"
ignore-filter
icon="i-lucide-user"
@@ -31,7 +29,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
<UAvatar
v-if="modelValue"
v-bind="modelValue.avatar"
:size="(ui.leadingAvatarSize() as AvatarProps['size'])"
:size="ui.leadingAvatarSize()"
:class="ui.leadingAvatar()"
/>
</template>

View File

@@ -1,6 +1,4 @@
<script setup lang="ts">
import type { InputMenuItem } from '@nuxt/ui'
const items = ref([
{
label: 'benjamincanac',
@@ -25,16 +23,8 @@ const items = ref([
src: 'https://github.com/noook.png',
alt: 'noook'
}
},
{
label: 'sandros94',
value: 'sandros94',
avatar: {
src: 'https://github.com/sandros94.png',
alt: 'sandros94'
}
}
] satisfies InputMenuItem[])
])
const value = ref(items.value[0])
</script>

View File

@@ -1,30 +1,27 @@
<script setup lang="ts">
import type { InputMenuItem, ChipProps } from '@nuxt/ui'
const items = ref([
{
label: 'bug',
value: 'bug',
chip: {
color: 'error'
color: 'error' as const
}
},
{
label: 'feature',
value: 'feature',
chip: {
color: 'success'
color: 'success' as const
}
},
{
label: 'enhancement',
value: 'enhancement',
chip: {
color: 'info'
color: 'info' as const
}
}
] satisfies InputMenuItem[])
])
const value = ref(items.value[0])
</script>
@@ -36,7 +33,7 @@ const value = ref(items.value[0])
v-bind="modelValue.chip"
inset
standalone
:size="(ui.itemLeadingChipSize() as ChipProps['size'])"
:size="ui.itemLeadingChipSize()"
:class="ui.itemLeadingChip()"
/>
</template>

View File

@@ -1,6 +1,4 @@
<script setup lang="ts">
import type { InputMenuItem } from '@nuxt/ui'
const items = ref([
{
label: 'Backlog',
@@ -22,8 +20,7 @@ const items = ref([
value: 'done',
icon: 'i-lucide-circle-check'
}
] satisfies InputMenuItem[])
])
const value = ref(items.value[0])
</script>

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,12 +10,12 @@ const domain = ref(domains[0])
v-model="value"
placeholder="nuxt"
:ui="{
base: 'pl-14.5',
base: 'pl-[57px]',
leading: 'pointer-events-none'
}"
>
<template #leading>
<p class="text-sm text-muted">
<p class="text-sm text-(--ui-text-muted)">
https://
</p>
</template>

View File

@@ -13,7 +13,7 @@ const maxLength = 15
<template #trailing>
<div
id="character-count"
class="text-xs text-muted tabular-nums"
class="text-xs text-(--ui-text-muted) tabular-nums"
aria-live="polite"
role="status"
>

View File

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

View File

@@ -4,8 +4,8 @@ const value = ref('')
<template>
<UInput v-model="value" placeholder="" :ui="{ base: 'peer' }">
<label class="pointer-events-none absolute left-0 -top-2.5 text-highlighted text-xs font-medium px-1.5 transition-all peer-focus:-top-2.5 peer-focus:text-highlighted peer-focus:text-xs peer-focus:font-medium peer-placeholder-shown:text-sm peer-placeholder-shown:text-dimmed peer-placeholder-shown:top-1.5 peer-placeholder-shown:font-normal">
<span class="inline-flex bg-default px-1">Email address</span>
<label class="pointer-events-none absolute left-0 -top-2.5 text-(--ui-text-highlighted) text-xs font-medium px-1.5 transition-all peer-focus:-top-2.5 peer-focus:text-(--ui-text-highlighted) peer-focus:text-xs peer-focus:font-medium peer-placeholder-shown:text-sm peer-placeholder-shown:text-(--ui-text-dimmed) peer-placeholder-shown:top-1.5 peer-placeholder-shown:font-normal">
<span class="inline-flex bg-(--ui-bg) px-1">Email address</span>
</label>
</UInput>
</template>

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

@@ -77,7 +77,7 @@ const text = computed(() => {
v-for="(req, index) in strength"
:key="index"
class="flex items-center gap-0.5"
:class="req.met ? 'text-success' : 'text-muted'"
:class="req.met ? 'text-(--ui-success)' : 'text-(--ui-text-muted)'"
>
<UIcon :name="req.met ? 'i-lucide-circle-check' : 'i-lucide-circle-x'" class="size-4 shrink-0" />

View File

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

View File

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

View File

@@ -1,11 +1,9 @@
<script setup lang="ts">
import type { NavigationMenuItem } from '@nuxt/ui'
const items = [
{
label: 'Docs',
icon: 'i-lucide-book-open',
slot: 'docs' as const,
slot: 'docs',
children: [
{
label: 'Icons',
@@ -24,7 +22,7 @@ const items = [
{
label: 'Components',
icon: 'i-lucide-box',
slot: 'components' as const,
slot: 'components',
children: [
{
label: 'Link',
@@ -56,7 +54,7 @@ const items = [
label: 'GitHub',
icon: 'i-simple-icons-github'
}
] satisfies NavigationMenuItem[]
]
</script>
<template>
@@ -65,7 +63,6 @@ const items = [
class="w-full justify-center"
:ui="{
viewport: 'sm:w-(--reka-navigation-menu-viewport-width)',
content: 'sm:w-auto',
childList: 'sm:w-96',
childLinkDescription: 'text-balance line-clamp-2'
}"
@@ -77,11 +74,11 @@ const items = [
</li>
<li v-for="child in item.children" :key="child.label">
<ULink class="text-sm text-left rounded-md p-3 transition-colors hover:bg-elevated/50">
<p class="font-medium text-highlighted">
<ULink class="text-sm text-left rounded-md p-3 transition-colors hover:bg-(--ui-bg-elevated)/50">
<p class="font-medium text-(--ui-text-highlighted)">
{{ child.label }}
</p>
<p class="text-muted line-clamp-2">
<p class="text-(--ui-text-muted) line-clamp-2">
{{ child.description }}
</p>
</ULink>

View File

@@ -1,21 +1,21 @@
<script setup lang="ts">
import type { NavigationMenuItem } from '@nuxt/ui'
const items = [
{
label: 'Guide',
icon: 'i-lucide-book-open'
},
{
label: 'Composables',
icon: 'i-lucide-database'
},
{
label: 'Components',
icon: 'i-lucide-box',
slot: 'components' as const
slot: 'components'
}
] satisfies NavigationMenuItem[]
]
</script>
<template>

View File

@@ -1,7 +1,5 @@
<script setup lang="ts">
import type { NavigationMenuItem } from '@nuxt/ui'
const items: NavigationMenuItem[] = [
const items = [
{
label: 'Guide',
icon: 'i-lucide-book-open',

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

@@ -40,7 +40,7 @@ const label = ref([])
multiple
placeholder="Search labels..."
:groups="[{ id: 'labels', items }]"
:ui="{ input: '[&>input]:h-8 [&>input]:text-sm' }"
:ui="{ input: '[&>input]:h-8' }"
/>
</template>
</UPopover>

View File

@@ -8,7 +8,7 @@ const open = ref(false)
<template #content>
<div class="flex items-center gap-4 mb-4">
<h2 class="text-highlighted font-semibold">
<h2 class="text-(--ui-text-highlighted) font-semibold">
Popover non-dismissible
</h2>

View File

@@ -4,7 +4,8 @@ const { data: countries, status, execute } = await useLazyFetch<{
code: string
emoji: string
}[]>('/api/countries.json', {
immediate: false
immediate: false,
default: () => []
})
function onOpen() {

View File

@@ -1,6 +1,4 @@
<script setup lang="ts">
import type { AvatarProps } from '@nuxt/ui'
const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', {
key: 'typicode-users',
transform: (data: { id: number, name: string }[]) => {
@@ -8,7 +6,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
label: user.name,
value: String(user.id),
avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` }
}))
})) || []
},
lazy: true
})
@@ -16,7 +14,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
<template>
<USelectMenu
:items="users"
:items="users || []"
:loading="status === 'pending'"
icon="i-lucide-user"
placeholder="Select user"
@@ -26,7 +24,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
<UAvatar
v-if="modelValue"
v-bind="modelValue.avatar"
:size="(ui.leadingAvatarSize() as AvatarProps['size'])"
:size="ui.leadingAvatarSize()"
:class="ui.leadingAvatar()"
/>
</template>

View File

@@ -1,6 +1,4 @@
<script setup lang="ts">
import type { AvatarProps } from '@nuxt/ui'
const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', {
key: 'typicode-users-email',
transform: (data: { id: number, name: string, email: string }[]) => {
@@ -9,7 +7,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
email: user.email,
value: String(user.id),
avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` }
}))
})) || []
},
lazy: true
})
@@ -17,7 +15,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
<template>
<USelectMenu
:items="users"
:items="users || []"
:loading="status === 'pending'"
:filter-fields="['label', 'email']"
icon="i-lucide-user"
@@ -28,7 +26,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
<UAvatar
v-if="modelValue"
v-bind="modelValue.avatar"
:size="(ui.leadingAvatarSize() as AvatarProps['size'])"
:size="ui.leadingAvatarSize()"
:class="ui.leadingAvatar()"
/>
</template>
@@ -36,7 +34,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
<template #item-label="{ item }">
{{ item.label }}
<span class="text-muted">
<span class="text-(--ui-text-muted)">
{{ item.email }}
</span>
</template>

View File

@@ -1,18 +1,16 @@
<script setup lang="ts">
import { refDebounced } from '@vueuse/core'
import type { AvatarProps } from '@nuxt/ui'
const searchTerm = ref('')
const searchTermDebounced = refDebounced(searchTerm, 200)
const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', {
key: 'typicode-users',
params: { q: searchTermDebounced },
transform: (data: { id: number, name: string }[]) => {
return data?.map(user => ({
label: user.name,
value: String(user.id),
avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` }
}))
})) || []
},
lazy: true
})
@@ -21,7 +19,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
<template>
<USelectMenu
v-model:search-term="searchTerm"
:items="users"
:items="users || []"
:loading="status === 'pending'"
ignore-filter
icon="i-lucide-user"
@@ -32,7 +30,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
<UAvatar
v-if="modelValue"
v-bind="modelValue.avatar"
:size="(ui.leadingAvatarSize() as AvatarProps['size'])"
:size="ui.leadingAvatarSize()"
:class="ui.leadingAvatar()"
/>
</template>

View File

@@ -1,6 +1,4 @@
<script setup lang="ts">
import type { SelectMenuItem } from '@nuxt/ui'
const items = ref([
{
label: 'benjamincanac',
@@ -25,16 +23,8 @@ const items = ref([
src: 'https://github.com/noook.png',
alt: 'noook'
}
},
{
label: 'sandros94',
value: 'sandros94',
avatar: {
src: 'https://github.com/sandros94.png',
alt: 'sandros94'
}
}
] satisfies SelectMenuItem[])
])
const value = ref(items.value[0])
</script>

View File

@@ -1,29 +1,27 @@
<script setup lang="ts">
import type { SelectMenuItem, ChipProps } from '@nuxt/ui'
const items = ref([
{
label: 'bug',
value: 'bug',
chip: {
color: 'error'
color: 'error' as const
}
},
{
label: 'feature',
value: 'feature',
chip: {
color: 'success'
color: 'success' as const
}
},
{
label: 'enhancement',
value: 'enhancement',
chip: {
color: 'info'
color: 'info' as const
}
}
] satisfies SelectMenuItem[])
])
const value = ref(items.value[0])
</script>
@@ -35,7 +33,7 @@ const value = ref(items.value[0])
v-bind="modelValue.chip"
inset
standalone
:size="(ui.itemLeadingChipSize() as ChipProps['size'])"
:size="ui.itemLeadingChipSize()"
:class="ui.itemLeadingChip()"
/>
</template>

View File

@@ -1,6 +1,4 @@
<script setup lang="ts">
import type { SelectMenuItem } from '@nuxt/ui'
const items = ref([
{
label: 'Backlog',
@@ -22,7 +20,7 @@ const items = ref([
value: 'done',
icon: 'i-lucide-circle-check'
}
] satisfies SelectMenuItem[])
])
const value = ref(items.value[0])
</script>

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