Skip to content
This repository has been archived by the owner on Oct 19, 2021. It is now read-only.

Commit

Permalink
fix(Modal): Focus primary actionable button on modal opening (#980)
Browse files Browse the repository at this point in the history
* fix(Modal): Focus primary actionable button on modal opening

* fix(ModalWrapper): Focus primary actionable button only on Modal open
Set timeout to circumvent CSS transitions

* refactor(Button): convert Button from class component back to stateless function

* refactor(Modal): refactor DOM refs according to React best practices

* refactor(Button): properly declare custom attribute

* refactor(Modal): properly declare custom attribute

* test(ModalWrapper): update snapshot

* refactor(Modal): use `onTransitionEnd` handler over `componentDidUpdate`

* test(ModalWrapper): update snapshot

* refactor(Modal): query `offsetWidth` and `offsetHeight` before focusing button

* refactor(Modal): reduce event handler calls

* test(ModalWrapper): update snapshot

* fix(Modal): rewrite conditional to remove Jest warning

* refactor(Modal): rename `buttonIsFocusable` property to `beingOpen`
  • Loading branch information
emyarod authored and marijohannessen committed Jun 20, 2018
1 parent 74ccc0a commit 102f805
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 5 deletions.
14 changes: 12 additions & 2 deletions src/components/Button/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,24 @@ const Button = ({
) : null;

const button = (
<button {...other} {...commonProps} disabled={disabled} type={type}>
<button
{...other}
{...commonProps}
disabled={disabled}
type={type}
ref={other.inputref}>
{children}
{buttonImage}
</button>
);

const anchor = (
<a {...other} {...commonProps} href={href} role="button">
<a
{...other}
{...commonProps}
href={href}
role="button"
ref={other.inputref}>
{children}
{buttonImage}
</a>
Expand Down
39 changes: 36 additions & 3 deletions src/components/Modal/Modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ export default class Modal extends Component {
modalLabel: '',
};

button = React.createRef();

handleKeyDown = evt => {
if (evt.which === 27) {
this.props.onRequestClose();
Expand All @@ -52,6 +54,31 @@ export default class Modal extends Component {
}
};

componentDidUpdate(prevProps) {
if (!prevProps.open && this.props.open) {
this.beingOpen = true;
} else if (prevProps.open && !this.props.open) {
this.beingOpen = false;
}
}

focusButton = () => {
if (this.button) {
this.button.current.focus();
}
};

handleTransitionEnd = () => {
if (
this.outerModal.offsetWidth &&
this.outerModal.offsetHeight &&
this.beingOpen
) {
this.focusButton();
this.beingOpen = false;
}
};

render() {
const {
modalHeading,
Expand Down Expand Up @@ -86,7 +113,8 @@ export default class Modal extends Component {
<button
className="bx--modal-close"
type="button"
onClick={onRequestClose}>
onClick={onRequestClose}
ref={this.button}>
<Icon
name="close"
className="bx--modal-close__icon"
Expand Down Expand Up @@ -123,7 +151,8 @@ export default class Modal extends Component {
<Button
kind={danger ? 'danger--primary' : 'primary'}
disabled={primaryButtonDisabled}
onClick={onRequestSubmit}>
onClick={onRequestSubmit}
inputref={this.button}>
{primaryButtonText}
</Button>
</div>
Expand All @@ -139,7 +168,11 @@ export default class Modal extends Component {
onClick={this.handleClick}
className={modalClasses}
role="presentation"
tabIndex={-1}>
tabIndex={-1}
onTransitionEnd={this.props.open ? this.handleTransitionEnd : undefined}
ref={outerModal => {
this.outerModal = outerModal;
}}>
{modalBody}
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,18 @@ exports[`ModalWrapper should render 1`] = `
<Button
disabled={false}
iconDescription="Provide icon description if icon is used"
inputref={
Object {
"current": <button
class="bx--btn bx--btn--primary"
inputref="[object Object]"
tabindex="0"
type="button"
>
Save
</button>,
}
}
kind="primary"
onClick={[Function]}
small={false}
Expand All @@ -158,6 +170,18 @@ exports[`ModalWrapper should render 1`] = `
<button
className="bx--btn bx--btn--primary"
disabled={false}
inputref={
Object {
"current": <button
class="bx--btn bx--btn--primary"
inputref="[object Object]"
tabindex="0"
type="button"
>
Save
</button>,
}
}
onClick={[Function]}
tabIndex={0}
type="button"
Expand Down

0 comments on commit 102f805

Please sign in to comment.