Security News
PyPI Introduces Digital Attestations to Strengthen Python Package Security
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.
react-aria-modal
Advanced tools
A fully accessible and flexible React modal built according WAI-ARIA Authoring Practices
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:
role
of dialog
(or alertdialog
).aria-label
or aria-labelledby
.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?)
If you like this kind of module (accessible, flexible, unstyled) you should also check out these projects:
npm install react-aria-modal
dist/react-aria-modal.js
is the Babel-compiled file that you'll use.
Version 2+ is compatible with React >0.14.
Version 1+ is compatible with React 0.13.
Just provide the right props (see below) and pass the content of the modal as this component's child.
Look in demo/js/
for examples and view the demo, but here's a simple example:
const React = require('react');
const ReactDOM = require('react-dom');
const AriaModal = require('../../');
class DemoOne extends React.Component {
constructor(props) {
super(props);
this.state = {
modalActive: false
};
this.activateModal = this.activateModal.bind(this);
this.deactivateModal = this.deactivateModal.bind(this);
this.getApplicationNode = this.getApplicationNode.bind(this);
}
activateModal = () => {
this.setState({ modalActive: true });
};
deactivateModal = () => {
this.setState({ modalActive: false });
};
getApplicationNode = () => {
return document.getElementById('application');
};
render() {
const modal = this.state.modalActive
? <AriaModal
titleText="demo one"
onExit={this.deactivateModal}
initialFocus="#demo-one-deactivate"
getApplicationNode={this.getApplicationNode}
underlayStyle={{ paddingTop: '2em' }}
>
<div id="demo-one-modal" className="modal">
<div className="modal-body">
<p>
Here is a modal
{' '}
<a href="#">with</a>
{' '}
<a href="#">some</a>
{' '}
<a href="#">focusable</a>
{' '}
parts.
</p>
</div>
<footer className="modal-footer">
<button id="demo-one-deactivate" onClick={this.deactivateModal}>
deactivate modal
</button>
</footer>
</div>
</AriaModal>
: false;
return (
<div>
<button onClick={this.activateModal}>
activate modal
</button>
{modal}
</div>
);
}
}
ReactDOM.render(<DemoOne />, document.getElementById('demo-one'));
The modal can be activated in a couple of ways:
mounted
proptrue
as the mounted
propSimilarly, the modal can be deactivated in a couple of ways:
false
as the mounted
propPass your dialog element as the child. And that's it.
When the modal is mounted, you'll notice the following:
role
of dialog
(or alertdialog
) and an aria-label
or aria-labelledby
attribute.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).)Any data-*
or aria-*
props that you provide will be passed directly to the modal's container <div>
.
Type: Function
This function handles the state change of exiting (or deactivating) the modal.
It will be invoked when the user clicks outside the modal (if underlayClickExits={true}
, as is the default) or hits Escape (if escapeExits={true}
, as is the default).
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.
If you may omit this prop if you don't want clicks outside the modal or Escape to close it, so don't want to provide a function.
Type: DOM Node
Provide your main application node here (which the modal should render outside of), and when the modal is open this application node will receive the attribute aria-hidden="true"
. This can help screen readers understand what's going on.
This module can't guess your application node, so you have to provide this prop to get the full accessibility benefit.
Type: Function
Same as applicationNode
, but a function that returns the node instead of the node itself. This can be useful or necessary in a variety of situations, one of which is server-side React rendering. The function will not be called until after the component mounts, so it is safe to use browser globals and refer to DOM nodes within it (e.g. document.getElementById(..)
), without ruining your server-side rendering.
Type: Boolean
If true
, the modal will receive a role
of alertdialog
, instead of its default dialog
. The alertdialog
role should only be used when an alert, error, or warning occurs (more info).
Type: Boolean
, Default: true
By default, styles are applied inline to the dialog and underlay portions of the component. However, you can disable all inline styles by setting includeDefaultStyles
to false
. If set, you must specify all styles externally, including positioning. This is helpful if your project uses external CSS assets.
Note: underlayStyle
and dialogStyle
can still be set inline, but these will be the only styles applied.
Type: String
Apply a class to the dialog in order to custom-style it.
Be aware that, by default, this module does apply various inline styles to the dialog element in order position it. To disable all inline styles, see includeDefaultStyles
.
Type: String
, Default: react-aria-modal-dialog
Choose your own id attribute for the dialog element.
Type: Object
Customize properties of the style
prop that is passed to the dialog.
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.
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;
.)
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>
);
},
});
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.
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.
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.
Type: object
Customize properties of the style
prop that is passed to the underlay.
The best way to add some vertical displacement to the dialog is to add top & bottom padding to the underlay. This is illustrated in the demo examples.
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. If you would rather control all CSS, see includeDefaultStyles
.
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.
Type: boolean
, Default: true
By default, the Escape key exits the modal. Pass false
, and it won't.
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
.
Type: boolean
If true
, the modal's contents will be vertically (as well as horizontally) centered.
Type: boolean
If true
, the modal dialog's focus trap will be paused.
You'll want to use this prop if you have another nested focus trap inside the modal.
react-aria-modal uses react-displace to insert the modal into a new element at the end of <body>
, making it easier to deal with positioning and z-indexes.
The static renderTo
function returns a new component that renders modals into a specific element, rather than a newly created element at the bottom of the page.
Strings are used as selectors, passed to querySelector
.
See demo six for an example.
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'
underlayClickExits={false}
verticallyCenter={true}
>
<div
style={{ outline: 0 }}
className='my-modal-dialog'
>
<h2 id='modal-title'>Alert!</h2>
..
</div>
</AriaModal>
)
}
})
Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
Lint with npm run lint
.
Test the demos with npm start
.
Build with npm build
.
2.8.0
onExit
is now optional. If omitted, clicking outside the modal or hitting escape will not attempt to call onExit
.FAQs
A fully accessible and flexible React modal built according WAI-ARIA Authoring Practices
The npm package react-aria-modal receives a total of 14,897 weekly downloads. As such, react-aria-modal popularity was classified as popular.
We found that react-aria-modal demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
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.
Security News
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.