Merge pull request #12288 from BerkeleyTrue/feat/add-dropdown-nav

feat(nav): Add dropdown menu
This commit is contained in:
Quincy Larson
2016-12-30 21:26:37 -06:00
committed by GitHub
5 changed files with 81 additions and 52 deletions

View File

@ -33,7 +33,8 @@
z-index: @zindex-dropdown; z-index: @zindex-dropdown;
display: none; // none by default, but block on "open" of the menu display: none; // none by default, but block on "open" of the menu
float: left; float: left;
min-width: 160px; min-width: 0;
width: 100%;
padding: 5px 0; padding: 5px 0;
margin: 2px 0 0; // override default ul margin: 2px 0 0; // override default ul
list-style: none; list-style: none;

View File

@ -235,9 +235,9 @@
@dropdown-divider-bg: #e5e5e5; @dropdown-divider-bg: #e5e5e5;
//** Dropdown link text color. //** Dropdown link text color.
@dropdown-link-color: @gray-dark; @dropdown-link-color: darkgreen;
//** Hover color for dropdown links. //** Hover color for dropdown links.
@dropdown-link-hover-color: darken(@gray-dark, 5%); @dropdown-link-hover-color: darkgreen;
//** Hover background for dropdown links. //** Hover background for dropdown links.
@dropdown-link-hover-bg: #f5f5f5; @dropdown-link-hover-bg: #f5f5f5;
@ -365,8 +365,8 @@
@navbar-default-link-color: @gray-lighter; @navbar-default-link-color: @gray-lighter;
@navbar-default-link-hover-color: darkgreen; @navbar-default-link-hover-color: darkgreen;
@navbar-default-link-hover-bg: @gray-lighter; @navbar-default-link-hover-bg: @gray-lighter;
@navbar-default-link-active-color: @gray-lighter; @navbar-default-link-active-color: darkgreen;
@navbar-default-link-active-bg: darken(@navbar-default-bg, 6.5%); @navbar-default-link-active-bg: @gray-lighter;
@navbar-default-link-disabled-color: #ccc; @navbar-default-link-disabled-color: #ccc;
@navbar-default-link-disabled-bg: transparent; @navbar-default-link-disabled-bg: transparent;

View File

@ -3,10 +3,12 @@ import ReactDOM from 'react-dom';
import { LinkContainer } from 'react-router-bootstrap'; import { LinkContainer } from 'react-router-bootstrap';
import { import {
Col, Col,
MenuItem,
Nav, Nav,
NavbarBrand, NavDropdown,
NavItem,
Navbar, Navbar,
NavItem NavbarBrand
} from 'react-bootstrap'; } from 'react-bootstrap';
import navLinks from './links.json'; import navLinks from './links.json';
@ -76,36 +78,45 @@ export default class FCCNav extends React.Component {
this.props.loadCurrentChallenge(); this.props.loadCurrentChallenge();
} }
renderLinks() { renderLink(isNavItem, { isReact, isDropdown, content, link, links, target }) {
return navLinks.map(({ content, link, react, target }, index) => { const Component = isNavItem ? NavItem : MenuItem;
if (react) { if (isDropdown) {
return (
<LinkContainer
eventKey={ index + 2 }
key={ content }
onClick={ this[`handle${content}Click`] }
to={ link }
>
<NavItem
target={ target || null }
>
{ content }
</NavItem>
</LinkContainer>
);
}
return ( return (
<NavItem <NavDropdown
eventKey={ index + 1 } id={ `nav-${content}-dropdown` }
href={ link } key={ content }
noCaret={ true }
title={ content }
>
{ links.map(this.renderLink.bind(this, false)) }
</NavDropdown>
);
}
if (isReact) {
return (
<LinkContainer
key={ content } key={ content }
onClick={ this[`handle${content}Click`] } onClick={ this[`handle${content}Click`] }
target={ target || null } to={ link }
> >
{ content } <Component
</NavItem> target={ target || null }
>
{ content }
</Component>
</LinkContainer>
); );
}); }
return (
<Component
href={ link }
key={ content }
onClick={ this[`handle${content}Click`] }
target={ target || null }
>
{ content }
</Component>
);
} }
renderSignIn(username, points, picture, showLoading) { renderSignIn(username, points, picture, showLoading) {
@ -123,7 +134,6 @@ export default class FCCNav extends React.Component {
} else { } else {
return ( return (
<NavItem <NavItem
eventKey={ 2 }
href='/signup' href='/signup'
key='signup' key='signup'
> >
@ -140,6 +150,17 @@ export default class FCCNav extends React.Component {
picture, picture,
showLoading showLoading
} = this.props; } = this.props;
let navLinksCache;
if (this._navLinksCache) {
navLinksCache = this._navLinksCache;
} else {
// we cache the rendered static links on the instance
// these do not change for the lifetime of the app
navLinksCache = this._navLinksCache = navLinks.map(
this.renderLink.bind(this, true)
);
}
return ( return (
<Navbar <Navbar
@ -167,7 +188,7 @@ export default class FCCNav extends React.Component {
navbar={ true } navbar={ true }
pullRight={ true } pullRight={ true }
> >
{ this.renderLinks() } { navLinksCache }
{ this.renderSignIn(username, points, picture, showLoading) } { this.renderSignIn(username, points, picture, showLoading) }
</Nav> </Nav>
</Navbar.Collapse> </Navbar.Collapse>

View File

@ -1,18 +1,22 @@
[{ [{
"content": "Community",
"isDropdown": true,
"links": [{
"content": "About",
"link": "/about"
}, {
"content": "Forum",
"link": "https://forum.freecodecamp.com/",
"target": "_blank"
}, {
"content": "Chat",
"link": "https://gitter.im/freecodecamp/home",
"target": "_blank"
}]
},{
"content": "Map", "content": "Map",
"link": "/map", "link": "/map",
"react": true "isReact": true
},{
"content": "Chat",
"link": "https://gitter.im/freecodecamp/home",
"target": "_blank"
},{
"content": "Forum",
"link": "https://forum.freecodecamp.com/",
"target": "_blank"
},{
"content": "About",
"link": "/about"
},{ },{
"content": "Shop", "content": "Shop",
"link": "/shop" "link": "/shop"

View File

@ -7,14 +7,17 @@ nav.navbar.navbar-default.navbar-fixed-top.nav-height
img.img-responsive.nav-logo(src='https://s3.amazonaws.com/freecodecamp/freecodecamp_logo.svg', alt='learn to code javascript at Free Code Camp logo') img.img-responsive.nav-logo(src='https://s3.amazonaws.com/freecodecamp/freecodecamp_logo.svg', alt='learn to code javascript at Free Code Camp logo')
.collapse.navbar-collapse .collapse.navbar-collapse
ul.nav.navbar-nav.navbar-right.hamburger-dropdown ul.nav.navbar-nav.navbar-right.hamburger-dropdown
li.dropdown
a.dropdown-toggle(data-toggle='dropdown' role='button' href='#' aria-haspopup='true') Community
ul.dropdown-menu
li
a(href='/about') About
li
a(href='https://gitter.im/freecodecamp/home' target='_blank') Chat
li
a(href='https://forum.freecodecamp.com', target='_blank') Forum
li li
a(href='/map') Map a(href='/map') Map
li
a(href='https://gitter.im/freecodecamp/home' target='_blank') Chat
li
a(href='https://forum.freecodecamp.com', target='_blank') Forum
li
a(href='/about') About
li li
a(href='/shop') Shop a(href='/shop') Shop
if !user if !user