Skip to content

Commit

Permalink
DateRange: Highlight secondary range in DateRange component (web) (#3910
Browse files Browse the repository at this point in the history
)
  • Loading branch information
CarlosAvina authored Jan 2, 2025
1 parent b241a35 commit 5560a8e
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 26 deletions.
12 changes: 8 additions & 4 deletions docs/pages/visual-test/DateRange-secondary-date.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ import { Box, ColorSchemeProvider } from 'gestalt';
import { DateRange } from 'gestalt-datepicker';

export default function Snapshot() {
const [startDate, setStartDate] = useState<Date | null>(null);
const [endDate, setEndDate] = useState<Date | null>(null);
const [compStartDate, setCompStartDate] = useState<Date | null>(null);
const [compEndDate, setCompEndDate] = useState<Date | null>(null);
const [startDate, setStartDate] = useState<Date | null>(new Date('December 16, 2024 03:24:00'));
const [endDate, setEndDate] = useState<Date | null>(new Date('December 20, 2024 03:24:00'));
const [compStartDate, setCompStartDate] = useState<Date | null>(
new Date('December 9, 2024 03:24:00'),
);
const [compEndDate, setCompEndDate] = useState<Date | null>(
new Date('December 13, 2024 03:24:00'),
);

return (
<ColorSchemeProvider colorScheme="light">
Expand Down
7 changes: 7 additions & 0 deletions packages/gestalt-datepicker/src/DatePicker.css
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,13 @@ html:not([dir="rtl"]) :global ._gestalt .react-datepicker__navigation--next {
z-index: 1;
}

/* styles secondary in range days */

.react-datepicker__day--in-range-secondary {
background-color: var(--color-background-datepicker-range-default);
font-weight: bold;
}

/* Year / Month dropdown */

:global ._gestalt .react-datepicker__month-select,
Expand Down
25 changes: 25 additions & 0 deletions packages/gestalt-datepicker/src/DateRange.jsdom.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -308,4 +308,29 @@ describe('DateRange', () => {
expect(startDateInput).toHaveAttribute('readonly');
expect(endDateInput).toHaveAttribute('readonly');
});

it('highlights secondary date range with correct class', () => {
const initialStartDate = new Date('December 10, 2024 03:24:00');
const initialEndDate = new Date('December 11, 2024 03:24:00');
const initialCompStartDate = new Date('December 16, 2024 03:24:00');
const initialCompEndDate = new Date('December 17, 2024 03:24:00');
render(
<TwoDateRangeWrap
initialCompEndDate={initialCompEndDate}
initialCompStartDate={initialCompStartDate}
initialEndDate={initialEndDate}
initialStartDate={initialStartDate}
localeData={enUS}
/>,
);

const firstDay = screen.getByRole('option', {
name: /choose monday, december 16th, 2024/i,
});
const secondDay = screen.getByRole('option', {
name: /choose tuesday, december 17th, 2024/i,
});
expect(firstDay).toHaveClass('react-datepicker__day--in-range-secondary');
expect(secondDay).toHaveClass('react-datepicker__day--in-range-secondary');
});
});
17 changes: 6 additions & 11 deletions packages/gestalt-datepicker/src/DateRange.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ type Props = {
readOnly?: boolean;
};

