Skip to content

Commit d34d738

Browse files
TheSharpieOneeddywashere
authored andcommitted
feat(breadcrumb): Add Breadcrumb and BreadcrumbItem
1 parent 1adcf67 commit d34d738

File tree

11 files changed

+231
-0
lines changed

11 files changed

+231
-0
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/* eslint react/no-multi-comp: 0, react/prop-types: 0 */
2+
import React from 'react';
3+
import { PrismCode } from 'react-prism';
4+
import Helmet from 'react-helmet';
5+
6+
import BreadcrumbExample from '../examples/Breadcrumb';
7+
const BreadcrumbExampleSource = require('!!raw!../examples/Breadcrumb.jsx');
8+
9+
import BreadcrumbNoListExample from '../examples/BreadcrumbNoList';
10+
const BreadcrumbNoListExampleSource = require('!!raw!../examples/BreadcrumbNoList.jsx');
11+
12+
export default class BreadcrumbsPage extends React.Component {
13+
render() {
14+
return (
15+
<div>
16+
<Helmet title="Breadcrumbs" />
17+
<h3>Breadcrumbs</h3>
18+
<div className="docs-example">
19+
<BreadcrumbExample />
20+
</div>
21+
<pre>
22+
<PrismCode className="language-jsx">
23+
{BreadcrumbExampleSource}
24+
</PrismCode>
25+
</pre>
26+
<h3>No list</h3>
27+
<hr />
28+
<p>Breadcrumbs can work without the usage of list markup.</p>
29+
<div className="docs-example">
30+
<BreadcrumbNoListExample />
31+
</div>
32+
<pre>
33+
<PrismCode className="language-jsx">
34+
{BreadcrumbNoListExampleSource}
35+
</PrismCode>
36+
</pre>
37+
</div>
38+
);
39+
}
40+
}

