From 4b97a166090a7b5329246bcd8159ef206a055ce8 Mon Sep 17 00:00:00 2001 From: Vicki Yang Date: Tue, 14 Apr 2026 14:24:57 -0400 Subject: [PATCH 1/9] add allowOnlyDatesList to DatePicker props --- src/components/DatePicker/DatePicker.tsx | 11 ++++++++++- src/components/DatePicker/DatePicker.types.ts | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/components/DatePicker/DatePicker.tsx b/src/components/DatePicker/DatePicker.tsx index b082c6737..7385f8b5d 100644 --- a/src/components/DatePicker/DatePicker.tsx +++ b/src/components/DatePicker/DatePicker.tsx @@ -40,6 +40,7 @@ const PopoverContent = styled(Popover.Content)` `; interface CalendarProps { + allowOnlyDatesList?: Date[]; calendarBody: Body; closeDatepicker: () => void; futureDatesDisabled: boolean; @@ -49,6 +50,7 @@ interface CalendarProps { } const Calendar = ({ + allowOnlyDatesList, calendarBody, closeDatepicker, futureDatesDisabled, @@ -134,7 +136,12 @@ const Calendar = ({ {week.map(({ date, isCurrentMonth, key: dayKey, value: fullDate }) => { const isSelected = selectedDate && isSameDate(selectedDate, fullDate); const isPresent = isSameDate(today, fullDate); - const isDisabled = futureDatesDisabled ? fullDate > today : false; + const isNotAllowed = + allowOnlyDatesList && allowOnlyDatesList.length > 0 + ? !allowOnlyDatesList.some(d => isSameDate(d, fullDate)) + : false; + const isFutureDisabled = futureDatesDisabled && fullDate > today; + const isDisabled = isNotAllowed || isFutureDisabled; const currentIndex = dayIndex; dayIndex++; @@ -172,6 +179,7 @@ const Calendar = ({ }; export const DatePicker = ({ + allowOnlyDatesList, date, disabled = false, futureDatesDisabled = false, @@ -276,6 +284,7 @@ export const DatePicker = ({ > {body => ( Date: Tue, 14 Apr 2026 14:26:25 -0400 Subject: [PATCH 2/9] update storybook --- src/components/DatePicker/DatePicker.stories.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/DatePicker/DatePicker.stories.tsx b/src/components/DatePicker/DatePicker.stories.tsx index 5453f5d39..6ad7a6d79 100644 --- a/src/components/DatePicker/DatePicker.stories.tsx +++ b/src/components/DatePicker/DatePicker.stories.tsx @@ -3,6 +3,7 @@ import { DatePicker } from '@/components/DatePicker'; const defaultStory = { args: { + allowOnlyDatesList: [], onSelectDate: (date: Date) => { console.log('Date selected: ', date); }, @@ -26,6 +27,7 @@ const defaultStory = { const date = args.date ? new Date(args.date) : undefined; return ( Date: Tue, 14 Apr 2026 14:36:09 -0400 Subject: [PATCH 3/9] update unit test --- src/components/DatePicker/DatePicker.test.tsx | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/components/DatePicker/DatePicker.test.tsx b/src/components/DatePicker/DatePicker.test.tsx index b0abded2c..b153790af 100644 --- a/src/components/DatePicker/DatePicker.test.tsx +++ b/src/components/DatePicker/DatePicker.test.tsx @@ -123,6 +123,49 @@ describe('DatePicker', () => { expect(handleSelectDate).not.toHaveBeenCalled(); }); + + it('disables selecting dates not in allowOnlyDatesList', async () => { + const date = new Date('07-04-2020'); + const allowOnlyDatesList = [new Date('07-04-2020'), new Date('07-06-2020')]; + const handleSelectDate = vi.fn(); + const user = userEvent.setup({ advanceTimers: vi.advanceTimersByTime }); + + const { getByTestId, findByText } = renderCUI( + + ); + + user.click(getByTestId('datepicker-input')); + user.click(await findByText('5')); + + expect(handleSelectDate).not.toHaveBeenCalled(); + }); + + it('disables selecting futures dates in allowOnlyDatesList when futureDatesDisabled', async () => { + // System time is July 5, 2020 + const date = new Date('07-04-2020'); + const allowOnlyDatesList = [new Date('07-04-2020'), new Date('07-06-2020')]; + const handleSelectDate = vi.fn(); + const user = userEvent.setup({ advanceTimers: vi.advanceTimersByTime }); + + const { getByTestId, findByText } = renderCUI( + + ); + + user.click(getByTestId('datepicker-input')); + // July 6 is in allowOnlyDatesList but is a future date + user.click(await findByText('6')); + + expect(handleSelectDate).not.toHaveBeenCalled(); + }); }); describe('two phased date selection', () => { From 5e506b04bfcea8fd5de4edb4e871bc06c91c4102 Mon Sep 17 00:00:00 2001 From: Vicki Yang Date: Tue, 14 Apr 2026 14:56:22 -0400 Subject: [PATCH 4/9] add changeset --- .changeset/bil-5134-add-allowlist-param-to-datepicker.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/bil-5134-add-allowlist-param-to-datepicker.md diff --git a/.changeset/bil-5134-add-allowlist-param-to-datepicker.md b/.changeset/bil-5134-add-allowlist-param-to-datepicker.md new file mode 100644 index 000000000..cd6360cad --- /dev/null +++ b/.changeset/bil-5134-add-allowlist-param-to-datepicker.md @@ -0,0 +1,5 @@ +--- +'@clickhouse/click-ui': minor +--- + +Adds optional `allowOnlyDatesList` prop to `DatePicker`, which enables the user to provide a predefined allowlist of dates that can be selected. From 4372a636ff1d06c24112814f374a09ab4cec0841 Mon Sep 17 00:00:00 2001 From: Vicki Yang Date: Wed, 15 Apr 2026 13:32:02 -0400 Subject: [PATCH 5/9] use Array<> over [] --- src/components/DatePicker/DatePicker.tsx | 2 +- src/components/DatePicker/DatePicker.types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/DatePicker/DatePicker.tsx b/src/components/DatePicker/DatePicker.tsx index 7385f8b5d..baecfeeb1 100644 --- a/src/components/DatePicker/DatePicker.tsx +++ b/src/components/DatePicker/DatePicker.tsx @@ -40,7 +40,7 @@ const PopoverContent = styled(Popover.Content)` `; interface CalendarProps { - allowOnlyDatesList?: Date[]; + allowOnlyDatesList?: Array; calendarBody: Body; closeDatepicker: () => void; futureDatesDisabled: boolean; diff --git a/src/components/DatePicker/DatePicker.types.ts b/src/components/DatePicker/DatePicker.types.ts index c2b45a1c1..080b35819 100644 --- a/src/components/DatePicker/DatePicker.types.ts +++ b/src/components/DatePicker/DatePicker.types.ts @@ -1,5 +1,5 @@ export interface DatePickerProps { - allowOnlyDatesList?: Date[]; + allowOnlyDatesList?: Array; date?: Date; disabled?: boolean; futureDatesDisabled?: boolean; From 9e7d203c3587252a4816f0d06f479e22d5ab9e84 Mon Sep 17 00:00:00 2001 From: Vicki Yang Date: Wed, 15 Apr 2026 13:32:39 -0400 Subject: [PATCH 6/9] Apply suggestion from @punkbit Co-authored-by: Helder Oliveira --- .../bil-5134-add-allowlist-param-to-datepicker.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.changeset/bil-5134-add-allowlist-param-to-datepicker.md b/.changeset/bil-5134-add-allowlist-param-to-datepicker.md index cd6360cad..abfbdd5c0 100644 --- a/.changeset/bil-5134-add-allowlist-param-to-datepicker.md +++ b/.changeset/bil-5134-add-allowlist-param-to-datepicker.md @@ -3,3 +3,15 @@ --- Adds optional `allowOnlyDatesList` prop to `DatePicker`, which enables the user to provide a predefined allowlist of dates that can be selected. + +### How to use? + +```tsx + console.log('Selected:', date)} +/> From 0ad03422bafa82a13765888e01cd0dc59c064f28 Mon Sep 17 00:00:00 2001 From: Vicki Yang Date: Wed, 15 Apr 2026 13:50:35 -0400 Subject: [PATCH 7/9] prettier --- src/components/DatePicker/DatePicker.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/DatePicker/DatePicker.tsx b/src/components/DatePicker/DatePicker.tsx index baecfeeb1..94a5f99ac 100644 --- a/src/components/DatePicker/DatePicker.tsx +++ b/src/components/DatePicker/DatePicker.tsx @@ -137,9 +137,9 @@ const Calendar = ({ const isSelected = selectedDate && isSameDate(selectedDate, fullDate); const isPresent = isSameDate(today, fullDate); const isNotAllowed = - allowOnlyDatesList && allowOnlyDatesList.length > 0 - ? !allowOnlyDatesList.some(d => isSameDate(d, fullDate)) - : false; + allowOnlyDatesList && + allowOnlyDatesList.length > 0 && + !allowOnlyDatesList.some(d => isSameDate(d, fullDate)); const isFutureDisabled = futureDatesDisabled && fullDate > today; const isDisabled = isNotAllowed || isFutureDisabled; const currentIndex = dayIndex; From de123520f4224e5c0f27ea586844617b8e2dbc04 Mon Sep 17 00:00:00 2001 From: Vicki Yang Date: Wed, 15 Apr 2026 15:40:16 -0400 Subject: [PATCH 8/9] add story: DatePickerAllowOnlyNext30Days --- src/components/DatePicker/DatePicker.stories.tsx | 11 ++++++++++- src/components/DatePicker/utils.ts | 8 ++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/components/DatePicker/DatePicker.stories.tsx b/src/components/DatePicker/DatePicker.stories.tsx index 6ad7a6d79..b523933fe 100644 --- a/src/components/DatePicker/DatePicker.stories.tsx +++ b/src/components/DatePicker/DatePicker.stories.tsx @@ -1,5 +1,6 @@ import { Args } from '@storybook/react-vite'; import { DatePicker } from '@/components/DatePicker'; +import { getNextNDatesForDatePickerAllowOnlyList } from './utils'; const defaultStory = { args: { @@ -42,6 +43,14 @@ const defaultStory = { export default defaultStory; -export const Playground = { +export const Default = { ...defaultStory, }; + +export const DatePickerAllowOnlyNext30Days = { + ...defaultStory, + args: { + ...defaultStory.args, + allowOnlyDatesList: getNextNDatesForDatePickerAllowOnlyList(30), + }, +}; diff --git a/src/components/DatePicker/utils.ts b/src/components/DatePicker/utils.ts index 7b9bd6e37..cb9713906 100644 --- a/src/components/DatePicker/utils.ts +++ b/src/components/DatePicker/utils.ts @@ -148,6 +148,14 @@ export const getPredefinedTimePeriodsForDateTimePicker = (): DateRangeListItem[] return dateRangeList; }; +export const getNextNDatesForDatePickerAllowOnlyList = (numberOfDays: number): Date[] => { + const now = dayjs(); + + return Array.from({ length: numberOfDays }, (_, i) => + now.add(i, 'day').startOf('day').toDate() + ); +}; + export const datesAreWithinMaxRange = ( startDate: Date, endDate: Date, From 54565c0cb38d8540bd35c80c7d38df7fb5f1a175 Mon Sep 17 00:00:00 2001 From: Vicki Yang Date: Wed, 15 Apr 2026 16:10:30 -0400 Subject: [PATCH 9/9] fix markdown --- .changeset/bil-5134-add-allowlist-param-to-datepicker.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.changeset/bil-5134-add-allowlist-param-to-datepicker.md b/.changeset/bil-5134-add-allowlist-param-to-datepicker.md index abfbdd5c0..055863850 100644 --- a/.changeset/bil-5134-add-allowlist-param-to-datepicker.md +++ b/.changeset/bil-5134-add-allowlist-param-to-datepicker.md @@ -15,3 +15,5 @@ Adds optional `allowOnlyDatesList` prop to `DatePicker`, which enables the user ]} onSelectDate={(date) => console.log('Selected:', date)} /> +``` +Only the dates in `allowOnlyDatesList` will be selectable. All other dates will be disabled.