enum DateRangeType {
export enum DateRangeType {
Primary,
Secondary,
}
Expand Down Expand Up @@ -351,16 +351,11 @@ function DateRange({
onSecondaryDateChange({ value: startDate }, { value: endDate });
}
}}
rangeEndDate={
selectedRange === DateRangeType.Primary
? dateValue.endDate
: secondaryDateValue?.endDate
}
rangeStartDate={
selectedRange === DateRangeType.Primary
? dateValue.startDate
: secondaryDateValue?.startDate
}
rangeEndDate={dateValue.endDate}
rangeStartDate={dateValue.startDate}
secondaryRangeEndDate={secondaryDateValue?.endDate}
secondaryRangeStartDate={secondaryDateValue?.startDate}
selectedRange={selectedRange}
/>
</Box>
{onSubmit && onCancel ? (
Expand Down
72 changes: 63 additions & 9 deletions packages/gestalt-datepicker/src/DateRange/InternalDatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ import ReactDatePicker, { registerLocale } from 'react-datepicker';
import { Icon, useDeviceType } from 'gestalt';
import { Props } from '../DatePicker';
import styles from '../DatePicker.css';
import { DateRangeType } from '../DateRange';

type ModifiedProps = Props & {
onChange: (arg1: { startDate: Date; endDate: Date }) => void;
selectedRange: DateRangeType;
secondaryRangeStartDate?: Date | null;
secondaryRangeEndDate?: Date | null;
};

const InternalDatePickerWithForwardRef = forwardRef<HTMLInputElement, ModifiedProps>(
Expand All @@ -20,6 +24,9 @@ const InternalDatePickerWithForwardRef = forwardRef<HTMLInputElement, ModifiedPr
onChange,
rangeEndDate,
rangeStartDate,
secondaryRangeStartDate,
secondaryRangeEndDate,
selectedRange,
}: ModifiedProps,
ref,
): ReactElement {
Expand All @@ -35,11 +42,6 @@ const InternalDatePickerWithForwardRef = forwardRef<HTMLInputElement, ModifiedPr
const [, setMonth] = useState<number | null | undefined>();
const [format, setFormat] = useState<string | null | undefined>();
const [updatedLocale, setUpdatedLocale] = useState<string | null | undefined>();
const [initRangeHighlight, setInitRangeHighlight] = useState<Date | null | undefined>();

useEffect(() => {
setInitRangeHighlight(rangeStartDate || rangeEndDate);
}, [rangeStartDate, rangeEndDate]);

useEffect(() => {
if (localeData && localeData.code) {
Expand All @@ -55,6 +57,42 @@ const InternalDatePickerWithForwardRef = forwardRef<HTMLInputElement, ModifiedPr
}
}, [localeData]);

function getDatesArray(startDate: Date, endDate: Date) {
// Ensure the input dates are valid Date objects
const start = new Date(startDate);
const end = new Date(endDate);

// Check if the start date is after the end date
if (start > end) {
return [];
}

const dates = [];
const currentDate = start;

// Loop through all dates from start to end
while (currentDate <= end) {
// Push the current date to the array
dates.push(new Date(currentDate));
// Increment the current date by one day
currentDate.setDate(currentDate.getDate() + 1);
}

return dates;
}

function generateHighlights(
startDate: Date | null | undefined,
endDate: Date | null | undefined,
) {
const datesArray = startDate && endDate ? getDatesArray(startDate, endDate) : [];
return [
{
[styles['react-datepicker__day--in-range-secondary']]: datesArray,
},
];
}

return (
<div className="_gestalt">
<div className={isMobile ? undefined : '_gestalt_daterange'}>
Expand All @@ -73,9 +111,17 @@ const InternalDatePickerWithForwardRef = forwardRef<HTMLInputElement, ModifiedPr
calendarClassName={styles['react-datepicker-inline']}
dateFormat={format}
dayClassName={() => styles['react-datepicker__days']}
endDate={rangeEndDate ?? undefined}
endDate={
selectedRange === DateRangeType.Primary
? rangeEndDate ?? undefined
: secondaryRangeEndDate ?? undefined
}
excludeDates={excludeDates && [...excludeDates]}
highlightDates={initRangeHighlight ? [initRangeHighlight] : []}
highlightDates={
selectedRange === DateRangeType.Primary
? generateHighlights(secondaryRangeStartDate, secondaryRangeEndDate)
: generateHighlights(rangeStartDate, rangeEndDate)
}
id={id}
includeDates={includeDates && [...includeDates]}
inline
Expand All @@ -95,9 +141,17 @@ const InternalDatePickerWithForwardRef = forwardRef<HTMLInputElement, ModifiedPr
previousMonthButtonLabel={
<Icon accessibilityLabel="" color="default" icon="arrow-back" size={16} />
}
selected={rangeStartDate ?? undefined}
selected={
selectedRange === DateRangeType.Primary
? rangeStartDate ?? undefined
: secondaryRangeStartDate ?? undefined
}
selectsRange
startDate={rangeStartDate ?? undefined}
startDate={
selectedRange === DateRangeType.Primary
? rangeStartDate ?? undefined
: secondaryRangeStartDate ?? undefined
}
/>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions playwright/visual-test/DateRange-secondary-date.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, test } from '@playwright/test';

test('DateRange secondary date range visual regression check', async ({ page }) => {
test('DateRange secondaryHighlight range appears when selected', async ({ page }) => {
await page.goto('/visual-test/DateRange-secondary-date');
const locator = page.locator('[data-test-id="visual-test"]');
await expect(locator).toHaveScreenshot('DateRange-dark.png');
await expect(locator).toHaveScreenshot('DateRange-secondary-range.png');
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 5560a8e

Please sign in to comment.