components/navbar/Navbar.js

import React, { Component, Fragment } from 'react';

import { ArrowLeftAltIcon } from 'assets/icons/ArrowLeftAltIcon';
import { ArrowLeftIcon } from 'assets/icons/ArrowLeftIcon';
import { CloseAltIcon } from 'assets/icons/CloseAltIcon';
import { CloseIcon } from 'assets/icons/CloseIcon';
import { MenuAltIcon } from 'assets/icons/MenuAltIcon';
import { MenuIcon } from 'assets/icons/MenuIcon';
import PropTypes from 'prop-types';
import setClassName from 'utilities/setClassName';
import styles from 'src/components/navbar/Navbar.module.scss';

/**
 * @namespace Navbar
 * @description Default styled navbar component.
 * @property {Array.<Object>} links - Array of navigation link objects.
 * @property {string} logo - "src" attribute for logo <img />.
 * @property {string} logoLink - Link navbar logo/icon directs to.
 * @property {string} logoTitle - Title text for logo/icon.
 * @property {string} variant - Variant of navbar to use (e.g., "navbar-underline").
 * @tutorial `src\stories\Navbar.stories.js`.
 */

export class Navbar extends Component {

  state = { menuOpen: false };

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

  render() {
    const {
      props: {
        links,
        logo,
        logoLink,
        logoTitle,
        variant = '',
        ...drilledProps
      }
    } = this;

    const { state: { menuOpen } } = this;
    const { toggleMenu } = this;

    const className = menuOpen ? styles['navbar-open'] : styles.navbar;

    // Check if there's an 'underline' variant in props
    const underline = (
      variant.includes('navbar-underline')
      || variant.includes('navbar-right-underline')
    );

    // Determining which menu icon to serve & menu offset
    const Close = (props) => (variant.includes('alt-icons')
      ? variant.includes('arrow-close')
        ? <ArrowLeftAltIcon { ...props } />
        : <CloseAltIcon { ...props } />

      : variant.includes('arrow-close')
        ? <ArrowLeftIcon { ...props } />
        : <CloseIcon { ...props } />);


    const Menu = (props) => (variant.includes('alt-icons')
      ? <MenuAltIcon { ...props } />
      : <MenuIcon { ...props } />);

    const Icon = (props) => (menuOpen
      ? <Close { ...props } />
      : <Menu { ...props } />);

    const labelText = menuOpen ? 'close' : 'open';


    return (
      <Fragment>
        <header
          { ...drilledProps }
          variant={ variant }
          className={ setClassName(this.props, className) }
        >
          <aside role="dialog" />
          <nav>
            <div role="dialog">
              <Icon onClick={ toggleMenu } aria-label={ labelText } />
            </div>
            <section>
              { logoTitle ? <h3>{ logoTitle }</h3> : undefined }
              {
                logo
                  ? (
                    <aside>
                      {
                        logoLink
                          ? (
                            <a href={ logoLink } title={ logoTitle || null }>
                              <img src={ logo } alt={ logoTitle || 'logo' } />
                            </a>
                          )
                          : <img src={ logo } alt={ logoTitle || 'logo' } />
                      }
                    </aside>
                  )
                  : undefined
              }
              <ul>
                {
                  links.map((link) => {
                    const { a, li, text } = link;
                    const { key } = li;

                    return (
                      <li { ...li } key={ key } onClick={ toggleMenu }>
                        <a { ...a }>{ text }</a>
                        { underline ? <span /> : undefined }
                      </li>
                    );
                  })
                }
              </ul>

            </section>
          </nav>
        </header>
        <div role="dialog" />
      </Fragment>
    );
  }
}

Navbar.propTypes = {
  logo: PropTypes.any,
  logoLink: PropTypes.string,
  logoTitle: PropTypes.string,
  links: PropTypes.arrayOf(PropTypes.object).isRequired,
  variant: PropTypes.string
};

Navbar.defaultProps = {
  logo: '',
  logoLink: '',
  logoTitle: '',
  variant: ''
};