Skip to content

Commit

Permalink
Change navbar to be a controlled component
Browse files Browse the repository at this point in the history
commit b88baf2
Author: John Benavides <john@mailtrack.io>
Date:   Tue Jul 3 15:49:57 2018 +0200

    use context to handle navbar active status
  • Loading branch information
John Benavides committed Jul 3, 2018
1 parent 2dd7109 commit d4b62d0
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 153 deletions.
14 changes: 1 addition & 13 deletions src/components/navbar/components/brand.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import Burger from './burger';

export default class NavbarBrand extends React.PureComponent {
static displayName = 'Navbar.Brand'
Expand All @@ -10,37 +9,26 @@ export default class NavbarBrand extends React.PureComponent {
style: PropTypes.shape({}),
className: PropTypes.string,
children: PropTypes.node,
active: PropTypes.bool,
toggleMenu: PropTypes.func,
}

static defaultProps = {
style: {},
className: '',
children: null,
active: false,
toggleMenu: () => {},
}

render() {
const {
className,
children,
active,
toggleMenu,
...props
} = this.props;
return (
<div
{...props}
className={classnames('navbar-brand', className)}
>
{React.Children.map(children, (child) => {
if ([Burger].includes(child.type)) {
return React.cloneElement(child, { active, toggleMenu });
}
return child;
})}
{children}
</div>
);
}
Expand Down
45 changes: 23 additions & 22 deletions src/components/navbar/components/burger.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,56 @@ import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';

import { ShowContext } from '../context';

export default class NavbarBurger extends React.PureComponent {
static displayName = 'Navbar.Burger'

static propTypes = {
style: PropTypes.shape({}),
className: PropTypes.string,
active: PropTypes.bool,
onClick: PropTypes.func,
toggleMenu: PropTypes.func,
}

static defaultProps = {
style: {},
className: '',
active: false,
onClick: () => {},
toggleMenu: () => {},
}

onClick = (evt) => {
const { onClick, toggleMenu } = this.props;
const { onClick } = this.props;
onClick(evt);
toggleMenu();
}

render() {
const {
style,
className,
active,
onClick,
toggleMenu,
...props
} = this.props;
return (
<div
onClick={this.onClick}
role="button"
tabIndex="0"
style={{ outline: 'none', ...style }}
className={classnames('navbar-burger', className, {
'is-active': active,
})}
{...props}
>
<span />
<span />
<span />
</div>
<ShowContext.Consumer>
{
active => (
<div
onClick={this.onClick}
role="button"
tabIndex="0"
style={{ outline: 'none', ...style }}
className={classnames('navbar-burger', className, {
'is-active': active,
})}
{...props}
>
<span />
<span />
<span />
</div>
)
}
</ShowContext.Consumer>
);
}
}
27 changes: 16 additions & 11 deletions src/components/navbar/components/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,45 @@ import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';

import { ShowContext } from '../context';

export default class NavbarMenu extends React.PureComponent {
static displayName = 'Navbar.Menu'

static propTypes = {
style: PropTypes.shape({}),
className: PropTypes.string,
active: PropTypes.bool,
children: PropTypes.node,
}

static defaultProps = {
style: {},
className: '',
active: false,
children: null,
}

render() {
const {
className,
active,
children,
...props
} = this.props;

return (
<div
{...props}
className={classnames('navbar-menu', className, {
'is-active': active,
})}
>
{children}
</div>
<ShowContext.Consumer>
{
active => (
<div
{...props}
className={classnames('navbar-menu', className, {
'is-active': active,
})}
>
{children}
</div>
)
}
</ShowContext.Consumer>
);
}
}
3 changes: 3 additions & 0 deletions src/components/navbar/context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import React from 'react';

export const ShowContext = React.createContext('active');
52 changes: 18 additions & 34 deletions src/components/navbar/navbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import Divider from './components/divider';
import Link from './components/link';
import Container from './components/container';
import CONSTANTS from '../../constants';
import { ShowContext } from './context';

const colors = [null].concat(Object.keys(CONSTANTS.COLORS).map(key => CONSTANTS.COLORS[key]));


export default class Navbar extends React.PureComponent {
static Brand = Brand

Expand All @@ -40,6 +40,7 @@ export default class Navbar extends React.PureComponent {
renderAs: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
fixed: PropTypes.oneOf(['top', 'bottom']),
color: PropTypes.oneOf(colors),
active: PropTypes.bool,
}

static defaultProps = {
Expand All @@ -48,13 +49,12 @@ export default class Navbar extends React.PureComponent {
style: {},
renderAs: 'nav',
transparent: false,
active: false,
fixed: null,
color: null,
}

state = {
showMobileMenu: false,
}
state = {}

componentDidMount() {
const { fixed } = this.props;
Expand All @@ -63,11 +63,6 @@ export default class Navbar extends React.PureComponent {
}
}

// TODO: Remove this on future releases
componentWillReceiveProps(nextProps) {
Navbar.getDerivedStateFromProps(nextProps);
}

componentWillUnmount() {
const { fixed } = this.props;
window.document.querySelector('html').classList.remove(`has-navbar-fixed-${fixed}`);
Expand All @@ -86,10 +81,6 @@ export default class Navbar extends React.PureComponent {
return null;
}

toggleMenu = () => {
this.setState(({ showMobileMenu }) => ({ showMobileMenu: !showMobileMenu }));
}

render() {
const {
children,
Expand All @@ -98,33 +89,26 @@ export default class Navbar extends React.PureComponent {
fixed,
transparent,
color,
active,
...props
} = this.props;

const { showMobileMenu } = this.state;

const Element = renderAs;

return (
<Element
{...props}
role="navigation"
className={classnames('navbar', className, {
'is-transparent': transparent,
[`is-fixed-${fixed}`]: fixed,
[`is-${color}`]: color,
})}
>
{React.Children.map(children, (child) => {
if ([Brand].includes(child.type)) {
return React.cloneElement(child, { active: showMobileMenu, toggleMenu: this.toggleMenu });
}
if ([Menu].includes(child.type)) {
return React.cloneElement(child, { active: showMobileMenu });
}
return child;
})}
</Element>
<ShowContext.Provider value={active}>
<Element
{...props}
role="navigation"
className={classnames('navbar', className, {
'is-transparent': transparent,
[`is-fixed-${fixed}`]: fixed,
[`is-${color}`]: color,
})}
>
{children}
</Element>
</ShowContext.Provider>
);
}
}

0 comments on commit d4b62d0

Please sign in to comment.