Skip to content

Commit 3c8468e

Browse files
authored
Merge branch 'nuxt:v3' into feat/toolbar-component
2 parents 7456c37 + 8922c73 commit 3c8468e

File tree

161 files changed

+6236
-4504
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

161 files changed

+6236
-4504
lines changed

CHANGELOG.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,51 @@
11
# Changelog
22

3+
## [3.2.0](https://github.com/nuxt/ui/compare/v3.1.3...v3.2.0) (2025-06-25)
4+
5+
### ⚠ BREAKING CHANGES
6+
7+
* **useOverlay:** correct spelling of `unmount` function (#4051)
8+
9+
### Features
10+
11+
* **Avatar:** add `chip` prop ([#4224](https://github.com/nuxt/ui/issues/4224)) ([03ac395](https://github.com/nuxt/ui/commit/03ac395164c02c964361c68743268b1bc90aae59))
12+
* **Carousel:** allow customization of active dot color ([#4229](https://github.com/nuxt/ui/issues/4229)) ([2ee1c5a](https://github.com/nuxt/ui/commit/2ee1c5ac2e20ab9ce2f4037a8e8c64e561b0428b))
13+
* **CommandPalette:** handle `children` in items ([#4226](https://github.com/nuxt/ui/issues/4226)) ([59c26ec](https://github.com/nuxt/ui/commit/59c26ec1230375a24fbaf8a630a696ae854700c7))
14+
* **extendLocale:** new composable ([0f558fc](https://github.com/nuxt/ui/commit/0f558fc0d014d51549222accfc50286d1770d1aa)), closes [#3729](https://github.com/nuxt/ui/issues/3729)
15+
* **Form:** expose loading state to default slot ([#4247](https://github.com/nuxt/ui/issues/4247)) ([ea0c459](https://github.com/nuxt/ui/commit/ea0c459306be585bacaaf5b433114d072550c824))
16+
* **InputTags:** new component ([#4261](https://github.com/nuxt/ui/issues/4261)) ([54bb228](https://github.com/nuxt/ui/commit/54bb2282c58d3bf5a7dde4cdee687c68efd934a0))
17+
* **locale:** add Luxembourgish language ([#4264](https://github.com/nuxt/ui/issues/4264)) ([43cbb94](https://github.com/nuxt/ui/commit/43cbb94ee25106b414fc8fe979fa65ebaa9ccc76))
18+
* **Modal/Slideover:** add `actions` slot ([#4358](https://github.com/nuxt/ui/issues/4358)) ([8156971](https://github.com/nuxt/ui/commit/81569713e9da9d5531ecdf4614660b84c686fa81))
19+
* **Modal/Slideover:** add `close` method in slots ([#4219](https://github.com/nuxt/ui/issues/4219)) ([5835eb5](https://github.com/nuxt/ui/commit/5835eb5f0f835b5f03646dec78f85b2f556a109b))
20+
* **Select/SelectMenu/Tabs:** expose trigger refs ([7a2bd4e](https://github.com/nuxt/ui/commit/7a2bd4e6179373902ba6f285903ea896fd1d378f)), closes [#4292](https://github.com/nuxt/ui/issues/4292)
21+
* **Select/SelectMenu:** handle dynamic `autofocus` ([1a4de49](https://github.com/nuxt/ui/commit/1a4de49c1665c9ef65279315be0393d6272447b9)), closes [#4324](https://github.com/nuxt/ui/issues/4324)
22+
* **Table:** add `body-top` / `body-bottom` slots ([#4354](https://github.com/nuxt/ui/issues/4354)) ([595fc64](https://github.com/nuxt/ui/commit/595fc64515613fe82c3a56fc5518f2e3fcce6e19))
23+
* **Timeline:** add `reverse` prop ([#4316](https://github.com/nuxt/ui/issues/4316)) ([5170cfd](https://github.com/nuxt/ui/commit/5170cfd7eb44a25c64673cf12979f9ca1049695f))
24+
* **Timeline:** new component ([#4215](https://github.com/nuxt/ui/issues/4215)) ([8017767](https://github.com/nuxt/ui/commit/80177679f2aa0d7f0e39e639a02d527a06e6172c))
25+
26+
### Bug Fixes
27+
28+
* **Card/Drawer/Modal:** prevent scrollbars overflow ([#4368](https://github.com/nuxt/ui/issues/4368)) ([c3adc38](https://github.com/nuxt/ui/commit/c3adc381c90dad7152e27fc303ee678efc7c4c94))
29+
* **components:** remove default `md` size on buttons ([#4357](https://github.com/nuxt/ui/issues/4357)) ([be41aed](https://github.com/nuxt/ui/commit/be41aed1f3d3476801e1840dbb8766926bc93c05))
30+
* **defineShortcuts:** allow `meta_-` shortcut ([#4321](https://github.com/nuxt/ui/issues/4321)) ([4e7c1c9](https://github.com/nuxt/ui/commit/4e7c1c9c305b45dd76d4c238e70a6aeedae78c8b))
31+
* **Form:** conditionally type form data via `transform` prop ([#4188](https://github.com/nuxt/ui/issues/4188)) ([37abcc6](https://github.com/nuxt/ui/commit/37abcc6a5b0a678be626673af5067956657a50d6))
32+
* **Form:** expose reactive fields ([#4386](https://github.com/nuxt/ui/issues/4386)) ([1a8feb7](https://github.com/nuxt/ui/commit/1a8feb751e6827c414ef82fe9fb259ba7dcc7e08))
33+
* **InputMenu/SelectMenu:** dynamic `empty` size ([ba3c6e8](https://github.com/nuxt/ui/commit/ba3c6e8788ed75d86d4406749797da52d7816b84)), closes [#4377](https://github.com/nuxt/ui/issues/4377)
34+
* **InputTags:** extend emits interface ([8781a07](https://github.com/nuxt/ui/commit/8781a079096def0d3bae5b8d896db0df6ce37e23))
35+
* **Modal/Slideover:** don't emit `close:prevent` on `closeAutoFocus` ([150b334](https://github.com/nuxt/ui/commit/150b334b1d242c6dc132193e23359c03e6f35666))
36+
* **NavigationMenu:** nested accordion context at every level ([#4363](https://github.com/nuxt/ui/issues/4363)) ([2fa8db6](https://github.com/nuxt/ui/commit/2fa8db64ddf4c92a19e73774143518d87d001b72))
37+
* **NavigationMenu:** set content `max-height` in `horizontal` orientation ([62bc7b2](https://github.com/nuxt/ui/commit/62bc7b25a2d205d8dffb47a109196f91ff3e823a)), closes [#4208](https://github.com/nuxt/ui/issues/4208)
38+
* **Pagination:** match default button `size` ([#4350](https://github.com/nuxt/ui/issues/4350)) ([4dd56c8](https://github.com/nuxt/ui/commit/4dd56c8111e5a224105b82d541b7742b46abb34a))
39+
* **Select/SelectMenu:** display falsy values ([7df7ee3](https://github.com/nuxt/ui/commit/7df7ee336a925d7ee07f866551dad9350785c9fc))
40+
* **Select/SelectMenu:** prevent empty string display when multiple ([483e473](https://github.com/nuxt/ui/commit/483e473e3f5681cc97c3766ea47283dc95f76345))
41+
* **SelectMenu:** dynamic input size ([b0364b9](https://github.com/nuxt/ui/commit/b0364b96b73b9e543781a35962c03b5a983352c4))
42+
* **Table:** use `tr` as separator ([#4083](https://github.com/nuxt/ui/issues/4083)) ([edca3bc](https://github.com/nuxt/ui/commit/edca3bcb743c7eb63e6abbaa801d3858342a8777))
43+
* **Toast:** calc height on next tick ([3bf5acb](https://github.com/nuxt/ui/commit/3bf5acb683f0ad09735b2417d265d6fcfd901b11)), closes [#4265](https://github.com/nuxt/ui/issues/4265)
44+
* **Toaster:** smoother visibility transition for stacked toasts ([#4367](https://github.com/nuxt/ui/issues/4367)) ([abfd0ed](https://github.com/nuxt/ui/commit/abfd0ede036fa2953f9abc841d77ac71bbd3bba9))
45+
* **useOverlay:** correct spelling of `unmount` function ([#4051](https://github.com/nuxt/ui/issues/4051)) ([546df57](https://github.com/nuxt/ui/commit/546df572fca60325315bed17c9be3367052fb7a9))
46+
* **useOverlay:** set props to original props when `defaultOpen` is set ([#4308](https://github.com/nuxt/ui/issues/4308)) ([66355ba](https://github.com/nuxt/ui/commit/66355ba301d569b9f44527bafc5f8f09bcda63c0))
47+
* **useOverlay:** use original props when not provided to `open` ([#4269](https://github.com/nuxt/ui/issues/4269)) ([bf56e15](https://github.com/nuxt/ui/commit/bf56e15a2eed7d51199d5641649a822e91ca41ba))
48+
349
## [3.1.3](https://github.com/nuxt/ui/compare/v3.1.2...v3.1.3) (2025-05-26)
450

551
### ⚠ BREAKING CHANGES

cli/templates.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ const test = ({ name, prose, content }) => {
147147
? undefined
148148
: `
149149
import { describe, it, expect } from 'vitest'
150-
import ${upperName}, { type ${upperName}Props, type ${upperName}Slots } from '../../${content ? '../' : ''}src/runtime/components/${content ? 'content/' : ''}${upperName}.vue'
150+
import ${upperName} from '../../${content ? '../' : ''}src/runtime/components/${content ? 'content/' : ''}${upperName}.vue'
151+
import type { ${upperName}Props, ${upperName}Slots } from '../../${content ? '../' : ''}src/runtime/components/${content ? 'content/' : ''}${upperName}.vue'
151152
import ComponentRender from '../${content ? '../' : ''}component-render'
152153
153154
describe('${upperName}', () => {

docs/app/components/Banner.vue

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<template>
22
<UBanner
33
id="ui3-launch"
4+
title="Nuxt UI v3 is officially released!"
45
icon="i-lucide-rocket"
56
:actions="[
67
{
@@ -10,9 +11,5 @@
1011
}
1112
]"
1213
close
13-
>
14-
<template #title>
15-
<span class="font-semibold">Nuxt UI v3</span> is officially released.
16-
</template>
17-
</UBanner>
14+
/>
1815
</template>
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<script setup lang="ts">
2+
const route = useRoute()
3+
const toast = useToast()
4+
const { copy, copied } = useClipboard()
5+
const site = useSiteConfig()
6+
7+
const mdPath = computed(() => `${site.url}/raw${route.path}.md`)
8+
9+
const items = [
10+
{
11+
label: 'Copy Markdown link',
12+
icon: 'i-lucide-link',
13+
onSelect() {
14+
copy(mdPath.value)
15+
toast.add({
16+
title: 'Copied to clipboard',
17+
icon: 'i-lucide-check-circle'
18+
})
19+
}
20+
},
21+
{
22+
label: 'View as Markdown',
23+
icon: 'i-simple-icons:markdown',
24+
target: '_blank',
25+
to: `/raw${route.path}.md`
26+
},
27+
{
28+
label: 'Open in ChatGPT',
29+
icon: 'i-simple-icons:openai',
30+
target: '_blank',
31+
to: `https://chatgpt.com/?hints=search&q=${encodeURIComponent(`Read ${mdPath.value} so I can ask questions about it.`)}`
32+
},
33+
{
34+
label: 'Open in Claude',
35+
icon: 'i-simple-icons:anthropic',
36+
target: '_blank',
37+
to: `https://claude.ai/new?q=${encodeURIComponent(`Read ${mdPath.value} so I can ask questions about it.`)}`
38+
}
39+
]
40+
41+
async function copyPage() {
42+
copy(await $fetch<string>(`/raw${route.path}.md`))
43+
}
44+
</script>
45+
46+
<template>
47+
<UButtonGroup>
48+
<UButton
49+
label="Copy page"
50+
:icon="copied ? 'i-lucide-copy-check' : 'i-lucide-copy'"
51+
color="neutral"
52+
variant="outline"
53+
:ui="{
54+
leadingIcon: [copied ? 'text-primary' : 'text-neutral', 'size-3.5']
55+
}"
56+
@click="copyPage"
57+
/>
58+
<UDropdownMenu
59+
:items="items"
60+
:content="{
61+
align: 'end',
62+
side: 'bottom',
63+
sideOffset: 8
64+
}"
65+
:ui="{
66+
content: 'w-48'
67+
}"
68+
>
69+
<UButton
70+
icon="i-lucide-chevron-down"
71+
size="sm"
72+
color="neutral"
73+
variant="outline"
74+
/>
75+
</UDropdownMenu>
76+
</UButtonGroup>
77+
</template>

docs/app/components/content/examples/form/FormExampleSuperstruct.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script setup lang="ts">
2-
import { object, string, nonempty, refine, type Infer } from 'superstruct'
2+
import { object, string, nonempty, refine } from 'superstruct'
3+
import type { Infer } from 'superstruct'
34
import type { FormSubmitEvent } from '@nuxt/ui'
45
56
const schema = object({

docs/app/components/content/examples/form/FormExampleYup.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script setup lang="ts">
2-
import { object, string, type InferType } from 'yup'
2+
import { object, string } from 'yup'
3+
import type { InferType } from 'yup'
34
import type { FormSubmitEvent } from '@nuxt/ui'
45
56
const schema = object({
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<script setup lang="ts">
2+
const open = ref(false)
3+
const anchor = ref({ x: 0, y: 0 })
4+
5+
const reference = computed(() => ({
6+
getBoundingClientRect: () =>
7+
({
8+
width: 0,
9+
height: 0,
10+
left: anchor.value.x,
11+
right: anchor.value.x,
12+
top: anchor.value.y,
13+
bottom: anchor.value.y,
14+
...anchor.value
15+
} as DOMRect)
16+
}))
17+
</script>
18+
19+
<template>
20+
<UPopover
21+
:open="open"
22+
:reference="reference"
23+
:content="{ side: 'top', sideOffset: 16, updatePositionStrategy: 'always' }"
24+
>
25+
<div
26+
class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72"
27+
@pointerenter="open = true"
28+
@pointerleave="open = false"
29+
@pointermove="(ev) => {
30+
anchor.x = ev.clientX
31+
anchor.y = ev.clientY
32+
}"
33+
>
34+
Hover me
35+
</div>
36+
37+
<template #content>
38+
<div class="p-4">
39+
{{ anchor.x.toFixed(0) }} - {{ anchor.y.toFixed(0) }}
40+
</div>
41+
</template>
42+
</UPopover>
43+
</template>
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<script setup lang="ts">
2+
import { h, resolveComponent } from 'vue'
3+
import type { TableColumn, TableRow } from '@nuxt/ui'
4+
5+
const UBadge = resolveComponent('UBadge')
6+
7+
type Payment = {
8+
id: string
9+
date: string
10+
status: 'paid' | 'failed' | 'refunded'
11+
email: string
12+
amount: number
13+
}
14+
15+
const data = ref<Payment[]>([{
16+
id: '4600',
17+
date: '2024-03-11T15:30:00',
18+
status: 'paid',
19+
20+
amount: 594
21+
}, {
22+
id: '4599',
23+
date: '2024-03-11T10:10:00',
24+
status: 'failed',
25+
26+
amount: 276
27+
}, {
28+
id: '4598',
29+
date: '2024-03-11T08:50:00',
30+
status: 'refunded',
31+
32+
amount: 315
33+
}, {
34+
id: '4597',
35+
date: '2024-03-10T19:45:00',
36+
status: 'paid',
37+
38+
amount: 529
39+
}, {
40+
id: '4596',
41+
date: '2024-03-10T15:55:00',
42+
status: 'paid',
43+
44+
amount: 639
45+
}])
46+
47+
const columns: TableColumn<Payment>[] = [{
48+
accessorKey: 'id',
49+
header: '#',
50+
cell: ({ row }) => `#${row.getValue('id')}`
51+
}, {
52+
accessorKey: 'date',
53+
header: 'Date',
54+
cell: ({ row }) => {
55+
return new Date(row.getValue('date')).toLocaleString('en-US', {
56+
day: 'numeric',
57+
month: 'short',
58+
hour: '2-digit',
59+
minute: '2-digit',
60+
hour12: false
61+
})
62+
}
63+
}, {
64+
accessorKey: 'status',
65+
header: 'Status',
66+
cell: ({ row }) => {
67+
const color = ({
68+
paid: 'success' as const,
69+
failed: 'error' as const,
70+
refunded: 'neutral' as const
71+
})[row.getValue('status') as string]
72+
73+
return h(UBadge, { class: 'capitalize', variant: 'subtle', color }, () => row.getValue('status'))
74+
}
75+
}, {
76+
accessorKey: 'email',
77+
header: 'Email'
78+
}, {
79+
accessorKey: 'amount',
80+
header: () => h('div', { class: 'text-right' }, 'Amount'),
81+
footer: ({ column }) => {
82+
const total = column.getFacetedRowModel().rows.reduce((acc: number, row: TableRow<Payment>) => acc + Number.parseFloat(row.getValue('amount')), 0)
83+
84+
const formatted = new Intl.NumberFormat('en-US', {
85+
style: 'currency',
86+
currency: 'EUR'
87+
}).format(total)
88+
89+
return h('div', { class: 'text-right font-medium' }, `Total: ${formatted}`)
90+
},
91+
cell: ({ row }) => {
92+
const amount = Number.parseFloat(row.getValue('amount'))
93+
94+
const formatted = new Intl.NumberFormat('en-US', {
95+
style: 'currency',
96+
currency: 'EUR'
97+
}).format(amount)
98+
99+
return h('div', { class: 'text-right font-medium' }, formatted)
100+
}
101+
}]
102+
</script>
103+
104+
<template>
105+
<UTable :data="data" :columns="columns" class="flex-1" />
106+
</template>

docs/app/components/content/examples/table/TableGroupedRowsExample.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<script setup lang="ts">
22
import { h, resolveComponent } from 'vue'
33
import type { TableColumn } from '@nuxt/ui'
4-
import { getGroupedRowModel, type GroupingOptions } from '@tanstack/vue-table'
4+
import { getGroupedRowModel } from '@tanstack/vue-table'
5+
import type { GroupingOptions } from '@tanstack/vue-table'
56
67
const UBadge = resolveComponent('UBadge')
78

0 commit comments

Comments
 (0)