Skip to content

feat(menu)!: allow users to specify both window and document env #694

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

ze-flo
Copy link
Contributor

@ze-flo ze-flo commented Apr 28, 2025

Description

This PR updates useMenu to allow users to specify both window and document environment independently.

💥 BREAKING CHANGE:

The environment prop has been removed and replaced with the optional window and document props to improve clarity and flexibility.

Detail

  • Adds optional window and document props
  • Fallbacks to window and window.document if props.window and/or props.document are undefined.
  • See implementation PR and preview.

Checklist

  • 🌐 demo is up-to-date (npm start)
  • 💂‍♂️ includes new unit tests
  • ♿ tested for WCAG 2.1 AA compliance
  • 📝 tested in Chrome, Firefox, Safari, and Edge

@coveralls
Copy link

coveralls commented Apr 28, 2025

Coverage Status

coverage: 94.833% (-0.1%) from 94.934%
when pulling 2b0f4b1 on ze-flo/menu-document-support
into a79dac8 on main.

Comment on lines 65 to 66
let _document: Document | ShadowRoot = _window ? _window.document : window.document;
_document = documentProp ? documentProp : _document;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let _document: Document | ShadowRoot = _window ? _window.document : window.document;
_document = documentProp ? documentProp : _document;
let _document: IUseMenuProps['document'];
if (documentProp) {
_document = documentProp
} else {
_document = _window ? _window.document : window.document;
}

...for improved readability and type reuse. Repeated ternaries are difficult to read and usually a signal for refactor.

}: IUseMenuProps<T, M>): IUseMenuReturnValue => {
const prefix = `${useId(idPrefix)}-`;
const triggerId = `${prefix}menu-trigger`;
const isExpandedControlled = isExpanded !== undefined;
const isSelectedItemsControlled = selectedItems !== undefined;
const isFocusedValueControlled = focusedValue !== undefined;

const _window = windowProp || environment;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recall there being problems with initializing this outside of the handlers because it potentially references globals in a way that breaks SSR. The logic should be restored throughout to get the window and/or document as needed – probably via a utility function.

Comment on lines 89 to 93
/**
* Sets the environment where the menu is rendered
* @deprecated use `window` prop instead.
* */
environment?: Window;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not deprecate; prefer the immediate feat(menu)!: ... breaking change in react-containers

@ze-flo ze-flo changed the title feat(menu): allow users to specify both window and document env feat(menu)!: allow users to specify both window and document env Apr 28, 2025
Comment on lines +665 to +674
const _document = getDocument(windowProp, documentProp) as Document;

if (controlledIsExpanded) {
win.document.addEventListener('keydown', handleMenuKeyDown, true);
_document.addEventListener('keydown', handleMenuKeyDown, true);
} else if (!controlledIsExpanded) {
win.document.removeEventListener('keydown', handleMenuKeyDown, true);
_document.removeEventListener('keydown', handleMenuKeyDown, true);
}

return () => {
win.document.removeEventListener('keydown', handleMenuKeyDown, true);
(_document as Document).removeEventListener('keydown', handleMenuKeyDown, true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth coercing the getDocument return value to Document so you don't need to repeatedly coerce throughout?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants