Skip to content

Commit

Permalink
[added] Inline CSS for modal and overlay as well as props to override.
Browse files Browse the repository at this point in the history
[changed] injectCSS has been changed to a warning message in preperation for a future removal. lib/components/Modal.js
[changed] setAppElement method is now optional. Defaults to document.body and now allows for a css selector to be passed in rather than the whole element.
  • Loading branch information
Jack Morgan authored and jackofseattle committed Sep 17, 2015
1 parent acd3c65 commit 4d25989
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 89 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
examples/**/*-bundle.js
node_modules/
.idea/
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ examples
karma.conf.js
script
specs
.idea/
62 changes: 59 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,47 @@ Accessible modal dialog component for React.JS
isOpen={bool}
onRequestClose={fn}
closeTimeoutMS={n}
>
style={customStyle}>

<h1>Modal Content</h1>
<p>Etc.</p>
</Modal>
```
## Styles
Styles are passed as an object with 2 keys, 'overlay' and 'content' like so
```js
{
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.


## Examples
Inside an app:

```js
Expand All @@ -23,8 +58,28 @@ var Modal = require('react-modal');

var appElement = document.getElementById('your-app-element');

/*
By default the modal is anchored to document.body. All of the following overrides are available.
* element
Modal.setAppElement(appElement);
Modal.injectCSS();
* query selector - uses the first element found if you pass in a class.
Modal.setAppElement('#your-app-element');
*/

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


var App = React.createClass({

Expand All @@ -47,7 +102,8 @@ var App = React.createClass({
<Modal
isOpen={this.state.modalIsOpen}
onRequestClose={this.closeModal}
>
style={customStyles} >

<h2>Hello</h2>
<button onClick={this.closeModal}>close</button>
<div>I am a modal</div>
Expand Down
6 changes: 2 additions & 4 deletions examples/basic/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ var Modal = require('../../lib/index');

var appElement = document.getElementById('example');

Modal.setAppElement(appElement);
Modal.injectCSS();
Modal.setAppElement('#example');

var App = React.createClass({

Expand Down Expand Up @@ -37,8 +36,7 @@ var App = React.createClass({
<Modal
closeTimeoutMS={150}
isOpen={this.state.modalIsOpen}
onRequestClose={this.handleModalCloseRequest}
>
onRequestClose={this.handleModalCloseRequest}>
<h1>Hello</h1>
<button onClick={this.closeModal}>close</button>
<div>I am a modal</div>
Expand Down
1 change: 0 additions & 1 deletion examples/bootstrap/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ var Modal = require('../../lib/index');
var appElement = document.getElementById('example');

Modal.setAppElement(appElement);
Modal.injectCSS();

var App = React.createClass({

Expand Down
14 changes: 10 additions & 4 deletions lib/components/Modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,30 @@ var React = require('react');
var ExecutionEnvironment = require('react/lib/ExecutionEnvironment');
var ModalPortal = React.createFactory(require('./ModalPortal'));
var ariaAppHider = require('../helpers/ariaAppHider');
var injectCSS = require('../helpers/injectCSS');
var elementClass = require('element-class');

var SafeHTMLElement = ExecutionEnvironment.canUseDOM ? window.HTMLElement : {};

var Modal = module.exports = React.createClass({

displayName: 'Modal',

statics: {
setAppElement: ariaAppHider.setElement,
injectCSS: injectCSS
injectCSS : function() {
"production" !== process.env.NODE_ENV
&& console.warn('React-Modal: injectCSS has been deprecated ' +
'and no longer has any effect. It will be removed in a later version');
}
},

propTypes: {
isOpen: React.PropTypes.bool.isRequired,
onRequestClose: React.PropTypes.func,
style : React.PropTypes.shape({
content: React.PropTypes.object,
overlay: React.PropTypes.object
}),
appElement: React.PropTypes.instanceOf(SafeHTMLElement),
onRequestClose: React.PropTypes.func,
closeTimeoutMS: React.PropTypes.number,
ariaHideApp: React.PropTypes.bool
},
Expand Down
50 changes: 42 additions & 8 deletions lib/components/ModalPortal.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ var React = require('react');
var div = React.DOM.div;
var focusManager = require('../helpers/focusManager');
var scopeTab = require('../helpers/scopeTab');
var cx = require('classnames');
var Assign = require('lodash.assign');


// so that our CSS is statically analyzable
var CLASS_NAMES = {
Expand All @@ -18,7 +19,31 @@ var CLASS_NAMES = {
}
};

var OVERLAY_STYLES = { position: 'fixed', left: 0, right: 0, top: 0, bottom: 0 };
var defaultStyles = {
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'

}
};

function stopPropagation(event) {
event.stopPropagation();
Expand All @@ -28,6 +53,15 @@ var ModalPortal = module.exports = React.createClass({

displayName: 'ModalPortal',

getDefaultProps: function() {
return {
style: {
overlay : {},
content : {}
}
}
},

getInitialState: function() {
return {
afterOpen: false,
Expand Down Expand Up @@ -132,27 +166,27 @@ var ModalPortal = module.exports = React.createClass({
return !this.props.isOpen && !this.state.beforeClose;
},

buildClassName: function(which) {
buildClassName: function(which, additional) {
var className = CLASS_NAMES[which].base;
if (this.state.afterOpen)
className += ' '+CLASS_NAMES[which].afterOpen;
if (this.state.beforeClose)
className += ' '+CLASS_NAMES[which].beforeClose;
return className;
return additional ? className + ' ' + additional : className;
},

render: function() {
return this.shouldBeClosed() ? div() : (
div({
ref: "overlay",
className: cx(this.buildClassName('overlay'), this.props.overlayClassName),
style: OVERLAY_STYLES,
className: this.buildClassName('overlay', this.props.overlayClassName),
style: Assign({}, defaultStyles.overlay, this.props.style.overlay || {}),
onClick: this.handleOverlayClick
},
div({
ref: "content",
style: this.props.style,
className: cx(this.buildClassName('content'), this.props.className),
style: Assign({}, defaultStyles.content, this.props.style.content || {}),
className: this.buildClassName('content', this.props.className),
tabIndex: "-1",
onClick: stopPropagation,
onKeyDown: this.handleKeyDown
Expand Down
10 changes: 7 additions & 3 deletions lib/helpers/ariaAppHider.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
var _element = null;
var _element = document.body;

function setElement(element) {
_element = element;
if (typeof element === 'string') {
var el = document.querySelectorAll(element);
element = 'length' in el ? el[0] : el;
}
_element = element || _element;
}

function hide(appElement) {
Expand All @@ -27,7 +31,7 @@ function validateElement(appElement) {
}

function resetForTesting() {
_element = null;
_element = document.body;
}

exports.toggle = toggle;
Expand Down
48 changes: 0 additions & 48 deletions lib/helpers/injectCSS.js

This file was deleted.

9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-modal",
"version": "0.3.0",
"version": "0.4.0",
"description": "Accessible modal dialog component for React.JS",
"main": "./lib/index",
"repository": {
Expand Down Expand Up @@ -32,6 +32,7 @@
"karma-cli": "0.1.0",
"karma-firefox-launcher": "0.1.6",
"karma-mocha": "0.2.0",
"karma-safari-launcher": "^0.1.1",
"mocha": "2.2.5",
"react": ">=0.13.3",
"reactify": "^1.1.1",
Expand All @@ -40,8 +41,8 @@
"webpack-dev-server": "1.10.1"
},
"dependencies": {
"classnames": "^2.1.3",
"element-class": "^0.2.0"
"element-class": "^0.2.0",
"lodash.assign": "^3.2.0"
},
"peerDependencies": {
"react": ">=0.13.3"
Expand All @@ -60,4 +61,4 @@
"browserify-shim": {
"react": "global:React"
}
}
}
Loading

0 comments on commit 4d25989

Please sign in to comment.