docs/lib/Components/index.jsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ class Components extends React.Component {
3939
name: 'Form',
4040
to: '/components/form/'
4141
},
42+
{
43+
name: 'Breadscrumbs',
44+
to: '/components/breadcrumbs/'
45+
},
4246
{
4347
name: 'Tags',
4448
to: '/components/tags/'

docs/lib/examples/Breadcrumb.jsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import React from 'react';
2+
import { Breadcrumb, BreadcrumbItem } from 'reactstrap';
3+
4+
const Example = (props) => {
5+
return (
6+
<div>
7+
<Breadcrumb>
8+
<BreadcrumbItem active>Home</BreadcrumbItem>
9+
</Breadcrumb>
10+
<Breadcrumb>
11+
<BreadcrumbItem><a href="#">Home</a></BreadcrumbItem>
12+
<BreadcrumbItem active>Library</BreadcrumbItem>
13+
</Breadcrumb>
14+
<Breadcrumb>
15+
<BreadcrumbItem><a href="#">Home</a></BreadcrumbItem>
16+
<BreadcrumbItem><a href="#">Library</a></BreadcrumbItem>
17+
<BreadcrumbItem active>Data</BreadcrumbItem>
18+
</Breadcrumb>
19+
</div>
20+
);
21+
};
22+
23+
export default Example;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import React from 'react';
2+
import { Breadcrumb, BreadcrumbItem } from 'reactstrap';
3+
4+
const Example = (props) => {
5+
return (
6+
<div>
7+
<Breadcrumb tag="nav">
8+
<BreadcrumbItem tag="a" href="#">Home</BreadcrumbItem>
9+
<BreadcrumbItem tag="a" href="#">Library</BreadcrumbItem>
10+
<BreadcrumbItem tag="a" href="#">Data</BreadcrumbItem>
11+
<BreadcrumbItem active tag="span">Bootstrap</BreadcrumbItem>
12+
</Breadcrumb>
13+
</div>
14+
);
15+
};
16+
17+
export default Example;

docs/lib/routes.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Home from './Home';
44
import LayoutPage from './Components/LayoutPage';
55
import NavsPage from './Components/NavsPage';
66
import NavbarPage from './Components/NavbarPage';
7+
import BreadcrumbsPage from './Components/BreadcrumbsPage';
78
import ButtonsPage from './Components/ButtonsPage';
89
import ButtonGroupPage from './Components/ButtonGroupPage';
910
import ButtonDropdownPage from './Components/ButtonDropdownPage';
@@ -24,6 +25,7 @@ const routes = (
2425
<IndexRoute component={ Home } />
2526
<Route path="/components/" component={Components}>
2627
<IndexRedirect to="buttons/" />
28+
<Route path="breadcrumbs/" component={ BreadcrumbsPage } />
2729
<Route path="buttons/" component={ ButtonsPage } />
2830
<Route path="button-group/" component={ ButtonGroupPage } />
2931
<Route path="button-dropdown/" component={ ButtonDropdownPage } />

src/Breadcrumb.jsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React, { PropTypes } from 'react';
2+
import classNames from 'classnames';
3+
4+
const propTypes = {
5+
tag: PropTypes.string,
6+
7+
className: PropTypes.any
8+
};
9+
10+
const defaultProps = {
11+
tag: 'ol'
12+
};
13+
14+
const Breadcrumb = (props) => {
15+
const {
16+
className,
17+
tag: Tag,
18+
...attributes
19+
} = props;
20+
const classes = classNames(
21+
className,
22+
'breadcrumb'
23+
);
24+
25+
return (
26+
<Tag {...attributes} className={classes} />
27+
);
28+
};
29+
30+
Breadcrumb.propTypes = propTypes;
31+
Breadcrumb.defaultProps = defaultProps;
32+
33+
export default Breadcrumb;

src/BreadcrumbItem.jsx

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import React, { PropTypes } from 'react';
2+
import classNames from 'classnames';
3+
4+
const propTypes = {
5+
tag: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
6+
active: PropTypes.string,
7+
className: PropTypes.any
8+
};
9+
10+
const defaultProps = {
11+
tag: 'li'
12+
};
13+
14+
const BreadcrumbItem = (props) => {
15+
const {
16+
className,
17+
active,
18+
tag: Tag,
19+
...attributes
20+
} = props;
21+
const classes = classNames(
22+
className,
23+
active ? 'active' : false,
24+
'breadcrumb-item'
25+
);
26+
27+
return (
28+
<Tag {...attributes} className={classes} />
29+
);
30+
};
31+
32+
BreadcrumbItem.propTypes = propTypes;
33+
BreadcrumbItem.defaultProps = defaultProps;
34+
35+
export default BreadcrumbItem;

src/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import Nav from './Nav';
88
import NavItem from './NavItem';
99
import NavDropdown from './NavDropdown';
1010
import NavLink from './NavLink';
11+
import Breadcrumb from './Breadcrumb';
12+
import BreadcrumbItem from './BreadcrumbItem';
1113
import Button from './Button';
1214
import ButtonDropdown from './ButtonDropdown';
1315
import ButtonGroup from './ButtonGroup';
@@ -60,6 +62,8 @@ export {
6062
NavItem,
6163
NavDropdown,
6264
NavLink,
65+
Breadcrumb,
66+
BreadcrumbItem,
6367
Button,
6468
ButtonDropdown,
6569
ButtonGroup,

test/Breadcrumb.spec.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* eslint react/no-multi-comp: 0, react/prop-types: 0 */
2+
import React from 'react';
3+
import { shallow } from 'enzyme';
4+
import { Breadcrumb } from 'reactstrap';
5+
6+
describe('Breadcrumb', () => {
7+
it('should render children', () => {
8+
const wrapper = shallow(<Breadcrumb>Yo!</Breadcrumb>);
9+
10+
expect(wrapper.text()).toBe('Yo!');
11+
});
12+
13+
it('should render "ol" by default', () => {
14+
const wrapper = shallow(<Breadcrumb>Yo!</Breadcrumb>);
15+
16+
expect(wrapper.type()).toBe('ol');
17+
});
18+
19+
it('should render with the "breadcrumb" class', () => {
20+
const wrapper = shallow(<Breadcrumb>Default Breadcrumb</Breadcrumb>);
21+
22+
expect(wrapper.hasClass('breadcrumb')).toBe(true);
23+
});
24+
25+
it('should render custom tag', () => {
26+
const wrapper = shallow(<Breadcrumb tag="main">Yo!</Breadcrumb>);
27+
28+
expect(wrapper.type()).toBe('main');
29+
});
30+
});

test/BreadcrumbList.spec.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/* eslint react/no-multi-comp: 0, react/prop-types: 0 */
2+
import React from 'react';
3+
import { shallow } from 'enzyme';
4+
import { BreadcrumbItem } from 'reactstrap';
5+
6+
describe('BreadcrumbItem', () => {
7+
it('should render children', () => {
8+
const wrapper = shallow(<BreadcrumbItem>Yo!</BreadcrumbItem>);
9+
10+
expect(wrapper.text()).toBe('Yo!');
11+
});
12+
13+
it('should render "li" by default', () => {
14+
const wrapper = shallow(<BreadcrumbItem>Yo!</BreadcrumbItem>);
15+
16+
expect(wrapper.type()).toBe('li');
17+
});
18+
19+
it('should render with the "breadcrumb-item" class', () => {
20+
const wrapper = shallow(<BreadcrumbItem>Default BreadcrumbItem</BreadcrumbItem>);
21+
22+
expect(wrapper.hasClass('breadcrumb-item')).toBe(true);
23+
});
24+
25+
it('should not render with the "active" class by default', () => {
26+
const wrapper = shallow(<BreadcrumbItem>Default BreadcrumbItem</BreadcrumbItem>);
27+
28+
expect(wrapper.hasClass('active')).toBe(false);
29+
});
30+
31+
it('should render with the "active" class when the avtive prop is truthy', () => {
32+
const wrapper = shallow(<BreadcrumbItem active>Default BreadcrumbItem</BreadcrumbItem>);
33+
34+
expect(wrapper.hasClass('active')).toBe(true);
35+
});
36+
37+
it('should render custom tag', () => {
38+
const wrapper = shallow(<BreadcrumbItem tag="main">Yo!</BreadcrumbItem>);
39+
40+
expect(wrapper.type()).toBe('main');
41+
});
42+
});

0 commit comments

Comments
 (0)