Skip to content
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

PLAT-115535: Wrap the created portal with div having aria-owns #2840

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions packages/ui/FloatingLayer/FloatingLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ class FloatingLayerBase extends React.Component {
}
}

generateId = () => {
return Math.random().toString(36).substr(2, 8);
};

handleNotify = oneOf(
[forEventProp('action', 'close'), call('handleClose')],
[forEventProp('action', 'mount'), call('setFloatingLayer')]
Expand Down Expand Up @@ -243,6 +247,7 @@ class FloatingLayerBase extends React.Component {

render () {
const {children, open, scrimType, ...rest} = this.props;
const id = this.generateId();

delete rest.floatLayerClassName;
delete rest.floatLayerId;
Expand All @@ -252,13 +257,15 @@ class FloatingLayerBase extends React.Component {
delete rest.onOpen;

if (open && this.state.nodeRendered) {
return ReactDOM.createPortal(
<div {...rest}>
const portal = ReactDOM.createPortal(
<div {...rest} id={id}>
{scrimType !== 'none' ? <Scrim type={scrimType} onClick={this.handleClick} /> : null}
{React.cloneElement(children, {onClick: this.stopPropagation})}
</div>,
this.node
);

return <div aria-owns={id}>{portal}</div>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Adding DOM here could be problematic. Since the portal is rendering in another subtree, this <div /> ends up being dropped wherever FloatingLayer was used and those component might not be expecting it.

I like the instinct to build this into ui but I'm not sure this is the right way. It might not be feasible to do since some outer component needs the id in order to set aria-owns correctly.

An alternative might be to add some Context to this to help auto-wire IDs up since they are required (instead of something generic like CSS classes) for ARIA to behave correctly. I'm not sure what that would be yet but something to consider.

}

return null;
Expand Down