Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-aria-modal

Package Overview
Dependencies
Maintainers
1
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-aria-modal

A fully accessible and flexible React modal built according WAI-ARIA Authoring Practices

  • 1.0.1
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
19K
decreased by-19.68%
Maintainers
1
Weekly downloads
 
Created
Source

react-aria-modal

A fully accessible and flexible React modal built according WAI-ARIA Authoring Practices.

This module provides a "smart" minimally styled component to wrap you "dumb" fully styled component. It provides the following features, while giving you complete control of the content:

  • Focus is trapped within the modal: Tab and Shift+Tab will cycle through the modal's focusable nodes without returning to the main document beneath.
  • Escape will close the modal.
  • Scrolling is frozen on the main document beneath the modal. (Although, sadly, you can still mess with the scrolling using a touch screen.)
  • When the modal closes, focus returns to the element that was focused just before the modal activated.
  • The dialog element has an ARIA role of dialog (or alertdialog).
  • The dialog element has an ARIA attribute designating its title, either aria-label or aria-labelledby.
  • By default, clicking on the modal's underlay (outside the dialog element) will close the modal (this can be disabled).
  • The modal is appended to the end of document.body instead of its taking up its source-order position within the React component tree.

"Flexible" mostly means that this module provides absolutely minimal inline styles — just enough to get the thing working — but does not provide "complete" modal styling that would get in your way. You get to (have to) style the dialog yourself. (Maybe make a fancy-looking modal module that others could use, which depends on this one behind the scenes?)

Check out the demo.

Project Goals

  • Full accessibility
  • Maximum flexibility
  • Absolutely minimal styling
  • Modular construction: this module is built on top of a few small JS modules that could be used by other React and non-React frontend components:

If you like this kind of module (accessible, flexible, unstyled) you should also check out these projects:

Installation

npm install react-aria-modal

Usage

Just provide the right props (see below) and pass the content of the modal as this component's child.

