react-modal 0,0,2,6,0,3 travis-ci Bower karma npm webpack

Accessible modal dialog component for React

2 years after MIT

react-modal

Accessible modal dialog component for React.JS

Code Climate Coverage Status gzip size

Build Status

Active Development

The modal is currently undergoing significant development for a v2 release. The master branch contains that development work. If you'd like to see the latest stable version please use the release tags (https://github.com/reactjs/react-modal/releases)

Installation

To install the stable version:

npm install --save react-modal

Usage

The Modal object has two required props:

  • isOpen to render its children.
  • contentLabel to improve a11y, since v1.6.0.

Example:

<Modal
  isOpen={bool}
  onAfterOpen={afterOpenFn}
  onRequestClose={requestCloseFn}
  closeTimeoutMS={n}
  style={customStyle}
  contentLabel="Modal"
>
  <h1>Modal Content</h1>
  <p>Etc.</p>
</Modal>

Styles

Styles are passed as an object with 2 keys, 'overlay' and 'content' like so

{
  overlay : {
    position          : 'fixed',
    top               : 0,
    left              : 0,
    right             : 0,
    bottom            : 0,
    backgroundColor   : 'rgba(255, 255, 255, 0.75)'
  },
  content : {
    position                   : 'absolute',
    top                        : '40px',
    left                       : '40px',
    right                      : '40px',
    bottom                     : '40px',
    border                     : '1px solid #ccc',
    background                 : '#fff',
    overflow                   : 'auto',
    WebkitOverflowScrolling    : 'touch',
    borderRadius               : '4px',
    outline                    : 'none',
    padding                    : '20px'

  }
}

Styles passed to the modal are merged in with the above defaults and applied to their respective elements. At this time, media queries will need to be handled by the consumer.

Using CSS Classes

If you prefer not to use inline styles or are unable to do so in your project, you can pass className and overlayClassName props to the Modal. If you do this then none of the default styles will apply and you will have full control over styling via CSS.

If you want to override default content and overlay classes you can pass object with three required properties: base, afterOpen, beforeClose.

<Modal
  ...
  className={{
    base: 'myClass',
    afterOpen: 'myClass_after-open',
    beforeClose: 'myClass_before-close'
  }}
  overlayClassName={{
    base: 'myOverlayClass',
    afterOpen: 'myOverlayClass_after-open',
    beforeClose: 'myOverlayClass_before-close'
  }}
  ...
>

You can also pass a portalClassName to change the wrapper's class (ReactModalPortal). This doesn't affect styling as no styles are applied to this element by default.

Overriding styles globally

The default styles above are available on Modal.defaultStyles. Changes to this object will apply to all instances of the modal.

Appended to custom node

You can choose an element for the modal to be appended to, rather than using body tag. To do this, provide a function to parentSelector prop that return the element to be used.


function getParent() {
  return document.querySelector('#root');
}

<Modal
  ...
  parentSelector={getParent}
  ...
>
  <p>Modal Content.</p>
</Modal>

Body class

When the modal is opened a ReactModal__Body--open class is added to the body tag. You can use this to remove scrolling on the the body while the modal is open. You can also pass a bodyOpenClassName to change the default class.

/* Remove scroll on the body when react-modal is open */
.ReactModal__Body--open {
    overflow: hidden;
}

Examples

Inside an app:

import React from 'react';
import ReactDOM from 'react-dom';
import Modal from 'react-modal';

/*
The app element allows you to specify the portion of your app that should be hidden (via aria-hidden)
to prevent assistive technologies such as screenreaders from reading content outside of the content of
your modal.  It can be specified in the following ways:

* element
Modal.setAppElement(appElement);

* query selector - uses the first element found if you pass in a class.
Modal.setAppElement('#your-app-element');

*/
const appElement = document.getElementById('your-app-element');

const customStyles = {
  content : {
    top                   : '50%',
    left                  : '50%',
    right                 : 'auto',
    bottom                : 'auto',
    marginRight           : '-50%',
    transform             : 'translate(-50%, -50%)'
  }
};

class App extends React.Component {
  constructor() {
    super();

    this.state = {
      modalIsOpen: false
    };

    this.openModal = this.openModal.bind(this);
    this.afterOpenModal = this.afterOpenModal.bind(this);
    this.closeModal = this.closeModal.bind(this);
  }

  openModal() {
    this.setState({modalIsOpen: true});
  }

  afterOpenModal() {
    // references are now sync'd and can be accessed.
    this.subtitle.style.color = '#f00';
  }

  closeModal() {
    this.setState({modalIsOpen: false});
  }

