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

fix(Modal): Lock focus #41

Merged
merged 7 commits into from
May 2, 2019
Merged
Show file tree
Hide file tree
Changes from 3 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
70 changes: 70 additions & 0 deletions src/Modal/Modal.dropdownExample.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React from 'react';
import Modal from './Modal';
import Button from '../Button';
import Input from '../Form/Input';
import Dropdown from '../Dropdown';

export default class ModalDropdownDemo extends React.Component {
state = {
isModalOpen: false,
isModalTwoOpen: false,
};

toggle = () => {
this.setState({ isModalOpen: !this.state.isModalOpen, isModalTwoOpen: false });
};

toggleModalTwo = () => {
this.setState({ isModalTwoOpen: !this.state.isModalTwoOpen });
};

onCancel = () => {
this.toggle();

setTimeout(() => {
alert('Oh no! It has been canceled.');
}, 500);
};

render() {
const { body, ...props } = this.props;

return (
<div>
<Dropdown placement="0 100%" width={250} trigger={<Button variant="success">Open Dropdown</Button>}>
<Dropdown.Header title="Dropdown" />

<Dropdown.Body>
<Dropdown.SectionTitle>Section One</Dropdown.SectionTitle>
<Dropdown.Item onClick={this.toggle} as="button">
Open Modal
</Dropdown.Item>
</Dropdown.Body>

<Dropdown.Footer>Footer</Dropdown.Footer>
</Dropdown>

<Modal
open={this.state.isModalOpen}
onClose={this.toggle}
title="Example Dropdown Modal"
{...props}>
<Modal.Body>
<>
{body}
<Input autoFocus name="password" label="Password" />
</>
</Modal.Body>

<Modal.Footer>
<Button.Group justifyContent="flex-end">
<Button variant="gray" onClick={this.onCancel}>
Cancel
</Button>
</Button.Group>
</Modal.Footer>
</Modal>
</div>
);
}
}
19 changes: 15 additions & 4 deletions src/Modal/Modal.example.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import Modal from './Modal';
import Button from '../Button';
import Box from '../Box';
import Input from '../Form/Input';

export default class ModalDemo extends React.Component {
state = {
Expand Down Expand Up @@ -32,11 +32,22 @@ export default class ModalDemo extends React.Component {
<div>
<Button onClick={this.toggle}>Open Modal</Button>

<Modal open={this.state.isModalOpen} onClose={this.toggle} title="Example Modal" {...props}>
<Modal
open={this.state.isModalOpen}
onClose={this.toggle}
title="Example Modal"
{...props}>
<Modal.Body>
{body}
<>
{body}
<Input autoFocus name="password" label="Password" />
</>

<Modal open={this.state.isModalTwoOpen} onClose={this.toggleModalTwo} title="Example Modal Two" {...props}>
<Modal
open={this.state.isModalTwoOpen}
onClose={this.toggleModalTwo}
title="Example Modal Two"
{...props}>
<Modal.Body>{bodyTwo}</Modal.Body>

<Modal.Footer>
Expand Down
11 changes: 7 additions & 4 deletions src/Modal/Modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import { keyframes, css } from 'styled-components';
import * as animations from 'react-animations';
import { Transition } from 'react-transition-group';
import FocusLock from 'react-focus-lock';
import Portal from '../Portal';
import Flex from '../Flex';
import Box from '../Box';
Expand Down Expand Up @@ -105,10 +106,12 @@ function Modal({ children, title, animationDuration, showClose, onClose, open, .
<Transition in={isOpen} timeout={animationDuration}>
{state => (
<Backdrop transitionState={state} onClick={handleBackdropClick}>
<ModalContent transitionState={state} onClick={handleContentClick} {...props}>
{title && <Modal.Header title={title} showClose={showClose} />}
{children}
</ModalContent>
<FocusLock lockProps={{ style: { height: '100%' } }} disabled={!isOpen}>
<ModalContent transitionState={state} onClick={handleContentClick} {...props}>
{title && <Modal.Header title={title} showClose={showClose} />}
{children}
</ModalContent>
</FocusLock>
</Backdrop>
)}
</Transition>
Expand Down
13 changes: 11 additions & 2 deletions src/Modal/Modal.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ name: Modal
import { Playground, PropsTable } from 'docz'
import Modal from './Modal'
import ModalExample from './Modal.example'
import ModalDropdownExample from './Modal.dropdownexample'

# Modal

Expand All @@ -19,13 +20,21 @@ Modals are a great way to add dialogs to your site for lightboxes, user notifica
Toggle a working modal demo by clicking the button below. It will slide up and fade in from the bottom of the page.

<Playground>
<ModalExample body="I am an example modal that displays example content to prove that I can actually do some things" maxWidth={300} />
<ModalExample groupId={1} body="I am an example modal that displays example content to prove that I can actually do some things" maxWidth={300} />
cehsu marked this conversation as resolved.
Show resolved Hide resolved
</Playground>

## Handling Long Content

When modals become too long for the user’s viewport or device, they scroll independent of the page itself.

<Playground>
<ModalExample body={<div>{new Array(50).fill(null).map((_, i) => <p key={i}>I'm really long annoying content.</p>)}</div>} />
<ModalExample groupdId={2} body={<div>{new Array(50).fill(null).map((_, i) => <p key={i}>I'm really long annoying content.</p>)}</div>} />
cehsu marked this conversation as resolved.
Show resolved Hide resolved
</Playground>

## Handling Dropdown Triggered Content

When modals are triggered by dropdowns with returnFocus set to true, modals still receive focus.

<Playground>
<ModalDropdownExample groupdId={3} body="I'm triggered by a dropdown" />
</Playground>