Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ export enum Weekday {
Saturday
}

export interface CalendarMonthInlineProps {
/** Component wrapping the calendar month when used inline. Recommended to be 'article'. */
component?: keyof JSX.IntrinsicElements;
/** Title of the calendar rendered above the inline calendar month. Recommended to be a 'title' component. */
title?: React.ReactNode;
/** Id of the accessible label of the calendar month. Recommended to map to the title. */
ariaLabelledby?: string;
}

/** Additional properties that extend from and can be passed to the main component. These
* properties allow customizing the calendar formatting and aria-labels.
*/
Expand Down Expand Up @@ -49,6 +58,8 @@ export interface CalendarFormat {
weekStart?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | Weekday;
/** Accessible label for the year input. */
yearInputAriaLabel?: string;
/** Props used to ensure accessibility when displaying the calendar month inline. */
inlineProps?: CalendarMonthInlineProps;
}

export interface CalendarProps extends CalendarFormat, Omit<React.HTMLProps<HTMLDivElement>, 'onChange'> {
Expand Down Expand Up @@ -133,6 +144,7 @@ export const CalendarMonth = ({
yearInputAriaLabel = 'Select year',
cellAriaLabel,
isDateFocused = false,
inlineProps,
...props
}: CalendarProps) => {
const longMonths = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map(monthNum => new Date(1990, monthNum)).map(monthFormat);
Expand Down Expand Up @@ -232,7 +244,8 @@ export const CalendarMonth = ({
const isHoveredDateValid = isValidated(hoveredDate);
const monthFormatted = monthFormat(focusedDate);
const yearFormatted = yearFormat(focusedDate);
return (

const calendarToRender = (
<div className={css(styles.calendarMonth, className)} {...props}>
<div className={styles.calendarMonthHeader}>
<div className={css(styles.calendarMonthHeaderNavControl, styles.modifiers.prevMonth)}>
Expand Down Expand Up @@ -386,4 +399,16 @@ export const CalendarMonth = ({
</table>
</div>
);

if (inlineProps !== undefined) {
const Component = (inlineProps.component ? inlineProps.component : 'article') as any;
return (
<Component {...(inlineProps.ariaLabelledby && { 'aria-labelledby': inlineProps.ariaLabelledby })}>
{inlineProps.title}
{calendarToRender}
</Component>
);
}
return calendarToRender;
};
CalendarMonth.displayName = 'CalendarMonth';
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,12 @@ test('Next year dates have correct year in aria label', () => {
const nextYearDate = screen.getByRole('button', { name: '1 January 2025' });
expect(nextYearDate).toBeVisible();
});

test('InlineProps render correct wrapper component and attributes', () => {
render(<CalendarMonth inlineProps={{component: 'article', title: <div id="hi">Title</div>, ariaLabelledby: "hi"}} />);

const article = screen.getByRole('article');
expect(article).toHaveAttribute('aria-labelledby', 'hi');
const title = screen.getByText('Title');
expect(title).toBeVisible();
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
id: Calendar month
section: components
cssPrefix: pf-c-calendar-month
propComponents: ['CalendarMonth', 'CalendarFormat']
propComponents: ['CalendarMonth', 'CalendarFormat', 'CalendarMonthInlineProps']
---

## Examples
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
import React from 'react';
import { CalendarMonth } from '@patternfly/react-core';
import { CalendarMonth, Title, CalendarMonthInlineProps } from '@patternfly/react-core';

export const CalendarMonthDateRange: React.FunctionComponent = () => {
const startDate = new Date(2020, 10, 11);
const endDate = new Date(2020, 10, 24);
const disablePreStartDates = (date: Date) => date >= startDate;

return <CalendarMonth validators={[disablePreStartDates]} date={endDate} rangeStart={startDate} />;
const inlineProps: CalendarMonthInlineProps = {
component: 'article',
title: (
<Title id="display-range" headingLevel="h4">
Calendar month displaying a range
</Title>
),
ariaLabelledby: 'display-range'
};

return (
<CalendarMonth
validators={[disablePreStartDates]}
date={endDate}
rangeStart={startDate}
inlineProps={inlineProps}
/>
);
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { CalendarMonth } from '@patternfly/react-core';
import { CalendarMonth, Title, CalendarMonthInlineProps } from '@patternfly/react-core';

export const CalendarMonthSelectableDate: React.FunctionComponent = () => {
const [date, setDate] = React.useState(new Date(2020, 10, 24));
Expand All @@ -9,10 +9,20 @@ export const CalendarMonthSelectableDate: React.FunctionComponent = () => {
console.log(`updated month: ${newDate.getMonth()}, updated year: ${newDate.getFullYear()}`);
};

const inlineProps: CalendarMonthInlineProps = {
component: 'article',
title: (
<Title headingLevel="h4" id="favorite-date">
Select your favorite date
</Title>
),
ariaLabelledby: 'favorite-date'
};

return (
<React.Fragment>
<>
<CalendarMonth date={date} onChange={setDate} onMonthChange={onMonthChange} inlineProps={inlineProps} />
<pre>Selected date: {date.toString()}</pre>
<CalendarMonth date={date} onChange={setDate} onMonthChange={onMonthChange} />
</React.Fragment>
</>
);
};