Custom Components
Use the components
prop to extend each rendered HTML element with your own custom components.
Prop Name | Type | Description |
---|---|---|
components | CustomComponents | Change the components of the calendar. |
You may need to use custom components in advanced applications to:
- Prevent default events from occurring.
- Add new event listeners, such as touch events.
- Display extra content, such as a calendar entry in the day cell.
- Implement buttons or dropdowns using your own design system components.
- Wrap an element with another element, like adding a tooltip to a day cell.
When customizing components, familiarize yourself with the API Reference and the DayPicker Anatomy. Ensure you maintain accessibility.
Custom components allow you to extend DayPicker beyond just using formatters. While formatters modify the content within the calendar, custom components enable you to alter the structure of the HTML elements.
Implementing a Custom Component
- Pass the components you want to customize to the
components
prop (see the list of custom components below). - Consider reusing the core components and composing your customizations on top of them.
- Use a custom React Context to share state between your custom components and your application.
<DayPicker
components={{
Day: CustomDaycell,
MonthGrid: CustomMonthGrid,
// etc.
}}
/>
List of Custom Components
Name | Description |
---|---|
CaptionLabel | The caption label of the month grid. |
Chevron | The chevron icon used in the navigation buttons and dropdowns. |
Day | The day cell in the month grid. |
DayButton | The button containing the day in the day cell. |
Dropdown | The dropdown element to select years and months. |
DropdownNav | The container of the dropdowns. |
Footer | The footer element announced by screen readers. |
Month | The container of the MonthGrid. |
MonthCaption | The caption of the month grid. |
MonthGrid | The grid of days in a month. |
Months | Wrapper of the month grids. |
MonthsDropdown | The dropdown with the months. |
Nav | The navigation element with the next and previous buttons. |
NextMonthButton | The next month button element in the navigation. |
Option | The <option> HTML element in the dropdown. |
PreviousMonthButton | The previous month button element in the navigation. |
Root | The root element of the calendar. |
Select | The select element in the dropdowns. |
Week | The week rows. |
WeekNumber | The cell with the number of the week. |
WeekNumberHeader | The header of the week number column. |
Weekday | The weekday name in the header. |
Weekdays | The row containing the week days. |
Weeks | The weeks section in the month grid. |
YearsDropdown | The dropdown with the years. |
DayPicker Hook
In a custom component, import the useDayPicker
hook to access the DayPicker context.
import { useDayPicker } from "react-day-picker";
Function | Return value | Description |
---|---|---|
useDayPicker | DayPickerContext | Returns the current state of DayPicker and functions to navigate the calendar. |
DayPicker Context
The DayPicker context provides the current state of the calendar, including the selected days, modifiers, and navigation state.
Name | Type | Description |
---|---|---|
classNames | ClassNames | The class names for the UI elements. |
components | CustomComponents | The components used internally by DayPicker. |
formatters | Formatters | The formatters used to format the UI elements. |
getModifiers | (day ) => Modifiers | Returns the modifiers for the given day. |
goToMonth | (month ) => void | Navigates to the specified month. |
isSelected | (date ) => boolean | undefined | Whether the given date is selected. |
labels | Labels | The labels used in the user interface. |
months | CalendarMonth [] | The months displayed in the calendar. |
nextMonth | Date | undefined | The next month to display. |
previousMonth | Date | undefined | The previous month to display. |
select | SelectHandler <T > | undefined | Sets a selection. |
selected | SelectedValue <T > | undefined | The selected date(s). |
styles | Partial <Styles > | undefined | The styles for the UI elements. |
dayPickerProps | DayPickerProps | The props passed to the DayPicker component. |
Examples
Intercepting Click Events
For example, you can use a custom DayButton to select days with a double-click event. This approach uses a custom React context to share the selected date state between the custom DayButton
and the main component.
import React from "react";
import { DayButton, type DayButtonProps, DayPicker } from "react-day-picker";
// Create a context to share the selected date state between the custom DayButton and the main component.
const SelectedDateContext = React.createContext<{
selected?: Date;
setSelected?: React.Dispatch<React.SetStateAction<Date | undefined>>;
}>({});
// Custom DayButton that uses the context to set the selected date on double-click and clear it on single click.
function DayButtonWithContext(props: DayButtonProps) {
const { day, modifiers, ...buttonProps } = props;
const { setSelected } = React.use(SelectedDateContext);
return (
<DayButton
{...buttonProps}
day={day}
modifiers={modifiers}
onClick={() => setSelected?.(undefined)}
onDoubleClick={() => setSelected?.(day.date)}
/>
);
}
export function MyDatePicker() {
const [selected, setSelected] = React.useState<Date>();
return (
<SelectedDateContext.Provider value={{ selected, setSelected }}>
<DayPicker
mode="single"
selected={selected}
onSelect={setSelected}
components={{
DayButton: DayButtonWithContext,
}}
/>
</SelectedDateContext.Provider>
);
}
Custom Select Dropdown
You can use a custom Dropdown to select years and months. The example below uses a simplified version of shadcn/ui
's Select.
import React, { useState } from "react";
import { DayButtonProps, DayPicker } from "react-day-picker";
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
export function CustomSelectDropdown(props: DropdownProps) {
const { options, value, onChange } = props;
const handleValueChange = (newValue: string) => {
if (onChange) {
const syntheticEvent = {
target: {
value: newValue,
},
} as React.ChangeEvent<HTMLSelectElement>;
onChange(syntheticEvent);
}
};
return (
<Select value={value?.toString()} onValueChange={handleValueChange}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectGroup>
{options?.map((option) => (
<SelectItem
key={option.value}
value={option.value.toString()}
disabled={option.disabled}
>
{option.label}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
);
}
export function CustomDropdown() {
const [selected, setSelected] = useState<Date | undefined>();
return (
<DayPicker
captionLayout="dropdown"
components={{ Dropdown: CustomSelectDropdown }}
mode="single"
selected={selected}
onSelect={setSelected}
footer={
selected ? `Selected: ${selected.toLocaleDateString()}` : "Pick a day."
}
/>
);
}
What are you using custom components for? Let us know.