Month day picker

Picks a month and day for a date that repeats every year.

Refined portVue source: WildMonthDayPicker.vueStorybook story: Forms/Month Day PickerReact component: WMonthDayPicker

Try it

Start on 31 January, jump to April, then back. Compare the two overflow rules.

Stored day 31 · shows January 31
Jump to
Overflow
Year
Size
Error
Disabled
<WMonthDayPicker
  value={repeatsOn}
  onChange={setRepeatsOn}
  year={2026}
  overflow="clamp"
  size="sm"
  ariaLabel="Repeats on"
/>

When to use

  • Use it for a date that repeats every year, where the stored value carries no year.
  • Use hold when the chosen day must survive a change of month, such as the 31st.
  • Use clamp when the date must always exist in the month shown.
Don’t use it

Overflow

When a month is shorter than the chosen day, clamp moves the day to the month’s last day. hold keeps the stored day, shows the last day, and notes the held day beside the field.

clamp
hold
<WMonthDayPicker value={repeatsOn} onChange={setRepeatsOn} overflow="clamp" />
<WMonthDayPicker value={repeatsOn} onChange={setRepeatsOn} overflow="hold" />
Choose April, then go back to January. Clamp ends on the 30th; hold returns to the 31st.
Day 29 is held. February shows 28.
2026
2028
February’s length comes from year. The 29th shows only in a leap year.

Sizes and states

Two heights, 36 and 44px, to match the other fields. Error and disabled always apply to both selects.

Repeats on
Every year, on this date.
lg · 44
error
disabled
<WFormRow label="Repeats on" help="Every year, on this date.">
  <WMonthDayPicker value={repeatsOn} onChange={setRepeatsOn} width="100%" ariaLabel="Repeats on" />
</WFormRow>

Accessibility

The selects are announced as Month and Day. Pass ariaLabel to name the pair, usually with the form row’s label. A held day is announced as it appears.

KeyWhat it does
TabMoves focus to the month, then the day, closing any open list.
↓ / ↑Opens the list, then moves through it.
Enter / SpaceOpens or closes the list, or chooses the highlighted option.
EscapeCloses the list and keeps focus on the select.

Props

PropTypeDefaultDescription
valueMonthDay—The stored { month, day }. Month runs 1 to 12.
defaultValueMonthDayJanuary 31Starting value when value isn’t set.
onChange(value) => void—Called with the new month and day.
yearnumbercurrent yearSets February’s length.
overflow'clamp' | 'hold''clamp'What a too-short month does to the day.
size'sm' | 'lg''sm'36 or 44px.
widthnumber | string268Total width. The day select stays 88px, 96px at lg.
disabledbooleanfalseDisables both selects.
errorbooleanfalseError border on both selects.
ariaLabelstring—Accessible name for the pair.

Tokens

TokenValueWhere it lands
--radius-lg8pxBoth frames, and the open list.
--global-neutral-grey-600#DCDCDEBorder at rest.
--global-neutral-grey-800#ADACB0Border on hover, disabled chevron.
--global-blue-1000#1877F2Focus edge, halo and keyboard row.
--global-red-800#E12121Error edge.
--global-neutral-grey-300#F1F1F1Hovered and chosen rows, disabled ground.
--global-neutral-grey-500#E6E6E6Open list border, disabled border.
--global-neutral-grey-1100#2D2B32Chosen month and day, hovered or open chevron.
--global-neutral-grey-900#7F7D83Chevron at rest, disabled value.
--global-neutral-grey-1200#1D1C20Option text.
--global-blue-1100#0C296AThe chosen option’s text.
--global-neutral-grey-1000#4F4D55Placeholders and the held-day note.
--shadow-dropdown0 4px 12px rgba(0,0,0,.08), …The open list.
--spacing-28pxGap between month and day.