mirror of
https://github.com/kremalicious/blog.git
synced 2025-01-05 03:15:07 +01:00
port over main menu
This commit is contained in:
parent
3fa552016e
commit
8bb892a07d
@ -65,7 +65,7 @@
|
|||||||
"prettier": "^1.13.7",
|
"prettier": "^1.13.7",
|
||||||
"prettier-stylelint": "^0.4.2",
|
"prettier-stylelint": "^0.4.2",
|
||||||
"stylelint": "^9.2.1",
|
"stylelint": "^9.2.1",
|
||||||
"stylelint-config-css-modules": "^1.2.0",
|
"stylelint-config-css-modules": "^1.3.0",
|
||||||
"stylelint-config-recommended-scss": "^3.2.0",
|
"stylelint-config-recommended-scss": "^3.2.0",
|
||||||
"stylelint-config-standard": "^18.2.0",
|
"stylelint-config-standard": "^18.2.0",
|
||||||
"stylelint-scss": "^3.2.0"
|
"stylelint-scss": "^3.2.0"
|
||||||
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
|||||||
import { StaticQuery, graphql } from 'gatsby'
|
import { StaticQuery, graphql } from 'gatsby'
|
||||||
import Container from './atoms/Container'
|
import Container from './atoms/Container'
|
||||||
import Head from './molecules/Head'
|
import Head from './molecules/Head'
|
||||||
import Header from './molecules/Header'
|
import Header from './organisms/Header'
|
||||||
import styles from './Layout.module.scss'
|
import styles from './Layout.module.scss'
|
||||||
|
|
||||||
const Layout = ({ children, location }) => {
|
const Layout = ({ children, location }) => {
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.site__content,
|
.site__content,
|
||||||
.header__content,
|
|
||||||
.footer__content {
|
.footer__content {
|
||||||
padding: 0 $spacer;
|
padding: 0 $spacer;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -33,19 +32,19 @@
|
|||||||
0 -1px 4px rgba($brand-main, .2);
|
0 -1px 4px rgba($brand-main, .2);
|
||||||
transform: translate3d(0, 0, 0);
|
transform: translate3d(0, 0, 0);
|
||||||
|
|
||||||
.has-menu-open & {
|
:global(.has-menu-open) & {
|
||||||
transform: translate3d(0, 0, 0);
|
transform: translate3d(0, ($spacer * 8), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: $screen-sm) {
|
@media (min-width: $screen-sm) {
|
||||||
@include transition;
|
@include transition;
|
||||||
|
|
||||||
margin-top: $spacer * 3;
|
margin-top: $spacer * 2.65;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
|
||||||
.has-menu-open & {
|
:global(.has-menu-open) & {
|
||||||
transform: translate3d(0, ($spacer * 8), 0);
|
transform: translate3d(0, ($spacer * 5), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
src/components/atoms/Hamburger.jsx
Normal file
14
src/components/atoms/Hamburger.jsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import styles from './Hamburger.module.scss'
|
||||||
|
|
||||||
|
const Hamburger = props => (
|
||||||
|
<button type="button" className={styles.hamburgerButton} {...props}>
|
||||||
|
<span className={styles.hamburger}>
|
||||||
|
<span className={styles.hamburgerLine} />
|
||||||
|
<span className={styles.hamburgerLine} />
|
||||||
|
<span className={styles.hamburgerLine} />
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default Hamburger
|
77
src/components/atoms/Hamburger.module.scss
Normal file
77
src/components/atoms/Hamburger.module.scss
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
@import 'variables';
|
||||||
|
@import 'mixins';
|
||||||
|
|
||||||
|
.hamburgerLine {
|
||||||
|
@include transition;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
height: 3px;
|
||||||
|
width: 100%;
|
||||||
|
background: $text-color-light;
|
||||||
|
border-radius: 20px;
|
||||||
|
opacity: 1;
|
||||||
|
left: 0;
|
||||||
|
transform: rotate(0deg);
|
||||||
|
|
||||||
|
&:nth-child(1) {
|
||||||
|
top: 0;
|
||||||
|
transform-origin: left center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(2) {
|
||||||
|
top: 5px;
|
||||||
|
transform-origin: left center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(3) {
|
||||||
|
top: 10px;
|
||||||
|
transform-origin: left center;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open state
|
||||||
|
:global(.has-menu-open) & {
|
||||||
|
&:nth-child(1) {
|
||||||
|
transform: rotate(45deg);
|
||||||
|
top: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(2) {
|
||||||
|
width: 0%;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(3) {
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
top: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hamburgerButton {
|
||||||
|
padding: .65rem .85rem;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1;
|
||||||
|
vertical-align: middle;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
outline: 0;
|
||||||
|
|
||||||
|
.hamburgerLine {
|
||||||
|
background: $brand-cyan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hamburger {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
transform: rotate(0deg);
|
||||||
|
cursor: pointer;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
@ -1,60 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
// import PropTypes from 'prop-types'
|
|
||||||
import { Link } from 'gatsby'
|
|
||||||
import styles from './Header.module.scss'
|
|
||||||
import layout from '../Layout.module.scss'
|
|
||||||
|
|
||||||
const Header = () => {
|
|
||||||
return (
|
|
||||||
<header role="banner" className={styles.header}>
|
|
||||||
<div className={layout.header__content}>
|
|
||||||
<h1 className={styles.title}>
|
|
||||||
<Link className={styles.header__logo} to="/">
|
|
||||||
kremalicious
|
|
||||||
</Link>
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
{/* <nav role="navigation" className="nav-main grid__col">
|
|
||||||
<button type="button" className="menu-btn">
|
|
||||||
<div className="hamburger">
|
|
||||||
<span />
|
|
||||||
<span />
|
|
||||||
<span />
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</nav> */}
|
|
||||||
|
|
||||||
{/* <section class="site-search">
|
|
||||||
<button type="button" class="search-btn">
|
|
||||||
<svg class="icon icon-search" role="img" aria-labelledby="title">
|
|
||||||
<title id="title">Search</title>
|
|
||||||
<use xlink:href="/assets/img/sprite.svg#magnifying-glass"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<div class="search-area">
|
|
||||||
<input type="search" id="search-input" class="form-control input-search search-field" placeholder="Search everything">
|
|
||||||
<button class="close search-close">×</button>
|
|
||||||
</div>
|
|
||||||
</section> */}
|
|
||||||
|
|
||||||
{/* <ul class="nav-popover grid grid--half grid-medium--third">
|
|
||||||
<li class="grid__col">
|
|
||||||
<a class="nav-link" href="/{{ category | first }}/">
|
|
||||||
{{ category | first }}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul> */}
|
|
||||||
|
|
||||||
{/* <div id="search-popover" class="search-popover hide">
|
|
||||||
<div class="container">
|
|
||||||
<nav id="search-results" class="search-results"></nav>
|
|
||||||
</div>
|
|
||||||
</div> */}
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Header.propTypes = {}
|
|
||||||
|
|
||||||
export default Header
|
|
79
src/components/molecules/Menu.jsx
Normal file
79
src/components/molecules/Menu.jsx
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import React, { PureComponent, Fragment } from 'react'
|
||||||
|
import Helmet from 'react-helmet'
|
||||||
|
import { Link, StaticQuery, graphql } from 'gatsby'
|
||||||
|
import Hamburger from '../atoms/Hamburger'
|
||||||
|
import styles from './Menu.module.scss'
|
||||||
|
|
||||||
|
class Menu extends PureComponent {
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
menuOpen: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleMenu = () => {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
menuOpen: !prevState.menuOpen
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
isMenuOpen = () => this.state.menuOpen === true
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<Helmet>
|
||||||
|
<body className={this.isMenuOpen() ? 'has-menu-open' : null} />
|
||||||
|
</Helmet>
|
||||||
|
<StaticQuery
|
||||||
|
query={graphql`
|
||||||
|
query {
|
||||||
|
allMarkdownRemark(
|
||||||
|
sort: { fields: [fields___date], order: DESC }
|
||||||
|
) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
frontmatter {
|
||||||
|
category
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
render={data => {
|
||||||
|
const posts = data.allMarkdownRemark.edges
|
||||||
|
const categorySet = new Set()
|
||||||
|
|
||||||
|
posts.forEach(post => {
|
||||||
|
if (post.node.frontmatter.category) {
|
||||||
|
categorySet.add(post.node.frontmatter.category)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const categoryList = Array.from(categorySet)
|
||||||
|
|
||||||
|
const Categories = categoryList.map(category => (
|
||||||
|
<li key={category}>
|
||||||
|
<Link onClick={this.toggleMenu} to={`/${category}/`}>
|
||||||
|
{category}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<Hamburger onClick={this.toggleMenu} />
|
||||||
|
<ul className={styles.menu}>{Categories}</ul>
|
||||||
|
</Fragment>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Fragment>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Menu
|
42
src/components/molecules/Menu.module.scss
Normal file
42
src/components/molecules/Menu.module.scss
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
@import 'variables';
|
||||||
|
@import 'mixins';
|
||||||
|
|
||||||
|
.menu {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% + #{$spacer});
|
||||||
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
li {
|
||||||
|
list-style: none;
|
||||||
|
flex: 0 0 100%;
|
||||||
|
|
||||||
|
@media (min-width: $screen-sm) {
|
||||||
|
flex-basis: 33%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
opacity: 0;
|
||||||
|
|
||||||
|
:global(.has-menu-open) & {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $text-color;
|
||||||
|
line-height: 1;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin: 0;
|
||||||
|
font-size: $font-size-small;
|
||||||
|
text-shadow: 0 1px 0 rgba(#fff, .5);
|
||||||
|
padding: $padding-base-horizontal;
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
58
src/components/organisms/Header.jsx
Normal file
58
src/components/organisms/Header.jsx
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import React, { PureComponent } from 'react'
|
||||||
|
import { Link } from 'gatsby'
|
||||||
|
import Container from '../atoms/Container'
|
||||||
|
import Menu from '../molecules/Menu'
|
||||||
|
import Search from '../svg/MagnifyingGlass'
|
||||||
|
|
||||||
|
import styles from './Header.module.scss'
|
||||||
|
|
||||||
|
class Header extends PureComponent {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<header role="banner" className={styles.header}>
|
||||||
|
<Container>
|
||||||
|
<div className={styles.header__content}>
|
||||||
|
<h1 className={styles.title}>
|
||||||
|
<Link className={styles.header__logo} to="/">
|
||||||
|
kremalicious
|
||||||
|
</Link>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<nav role="navigation" className={styles.nav}>
|
||||||
|
<button type="button" className={styles.search}>
|
||||||
|
<Search />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<Menu />
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{/* <section class="site-search">
|
||||||
|
<div class="search-area">
|
||||||
|
<input type="search" id="search-input" class="form-control input-search search-field" placeholder="Search everything">
|
||||||
|
<button class="close search-close">×</button>
|
||||||
|
</div>
|
||||||
|
</section> */}
|
||||||
|
|
||||||
|
{/* <ul class="nav-popover grid grid--half grid-medium--third">
|
||||||
|
<li class="grid__col">
|
||||||
|
<a class="nav-link" href="/{{ category | first }}/">
|
||||||
|
{{ category | first }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul> */}
|
||||||
|
|
||||||
|
{/* <div id="search-popover" class="search-popover hide">
|
||||||
|
<div class="container">
|
||||||
|
<nav id="search-results" class="search-results"></nav>
|
||||||
|
</div>
|
||||||
|
</div> */}
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
</header>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Header.propTypes = {}
|
||||||
|
|
||||||
|
export default Header
|
@ -6,8 +6,6 @@
|
|||||||
margin-bottom: ($spacer/2);
|
margin-bottom: ($spacer/2);
|
||||||
|
|
||||||
@media (min-width: $screen-sm) {
|
@media (min-width: $screen-sm) {
|
||||||
margin-top: $spacer;
|
|
||||||
margin-bottom: $spacer;
|
|
||||||
position: fixed;
|
position: fixed;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
@ -17,6 +15,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header__content {
|
||||||
|
@include breakoutviewport;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 $spacer;
|
||||||
|
|
||||||
|
@media (min-width: $screen-md) {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Logo
|
// Logo
|
||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
|
|
||||||
@ -44,7 +55,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
margin: 0;
|
margin-top: $spacer / 5;
|
||||||
|
margin-bottom: 0;
|
||||||
// display toned down logo
|
// display toned down logo
|
||||||
// by default
|
// by default
|
||||||
@extend .logo;
|
@extend .logo;
|
||||||
@ -71,3 +83,39 @@
|
|||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search {
|
||||||
|
padding: .65rem .85rem;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1;
|
||||||
|
vertical-align: middle;
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: $spacer / 4;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
fill: $text-color-light;
|
||||||
|
width: 21px;
|
||||||
|
height: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
svg {
|
||||||
|
fill: $brand-cyan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
svg {
|
||||||
|
fill: darken($brand-cyan, 30%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -61,6 +61,20 @@ textarea {
|
|||||||
line-height: inherit;
|
line-height: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset default button element
|
||||||
|
button {
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transition: none;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Headings
|
// Headings
|
||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
|
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
@import 'mixins';
|
@import 'mixins';
|
||||||
|
|
||||||
.archiveTitle {
|
.archiveTitle {
|
||||||
font-size: $font-size-h3;
|
|
||||||
|
|
||||||
@include heading-band();
|
@include heading-band();
|
||||||
|
|
||||||
|
font-size: $font-size-h3;
|
||||||
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user