react-day-picker
Version:
Customizable Date Picker for React
163 lines (128 loc) • 4.66 kB
text/mdx
---
sidebar_position: 2
---
# Custom Selections
:::info Draft
This documentation is still a work in progress. If you have any questions, ask to the [discussions](https://github.com/gpbl/react-day-picker/discussions) page on Github.
:::
If the built-in [selection modes](../docs/selection-modes.mdx) does not satisfy for your app’s requirements, you can control the selection behavior using the [`onDayClick`](../api/interfaces/PropsBase.md#ondayclick) and [`modifiers`](../api/interfaces/PropsBase.md#modifiers) props:
| Prop | Type | Description |
| ------------ | ----------------------------------------------------------- | ----------------------------------------- |
| `onDayClick` | [`DayEventHandler`](../api/type-aliases/DayEventHandler.md) | Callback when a day is clicked. |
| `modifiers` | [`Modifiers`](../api/type-aliases/Modifiers.md) | An object with the modifiers of the days. |
This prop is a function that receives the clicked day and the modifiers of the day as arguments.
## Examples
### Week Selection
The following example shows how to select the whole week when a day is clicked.
Note the use of the `startOfWeek` and `endOfWeek` functions from [date-fns](https://date-fns.org) and how the `selectedWeek` state is passed to the `modifiers` prop.
```tsx
import React, { useState } from "react";
import { endOfWeek, startOfWeek } from "date-fns";
import { DateRange, DayPicker, isDateInRange } from "react-day-picker";
/** Select the whole week when the day is clicked. */
export function CustomWeek() {
const [selectedWeek, setSelectedWeek] = useState<DateRange | undefined>();
return (
<DayPicker
showWeekNumber
showOutsideDays
modifiers={{
selected: selectedWeek,
range_start: selectedWeek?.from,
range_end: selectedWeek?.to,
range_middle: (date: Date) =>
selectedWeek
? isDateInRange(date, selectedWeek, { excludeEnds: true })
: false
}}
onDayClick={(day, modifiers) => {
if (modifiers.selected) {
setSelectedWeek(undefined); // clear the selection if the day is already selected
return;
}
setSelectedWeek({
from: startOfWeek(day),
to: endOfWeek(day)
});
}}
footer={
selectedWeek &&
`Week from ${selectedWeek?.from?.toLocaleDateString()} to
${selectedWeek?.to?.toLocaleDateString()}`
}
/>
);
}
```
<BrowserWindow>
<Examples.CustomWeek />
</BrowserWindow>
### Single Selection
For example, to implement the "single selection" behavior (like when `mode="single"`):
```tsx
import { useState } from "react";
import { DayPicker, DayPickerProps } from "react-day-picker";
export function CustomSingle() {
const [selectedDate, setSelectedDate] = useState<Date | undefined>();
const modifiers: DayPickerProps["modifiers"] = {};
if (selectedDate) {
modifiers.selected = selectedDate;
}
return (
<DayPicker
modifiers={modifiers}
onDayClick={(day, modifiers) => {
if (modifiers.selected) {
setSelectedDate(undefined);
} else {
setSelectedDate(day);
}
}}
footer={selectedDate && `You selected ${selectedDate.toDateString()}`}
/>
);
}
```
<BrowserWindow>
<Examples.CustomSingle />
</BrowserWindow>
### Multi Selections
The case of a multi-days select is a bit more complex as it deals with an array. The following example replicates the `mode="multiple"`
selection mode.
```tsx
import { useState } from "react";
import { isSameDay } from "date-fns";
import { DayMouseEventHandler, DayPicker } from "react-day-picker";
export function CustomMultiple() {
const [value, setValue] = useState<Date[]>([]);
const handleDayClick: DayMouseEventHandler = (day, modifiers) => {
const newValue = [...value];
if (modifiers.selected) {
const index = value.findIndex((d) => isSameDay(day, d));
newValue.splice(index, 1);
} else {
newValue.push(day);
}
setValue(newValue);
};
const handleResetClick = () => setValue([]);
let footer = <>Please pick one or more days.</>;
if (value.length > 0)
footer = (
<>
You selected {value.length} days.{" "}
<button onClick={handleResetClick}>Reset</button>
</>
);
return (
<DayPicker
onDayClick={handleDayClick}
modifiers={{ selected: value }}
footer={footer}
/>
);
}
```
<BrowserWindow>
<Examples.CustomMultiple />
</BrowserWindow>