Date pickers: a month, week, day and range picker for the calendar's views, then for every date in the app #933

Closed
opened 2026-10-16 13:15:07 +00:00 by tiagoagueda · 0 comments
Owner

The calendar's period title opens the same "Go to the day" box in every view. Each view should instead open a picker that suits it: a month picker for the month view, a day grid that selects a whole week for the week view, a day grid for the day view, and a range picker for the agenda. The same pickers, built once, then replace the browser's date inputs across the app.

What exists today

  • One picker for every view. On the calendar (templates/applications/calendar.html), the period title is a button (popovertarget="calendar-picker"). It opens a popover holding one native <input type="date" name="on"> ("Go to the day") and a Go button. The month, week, day and agenda views all get the same box.
  • Native date inputs elsewhere. The rest of the app uses the browser's own date input, whose look and behaviour differ between browsers and operating systems:
    • applications/forms.py, documents/forms.py, jobs/forms.py, resume/forms.py, jobs/capture_views.py;
    • templates/accounts/profile.html (date of birth, see #928);
    • templates/applications/report.html;
    • the table filters (templates/cotton/table/filter.html).

What would change

On the calendar, a picker per view

  • Month view. Clicking the month's name opens a month picker: the twelve months of the year shown, with arrows to change the year. Choosing a month goes to it.
  • Week view. Clicking the week opens a date picker showing a month. Hovering a day highlights its whole week, and clicking any day selects that week. The current week is highlighted when the picker opens.
  • Day view. Clicking the day opens a date picker showing a month. Clicking a day goes to it.
  • Agenda view. Clicking the range opens a range picker showing a month. A first click sets the start and a second sets the end, with the days between highlighted. The current range is shown when the picker opens.
  • Model. The pickers should take their behaviour from the Bootstrap datepicker (bootstrap-datepicker): its month and year modes (minViewMode), its week selection and its range mode. They should look like the rest of the interface (Basecoat structure, Postulo paint, see #262), not like Bootstrap.

Across the app

  • One set of pickers. The pickers become a single component (a date picker, month picker, week picker and range picker, built on one grid). It is used wherever the app asks for a date today, starting with the date of birth (#928), the report period and the table filters.
  • No-script fallback. The field underneath stays a real date input. Without the script, or with the picker closed, the native input still works and posts the same value.

Requirements for every picker

  • Keyboard and screen readers. Follow the WAI-ARIA date picker dialog pattern:
    • a grid of days with arrow-key navigation, Page Up and Page Down for months, and Home and End for the week;
    • Escape closes the picker and puts focus back on the button that opened it;
    • every day has a full accessible name ("Thursday, 16 October 2026");
    • today and the selected days are announced.
  • Locale. The first day of the week comes from the person's locale (as the calendar already does). Month and day names are in the interface language. Weeks are numbered where the locale numbers them. Right-to-left layouts are mirrored.
  • Phones. On a narrow screen the picker opens as a sheet or drawer, with touch targets of at least 44 px.
  • Text goes through Weblate. Any new text (button names, the accessible labels) goes through the catalogues.

#928 (date-of-birth picker redesign) is the first field outside the calendar to use these pickers.

The calendar's period title opens the same "Go to the day" box in every view. Each view should instead open a picker that suits it: a month picker for the month view, a day grid that selects a whole week for the week view, a day grid for the day view, and a range picker for the agenda. The same pickers, built once, then replace the browser's date inputs across the app. ## What exists today - **One picker for every view.** On the calendar (`templates/applications/calendar.html`), the period title is a button (`popovertarget="calendar-picker"`). It opens a popover holding one native `<input type="date" name="on">` ("Go to the day") and a *Go* button. The month, week, day and agenda views all get the same box. - **Native date inputs elsewhere.** The rest of the app uses the browser's own date input, whose look and behaviour differ between browsers and operating systems: - `applications/forms.py`, `documents/forms.py`, `jobs/forms.py`, `resume/forms.py`, `jobs/capture_views.py`; - `templates/accounts/profile.html` (date of birth, see #928); - `templates/applications/report.html`; - the table filters (`templates/cotton/table/filter.html`). ## What would change ### On the calendar, a picker per view - **Month view.** Clicking the month's name opens a **month picker**: the twelve months of the year shown, with arrows to change the year. Choosing a month goes to it. - **Week view.** Clicking the week opens a **date picker** showing a month. Hovering a day highlights its whole week, and clicking any day selects that week. The current week is highlighted when the picker opens. - **Day view.** Clicking the day opens a **date picker** showing a month. Clicking a day goes to it. - **Agenda view.** Clicking the range opens a **range picker** showing a month. A first click sets the start and a second sets the end, with the days between highlighted. The current range is shown when the picker opens. - **Model.** The pickers should take their behaviour from the Bootstrap datepicker ([bootstrap-datepicker](https://github.com/uxsolutions/bootstrap-datepicker)): its month and year modes (`minViewMode`), its week selection and its range mode. They should look like the rest of the interface (Basecoat structure, Postulo paint, see #262), not like Bootstrap. ### Across the app - **One set of pickers.** The pickers become a single component (a date picker, month picker, week picker and range picker, built on one grid). It is used wherever the app asks for a date today, starting with the date of birth (#928), the report period and the table filters. - **No-script fallback.** The field underneath stays a real date input. Without the script, or with the picker closed, the native input still works and posts the same value. ### Requirements for every picker - **Keyboard and screen readers.** Follow the WAI-ARIA date picker dialog pattern: - a grid of days with arrow-key navigation, Page Up and Page Down for months, and Home and End for the week; - Escape closes the picker and puts focus back on the button that opened it; - every day has a full accessible name ("Thursday, 16 October 2026"); - today and the selected days are announced. - **Locale.** The first day of the week comes from the person's locale (as the calendar already does). Month and day names are in the interface language. Weeks are numbered where the locale numbers them. Right-to-left layouts are mirrored. - **Phones.** On a narrow screen the picker opens as a sheet or drawer, with touch targets of at least 44 px. - **Text goes through Weblate.** Any new text (button names, the accessible labels) goes through the catalogues. ## Related #928 (date-of-birth picker redesign) is the first field outside the calendar to use these pickers.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo#933
No description provided.