Skip to content

feat(DatePicker): New DatePicker component#3286

Draft
aresnik11 wants to merge 67 commits intomainfrom
ajr-datepicker-localization
Draft

feat(DatePicker): New DatePicker component#3286
aresnik11 wants to merge 67 commits intomainfrom
ajr-datepicker-localization

Conversation

@aresnik11
Copy link
Copy Markdown
Contributor

@aresnik11 aresnik11 commented Mar 17, 2026

Overview

Adds DatePicker to Gamut: a locale-aware, accessible date (or date range) picker with text inputs, a popover calendar, keyboard support, and optional composition via context.

Modes

  • Single dateselectedDate / setSelectedDate.
  • Date rangestartDate, endDate, setStartDate, setEndDate; optional startLabel / endLabel.

Default UI vs composition

  • Default — text input(s) + calendar in a popover under the input.
  • Custom — pass children for layout only; compose DatePickerInput and DatePickerCalendar (calendar requires DatePicker context).

Text input

  • Locale-aware formatting and default placeholder from the locale date pattern.
  • Live typing with blur normalization when input is invalid or partial.
  • Empty input clears the relevant selection (single or range bound).

Calendar & layout

  • Responsivetwo adjacent months from the xs breakpoint up; one month on smaller viewports.
  • Month navigation with nav adjusted for two-month view.
  • Week starts from Intl.Locale#getWeekInfo() (polyfill when needed), optional weekStartsOn on DatePickerCalendar.

Selection behavior

Disabled dates

  • disabledDates — unselectable days; integrated into range validation.

Footer

  • Today — select today and align visible month(s).
  • Clearrange mode; clears range; disabled when empty.

Keyboard & focus

  • ArrowDown from input opens calendar and moves focus into the grid (or focuses grid if already open).
  • Open via click keeps focus on the input (pointer-friendly / WCAG-oriented).
  • Grid — arrows (day/week), Home / End (row), PageUp / PageDown (month; Shift for year), Enter / Space to select, Escape closes and returns focus to input.
  • Two-month — horizontal arrows can move between visible months appropriately.

Accessibility

  • Calendar role="dialog" with configurable aria-label.
  • Input role="combobox" with aria-expanded, aria-controls, aria-haspopup, aria-autocomplete="none".
  • Grid tied to month heading and per-day accessible names.

Internationalization

  • locale usesIntl.LocalesArgument, defaults to runtime locale but ability to override via locale prop
  • translations for clear button, field labels, and dialog label. default values in English but ability to override via translations prop
  • weekStartsOn uses Intl.Locale#getWeekInfo() (polyfill when needed) but ability to override via weekStartsOn prop
  • Calendar month/year, weekday table headers, placeholder date format (MM/DD/YYYY), date cell aria labels, are automatically localized to the locale via Intl.DateTimeFormat
  • Last month/next month tip text and today button text are automatically localized to the locale via Intl.RelativeTimeFormat

Other

  • inputSize passes through to Input size in the default layout.

Things I know are missing/not completely working:

  • segmented input
  • calendar is supposed to close after selecting a date(s)
  • tests
  • calendar quick actions

PR Checklist

  • Related to designs:
  • Related to JIRA ticket: GMT-1520
  • I have run this code to verify it works
  • This PR includes unit tests for the code change
  • This PR includes testing instructions tests for the code change
  • The alpha package of this PR is passing end-to-end tests in all relevant Codecademy repositories

Testing Instructions

Don't make me tap the sign.

  1. Go to story X
  2. Do something
  3. Do that something in dark mode
  4. Check it with VO
  5. Finish and do a celebratory dance

PR Links and Envs

Repository PR Link
Monolith Monolith PR
Mono Mono PR

@aresnik11
Copy link
Copy Markdown
Contributor Author

@sh0ji re focus ring transition: this is our default gamut focus ring. do you want me to override it for this case or can i cut a separate ticket to update the focus ring opacity transition across the board?

Copy link
Copy Markdown
Contributor

@dreamwasp dreamwasp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have a couple comments but looking good overall!

@@ -0,0 +1,115 @@
/**
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you get the robot to add tests for these longer util functions

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah im going to tackle tests separately and everything will have tests

range && isDateInRange(date, selectedDate, endDate);
const disabled = isDateDisabled(date, disabledDates);
const today = isToday(date);
// this is making the selected date a differnet color bc it is focused, look into further
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idk if you want to get nitty gritty w/ it, but comment here

@codecademydev
Copy link
Copy Markdown
Collaborator

📬 Published Alpha Packages:

Package Version npm Diff
@codecademy/gamut 68.2.3-alpha.02a91b.0 npm diff
@codecademy/gamut-icons 9.57.3-alpha.02a91b.0 npm diff
@codecademy/gamut-illustrations 0.58.10-alpha.02a91b.0 npm diff
@codecademy/gamut-kit 0.6.593-alpha.02a91b.0 npm diff
@codecademy/gamut-patterns 0.10.29-alpha.02a91b.0 npm diff
@codecademy/gamut-styles 17.13.2-alpha.02a91b.0 npm diff
@codecademy/gamut-tests 5.3.4-alpha.02a91b.0 npm diff
@codecademy/variance 0.26.2-alpha.02a91b.0 npm diff
eslint-plugin-gamut 2.4.4-alpha.02a91b.0 npm diff

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 6, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants