Conversation
- Updated package.json to remove react-dates and add react-day-picker. - Created DateTimePicker component using react-day-picker, supporting both single and range date selection. - Removed SingleDatePickerComponent as it is no longer needed. - Added new styles for the DateTimePicker component. - Updated constants and types to accommodate changes in date handling. - Removed old date picker styles and configurations related to react-dates. - Adjusted Vite configuration to exclude react-dates from manual chunks.
There was a problem hiding this comment.
Pull request overview
This PR migrates the date picker component from the deprecated react-dates library to the modern react-day-picker library. The refactor adds support for both single date and date range selection, improves accessibility, and reduces dependency bloat.
Key Changes:
- Replaced
react-dateswithreact-day-pickerv9.11.2 and removed deprecated dependencies - Introduced discriminated union types to support both single date and range picker modes
- Added custom navigation components using the existing Button and Icon components for consistent styling
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| package.json | Replaced react-dates dependency with react-day-picker and removed related type definitions |
| package-lock.json | Updated lockfile with new dependencies including date-fns, date-fns-jalali, and @date-fns/tz |
| vite.config.ts | Removed react-dates manual chunk configuration |
| src/Shared/Components/DatePicker/types.ts | Refactored types to use discriminated unions for single/range picker modes and defined new handler types |
| src/Shared/Components/DatePicker/utils.tsx | Added generic type parameter to DEFAULT_TIME_OPTIONS and removed outdated eslint comment |
| src/Shared/Components/DatePicker/constants.tsx | Replaced legacy date styles with custom navigation button components using react-day-picker's CustomComponents API |
| src/Shared/Components/DatePicker/DateTimePicker.tsx | Complete rewrite using react-day-picker with Popover component, supporting both single and range selection modes |
| src/Shared/Components/DatePicker/DateTimePicker.scss | New styles customizing react-day-picker appearance with CSS custom properties |
| src/Shared/Components/DatePicker/datePicker.scss | Removed legacy styles for react-dates |
| src/Shared/Components/DatePicker/SingleDatePickerComponent.tsx | Removed deprecated component |
| src/Shared/Components/DatePicker/index.ts | Removed export of deprecated SingleDatePickerComponent |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.
|
|
||
| const renderInputLabel = () => { | ||
| if (isRangePicker) { | ||
| const fromDate = dateRange.from ? dayjs(dateRange.from).format(DATE_TIME_FORMATS.DD_MMM_YYYY) : '' |
There was a problem hiding this comment.
[nitpick] When dateRange.from is falsy in range picker mode, the fromDate will be an empty string, resulting in a label like - .... This could be visually awkward. Consider displaying a more user-friendly placeholder text like "Select start date - ..." when from is not set.
| const fromDate = dateRange.from ? dayjs(dateRange.from).format(DATE_TIME_FORMATS.DD_MMM_YYYY) : '' | |
| const fromDate = dateRange.from ? dayjs(dateRange.from).format(DATE_TIME_FORMATS.DD_MMM_YYYY) : 'Select start date' |
|
|
||
| const triggerElement = ( | ||
| <SelectPicker | ||
| inputId="date-picker-input" |
There was a problem hiding this comment.
The label element uses htmlFor={id} but the actual input element inside SelectPicker uses inputId="date-picker-input" (a hardcoded value). This means the label won't properly associate with the input when clicked. Either use the id prop for the inputId or ensure they match for proper accessibility.
| const handleSingleDateSelect: OnSelectHandler<Date> = (date) => { | ||
| if (!isDateUpdateRange(isRangePicker, onChange)) { | ||
| const updatedDate = date ? updateDate(dateObject, date) : null | ||
| onChange(updatedDate) | ||
| } | ||
| } |
There was a problem hiding this comment.
The handleSingleDateSelect function might pass null to onChange when no date is selected, but the UpdateSingleDateType type signature expects a non-nullable Date parameter. This could cause a type error. Consider updating the type to UpdateSingleDateType = (date: Date | null) => void or ensure that null dates are properly handled.
| const today = getTodayDate() | ||
| today.setHours(0, 0, 0, 0) |
There was a problem hiding this comment.
The getTodayDate() function is called and then mutated with setHours(0, 0, 0, 0). This mutates a fresh Date object on every call to getDisabledState(). Consider creating the normalized today date once using useMemo to avoid unnecessary object mutations on every render when getDisabledState is called.
| dateRange = { | ||
| from: getTodayDate(), | ||
| to: getTodayDate(), | ||
| }, |
There was a problem hiding this comment.
[nitpick] The default value for dateRange is set to { from: getTodayDate(), to: getTodayDate() }, which means both start and end dates default to today. This could be confusing for range pickers where typically the end date might be undefined initially. Consider using { from: getTodayDate(), to: undefined } or making the default value conditional based on whether it's a range picker.
| } | ||
|
|
||
| export type UpdateDateRangeType = (dateRange: DateRangeType) => void | ||
| export type UpdateSingleDateType = (date: Date) => void |
There was a problem hiding this comment.
The UpdateSingleDateType type is defined as (date: Date) => void, but in the handleSingleDateSelect function on line 130, onChange may be called with null when updatedDate is null. Update the type to (date: Date | null) => void to accurately reflect the function signature.
| export type UpdateSingleDateType = (date: Date) => void | |
| export type UpdateSingleDateType = (date: Date | null) => void |
| value: '', | ||
| startIcon: <Icon name="ic-calendar" color={null} />, | ||
| }} | ||
| size={ComponentSizeType.large} |
There was a problem hiding this comment.
The disabled prop is not passed to the date picker trigger element (SelectPicker). When the DateTimePicker is disabled, only the time picker reflects this state (line 257), but the date picker input appears enabled. Consider passing isDisabled={disabled} to the trigger SelectPicker to ensure consistent disabled state across both inputs.
| size={ComponentSizeType.large} | |
| size={ComponentSizeType.large} | |
| isDisabled={disabled} |
| const handleDateRangeChange = (range: DateRange) => { | ||
| if (isDateUpdateRange(isRangePicker, onChange)) { | ||
| const fromDate = range.from ? range.from : new Date() | ||
| const toDate = range.to ? range.to : undefined | ||
|
|
||
| const handleFocusChange = ({ focused }) => { | ||
| setFocused(focused) | ||
| onChange({ | ||
| from: fromDate, | ||
| to: toDate, | ||
| }) |
There was a problem hiding this comment.
When range.from is falsy in range selection mode, the code defaults to new Date(). This means that if a user clears the start date, it will automatically default to today instead of allowing an empty/undefined state. Consider whether this is the intended behavior or if it should allow undefined for from.
| */ | ||
| datePickerProps?: any | ||
| interface DateRangeType { | ||
| from: Date |
There was a problem hiding this comment.
[nitpick] The DateRangeType interface requires from to always be defined (from: Date), but in the handleDateRangeChange function, when range.from is undefined, it defaults to new Date(). Consider whether from should be optional (from?: Date) to better represent the actual state during range selection, or document that from must always be present.
| from: Date | |
| from?: Date |
| type="button" | ||
| key={optionLabel} | ||
| className="bg__hover cn-9 dc__tab-focus dc__align-left dc__transparent p-8 br-4" | ||
| onClick={onClick || getRangeUpdateHandler(value)} |
There was a problem hiding this comment.
The shortcut buttons in the range picker lack accessible labels. Each button should have an aria-label attribute to describe its purpose for screen reader users, especially since the buttons only contain text that might not be self-descriptive in all contexts.
| onClick={onClick || getRangeUpdateHandler(value)} | |
| onClick={onClick || getRangeUpdateHandler(value)} | |
| aria-label={`Select range: ${optionLabel}`} |
…common-lib into feat/day-picker
…n and package-lock.json
…t for layout consistency
…ck.json; add instanceData to DevtronLicenseDTO type
- Imported ImgInstallFreemiumSaas and ImgInstallViaAwsMarketplace SVGs. - Updated illustrationMap to include new illustrations for 'img-install-freemium-saas' and 'img-install-via-aws-marketplace'.
….json; add img-page-not-found.svg illustration and update DevtronLicenseCard to handle SaaS instance
….json; add isSaasInstance to DevtronLicenseCardProps and update utils to derive its value from instanceData
….json; add LICENSE_KEY_QUERY_PARAM constant
…k.json; add activateLicense export in License component
…k.json; update instanceData handling in License component
…lustration - Updated package.json and package-lock.json to version 1.21.1-beta-1 - Added new SVG illustration for celebration to the assets - Updated Illustration.tsx to include the new celebration illustration in the illustration map
…-img chore: update version to 1.22.3 and add new illustration for installing Devtron
…common-lib into feat/day-picker
fix: date picker focus
… add escape key handling for focus trap
feat: navigation upgraded
…nd improved state management
…mon-lib into refactor/app-details
refactor: remove unused PodMetadatum interface and update aggregateNo…
fix: add constants required for project navigation movement to global config
feat: grafana org id flag
feat: markdown editor
…mon-lib into feat/day-picker
Description
This pull request completely refactors the date picker component to replace the
react-dateslibrary withreact-day-picker. The new implementation introduces support for both single date and range selection, improves accessibility and customizability, and updates the styling to match the new library. Several legacy files and dependencies are removed, and the API for the date picker is updated for clarity and flexibility.Migration from
react-datestoreact-day-picker:react-dateswithreact-day-pickerinDateTimePicker.tsx, updating all related logic to support both single date and range selection, and removed the old focus trap and moment.js usage. ([[1]](https://github.com/devtron-labs/devtron-fe-common-lib/pull/970/files#diff-dc6bf3a6084005ddabd8b1bf06bec25bfabf5a30ef376cb4835c2c226a755bd6L17-R48),[[2]](https://github.com/devtron-labs/devtron-fe-common-lib/pull/970/files#diff-dc6bf3a6084005ddabd8b1bf06bec25bfabf5a30ef376cb4835c2c226a755bd6L52-R189),[[3]](https://github.com/devtron-labs/devtron-fe-common-lib/pull/970/files#diff-dc6bf3a6084005ddabd8b1bf06bec25bfabf5a30ef376cb4835c2c226a755bd6L93-R211), [4] [5]SingleDatePickerComponent.tsxand old styles indatePicker.scss. ([[1]](https://github.com/devtron-labs/devtron-fe-common-lib/pull/970/files#diff-eca9ccbc1a9c798ae4001b6ef206bc9297843582257199060d25e02c10fd30ebL1-L80),[[2]](https://github.com/devtron-labs/devtron-fe-common-lib/pull/970/files#diff-db59d30cff39b6924b419a9f6fd6b4e01a673a3861bb99984a209e50903a2541L1-L103),[[3]](https://github.com/devtron-labs/devtron-fe-common-lib/pull/970/files#diff-b22dd3646a7f1a8bd9b1a23ab285cf4c91ebd70e348e125a1613bdf80a46459dL20))Styling and Customization:
DateTimePicker.scssto match the look and feel ofreact-day-pickerand support range selection. ([src/Shared/Components/DatePicker/DateTimePicker.scssR1-R71](https://github.com/devtron-labs/devtron-fe-common-lib/pull/970/files#diff-307fd37871b0ead4448a16ec2cccd71f7a68b3c7848c8c954fe38b9d5bf2986aR1-R71))constants.tsx. ([[1]](https://github.com/devtron-labs/devtron-fe-common-lib/pull/970/files#diff-4ccc31505f53c29409f6361ae5d0f498fe4e1824e719c6f487a31ce76590e477L17-R24),[[2]](https://github.com/devtron-labs/devtron-fe-common-lib/pull/970/files#diff-4ccc31505f53c29409f6361ae5d0f498fe4e1824e719c6f487a31ce76590e477R124-R154))API and Type Updates:
DateTimePickerPropsto support both single date and range selection, removed references toreact-datestypes, and improved clarity of props. ([[1]](https://github.com/devtron-labs/devtron-fe-common-lib/pull/970/files#diff-9031429d6cd8ea472101914a172cd7c014b93160d9632bf4a65ad46b0092a305L17),[[2]](https://github.com/devtron-labs/devtron-fe-common-lib/pull/970/files#diff-9031429d6cd8ea472101914a172cd7c014b93160d9632bf4a65ad46b0092a305L106-R116),[[3]](https://github.com/devtron-labs/devtron-fe-common-lib/pull/970/files#diff-9031429d6cd8ea472101914a172cd7c014b93160d9632bf4a65ad46b0092a305L125-L128))These changes modernize the date picker component, reduce dependency bloat, and make it easier to maintain and extend.
Type of change
How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration
Checklist