Skip to content

Commit 7707007

Browse files
committed
first commit
0 parents  commit 7707007

File tree

18 files changed

+744
-0
lines changed

18 files changed

+744
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules/

.npmignore

Whitespace-only changes.

.travis.yml

Whitespace-only changes.

CHANGELOG.md

Whitespace-only changes.

README.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# react-tray
2+
3+
An accessible tray component useful for navigation menus
4+
See example at [http://instructure-react.github.io/react-tray](http://instructure-react.github.io/react-tray)
5+
6+
## Usage
7+
8+
```js
9+
var React = require('react');
10+
var Tray = require('react-tray');
11+
12+
var App = React.createClass({
13+
getInitialState: function () {
14+
return {
15+
isTrayOpen: false
16+
};
17+
},
18+
19+
openTray: function () {
20+
this.setState({
21+
isTrayOpen: true
22+
});
23+
},
24+
25+
closeTray: function () {
26+
this.setState({
27+
isTrayOpen: false
28+
});
29+
},
30+
31+
32+
render: function () {
33+
return (
34+
<div>
35+
<ul role="menu" className="navigation">
36+
<li role="menuitem">
37+
<a tabIndex={0}
38+
role="button"
39+
aria-haspopup={true}
40+
onClick={this.handleNavClick}>Menu</a>
41+
</li>
42+
</ul>
43+
<Tray isOpen={this.state.isTrayOpen}
44+
onBlur={this.closeTray}
45+
closeTimeoutMS={150}
46+
>
47+
<h1>Tray Content</h1>
48+
<div>Learn to drive and everything.</div>
49+
</Tray>
50+
</div>
51+
);
52+
}
53+
});
54+
55+
React.render(<App/>, document.getElementById('content'));
56+
```
57+

examples/basic/app.js

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/** @jsx React.DOM */
2+
var React = require('react');
3+
var Tray = require('../../lib/main');
4+
5+
function cx(map) {
6+
var className = [];
7+
Object.keys(map).forEach(function (key) {
8+
if (map[key]) {
9+
className.push(key);
10+
}
11+
});
12+
return className.join(' ');
13+
}
14+
15+
var App = React.createClass({
16+
getInitialState: function () {
17+
return {
18+
orientation: 'left',
19+
isTrayOpen: false
20+
};
21+
},
22+
23+
handleNavClick: function (e) {
24+
var type = e.target.getAttribute('data-type');
25+
this.openTray(type);
26+
},
27+
28+
handleNavKeyPress: function (e) {
29+
if (e.which === 13 || e.which === 32) {
30+
var type = e.target.getAttribute('data-type');
31+
this.openTray(type);
32+
}
33+
},
34+
35+
handleOrientationChange: function (e) {
36+
this.setState({
37+
orientation: e.target.value
38+
});
39+
},
40+
41+
openTray: function (type) {
42+
this.setState({
43+
type: type,
44+
isTrayOpen: true
45+
});
46+
},
47+
48+
closeTray: function () {
49+
this.setState({
50+
isTrayOpen: false
51+
}, function () {
52+
setTimeout(function () {
53+
this.setState({
54+
type: null
55+
});
56+
}.bind(this), 150);
57+
});
58+
},
59+
60+
renderTrayContent: function () {
61+
switch (this.state.type) {
62+
case 'foo':
63+
return (
64+
<div>
65+
<h2>Foo</h2>
66+
<div>Content for foo</div>
67+
<nav role="navigation">
68+
<div><a href="javascript://">A</a></div>
69+
<div><a href="javascript://">B</a></div>
70+
<div><a href="javascript://">C</a></div>
71+
</nav>
72+
</div>
73+
);
74+
break;
75+
case 'bar':
76+
return (
77+
<div>
78+
<h2>Bar</h2>
79+
<div>Lorem Ipsum</div>
80+
<nav role="navigation">
81+
<div><a href="javascript://">A</a></div>
82+
<div><a href="javascript://">B</a></div>
83+
<div><a href="javascript://">C</a></div>
84+
</nav>
85+
</div>
86+
);
87+
break;
88+
case 'baz':
89+
return (
90+
<div>
91+
<h2>Baz</h2>
92+
<div>Other stuff here</div>
93+
<nav role="navigation">
94+
<div><a href="javascript://">A</a></div>
95+
<div><a href="javascript://">B</a></div>
96+
<div><a href="javascript://">C</a></div>
97+
</nav>
98+
</div>
99+
);
100+
break;
101+
default:
102+
return (
103+
<h1>You shouldn't see me</h1>
104+
);
105+
}
106+
},
107+
108+
render: function () {
109+
return (
110+
<div>
111+
<ul role="menu" className={cx({
112+
'navigation': true,
113+
'navigation-left': this.state.orientation === 'left',
114+
'navigation-right': this.state.orientation === 'right'
115+
})}
116+
>
117+
<li role="menuitem"
118+
className={cx({ active: this.state.type === 'foo' })}
119+
>
120+
<a tabIndex={0}
121+
role="button"
122+
aria-haspopup={true}
123+
data-type="foo"
124+
onKeyPress={this.handleNavKeyPress}
125+
onClick={this.handleNavClick}>Foo</a>
126+
</li>
127+
<li role="menuitem"
128+
className={cx({ active: this.state.type === 'bar' })}
129+
>
130+
<a tabIndex={0}
131+
role="button"
132+
aria-haspopup={true}
133+
data-type="bar"
134+
onKeyPress={this.handleNavKeyPress}
135+
onClick={this.handleNavClick}>Bar</a>
136+
</li>
137+
<li role="menuitem"
138+
className={cx({ active: this.state.type === 'baz' })}
139+
>
140+
<a tabIndex={0}
141+
role="button"
142+
aria-haspopup={true}
143+
data-type="baz"
144+
onKeyPress={this.handleNavKeyPress}
145+
onClick={this.handleNavClick}>Baz</a>
146+
</li>
147+
</ul>
148+
<Tray isOpen={this.state.isTrayOpen}
149+
onBlur={this.closeTray}
150+
closeTimeoutMS={150}
151+
className={cx({
152+
'tray-left': this.state.orientation === 'left',
153+
'tray-right': this.state.orientation === 'right'
154+
})}
155+
>
156+
{this.renderTrayContent()}
157+
</Tray>
158+
<div className="content">
159+
<select onChange={this.handleOrientationChange}>
160+
<option value="left">Left</option>
161+
<option value="right">Right</option>
162+
</select>
163+
</div>
164+
</div>
165+
);
166+
}
167+
});
168+
169+
React.render(<App/>, document.getElementById('example'));

examples/basic/index.html

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<!doctype html>
2+
<meta charset="utf-8"/>
3+
<title>React Tray</title>
4+
<link rel="stylesheet" href="http://instructure-react.github.io/library/shared.css"/>
5+
<style type="text/css">
6+
/* Tray styles */
7+
.ReactTray__Overlay {
8+
background: rgba(0, 0, 0, 0.65);
9+
}
10+
11+
.ReactTray__Content {
12+
top: 212px;
13+
bottom: 0;
14+
padding: 10px;
15+
width: 250px;
16+
box-shadow: 1px 0 5px #333;
17+
width: 0;
18+
overflow-x: hidden;
19+
white-space: nowrap;
20+
}
21+
22+
.ReactTray__Content--after-open {
23+
width: 250px;
24+
transition: width 150ms ease-out;
25+
}
26+
27+
.ReactTray__Content--before-close {
28+
width: 0;
29+
transition: width 150ms ease-in;
30+
}
31+
32+
/* App specific styles */
33+
.navigation {
34+
position: absolute;
35+
top: 212px;
36+
bottom: 0;
37+
width: 50px;
38+
background: rgb(52, 69, 81);
39+
color: rgb(235, 235, 235);
40+
margin: 0;
41+
padding: 0;
42+
z-index: 100;
43+
}
44+
.navigation ul {
45+
padding: 0;
46+
margin: 0;
47+
}
48+
.navigation li {
49+
padding: 20px 10px;
50+
list-style: none;
51+
}
52+
.navigation li.active {
53+
background: #fff;
54+
color: rgb(21, 148, 218);
55+
}
56+
.navigation a {
57+
cursor: pointer;
58+
}
59+
60+
.content {
61+
margin: 150px auto;
62+
width: 100px;
63+
}
64+
65+
.ReactTray__Content h2 {
66+
color: rgb(60, 78, 91);
67+
border-bottom: 1px solid rgb(229, 229, 229);
68+
margin: 0;
69+
margin-bottom: 10px;
70+
padding: 10px 5px;
71+
}
72+
73+
.navigation-left { left: 0; }
74+
.navigation-right { right: 0; }
75+
.tray-left {
76+
border-right: 1px solid #333;
77+
left: 50px;
78+
}
79+
.tray-right {
80+
border-left: 1px solid #333;
81+
right: 50px;
82+
}
83+
</style>
84+
<body>
85+
<header class="branding padbox">
86+
<h1>react-tray</h1>
87+
<h2>React tray component</h2>
88+
</header>
89+
<div id="example" class="padbox"></div>
90+
<a target="_blank" href="https://github.com/instructure-react/react-tray"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://github-camo.global.ssl.fastly.net/a6677b08c955af8400f44c6298f40e7d19cc5b2d/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f677261795f3664366436642e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png"></a>
91+
<script src="../__build__/shared.js"></script>
92+
<script src="../__build__/basic.js"></script>

lib/components/Tray.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
var React = require('react');
2+
var TrayPortal = React.createFactory(require('./TrayPortal'));
3+
4+
var Tray = React.createClass({
5+
displayName: 'Tray',
6+
7+
propTypes: {
8+
isOpen: React.PropTypes.bool,
9+
onBlur: React.PropTypes.func,
10+
closeTimeoutMS: React.PropTypes.number
11+
},
12+
13+
getDefaultProps: function () {
14+
return {
15+
isOpen: false,
16+
closeTimeoutMS: 0
17+
};
18+
},
19+
20+
componentDidMount: function () {
21+
this.node = document.createElement('div');
22+
this.node.className = 'ReactTrayPortal';
23+
document.body.appendChild(this.node);
24+
this.renderPortal(this.props);
25+
},
26+
27+
componentWillReceiveProps: function (props) {
28+
this.renderPortal(props);
29+
},
30+
31+
componentWillUnmount: function () {
32+
React.unmountComponentAtNode(this.node);
33+
document.body.removeChild(this.node);
34+
},
35+
36+
renderPortal: function (props) {
37+
delete props.ref;
38+
39+
if (this.portal) {
40+
this.portal.setProps(props);
41+
} else {
42+
this.portal = React.render(TrayPortal(props), this.node);
43+
}
44+
},
45+
46+
render: function () {
47+
return null;
48+
}
49+
});
50+
51+
module.exports = Tray;

0 commit comments

Comments
 (0)