Menu update. Use react hooks, not client based script.
This commit is contained in:
1 parent
0f1438e8db
commit
ab577fa263
7 files changed
+94
-156
No files matched your search
Generated
+5
@@ -16128,6 +16128,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"use-media": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/use-media/-/use-media-1.4.0.tgz",
|
||||
"integrity": "sha512-XsgyUAf3nhzZmEfhc5MqLHwyaPjs78bgytpVJ/xDl0TF4Bptf3vEpBNBBT/EIKOmsOc8UbuECq3mrP3mt1QANA=="
|
||||
},
|
||||
"util": {
|
||||
"version": "0.10.3",
|
||||
"resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
|
||||
|
||||
+2
-1
@@ -45,7 +45,8 @@
|
||||
"redux-thunk": "^2.2.0",
|
||||
"request-promise": "^2.0.1",
|
||||
"sitemap": "^1.5.0",
|
||||
"thunkify": "^2.1.2"
|
||||
"thunkify": "^2.1.2",
|
||||
"use-media": "^1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.4.4",
|
||||
|
||||
@@ -63,8 +63,6 @@ export default class MyDocument extends Document {
|
||||
<body className="custom_class">
|
||||
<Main />
|
||||
<NextScript />
|
||||
|
||||
<script src="/static/app.js" />
|
||||
</body>
|
||||
</Html>
|
||||
);
|
||||
|
||||
@@ -2,26 +2,39 @@ import * as React from 'react'
|
||||
import cx from 'classnames'
|
||||
|
||||
export interface IMenuToggleProps {
|
||||
style?: React.CSSProperties
|
||||
open: boolean
|
||||
position: 'left' | 'right'
|
||||
onClick: () => void
|
||||
}
|
||||
|
||||
export const MenuToggle: React.FC<IMenuToggleProps> = props => {
|
||||
return (
|
||||
<div className={cx({
|
||||
open: props.open,
|
||||
close: !props.open,
|
||||
})}>
|
||||
<div
|
||||
className={cx(props.position, {
|
||||
open: props.open,
|
||||
close: !props.open,
|
||||
})}
|
||||
style={props.style}
|
||||
>
|
||||
<style jsx>{`
|
||||
div {
|
||||
//position: absolute;
|
||||
//left: 0;
|
||||
position: absolute;
|
||||
height: var(--hmenu-icon-height);
|
||||
|
||||
margin: var(--hmenu-margin);
|
||||
|
||||
display: flex;
|
||||
}
|
||||
|
||||
div.right {
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
div.left {
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
@@ -53,7 +66,10 @@ export const MenuToggle: React.FC<IMenuToggleProps> = props => {
|
||||
}
|
||||
`}</style>
|
||||
|
||||
<a href="#"></a>
|
||||
<a
|
||||
href="#"
|
||||
onClick={props.onClick}
|
||||
></a>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,13 +1,16 @@
|
||||
import * as React from 'react'
|
||||
import cx from 'classnames'
|
||||
import { getPathWithNoTrailingSlash } from '../../lib/url'
|
||||
import { MenuToggle } from './MenuToggle'
|
||||
import { useScreenType } from '../../hooks/useScreenType'
|
||||
|
||||
const itemUrl = url => getPathWithNoTrailingSlash(url)
|
||||
const itemUrl = (url: string) => getPathWithNoTrailingSlash(url)
|
||||
|
||||
const selectedClassName = flag => flag
|
||||
const selectedClassName = (flag: boolean) => flag
|
||||
? 'selected'
|
||||
: ''
|
||||
|
||||
const hmenuCurClassName = flag => flag
|
||||
const hmenuCurClassName = (flag: boolean) => flag
|
||||
? 'HMenu__item--cur'
|
||||
: ''
|
||||
|
||||
@@ -18,22 +21,46 @@ const MenuItem = ({ active, text, url }) => active
|
||||
<a href={itemUrl(url)}>{text}</a>
|
||||
)
|
||||
|
||||
const MenuToggle = () => (
|
||||
<div className="HMenu__toggle">
|
||||
<a href="#"></a>
|
||||
</div>
|
||||
)
|
||||
export interface IMenuProps {
|
||||
items: any[]
|
||||
}
|
||||
|
||||
export const Menu = ({ items }) => (
|
||||
<menu className="main-menu HMenu" data-toggle-width="1024">
|
||||
<MenuToggle />
|
||||
export const Menu: React.FC<IMenuProps> = props => {
|
||||
const isMobile = useScreenType(['phone', 'tablet'])
|
||||
const [open, setOpen] = React.useState(false)
|
||||
const onClick = React.useCallback(
|
||||
() => {
|
||||
setOpen(!open)
|
||||
},
|
||||
[open]
|
||||
)
|
||||
|
||||
{items.map((item, index) => (
|
||||
<li key={index}
|
||||
className={`HMenu__item ${hmenuCurClassName(item.highlighted)} ${item.color} ${selectedClassName(item.highlighted)}`}
|
||||
>
|
||||
<MenuItem {...item} />
|
||||
</li>
|
||||
))}
|
||||
</menu>
|
||||
)
|
||||
React.useEffect(() => {
|
||||
console.log(isMobile)
|
||||
}, [isMobile])
|
||||
|
||||
return (
|
||||
<menu className="main-menu HMenu" data-toggle-width="1024">
|
||||
{!isMobile ? null : (
|
||||
<MenuToggle
|
||||
open={open}
|
||||
position={'right'}
|
||||
onClick={onClick}
|
||||
/>
|
||||
)}
|
||||
|
||||
{props.items.map((item, index) => (
|
||||
<li key={index}
|
||||
className={cx(
|
||||
'HMenu__item',
|
||||
hmenuCurClassName(item.highlighted),
|
||||
selectedClassName(item.highlighted),
|
||||
item.color,
|
||||
)}
|
||||
>
|
||||
<MenuItem {...item} />
|
||||
</li>
|
||||
))}
|
||||
</menu>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import * as React from 'react'
|
||||
import useMedia from 'use-media'
|
||||
|
||||
export type Type = 'phone' | 'tablet' | 'laptop' | 'desktop'
|
||||
|
||||
export function useScreenType(types: Type[]): boolean {
|
||||
const isPhone = useMedia('(max-width: 31.25em)')
|
||||
const [match, setMatch] = React.useState(false)
|
||||
|
||||
React.useEffect(() => {
|
||||
setMatch(isPhone && types.includes('phone'))
|
||||
}, [isPhone])
|
||||
|
||||
return match
|
||||
}
|
||||
-124
@@ -1,124 +0,0 @@
|
||||
const body = document.querySelector('body')
|
||||
|
||||
function isFoldedState(element) {
|
||||
const w = body.clientWidth
|
||||
const toggleWidth = getToggleWidth(element)
|
||||
|
||||
return w <= toggleWidth
|
||||
}
|
||||
|
||||
function isFolded(element) {
|
||||
return element.classList.contains('HMenu--folded')
|
||||
}
|
||||
|
||||
function isUnfolded(element) {
|
||||
return element.classList.contains('HMenu--unfolded')
|
||||
}
|
||||
|
||||
function isOpen(element) {
|
||||
return element.classList.contains('HMenu--open')
|
||||
}
|
||||
|
||||
function isClosed(element) {
|
||||
return element.classList.contains('HMenu--closed')
|
||||
}
|
||||
|
||||
function foldMenu(element) {
|
||||
element.classList.remove('HMenu--unfolded')
|
||||
element.classList.add('HMenu--folded')
|
||||
|
||||
return element
|
||||
}
|
||||
|
||||
function unfoldMenu(element) {
|
||||
element.classList.remove('HMenu--folded')
|
||||
element.classList.add('HMenu--unfolded')
|
||||
|
||||
return element
|
||||
}
|
||||
|
||||
function openMenu(element) {
|
||||
body.classList.add('no-scroll')
|
||||
element.classList.remove('HMenu--closed')
|
||||
element.classList.add('HMenu--open')
|
||||
|
||||
setTimeout(() => {
|
||||
document.querySelector('main').style.display = 'none'
|
||||
}, 100)
|
||||
|
||||
return element
|
||||
}
|
||||
|
||||
function closeMenu(element) {
|
||||
body.classList.remove('no-scroll')
|
||||
element.classList.remove('HMenu--open')
|
||||
element.classList.add('HMenu--closed')
|
||||
|
||||
document.querySelector('main').style.display = 'block'
|
||||
|
||||
return element
|
||||
}
|
||||
|
||||
function toggleMenu(element) {
|
||||
if (isOpen(element)) {
|
||||
closeMenu(element)
|
||||
} else {
|
||||
openMenu(element)
|
||||
}
|
||||
}
|
||||
|
||||
function createToggle() {
|
||||
return `
|
||||
<div>
|
||||
<a class="HMenu__toggle" href="#">✕</a>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
function getToggleWidth(element) {
|
||||
const value = element.dataset.toggleWidth
|
||||
if (value) return Number(value)
|
||||
|
||||
return 700
|
||||
}
|
||||
|
||||
function runHmenu() {
|
||||
const menus = [...document.querySelectorAll('.HMenu')]
|
||||
|
||||
function initMenus() {
|
||||
return menus
|
||||
.map(menu => {
|
||||
const toggle = menu.querySelector('.HMenu__toggle')
|
||||
toggle.addEventListener('click', e => {
|
||||
e.preventDefault()
|
||||
toggleMenu(menu)
|
||||
})
|
||||
|
||||
if (isFoldedState(menu)) {
|
||||
return foldMenu(menu)
|
||||
} else {
|
||||
return unfoldMenu(menu)
|
||||
}
|
||||
})
|
||||
.map(menu => closeMenu(menu))
|
||||
}
|
||||
|
||||
function handleMenus() {
|
||||
return menus.map(menu => {
|
||||
const foldedState = isFoldedState(menu)
|
||||
|
||||
if (foldedState && !isFolded(menu)) {
|
||||
return foldMenu(menu)
|
||||
} else if (!foldedState && isFolded(menu)) {
|
||||
return unfoldMenu(menu)
|
||||
} else {
|
||||
return menu
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
initMenus()
|
||||
window.addEventListener('resize', handleMenus)
|
||||
}
|
||||
|
||||
runHmenu()
|
||||
Reference in new issue
Block a user