Look in demo/js/ for example code. (And see what they look like here But here's a simple example.

var AriaModal = require('react-aria-modal');

var DemoOne = React.createClass({
  getInitialState: function() {
    return { modalActive: false };
  },

  activateModal: function() {
    this.setState({ modalActive: true });
  },

  deactivateModal: function() {
    this.setState({ modalActive: false });
  },

  render: function() {
    return (
      <div>
        <button onClick={this.activateModal}>
          activate modal
        </button>
        <AriaModal
          mounted={this.state.modalActive}
          titleText='demo one'
          onExit={this.deactivateModal}
          initialFocus='#demo-one-deactivate'
        >
          <div className='modal-dialog'>
            <p>
              Here is a modal.
            </p>
            <p>
              <button
                id='demo-one-deactivate'
                onClick={this.deactivateModal}
              >
                deactivate modal
              </button>
            </p>
          </div>
        </AriaModal>
      </div>
    )
  },
});

Details

The modal can be activated in a couple of ways:

  • mounting the component without an mounted prop
  • passing true as the mounted prop

Similarly, the modal can be deactivated in a couple of ways:

  • unmounting the component
  • passing false as the mounted prop

Pass your dialog element as the child. And that's it.

When the modal is mounted, you'll notice the following:

  • Focus is trapped: only elements within the modal will receive focus as you tab through. This is done by focus-trap, via focus-trap-react.
  • The modal has the ARIA attributes it needs: a role of dialog (or alertdialog) and an aria-label or aria-labelledby attribute.
  • The main document's scroll is frozen (except on touchscreens). This is done by no-scroll.
  • Your content is set atop a fixed-position underlay. You can control the appearance and behavior of this underlay in various ways (see below).
  • Your content is horizontally centered. You can also vertically center it, if you wish.
  • The modal is appended to document.body, not inserted directly into the HTML source order, as you might assume; but it should still update correctly. (This makes positioning easier (no weird nested z-index troubles).)

Props

onExit

Type: Function, required

This function needs to handles the state change of exiting (or deactivating) the modal.

Maybe it's just a wrapper around setState(); or maybe you use some more involved Flux-inspired state management — whatever the case, this module leaves the state management up to you instead of making assumptions. That also makes it easier to create your own "close modal" buttons; because you have the function that closes the modal right there, written by you, at your disposal.

alert

Type: Boolean

If true, the modal will receive a role of alertdialog, instead of its default dialog.

focusDialog

Type: Boolean

By default, when the modal activates its first focusable child will receive focus. However, if focusDialog is true, the dialog itself will receive initial focus — and that focus will be hidden. (This is essentially what Bootstrap does with their modal.)

See the example below.

initialFocus

Type: String

By default, when the modal activates its first focusable child will receive focus. If, instead, you want to identify a specific element that should receive initial focus, pass a selector string to this prop. (That selector is passed to document.querySelector() to find the DOM node.)

Demo example 3 and an additional example below illustrate a good method if you want no initial visible focus. (Add tabIndex='0' to the modal's content and give it outline: 0;.)

mounted

Type: Boolean

By default, the modal is active when mounted, deactivated when unmounted. However, you can also control its active/inactive state by changing its mounted property instead.

The following two examples are near-equivalents — the first mounts and unmounts, while the second changes the mounted prop:

var MyComponent = React.createClass({
  ..
  render: function() {
    ..
    var modal = (this.state.modalActive) ? (
      <AriaModal onExit={this.myExitHandler}>
        {modalContents}
      </AriaModal>
    ) : false;
    return <div>{modal}</div>;
  },
});

var MyComponentTakeTwo = React.createClass({
  ..
  render: function() {
    ..
    return (
      <div>
        <AriaModal
          mounted={this.state.modalActive}
          onExit={this.myExitHandler}
        >
          {modalContents}
        </AriaModal>
      </div>
    );
  },
});

onEnter

Type: Function

This function is called in the modal's componentDidMount() lifecycle method. You can use it to do whatever diverse and sundry things you feel like doing after the modal activates.

Demo Five, for example, uses it to modify class names and enable some CSS transitions.

titleId

Type: String

The id of the element that should be used as the modal's accessible title. This value is passed to the modal's aria-labelledby attribute.

You must use either titleId or titleText, but not both.

titleText

Type: String

A string to use as the modal's accessible title. This value is passed to the modal's aria-label attribute.

You must use either titleId or titleText, but not both.

underlayClass

Type: String

Apply a class to the underlay in order to custom-style it.

This module does apply various inline styles, though, so be aware that overriding some styles might be difficult. If, for example, you want to change the underlay's color, you should probably use the underlayColor prop instead of a class.

underlayClickExits

Type: Boolean, Default true

By default, a click on the underlay will exit the modal. Pass false, and clicking on the underlay will do nothing.

underlayColor

Type: String (color value) or false, Default: rgba(0,0,0,0.5)

If you want to change the underlay's color, you can do that with this prop.

If false, no background color will be applied with inline styles. Presumably you will apply then yourself via an underlayClass.

verticallyCenter

Type: Boolean

If true, the modal's contents will be vertically (as well as horizontally) centered.

More examples

An alert dialog that itself receives initial focus (but has no visible outline) and does not exit when the underlay is clicked, and is vertically centered:

var AriaModal = require('react-aria-modal');

var MyModal = React.createClass({
  ..
  render: function() {
    return (
      <AriaModal
        onExit={this.myExitHandler}
        alert={true}
        focusDialog={true}
        titleId='modal-title'
        underlayClickExists={false}
        verticallyCenter={true}
      >
        <div
          style={{ outline: 0 }}
          className='my-modal-dialog'
        >
          <h2 id='modal-title'>Alert!</h2>
          ..
        </div>
      </AriaModal>
    )
  }
})

Keywords

FAQs

Package last updated on 30 Aug 2015

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc