From a20ffe3364f4224d5e381e619ce39d142fe1efc4 Mon Sep 17 00:00:00 2001 From: Eyal Roth Date: Wed, 3 Jul 2019 22:10:06 +0300 Subject: [PATCH 01/26] Refactor the sidebar browser code to be part of the sidebar react component --- gatsby-browser.js | 144 -------------- src/assets/scss/_mixins.scss | 3 +- src/assets/scss/mixins/_toggle.scss | 15 ++ src/components/GlobalState/index.jsx | 16 ++ src/components/Home/index.jsx | 3 + src/components/Sidebar/index.jsx | 282 ++++++++++++++++++++++----- src/components/Sidebar/style.scss | 30 +-- src/components/Toggle/index.jsx | 14 ++ 8 files changed, 301 insertions(+), 206 deletions(-) create mode 100644 src/assets/scss/mixins/_toggle.scss create mode 100644 src/components/GlobalState/index.jsx create mode 100644 src/components/Toggle/index.jsx diff --git a/gatsby-browser.js b/gatsby-browser.js index 68e53ca..7b3c8e8 100644 --- a/gatsby-browser.js +++ b/gatsby-browser.js @@ -5,9 +5,6 @@ import littlefoot from 'littlefoot' import 'littlefoot/dist/littlefoot.css' import './src/assets/scss/_progress.scss' -var sidebarState = "main" -var lastUnderlineLink = null - export const onServiceWorkerUpdateReady = () => { const answer = window.confirm( `This application has been updated. ` + @@ -21,7 +18,6 @@ export const onServiceWorkerUpdateReady = () => { export function onRouteUpdate({ location }) { addLittlefoot() - addSidebarCollapse(location) } function addLittlefoot() { @@ -39,144 +35,4 @@ function addLittlefoot() { ` littlefoot({buttonTemplate: bt}) -} - -function addSidebarCollapse(location) { - - if (location.pathname == "/") { - sidebarState = "main" - lastUnderlineLink = null - } - - if (document.getElementById("sidebar")) { - const menu = document.getElementById("sidebar__menu") - const menuButton = document.getElementById("sidebar__menu-button") - const menuLinks = document.getElementsByClassName("sidebar__menu-list-item-link") - const menuUnderline = document.getElementById("sidebar__menu-underline") - - const contact = document.getElementById("sidebar__contact") - const contactButton = document.getElementById("sidebar__contact-button") - - const profileImage = document.getElementById("sidebar__author-img") - const authorTitle = document.getElementById("sidebar__author-title") - - setSidebarState(sidebarState) - setupUnderline(location) - - menuButton.addEventListener("click", () => toggle("menu-button")) - contactButton.addEventListener("click", () => toggle("contact-button")) - - function toggle(buttonClicked) { - if (buttonClicked == "menu-button") { - if (sidebarState == "menu") { - setSidebarState("main") - } else { - setSidebarState("menu") - } - } else if (buttonClicked == "contact-button") { - if (sidebarState == "contact") { - setSidebarState("main") - } else { - setSidebarState("contact") - } - } - } - - function setSidebarState(state) { - - sidebarState = state - - if (state == "main") { - enable(profileImage) - enable(authorTitle) - disable(menu) - disable(menuButton) - disable(contact) - disable(contactButton) - } else if (state == "menu") { - disable(profileImage) - disable(authorTitle) - enable(menu) - enable(menuButton) - disable(contact) - disable(contactButton) - } else if (state == "contact") { - enable(profileImage) - disable(authorTitle) - disable(menu) - disable(menuButton) - enable(contact) - enable(contactButton) - } - } - - function setupUnderline(location) { - - const lastLink = findMatchingLink(lastUnderlineLink) - const currentLink = findMatchingLink(location) - - if (currentLink) { - if (lastLink) { - setUnderline(lastLink) - shiftUnderline({from: lastLink, to: currentLink}) - } else { - if (menu.getBoundingClientRect().width > 0) { - setUnderline(currentLink) - } else { - menuButton.addEventListener('click', () => { - menu.addEventListener('transitionend', () => { - setUnderline(currentLink) - }, {once: true}) - }, {once: true}) - } - } - lastUnderlineLink = currentLink - } else { - lastUnderlineLink = null - } - - function setUnderline(link) { - const { left, width } = link.getBoundingClientRect() - menuUnderline.style.left = `${left}px` - menuUnderline.style.width = `${width}px` - } - - function shiftUnderline({from, to}) { - const { left: fromX } = from.getBoundingClientRect() - const { left: toX, width } = to.getBoundingClientRect() - menuUnderline.style.transform = `translateX(${toX - fromX}px)` - menuUnderline.style.width = `${width}px` - } - } - - function enable(item) { - item.classList.add(`${item.id}-enabled`) - item.classList.remove(`${item.id}-disabled`) - } - - function disable(item) { - item.classList.add(`${item.id}-disabled`) - item.classList.remove(`${item.id}-enabled`) - } - - function findMatchingLink(location) { - - if (location == null) { - return null - } - - for (let i = 0; i < menuLinks.length; i++) { - let link = menuLinks[i] - if (noTrailingSlash(link.pathname) == noTrailingSlash(location.pathname)) { - return link - } - } - - return null - - function noTrailingSlash(pathname) { - return pathname.replace(/\/$/, "") - } - } - } } \ No newline at end of file diff --git a/src/assets/scss/_mixins.scss b/src/assets/scss/_mixins.scss index 783c4f1..7c7acf7 100644 --- a/src/assets/scss/_mixins.scss +++ b/src/assets/scss/_mixins.scss @@ -3,4 +3,5 @@ @import "mixins/breakpoints"; @import "mixins/margin"; @import "mixins/padding"; -@import "mixins/line-height"; \ No newline at end of file +@import "mixins/line-height"; +@import "mixins/toggle"; \ No newline at end of file diff --git a/src/assets/scss/mixins/_toggle.scss b/src/assets/scss/mixins/_toggle.scss new file mode 100644 index 0000000..7d397be --- /dev/null +++ b/src/assets/scss/mixins/_toggle.scss @@ -0,0 +1,15 @@ +/** + * Toggle control + */ + +@mixin enabled { + .enabled > & { + @content; + } +} + +@mixin disabled { + .disabled > & { + @content; + } +} \ No newline at end of file diff --git a/src/components/GlobalState/index.jsx b/src/components/GlobalState/index.jsx new file mode 100644 index 0000000..9d87240 --- /dev/null +++ b/src/components/GlobalState/index.jsx @@ -0,0 +1,16 @@ +class GlobalState { + constructor() { + this.reset() + } + + reset() { + this.sidebar = { + mode: null, + lastUnderlinePath: null + } + } +} + +const globalState = new GlobalState() + +export default globalState \ No newline at end of file diff --git a/src/components/Home/index.jsx b/src/components/Home/index.jsx index 448a8d1..a5f996e 100644 --- a/src/components/Home/index.jsx +++ b/src/components/Home/index.jsx @@ -4,10 +4,13 @@ import Helmet from 'react-helmet' import Links from '../Links' import ProfileImg from '../ProfileImg' import Footer from '../Footer' +import globalState from '../GlobalState' import './style.scss' class Home extends React.Component { render() { + globalState.reset() + return (
diff --git a/src/components/Sidebar/index.jsx b/src/components/Sidebar/index.jsx index 4c41cb6..d859c70 100644 --- a/src/components/Sidebar/index.jsx +++ b/src/components/Sidebar/index.jsx @@ -2,6 +2,8 @@ import React from 'react' import { Link, StaticQuery, graphql } from "gatsby" import Links from '../Links' import ProfileImg from '../ProfileImg' +import Toggle from '../Toggle' +import globalState from '../GlobalState' import './style.scss' const menuList = [ @@ -19,8 +21,28 @@ const menuList = [ }, ] +const SidebarMode = Object.freeze({ + Main: "main", + Menu: "menu", + Contact: "contact" +}) + class Sidebar extends React.Component { + constructor(props) { + super(props) + if (!globalState.sidebar.mode) { + globalState.sidebar.mode = SidebarMode.Main + } + this.state = { mode: globalState.sidebar.mode } + this.menuLinks = {} + } + + changeMode(newMode) { + this.setState({mode: newMode}) + globalState.sidebar.mode = newMode + } + render() { return ( -
    - {menuList.map(item => ( -
  • - - {item.label} - -
  • - ))} -
-