Skip to content
This repository was archived by the owner on Apr 5, 2022. It is now read-only.

Commit 5abfacf

Browse files
authored
Added Sidebar component (#5)
* Added Sidebar component Added .editorconfig file
1 parent a33bd10 commit 5abfacf

5 files changed

Lines changed: 172 additions & 0 deletions

File tree

.editorconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# http://editorconfig.org
2+
3+
root = true
4+
5+
[*]
6+
charset = utf-8
7+
end_of_line = lf
8+
insert_final_newline = true
9+
trim_trailing_whitespace = true
10+
11+
[*.{js,jsx,json,css}]
12+
indent_style = space
13+
indent_size = 2

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
},
2020
"dependencies": {
2121
"bootstrap": "^3.3.6",
22+
"classnames": "^2.2.5",
2223
"ramda": "^0.19.1"
2324
},
2425
"devDependencies": {

src/components/Sidebar.css

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
.side-nav {
2+
background: #343637;
3+
bottom: 0;
4+
color: #ddd;
5+
font-size: 14px;
6+
left: 0;
7+
position: fixed;
8+
top:60px;
9+
width: 185px;
10+
}
11+
12+
.side-nav a {
13+
color: #ddd;
14+
}
15+
.side-nav a:hover {
16+
text-decoration: none;
17+
}
18+
19+
.side-nav button {
20+
background-color: transparent;
21+
border: none;
22+
color: #ddd;
23+
cursor: pointer;
24+
margin: 0;
25+
outline: 0;
26+
padding: 10px 15px;
27+
text-align: left;
28+
width: 100%;
29+
font-size: 13px;
30+
}
31+
32+
.side-nav button.indent {
33+
padding-left: 50px;
34+
}
35+
36+
.side-nav button.toplevel {
37+
padding-left: 35px;
38+
}
39+
40+
.side-nav button:hover {
41+
background: rgba(0,0,0,.2);
42+
color: #f0f0f0;
43+
}
44+
.side-nav .active-link button {
45+
/* color: #00AF66; */
46+
color: #FFF;
47+
}
48+
49+
.side-nav button .fa {
50+
padding-right: 5px;
51+
}
52+
53+
.collapse {
54+
display:none;
55+
}
56+

src/components/Sidebar.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import classNames from 'classnames';
2+
import React, { PropTypes } from 'react';
3+
import './Sidebar.css';
4+
5+
export const NavItem = ({ label, grouped = false, expanded = false, linkTo }) => {
6+
const classes = classNames({
7+
indent: grouped,
8+
collapse: grouped && !expanded,
9+
toplevel: !grouped,
10+
});
11+
return (
12+
<div className="nav-item">
13+
<button className={classes}>
14+
{label}
15+
</button>
16+
</div>
17+
);
18+
};
19+
20+
21+
export const NavGroup = ({ label, open, children, onNavGroupClick }) => {
22+
const arrowClasses = 'fa fa-fw fa-caret-' + (open? 'down' : 'right');
23+
let navOptions;
24+
if (open) {
25+
navOptions = children;
26+
}
27+
28+
return (
29+
<div className="nav-group">
30+
<button onClick={onNavGroupClick}>
31+
<i className={arrowClasses}></i>
32+
{label}
33+
</button>
34+
{navOptions}
35+
</div>
36+
);
37+
};
38+
39+
NavGroup.propTypes = {
40+
open: PropTypes.bool,
41+
};
42+
43+
export const Sidebar = ({ children }) => {
44+
return (
45+
<div className="side-nav">
46+
{ children }
47+
</div>
48+
);
49+
};
50+

test/components/SidebarTest.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import React from 'react';
2+
import { shallow } from 'enzyme';
3+
import { equal, ok } from 'assert';
4+
import { Sidebar, NavGroup, NavItem } from '../../src/components/Sidebar';
5+
6+
describe('Sidebar', () => {
7+
it('should render Sidebar wrapper', () => {
8+
const shallowWrapper = shallow(<Sidebar/>);
9+
equal(shallowWrapper.hasClass('side-nav'), true);
10+
});
11+
describe('NavGroup', () => {
12+
let shallowWrapper, hasBeenClicked, navItem;
13+
describe('without dropdown', () => {
14+
const clickDummy = () => { hasBeenClicked = true; };
15+
beforeEach(() => {
16+
hasBeenClicked = false;
17+
shallowWrapper = shallow(<NavGroup label="something" onNavGroupClick={clickDummy}></NavGroup>);
18+
});
19+
it('should render NavGroup', () => {
20+
equal(shallowWrapper.hasClass('nav-group'), true);
21+
});
22+
it('should handle an onClick function', () => {
23+
shallowWrapper.find('button').simulate('click');
24+
ok(hasBeenClicked);
25+
});
26+
});
27+
describe('with dropdown', () => {
28+
beforeEach(() => {
29+
hasBeenClicked = false;
30+
navItem = <NavItem label="something"/>;
31+
shallowWrapper = shallow(<NavGroup label="something" open={true}>{navItem}</NavGroup>);
32+
});
33+
it('should render internal NavItem', () => {
34+
equal(shallowWrapper.contains(navItem), true);
35+
});
36+
});
37+
describe('should render no children if open prop passed in is false', () => {
38+
beforeEach(() => {
39+
navItem = <NavItem label="something"/>;
40+
shallowWrapper = shallow(<NavGroup label="something" open={false}>{navItem}</NavGroup>);
41+
});
42+
it('should render internal NavItem', () => {
43+
equal(shallowWrapper.contains(navItem), false);
44+
});
45+
});
46+
});
47+
it('should render NavItem independent of NavGroup', () => {
48+
const shallowWrapper = shallow(<NavItem label="something" />);
49+
equal(shallowWrapper.hasClass('nav-item'), true);
50+
});
51+
});
52+

0 commit comments

Comments
 (0)