Skip to content

Commit 6b50f7b

Browse files
committed
Merge pull request #58 from jackofseattle/fix/NoMoreInjectCSS
Inline Styles, optional setElement calls,
2 parents acd3c65 + 4d25989 commit 6b50f7b

File tree

11 files changed

+148
-89
lines changed

11 files changed

+148
-89
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
examples/**/*-bundle.js
22
node_modules/
3+
.idea/

.npmignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ examples
44
karma.conf.js
55
script
66
specs
7+
.idea/

README.md

+59-3
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,47 @@ Accessible modal dialog component for React.JS
99
isOpen={bool}
1010
onRequestClose={fn}
1111
closeTimeoutMS={n}
12-
>
12+
style={customStyle}>
13+
1314
<h1>Modal Content</h1>
1415
<p>Etc.</p>
1516
</Modal>
1617
```
18+
## Styles
19+
Styles are passed as an object with 2 keys, 'overlay' and 'content' like so
20+
```js
21+
{
22+
overlay : {
23+
position : 'fixed',
24+
top : 0,
25+
left : 0,
26+
right : 0,
27+
bottom : 0,
28+
backgroundColor : 'rgba(255, 255, 255, 0.75)'
29+
},
30+
content : {
31+
position : 'absolute',
32+
top : '40px',
33+
left : '40px',
34+
right : '40px',
35+
bottom : '40px',
36+
border : '1px solid #ccc',
37+
background : '#fff',
38+
overflow : 'auto',
39+
WebkitOverflowScrolling : 'touch',
40+
borderRadius : '4px',
41+
outline : 'none',
42+
padding : '20px'
43+
44+
}
45+
}
46+
```
47+
48+
Styles passed to the modal are merged in with the above defaults and applied to their respective elements.
49+
At this time, media queries will need to be handled by the consumer.
50+
1751

52+
## Examples
1853
Inside an app:
1954

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

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

61+
/*
62+
By default the modal is anchored to document.body. All of the following overrides are available.
63+
64+
* element
2665
Modal.setAppElement(appElement);
27-
Modal.injectCSS();
66+
67+
* query selector - uses the first element found if you pass in a class.
68+
Modal.setAppElement('#your-app-element');
69+
70+
*/
71+
72+
const customStyles = {
73+
content : {
74+
top : '50%',
75+
left : '50%',
76+
right : 'auto',
77+
bottom : 'auto',
78+
marginRight : '-50%',
79+
transform : 'translate(-50%, -50%)'
80+
}
81+
};
82+
2883

2984
var App = React.createClass({
3085

@@ -47,7 +102,8 @@ var App = React.createClass({
47102
<Modal
48103
isOpen={this.state.modalIsOpen}
49104
onRequestClose={this.closeModal}
50-
>
105+
style={customStyles} >
106+
51107
<h2>Hello</h2>
52108
<button onClick={this.closeModal}>close</button>
53109
<div>I am a modal</div>

examples/basic/app.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ var Modal = require('../../lib/index');
33

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

6-
Modal.setAppElement(appElement);
7-
Modal.injectCSS();
6+
Modal.setAppElement('#example');
87

98
var App = React.createClass({
109

@@ -37,8 +36,7 @@ var App = React.createClass({
3736
<Modal
3837
closeTimeoutMS={150}
3938
isOpen={this.state.modalIsOpen}
40-
onRequestClose={this.handleModalCloseRequest}
41-
>
39+
onRequestClose={this.handleModalCloseRequest}>
4240
<h1>Hello</h1>
4341
<button onClick={this.closeModal}>close</button>
4442
<div>I am a modal</div>

examples/bootstrap/app.js

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ var Modal = require('../../lib/index');
44
var appElement = document.getElementById('example');
55

66
Modal.setAppElement(appElement);
7-
Modal.injectCSS();
87

98
var App = React.createClass({
109

lib/components/Modal.js

+10-4
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,30 @@ var React = require('react');
22
var ExecutionEnvironment = require('react/lib/ExecutionEnvironment');
33
var ModalPortal = React.createFactory(require('./ModalPortal'));
44
var ariaAppHider = require('../helpers/ariaAppHider');
5-
var injectCSS = require('../helpers/injectCSS');
65
var elementClass = require('element-class');
76

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

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

1211
displayName: 'Modal',
13-
1412
statics: {
1513
setAppElement: ariaAppHider.setElement,
16-
injectCSS: injectCSS
14+
injectCSS : function() {
15+
"production" !== process.env.NODE_ENV
16+
&& console.warn('React-Modal: injectCSS has been deprecated ' +
17+
'and no longer has any effect. It will be removed in a later version');
18+
}
1719
},
1820

1921
propTypes: {
2022
isOpen: React.PropTypes.bool.isRequired,
21-
onRequestClose: React.PropTypes.func,
23+
style : React.PropTypes.shape({
24+
content: React.PropTypes.object,
25+
overlay: React.PropTypes.object
26+
}),
2227
appElement: React.PropTypes.instanceOf(SafeHTMLElement),
28+
onRequestClose: React.PropTypes.func,
2329
closeTimeoutMS: React.PropTypes.number,
2430
ariaHideApp: React.PropTypes.bool
2531
},

lib/components/ModalPortal.js

+42-8
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ var React = require('react');
22
var div = React.DOM.div;
33
var focusManager = require('../helpers/focusManager');
44
var scopeTab = require('../helpers/scopeTab');
5-
var cx = require('classnames');
5+
var Assign = require('lodash.assign');
6+
67

78
// so that our CSS is statically analyzable
89
var CLASS_NAMES = {
@@ -18,7 +19,31 @@ var CLASS_NAMES = {
1819
}
1920
};
2021

21-
var OVERLAY_STYLES = { position: 'fixed', left: 0, right: 0, top: 0, bottom: 0 };
22+
var defaultStyles = {
23+
overlay : {
24+
position : 'fixed',
25+
top : 0,
26+
left : 0,
27+
right : 0,
28+
bottom : 0,
29+
backgroundColor : 'rgba(255, 255, 255, 0.75)'
30+
},
31+
content : {
32+
position : 'absolute',
33+
top : '40px',
34+
left : '40px',
35+
right : '40px',
36+
bottom : '40px',
37+
border : '1px solid #ccc',
38+
background : '#fff',
39+
overflow : 'auto',
40+
WebkitOverflowScrolling : 'touch',
41+
borderRadius : '4px',
42+
outline : 'none',
43+
padding : '20px'
44+
45+
}
46+
};
2247

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

2954
displayName: 'ModalPortal',
3055

56+
getDefaultProps: function() {
57+
return {
58+
style: {
59+
overlay : {},
60+
content : {}
61+
}
62+
}
63+
},
64+
3165
getInitialState: function() {
3266
return {
3367
afterOpen: false,
@@ -132,27 +166,27 @@ var ModalPortal = module.exports = React.createClass({
132166
return !this.props.isOpen && !this.state.beforeClose;
133167
},
134168

135-
buildClassName: function(which) {
169+
buildClassName: function(which, additional) {
136170
var className = CLASS_NAMES[which].base;
137171
if (this.state.afterOpen)
138172
className += ' '+CLASS_NAMES[which].afterOpen;
139173
if (this.state.beforeClose)
140174
className += ' '+CLASS_NAMES[which].beforeClose;
141-
return className;
175+
return additional ? className + ' ' + additional : className;
142176
},
143177

144178
render: function() {
145179
return this.shouldBeClosed() ? div() : (
146180
div({
147181
ref: "overlay",
148-
className: cx(this.buildClassName('overlay'), this.props.overlayClassName),
149-
style: OVERLAY_STYLES,
182+
className: this.buildClassName('overlay', this.props.overlayClassName),
183+
style: Assign({}, defaultStyles.overlay, this.props.style.overlay || {}),
150184
onClick: this.handleOverlayClick
151185
},
152186
div({
153187
ref: "content",
154-
style: this.props.style,
155-
className: cx(this.buildClassName('content'), this.props.className),
188+
style: Assign({}, defaultStyles.content, this.props.style.content || {}),
189+
className: this.buildClassName('content', this.props.className),
156190
tabIndex: "-1",
157191
onClick: stopPropagation,
158192
onKeyDown: this.handleKeyDown

lib/helpers/ariaAppHider.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
var _element = null;
1+
var _element = document.body;
22

33
function setElement(element) {
4-
_element = element;
4+
if (typeof element === 'string') {
5+
var el = document.querySelectorAll(element);
6+
element = 'length' in el ? el[0] : el;
7+
}
8+
_element = element || _element;
59
}
610

711
function hide(appElement) {
@@ -27,7 +31,7 @@ function validateElement(appElement) {
2731
}
2832

2933
function resetForTesting() {
30-
_element = null;
34+
_element = document.body;
3135
}
3236

3337
exports.toggle = toggle;

lib/helpers/injectCSS.js

-48
This file was deleted.

package.json

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-modal",
3-
"version": "0.3.0",
3+
"version": "0.4.0",
44
"description": "Accessible modal dialog component for React.JS",
55
"main": "./lib/index",
66
"repository": {
@@ -32,6 +32,7 @@
3232
"karma-cli": "0.1.0",
3333
"karma-firefox-launcher": "0.1.6",
3434
"karma-mocha": "0.2.0",
35+
"karma-safari-launcher": "^0.1.1",
3536
"mocha": "2.2.5",
3637
"react": ">=0.13.3",
3738
"reactify": "^1.1.1",
@@ -40,8 +41,8 @@
4041
"webpack-dev-server": "1.10.1"
4142
},
4243
"dependencies": {
43-
"classnames": "^2.1.3",
44-
"element-class": "^0.2.0"
44+
"element-class": "^0.2.0",
45+
"lodash.assign": "^3.2.0"
4546
},
4647
"peerDependencies": {
4748
"react": ">=0.13.3"
@@ -60,4 +61,4 @@
6061
"browserify-shim": {
6162
"react": "global:React"
6263
}
63-
}
64+
}

0 commit comments

Comments
 (0)