Skip to content

Commit 4d64993

Browse files
committed
feat(calendar): add month/year picker
1 parent d0971ba commit 4d64993

16 files changed

Lines changed: 3083 additions & 1108 deletions

File tree

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<script setup lang="ts">
2+
import type { CalendarDate } from '@internationalized/date'
3+
4+
const modelValue = shallowRef<CalendarDate>()
5+
6+
const displayValue = computed(() => {
7+
if (!modelValue.value) return 'Select month'
8+
const d = new Date(modelValue.value.year, modelValue.value.month - 1, 1)
9+
return new Intl.DateTimeFormat('en', { month: 'short', year: 'numeric' }).format(d)
10+
})
11+
</script>
12+
13+
<template>
14+
<UPopover>
15+
<UButton variant="outline" color="neutral" trailing-icon="i-lucide-calendar">
16+
{{ displayValue }}
17+
</UButton>
18+
19+
<template #content>
20+
<UCalendar v-model="modelValue" type="month" />
21+
</template>
22+
</UPopover>
23+
</template>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<script setup lang="ts">
2+
import type { CalendarDate } from '@internationalized/date'
3+
4+
const modelValue = shallowRef<CalendarDate>()
5+
6+
const displayValue = computed(() => modelValue.value ? String(modelValue.value.year) : 'Select year')
7+
</script>
8+
9+
<template>
10+
<UPopover>
11+
<UButton variant="outline" color="neutral" trailing-icon="i-lucide-calendar">
12+
{{ displayValue }}
13+
</UButton>
14+
15+
<template #content>
16+
<UCalendar v-model="modelValue" type="year" />
17+
</template>
18+
</UPopover>
19+
</template>

docs/app/pages/team.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ defineOgImageComponent('Docs')
1616
1717
const { data: module } = await useFetch('/api/module.json')
1818
19-
const contributors = computed(() => module.value?.contributors?.filter(contributor => !module.value?.team?.find(user => user.login === contributor.username)))
19+
const contributors = computed(() => module.value?.contributors?.filter((contributor: { username: string }) => !module.value?.team?.find((user: { login: string }) => user.login === contributor.username)))
2020
2121
const icons = {
2222
website: 'i-lucide-link',

docs/content/docs/2.components/calendar.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,65 @@ props:
209209
---
210210
::
211211

212+
### Type
213+
214+
Use the `type` prop to change the calendar picker type. Defaults to `date`.
215+
216+
Set `type="month"` for a month-only picker.
217+
218+
::component-code
219+
---
220+
cast:
221+
modelValue: DateValue
222+
ignore:
223+
- modelValue
224+
- type
225+
external:
226+
- modelValue
227+
props:
228+
type: month
229+
modelValue: [2022, 3, 1]
230+
---
231+
::
232+
233+
Set `type="year"` for a year-only picker.
234+
235+
::component-code
236+
---
237+
cast:
238+
modelValue: DateValue
239+
ignore:
240+
- modelValue
241+
- type
242+
external:
243+
- modelValue
244+
props:
245+
type: year
246+
modelValue: [2022, 1, 1]
247+
---
248+
::
249+
250+
### Default View
251+
252+
Use the `default-view` prop to set the initial view. Defaults to `day` when `type="date"`, or to the picker type when using `type="month"` or `type="year"`.
253+
254+
::component-code
255+
---
256+
cast:
257+
defaultValue: DateValue
258+
ignore:
259+
- defaultView
260+
- defaultValue
261+
external:
262+
- defaultValue
263+
props:
264+
defaultView: month
265+
defaultValue: [2022, 2, 3]
266+
---
267+
::
268+
269+
The heading is clickable when using `type="date"` (default) and allows switching between day, month, and year views. Selecting a month or year navigates back to the day view.
270+
212271
## Examples
213272

214273
### With chip events
@@ -275,6 +334,26 @@ name: 'calendar-external-controls-example'
275334
---
276335
::
277336

337+
### As a MonthPicker
338+
339+
Use `type="month"` with a [Popover](/docs/components/popover) to create a month picker.
340+
341+
::component-example
342+
---
343+
name: 'calendar-month-picker-example'
344+
---
345+
::
346+
347+
### As a YearPicker
348+
349+
Use `type="year"` with a [Popover](/docs/components/popover) to create a year picker.
350+
351+
::component-example
352+
---
353+
name: 'calendar-year-picker-example'
354+
---
355+
::
356+
278357
### As a DatePicker
279358

280359
Use a [Button](/docs/components/button) and a [Popover](/docs/components/popover) component to create a date picker.

docs/package.json

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
"typecheck": "nuxt typecheck"
1010
},
1111
"dependencies": {
12-
"@ai-sdk/gateway": "^3.0.32",
13-
"@ai-sdk/mcp": "^1.0.18",
14-
"@ai-sdk/vue": "^3.0.68",
12+
"@ai-sdk/gateway": "^3.0.22",
13+
"@ai-sdk/mcp": "^1.0.13",
14+
"@ai-sdk/vue": "^3.0.49",
1515
"@iconify-json/logos": "^1.2.10",
1616
"@iconify-json/lucide": "^1.2.87",
17-
"@iconify-json/simple-icons": "^1.2.69",
17+
"@iconify-json/simple-icons": "^1.2.68",
1818
"@iconify-json/vscode-icons": "^1.2.40",
1919
"@modelcontextprotocol/sdk": "^1.25.3",
2020
"@nuxt/a11y": "1.0.0-alpha.1",
@@ -25,15 +25,15 @@
2525
"@nuxtjs/mdc": "^0.20.0",
2626
"@nuxtjs/plausible": "^2.0.1",
2727
"@octokit/rest": "^22.0.1",
28-
"@regle/core": "^1.17.4",
29-
"@regle/rules": "^1.17.4",
30-
"@tiptap/extension-emoji": "^3.18.0",
31-
"@tiptap/extension-text-align": "^3.18.0",
28+
"@regle/core": "^1.17.1",
29+
"@regle/rules": "^1.17.1",
30+
"@tiptap/extension-emoji": "^3.17.1",
31+
"@tiptap/extension-text-align": "^3.17.1",
3232
"@vercel/analytics": "^1.6.1",
3333
"@vercel/speed-insights": "^1.3.1",
34-
"@vueuse/integrations": "^14.2.0",
35-
"@vueuse/nuxt": "^14.2.0",
36-
"ai": "^6.0.68",
34+
"@vueuse/integrations": "^14.1.0",
35+
"@vueuse/nuxt": "^14.1.0",
36+
"ai": "^6.0.49",
3737
"better-sqlite3": "^12.6.2",
3838
"capture-website": "^5.1.0",
3939
"joi": "^18.0.2",
@@ -46,7 +46,7 @@
4646
"nuxt-llms": "^0.2.0",
4747
"nuxt-og-image": "^5.1.13",
4848
"prettier": "^3.8.1",
49-
"shiki": "^3.22.0",
49+
"shiki": "^3.21.0",
5050
"shiki-stream": "^0.1.4",
5151
"shiki-transformer-color-highlight": "^1.0.0",
5252
"simple-git": "^3.30.0",
@@ -60,8 +60,5 @@
6060
"vue-component-meta": "^3.2.4",
6161
"yup": "^1.7.1",
6262
"zod": "^4.3.6"
63-
},
64-
"devDependencies": {
65-
"@types/sortablejs": "^1.15.9"
6663
}
6764
}

