Implement hamburger menu for mobile
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user