Menu update. Use react hooks, not client based script.

This commit is contained in:
tmshv committed 2019-10-15 04:39:20 +03:00
1 parent 0f1438e8db
commit ab577fa263
7 files changed
+94 -156

No files matched your search

+5
View File
@@ -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
View File
@@ -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",
-2
View File
@@ -63,8 +63,6 @@ export default class MyDocument extends Document {
<body className="custom_class">
<Main />
<NextScript />
<script src="/static/app.js" />
</body>
</Html>
);
+25 -9
View File
@@ -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>
)
}
+47 -20
View File
@@ -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>
)
}
+15
View File
@@ -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
View File
@@ -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()