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

feat: add weekdayContent to render custom weekdays component on month view #931

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions packages/react-calendar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ Displays a given month, year, decade and a century, respectively.
| tileClassName | Class name(s) that will be applied to a given calendar item (day on month view, month on year view and so on). | n/a | <ul><li>String: `"class1 class2"`</li><li>Array of strings: `["class1", "class2 class3"]`</li><li>Function: `({ date, view }) => view === 'month' && date.getDay() === 3 ? 'wednesday' : null`</li></ul> |
| tileContent | Allows to render custom content within a given item (day on month view, month on year view and so on). **Note**: For tiles with custom content you might want to set fixed height of `react-calendar__tile` to ensure consistent layout. | n/a | `({ date, view }) => view === 'month' && date.getDay() === 0 ? <p>It's Sunday!</p> : null` |
| value | Calendar value. Can be either one value or an array of two values. | n/a | <ul><li>Date: `new Date()`</li><li>An array of dates: `[new Date(2017, 0, 1), new Date(2017, 7, 1)]`</li><li>String: `2017-01-01`</li><li>An array of strings: `['2017-01-01', '2017-08-01']`</li></ul> |
| weekdayContent | Allows to render custom content within a given weekday container on month view. | n/a | `({ locale, date }) => <p>{formatDate(date, 'dd')}</p> : null` |

## Useful links

Expand Down
10 changes: 10 additions & 0 deletions packages/react-calendar/src/Calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import type {
TileDisabledFunc,
Value,
View,
WeekdayContentFunc,
} from './shared/types.js';

import type {
Expand Down Expand Up @@ -430,6 +431,13 @@ export type CalendarProps = {
* @example 'year'
*/
view?: View;
/**
* Allows to render custom content within a given weekday container on month view.
*
* @example 'Sample'
* @example ({ locale, date }) => <p>{formatDate(date, 'dd')}</p> : null
*/
weekdayContent?: WeekdayContentFunc | React.ReactNode;
};

function toDate(value: Date | string): Date {
Expand Down Expand Up @@ -666,6 +674,7 @@ const Calendar = forwardRef(function Calendar(props: CalendarProps, ref) {
tileDisabled,
value: valueProps,
view: viewProps,
weekdayContent,
} = props;

const [activeStartDateState, setActiveStartDateState] = useState<Date | null | undefined>(
Expand Down Expand Up @@ -1077,6 +1086,7 @@ const Calendar = forwardRef(function Calendar(props: CalendarProps, ref) {
}
showNeighboringMonth={showNeighboringMonth}
showWeekNumbers={showWeekNumbers}
weekdayContent={weekdayContent}
{...commonProps}
/>
);
Expand Down
2 changes: 2 additions & 0 deletions packages/react-calendar/src/MonthView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const MonthView: React.FC<MonthViewProps> = function MonthView(props) {
formatWeekday,
onClickWeekNumber,
showWeekNumbers,
weekdayContent,
...childProps
} = props;

Expand All @@ -66,6 +67,7 @@ const MonthView: React.FC<MonthViewProps> = function MonthView(props) {
formatWeekday={formatWeekday}
locale={locale}
onMouseLeave={onMouseLeave}
weekdayContent={weekdayContent}
/>
);
}
Expand Down
21 changes: 21 additions & 0 deletions packages/react-calendar/src/MonthView/Weekdays.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,25 @@ describe('Weekdays', () => {

expect(firstWeekdayAbbr).toHaveAccessibleName('Weekday');
});

it('applies weekdayContent properly given function', () => {
const content = 'content';
const weekdayContent = () => content;

const { container } = render(<Weekdays {...defaultProps} weekdayContent={weekdayContent} />);

const firstWeekday = container.querySelector('.react-calendar__month-view__weekdays__weekday');

expect(firstWeekday).toHaveTextContent(content);
});

it('applies weekdayContent properly given string', () => {
const content = 'content';

const { container } = render(<Weekdays {...defaultProps} weekdayContent={content} />);

const firstWeekday = container.querySelector('.react-calendar__month-view__weekdays__weekday');

expect(firstWeekday).toHaveTextContent(content);
});
});
16 changes: 15 additions & 1 deletion packages/react-calendar/src/MonthView/Weekdays.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from '../shared/dateFormatter.js';
import { mapCalendarType } from '../shared/utils.js';

import type { CalendarType, DeprecatedCalendarType } from '../shared/types.js';
import type { CalendarType, DeprecatedCalendarType, WeekdayContentFunc } from '../shared/types.js';

const className = 'react-calendar__month-view__weekdays';
const weekdayClassName = `${className}__weekday`;
Expand All @@ -35,6 +35,13 @@ type WeekdaysProps = {
* @example (locale, date) => formatDate(date, 'dd')
*/
formatWeekday?: typeof defaultFormatWeekday;
/**
* Allows to render custom content within a given weekday container on month view.
*
* @example 'Sample'
* @example ({ locale, date }) => <p>{formatDate(date, 'dd')}</p> : null
*/
weekdayContent?: WeekdayContentFunc | React.ReactNode;
/**
* Locale that should be used by the calendar. Can be any [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag). **Note**: When using SSR, setting this prop may help resolving hydration errors caused by locale mismatch between server and client.
*
Expand All @@ -51,6 +58,7 @@ export default function Weekdays(props: WeekdaysProps) {
formatWeekday = defaultFormatWeekday,
locale,
onMouseLeave,
weekdayContent: weekdayContentProps,
} = props;

const calendarType = mapCalendarType(calendarTypeOrDeprecatedCalendarType);
Expand All @@ -70,6 +78,11 @@ export default function Weekdays(props: WeekdaysProps) {

const abbr = formatWeekday(locale, weekdayDate);

const weekdayContent =
typeof weekdayContentProps === 'function'
? weekdayContentProps({ locale, date: weekdayDate })
: weekdayContentProps;

weekdays.push(
<div
key={weekday}
Expand All @@ -82,6 +95,7 @@ export default function Weekdays(props: WeekdaysProps) {
<abbr aria-label={abbr} title={abbr}>
{formatShortWeekday(locale, weekdayDate).replace('.', '')}
</abbr>
{weekdayContent}
</div>,
);
}
Expand Down
7 changes: 7 additions & 0 deletions packages/react-calendar/src/shared/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,10 @@ export type TileClassNameFunc = (args: TileArgs) => ClassName;
export type TileContentFunc = (args: TileArgs) => React.ReactNode;

export type TileDisabledFunc = (args: TileArgs) => boolean;

export type WeekdayArgs = {
date: Date;
locale: string | undefined;
};

export type WeekdayContentFunc = (args: WeekdayArgs) => React.ReactNode;