  render() {
    return (
      <div>
        <button onClick={this.openModal}>Open Modal</button>
        <Modal
          isOpen={this.state.modalIsOpen}
          onAfterOpen={this.afterOpenModal}
          onRequestClose={this.closeModal}
          style={customStyles}
          contentLabel="Example Modal"
        >

          <h2 ref={subtitle => this.subtitle = subtitle}>Hello</h2>
          <button onClick={this.closeModal}>close</button>
          <div>I am a modal</div>
          <form>
            <input />
            <button>tab navigation</button>
            <button>stays</button>
            <button>inside</button>
            <button>the modal</button>
          </form>
        </Modal>
      </div>
    );
  }
}

ReactDOM.render(<App />, appElement);

Testing

When using React Test Utils with this library, here are some things to keep in mind:

  • You need to set isOpen={true} on the modal component for it to render its children.
  • You need to use the .portal property, as in ReactDOM.findDOMNode(renderedModal.portal) or TestUtils.scryRenderedDOMComponentsWithClass(Modal.portal, 'my-modal-class') to acquire a handle to the inner contents of your modal.

By default the modal will attempt to close when clicking outside of it (on the overlay area). Because the open and closed state of the modal should be controlled outside of the modal, you need to provide the onRequestClose function prop to actually set the state. If you want to prevent the overlay close behavior, you should pass the shouldCloseOnOverlayClick props as false.

<Modal
  isOpen={bool}
  onAfterOpen={afterOpenFn}
  onRequestClose={requestCloseFn}
  closeTimeoutMS={n}
  shouldCloseOnOverlayClick={false}
  style={customStyle}
  contentLabel="No Overlay Click Modal"
>

  <h1>Force Modal</h1>
  <p>Modal cannot be closed when clicking the overlay area</p>
  <button onClick={handleCloseFunc}>Close Modal...</button>
</Modal>

Demos

Related Repositories

awesome-react-components

awesome-react-components

Catalog of React Components & Libraries ...

react-tooltip

react-tooltip

react tooltip component ...

rodal

rodal

A React modal with animations. ...

react-modal-dialog

react-modal-dialog

A modal dialog for ReactJS ...

react-modal-box

react-modal-box

React Modal Box, is a simple dependency free and customizable React Component to ...


Top Contributors

mzabriskie claydiffrient ryanflorence evoyy diasbruno roth1002 amccloud dinodsaurus everdimension leoasis Leimi DelvarWorld basarat existentialism codegoblin conlanpatrek danielsiwiec davezuko doque dorsha djkirby arasmussen cavneb ewiner EvNaverniouk jasonblanchard knomedia flskif miracle2k mjackson

Dependencies

package version
exenv ^1.2.0
prop-types ^15.5.10
react-dom-factories ^1.0.0
dev babel-cli ^6.24.1
babel-core ^6.25.0
babel-eslint ^7.1.1
babel-loader ^6.2.4
babel-preset-es2015 ^6.24.1
babel-preset-react ^6.24.1
babel-preset-stage-2 ^6.24.1
codeclimate-test-reporter ^0.4.0
coveralls ^2.13.1
cross-env ^5.0.1
envify ^3.4.1
eslint ^3.19.0
eslint-config-airbnb ^15.0.1
eslint-plugin-import ^2.3.0
eslint-plugin-jsx-a11y ^5.0.3
eslint-plugin-react ^7.1.0
expect ^1.20.2
gitbook-cli ^2.3.0
istanbul-instrumenter-loader 0.2.0
karma ^1.3.0
karma-chrome-launcher 2.0.0
karma-cli 1.0.1
karma-coverage ^1.1.1
karma-firefox-launcher 1.0.0
karma-mocha ^1.3.0
karma-mocha-reporter ^2.2.1
karma-sourcemap-loader ^0.3.7
karma-webpack ^1.8.1
mocha 3.2.0
npm-run-all ^3.1.2
react ^15.6.1
react-dom ^15.6.1
rf-release 0.4.0
sinon next
uglify-js 2.4.24
webpack ^1.12.14
webpack-dev-server 1.11.0
peer react ^0.14.0 || ^15.0.0
react-dom ^0.14.0 || ^15.0.0

Releases

-   v1.4.0 zip tar
-   v1.3.0 zip tar
-   v1.2.1 zip tar
-   v1.2.0 zip tar
-   v1.1.2 zip tar
-   v1.1.1 zip tar
-   v1.1.0 zip tar
-   v1.0.0 zip tar
-   v0.6.1 zip tar
-   v0.6.0 zip tar
-   v0.5.0 zip tar
-   v0.3.0 zip tar
-   v0.2.0 zip tar
-   v0.1.1 zip tar
-   v0.1.0 zip tar
-   v0.0.7 zip tar
-   v0.0.6 zip tar
-   v0.0.5 zip tar
-   v0.0.4 zip tar
-   v0.0.3 zip tar
-   v0.0.2 zip tar
-   v0.0.1 zip tar
-   v0.0.0 zip tar