Week Picker
Accessible, unstyled calendar that selects whole weeks and shows ISO week numbers.
|
|
| Package |
@vizejs/ui/week-picker |
| Maturity |
stable |
| Own the source |
vize lib pull week-picker |
| Requires |
calendar, context, controllable-state, id, locale |
| Aliases |
week selector, iso week, week input, sprint week |
| Covers |
HTML input type=week, ISO 8601 week dates, WAI-ARIA grid |
Minimal setup
Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).
vp install @vizejs/ui
Add the public import below to <script setup lang="ts">. Components provide behavior without styles; the preview uses optional Paper styles.
import { WeekPicker, WeekPickerRoot, WeekPickerGrid, WeekPickerHeading, WeekPickerMonthSelect, WeekPickerNext, WeekPickerPrev, WeekPickerYearSelect } from "@vizejs/ui/week-picker";
Or copy the source into your project with vize lib pull week-picker (see Source Distribution).
Try it
This is the basic example maintained with the component source, using the public package imports. The preview adds the optional Paper styles.
Open the interactive example · Styling these components
Copy the example
<!-- Week picker with ISO week numbers, a fixed SSR-safe today, and ISO week submission. -->
<script setup lang="ts">
import { ref } from "vue";
import { WeekPicker, weekOf } from "@vizejs/ui/week-picker";
import type { DateRange, PlainDate } from "@vizejs/ui/week-picker";
function label(date: PlainDate): string {
return `${date.year}-${String(date.month).padStart(2, "0")}-${String(date.day).padStart(2, "0")}`;
}
const sprint = ref<DateRange | null>(weekOf({ year: 2026, month: 10, day: 7 }, 1));
</script>
<template>
<div>
<WeekPicker
v-model="sprint"
name="sprint-week"
locale="en-GB"
aria-label="Sprint week"
:today="{ year: 2026, month: 10, day: 1 }"
/>
<output>
{{ sprint ? `${label(sprint.start)} – ${label(sprint.end)}` : "No week" }}
</output>
</div>
</template>
API
WeekPicker
Source: src/families/date-time/week-picker/week-picker-root.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null | undefined |
undefined |
Consumer-owned base id; nullish values use a deterministic fallback. |
modelValue |
DateRange | null | undefined |
undefined |
Controlled week as a start–end range; undefined selects uncontrolled mode and null clears. |
defaultValue |
DateRange | null | undefined |
null |
Initial uncontrolled week. |
focusedDate |
PlainDate | null | undefined |
undefined |
Controlled keyboard focus date; also decides which months are visible. |
min |
PlainDate | null | undefined |
undefined |
Earliest selectable date, inclusive. |
max |
PlainDate | null | undefined |
undefined |
Latest selectable date, inclusive. |
isDateUnavailable |
DateMatcher | undefined |
undefined |
Predicate for dates that stay focusable but cannot be selected. |
locale |
string | undefined |
undefined |
BCP 47 locale; defaults to the nearest LocaleProvider. |
calendar |
string | undefined |
undefined |
Intl calendar used for display labels only, for example japanese. |
numberingSystem |
string | undefined |
undefined |
Intl numbering system for labels. |
dir |
CalendarDirection | undefined |
undefined |
Text direction; defaults to the nearest LocaleProvider. |
weekStartsOn |
Weekday | undefined |
undefined |
First day of week (0 = Sunday); defaults to the locale preference. |
weekdayFormat |
CalendarWeekdayFormat | undefined |
"short" |
Weekday column label width. |
numberOfMonths |
number | undefined |
1 |
Number of consecutive months rendered. |
pagedNavigation |
boolean | undefined |
false |
Move month controls by numberOfMonths instead of one month. |
fixedWeeks |
boolean | undefined |
false |
Always render six week rows per month. |
today |
PlainDate | null | undefined |
undefined |
Explicit current date; the SSR-safe way to mark today. |
now |
DateTimeNow | undefined |
undefined |
Injectable clock evaluated during setup on server and client. |
timeZone |
string | undefined |
undefined |
IANA time zone used with now and the post-mount host clock. |
disabled |
boolean | undefined |
false |
Disable navigation, focus, and selection. |
readOnly |
boolean | undefined |
false |
Allow navigation while blocking selection. |
name |
string | undefined |
undefined |
Hidden input name that submits the ISO 8601 week (YYYY-Www) of the selected week. |
hideWeekNumbers |
boolean | undefined |
false |
Omit ISO week numbers from the default grid composition. |
ariaLabel |
string | undefined |
undefined |
Accessible name for the calendar group. |
ariaLabelledby |
string | undefined |
undefined |
Ids that label the calendar group; defaults to the heading. |
ariaDescribedby |
string | undefined |
undefined |
Ids that describe the calendar group. |
Events
| Event |
Payload |
Description |
update:modelValue |
[value: DateRange | null] |
Fired when the picker requests a new controlled week. |
change |
[value: DateRange | null, previous: DateRange | null, nativeEvent: Event | null] |
Fired after a distinct committed week with the previous week and triggering event. |
select |
[value: DateRange, nativeEvent: Event] |
Fired for every week activation, even when the week is unchanged. |
update:focusedDate |
[date: PlainDate] |
Fired when keyboard or navigation moves the focus date. |
Slots
| Slot |
Slot props |
Description |
default |
CalendarSlotState |
Week picker composition. Receives months, weekdays, heading, and state; defaults to a header plus one grid per month. |
Exposed
| Member |
Type |
Description |
value |
— |
|
isoWeek |
— |
|
setValue |
— |
|
WeekPickerRoot
Source: src/families/date-time/week-picker/week-picker-root.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null | undefined |
undefined |
Consumer-owned base id; nullish values use a deterministic fallback. |
modelValue |
DateRange | null | undefined |
undefined |
Controlled week as a start–end range; undefined selects uncontrolled mode and null clears. |
defaultValue |
DateRange | null | undefined |
null |
Initial uncontrolled week. |
focusedDate |
PlainDate | null | undefined |
undefined |
Controlled keyboard focus date; also decides which months are visible. |
min |
PlainDate | null | undefined |
undefined |
Earliest selectable date, inclusive. |
max |
PlainDate | null | undefined |
undefined |
Latest selectable date, inclusive. |
isDateUnavailable |
DateMatcher | undefined |
undefined |
Predicate for dates that stay focusable but cannot be selected. |
locale |
string | undefined |
undefined |
BCP 47 locale; defaults to the nearest LocaleProvider. |
calendar |
string | undefined |
undefined |
Intl calendar used for display labels only, for example japanese. |
numberingSystem |
string | undefined |
undefined |
Intl numbering system for labels. |
dir |
CalendarDirection | undefined |
undefined |
Text direction; defaults to the nearest LocaleProvider. |
weekStartsOn |
Weekday | undefined |
undefined |
First day of week (0 = Sunday); defaults to the locale preference. |
weekdayFormat |
CalendarWeekdayFormat | undefined |
"short" |
Weekday column label width. |
numberOfMonths |
number | undefined |
1 |
Number of consecutive months rendered. |
pagedNavigation |
boolean | undefined |
false |
Move month controls by numberOfMonths instead of one month. |
fixedWeeks |
boolean | undefined |
false |
Always render six week rows per month. |
today |
PlainDate | null | undefined |
undefined |
Explicit current date; the SSR-safe way to mark today. |
now |
DateTimeNow | undefined |
undefined |
Injectable clock evaluated during setup on server and client. |
timeZone |
string | undefined |
undefined |
IANA time zone used with now and the post-mount host clock. |
disabled |
boolean | undefined |
false |
Disable navigation, focus, and selection. |
readOnly |
boolean | undefined |
false |
Allow navigation while blocking selection. |
name |
string | undefined |
undefined |
Hidden input name that submits the ISO 8601 week (YYYY-Www) of the selected week. |
hideWeekNumbers |
boolean | undefined |
false |
Omit ISO week numbers from the default grid composition. |
ariaLabel |
string | undefined |
undefined |
Accessible name for the calendar group. |
ariaLabelledby |
string | undefined |
undefined |
Ids that label the calendar group; defaults to the heading. |
ariaDescribedby |
string | undefined |
undefined |
Ids that describe the calendar group. |
Events
| Event |
Payload |
Description |
update:modelValue |
[value: DateRange | null] |
Fired when the picker requests a new controlled week. |
change |
[value: DateRange | null, previous: DateRange | null, nativeEvent: Event | null] |
Fired after a distinct committed week with the previous week and triggering event. |
select |
[value: DateRange, nativeEvent: Event] |
Fired for every week activation, even when the week is unchanged. |
update:focusedDate |
[date: PlainDate] |
Fired when keyboard or navigation moves the focus date. |
Slots
| Slot |
Slot props |
Description |
default |
CalendarSlotState |
Week picker composition. Receives months, weekdays, heading, and state; defaults to a header plus one grid per month. |
Exposed
| Member |
Type |
Description |
mode |
CalendarSelectionMode |
Selection model of the root. |
months |
readonly CalendarMonthState[] |
Visible month grids; empty while pending. |
weekdays |
readonly CalendarWeekdayLabel[] |
Localized weekday labels in column order. |
heading |
string |
Localized heading for the visible months. |
focusedDate |
PlainDate | null |
Keyboard focus target, or null while pending. |
today |
PlainDate | null |
Resolved current date, or null before a clock is available. |
locale |
string |
Resolved BCP 47 locale. |
direction |
CalendarDirection |
Resolved text direction. |
weekStartsOn |
Weekday |
Resolved first day of week. |
disabled |
boolean |
Whether every control is disabled. |
readOnly |
boolean |
Whether selection is blocked while navigation works. |
pending |
boolean |
Whether no date is known yet: no value, focused date, today, or now was supplied, so the grid waits for the client clock after mount. |
state |
CalendarState |
Stable root state token. |
root |
HTMLDivElement | null |
Rendered root element. |
focus |
(options?: FocusOptions) => boolean |
Focus the roving day button; returns whether focus moved. |
setFocusedDate |
(date: PlainDate) => void |
Move the keyboard focus target (and visible months) to a date, clamped to min/max. |
setVisibleMonth |
(month: PlainYearMonth) => void |
Show a month as the first visible month. |
navigate |
(unit: CalendarNavigationUnit, direction: -1 | 1) => boolean |
Navigate by one page of months or years; returns whether the view moved. |
value |
DateRange | null |
Selected week as an inclusive start–end range. |
isoWeek |
IsoWeek | null |
ISO 8601 week of the selection, taken from its fourth day. |
setValue |
(value: DateRange | null) => boolean |
Request a week; returns whether it differs. |
WeekPickerGrid
Source: src/families/date-time/calendar/calendar-grid.vue
Props
| Prop |
Type |
Default |
Description |
monthIndex |
number |
0 |
Zero-based index of the visible month this grid renders. |
showWeekNumbers |
boolean |
false |
Render a leading row header with the ISO 8601 week number of each row. |
weekNumberLabel |
string |
"Wk" |
Visible week-number column header. |
weekNumberHeader |
string |
"Week" |
Full week-number column header used as abbr. |
Slots
| Slot |
Slot props |
Description |
weekday |
CalendarWeekdaySlotState |
Weekday column header content. Receives the weekday, its labels, and column index. |
weekNumber |
CalendarWeekNumberSlotState |
Week-number row header content. Receives the ISO week and the row's days. |
day |
CalendarDayState |
Day button content. Receives the complete day state; defaults to the localized day number. |
WeekPickerHeading
Source: src/families/date-time/calendar/calendar-heading.vue
Slots
| Slot |
Slot props |
Description |
default |
CalendarHeadingSlotState |
Heading content. Receives the localized heading and visible months. |
WeekPickerMonthSelect
Source: src/families/date-time/calendar/calendar-month-select.vue
Props
| Prop |
Type |
Default |
Description |
ariaLabel |
string |
"Month" |
Accessible name of the native select. |
Events
| Event |
Payload |
Description |
change |
[month: number, nativeEvent: Event] |
Fired after the user picks a month, with the ISO month number. |
WeekPickerNext
Source: src/families/date-time/calendar/calendar-next.vue
Props
| Prop |
Type |
Default |
Description |
unit |
CalendarNavigationUnit |
"month" |
Whether the control pages by month (or numberOfMonths when paged) or by year. |
ariaLabel |
string |
undefined |
Accessible name; defaults to "Next month" or "Next year". |
Events
| Event |
Payload |
Description |
click |
[nativeEvent: MouseEvent] |
Fired before navigation. Call preventDefault() to keep the view unchanged. |
Slots
| Slot |
Slot props |
Description |
default |
CalendarNavigationSlotState |
Control content. Receives the unit and whether navigation is possible. |
WeekPickerPrev
Source: src/families/date-time/calendar/calendar-prev.vue
Props
| Prop |
Type |
Default |
Description |
unit |
CalendarNavigationUnit |
"month" |
Whether the control pages by month (or numberOfMonths when paged) or by year. |
ariaLabel |
string |
undefined |
Accessible name; defaults to "Previous month" or "Previous year". |
Events
| Event |
Payload |
Description |
click |
[nativeEvent: MouseEvent] |
Fired before navigation. Call preventDefault() to keep the view unchanged. |
Slots
| Slot |
Slot props |
Description |
default |
CalendarNavigationSlotState |
Control content. Receives the unit and whether navigation is possible. |
WeekPickerYearSelect
Source: src/families/date-time/calendar/calendar-year-select.vue
Props
| Prop |
Type |
Default |
Description |
from |
number |
undefined |
First listed year; defaults to the min year or ten years before the view. |
to |
number |
undefined |
Last listed year; defaults to the max year or ten years after the view. |
ariaLabel |
string |
"Year" |
Accessible name of the native select. |
Events
| Event |
Payload |
Description |
change |
[year: number, nativeEvent: Event] |
Fired after the user picks a year. |
Behavior
Normative state x input -> outcome table for week-picker-root.vue
(@vizejs/ui/week-picker). WeekPicker reuses the Calendar runtime and parts
(calendar.behavior.md keyboard, locale, bounds, and SSR rows apply) with a
whole-week selection model. Every row is proven by the named test.
| # |
State |
Input |
Outcome |
Proven by |
| W1 |
any |
render / day activation |
grids show a leading <th scope="row"> ISO week number column (omit with hideWeekNumbers); activating a day selects its locale week as a DateRange, emits update:modelValue, change, select, and name submits YYYY-Www |
activating any day selects its locale week and shows ISO week numbers |
| W2 |
any |
pointer / keyboard focus |
the week under the pointer or focus is previewed with data-preview; weeks follow the locale start (Sunday for en-US); isoWeek and setValue are exposed |
pointer and keyboard focus preview the week; US locales start on Sunday |
| W3 |
model |
helpers |
isoWeekOf, startOfIsoWeek, formatIsoWeek, and parseIsoWeek handle year boundaries and week 53; weekOf honors any week start |
ISO week helpers cover year boundaries and week 53 |
| W4 |
SSR |
isolated requests |
byte-identical markup and silent hydration |
renders byte-identical week picker markup across isolated SSR requests, hydrates week picker markup without mismatches |