Skip to content

Commit

Permalink
docs(website): add example for week custom selections
Browse files Browse the repository at this point in the history
  • Loading branch information
gpbl committed May 15, 2024
1 parent b3316b8 commit b494015
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 2 deletions.
65 changes: 63 additions & 2 deletions website/docs/advanced-guides/custom-selections.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,68 @@ This documentation is still a work in progress. If you have any questions, ask t

If the built-in selection modes are not enough for your app’s requirements, you can control the selection behavior using `onDayClick`.

### Example: Single Selection
## 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` and how the `selectedWeek` state is passed to the `modifiers` prop.

```tsx
import { useState } from "react";

import { endOfWeek, isSameWeek, startOfWeek } from "date-fns";
import { DateRange, DayPicker } 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
modifiers={{
selected: selectedWeek
}}
onDayClick={(day, modifiers) => {
if (modifiers.selected) {
setSelectedWeek(undefined); // clear the selection if the week is already selected
return;
}
setSelectedWeek({
from: startOfWeek(day),
to: endOfWeek(day)
});
}}
onWeekNumberClick={(weekNumber, dates) => {
if (selectedWeek?.from && isSameWeek(dates[0], selectedWeek.from)) {
setSelectedWeek(undefined); // clear the selection if the week is already selected
return;
}
setSelectedWeek({
from: startOfWeek(dates[0]),
to: endOfWeek(dates[dates.length - 1])
});
}}
footer={
selectedWeek && (
<p>
Week from {selectedWeek.from.toLocaleDateString()} to
{selectedWeek.to.toLocaleDateString()}
</p>
)
}
/>
);
}
```

<BrowserWindow>
<Examples.CustomWeek />
</BrowserWindow>

### Single Selection

For example, to implement the "single selection" behavior (like when `mode="single"`):

Expand Down Expand Up @@ -48,7 +109,7 @@ export function CustomSingle() {
<Examples.CustomSingle />
</BrowserWindow>

### Example: Multi Selections
### 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.
Expand Down
49 changes: 49 additions & 0 deletions website/examples/CustomWeek.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { mockDate, gridcell, renderApp, user, act } from "@/test";

import { CustomWeek } from "./CustomWeek";

const today = new Date(2021, 10, 25);
mockDate(today);

beforeEach(() => {
renderApp(<CustomWeek />);
});

describe("when a day is clicked", () => {
beforeEach(async () => {
await act(() => user.click(gridcell(today)));
});
test("the whole week should appear selected", () => {
const week = [
gridcell(new Date(2021, 10, 21)),
gridcell(new Date(2021, 10, 22)),
gridcell(new Date(2021, 10, 23)),
gridcell(new Date(2021, 10, 24)),
gridcell(new Date(2021, 10, 25)),
gridcell(new Date(2021, 10, 26)),
gridcell(new Date(2021, 10, 27))
];
week.forEach((day) => {
expect(day).toHaveAttribute("aria-selected", "true");
});
});
describe("when clicking the day again", () => {
beforeEach(async () => {
await act(() => user.click(gridcell(today)));
});
test("the whole week should not be selected", () => {
const week = [
gridcell(new Date(2021, 10, 21)),
gridcell(new Date(2021, 10, 22)),
gridcell(new Date(2021, 10, 23)),
gridcell(new Date(2021, 10, 24)),
gridcell(new Date(2021, 10, 25)),
gridcell(new Date(2021, 10, 26)),
gridcell(new Date(2021, 10, 27))
];
week.forEach((day) => {
expect(day).not.toHaveAttribute("aria-selected", "true");
});
});
});
});
46 changes: 46 additions & 0 deletions website/examples/CustomWeek.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useState } from "react";

import { endOfWeek, isSameWeek, startOfWeek } from "date-fns";
import { DateRange, DayPicker } 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
modifiers={{
selected: selectedWeek
}}
onDayClick={(day, modifiers) => {
if (modifiers.selected) {
setSelectedWeek(undefined); // clear the selection if the week is already selected
return;
}
setSelectedWeek({
from: startOfWeek(day),
to: endOfWeek(day)
});
}}
onWeekNumberClick={(weekNumber, dates) => {
if (selectedWeek?.from && isSameWeek(dates[0], selectedWeek.from)) {
setSelectedWeek(undefined); // clear the selection if the week is already selected
return;
}
setSelectedWeek({
from: startOfWeek(dates[0]),
to: endOfWeek(dates[dates.length - 1])
});
}}
footer={
selectedWeek && (
<p>
Week from {selectedWeek.from.toLocaleDateString()} to
{selectedWeek.to.toLocaleDateString()}
</p>
)
}
/>
);
}
1 change: 1 addition & 0 deletions website/examples/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * from "./CustomCaption";
export * from "./CustomDayContent";
export * from "./CustomDisableRow";
export * from "./CustomMultiple";
export * from "./CustomWeek";
export * from "./CustomSingle";
export * from "./Input";
export * from "./Dialog";
Expand Down

0 comments on commit b494015

Please sign in to comment.