Merge pull request #12288 from BerkeleyTrue/feat/add-dropdown-nav
feat(nav): Add dropdown menu
This commit is contained in:
@ -33,7 +33,8 @@
|
||||
z-index: @zindex-dropdown;
|
||||
display: none; // none by default, but block on "open" of the menu
|
||||
float: left;
|
||||
min-width: 160px;
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
padding: 5px 0;
|
||||
margin: 2px 0 0; // override default ul
|
||||
list-style: none;
|
||||
|
@ -235,9 +235,9 @@
|
||||
@dropdown-divider-bg: #e5e5e5;
|
||||
|
||||
//** Dropdown link text color.
|
||||
@dropdown-link-color: @gray-dark;
|
||||
@dropdown-link-color: darkgreen;
|
||||
//** Hover color for dropdown links.
|
||||
@dropdown-link-hover-color: darken(@gray-dark, 5%);
|
||||
@dropdown-link-hover-color: darkgreen;
|
||||
//** Hover background for dropdown links.
|
||||
@dropdown-link-hover-bg: #f5f5f5;
|
||||
|
||||
@ -365,8 +365,8 @@
|
||||
@navbar-default-link-color: @gray-lighter;
|
||||
@navbar-default-link-hover-color: darkgreen;
|
||||
@navbar-default-link-hover-bg: @gray-lighter;
|
||||
@navbar-default-link-active-color: @gray-lighter;
|
||||
@navbar-default-link-active-bg: darken(@navbar-default-bg, 6.5%);
|
||||
@navbar-default-link-active-color: darkgreen;
|
||||
@navbar-default-link-active-bg: @gray-lighter;
|
||||
@navbar-default-link-disabled-color: #ccc;
|
||||
@navbar-default-link-disabled-bg: transparent;
|
||||
|
||||
|
@ -3,10 +3,12 @@ import ReactDOM from 'react-dom';
|
||||
import { LinkContainer } from 'react-router-bootstrap';
|
||||
import {
|
||||
Col,
|
||||
MenuItem,
|
||||
Nav,
|
||||
NavbarBrand,
|
||||
NavDropdown,
|
||||
NavItem,
|
||||
Navbar,
|
||||
NavItem
|
||||
NavbarBrand
|
||||
} from 'react-bootstrap';
|
||||
|
||||
import navLinks from './links.json';
|
||||
@ -76,36 +78,45 @@ export default class FCCNav extends React.Component {
|
||||
this.props.loadCurrentChallenge();
|
||||
}
|
||||
|
||||
renderLinks() {
|
||||
return navLinks.map(({ content, link, react, target }, index) => {
|
||||
if (react) {
|
||||
renderLink(isNavItem, { isReact, isDropdown, content, link, links, target }) {
|
||||
const Component = isNavItem ? NavItem : MenuItem;
|
||||
if (isDropdown) {
|
||||
return (
|
||||
<NavDropdown
|
||||
id={ `nav-${content}-dropdown` }
|
||||
key={ content }
|
||||
noCaret={ true }
|
||||
title={ content }
|
||||
>
|
||||
{ links.map(this.renderLink.bind(this, false)) }
|
||||
</NavDropdown>
|
||||
);
|
||||
}
|
||||
if (isReact) {
|
||||
return (
|
||||
<LinkContainer
|
||||
eventKey={ index + 2 }
|
||||
key={ content }
|
||||
onClick={ this[`handle${content}Click`] }
|
||||
to={ link }
|
||||
>
|
||||
<NavItem
|
||||
<Component
|
||||
target={ target || null }
|
||||
>
|
||||
{ content }
|
||||
</NavItem>
|
||||
</Component>
|
||||
</LinkContainer>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<NavItem
|
||||
eventKey={ index + 1 }
|
||||
<Component
|
||||
href={ link }
|
||||
key={ content }
|
||||
onClick={ this[`handle${content}Click`] }
|
||||
target={ target || null }
|
||||
>
|
||||
{ content }
|
||||
</NavItem>
|
||||
</Component>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
renderSignIn(username, points, picture, showLoading) {
|
||||
@ -123,7 +134,6 @@ export default class FCCNav extends React.Component {
|
||||
} else {
|
||||
return (
|
||||
<NavItem
|
||||
eventKey={ 2 }
|
||||
href='/signup'
|
||||
key='signup'
|
||||
>
|
||||
@ -140,6 +150,17 @@ export default class FCCNav extends React.Component {
|
||||
picture,
|
||||
showLoading
|
||||
} = 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 (
|
||||
<Navbar
|
||||
@ -167,7 +188,7 @@ export default class FCCNav extends React.Component {
|
||||
navbar={ true }
|
||||
pullRight={ true }
|
||||
>
|
||||
{ this.renderLinks() }
|
||||
{ navLinksCache }
|
||||
{ this.renderSignIn(username, points, picture, showLoading) }
|
||||
</Nav>
|
||||
</Navbar.Collapse>
|
||||
|
@ -1,18 +1,22 @@
|
||||
[{
|
||||
"content": "Map",
|
||||
"link": "/map",
|
||||
"react": true
|
||||
},{
|
||||
"content": "Chat",
|
||||
"link": "https://gitter.im/freecodecamp/home",
|
||||
"target": "_blank"
|
||||
"content": "Community",
|
||||
"isDropdown": true,
|
||||
"links": [{
|
||||
"content": "About",
|
||||
"link": "/about"
|
||||
}, {
|
||||
"content": "Forum",
|
||||
"link": "https://forum.freecodecamp.com/",
|
||||
"target": "_blank"
|
||||
}, {
|
||||
"content": "About",
|
||||
"link": "/about"
|
||||
"content": "Chat",
|
||||
"link": "https://gitter.im/freecodecamp/home",
|
||||
"target": "_blank"
|
||||
}]
|
||||
},{
|
||||
"content": "Map",
|
||||
"link": "/map",
|
||||
"isReact": true
|
||||
},{
|
||||
"content": "Shop",
|
||||
"link": "/shop"
|
||||
|
@ -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')
|
||||
.collapse.navbar-collapse
|
||||
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='/map') Map
|
||||
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
|
||||
a(href='/about') About
|
||||
a(href='/map') Map
|
||||
li
|
||||
a(href='/shop') Shop
|
||||
if !user
|
||||
|
Reference in New Issue
Block a user