diff --git a/packages/react-aria-components/src/Table.tsx b/packages/react-aria-components/src/Table.tsx index 4ad5580af30..d62536ca4e2 100644 --- a/packages/react-aria-components/src/Table.tsx +++ b/packages/react-aria-components/src/Table.tsx @@ -497,7 +497,7 @@ export const TableHeader = /*#__PURE__*/ createBranchComponent( } }, []) }); - + let {rowGroupProps} = useTableRowGroup(); return ( extends StyleRenderProps, LinkDOMProps, HoverEvents { /** The unique id of the row. */ @@ -918,23 +922,27 @@ export const Row = /*#__PURE__*/ createBranchComponent( ref ); let {isFocused, isFocusVisible, focusProps} = useFocusRing(); + let { + isFocusVisible: isFocusVisibleWithin, + focusProps: focusWithinProps + } = useFocusRing({within: true}); let {hoverProps, isHovered} = useHover({ isDisabled: !states.allowsSelection && !states.hasAction, onHoverStart: props.onHoverStart, onHoverChange: props.onHoverChange, onHoverEnd: props.onHoverEnd }); - + let {checkboxProps} = useTableSelectionCheckbox( {key: item.key}, state ); - + let draggableItem: DraggableItemResult | undefined = undefined; if (dragState && dragAndDropHooks) { draggableItem = dragAndDropHooks.useDraggableItem!({key: item.key, hasDragButton: true}, dragState); } - + let dropIndicator: DropIndicatorAria | undefined = undefined; let dropIndicatorRef = useRef(null); let {visuallyHiddenProps} = useVisuallyHidden(); @@ -943,7 +951,7 @@ export const Row = /*#__PURE__*/ createBranchComponent( target: {type: 'item', key: item.key, dropPosition: 'on'} }, dropState, dropIndicatorRef); } - + let renderDropIndicator = dragAndDropHooks?.renderDropIndicator || (target => ); let dragButtonRef = useRef(null); useEffect(() => { @@ -952,7 +960,7 @@ export const Row = /*#__PURE__*/ createBranchComponent( } // eslint-disable-next-line }, []); - + let isDragging = dragState && dragState.isDragging(item.key); // eslint-disable-next-line @typescript-eslint/no-unused-vars let {children: _, ...restProps} = props; @@ -968,10 +976,11 @@ export const Row = /*#__PURE__*/ createBranchComponent( selectionMode: state.selectionManager.selectionMode, selectionBehavior: state.selectionManager.selectionBehavior, isDragging, - isDropTarget: dropIndicator?.isDropTarget + isDropTarget: dropIndicator?.isDropTarget, + isFocusVisibleWithin } }); - + return ( <> {dragAndDropHooks?.useDropIndicator && @@ -985,7 +994,7 @@ export const Row = /*#__PURE__*/ createBranchComponent( )} + data-selection-mode={state.selectionManager.selectionMode === 'none' ? undefined : state.selectionManager.selectionMode} + data-focus-visible-within={isFocusVisibleWithin || undefined}> )} - {props.allowsResizing && } + {props.allowsResizing && } )} ); @@ -769,6 +769,25 @@ describe('Table', () => { expect(onScroll).toHaveBeenCalled(); }); + it('should support data-focus-visible-within', async () => { + let {getAllByRole} = renderTable(); + let items = getAllByRole('row'); + expect(items[1]).not.toHaveAttribute('data-focus-visible-within', 'true'); + + await user.tab(); + expect(document.activeElement).toBe(items[1]); + expect(items[1]).toHaveAttribute('data-focus-visible-within', 'true'); + await user.keyboard('{ArrowRight}'); + + let cell = within(items[1]).getAllByRole('rowheader')[0]; + expect(document.activeElement).toBe(cell); + expect(cell).toHaveAttribute('data-focus-visible', 'true'); + expect(items[1]).toHaveAttribute('data-focus-visible-within', 'true'); + + await user.keyboard('{ArrowDown}'); + expect(items[1]).not.toHaveAttribute('data-focus-visible-within', 'true'); + }); + describe('drag and drop', () => { it('should support drag button slot', () => { let {getAllByRole} = render(); @@ -1003,6 +1022,12 @@ describe('Table', () => { ); } + + it('Column resizer accepts data attributes', () => { + let {getAllByTestId} = render(); + let resizers = getAllByTestId('resizer'); + expect(resizers).toHaveLength(5); + }); }); it('should support overriding table style', () => {