`. \n\n' +
+ 'for more details see: http://react-bootstrap.github.io/components.html#navbars'
+ });
+
+ return ;
+ }
+
const classes = tbsUtils.getClassSet(this.props);
classes[tbsUtils.prefix(this.props, 'fixed-top')] = this.props.fixedTop;
diff --git a/src/deprecated/Navbar.js b/src/deprecated/Navbar.js
new file mode 100644
index 0000000000..f625fe19f5
--- /dev/null
+++ b/src/deprecated/Navbar.js
@@ -0,0 +1,220 @@
+import React from 'react';
+import classNames from 'classnames';
+import deprecated from 'react-prop-types/lib/deprecated';
+import elementType from 'react-prop-types/lib/elementType';
+
+import Grid from '../Grid';
+import NavBrand from '../NavBrand';
+
+import tbsUtils, { bsClass, bsStyles } from '../utils/bootstrapUtils';
+import { DEFAULT, INVERSE } from '../styleMaps';
+import createChainedFunction from '../utils/createChainedFunction';
+import ValidComponentChildren from '../utils/ValidComponentChildren';
+
+const Navbar = React.createClass({
+
+ propTypes: {
+ fixedTop: React.PropTypes.bool,
+ fixedBottom: React.PropTypes.bool,
+ staticTop: React.PropTypes.bool,
+ inverse: React.PropTypes.bool,
+ fluid: React.PropTypes.bool,
+ role: React.PropTypes.string,
+ /**
+ * You can use a custom element for this component
+ */
+ componentClass: elementType,
+ brand: deprecated(React.PropTypes.node, 'Use the `NavBrand` component.'),
+ toggleButton: React.PropTypes.node,
+ toggleNavKey: React.PropTypes.oneOfType([
+ React.PropTypes.string,
+ React.PropTypes.number
+ ]),
+ onToggle: React.PropTypes.func,
+ navExpanded: React.PropTypes.bool,
+ defaultNavExpanded: React.PropTypes.bool
+ },
+
+ // TODO Remove in 0.29
+ childContextTypes: {
+ $bs_deprecated_navbar: React.PropTypes.bool
+ },
+
+ getChildContext() {
+ return {
+ $bs_deprecated_navbar: true
+ };
+ },
+
+ getDefaultProps() {
+ return {
+ role: 'navigation',
+ componentClass: 'nav',
+ fixedTop: false,
+ fixedBottom: false,
+ staticTop: false,
+ inverse: false,
+ fluid: false,
+ defaultNavExpanded: false
+ };
+ },
+
+ getInitialState() {
+ return {
+ navExpanded: this.props.defaultNavExpanded
+ };
+ },
+
+ shouldComponentUpdate() {
+ // Defer any updates to this component during the `onSelect` handler.
+ return !this._isChanging;
+ },
+
+ handleToggle() {
+ if (this.props.onToggle) {
+ this._isChanging = true;
+ this.props.onToggle();
+ this._isChanging = false;
+ }
+
+ this.setState({
+ navExpanded: !this.state.navExpanded
+ });
+ },
+
+ isNavExpanded() {
+ return this.props.navExpanded != null ? this.props.navExpanded : this.state.navExpanded;
+ },
+
+ hasNavBrandChild() {
+ return ValidComponentChildren.findValidComponents(
+ this.props.children, child => child.props.bsRole === 'brand'
+ ).length > 0;
+ },
+
+ render() {
+ const {
+ brand,
+ toggleButton,
+ toggleNavKey,
+ fixedTop,
+ fixedBottom,
+ staticTop,
+ inverse,
+ componentClass: ComponentClass,
+ fluid,
+ className,
+ children,
+ ...props
+ } = this.props;
+
+ const classes = tbsUtils.getClassSet(this.props);
+
+ classes[tbsUtils.prefix(this.props, 'fixed-top')] = this.props.fixedTop;
+ classes[tbsUtils.prefix(this.props, 'fixed-bottom')] = this.props.fixedBottom;
+ classes[tbsUtils.prefix(this.props, 'static-top')] = this.props.staticTop;
+
+ // handle built-in styles manually to provide the convenience `inverse` prop
+ classes[tbsUtils.prefix(this.props, INVERSE)] = this.props.inverse;
+ classes[tbsUtils.prefix(this.props, DEFAULT)] = !this.props.inverse;
+
+ const showHeader =
+ (brand || toggleButton || toggleNavKey != null) &&
+ !this.hasNavBrandChild();
+
+ return (
+
+
+ {showHeader ? this.renderBrandHeader() : null}
+ {ValidComponentChildren.map(children, this.renderChild)}
+
+
+ );
+ },
+
+ renderBrandHeader() {
+ let {brand} = this.props;
+ if (brand) {
+ brand = {brand};
+ }
+
+ return this.renderHeader(brand);
+ },
+
+
+ renderHeader(brand) {
+ const hasToggle = this.props.toggleButton || this.props.toggleNavKey != null;
+ const headerClass = tbsUtils.prefix(this.props, 'header');
+
+ return (
+
+ {brand}
+ {hasToggle ? this.renderToggleButton() : null}
+
+ );
+ },
+
+ renderChild(child, index) {
+ const key = child.key != null ? child.key : index;
+
+ if (child.props.bsRole === 'brand') {
+ return React.cloneElement(this.renderHeader(child), {key});
+ }
+
+ const {toggleNavKey} = this.props;
+ const collapsible =
+ toggleNavKey != null && toggleNavKey === child.props.eventKey;
+
+ return React.cloneElement(child, {
+ navbar: true,
+ collapsible,
+ expanded: collapsible && this.isNavExpanded(),
+ key
+ });
+ },
+
+ renderToggleButton() {
+ const {toggleButton} = this.props;
+ const toggleClass = tbsUtils.prefix(this.props, 'toggle');
+
+ if (React.isValidElement(toggleButton)) {
+ return React.cloneElement(toggleButton, {
+ className: classNames(toggleButton.props.className, toggleClass),
+ onClick: createChainedFunction(
+ this.handleToggle, toggleButton.props.onClick
+ )
+ });
+ }
+
+ let children;
+ if (toggleButton != null) {
+ children = toggleButton;
+ } else {
+ children = [
+ Toggle navigation,
+ ,
+ ,
+
+ ];
+ }
+
+ return (
+
+ );
+ }
+
+});
+
+const NAVBAR_STATES = [DEFAULT, INVERSE];
+
+export default bsStyles(NAVBAR_STATES, DEFAULT,
+ bsClass('navbar',
+ Navbar
+ )
+);
diff --git a/test/NavSpec.js b/test/NavSpec.js
index 7f4d304dca..0d33df38c8 100644
--- a/test/NavSpec.js
+++ b/test/NavSpec.js
@@ -65,7 +65,7 @@ describe('Nav', () => {
it('Should add navbar-right class', () => {
let instance = ReactTestUtils.renderIntoDocument(
-