diff --git a/packages/@react-aria/calendar/src/useCalendarCell.ts b/packages/@react-aria/calendar/src/useCalendarCell.ts index fa7c422987b..c1da41afb36 100644 --- a/packages/@react-aria/calendar/src/useCalendarCell.ts +++ b/packages/@react-aria/calendar/src/useCalendarCell.ts @@ -40,6 +40,8 @@ export interface CalendarCellAria { isPressed: boolean, /** Whether the cell is selected. */ isSelected: boolean, + /** Whether the cell is read only. */ + isReadOnly: boolean, /** Whether the cell is focused. */ isFocused: boolean, /** @@ -305,7 +307,8 @@ export function useCalendarCell(props: AriaCalendarCellProps, state: CalendarSta role: 'gridcell', 'aria-disabled': !isSelectable || undefined, 'aria-selected': isSelected || undefined, - 'aria-invalid': isInvalid || undefined + 'aria-invalid': isInvalid || undefined, + 'aria-readonly': state.isReadOnly || undefined }, buttonProps: mergeProps(pressProps, { onFocus() { @@ -343,6 +346,7 @@ export function useCalendarCell(props: AriaCalendarCellProps, state: CalendarSta }), isPressed, isFocused, + isReadOnly: state.isReadOnly, isSelected, isDisabled, isUnavailable, diff --git a/packages/react-aria-components/src/Calendar.tsx b/packages/react-aria-components/src/Calendar.tsx index f3ed804b892..abd137a2437 100644 --- a/packages/react-aria-components/src/Calendar.tsx +++ b/packages/react-aria-components/src/Calendar.tsx @@ -262,6 +262,11 @@ export interface CalendarCellRenderProps { * @selector [data-selected] */ isSelected: boolean, + /** + * Whether the cell is read only. + * @selector [data-readonly] + */ + isReadOnly: boolean, /** * Whether the cell is the first date in a range selection. * @selector [data-selection-start] @@ -541,7 +546,8 @@ export const CalendarCell = /*#__PURE__*/ (forwardRef as forwardRefType)(functio 'data-selected': states.isSelected || undefined, 'data-selection-start': isSelectionStart || undefined, 'data-selection-end': isSelectionEnd || undefined, - 'data-invalid': states.isInvalid || undefined + 'data-invalid': states.isInvalid || undefined, + 'data-readonly': states.isReadOnly || undefined }; return ( diff --git a/packages/react-aria-components/test/Calendar.test.js b/packages/react-aria-components/test/Calendar.test.js index ba590708101..f689d3cfb51 100644 --- a/packages/react-aria-components/test/Calendar.test.js +++ b/packages/react-aria-components/test/Calendar.test.js @@ -263,6 +263,18 @@ describe('Calendar', () => { expect(cell).toHaveClass('disabled'); }); + it('should support read only state', () => { + let {getByRole} = renderCalendar({isReadOnly: true}, {}, {className: ({isReadOnly}) => isReadOnly ? 'readonly' : ''}); + let grid = getByRole('grid'); + let cell = within(grid).getAllByRole('gridcell')[7]; + let button = within(cell).getByRole('button'); + + + expect(cell).toHaveAttribute('aria-readonly', 'true'); + expect(button).toHaveAttribute('data-readonly'); + expect(button).toHaveClass('readonly'); + }); + it('should support invalid state', () => { let {getByRole} = renderCalendar({isInvalid: true, value: startOfWeek(startOfMonth(today(getLocalTimeZone())), 'en-US').add({days: 7})}, {}, {className: ({isInvalid}) => isInvalid ? 'invalid' : ''}); let grid = getByRole('grid');