From 5959e26522eed27788d771cfbeea692a32772cdd Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Mon, 2 Feb 2026 18:02:34 -0800 Subject: [PATCH 1/5] fix: add missing "use client" so that local docs build works (#9579) --- packages/dev/s2-docs/pages/s2/forms.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/dev/s2-docs/pages/s2/forms.mdx b/packages/dev/s2-docs/pages/s2/forms.mdx index 47fbfef6c9e..1da75e033d1 100644 --- a/packages/dev/s2-docs/pages/s2/forms.mdx +++ b/packages/dev/s2-docs/pages/s2/forms.mdx @@ -131,6 +131,7 @@ Well-designed form validation assists the user with specific, helpful error mess All React Spectrum form components integrate with native HTML [constraint validation](https://developer.mozilla.org/en-US/docs/Web/HTML/Constraint_validation). This allows you to define constraints on each field such as required, minimum and maximum values, text formats such as email addresses, and even custom regular expression patterns. These constraints are checked by the browser when the user commits changes to the value (e.g. on blur) or submits the form. ```tsx render +'use client'; import {Form, TextField, ButtonGroup, Button} from '@react-spectrum/s2'; import {style} from '@react-spectrum/s2/style' with {type: 'macro'}; From 8b7f090ae5f12abefeb9291689b246fefc693871 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Mon, 2 Feb 2026 18:17:42 -0800 Subject: [PATCH 2/5] Revert "feat: allow customizing behavior of pressed state (#8971)" (#9578) This reverts commit 92aa6f497f46b401d2bbc9db0abf7af7784ae7ab. --- packages/@react-spectrum/s2/src/ComboBox.tsx | 6 +- .../@react-spectrum/s2/src/DatePicker.tsx | 6 +- .../s2/src/DateRangePicker.tsx | 3 +- .../@react-spectrum/s2/src/DialogTrigger.tsx | 11 +- packages/@react-spectrum/s2/src/Menu.tsx | 4 +- packages/@react-spectrum/s2/src/Picker.tsx | 6 +- .../@react-spectrum/s2/src/TabsPicker.tsx | 129 ++++++++---------- .../react-aria-components/src/ComboBox.tsx | 6 +- .../react-aria-components/src/DatePicker.tsx | 12 +- packages/react-aria-components/src/Dialog.tsx | 4 +- packages/react-aria-components/src/Menu.tsx | 4 +- packages/react-aria-components/src/Select.tsx | 6 +- .../stories/DatePicker.stories.tsx | 3 - .../stories/Select.stories.tsx | 3 - .../test/ComboBox.test.js | 9 -- .../test/DatePicker.test.js | 9 -- .../test/DateRangePicker.test.js | 9 -- .../react-aria-components/test/Dialog.test.js | 17 --- .../react-aria-components/test/Menu.test.tsx | 19 --- .../react-aria-components/test/Select.test.js | 9 -- 20 files changed, 91 insertions(+), 184 deletions(-) diff --git a/packages/@react-spectrum/s2/src/ComboBox.tsx b/packages/@react-spectrum/s2/src/ComboBox.tsx index d3cd25f882f..e6178185891 100644 --- a/packages/@react-spectrum/s2/src/ComboBox.tsx +++ b/packages/@react-spectrum/s2/src/ComboBox.tsx @@ -79,7 +79,7 @@ export interface ComboboxStyleProps { size?: 'S' | 'M' | 'L' | 'XL' } export interface ComboBoxProps extends - Omit, 'children' | 'style' | 'className' | 'render' | 'defaultFilter' | 'allowsEmptyCollection' | 'isTriggerUpWhenOpen' | keyof GlobalDOMAttributes>, + Omit, 'children' | 'style' | 'className' | 'render' | 'defaultFilter' | 'allowsEmptyCollection' | keyof GlobalDOMAttributes>, ComboboxStyleProps, StyleProps, SpectrumLabelableProps, @@ -354,7 +354,6 @@ export const ComboBox = /*#__PURE__*/ (forwardRef as forwardRefType)(function Co return ( pressScale(buttonRef)(renderProps)} className={renderProps => inputButton({ ...renderProps, diff --git a/packages/@react-spectrum/s2/src/DatePicker.tsx b/packages/@react-spectrum/s2/src/DatePicker.tsx index ab44172d92c..c5e1ee8ca40 100644 --- a/packages/@react-spectrum/s2/src/DatePicker.tsx +++ b/packages/@react-spectrum/s2/src/DatePicker.tsx @@ -41,7 +41,7 @@ import {useSpectrumContextProps} from './useSpectrumContextProps'; export interface DatePickerProps extends - Omit, 'children' | 'className' | 'style' | 'render' | 'isTriggerUpWhenOpen' | keyof GlobalDOMAttributes>, + Omit, 'children' | 'className' | 'style' | 'render' | keyof GlobalDOMAttributes>, Pick, 'createCalendar' | 'pageBehavior' | 'firstDayOfWeek' | 'isDateUnavailable'>, Pick, StyleProps, @@ -155,7 +155,6 @@ export const DatePicker = /*#__PURE__*/ (forwardRef as forwardRefType)(function ref={ref} isRequired={isRequired} {...dateFieldProps} - isTriggerUpWhenOpen style={UNSAFE_style} className={(UNSAFE_className || '') + style(field(), getAllowedOverrides())({ isInForm: !!formContext, @@ -278,6 +277,9 @@ export function CalendarButton(props: {isOpen: boolean, size: 'S' | 'M' | 'L' | return ( - + } + }], + [InsideSelectValueContext, true] + ]}> + {defaultChildren} + + ); + }} + + + extends Omit, HTMLDivElement>>(null); @@ -210,7 +208,7 @@ function ComboBoxInner({props, collection, comboBoxRef: ref}: values={[ [ComboBoxStateContext, state], [LabelContext, {...labelProps, ref: labelRef}], - [ButtonContext, {...buttonProps, ref: buttonRef, isPressed: !props.isTriggerUpWhenOpen && state.isOpen}], + [ButtonContext, {...buttonProps, ref: buttonRef, isPressed: state.isOpen}], [InputContext, {...inputProps, ref: inputRef}], [OverlayTriggerStateContext, state], [PopoverContext, { diff --git a/packages/react-aria-components/src/DatePicker.tsx b/packages/react-aria-components/src/DatePicker.tsx index c1b8821612d..61a50dc6ae0 100644 --- a/packages/react-aria-components/src/DatePicker.tsx +++ b/packages/react-aria-components/src/DatePicker.tsx @@ -88,18 +88,14 @@ export interface DatePickerProps extends Omit, - /** Whether the trigger is up when the overlay is open. */ - isTriggerUpWhenOpen?: boolean + className?: ClassNameOrFunction } export interface DateRangePickerProps extends Omit, 'label' | 'description' | 'errorMessage' | 'validationState' | 'validationBehavior'>, Pick, 'shouldCloseOnSelect'>, RACValidation, RenderProps, SlotProps, GlobalDOMAttributes { /** * The CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the element. A function may be provided to compute the class based on component state. * @default 'react-aria-DateRangePicker' */ - className?: ClassNameOrFunction, - /** Whether the trigger is up when the overlay is open. */ - isTriggerUpWhenOpen?: boolean + className?: ClassNameOrFunction } export const DatePickerContext = createContext, HTMLDivElement>>(null); @@ -179,7 +175,7 @@ export const DatePicker = /*#__PURE__*/ (forwardRef as forwardRefType)(function [DatePickerStateContext, state], [GroupContext, {...groupProps, ref: groupRef, isInvalid: state.isInvalid}], [DateFieldContext, fieldProps], - [ButtonContext, {...buttonProps, isPressed: !props.isTriggerUpWhenOpen && state.isOpen}], + [ButtonContext, {...buttonProps, isPressed: state.isOpen}], [LabelContext, {...labelProps, ref: labelRef, elementType: 'span'}], [CalendarContext, calendarProps], [OverlayTriggerStateContext, state], @@ -288,7 +284,7 @@ export const DateRangePicker = /*#__PURE__*/ (forwardRef as forwardRefType)(func values={[ [DateRangePickerStateContext, state], [GroupContext, {...groupProps, ref: groupRef, isInvalid: state.isInvalid}], - [ButtonContext, {...buttonProps, isPressed: !props.isTriggerUpWhenOpen && state.isOpen}], + [ButtonContext, {...buttonProps, isPressed: state.isOpen}], [LabelContext, {...labelProps, ref: labelRef, elementType: 'span'}], [RangeCalendarContext, calendarProps], [OverlayTriggerStateContext, state], diff --git a/packages/react-aria-components/src/Dialog.tsx b/packages/react-aria-components/src/Dialog.tsx index c95dce96e32..2091109092a 100644 --- a/packages/react-aria-components/src/Dialog.tsx +++ b/packages/react-aria-components/src/Dialog.tsx @@ -22,8 +22,6 @@ import React, {createContext, ForwardedRef, forwardRef, JSX, ReactNode, useCallb import {RootMenuTriggerStateContext} from './Menu'; export interface DialogTriggerProps extends OverlayTriggerProps { - /** Whether the trigger is up when the overlay is open. */ - isTriggerUpWhenOpen?: boolean, children: ReactNode } @@ -88,7 +86,7 @@ export function DialogTrigger(props: DialogTriggerProps): JSX.Element { style: {'--trigger-width': buttonWidth} as React.CSSProperties }] ]}> - + {props.children} diff --git a/packages/react-aria-components/src/Menu.tsx b/packages/react-aria-components/src/Menu.tsx index 994df7d3932..91cb0727e4a 100644 --- a/packages/react-aria-components/src/Menu.tsx +++ b/packages/react-aria-components/src/Menu.tsx @@ -64,8 +64,6 @@ export const RootMenuTriggerStateContext = createContext(null); export interface MenuTriggerProps extends BaseMenuTriggerProps { - /** Whether the trigger is up when the overlay is open. */ - isTriggerUpWhenOpen?: boolean, children: ReactNode } @@ -105,7 +103,7 @@ export function MenuTrigger(props: MenuTriggerProps): JSX.Element { 'aria-labelledby': menuProps['aria-labelledby'] }] ]}> - + {props.children} diff --git a/packages/react-aria-components/src/Select.tsx b/packages/react-aria-components/src/Select.tsx index ded3a340eee..3d4e3e311bb 100644 --- a/packages/react-aria-components/src/Select.tsx +++ b/packages/react-aria-components/src/Select.tsx @@ -87,9 +87,7 @@ export interface SelectProps, HTMLDivElement>>(null); @@ -204,7 +202,7 @@ function SelectInner({props, selectRef: ref, collection}: Sele [SelectStateContext, state], [SelectValueContext, valueProps], [LabelContext, {...labelProps, ref: labelRef, elementType: 'span'}], - [ButtonContext, {...triggerProps, ref: buttonRef, isPressed: !props.isTriggerUpWhenOpen && state.isOpen, autoFocus: props.autoFocus}], + [ButtonContext, {...triggerProps, ref: buttonRef, isPressed: state.isOpen, autoFocus: props.autoFocus}], [OverlayTriggerStateContext, state], [PopoverContext, { trigger: 'Select', diff --git a/packages/react-aria-components/stories/DatePicker.stories.tsx b/packages/react-aria-components/stories/DatePicker.stories.tsx index bc9cde5a648..ae079959edf 100644 --- a/packages/react-aria-components/stories/DatePicker.stories.tsx +++ b/packages/react-aria-components/stories/DatePicker.stories.tsx @@ -47,9 +47,6 @@ export default { validationBehavior: { control: 'select', options: ['native', 'aria'] - }, - isTriggerUpWhenOpen: { - control: 'boolean' } } } as Meta; diff --git a/packages/react-aria-components/stories/Select.stories.tsx b/packages/react-aria-components/stories/Select.stories.tsx index b7bf2204137..c71374de62e 100644 --- a/packages/react-aria-components/stories/Select.stories.tsx +++ b/packages/react-aria-components/stories/Select.stories.tsx @@ -31,9 +31,6 @@ export default { selectionMode: { control: 'radio', options: ['single', 'multiple'] - }, - isTriggerUpWhenOpen: { - control: 'boolean' } } } as Meta; diff --git a/packages/react-aria-components/test/ComboBox.test.js b/packages/react-aria-components/test/ComboBox.test.js index a9cf870563c..bb17da5e894 100644 --- a/packages/react-aria-components/test/ComboBox.test.js +++ b/packages/react-aria-components/test/ComboBox.test.js @@ -115,15 +115,6 @@ describe('ComboBox', () => { expect(button).toHaveAttribute('data-pressed'); }); - it('should not apply isPressed state to button when expanded and isTriggerUpWhenOpen is true', async () => { - let {getByRole} = render(); - let button = getByRole('button'); - - expect(button).not.toHaveAttribute('data-pressed'); - await user.click(button); - expect(button).not.toHaveAttribute('data-pressed'); - }); - it('should support filtering sections', async () => { let tree = render( diff --git a/packages/react-aria-components/test/DatePicker.test.js b/packages/react-aria-components/test/DatePicker.test.js index e68afdb3be3..62d0ce8c462 100644 --- a/packages/react-aria-components/test/DatePicker.test.js +++ b/packages/react-aria-components/test/DatePicker.test.js @@ -113,15 +113,6 @@ describe('DatePicker', () => { expect(button).toHaveAttribute('data-pressed'); }); - it('should not apply isPressed state to button when expanded and isTriggerUpWhenOpen is true', async () => { - let {getByRole} = render(); - let button = getByRole('button'); - - expect(button).not.toHaveAttribute('data-pressed'); - await user.click(button); - expect(button).not.toHaveAttribute('data-pressed'); - }); - it('should support data-open state', async () => { let {getByRole} = render(); let datePicker = document.querySelector('.react-aria-DatePicker'); diff --git a/packages/react-aria-components/test/DateRangePicker.test.js b/packages/react-aria-components/test/DateRangePicker.test.js index f89cc8fee01..2dda3884105 100644 --- a/packages/react-aria-components/test/DateRangePicker.test.js +++ b/packages/react-aria-components/test/DateRangePicker.test.js @@ -134,15 +134,6 @@ describe('DateRangePicker', () => { await user.click(button); expect(button).toHaveAttribute('data-pressed'); }); - - it('should not apply isPressed state to button when expanded and isTriggerUpWhenOpen is true', async () => { - let {getByRole} = render(); - let button = getByRole('button'); - - expect(button).not.toHaveAttribute('data-pressed'); - await user.click(button); - expect(button).not.toHaveAttribute('data-pressed'); - }); it('should support data-open state', async () => { let {getByRole} = render(); diff --git a/packages/react-aria-components/test/Dialog.test.js b/packages/react-aria-components/test/Dialog.test.js index fa5a043b8d8..b9c57dc9940 100644 --- a/packages/react-aria-components/test/Dialog.test.js +++ b/packages/react-aria-components/test/Dialog.test.js @@ -56,23 +56,6 @@ describe('Dialog', () => { expect(dialog).toHaveAttribute('data-rac'); }); - it('should not apply isPressed state on trigger when expanded and isTriggerUpWhenOpen is true', async () => { - let {getByRole} = render( - - - - Title - - - ); - - let button = getByRole('button'); - expect(button).not.toHaveAttribute('data-pressed'); - - await user.click(button); - expect(button).not.toHaveAttribute('data-pressed'); - }); - it('works with modal', async () => { let {getByRole} = render( diff --git a/packages/react-aria-components/test/Menu.test.tsx b/packages/react-aria-components/test/Menu.test.tsx index aa3f48f1dbe..b46ac184faf 100644 --- a/packages/react-aria-components/test/Menu.test.tsx +++ b/packages/react-aria-components/test/Menu.test.tsx @@ -536,25 +536,6 @@ describe('Menu', () => { expect(onAction).toHaveBeenLastCalledWith('rename'); }); - it('should not apply isPressed state on trigger when expanded and isTriggerUpWhenOpen is true', async () => { - let {getByRole} = render( - - - - - Open - - - - ); - - let button = getByRole('button'); - expect(button).not.toHaveAttribute('data-pressed'); - - await user.click(button); - expect(button).not.toHaveAttribute('data-pressed'); - }); - it('should support onScroll', () => { let onScroll = jest.fn(); let {getByRole} = renderMenu({onScroll}); diff --git a/packages/react-aria-components/test/Select.test.js b/packages/react-aria-components/test/Select.test.js index 97d7cba1038..78dea4fccc1 100644 --- a/packages/react-aria-components/test/Select.test.js +++ b/packages/react-aria-components/test/Select.test.js @@ -399,15 +399,6 @@ describe('Select', () => { expect(trigger).toHaveTextContent('Kangaroo'); }); - it('should not apply isPressed state to button when expanded and isTriggerUpWhenOpen is true', async () => { - let {getByRole} = render(); - let button = getByRole('button'); - - expect(button).not.toHaveAttribute('data-pressed'); - await user.click(button); - expect(button).not.toHaveAttribute('data-pressed'); - }); - describe('typeahead', () => { beforeEach(() => { jest.useFakeTimers(); From b6797273bbc44bca6759194a7da5759409a19ff7 Mon Sep 17 00:00:00 2001 From: Yihui Liao <44729383+yihuiliao@users.noreply.github.com> Date: Mon, 2 Feb 2026 18:31:09 -0800 Subject: [PATCH 3/5] Revert "fix 'ResizeObserver loop completed with undelivered notifications' error when overlays get resized (#7742)" (#9576) This reverts commit 8a1ff6c4ba62659848f634a0f2714414ba9eb610. Co-authored-by: Robert Snow --- packages/@react-aria/utils/src/useResizeObserver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@react-aria/utils/src/useResizeObserver.ts b/packages/@react-aria/utils/src/useResizeObserver.ts index 0d33aa60a2d..ab0a1d5ae3c 100644 --- a/packages/@react-aria/utils/src/useResizeObserver.ts +++ b/packages/@react-aria/utils/src/useResizeObserver.ts @@ -37,7 +37,7 @@ export function useResizeObserver(options: useResizeObserverO return; } - requestAnimationFrame(() => onResizeEvent()); + onResizeEvent(); }); resizeObserverInstance.observe(element, {box}); From ac7aabe9a0aa42c461cc81442b2d64839cb30f17 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 2 Feb 2026 18:49:35 -0800 Subject: [PATCH 4/5] docs: Add some padding between example and alert (#9580) Co-authored-by: Robert Snow --- packages/dev/s2-docs/pages/react-aria/GridList.mdx | 2 +- packages/dev/s2-docs/pages/react-aria/Table.mdx | 2 +- packages/dev/s2-docs/pages/react-aria/Tree.mdx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/dev/s2-docs/pages/react-aria/GridList.mdx b/packages/dev/s2-docs/pages/react-aria/GridList.mdx index fd988402641..0be7e40e264 100644 --- a/packages/dev/s2-docs/pages/react-aria/GridList.mdx +++ b/packages/dev/s2-docs/pages/react-aria/GridList.mdx @@ -520,7 +520,7 @@ let images = [ ``` - + Client-side routing Due to [HTML spec limitations](https://github.com/w3c/html-aria/issues/473), GridListItems cannot be rendered as `` elements. React Aria handles link clicks with JavaScript and triggers native navigation. When using a client-side router, use the `onAction` event to programmatically trigger navigation instead of the `href` prop. diff --git a/packages/dev/s2-docs/pages/react-aria/Table.mdx b/packages/dev/s2-docs/pages/react-aria/Table.mdx index 424dc7ecd01..b84ae1716a4 100644 --- a/packages/dev/s2-docs/pages/react-aria/Table.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Table.mdx @@ -295,7 +295,7 @@ import {Table, TableHeader, Column, Row, TableBody, Cell} from 'vanilla-starter/ ``` - + Client-side routing Due to [HTML spec limitations](https://github.com/w3c/html-aria/issues/473), table rows cannot be rendered as `` elements. React Aria handles link clicks with JavaScript and triggers native navigation. When using a client-side router, use the `onAction` event to programmatically trigger navigation instead of the `href` prop. diff --git a/packages/dev/s2-docs/pages/react-aria/Tree.mdx b/packages/dev/s2-docs/pages/react-aria/Tree.mdx index 92555e74f77..0cfb27d58c4 100644 --- a/packages/dev/s2-docs/pages/react-aria/Tree.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Tree.mdx @@ -219,7 +219,7 @@ import {Tree, TreeItem} from 'vanilla-starter/Tree'; ``` - + Client-side routing Due to [HTML spec limitations](https://github.com/w3c/html-aria/issues/473), TreeItems cannot be rendered as `` elements. React Aria handles link clicks with JavaScript and triggers native navigation. When using a client-side router, use the `onAction` event to programmatically trigger navigation instead of the `href` prop. From 4955eb2c8218c853d074a87bd1685e8b8ccfed3c Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Mon, 2 Feb 2026 21:10:34 -0600 Subject: [PATCH 5/5] chore: no shadow support for test utils right now (#9581) * feat: revert shadow dom contains for test-utils * update eslint config to ignore test-utils * run yarn install --- eslint.config.mjs | 9 +++++++++ packages/@react-aria/test-utils/package.json | 1 - .../@react-aria/test-utils/src/checkboxgroup.ts | 3 +-- packages/@react-aria/test-utils/src/combobox.ts | 5 ++--- packages/@react-aria/test-utils/src/dialog.ts | 7 +++---- packages/@react-aria/test-utils/src/gridlist.ts | 5 ++--- packages/@react-aria/test-utils/src/listbox.ts | 3 +-- packages/@react-aria/test-utils/src/menu.ts | 9 ++++----- packages/@react-aria/test-utils/src/radiogroup.ts | 3 +-- packages/@react-aria/test-utils/src/select.ts | 7 +++---- packages/@react-aria/test-utils/src/table.ts | 13 ++++++------- packages/@react-aria/test-utils/src/tabs.ts | 5 ++--- packages/@react-aria/test-utils/src/tree.ts | 7 +++---- yarn.lock | 1 - 14 files changed, 37 insertions(+), 41 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index ad336dabaf3..cd41e502778 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -501,6 +501,15 @@ export default [{ message: "Use getOwnerDocument from @react-aria/utils instead.", }], }, +}, { + files: [ + "packages/@react-aria/test-utils/src/**/*.ts", + "packages/@react-aria/test-utils/src/**/*.tsx", + ], + + rules: { + "rsp-rules/no-non-shadow-contains": OFF, + }, }, { files: ["packages/@react-spectrum/s2/**", "packages/dev/s2-docs/**"], diff --git a/packages/@react-aria/test-utils/package.json b/packages/@react-aria/test-utils/package.json index ec18ecb6981..4393a60b129 100644 --- a/packages/@react-aria/test-utils/package.json +++ b/packages/@react-aria/test-utils/package.json @@ -26,7 +26,6 @@ "url": "https://github.com/adobe/react-spectrum" }, "dependencies": { - "@react-aria/utils": "^3.32.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { diff --git a/packages/@react-aria/test-utils/src/checkboxgroup.ts b/packages/@react-aria/test-utils/src/checkboxgroup.ts index 7451b7ec9cb..54e436a5cab 100644 --- a/packages/@react-aria/test-utils/src/checkboxgroup.ts +++ b/packages/@react-aria/test-utils/src/checkboxgroup.ts @@ -12,7 +12,6 @@ import {act, within} from '@testing-library/react'; import {CheckboxGroupTesterOpts, UserOpts} from './types'; -import {nodeContains} from '@react-aria/utils'; import {pressElement} from './events'; interface TriggerCheckboxOptions { @@ -95,7 +94,7 @@ export class CheckboxGroupTester { throw new Error('Checkbox provided is not in the checkbox group.'); } - if (!nodeContains(this.checkboxgroup, document.activeElement)) { + if (!this.checkboxgroup.contains(document.activeElement)) { act(() => checkboxes[0].focus()); } diff --git a/packages/@react-aria/test-utils/src/combobox.ts b/packages/@react-aria/test-utils/src/combobox.ts index 3dfb46c3946..d95ac6f5711 100644 --- a/packages/@react-aria/test-utils/src/combobox.ts +++ b/packages/@react-aria/test-utils/src/combobox.ts @@ -12,7 +12,6 @@ import {act, waitFor, within} from '@testing-library/react'; import {ComboBoxTesterOpts, UserOpts} from './types'; -import {nodeContains} from '@react-aria/utils'; interface ComboBoxOpenOpts { /** @@ -177,7 +176,7 @@ export class ComboBoxTester { if (option.getAttribute('href') == null) { await waitFor(() => { - if (nodeContains(document, listbox)) { + if (document.contains(listbox)) { throw new Error('Expected listbox element to not be in the document after selecting an option'); } else { return true; @@ -199,7 +198,7 @@ export class ComboBoxTester { await this.user.keyboard('[Escape]'); await waitFor(() => { - if (nodeContains(document, listbox)) { + if (document.contains(listbox)) { throw new Error('Expected listbox element to not be in the document after selecting an option'); } else { return true; diff --git a/packages/@react-aria/test-utils/src/dialog.ts b/packages/@react-aria/test-utils/src/dialog.ts index 10e3b22d0f5..213c86c2b1a 100644 --- a/packages/@react-aria/test-utils/src/dialog.ts +++ b/packages/@react-aria/test-utils/src/dialog.ts @@ -12,7 +12,6 @@ import {act, waitFor, within} from '@testing-library/react'; import {DialogTesterOpts, UserOpts} from './types'; -import {nodeContains} from '@react-aria/utils'; interface DialogOpenOpts { /** @@ -97,7 +96,7 @@ export class DialogTester { } }); - if (dialog && document.activeElement !== this._trigger && nodeContains(dialog, document.activeElement)) { + if (dialog && document.activeElement !== this._trigger && dialog.contains(document.activeElement)) { this._dialog = dialog; } else { throw new Error('New modal dialog doesnt contain the active element OR the active element is still the trigger. Uncertain if the proper modal dialog was found'); @@ -114,7 +113,7 @@ export class DialogTester { if (dialog) { await this.user.keyboard('[Escape]'); await waitFor(() => { - if (nodeContains(document, dialog)) { + if (document.contains(dialog)) { throw new Error('Expected the dialog to not be in the document after closing it.'); } else { this._dialog = undefined; @@ -139,6 +138,6 @@ export class DialogTester { * Returns the dialog if present. */ get dialog(): HTMLElement | null { - return this._dialog && nodeContains(document, this._dialog) ? this._dialog : null; + return this._dialog && document.contains(this._dialog) ? this._dialog : null; } } diff --git a/packages/@react-aria/test-utils/src/gridlist.ts b/packages/@react-aria/test-utils/src/gridlist.ts index ebf8af799b6..d5d1c21e082 100644 --- a/packages/@react-aria/test-utils/src/gridlist.ts +++ b/packages/@react-aria/test-utils/src/gridlist.ts @@ -13,7 +13,6 @@ import {act, within} from '@testing-library/react'; import {getAltKey, getMetaKey, pressElement, triggerLongPress} from './events'; import {GridListTesterOpts, GridRowActionOpts, ToggleGridRowOpts, UserOpts} from './types'; -import {nodeContains} from '@react-aria/utils'; interface GridListToggleRowOpts extends ToggleGridRowOpts {} interface GridListRowActionOpts extends GridRowActionOpts {} @@ -67,13 +66,13 @@ export class GridListTester { throw new Error('Option provided is not in the gridlist'); } - if (document.activeElement !== this._gridlist && !nodeContains(this._gridlist, document.activeElement)) { + if (document.activeElement !== this._gridlist && !this._gridlist.contains(document.activeElement)) { act(() => this._gridlist.focus()); } if (document.activeElement === this._gridlist) { await this.user.keyboard(`${selectionOnNav === 'none' ? `[${altKey}>]` : ''}[ArrowDown]${selectionOnNav === 'none' ? `[/${altKey}]` : ''}`); - } else if (nodeContains(this._gridlist, document.activeElement) && document.activeElement!.getAttribute('role') !== 'row') { + } else if (this._gridlist.contains(document.activeElement) && document.activeElement!.getAttribute('role') !== 'row') { do { await this.user.keyboard('[ArrowLeft]'); } while (document.activeElement!.getAttribute('role') !== 'row'); diff --git a/packages/@react-aria/test-utils/src/listbox.ts b/packages/@react-aria/test-utils/src/listbox.ts index d8fcab4a772..cac8d9d78bc 100644 --- a/packages/@react-aria/test-utils/src/listbox.ts +++ b/packages/@react-aria/test-utils/src/listbox.ts @@ -13,7 +13,6 @@ import {act, within} from '@testing-library/react'; import {getAltKey, getMetaKey, pressElement, triggerLongPress} from './events'; import {ListBoxTesterOpts, UserOpts} from './types'; -import {nodeContains} from '@react-aria/utils'; interface ListBoxToggleOptionOpts { /** @@ -104,7 +103,7 @@ export class ListBoxTester { throw new Error('Option provided is not in the listbox'); } - if (document.activeElement !== this._listbox && !nodeContains(this._listbox, document.activeElement)) { + if (document.activeElement !== this._listbox && !this._listbox.contains(document.activeElement)) { act(() => this._listbox.focus()); await this.user.keyboard(`${selectionOnNav === 'none' ? `[${altKey}>]` : ''}[ArrowDown]${selectionOnNav === 'none' ? `[/${altKey}]` : ''}`); } diff --git a/packages/@react-aria/test-utils/src/menu.ts b/packages/@react-aria/test-utils/src/menu.ts index f3dcdd3bdd0..87af5c11fd0 100644 --- a/packages/@react-aria/test-utils/src/menu.ts +++ b/packages/@react-aria/test-utils/src/menu.ts @@ -12,7 +12,6 @@ import {act, waitFor, within} from '@testing-library/react'; import {MenuTesterOpts, UserOpts} from './types'; -import {nodeContains} from '@react-aria/utils'; import {triggerLongPress} from './events'; interface MenuOpenOpts { @@ -216,7 +215,7 @@ export class MenuTester { return; } - if (document.activeElement !== menu && !nodeContains(menu, document.activeElement)) { + if (document.activeElement !== menu && !menu.contains(document.activeElement)) { act(() => menu.focus()); } @@ -263,7 +262,7 @@ export class MenuTester { // close. In React 16, focus actually makes it all the way to the root menu's submenu trigger so we need check the root menu if (this._isSubmenu) { await waitFor(() => { - if (document.activeElement === this.trigger || nodeContains(this._rootMenu, document.activeElement)) { + if (document.activeElement === this.trigger || this._rootMenu?.contains(document.activeElement)) { throw new Error('Expected focus after selecting an submenu option to move away from the original submenu trigger.'); } else { return true; @@ -343,7 +342,7 @@ export class MenuTester { private async keyboardNavigateToOption(opts: {option: HTMLElement}) { let {option} = opts; let options = this.options(); - let targetIndex = options.findIndex(opt => (opt === option) || nodeContains(opt, option)); + let targetIndex = options.findIndex(opt => (opt === option) || opt.contains(option)); if (targetIndex === -1) { throw new Error('Option provided is not in the menu'); @@ -379,7 +378,7 @@ export class MenuTester { } }); - if (nodeContains(document, menu)) { + if (document.contains(menu)) { throw new Error('Expected the menu to not be in the document after closing it.'); } } diff --git a/packages/@react-aria/test-utils/src/radiogroup.ts b/packages/@react-aria/test-utils/src/radiogroup.ts index bdcbfce9730..6c1d0e38c9e 100644 --- a/packages/@react-aria/test-utils/src/radiogroup.ts +++ b/packages/@react-aria/test-utils/src/radiogroup.ts @@ -12,7 +12,6 @@ import {act, within} from '@testing-library/react'; import {Direction, Orientation, RadioGroupTesterOpts, UserOpts} from './types'; -import {nodeContains} from '@react-aria/utils'; import {pressElement} from './events'; interface TriggerRadioOptions { @@ -95,7 +94,7 @@ export class RadioGroupTester { throw new Error('Radio provided is not in the radio group.'); } - if (!nodeContains(this.radiogroup, document.activeElement)) { + if (!this.radiogroup.contains(document.activeElement)) { let selectedRadio = this.selectedRadio; if (selectedRadio != null) { act(() => selectedRadio.focus()); diff --git a/packages/@react-aria/test-utils/src/select.ts b/packages/@react-aria/test-utils/src/select.ts index 56a9372dfe5..4cce164f53f 100644 --- a/packages/@react-aria/test-utils/src/select.ts +++ b/packages/@react-aria/test-utils/src/select.ts @@ -11,7 +11,6 @@ */ import {act, waitFor, within} from '@testing-library/react'; -import {nodeContains} from '@react-aria/utils'; import {SelectTesterOpts, UserOpts} from './types'; interface SelectOpenOpts { @@ -111,7 +110,7 @@ export class SelectTester { } }); - if (listbox && nodeContains(document, listbox)) { + if (listbox && document.contains(listbox)) { throw new Error('Expected the select element listbox to not be in the document after closing the dropdown.'); } } @@ -192,7 +191,7 @@ export class SelectTester { return; } - if (document.activeElement !== listbox && !nodeContains(listbox, document.activeElement)) { + if (document.activeElement !== listbox && !listbox.contains(document.activeElement)) { act(() => listbox.focus()); } await this.keyboardNavigateToOption({option}); @@ -215,7 +214,7 @@ export class SelectTester { } }); - if (nodeContains(document, listbox)) { + if (document.contains(listbox)) { throw new Error('Expected select element listbox to not be in the document after selecting an option'); } } diff --git a/packages/@react-aria/test-utils/src/table.ts b/packages/@react-aria/test-utils/src/table.ts index 24071fd3b90..95d4e6fe184 100644 --- a/packages/@react-aria/test-utils/src/table.ts +++ b/packages/@react-aria/test-utils/src/table.ts @@ -13,7 +13,6 @@ import {act, waitFor, within} from '@testing-library/react'; import {getAltKey, getMetaKey, pressElement, triggerLongPress} from './events'; import {GridRowActionOpts, TableTesterOpts, ToggleGridRowOpts, UserOpts} from './types'; -import {nodeContains} from '@react-aria/utils'; interface TableToggleRowOpts extends ToggleGridRowOpts {} interface TableToggleSortOpts { @@ -66,7 +65,7 @@ export class TableTester { } // Move focus into the table - if (document.activeElement !== this._table && !nodeContains(this._table, document.activeElement)) { + if (document.activeElement !== this._table && !this._table.contains(document.activeElement)) { act(() => this._table.focus()); } @@ -75,14 +74,14 @@ export class TableTester { } // If focus is currently somewhere in the first row group (aka on a column), we want to keyboard navigate downwards till we reach the rows - if (nodeContains(this.rowGroups[0], document.activeElement)) { + if (this.rowGroups[0].contains(document.activeElement)) { do { await this.user.keyboard('[ArrowDown]'); - } while (!nodeContains(this.rowGroups[1], document.activeElement)); + } while (!this.rowGroups[1].contains(document.activeElement)); } // Move focus onto the row itself - if (nodeContains(this.rowGroups[1], document.activeElement) && document.activeElement!.getAttribute('role') !== 'row') { + if (this.rowGroups[1].contains(document.activeElement) && document.activeElement!.getAttribute('role') !== 'row') { do { await this.user.keyboard('[ArrowLeft]'); } while (document.activeElement!.getAttribute('role') !== 'row'); @@ -223,7 +222,7 @@ export class TableTester { } await waitFor(() => { - if (nodeContains(document, menu)) { + if (document.contains(menu)) { throw new Error('Expected table column menu listbox to not be in the document after selecting an option'); } else { return true; @@ -309,7 +308,7 @@ export class TableTester { await pressElement(this.user, within(menu).getAllByRole('menuitem')[action], interactionType); await waitFor(() => { - if (nodeContains(document, menu)) { + if (document.contains(menu)) { throw new Error('Expected table column menu listbox to not be in the document after selecting an option'); } else { return true; diff --git a/packages/@react-aria/test-utils/src/tabs.ts b/packages/@react-aria/test-utils/src/tabs.ts index f87a2d9afd2..c26da3e7656 100644 --- a/packages/@react-aria/test-utils/src/tabs.ts +++ b/packages/@react-aria/test-utils/src/tabs.ts @@ -12,7 +12,6 @@ import {act, within} from '@testing-library/react'; import {Direction, Orientation, TabsTesterOpts, UserOpts} from './types'; -import {nodeContains} from '@react-aria/utils'; import {pressElement} from './events'; interface TriggerTabOptions { @@ -90,7 +89,7 @@ export class TabsTester { throw new Error('Tab provided is not in the tablist'); } - if (!nodeContains(this._tablist, document.activeElement)) { + if (!this._tablist.contains(document.activeElement)) { let selectedTab = this.selectedTab; if (selectedTab != null) { act(() => selectedTab.focus()); @@ -143,7 +142,7 @@ export class TabsTester { } if (interactionType === 'keyboard') { - if (document.activeElement !== this._tablist && !nodeContains(this._tablist, document.activeElement)) { + if (document.activeElement !== this._tablist && !this._tablist.contains(document.activeElement)) { act(() => this._tablist.focus()); } diff --git a/packages/@react-aria/test-utils/src/tree.ts b/packages/@react-aria/test-utils/src/tree.ts index 28a566d59ec..cadcf52b72a 100644 --- a/packages/@react-aria/test-utils/src/tree.ts +++ b/packages/@react-aria/test-utils/src/tree.ts @@ -13,7 +13,6 @@ import {act, within} from '@testing-library/react'; import {BaseGridRowInteractionOpts, GridRowActionOpts, ToggleGridRowOpts, TreeTesterOpts, UserOpts} from './types'; import {getAltKey, getMetaKey, pressElement, triggerLongPress} from './events'; -import {nodeContains} from '@react-aria/utils'; interface TreeToggleExpansionOpts extends BaseGridRowInteractionOpts {} interface TreeToggleRowOpts extends ToggleGridRowOpts {} @@ -74,13 +73,13 @@ export class TreeTester { throw new Error('Option provided is not in the tree'); } - if (document.activeElement !== this._tree && !nodeContains(this._tree, document.activeElement)) { + if (document.activeElement !== this._tree && !this._tree.contains(document.activeElement)) { act(() => this._tree.focus()); } if (document.activeElement === this.tree) { await this.user.keyboard(`${selectionOnNav === 'none' ? `[${altKey}>]` : ''}[ArrowDown]${selectionOnNav === 'none' ? `[/${altKey}]` : ''}`); - } else if (nodeContains(this._tree, document.activeElement) && document.activeElement!.getAttribute('role') !== 'row') { + } else if (this._tree.contains(document.activeElement) && document.activeElement!.getAttribute('role') !== 'row') { do { await this.user.keyboard('[ArrowLeft]'); } while (document.activeElement!.getAttribute('role') !== 'row'); @@ -179,7 +178,7 @@ export class TreeTester { row, interactionType = this._interactionType } = opts; - if (!nodeContains(this.tree, document.activeElement)) { + if (!this.tree.contains(document.activeElement)) { await act(async () => { this.tree.focus(); }); diff --git a/yarn.lock b/yarn.lock index 82f4b7eb377..d716c3117ce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6179,7 +6179,6 @@ __metadata: version: 0.0.0-use.local resolution: "@react-aria/test-utils@workspace:packages/@react-aria/test-utils" dependencies: - "@react-aria/utils": "npm:^3.32.0" "@swc/helpers": "npm:^0.5.0" peerDependencies: "@testing-library/react": ^16.0.0