package.json

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "@nuxt/ui",
33
"description": "A UI Library for Modern Web Apps, powered by Vue & Tailwind CSS.",
44
"version": "4.4.0",
5-
"packageManager": "pnpm@10.28.2",
5+
"packageManager": "pnpm@10.28.1",
66
"repository": {
77
"type": "git",
88
"url": "git+https://github.com/nuxt/ui.git"
@@ -123,7 +123,7 @@
123123
"release": "release-it"
124124
},
125125
"dependencies": {
126-
"@floating-ui/dom": "^1.7.5",
126+
"@floating-ui/dom": "^1.7.4",
127127
"@iconify/vue": "^5.0.0",
128128
"@internationalized/date": "^3.10.1",
129129
"@internationalized/number": "^3.6.5",
@@ -137,27 +137,27 @@
137137
"@tailwindcss/vite": "^4.1.18",
138138
"@tanstack/vue-table": "^8.21.3",
139139
"@tanstack/vue-virtual": "^3.13.18",
140-
"@tiptap/core": "^3.18.0",
141-
"@tiptap/extension-bubble-menu": "^3.18.0",
142-
"@tiptap/extension-code": "^3.18.0",
143-
"@tiptap/extension-collaboration": "^3.18.0",
144-
"@tiptap/extension-drag-handle": "^3.18.0",
145-
"@tiptap/extension-drag-handle-vue-3": "^3.18.0",
146-
"@tiptap/extension-floating-menu": "^3.18.0",
147-
"@tiptap/extension-horizontal-rule": "^3.18.0",
148-
"@tiptap/extension-image": "^3.18.0",
149-
"@tiptap/extension-mention": "^3.18.0",
150-
"@tiptap/extension-node-range": "^3.18.0",
151-
"@tiptap/extension-placeholder": "^3.18.0",
152-
"@tiptap/markdown": "^3.18.0",
153-
"@tiptap/pm": "^3.18.0",
154-
"@tiptap/starter-kit": "^3.18.0",
155-
"@tiptap/suggestion": "^3.18.0",
156-
"@tiptap/vue-3": "^3.18.0",
140+
"@tiptap/core": "^3.17.1",
141+
"@tiptap/extension-bubble-menu": "^3.17.1",
142+
"@tiptap/extension-code": "^3.17.1",
143+
"@tiptap/extension-collaboration": "^3.17.1",
144+
"@tiptap/extension-drag-handle": "^3.17.1",
145+
"@tiptap/extension-drag-handle-vue-3": "^3.17.1",
146+
"@tiptap/extension-floating-menu": "^3.17.1",
147+
"@tiptap/extension-horizontal-rule": "^3.17.1",
148+
"@tiptap/extension-image": "^3.17.1",
149+
"@tiptap/extension-mention": "^3.17.1",
150+
"@tiptap/extension-node-range": "^3.17.1",
151+
"@tiptap/extension-placeholder": "^3.17.1",
152+
"@tiptap/markdown": "^3.17.1",
153+
"@tiptap/pm": "^3.17.1",
154+
"@tiptap/starter-kit": "^3.17.1",
155+
"@tiptap/suggestion": "^3.17.1",
156+
"@tiptap/vue-3": "^3.17.1",
157157
"@unhead/vue": "^2.1.2",
158-
"@vueuse/core": "^14.2.0",
159-
"@vueuse/integrations": "^14.2.0",
160-
"@vueuse/shared": "^14.2.0",
158+
"@vueuse/core": "^14.1.0",
159+
"@vueuse/integrations": "^14.1.0",
160+
"@vueuse/shared": "^14.1.0",
161161
"colortranslator": "^5.0.0",
162162
"consola": "^3.4.2",
163163
"defu": "^6.1.4",
@@ -176,7 +176,7 @@
176176
"motion-v": "^1.10.2",
177177
"ohash": "^2.0.11",
178178
"pathe": "^2.0.3",
179-
"reka-ui": "2.8.0",
179+
"reka-ui": "https://pkg.pr.new/unovue/reka-ui@2434",
180180
"scule": "^1.3.0",
181181
"tailwind-merge": "^3.4.0",
182182
"tailwind-variants": "^3.2.2",
@@ -193,14 +193,17 @@
193193
"@nuxt/eslint-config": "^1.13.0",
194194
"@nuxt/module-builder": "^1.0.2",
195195
"@nuxt/test-utils": "^3.23.0",
196+
"@nuxtjs/mdc": "0.20.0",
196197
"@release-it/conventional-changelog": "^10.0.4",
197198
"@tanstack/table-core": "^8.21.3",
198199
"@vitejs/plugin-vue": "^6.0.2",
200+
"@vue/compiler-dom": "^3.5.27",
201+
"@vue/server-renderer": "^3.5.27",
199202
"@vue/test-utils": "^2.4.6",
200-
"ai": "^6.0.68",
203+
"ai": "^6.0.49",
201204
"embla-carousel": "^8.6.0",
202205
"eslint": "^9.39.2",
203-
"happy-dom": "^20.5.0",
206+
"happy-dom": "^20.3.9",
204207
"nuxt": "^4.3.0",
205208
"release-it": "^19.2.4",
206209
"unbuild": "^3.6.1",

playgrounds/nuxt/package.json

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@
99
"typecheck": "nuxt typecheck"
1010
},
1111
"dependencies": {
12-
"@ai-sdk/gateway": "^3.0.32",
13-
"@ai-sdk/vue": "^3.0.68",
12+
"@ai-sdk/gateway": "^3.0.22",
13+
"@ai-sdk/vue": "^3.0.49",
1414
"@iconify-json/lucide": "^1.2.87",
15-
"@iconify-json/simple-icons": "^1.2.69",
15+
"@iconify-json/simple-icons": "^1.2.68",
1616
"@internationalized/date": "^3.10.1",
1717
"@nuxt/content": "^3.11.0",
1818
"@nuxt/ui": "workspace:*",
19-
"@tiptap/extension-emoji": "^3.18.0",
20-
"@tiptap/extension-text-align": "^3.18.0",
21-
"ai": "^6.0.68",
19+
"@nuxtjs/mdc": "0.20.0",
20+
"@tiptap/extension-emoji": "^3.17.1",
21+
"@tiptap/extension-text-align": "^3.17.1",
22+
"ai": "^6.0.49",
2223
"nuxt": "^4.3.0",
2324
"tailwindcss": "^4.1.18",
2425
"zod": "^4.3.6"

playgrounds/vue/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
},
1212
"dependencies": {
1313
"@nuxt/ui": "workspace:*",
14-
"@tiptap/extension-emoji": "^3.18.0",
15-
"@tiptap/extension-text-align": "^3.18.0",
14+
"@tiptap/extension-emoji": "^3.17.1",
15+
"@tiptap/extension-text-align": "^3.17.1",
1616
"tailwindcss": "^4.1.18",
1717
"vue": "^3.5.25",
1818
"vue-router": "^4.6.3",

0 commit comments

Comments
 (0)