Skip to content

Conversation

@AbhishekA1509
Copy link
Member

Description

This pull request completely refactors the date picker component to replace the react-dates library with react-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-dates to react-day-picker:

  • Replaced react-dates with react-day-picker in DateTimePicker.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]
  • Removed legacy files and code, including SingleDatePickerComponent.tsx and old styles in datePicker.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:

  • Added new SCSS styles in DateTimePicker.scss to match the look and feel of react-day-picker and 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))
  • Introduced custom navigation buttons for the calendar using shared UI components in 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:

  • Updated the API and types for DateTimePickerProps to support both single date and range selection, removed references to react-dates types, 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

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

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

  • Test A
  • Test B

Checklist

  • The title of the PR states what changed and the related issues number (used for the release note).
  • Does this PR require documentation updates?
  • I've updated documentation as required by this PR.
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas

- 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.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

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-dates with react-day-picker v9.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) : ''
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

[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.

Suggested change
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'

Copilot uses AI. Check for mistakes.

const triggerElement = (
<SelectPicker
inputId="date-picker-input"
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment on lines +127 to +132
const handleSingleDateSelect: OnSelectHandler<Date> = (date) => {
if (!isDateUpdateRange(isRangePicker, onChange)) {
const updatedDate = date ? updateDate(dateObject, date) : null
onChange(updatedDate)
}
}
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment on lines +139 to +140
const today = getTodayDate()
today.setHours(0, 0, 0, 0)
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment on lines +50 to +53
dateRange = {
from: getTodayDate(),
to: getTodayDate(),
},
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

[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.

Copilot uses AI. Check for mistakes.
}

export type UpdateDateRangeType = (dateRange: DateRangeType) => void
export type UpdateSingleDateType = (date: Date) => void
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

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.

Suggested change
export type UpdateSingleDateType = (date: Date) => void
export type UpdateSingleDateType = (date: Date | null) => void

Copilot uses AI. Check for mistakes.
value: '',
startIcon: <Icon name="ic-calendar" color={null} />,
}}
size={ComponentSizeType.large}
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

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.

Suggested change
size={ComponentSizeType.large}
size={ComponentSizeType.large}
isDisabled={disabled}

Copilot uses AI. Check for mistakes.
Comment on lines +107 to +115
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,
})
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
*/
datePickerProps?: any
interface DateRangeType {
from: Date
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

[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.

Suggested change
from: Date
from?: Date

Copilot uses AI. Check for mistakes.
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)}
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

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.

Suggested change
onClick={onClick || getRangeUpdateHandler(value)}
onClick={onClick || getRangeUpdateHandler(value)}
aria-label={`Select range: ${optionLabel}`}

Copilot uses AI. Check for mistakes.
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.

2 participants