-
+
@@ -111,8 +113,8 @@ useSeoMeta({
:items="(page.faq.items as any[])"
class="max-w-4xl mx-auto"
>
-
-
+
+
diff --git a/docs/app/pages/pro/templates.vue b/docs/app/pages/pro/templates.vue
index e4fae686..07d7ba29 100644
--- a/docs/app/pages/pro/templates.vue
+++ b/docs/app/pages/pro/templates.vue
@@ -16,59 +16,60 @@ useSeoMeta({
-
-
+
+
-
-
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
+
diff --git a/docs/app/pages/roadmap.vue b/docs/app/pages/roadmap.vue
index 1bef6e56..6902b9b2 100644
--- a/docs/app/pages/roadmap.vue
+++ b/docs/app/pages/roadmap.vue
@@ -3,7 +3,7 @@ const title = 'Roadmap'
const description = 'Discover our Volta board for @nuxt/ui development status.'
useSeoMeta({
- titleTemplate: '%s - Nuxt UI v3',
+ titleTemplate: '%s - Nuxt UI',
title,
ogTitle: 'Nuxt UI Roadmap',
description
diff --git a/docs/content/1.getting-started/1.index.md b/docs/content/1.getting-started/1.index.md
index 66e0d68c..169762cb 100644
--- a/docs/content/1.getting-started/1.index.md
+++ b/docs/content/1.getting-started/1.index.md
@@ -1,14 +1,9 @@
---
-navigation.title: Introduction
-title: Nuxt UI v3
-description: 'A comprehensive, Nuxt-integrated UI library providing a rich set of fully-styled, accessible and highly customizable components for building modern web applications.'
+title: Introduction
+description: 'Nuxt UI harnesses the combined strengths of Reka UI, Tailwind CSS, and Tailwind Variants to offer developers an unparalleled set of tools for creating sophisticated, accessible, and highly performant user interfaces.'
navigation.icon: i-lucide-house
---
-We're thrilled to introduce this major update to our UI library, bringing significant improvements and powerful new features. Nuxt UI v3 represents a leap forward in creating robust, accessible, and highly customizable user interfaces for Nuxt applications.
-
-## What's New in v3?
-
### Reka UI
@@ -24,7 +19,7 @@ This transition empowers Nuxt UI to become a more comprehensive and flexible UI
### Tailwind CSS v4
-Nuxt UI v3 integrates the latest Tailwind CSS v4, bringing significant improvements:
+Nuxt UI integrates the latest Tailwind CSS v4, bringing significant improvements:
- **Built for performance**: Full builds in the new engine are up to 5x faster, and incremental builds are over 100x faster — and measured in microseconds.
- **Unified toolchain**: Built-in import handling, vendor prefixing, and syntax transforms, with no additional tooling required.
@@ -47,7 +42,7 @@ This integration unifies the styling of components, ensuring consistency and cod
### TypeScript Integration
-Nuxt UI v3 offers significantly improved TypeScript integration, providing a superior developer experience:
+Nuxt UI offers significantly improved TypeScript integration, providing a superior developer experience:
- **Enhanced Auto-completion**:
- Full auto-completion for component props based on your theme
@@ -112,11 +107,7 @@ Key points to consider:
## FAQ
::accordion
- ::accordion-item{label="What are the main considerations when upgrading to Nuxt UI v3?"}
- The transition to v3 involves significant changes, including new component structures, updated theming approaches, and revised TypeScript definitions. We recommend a careful, incremental upgrade process, starting with thorough testing in a development environment.
- ::
-
- ::accordion-item{label="Is Nuxt UI v3 compatible with standalone Vue projects?"}
+ ::accordion-item{label="Is Nuxt UI compatible with standalone Vue projects?"}
Nuxt UI is now compatible with Vue! You can follow the [installation guide](/getting-started/installation/vue) to get started.
::
@@ -124,23 +115,19 @@ Key points to consider:
We've also rebuilt Nuxt UI Pro from scratch as v3 to match Nuxt UI version. The license you bought or will buy is valid for both Nuxt UI Pro v1 and v3, this is a **free update**. You can follow the [installation guide](/getting-started/installation/pro/nuxt) to get started.
::
- ::accordion-item{label="Will Nuxt UI v3 work with other CSS frameworks like UnoCSS?"}
- Nuxt UI v3 is currently designed to work exclusively with Tailwind CSS. While there's interest in UnoCSS support, implementing it would require significant changes to the theme structure due to differences in class naming conventions. As a result, we don't have plans to add UnoCSS support in v3.
+ ::accordion-item{label="Will Nuxt UI work with other CSS frameworks like UnoCSS?"}
+ Nuxt UI is currently designed to work exclusively with Tailwind CSS. While there's interest in UnoCSS support, implementing it would require significant changes to the theme structure due to differences in class naming conventions. As a result, we don't have plans to add UnoCSS support.
::
- ::accordion-item{label="How does Nuxt UI v3 handle accessibility?"}
- Nuxt UI v3 enhances accessibility through Reka UI integration. This provides automatic ARIA attributes, keyboard navigation support, intelligent focus management, and screen reader announcements. While offering a strong foundation, proper implementation and testing in your specific use case remains crucial for full accessibility compliance. For more detailed information, refer to [Reka UI's accessibility documentation](https://reka-ui.com/docs/overview/accessibility).
+ ::accordion-item{label="How does Nuxt UI handle accessibility?"}
+ Nuxt UI enhances accessibility through Reka UI integration. This provides automatic ARIA attributes, keyboard navigation support, intelligent focus management, and screen reader announcements. While offering a strong foundation, proper implementation and testing in your specific use case remains crucial for full accessibility compliance. For more detailed information, refer to [Reka UI's accessibility documentation](https://reka-ui.com/docs/overview/accessibility).
::
- ::accordion-item{label="What is the testing approach for Nuxt UI v3?"}
- Nuxt UI v3 ensures reliability with 1000+ Vitest tests, covering core functionality and accessibility. This robust testing suite supports the library's stability and serves as a reference for developers.
- ::
-
- ::accordion-item{label="Is this version stable and suitable for production use?"}
- Nuxt UI v3 is now in beta and is stable enough to be used in production. We now recommend using v3 over v2. We welcome feedback from users to help improve the library further. Feel free to report any issues you encounter on our [GitHub repository](https://github.com/nuxt/ui/issues).
+ ::accordion-item{label="What is the testing approach for Nuxt UI?"}
+ Nuxt UI ensures reliability with 1000+ Vitest tests, covering core functionality and accessibility. This robust testing suite supports the library's stability and serves as a reference for developers.
::
::
:hr
-We're excited about the possibilities Nuxt UI v3 brings to your projects. Explore our documentation to learn more about new features, components, and best practices for building powerful, accessible user interfaces with Nuxt UI v3.
+We're excited about the possibilities Nuxt UI v3 brings to your projects. Explore our documentation to learn more about new features, components, and best practices for building powerful, accessible user interfaces.
diff --git a/docs/content/1.getting-started/2.installation/1.nuxt.md b/docs/content/1.getting-started/2.installation/1.nuxt.md
index a13184eb..aa550b19 100644
--- a/docs/content/1.getting-started/2.installation/1.nuxt.md
+++ b/docs/content/1.getting-started/2.installation/1.nuxt.md
@@ -20,24 +20,24 @@ Looking for the **Vue** version?
::steps{level="4"}
-#### Install the Nuxt UI v3 beta package
+#### Install the Nuxt UI package
::code-group{sync="pm"}
```bash [pnpm]
-pnpm add @nuxt/ui@next
+pnpm add @nuxt/ui
```
```bash [yarn]
-yarn add @nuxt/ui@next
+yarn add @nuxt/ui
```
```bash [npm]
-npm install @nuxt/ui@next
+npm install @nuxt/ui
```
```bash [bun]
-bun add @nuxt/ui@next
+bun add @nuxt/ui
```
::
@@ -85,7 +85,11 @@ It's recommended to install the [Tailwind CSS IntelliSense](https://marketplace.
},
"editor.quickSuggestions": {
"strings": "on"
-}
+},
+"tailwindCSS.classAttributes": ["class", "ui"],
+"tailwindCSS.experimental.classRegex": [
+ ["ui:\\s*{([^)]*)\\s*}", "(?:'|\"|`)([^']*)(?:'|\"|`)"]
+]
```
::
@@ -108,12 +112,12 @@ The `App` component provides global configurations and is required for **Toast**
### Use our Nuxt Starter
-Start your project using the [nuxt/starter#ui3](https://github.com/nuxt/starter/tree/ui3) template with Nuxt UI v3 pre-configured.
+Start your project using the [nuxt/starter#ui](https://github.com/nuxt/starter/tree/ui) template with Nuxt UI pre-configured.
Create a new project locally by running the following command:
```bash [Terminal]
-npx nuxi init -t ui3
+npx nuxi init -t ui
```
::note
@@ -225,30 +229,19 @@ This option adds the `transition-colors` class on components with hover or activ
## Continuous Releases
-Nuxt UI v3 uses [pkg.pr.new](https://github.com/stackblitz-labs/pkg.pr.new) for continuous preview releases, providing developers with instant access to the latest features and bug fixes without waiting for official releases.
+Nuxt UI uses [pkg.pr.new](https://github.com/stackblitz-labs/pkg.pr.new) for continuous preview releases, providing developers with instant access to the latest features and bug fixes without waiting for official releases.
-Preview releases are automatically generated for every commit to the `v3` branch and pull requests targeting the `v3` branch. To use it into your project, use the installation command below by replacing `5385f84` with any commit hash or pull request number.
+Automatic preview releases are created for all commits and PRs to the `v3` branch. Use them by replacing your package version with the specific commit hash or PR number.
-::code-group{sync="pm"}
-
-```bash [pnpm]
-pnpm add https://pkg.pr.new/@nuxt/ui@5385f84
+```diff [package.json]
+{
+ "dependencies": {
+- "@nuxt/ui": "^3.0.0",
++ "@nuxt/ui": "https://pkg.pr.new/@nuxt/ui@4c96909",
+ }
+}
```
-```bash [yarn]
-yarn add https://pkg.pr.new/@nuxt/ui@5385f84
-```
-
-```bash [npm]
-npm install https://pkg.pr.new/@nuxt/ui@5385f84
-```
-
-```bash [bun]
-bun add https://pkg.pr.new/@nuxt/ui@5385f84
-```
-
-::
-
::note
**pkg.pr.new** will automatically comment on PRs with the installation URL, making it easy to test changes.
::
diff --git a/docs/content/1.getting-started/2.installation/2.vue.md b/docs/content/1.getting-started/2.installation/2.vue.md
index ddd348c7..f94b779b 100644
--- a/docs/content/1.getting-started/2.installation/2.vue.md
+++ b/docs/content/1.getting-started/2.installation/2.vue.md
@@ -20,24 +20,24 @@ Looking for the **Nuxt** version?
::steps{level="4"}
-#### Install the Nuxt UI v3 beta package
+#### Install the Nuxt UI package
::code-group{sync="pm"}
```bash [pnpm]
-pnpm add @nuxt/ui@next
+pnpm add @nuxt/ui
```
```bash [yarn]
-yarn add @nuxt/ui@next
+yarn add @nuxt/ui
```
```bash [npm]
-npm install @nuxt/ui@next
+npm install @nuxt/ui
```
```bash [bun]
-bun add @nuxt/ui@next
+bun add @nuxt/ui
```
::
@@ -145,7 +145,11 @@ It's recommended to install the [Tailwind CSS IntelliSense](https://marketplace.
},
"editor.quickSuggestions": {
"strings": "on"
-}
+},
+"tailwindCSS.classAttributes": ["class", "ui"],
+"tailwindCSS.experimental.classRegex": [
+ ["ui:\\s*{([^)]*)\\s*}", "(?:'|\"|`)([^']*)(?:'|\"|`)"]
+]
```
::
@@ -168,7 +172,7 @@ The `App` component provides global configurations and is required for **Toast**
### Use our Vue starter
-Start your project using the [nuxtlabs/nuxt-ui-vue-starter](https://github.com/nuxtlabs/nuxt-ui-vue-starter) template with Nuxt UI v3 pre-configured.
+Start your project using the [nuxtlabs/nuxt-ui-vue-starter](https://github.com/nuxtlabs/nuxt-ui-vue-starter) template with Nuxt UI pre-configured.
Create a new project locally by running the following command:
@@ -313,30 +317,19 @@ This option adds the `transition-colors` class on components with hover or activ
## Continuous Releases
-Nuxt UI v3 uses [pkg.pr.new](https://github.com/stackblitz-labs/pkg.pr.new) for continuous preview releases, providing developers with instant access to the latest features and bug fixes without waiting for official releases.
+Nuxt UI uses [pkg.pr.new](https://github.com/stackblitz-labs/pkg.pr.new) for continuous preview releases, providing developers with instant access to the latest features and bug fixes without waiting for official releases.
-Preview releases are automatically generated for every commit to the `v3` branch and pull requests targeting the `v3` branch. To use it into your project, use the installation command below by replacing `5385f84` with any commit hash or pull request number.
+Automatic preview releases are created for all commits and PRs to the `v3` branch. Use them by replacing your package version with the specific commit hash or PR number.
-::code-group{sync="pm"}
-
-```bash [pnpm]
-pnpm add https://pkg.pr.new/@nuxt/ui@5385f84
+```diff [package.json]
+{
+ "dependencies": {
+- "@nuxt/ui": "^3.0.0",
++ "@nuxt/ui": "https://pkg.pr.new/@nuxt/ui@4c96909",
+ }
+}
```
-```bash [yarn]
-yarn add https://pkg.pr.new/@nuxt/ui@5385f84
-```
-
-```bash [npm]
-npm install https://pkg.pr.new/@nuxt/ui@5385f84
-```
-
-```bash [bun]
-bun add https://pkg.pr.new/@nuxt/ui@5385f84
-```
-
-::
-
::note
**pkg.pr.new** will automatically comment on PRs with the installation URL, making it easy to test changes.
::
diff --git a/docs/content/1.getting-started/2.migration.md b/docs/content/1.getting-started/2.migration.md
index 9ad932af..992c74ae 100644
--- a/docs/content/1.getting-started/2.migration.md
+++ b/docs/content/1.getting-started/2.migration.md
@@ -56,19 +56,19 @@ npx @tailwindcss/upgrade
::::code-group{sync="pm"}
```bash [pnpm]
-pnpm add @nuxt/ui@next
+pnpm add @nuxt/ui
```
```bash [yarn]
-yarn add @nuxt/ui@next
+yarn add @nuxt/ui
```
```bash [npm]
-npm install @nuxt/ui@next
+npm install @nuxt/ui
```
```bash [bun]
-bun add @nuxt/ui@next
+bun add @nuxt/ui
```
::::
@@ -81,19 +81,19 @@ bun add @nuxt/ui@next
::::code-group{sync="pm"}
```bash [pnpm]
-pnpm add @nuxt/ui-pro@next
+pnpm add @nuxt/ui-pro
```
```bash [yarn]
-yarn add @nuxt/ui-pro@next
+yarn add @nuxt/ui-pro
```
```bash [npm]
-npm install @nuxt/ui-pro@next
+npm install @nuxt/ui-pro
```
```bash [bun]
-bun add @nuxt/ui-pro@next
+bun add @nuxt/ui-pro
```
::::
@@ -130,7 +130,7 @@ bun add @nuxt/ui-pro@next
#ui
:::div
-5. Wrap you app with the [App](/components/app) component:
+5. Wrap your app with the [App](/components/app) component:
:::
#ui-pro
@@ -145,7 +145,7 @@ export default defineNuxtConfig({
})
```
-6. Wrap you app with the [App](/components/app) component:
+6. Wrap your app with the [App](/components/app) component:
:::
::
@@ -359,7 +359,7 @@ In addition to the renamed components, there are lots of changes to the componen
+
-
-+
++
```
@@ -367,6 +367,165 @@ In addition to the renamed components, there are lots of changes to the componen
This change affects the following components: `Breadcrumb`, `HorizontalNavigation`, `InputMenu`, `RadioGroup`, `Select`, `SelectMenu`, `VerticalNavigation`.
::
+2. The global `Modals`, `Slideovers` and `Notifications` components have been removed in favor the [App](/components/app) component:
+
+```diff [app.vue]
+
++
++
++
+-
+-
+-
+
+```
+
+3. The `v-model:open` directive and `default-open` prop are now used to control visibility:
+
+```diff
+
+-
++
+
+```
+
+::note
+This change affects the following components: `ContextMenu`, `Modal` and `Slideover` and enables controlling visibility for `InputMenu`, `Select`, `SelectMenu` and `Tooltip`.
+::
+
+4. The default slot is now used for the trigger and the content goes inside the `#content` slot (you don't need to use a `v-model:open` directive with this method):
+
+```diff
+
+
+
+-
+
+-
++
++
+
++
+
++
+
+
+```
+
+::note
+This change affects the following components: `Modal`, `Popover`, `Slideover`, `Tooltip`.
+::
+
+5. A `#header`, `#body` and `#footer` slots have been added inside the `#content` slot like the `Card` component:
+
+```diff
+
+-
++
+-
+
+
+```
+
+::note
+This change affects the following components: `Modal`, `Slideover`.
+::
+
+
+### Changed composables
+
+1. The `useToast()` composable `timeout` prop has been renamed to `duration`:
+
+```diff
+
+```
+
+2. The `useModal` and `useSlideover` composables have been removed in favor of a more generic `useOverlay` composable:
+
+Some important differences:
+- The `useOverlay` composable is now used to create overlay instances
+- Overlays that are opened, can be awaited for their result
+- Overlays can no longer be close using `modal.close()` or `slideover.close()`, rather, they close automatically: either when a `close` event is fired explicitly from the opened component OR when the overlay closes itself (clicking on backdrop, pressing the ESC key, etc)
+- To capture the return value in the parent component you must explictly emit a `close` event with the desired value
+
+
+```diff
+
+```
+
+Props are now passed through a props attribute:
+
+```diff
+
+```
+
+Closing a modal is now done through the `close` event. The `modal.open` method now returns a promise that resolves to the result of the modal whenever the modal is close:
+
+```diff
+
+```
+
---
::warning
diff --git a/docs/content/1.getting-started/3.theme.md b/docs/content/1.getting-started/3.theme.md
index fcee4498..d9c0bc21 100644
--- a/docs/content/1.getting-started/3.theme.md
+++ b/docs/content/1.getting-started/3.theme.md
@@ -6,7 +6,7 @@ navigation.icon: i-lucide-swatch-book
## Tailwind CSS
-Nuxt UI v3 uses Tailwind CSS v4, you can read the official [upgrade guide](https://tailwindcss.com/docs/upgrade-guide#changes-from-v3) to learn about all the breaking changes.
+Nuxt UI uses Tailwind CSS v4, you can read the official [upgrade guide](https://tailwindcss.com/docs/upgrade-guide#changes-from-v3) to learn about all the breaking changes.
### `@theme`
@@ -142,7 +142,7 @@ Nuxt UI leverages Vite config to provide customizable color aliases based on [Ta
::framework-only
#nuxt
-::div
+:::div
You can configure these color aliases at runtime in your `app.config.ts` file under the `ui.colors` key, allowing for dynamic theme customization without requiring an application rebuild:
```ts [app.config.ts]
@@ -156,14 +156,19 @@ export default defineAppConfig({
})
```
-::
+:::
#vue
-::module-only
-#ui
+
:::div
You can configure these color aliases at runtime in your `vite.config.ts` file under the `ui.colors` key:
+::::module-only
+
+#ui
+
+:::::div
+
```ts [vite.config.ts]
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
@@ -183,11 +188,12 @@ export default defineConfig({
]
})
```
-:::
+:::::
#ui-pro
-:::div
-You can configure these color aliases at runtime in your `vite.config.ts` file under the `uiPro.colors` key:
+
+:::::div
+
```ts [vite.config.ts]
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
@@ -207,9 +213,12 @@ export default defineConfig({
]
})
```
-:::
-::
+:::::
+
+::::
+
+:::
::
@@ -256,11 +265,17 @@ export default defineNuxtConfig({
:::
#vue
-::module-only
-#ui
+
:::tip
+
You can add you own dynamic color aliases in your `vite.config.ts`, you just have to make sure to also define them in the [`theme.colors`](/getting-started/installation/vue#themecolors) option of the `ui` plugin.
+::::module-only
+
+#ui
+
+:::::div
+
```ts [vite.config.ts]
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
@@ -283,11 +298,11 @@ export default defineConfig({
})
```
-:::
+:::::
#ui-pro
-:::tip
-You can add you own dynamic color aliases in your `vite.config.ts`, you just have to make sure to also define them in the [`theme.colors`](/getting-started/installation/vue#themecolors) option of the `uiPro` plugin.
+
+:::::div
```ts [vite.config.ts]
import { defineConfig } from 'vite'
@@ -311,9 +326,12 @@ export default defineConfig({
})
```
+:::::
+
+::::
+
:::
-::
::
### Tokens
diff --git a/docs/content/1.getting-started/7.i18n/1.nuxt.md b/docs/content/1.getting-started/7.i18n/1.nuxt.md
index 8a7838bc..e3315633 100644
--- a/docs/content/1.getting-started/7.i18n/1.nuxt.md
+++ b/docs/content/1.getting-started/7.i18n/1.nuxt.md
@@ -17,6 +17,11 @@ Nuxt UI provides an **App** component that wraps your app to provide global conf
### Locale
+::module-only
+
+#ui
+:::div
+
Use the `locale` prop with the locale you want to use from `@nuxt/ui/locale`:
```vue [app.vue]
@@ -31,13 +36,42 @@ import { fr } from '@nuxt/ui/locale'
```
+:::
+
+#ui-pro
+:::div
+
+Use the `locale` prop with the locale you want to use from `@nuxt/ui-pro/locale`:
+
+```vue [app.vue]
+
+
+
+
+
+
+
+```
+
+:::
+::
+
### Custom locale
You also have the option to add your own locale using `defineLocale`:
+::module-only
+
+#ui
+:::div
+
```vue [app.vue]
+
+
+
+
+
+
+```
+
+:::
+::
+
::tip
Look at the `code` parameter, there you need to pass the iso code of the language. Example:
@@ -116,6 +179,11 @@ export default defineNuxtConfig({
#### Set the `locale` prop using `useI18n`
+::module-only
+
+#ui
+:::div
+
```vue [app.vue]
+
+
+
+
+
+
+```
+
+:::
+::
+
::
### Dynamic direction
@@ -138,6 +228,11 @@ Each locale has a `dir` property which will be used by the `App` component to se
In a multilingual application, you might want to set the `lang` and `dir` attributes on the `` element dynamically based on the user's locale, which you can do with the [useHead](https://nuxt.com/docs/api/composables/use-head) composable:
+::module-only
+
+#ui
+:::div
+
```vue [app.vue]
+
+
+
+
+
+
+```
+
+:::
+::
+
## Supported languages
:supported-languages
diff --git a/docs/content/1.getting-started/7.i18n/2.vue.md b/docs/content/1.getting-started/7.i18n/2.vue.md
index 144dc69e..9476433c 100644
--- a/docs/content/1.getting-started/7.i18n/2.vue.md
+++ b/docs/content/1.getting-started/7.i18n/2.vue.md
@@ -17,6 +17,11 @@ Nuxt UI provides an **App** component that wraps your app to provide global conf
### Locale
+::module-only
+
+#ui
+:::div
+
Use the `locale` prop with the locale you want to use from `@nuxt/ui/locale`:
```vue [App.vue]
@@ -31,15 +36,43 @@ import { fr } from '@nuxt/ui/locale'
```
+:::
+
+#ui-pro
+:::div
+
+Use the `locale` prop with the locale you want to use from `@nuxt/ui-pro/locale`:
+
+```vue [App.vue]
+
+
+
+
+
+
+
+```
+
+:::
+::
+
### Custom locale
You also have the option to add your locale using `defineLocale`:
+::module-only
+
+#ui
+:::div
+
```vue [App.vue]
+
+
+
+
+
+
+```
+
+:::
+::
+
::tip
Look at the `code` parameter, there you need to pass the iso code of the language. Example:
@@ -131,6 +194,11 @@ app.mount('#app')
#### Set the `locale` prop using `useI18n`
+::module-only
+
+#ui
+:::div
+
```vue [App.vue]
+
+
+
+
+
+
+```
+
+:::
+::
+
::
### Dynamic direction
@@ -154,6 +245,11 @@ Each locale has a `dir` property which will be used by the `App` component to se
In a multilingual application, you might want to set the `lang` and `dir` attributes on the `` element dynamically based on the user's locale, which you can do with the [useHead](https://unhead.unjs.io/usage/composables/use-head) composable:
+::module-only
+
+#ui
+:::div
+
```vue [App.vue]
+
+
+
+
+
+
+```
+
+:::
+::
+
## Supported languages
:supported-languages
diff --git a/docs/content/1.getting-started/contribution.md b/docs/content/1.getting-started/contribution.md
index ff9240a3..1aecf5d3 100644
--- a/docs/content/1.getting-started/contribution.md
+++ b/docs/content/1.getting-started/contribution.md
@@ -1,13 +1,13 @@
---
title: Contribution Guide
-description: 'A comprehensive guide on contributing to Nuxt UI v3, including project structure, development workflow, and best practices.'
+description: 'A comprehensive guide on contributing to Nuxt UI, including project structure, development workflow, and best practices.'
navigation: false
---
Nuxt UI thrives thanks to its incredible community ❤️. We welcome all contributions through bug reports, pull requests, and feedback to help make this library even better.
::caution
-Before reporting a bug or requesting a feature, make sure that you have read through our [documentation](https://ui3.nuxt.dev/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
+Before reporting a bug or requesting a feature, 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).
::
## Project Structure
diff --git a/docs/content/3.components/button.md b/docs/content/3.components/button.md
index 81051629..ad8f064d 100644
--- a/docs/content/3.components/button.md
+++ b/docs/content/3.components/button.md
@@ -29,23 +29,6 @@ props:
---
::
-### Link
-
-You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
-
-::component-code
----
-ignore:
- - label
- - target
-props:
- to: https://github.com/nuxt/ui
- target: _blank
-slots:
- default: Button
----
-::
-
### Color
Use the `color` prop to change the color of the Button.
@@ -160,6 +143,96 @@ props:
---
::
+### Link
+
+You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
+
+::component-code
+---
+ignore:
+ - target
+props:
+ to: https://github.com/nuxt/ui
+ target: _blank
+slots:
+ default: Button
+---
+::
+
+When the Button is a link or when using the `active` prop, you can use the `active-color` and `active-variant` props to customize the active state.
+
+::component-code
+---
+prettier: true
+ignore:
+ - color
+ - variant
+items:
+ activeColor:
+ - primary
+ - secondary
+ - success
+ - info
+ - warning
+ - error
+ - neutral
+ activeVariant:
+ - solid
+ - outline
+ - soft
+ - subtle
+ - ghost
+ - link
+props:
+ active: true
+ color: neutral
+ variant: outline
+ activeColor: primary
+ activeVariant: solid
+slots:
+ default: |
+
+ Button
+---
+
+Button
+::
+
+You can also use the `active-class` and `inactive-class` props to customize the active state.
+
+::component-code
+---
+props:
+ active: true
+ activeClass: 'font-bold'
+ inactiveClass: 'font-light'
+slots:
+ default: Button
+---
+
+Button
+::
+
+::tip
+You can configure these styles globally in your `app.config.ts` file under the `ui.button.variants.active` key.
+
+```ts
+export default defineAppConfig({
+ ui: {
+ button: {
+ variants: {
+ active: {
+ true: {
+ base: 'font-bold'
+ }
+ }
+ }
+ }
+ }
+})
+```
+::
+
### Loading
Use the `loading` prop to show a loading icon and disable the Button.
diff --git a/docs/content/3.components/form.md b/docs/content/3.components/form.md
index 2191fdf9..4c305b8c 100644
--- a/docs/content/3.components/form.md
+++ b/docs/content/3.components/form.md
@@ -9,7 +9,7 @@ links:
## Usage
-Use the Form component to validate form data using schema libraries such as [Valibot](https://github.com/fabian-hiller/valibot), [Zod](https://github.com/colinhacks/zod), [Yup](https://github.com/jquense/yup), [Joi](https://github.com/hapijs/joi), [Superstruct](https://github.com/ianstormtaylor/superstruct) or your own validation logic.
+Use the Form component to validate form data using validation libraries such as [Valibot](https://github.com/fabian-hiller/valibot), [Zod](https://github.com/colinhacks/zod), [Yup](https://github.com/jquense/yup), [Joi](https://github.com/hapijs/joi), [Superstruct](https://github.com/ianstormtaylor/superstruct) or your own validation logic.
It works with the [FormField](/components/form-field) component to display error messages around form elements automatically.
@@ -18,7 +18,7 @@ It works with the [FormField](/components/form-field) component to display error
It requires two props:
- `state` - a reactive object holding the form's state.
-- `schema` - a schema object from a validation library like [Valibot](https://github.com/fabian-hiller/valibot), [Zod](https://github.com/colinhacks/zod), [Yup](https://github.com/jquense/yup), [Joi](https://github.com/hapijs/joi) or [Superstruct](https://github.com/ianstormtaylor/superstruct).
+- `schema` - any [Standard Schema](https://standardschema.dev/) or a schema from [Yup](https://github.com/jquense/yup), [Joi](https://github.com/hapijs/joi) or [Superstruct](https://github.com/ianstormtaylor/superstruct).
::warning
**No validation library is included** by default, ensure you **install the one you need**.
diff --git a/docs/content/3.components/tree.md b/docs/content/3.components/tree.md
index 45def87e..95f96001 100644
--- a/docs/content/3.components/tree.md
+++ b/docs/content/3.components/tree.md
@@ -8,7 +8,6 @@ links:
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/Tree.vue
-navigation.badge: New
---
## Usage
diff --git a/docs/nuxt.config.ts b/docs/nuxt.config.ts
index 8b3bdc76..412762b7 100644
--- a/docs/nuxt.config.ts
+++ b/docs/nuxt.config.ts
@@ -34,7 +34,7 @@ export default defineNuxtConfig({
},
$production: {
site: {
- url: 'https://ui3.nuxt.dev'
+ url: 'https://ui.nuxt.com'
}
},
@@ -55,6 +55,7 @@ export default defineNuxtConfig({
}]
},
rootAttrs: {
+ // @ts-expect-error - vaul-drawer-wrapper is not typed
'vaul-drawer-wrapper': '',
'class': 'bg-(--ui-bg)'
}
@@ -85,8 +86,8 @@ export default defineNuxtConfig({
},
routeRules: {
- '/': { redirect: '/getting-started', prerender: false },
'/getting-started/installation': { redirect: '/getting-started/installation/nuxt', prerender: false },
+ '/getting-started/installation/pro': { redirect: '/getting-started/installation/pro/nuxt', prerender: false },
'/getting-started/icons': { redirect: '/getting-started/icons/nuxt', prerender: false },
'/getting-started/color-mode': { redirect: '/getting-started/color-mode/nuxt', prerender: false },
'/getting-started/i18n': { redirect: '/getting-started/i18n/nuxt', prerender: false },
@@ -104,9 +105,10 @@ export default defineNuxtConfig({
routes: [
'/getting-started',
'/api/countries.json',
- '/api/locales.json'
+ '/api/locales.json',
// '/api/releases.json',
// '/api/pulls.json'
+ '/404.html'
],
crawlLinks: true,
autoSubfolderIndex: false
@@ -127,7 +129,12 @@ export default defineNuxtConfig({
vite: {
plugins: [
yaml()
- ]
+ ],
+ server: {
+ fs: {
+ allow: process.env.NUXT_UI_PRO_PATH ? [resolve(process.env.NUXT_UI_PRO_PATH)] : undefined
+ }
+ }
},
componentMeta: {
@@ -169,12 +176,12 @@ export default defineNuxtConfig({
},
llms: {
- domain: 'https://ui3.nuxt.dev',
- title: 'Nuxt UI v3',
+ domain: 'https://ui.nuxt.com',
+ title: 'Nuxt UI',
description: 'A comprehensive, Nuxt-integrated UI library providing a rich set of fully-styled, accessible and highly customizable components for building modern web applications.',
full: {
- title: 'Nuxt UI v3 Full Documentation',
- description: 'This is the full documentation for Nuxt UI v3. It includes all the Markdown files written with the MDC syntax.'
+ title: 'Nuxt UI Full Documentation',
+ description: 'This is the full documentation for Nuxt UI. It includes all the Markdown files written with the MDC syntax.'
},
sections: [
{
diff --git a/docs/package.json b/docs/package.json
index 5e380b2e..413f4772 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -4,34 +4,34 @@
"type": "module",
"dependencies": {
"@iconify-json/logos": "^1.2.4",
- "@iconify-json/lucide": "^1.2.28",
- "@iconify-json/simple-icons": "^1.2.27",
+ "@iconify-json/lucide": "^1.2.30",
+ "@iconify-json/simple-icons": "^1.2.28",
"@iconify-json/vscode-icons": "^1.2.16",
- "@nuxt/content": "https://pkg.pr.new/@nuxt/content@819ab7f",
+ "@nuxt/content": "https://pkg.pr.new/@nuxt/content@be99f3a",
"@nuxt/image": "^1.9.0",
"@nuxt/ui": "latest",
- "@nuxt/ui-pro": "https://pkg.pr.new/@nuxt/ui-pro@7cf4b69",
- "@nuxthub/core": "^0.8.17",
+ "@nuxt/ui-pro": "https://pkg.pr.new/@nuxt/ui-pro@d96a086",
+ "@nuxthub/core": "^0.8.18",
"@nuxtjs/plausible": "^1.2.0",
"@octokit/rest": "^21.1.1",
"@rollup/plugin-yaml": "^4.1.2",
- "@vueuse/nuxt": "^12.7.0",
+ "@vueuse/nuxt": "^13.0.0",
"joi": "^17.13.3",
- "motion": "^12.4.7",
- "motion-v": "0.11.0-beta.6",
- "nuxt": "^3.15.4",
+ "motion": "^12.5.0",
+ "motion-v": "0.13.0",
+ "nuxt": "^3.16.0",
"nuxt-component-meta": "^0.10.0",
"nuxt-llms": "^0.1.0",
- "nuxt-og-image": "^4.1.5",
+ "nuxt-og-image": "^5.0.4",
"prettier": "^3.5.3",
- "shiki-transformer-color-highlight": "^0.2.0",
+ "shiki-transformer-color-highlight": "^1.0.0",
"superstruct": "^2.0.2",
"ufo": "^1.5.4",
- "valibot": "^0.42.1",
+ "valibot": "^1.0.0",
"yup": "^1.6.1",
"zod": "^3.24.2"
},
"devDependencies": {
- "wrangler": "^3.111.0"
+ "wrangler": "^3.114.0"
}
}
diff --git a/docs/public/pro/ad.png b/docs/public/pro/ad.png
new file mode 100644
index 00000000..19a9c260
Binary files /dev/null and b/docs/public/pro/ad.png differ
diff --git a/package.json b/package.json
index 7ed06ef6..383a1454 100644
--- a/package.json
+++ b/package.json
@@ -1,13 +1,13 @@
{
"name": "@nuxt/ui",
"description": "A UI Library for Modern Web Apps, powered by Vue & Tailwind CSS.",
- "version": "3.0.0-beta.2",
- "packageManager": "pnpm@10.5.2",
+ "version": "3.0.0",
+ "packageManager": "pnpm@10.6.4",
"repository": {
"type": "git",
"url": "git+https://github.com/nuxt/ui.git"
},
- "homepage": "https://ui3.nuxt.dev",
+ "homepage": "https://ui.nuxt.com",
"type": "module",
"license": "MIT",
"exports": {
@@ -67,7 +67,7 @@
"dev:build": "nuxi build playground",
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground && nuxi prepare docs && vite build playground-vue",
"docs": "DEV=true nuxi dev docs",
- "docs:build": "nuxi build docs",
+ "docs:build": "NODE_OPTIONS='--max-old-space-size=8192' nuxi build docs",
"docs:prepare": "nuxt-component-meta docs",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
@@ -75,23 +75,23 @@
"test": "vitest",
"test:vue": "vitest -c vitest.vue.config.ts",
"test:vue:build": "vite build playground-vue",
- "release": "release-it --preRelease=beta --npm.tag=next"
+ "release": "release-it"
},
"dependencies": {
"@iconify/vue": "^4.3.0",
"@internationalized/date": "^3.7.0",
"@internationalized/number": "^3.6.0",
- "@nuxt/fonts": "^0.10.3",
- "@nuxt/icon": "^1.10.3",
- "@nuxt/kit": "^3.15.4",
- "@nuxt/schema": "^3.15.4",
+ "@nuxt/fonts": "^0.11.0",
+ "@nuxt/icon": "^1.11.0",
+ "@nuxt/kit": "^3.16.0",
+ "@nuxt/schema": "^3.16.0",
"@nuxtjs/color-mode": "^3.5.2",
- "@tailwindcss/postcss": "^4.0.9",
- "@tailwindcss/vite": "^4.0.9",
+ "@tailwindcss/postcss": "^4.0.14",
+ "@tailwindcss/vite": "^4.0.14",
"@tanstack/vue-table": "^8.21.2",
- "@unhead/vue": "^1.11.20",
- "@vueuse/core": "^12.7.0",
- "@vueuse/integrations": "^12.7.0",
+ "@unhead/vue": "^2.0.0-rc.13",
+ "@vueuse/core": "^13.0.0",
+ "@vueuse/integrations": "^13.0.0",
"colortranslator": "^4.1.0",
"consola": "^3.4.0",
"defu": "^6.1.4",
@@ -106,34 +106,36 @@
"knitwork": "^1.2.0",
"magic-string": "^0.30.17",
"mlly": "^1.7.4",
- "ohash": "^1.1.5",
+ "ohash": "^2.0.11",
"pathe": "^2.0.3",
- "reka-ui": "^2.0.2",
+ "reka-ui": "^2.1.0",
"scule": "^1.3.0",
- "tailwind-variants": "^0.3.1",
- "tailwindcss": "^4.0.9",
+ "tailwind-variants": "^1.0.0",
+ "tailwindcss": "^4.0.14",
"tinyglobby": "^0.2.12",
"unplugin": "^2.2.0",
"unplugin-auto-import": "^19.1.1",
"unplugin-vue-components": "^28.4.1",
- "vaul-vue": "^0.3.0"
+ "vaul-vue": "^0.3.0",
+ "vue": "^3.5.13",
+ "vue-router": "^4.5.0"
},
"devDependencies": {
- "@nuxt/eslint-config": "^1.1.0",
+ "@nuxt/eslint-config": "^1.2.0",
"@nuxt/module-builder": "^0.8.4",
- "@nuxt/test-utils": "^3.17.1",
+ "@nuxt/test-utils": "^3.17.2",
"@release-it/conventional-changelog": "^10.0.0",
"@standard-schema/spec": "^1.0.0",
"@vue/test-utils": "^2.4.6",
"embla-carousel": "^8.5.2",
- "eslint": "^9.21.0",
- "happy-dom": "^17.1.2",
+ "eslint": "^9.22.0",
+ "happy-dom": "^17.4.4",
"joi": "^17.13.3",
- "nuxt": "^3.15.4",
+ "nuxt": "^3.16.0",
"release-it": "^18.1.2",
"superstruct": "^2.0.2",
- "valibot": "^0.42.1",
- "vitest": "^3.0.7",
+ "valibot": "^1.0.0",
+ "vitest": "^3.0.9",
"vitest-environment-nuxt": "^1.0.1",
"vue-tsc": "^2.2.0",
"yup": "^1.6.1",
@@ -146,12 +148,9 @@
"@nuxt/ui": "workspace:*",
"chokidar": "3.6.0",
"debug": "4.3.7",
- "happy-dom": "17.1.2",
- "rollup": "4.32.1",
+ "rollup": "4.34.9",
"typescript": "5.6.3",
- "unimport": "3.14.5",
"unplugin": "^2.2.0",
- "vue": "3.5.13",
"vue-tsc": "2.2.0"
},
"pnpm": {
diff --git a/playground-vue/index.html b/playground-vue/index.html
index bfeb21d9..a8fc6eb5 100644
--- a/playground-vue/index.html
+++ b/playground-vue/index.html
@@ -2,8 +2,9 @@
+
-
Nuxt UI ❤️ Vue
+
Nuxt UI - Vue Playground
diff --git a/playground-vue/package.json b/playground-vue/package.json
index 3680dfe4..d69488de 100644
--- a/playground-vue/package.json
+++ b/playground-vue/package.json
@@ -15,9 +15,9 @@
"vue-router": "^4.5.0"
},
"devDependencies": {
- "@vitejs/plugin-vue": "^5.2.1",
+ "@vitejs/plugin-vue": "^5.2.3",
"typescript": "^5.6.3",
- "vite": "^6.2.0",
+ "vite": "^6.2.2",
"vue-tsc": "^2.2.0"
}
}
diff --git a/playground-vue/public/logo.svg b/playground-vue/public/logo.svg
new file mode 100644
index 00000000..d4d5f0bd
--- /dev/null
+++ b/playground-vue/public/logo.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/playground/app/pages/components/table.vue b/playground/app/pages/components/table.vue
index df32edb3..8ecaccea 100644
--- a/playground/app/pages/components/table.vue
+++ b/playground/app/pages/components/table.vue
@@ -1,7 +1,7 @@
-
-
+
@@ -69,7 +89,7 @@ onMounted(async () => {
nestedForms.value.set(event.formId, { validate: event.validate })
} else if (event.type === 'detach') {
nestedForms.value.delete(event.formId)
- } else if (props.validateOn?.includes(event.type)) {
+ } else if (props.validateOn?.includes(event.type) && !loading.value) {
if (event.type !== 'input') {
await _validate({ name: event.name, silent: true, nested: false })
} else if (event.eager || blurredFields.has(event.name)) {
@@ -121,7 +141,7 @@ const blurredFields = new Set()
function resolveErrorIds(errs: FormError[]): FormErrorWithId[] {
return errs.map(err => ({
...err,
- id: inputs.value[err.name]?.id
+ id: err?.name ? inputs.value[err.name]?.id : undefined
}))
}
@@ -159,12 +179,12 @@ async function _validate(opts: { name?: keyof T | (keyof T)[], silent?: boolean,
if (names) {
const otherErrors = errors.value.filter(error => !names.some((name) => {
const pattern = inputs.value?.[name]?.pattern
- return name === error.name || (pattern && error.name.match(pattern))
+ return name === error.name || (pattern && error.name?.match(pattern))
}))
const pathErrors = (await getErrors()).filter(error => names.some((name) => {
const pattern = inputs.value?.[name]?.pattern
- return name === error.name || (pattern && error.name.match(pattern))
+ return name === error.name || (pattern && error.name?.match(pattern))
}))
errors.value = otherErrors.concat(pathErrors)
@@ -269,6 +289,6 @@ defineExpose
diff --git a/src/runtime/components/FormField.vue b/src/runtime/components/FormField.vue
index afa453a2..7fd32a7e 100644
--- a/src/runtime/components/FormField.vue
+++ b/src/runtime/components/FormField.vue
@@ -31,7 +31,12 @@ export interface FormFieldProps {
*/
size?: FormFieldVariants['size']
required?: boolean
+ /** If true, validation on input will be active immediately instead of waiting for a blur event. */
eagerValidation?: boolean
+ /**
+ * Delay in milliseconds before validating the form on input events.
+ * @defaultValue `300`
+ */
validateOnInputDelay?: number
class?: any
ui?: Partial
@@ -63,7 +68,7 @@ const ui = computed(() => formField({
const formErrors = inject[ | null>('form-errors', null)
-const error = computed(() => props.error || formErrors?.value?.find(error => error.name === props.name || (props.errorPattern && error.name.match(props.errorPattern)))?.message)
+const error = computed(() => props.error || formErrors?.value?.find(error => error.name && (error.name === props.name || (props.errorPattern && error.name.match(props.errorPattern))))?.message)
const id = ref(useId())
// Copies id's initial value to bind aria-attributes such as aria-describedby.
diff --git a/src/runtime/components/Input.vue b/src/runtime/components/Input.vue
index 175828b0..20d3db13 100644
--- a/src/runtime/components/Input.vue
+++ b/src/runtime/components/Input.vue
@@ -82,7 +82,7 @@ const props = withDefaults(defineProps](), {
const emits = defineEmits()
const slots = defineSlots()
-const [modelValue, modelModifiers] = defineModel()
+const [modelValue, modelModifiers] = defineModel()
const { emitFormBlur, emitFormInput, emitFormChange, size: formGroupSize, color, id, name, highlight, disabled, emitFormFocus, ariaAttrs } = useFormField(props, { deferInputValidation: true })
const { orientation, size: buttonGroupSize } = useButtonGroup(props)
@@ -111,15 +111,19 @@ function autoFocus() {
}
// Custom function to handle the v-model properties
-function updateInput(value: string) {
+function updateInput(value: string | null) {
if (modelModifiers.trim) {
- value = value.trim()
+ value = value?.trim() ?? null
}
if (modelModifiers.number || props.type === 'number') {
value = looseToNumber(value)
}
+ if (modelModifiers.nullify) {
+ value ||= null
+ }
+
modelValue.value = value
emitFormInput()
}
diff --git a/src/runtime/components/InputMenu.vue b/src/runtime/components/InputMenu.vue
index 59c5c132..ef95e9a9 100644
--- a/src/runtime/components/InputMenu.vue
+++ b/src/runtime/components/InputMenu.vue
@@ -157,7 +157,7 @@ export interface InputMenuSlots {
import { computed, ref, toRef, onMounted, toRaw } from 'vue'
import { ComboboxRoot, ComboboxArrow, ComboboxAnchor, ComboboxInput, ComboboxTrigger, ComboboxPortal, ComboboxContent, ComboboxViewport, ComboboxEmpty, ComboboxGroup, ComboboxLabel, ComboboxSeparator, ComboboxItem, ComboboxItemIndicator, TagsInputRoot, TagsInputItem, TagsInputItemText, TagsInputItemDelete, TagsInputInput, useForwardPropsEmits, useFilter } from 'reka-ui'
import { defu } from 'defu'
-import { isEqual } from 'ohash'
+import { isEqual } from 'ohash/utils'
import { reactivePick, createReusableTemplate } from '@vueuse/core'
import { useAppConfig } from '#imports'
import { useButtonGroup } from '../composables/useButtonGroup'
diff --git a/src/runtime/components/Link.vue b/src/runtime/components/Link.vue
index 34501557..bdcde2d9 100644
--- a/src/runtime/components/Link.vue
+++ b/src/runtime/components/Link.vue
@@ -91,7 +91,7 @@ export interface LinkSlots {
diff --git a/src/runtime/components/NavigationMenu.vue b/src/runtime/components/NavigationMenu.vue
index 27cd18e8..f7cc688d 100644
--- a/src/runtime/components/NavigationMenu.vue
+++ b/src/runtime/components/NavigationMenu.vue
@@ -1,3 +1,4 @@
+