Skip to content

Commit

Permalink
chore(CalendarMonth): provided explicit guidance for labeling an inli…
Browse files Browse the repository at this point in the history
…ne calendar month (#8375)

* chore(CalendarMonth): provided explicit guidance for labeling an inline calendar month

* update per PR comments

* move inline accommodations into an inlineProps prop

* fix typo and address PR comments

* fix test failures

* fix tests and snapshots
  • Loading branch information
nicolethoen authored Dec 8, 2022
1 parent 2f30f0c commit 3c593cc
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 8 deletions.
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>
</>
);
};

0 comments on commit 3c593cc

Please sign in to comment.