Implement hamburger menu for mobile

This commit is contained in:
Jan Tuomi
2018-11-17 17:31:05 +02:00
parent 00c20cef0b
commit 93f209a908
7 changed files with 161 additions and 43 deletions
+74 -8
View File
@@ -1,22 +1,88 @@
import * as React from "react";
import { Fragment } from "react";
import { Link } from "react-router-dom";
import "./Header.scss";
import NavbarDropdownLink from "../NavbarDropdownLink/NavbarDropdownLink";
import NavbarChildLink from "../NavbarChildLink/NavbarChildLink";
import Navigation from "../Navigation";
// @ts-ignore
import * as TitleImage from "../../assets/img/SIK_RGB_W_side.png";
export interface HeaderProps {}
export interface HeaderState {}
export interface HeaderState {
mobileMenuOpen: boolean;
}
class Header extends React.Component<HeaderProps, HeaderState> {
render() {
constructor(props) {
super(props);
this.state = {
mobileMenuOpen: false,
};
}
renderNavigationDesktopItems = () => {
return (
<div className="header">
<Link to="/">
<img src={TitleImage} />
</Link>
<Navigation />
</div>
<Fragment>
<NavbarDropdownLink to="/kilta" text="Kilta ">
<NavbarChildLink to="/kilta/toiminta">Toiminta</NavbarChildLink>
<NavbarChildLink to="/kilta/fuksi">Fuksi</NavbarChildLink>
<NavbarChildLink to="/kilta/arkisto">Arkisto</NavbarChildLink>
</NavbarDropdownLink>
<NavbarDropdownLink to="/opinnot_ja_ura" text="Opinnot ja ura"></NavbarDropdownLink>
<NavbarDropdownLink to="/yritysyhteistyo" text="Yritysyhteistyö"></NavbarDropdownLink>
<NavbarDropdownLink to="/yhteystiedot" text="Yhteystiedot ">
<NavbarChildLink to="https://en.wikipedia.org/wiki/Gay">Simo Höglund</NavbarChildLink>
</NavbarDropdownLink>
<NavbarDropdownLink to="/in_english" text="In English"></NavbarDropdownLink>
</Fragment>
);
}
renderNavigationMobileItems = () => {
return (
<Fragment>
<NavbarDropdownLink to="/kilta" text="Kilta " exploded>
<NavbarChildLink to="/kilta/toiminta">Toiminta</NavbarChildLink>
<NavbarChildLink to="/kilta/fuksi">Fuksi</NavbarChildLink>
<NavbarChildLink to="/kilta/arkisto">Arkisto</NavbarChildLink>
</NavbarDropdownLink>
<NavbarDropdownLink to="/opinnot_ja_ura" text="Opinnot ja ura" exploded />
<NavbarDropdownLink to="/yritysyhteistyo" text="Yritysyhteistyö" exploded/>
<NavbarDropdownLink to="/yhteystiedot" text="Yhteystiedot " exploded>
<NavbarChildLink to="https://en.wikipedia.org/wiki/Gay">Simo Höglund</NavbarChildLink>
</NavbarDropdownLink>
<NavbarDropdownLink to="/in_english" text="In English" exploded />
</Fragment>
);
}
handleMobileMenuClick = (): void => {
this.setState(prevState => ({
mobileMenuOpen: !prevState.mobileMenuOpen,
}));
}
render() {
const desktopItems = this.renderNavigationDesktopItems();
const mobileItems = this.renderNavigationMobileItems();
const { mobileMenuOpen } = this.state;
return (
<Fragment>
<div className="header">
<Link to="/">
<img src={TitleImage} />
</Link>
<Navigation
onMobileMenuOpen={this.handleMobileMenuClick}
items={desktopItems}
/>
</div>
<div className="navigation-mobile-menu" hidden={!mobileMenuOpen}>
{mobileItems}
</div>
</Fragment>
);
}
}
+12 -3
View File
@@ -11,6 +11,7 @@ export enum IconType {
export interface IconProps {
name: IconType;
link?: string;
onClick?: (event?: any) => void;
}
export interface IconState {}
@@ -57,16 +58,24 @@ const nameToIcon = (name: IconType): JSX.Element => {
class Icon extends React.Component<IconProps, IconState> {
render() {
const { link, name } = this.props;
const { link, name, onClick } = this.props;
const elem = nameToIcon(name);
if (link) {
return (
<a href={link} className="so-me-icon">
<a
href={link}
className="so-me-icon"
onClick={onClick}
>
{elem}
</a>
);
} else {
return elem;
return (
<span onClick={onClick}>
{elem}
</span>
);
}
}
}
@@ -8,7 +8,15 @@ $border-width: 2px;
padding-right: 4rem;
font-weight: 400;
@media screen and (max-width: 1200px - 1px) {
border-bottom: 1px dotted $light-blue;
margin-left: 2rem;
padding-left: 0;
}
&:hover {
background-color: $light-blue;
@media screen and (min-width: 1200px) {
background-color: $light-blue;
}
}
}
@@ -9,6 +9,10 @@ $border-width: 2px;
text-transform: uppercase;
letter-spacing: 2px;
padding: 20px 0;
@media screen and (max-width: 1200px - 1px) {
border-bottom: 1px solid $light-blue;
}
}
.navbar-dropdown-container {
@@ -6,6 +6,7 @@ import DropDownBox from "../DropDownBox/DropDownBox";
export interface NavbarDropdownLinkProps {
to: string;
text: string;
exploded?: boolean; // if exploded, show items directly underneath without a dropdown menu
}
export interface NavbarDropdownLinkState {
mouseOverLink: Boolean;
@@ -47,17 +48,28 @@ class NavbarDropdownLink extends React.Component<NavbarDropdownLinkProps, Navbar
}
render() {
const { children } = this.props;
const { children, exploded, text, to } = this.props;
const { mouseOverLink, mouseOverBox } = this.state;
const open = mouseOverLink || mouseOverBox;
if (exploded) {
return (
<Fragment>
<a className="navbar-dropdown-link"
href={this.props.to}
>{text}</a>
{children}
</Fragment>
);
}
return (
<div className="navbar-dropdown-container">
<a className="navbar-dropdown-link"
href={this.props.to}
href={to}
onMouseEnter={this.handleMouseEnterLink}
onMouseLeave={this.handleMouseLeaveLink}
> {this.props.text} </a>
>{text}</a>
<DropDownBox
onMouseEnter={this.handleMouseEnterBox}
onMouseLeave={this.handleMouseLeaveBox}
+13 -6
View File
@@ -1,6 +1,15 @@
@import "../../assets/scss/globals";
$border-width: 2px;
.navigation,
.navigation-mobile-menu {
a,
a:-webkit-any-link {
fill: $light-blue;
color: $light-blue;
}
}
.navigation {
width: 100%;
display: flex;
@@ -20,12 +29,6 @@ $border-width: 2px;
margin-left: 0;
}
a,
a:-webkit-any-link {
fill: $light-blue;
color: $light-blue;
}
.navbar-dropdown-container {
@media screen and (max-width: 1200px - 1px) {
display: none;
@@ -64,3 +67,7 @@ $border-width: 2px;
}
}
}
.navigation-mobile-menu {
padding: 1rem 2rem;
}
+34 -22
View File
@@ -1,37 +1,49 @@
import * as React from "react";
import { Fragment } from "react";
import "./Navigation.scss";
import NavbarDropdownLink from "../NavbarDropdownLink/NavbarDropdownLink";
import NavbarChildLink from "../NavbarChildLink/NavbarChildLink";
import Icon from "../Icon";
import { IconType } from "../Icon/Icon";
export interface NavigationProps {}
export interface NavigationState {}
export interface NavigationProps {
onMobileMenuOpen: () => void;
items: JSX.Element;
}
export interface NavigationState {
menuOpen: boolean;
}
class Navigation extends React.Component<NavigationProps, NavigationState> {
constructor(props) {
super(props);
this.state = {
menuOpen: false
};
}
handleMobileMenuClick = () => {
const { onMobileMenuOpen } = this.props;
onMobileMenuOpen();
}
render() {
const { menuOpen } = this.state;
const { items } = this.props;
return (
<div className="navigation">
<NavbarDropdownLink to="/kilta" text="Kilta ">
<NavbarChildLink to="/kilta/toiminta">Toiminta</NavbarChildLink>
<NavbarChildLink to="/kilta/fuksi">Fuksi</NavbarChildLink>
<NavbarChildLink to="/kilta/arkisto">Arkisto</NavbarChildLink>
</NavbarDropdownLink>
<NavbarDropdownLink to="/opinnot_ja_ura" text="Opinnot ja ura"></NavbarDropdownLink>
<NavbarDropdownLink to="/yritysyhteistyo" text="Yritysyhteistyö"></NavbarDropdownLink>
<NavbarDropdownLink to="/yhteystiedot" text="Yhteystiedot ">
<NavbarChildLink to="https://en.wikipedia.org/wiki/Gay">Simo Höglund</NavbarChildLink>
</NavbarDropdownLink>
<NavbarDropdownLink to="/in_english" text="In English"></NavbarDropdownLink>
<div className="navigation-some">
<Icon name={IconType.Facebook} link="https://www.facebook.com/AaltoYliopistonSIK/" />
<Icon name={IconType.Instagram} link="https://www.instagram.com/sahkoinsinoorikilta/" />
<Icon name={IconType.LinkedIn} link="https://www.linkedin.com/groups/8103057/" />
<Fragment>
<div className="navigation">
{items}
<div className="navigation-some">
<Icon name={IconType.Facebook} link="https://www.facebook.com/AaltoYliopistonSIK/" />
<Icon name={IconType.Instagram} link="https://www.instagram.com/sahkoinsinoorikilta/" />
<Icon name={IconType.LinkedIn} link="https://www.linkedin.com/groups/8103057/" />
</div>
<div className="navigation-mobile">
<Icon name={IconType.HamburgerMenu} onClick={this.handleMobileMenuClick} />
</div>
</div>
<div className="navigation-mobile">
<Icon name={IconType.HamburgerMenu} />
</div>
</div>
</Fragment>
);
}
}