Skip to content

Commit

Permalink
fix(ComposedModal): fix focus trap and refocus to trigger element whe…
Browse files Browse the repository at this point in the history
…n closed (#11418)

* fix(ComposedModal): fix focus trap and refocus to trigger when closed

* fix(ComposedModal): add style and updated snapshot
  • Loading branch information
annawen1 committed May 17, 2022
1 parent ecaf9b3 commit 94be72c
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 35 deletions.
4 changes: 4 additions & 0 deletions packages/components/src/components/modal/_modal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@
@include carbon--breakpoint(xlg) {
width: 48%;
}

.#{$prefix}--modal-container-body {
display: contents;
}
}

// -----------------------------
Expand Down
16 changes: 13 additions & 3 deletions packages/react/src/components/ComposedModal/ComposedModal-story.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/

import React, { useState } from 'react';
import React, { useState, useRef } from 'react';
import ReactDOM from 'react-dom';
import { action } from '@storybook/addon-actions';
import {
Expand Down Expand Up @@ -275,6 +275,7 @@ export const PassiveModal = () => {
};

export const WithStateManager = () => {
const closeButton = useRef();
/**
* Simple state manager for modals.
*/
Expand All @@ -298,10 +299,19 @@ export const WithStateManager = () => {
return (
<ModalStateManager
renderLauncher={({ setOpen }) => (
<Button onClick={() => setOpen(true)}>Launch composed modal</Button>
<Button ref={closeButton} onClick={() => setOpen(true)}>
Launch composed modal
</Button>
)}>
{({ open, setOpen }) => (
<ComposedModal open={open} onClose={() => setOpen(false)}>
<ComposedModal
open={open}
onClose={() => {
setOpen(false);
setTimeout(() => {
closeButton.current.focus();
});
}}>
<ModalHeader label="Account resources" title="Add a custom domain" />
<ModalBody>
<p style={{ marginBottom: '1rem' }}>
Expand Down
38 changes: 20 additions & 18 deletions packages/react/src/components/ComposedModal/ComposedModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,36 +286,38 @@ export default class ComposedModal extends Component {
}
}
}}
aria-hidden={!open}
onBlur={this.handleBlur}
onClick={this.handleClick}
onKeyDown={this.handleKeyDown}
onTransitionEnd={open ? this.handleTransitionEnd : undefined}
className={modalClass}>
{/* Non-translatable: Focus-wrap code makes this `<span>` not actually read by screen readers */}
<span
ref={this.startSentinel}
tabIndex="0"
role="link"
className={`${prefix}--visually-hidden`}>
Focus sentinel
</span>
<div
ref={this.innerModal}
className={containerClass}
role="dialog"
aria-modal="true"
aria-label={ariaLabel ? ariaLabel : generatedAriaLabel}
aria-labelledby={ariaLabelledBy}>
{childrenWithProps}
{/* Non-translatable: Focus-wrap code makes this `<span>` not actually read by screen readers */}
<button
type="button"
ref={this.startSentinel}
className={`${prefix}--visually-hidden`}>
Focus sentinel
</button>
<div
ref={this.innerModal}
className={`${prefix}--modal-container-body`}>
{childrenWithProps}
</div>
{/* Non-translatable: Focus-wrap code makes this `<button>` not actually read by screen readers */}
<button
type="button"
ref={this.endSentinel}
className={`${prefix}--visually-hidden`}>
Focus sentinel
</button>
</div>
{/* Non-translatable: Focus-wrap code makes this `<span>` not actually read by screen readers */}
<span
ref={this.endSentinel}
tabIndex="0"
role="link"
className={`${prefix}--visually-hidden`}>
Focus sentinel
</span>
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ exports[`<ComposedModal /> renders 1`] = `
selectorPrimaryFocus="[data-modal-primary-focus]"
>
<div
aria-hidden={false}
className="bx--modal is-visible"
onBlur={[Function]}
onClick={[Function]}
Expand All @@ -15,25 +16,27 @@ exports[`<ComposedModal /> renders 1`] = `
open={true}
role="presentation"
>
<span
className="bx--visually-hidden"
role="link"
tabIndex="0"
>
Focus sentinel
</span>
<div
aria-modal="true"
className="bx--modal-container"
role="dialog"
/>
<span
className="bx--visually-hidden"
role="link"
tabIndex="0"
>
Focus sentinel
</span>
<button
className="bx--visually-hidden"
type="button"
>
Focus sentinel
</button>
<div
className="bx--modal-container-body"
/>
<button
className="bx--visually-hidden"
type="button"
>
Focus sentinel
</button>
</div>
</div>
</ComposedModal>
`;
4 changes: 4 additions & 0 deletions packages/styles/scss/components/modal/_modal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@
@include breakpoint(xlg) {
width: 48%;
}

.#{$prefix}--modal-container-body {
display: contents;
}
}

// -----------------------------
Expand Down

0 comments on commit 94be72c

Please sign in to comment.