diff --git a/packages/react-core/src/components/CalendarMonth/CalendarMonth.tsx b/packages/react-core/src/components/CalendarMonth/CalendarMonth.tsx index de0e55165c9..996a2f88d12 100644 --- a/packages/react-core/src/components/CalendarMonth/CalendarMonth.tsx +++ b/packages/react-core/src/components/CalendarMonth/CalendarMonth.tsx @@ -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. */ @@ -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, 'onChange'> { @@ -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); @@ -232,7 +244,8 @@ export const CalendarMonth = ({ const isHoveredDateValid = isValidated(hoveredDate); const monthFormatted = monthFormat(focusedDate); const yearFormatted = yearFormat(focusedDate); - return ( + + const calendarToRender = (
@@ -386,4 +399,16 @@ export const CalendarMonth = ({
); + + if (inlineProps !== undefined) { + const Component = (inlineProps.component ? inlineProps.component : 'article') as any; + return ( + + {inlineProps.title} + {calendarToRender} + + ); + } + return calendarToRender; }; +CalendarMonth.displayName = 'CalendarMonth'; diff --git a/packages/react-core/src/components/CalendarMonth/__tests__/CalendarMonth.test.tsx b/packages/react-core/src/components/CalendarMonth/__tests__/CalendarMonth.test.tsx index a5d5214408e..4b70968618e 100644 --- a/packages/react-core/src/components/CalendarMonth/__tests__/CalendarMonth.test.tsx +++ b/packages/react-core/src/components/CalendarMonth/__tests__/CalendarMonth.test.tsx @@ -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(Title
, ariaLabelledby: "hi"}} />); + + const article = screen.getByRole('article'); + expect(article).toHaveAttribute('aria-labelledby', 'hi'); + const title = screen.getByText('Title'); + expect(title).toBeVisible(); +}); diff --git a/packages/react-core/src/components/CalendarMonth/examples/CalendarMonth.md b/packages/react-core/src/components/CalendarMonth/examples/CalendarMonth.md index 993a87a1501..0c3b27f6938 100644 --- a/packages/react-core/src/components/CalendarMonth/examples/CalendarMonth.md +++ b/packages/react-core/src/components/CalendarMonth/examples/CalendarMonth.md @@ -2,7 +2,7 @@ id: Calendar month section: components cssPrefix: pf-c-calendar-month -propComponents: ['CalendarMonth', 'CalendarFormat'] +propComponents: ['CalendarMonth', 'CalendarFormat', 'CalendarMonthInlineProps'] --- ## Examples diff --git a/packages/react-core/src/components/CalendarMonth/examples/CalendarMonthDateRange.tsx b/packages/react-core/src/components/CalendarMonth/examples/CalendarMonthDateRange.tsx index 1afd9cdbbc9..1bdfd79ea46 100644 --- a/packages/react-core/src/components/CalendarMonth/examples/CalendarMonthDateRange.tsx +++ b/packages/react-core/src/components/CalendarMonth/examples/CalendarMonthDateRange.tsx @@ -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 ; + const inlineProps: CalendarMonthInlineProps = { + component: 'article', + title: ( + + Calendar month displaying a range + + ), + ariaLabelledby: 'display-range' + }; + + return ( + + ); }; diff --git a/packages/react-core/src/components/CalendarMonth/examples/CalendarMonthSelectableDate.tsx b/packages/react-core/src/components/CalendarMonth/examples/CalendarMonthSelectableDate.tsx index d61f03d889c..f9fe55fd318 100644 --- a/packages/react-core/src/components/CalendarMonth/examples/CalendarMonthSelectableDate.tsx +++ b/packages/react-core/src/components/CalendarMonth/examples/CalendarMonthSelectableDate.tsx @@ -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)); @@ -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: ( + + Select your favorite date + + ), + ariaLabelledby: 'favorite-date' + }; + return ( - + <> +
Selected date: {date.toString()}
- -
+ ); };