Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: captionLayout prop not working as expected #2177

Merged
merged 1 commit into from
Jun 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ import React from "react";
import { DayPicker } from "react-day-picker";

export function Dropdown() {
return <DayPicker dropdownNavigation fromYear={2015} toYear={2025} />;
return <DayPicker captionLayout="dropdown" fromYear={2010} />;
}
2 changes: 1 addition & 1 deletion examples/DropdownMultipleMonths.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export function DropdownMultipleMonths() {
return (
<DayPicker
numberOfMonths={5}
dropdownNavigation
captionLayout="dropdown"
fromYear={2015}
toYear={2025}
/>
Expand Down
15 changes: 4 additions & 11 deletions src/components/MonthCaption.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function MonthCaption(props: {
}) {
const {
classNames,
dropdownNavigation,
captionLayout,
formatters: { formatCaption },
locale,
styles
Expand All @@ -36,22 +36,15 @@ export function MonthCaption(props: {
className={classNames[UI.MonthCaption]}
style={styles?.[UI.MonthCaption]}
>
{dropdownNavigation ? (
<DropdownNav
month={props.month}
index={props.index}
showMonths
showYears
/>
) : dropdownNavigation ? (
{captionLayout?.startsWith("dropdown") ? (
<DropdownNav
month={props.month}
index={props.index}
showMonths={
dropdownNavigation === true || dropdownNavigation === "month"
captionLayout === "dropdown" || captionLayout === "dropdown-months"
}
showYears={
dropdownNavigation === true || dropdownNavigation === "year"
captionLayout === "dropdown" || captionLayout === "dropdown-years"
}
/>
) : (
Expand Down
2 changes: 2 additions & 0 deletions src/components/MonthsDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export function MonthsDropdown(props: {
const {
classNames,
components,
disableNavigation,
labels: { labelMonthDropdown }
} = useProps();

Expand All @@ -43,6 +44,7 @@ export function MonthsDropdown(props: {
<Dropdown
name="month"
aria-label={labelMonthDropdown()}
aria-disabled={disableNavigation ? "true" : undefined}
rootClassName={classNames[UI.MonthsDropdown]}
options={dropdown.months}
value={props.month.date.getMonth()}
Expand Down
3 changes: 2 additions & 1 deletion src/components/YearsDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export function YearsDropdown(props: {
const {
classNames,
components,
disableNavigation,
labels: { labelYearDropdown }
} = useProps();

Expand All @@ -42,8 +43,8 @@ export function YearsDropdown(props: {
const Dropdown = components?.Dropdown ?? DefaultDropdown;
return (
<Dropdown
name="year"
aria-label={labelYearDropdown()}
aria-disabled={disableNavigation ? "true" : undefined}
rootClassName={classNames[UI.YearsDropdown]}
options={dropdown.years}
value={props.month.date.getFullYear()}
Expand Down
61 changes: 30 additions & 31 deletions src/helpers/getFromToDate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ describe('when "toYear" is passed in', () => {
});
});

describe('when "showCaption" is passed in', () => {
describe('when "captionLayout" is dropdown', () => {
const today = new Date(2024, 4, 3);
const { fromDate, toDate } = getFromToDate({
dropdownNavigation: true,
captionLayout: "dropdown",
today
});
test('"fromDate" should be 100 years ago', () => {
Expand All @@ -62,35 +62,34 @@ describe('when "showCaption" is passed in', () => {
test('"toDate" should be the end of this year', () => {
expect(toDate).toEqual(new Date(2024, 11, 31));
});
});

describe('when "fromYear" and "showCaption" are passed in', () => {
const today = new Date(2024, 4, 3);
const fromYear = 2022;
const { fromDate, toDate } = getFromToDate({
dropdownNavigation: true,
fromYear,
today
});
test('"fromDate" should be equal to the "fromYear"', () => {
expect(fromDate).toEqual(new Date(2022, 0, 1));
});
test('"toDate" should be the end of this year', () => {
expect(toDate).toEqual(new Date(2024, 11, 31));
});
});
describe('when "toYear" and "showCaption" are passed in', () => {
const today = new Date(2021, 4, 3);
const toYear = 2022;
const { toDate, fromDate } = getFromToDate({
dropdownNavigation: true,
toYear,
today
});
test('"fromDate" should be 100 years ago', () => {
expect(fromDate).toEqual(new Date(1921, 0, 1));
describe('when "fromYear" is set', () => {
const today = new Date(2024, 4, 3);
const fromYear = 2022;
const { fromDate, toDate } = getFromToDate({
captionLayout: "dropdown",
fromYear,
today
});
test('"fromDate" should be equal to the "fromYear"', () => {
expect(fromDate).toEqual(new Date(2022, 0, 1));
});
test('"toDate" should be the end of this year', () => {
expect(toDate).toEqual(new Date(2024, 11, 31));
});
});
test('"toDate" should be equal to "toYear"', () => {
expect(toDate).toEqual(new Date(2022, 11, 31));
describe('when "toYear" is set', () => {
const today = new Date(2021, 4, 3);
const toYear = 2022;
const { toDate, fromDate } = getFromToDate({
captionLayout: "dropdown",
toYear,
today
});
test('"fromDate" should be 100 years ago', () => {
expect(fromDate).toEqual(new Date(1921, 0, 1));
});
test('"toDate" should be equal to "toYear"', () => {
expect(toDate).toEqual(new Date(2022, 11, 31));
});
});
});
8 changes: 4 additions & 4 deletions src/helpers/getFromToDate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,24 @@ export function getFromToDate(
| "fromMonth"
| "toMonth"
| "today"
| "dropdownNavigation"
| "captionLayout"
>
): Pick<DayPickerProps<Mode>, "fromDate" | "toDate"> {
const { fromYear, toYear, fromMonth, toMonth } = props;
let { fromDate, toDate } = props;

const hasDropdowns = props.captionLayout?.startsWith("dropdown");
if (fromMonth) {
fromDate = startOfMonth(fromMonth);
} else if (fromYear) {
fromDate = new Date(fromYear, 0, 1);
} else if (!fromDate && props.dropdownNavigation !== undefined) {
} else if (!fromDate && hasDropdowns) {
fromDate = startOfYear(addYears(props.today ?? new Date(), -100));
}
if (toMonth) {
toDate = endOfMonth(toMonth);
} else if (toYear) {
toDate = new Date(toYear, 11, 31);
} else if (!toDate && props.dropdownNavigation) {
} else if (!toDate && hasDropdowns) {
toDate = endOfYear(props.today ?? new Date());
}
return {
Expand Down
16 changes: 9 additions & 7 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,15 +143,17 @@ export interface PropsBase {
/**
* Show dropdowns to navigate between months or years.
*
* - `true`: display the dropdowns for both month and year.
* - `month`: display the dropdown for the month.
* - `year`: display the dropdown for the year.
* - `false`: hide the dropdowns.
* - `true`: display the dropdowns for both month and year
* - `label`: display the month and the year as a label. Change the label with
* the `formatCaption` formatter.
* - `month`: display only the dropdown for the months
* - `year`: display only the dropdown for the years
*
* **Note:** showing the dropdown will default {@link fromYear} to the 100
* years ago, and {@link toYear} to the current year.
* **Note:** showing the dropdown will set the start/end months
* {@link fromYear} to the 100 years ago, and {@link toYear} to the current
* year.
*/
dropdownNavigation?: boolean | "month" | "year";
captionLayout?: "label" | "dropdown" | "dropdown-months" | "dropdown-years";
/**
* Display always 6 weeks per each month, regardless the month’s number of
* weeks. Weeks will be filled with the days from the next month.
Expand Down
71 changes: 42 additions & 29 deletions website/docs/using-daypicker/customization.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,39 @@ Use the customization props to customize the appearance of the calendar.

### Customization Props

| Prop Name | Type | Description |
| ----------------- | -------------------------------------------------------- | ---------------------------------------------------------------- |
| `captionLayout` | `"dropdown"` \| `"buttons"` \|<br/> `"dropdown-buttons"` | Change the layout of the caption. <br /> Default is `"buttons"`. |
| `showOutsideDays` | `boolean` | Display the days falling into the other months. |
| `fixedWeeks` | `boolean` | Display 6 weeks per months. |
| `hideWeekdayRow` | `boolean` | Hide the row displaying the weekday names. |
| `footer` | `ReactNode` | Displays a footer below the calendar. |
| Prop Name | Type | Description |
| ----------------- | ------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| `captionLayout` | \| `label`<br/> \| `"dropdown"`<br/> \| `"dropdown-months"`<br/> \|`"dropdown-years"` | Choose the layout of the month caption. Default is `label`. |
| `showOutsideDays` | `boolean` | Display the days falling into the other months. |
| `fixedWeeks` | `boolean` | Display 6 weeks per months. |
| `hideWeekdayRow` | `boolean` | Hide the row displaying the weekday names. |
| `footer` | `ReactNode` | Displays a footer below the calendar. |

## Caption Layout

Use the `captionLayout` prop to the layout of the caption used to navigate the calendar.

As default, DayPicker will show navigation buttons on the top corner.
Use the `captionLayout` prop to choose the layout of the month caption:

```tsx
<DayPicker captionLayout="buttons" /> // Default value
<DayPicker captionLayout="label" /> // Default value: shows the month and year.
```

### Dropdown Navigation

Use `dropdown` or `dropdown-buttons` to display a navigation dropdown.
| Caption Layout | Description |
| ------------------- | ----------------------------------------------------- |
| `"label"` | Display the month and year as a label. Default value. |
| `"dropdown"` | Display a dropdown with the months and years. |
| `"dropdown-months"` | Display a dropdown with the months only. |
| `"dropdown-years"` | Display a dropdown with the years only. |

:::warning
### Caption Dropdown

To use this prop, you need to set both `fromYear` and `toYear`. (This requirement will be removed in a next version.)

:::
Set `captionLayout="dropdown"` to display a navigation dropdown. This will allow navigation within the last 100 years. Use the `from*` and `to*` props to [set the start and end dates](./navigation.mdx#start-and-end-dates).

```tsx
<DayPicker captionLayout="dropdown" fromYear={2010} toYear={2024} />
<DayPicker captionLayout="dropdown-buttons" fromYear={2010} toYear={2024} />
<DayPicker captionLayout="dropdown" />
<DayPicker captionLayout="dropdown-months" /> // Only months
<DayPicker captionLayout="dropdown-years" /> // Only years

<DayPicker captionLayout="dropdown" fromYear={2015} toYear={2025} /> // Set the years range
```

<BrowserWindow>
Expand All @@ -59,17 +61,10 @@ By default, DayPicker hides the days falling into the other months. Use `showOut

### Fixed Weeks

In a year, months can have between 4 an 6 weeks. Use `fixedWeeks` with `showOutsideDays` to always display 6 weeks per month. This will prevent the grid changing its height while navigating the calendar.

:::note

In the current version, this prop requires `showOutsideDays` set to work. This
requirement will be removed in the next major version.

:::
In a year, months can have between 4 an 6 weeks. Use `fixedWeeks` to always display 6 weeks per month. This will prevent the grid changing its height while navigating the calendar.

```tsx
<DayPicker showOutsideDays fixedWeeks />
<DayPicker fixedWeeks showWeekNumber />
```

<BrowserWindow>
Expand Down Expand Up @@ -122,3 +117,21 @@ To display the column with the week numbers, use the `showWeekNumber` prop. Use
<BrowserWindow>
<Examples.Weeknumber />
</BrowserWindow>

## Formatters and Labels

Use the [formatters](./localization.mdx#formatters) and [labels](./localization.mdx#labels) to customize the format of the dates and the ARIA labels.

| Prop Name | Type | Description |
| ------------ | ------------------------------------------------- | ---------------------------------------------- |
| `formatters` | [`Formatters`](../api/type-aliases/Formatters.md) | Format of the dates displayed in the calendar. |
| `labels` | [`Labels`](../api/type-aliases/Labels.md) | Set the ARIA labels used in the calendar. |

## Custom Components

In DayPicker, you can replace the components used internally to render the calendar. See the [Custom Components](../advanced-guides/custom-components.mdx) guide for more information.

| Prop Name | Type | Description |
| ------------ | ------------------------------------------------------------- | ----------------------------------------------------------- |
| `components` | [`CustomComponents`](../api/type-aliases/CustomComponents.md) | Change the internal components used to render the calendar. |
| `classNames` | [`ClassNames`](../api/type-aliases/ClassNames.md) | Use custom class names instead of the default ones. |
Loading