Skip to content

Commit

Permalink
[fixed] Breadcrumb and BreadcrumbItem components
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexKVal committed Sep 26, 2015
1 parent 3c710f9 commit 0348274
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 161 deletions.
2 changes: 1 addition & 1 deletion docs/examples/Breadcrumb.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const breadcrumbInstance = (
<BreadcrumbItem href="http://getbootstrap.com/components/#breadcrumbs">
Library
</BreadcrumbItem>
<BreadcrumbItem>
<BreadcrumbItem active>
Data
</BreadcrumbItem>
</Breadcrumb>
Expand Down
9 changes: 4 additions & 5 deletions docs/src/ComponentsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -544,15 +544,14 @@ const ComponentsPage = React.createClass({
{/* Breadcrumb */}
<div className="bs-docs-section">
<h1 className="page-header"><Anchor id="breadcrumbs">Breadcrumbs</Anchor> <small>Breadcrumb, BreadcrumbItems</small></h1>
<p>Breadcrumbs are used to indicate the current page's location. An <code>active</code> class is added to a <code>BreadcrumbItem</code> if there's no <code>href</code> property for it.</p>
<p>Breadcrumbs are used to indicate the current page's location. Add <code>active</code> attribute to active <code>BreadcrumbItem</code>.</p>
<p>Do not set both <code>active</code> and <code>href</code> attributes. <code>active</code> overrides <code>href</code> and <code>span</code> element is rendered instead of <code>a</code>.</p>

<h3><Anchor id="breadcrumbs-example">Breadcrumbs Example</Anchor></h3>
<ReactPlayground codeText={Samples.Breadcrumb} />

<h3><Anchor id="breadcrumbs-props">Props</Anchor></h3>

<h4><Anchor id="breadcrumbs-props-breadcrumb">Breadcrumb</Anchor></h4>
<PropTable component="Breadcrumb"/>
<p><code>Breadcrumb</code> component itself doesn't have any specific public properties</p>

<h4><Anchor id="breadcrumbs-props-breadcrumbItem">BreadcrumbItem</Anchor></h4>
<PropTable component="BreadcrumbItem"/>
Expand Down Expand Up @@ -964,7 +963,7 @@ const ComponentsPage = React.createClass({
<NavItem href="#progress" key={8}>Progress bars</NavItem>
<NavItem href="#navs" key={9}>Navs</NavItem>
<NavItem href="#navbars" key={10}>Navbars</NavItem>
<NavItem href="#breadcrumbs" key={29}>Breadcrumbs</NavItem>
<NavItem href="#breadcrumbs" key={30}>Breadcrumbs</NavItem>
<NavItem href="#tabs" key={11}>Tabs</NavItem>
<NavItem href="#pager" key={12}>Pager</NavItem>
<NavItem href="#pagination" key={13}>Pagination</NavItem>
Expand Down
24 changes: 13 additions & 11 deletions src/Breadcrumb.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import React, { cloneElement } from 'react';
import classNames from 'classnames';
import BootstrapMixin from './BootstrapMixin';
import ValidComponentChildren from './utils/ValidComponentChildren';

const Breadcrumb = React.createClass({
mixins: [BootstrapMixin],
propTypes: {
/**
* bootstrap className
* @private
*/
bsClass: React.PropTypes.string
},

getDefaultProps() {
return {
Expand All @@ -13,24 +18,21 @@ const Breadcrumb = React.createClass({
},

render() {
const classes = this.getBsClassSet();
const { className, ...props } = this.props;

return (
<ol {...props} role="navigation" aria-label="breadcrumbs" className={classNames(className, classes)}>
<ol
{...props}
role="navigation"
aria-label="breadcrumbs"
className={classNames(className, this.props.bsClass)}>
{ValidComponentChildren.map(this.props.children, this.renderBreadcrumbItem)}
</ol>
);
},

renderBreadcrumbItem(child, index) {
return cloneElement(
child,
{
key: child.key ? child.key : index,
navItem: true
}
);
return cloneElement( child, { key: child.key ? child.key : index } );
}
});

Expand Down
42 changes: 32 additions & 10 deletions src/BreadcrumbItem.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,39 @@
import React from 'react';
import classNames from 'classnames';
import BootstrapMixin from './BootstrapMixin';
import SafeAnchor from './SafeAnchor';
import warning from 'react/lib/warning';

const BreadcrumbItem = React.createClass({
mixins: [BootstrapMixin],

propTypes: {
id: React.PropTypes.string,
/**
* If set to true, renders `span` instead of `a`
*/
active: React.PropTypes.bool,
linkId: React.PropTypes.string,
/**
* HTML id for the wrapper `li` element
*/
id: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number
]),
/**
* HTML id for the inner `a` element
*/
linkId: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number
]),
/**
* `href` attribute for the inner `a` element
*/
href: React.PropTypes.string,
/**
* `title` attribute for the inner `a` element
*/
title: React.PropTypes.node,
/**
* `target` attribute for the inner `a` element
*/
target: React.PropTypes.string
},

Expand All @@ -23,18 +44,19 @@ const BreadcrumbItem = React.createClass({
},

render() {
warning(!(this.props.href && this.props.active), '[react-bootstrap] href and active properties cannot be set at the same time');

const {
id,
active,
className,
id,
linkId,
children,
href,
title,
target,
...props } = this.props;
const classes = { active };

warning(!(href && active), '[react-bootstrap] `href` and `active` properties cannot be set at the same time');

const linkProps = {
href,
title,
Expand All @@ -43,7 +65,7 @@ const BreadcrumbItem = React.createClass({
};

return (
<li id={id} className={classNames(props.className, classes)}>
<li id={id} className={classNames(className, { active })}>
{
active ?
<span {...props}>
Expand Down
1 change: 0 additions & 1 deletion src/styleMaps.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const styleMaps = {
CLASSES: {
'alert': 'alert',
'breadcrumb': 'breadcrumb',
'button': 'btn',
'button-group': 'btn-group',
'button-toolbar': 'btn-toolbar',
Expand Down
117 changes: 60 additions & 57 deletions test/BreadcrumbItemSpec.js
Original file line number Diff line number Diff line change
@@ -1,137 +1,140 @@
import React from 'react';
import ReactTestUtils from 'react/lib/ReactTestUtils';
import BreadcrumbItem from '../src/BreadcrumbItem';
import { shouldWarn } from './helpers';

describe('BreadcrumbItem', function () {
it('Should add active class', function () {
let instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem active>
Active Crumb
describe('BreadcrumbItem', () => {
it('Should warn if `active` and `href` attributes set', () => {
ReactTestUtils.renderIntoDocument(
<BreadcrumbItem href='#' active>
Crumb
</BreadcrumbItem>
);

assert.ok(ReactTestUtils.findRenderedDOMComponentWithClass(instance, 'active'));
shouldWarn('[react-bootstrap] `href` and `active` properties cannot be set at the same time');
});

it('Should not add active class', function () {
let instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem>
it('Should render `a` as inner element when is not active', () => {
const instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem href='#'>
Crumb
</BreadcrumbItem>
);

let liNode = React.findDOMNode(instance);
assert.notInclude(liNode.className, 'active');
assert.ok(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
assert.notInclude(React.findDOMNode(instance).className, 'active');
});

it('Should add custom classes', function () {
let instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem className="custom-one custom-two" active>
it('Should add `active` class with `active` attribute set.', () => {
const instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem active>
Active Crumb
</BreadcrumbItem>
);

let liNode = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithClass(instance, 'active'));
assert.include(React.findDOMNode(instance).className, 'active');
});

let classes = liNode.className;
assert.include(classes, 'active');
assert.include(classes, 'custom-one');
assert.include(classes, 'custom-two');
it('Should render `span` as inner element when is active', () => {
const instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem active>
Crumb
</BreadcrumbItem>
);

assert.ok(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'span'));
});

it('Should spread props onto an active item', function() {
let instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem herpa='derpa' active>
it('Should add custom classes onto `li` wrapper element', () => {
const instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem className="custom-one custom-two">
Active Crumb
</BreadcrumbItem>
);

let spanNode = ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'span');

spanNode.props.herpa.should.equal('derpa');
const classes = React.findDOMNode(instance).className;
assert.include(classes, 'custom-one');
assert.include(classes, 'custom-two');
});

it('Should spread props onto anchor', function(done) {
it('Should spread additional props onto inner element', (done) => {
const handleClick = () => {
done();
};

let instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem href='#' onClick={handleClick} herpa='derpa'>
Crumb 1
const instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem href='#' onClick={handleClick}>
Crumb
</BreadcrumbItem>
);

let anchorNode = ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a');
const anchorNode = ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a');
ReactTestUtils.Simulate.click(anchorNode);

anchorNode.props.herpa.should.equal('derpa');
});

it('Should add id for li element', function() {
let instance = ReactTestUtils.renderIntoDocument(
it('Should apply id onto `li` wrapper element via `id` property', () => {
const instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem href='#' id='test-li-id'>
Crumb 1
Crumb
</BreadcrumbItem>
);

let liNode = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'li'));
assert.equal(liNode.id, 'test-li-id');
assert.equal(React.findDOMNode(instance).id, 'test-li-id');
});

it('Should add linkId', function() {
let instance = ReactTestUtils.renderIntoDocument(
it('Should apply id onto `a` inner alement via `linkId` property', () => {
const instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem href='#' linkId='test-link-id'>
Crumb 1
Crumb
</BreadcrumbItem>
);

let linkNode = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
const linkNode = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
assert.equal(linkNode.id, 'test-link-id');
});

it('Should add href', function() {
let instance = ReactTestUtils.renderIntoDocument(
it('Should apply `href` property onto `a` inner element', () => {
const instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem href='http://getbootstrap.com/components/#breadcrumbs'>
Crumb 1
Crumb
</BreadcrumbItem>
);

let linkNode = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
const linkNode = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
assert.equal(linkNode.href, 'http://getbootstrap.com/components/#breadcrumbs');
});

it('Should have a title', function() {
let instance = ReactTestUtils.renderIntoDocument(
it('Should apply `title` property onto `a` inner element', () => {
const instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem title='test-title' href='http://getbootstrap.com/components/#breadcrumbs'>
Crumb 1
Crumb
</BreadcrumbItem>
);

let linkNode = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
const linkNode = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
assert.equal(linkNode.title, 'test-title');
});

it('Should not add anchor properties to li', function() {
let instance = ReactTestUtils.renderIntoDocument(
it('Should not apply properties for inner `anchor` onto `li` wrapper element', () => {
const instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem title='test-title' href='/hi'>
Crumb 1
Crumb
</BreadcrumbItem>
);

let liNode = React.findDOMNode(instance);
const liNode = React.findDOMNode(instance);
assert.notOk(liNode.hasAttribute('href'));
assert.notOk(liNode.hasAttribute('title'));
});

it('Should set target attribute on anchor', function () {
let instance = ReactTestUtils.renderIntoDocument(
it('Should set `target` attribute on `anchor`', () => {
const instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem target='_blank' href='http://getbootstrap.com/components/#breadcrumbs'>
Crumb 1
Crumb
</BreadcrumbItem>
);

let linkNode = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
const linkNode = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
assert.equal(linkNode.target, '_blank');
});
});

0 comments on commit 0348274

Please sign in to comment.