To receive notifications about scheduled maintenance, please subscribe to the mailing-list gitlab-operations@sympa.ethz.ch. You can subscribe to the mailing-list at https://sympa.ethz.ch

Commit 624d8405 authored by Sandro Lutz's avatar Sandro Lutz Committed by Sandro Lutz
Browse files

Add item highlighting on «How to Ersti» page

parent fdc3d3b0
......@@ -5369,14 +5369,6 @@
}
}
},
"animated-scroll-to": {
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/animated-scroll-to/-/animated-scroll-to-2.0.12.tgz",
"integrity": "sha512-08TlNWa0Os38ShzScfrlV7c4w3QCZWUG+jhrx2ojMmI8apR8o3C1RwLxEaSKyu8RmcJvU89z3HcKObbAdHMHGQ==",
"requires": {
"@types/node": "^14.11.10"
}
},
"ansi-align": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz",
......@@ -18205,6 +18197,11 @@
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
"integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4="
},
"lodash.throttle": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
},
"lodash.toarray": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz",
......@@ -21971,6 +21968,15 @@
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
"integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg=="
},
"react-scroll": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/react-scroll/-/react-scroll-1.8.1.tgz",
"integrity": "sha512-UAKmawFHn+c7x/DoXuHqOsQ5xwNk2Dxv7vP8Ft41K2hglPWkshcSos0tMTr8704UkFqImoUGzMTdN4vuZXoqbw==",
"requires": {
"lodash.throttle": "^4.1.1",
"prop-types": "^15.7.2"
}
},
"react-transition-group": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz",
......@@ -12,7 +12,6 @@
"@reach/router": "^1.3.4",
"ajv": "^6.12.6",
"amiv-react-components": "git+https://gitlab.ethz.ch/amiv/react-components.git#fc02eef7d6af30831310c21fc258e56218b023db",
"animated-scroll-to": "^2.0.12",
"axios": "^0.21.0",
"debounce": "^1.2.0",
"filesize": "^6.1.0",
......@@ -45,6 +44,7 @@
"react-helmet": "^6.1.0",
"react-intl": "^5.10.6",
"react-redux": "^7.2.2",
"react-scroll": "^1.8.1",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",
"typeface-roboto": "1.1.13"
......
import { useState, useEffect, useRef } from 'react'
import { useDispatch } from 'react-redux'
import animateScrollTo from 'animated-scroll-to'
import { animateScroll } from 'react-scroll'
import { useIntl } from 'gatsby-plugin-intl'
import { useTheme } from '@material-ui/core'
......@@ -68,10 +68,15 @@ const useFilteredList = (
useEffect(() => {
if (itemsReady && ref.current && shouldScroll) {
setShouldScroll(false)
animateScrollTo(ref.current, {
verticalOffset: -theme.shape.headerHeight,
speed: 125,
})
console.log(ref.current.offsetTop)
console.log(ref.current.getBoundingClientRect().top)
animateScroll.scrollTo(
ref.current.getBoundingClientRect().top - theme.shape.headerHeight,
{
duration: 250,
smooth: 'easeInOutQuint',
}
)
}
}, [itemsReady, ref.current, shouldScroll])
......
import React from 'react'
import React, { useState } from 'react'
import { useStaticQuery, graphql } from 'gatsby'
import { makeStyles } from '@material-ui/styles'
import { makeStyles, useTheme } from '@material-ui/styles'
import { FormattedMessage } from 'gatsby-plugin-intl'
import { Link } from 'react-scroll'
import Layout from '../../components/layout'
import FilteredListLayout from '../../components/filteredListPage/layout'
import TranslatedContent from '../../components/general/translatedContent'
import { rateLimit } from '../../utils'
const useStyles = makeStyles(
theme => ({
......@@ -48,10 +50,15 @@ const useStyles = makeStyles(
tableOfContentLinkItem: {
color: theme.palette.text.primary,
textDecoration: 'none',
cursor: 'pointer',
'&:hover': {
color: theme.palette.secondary.main,
},
},
tableOfContentActiveLinkItem: {
color: theme.palette.secondary.main,
fontWeigth: 600,
},
tableOfContentMainLinkItem: {
fontWeight: 600,
},
......@@ -60,7 +67,9 @@ const useStyles = makeStyles(
)
const HowToErstiPage = () => {
const [activeMenuItem, setActiveMenuItem] = useState(undefined)
const classes = useStyles()
const theme = useTheme()
const {
howToErstiJson: { nodes: howToErstiJsonNodes },
} = useStaticQuery(
......@@ -118,6 +127,54 @@ const HowToErstiPage = () => {
const menuItems = []
const contentItems = []
const handleScroll = () => {
const windowScrollTop =
document.body.scrollTop || document.documentElement.scrollTop
const checkActiveState = slug => {
const element = document.getElementById(slug)
return (
element &&
windowScrollTop < element.offsetTop - element.offsetHeight / 2
)
}
const findActiveItem = (items, firstIteration) => {
let newActiveItem
items.forEach(item => {
if (newActiveItem) return
const slug = firstIteration ? item.data.slug : item.slug
const subitems = firstIteration ? item.data.subitems : item.subitems
if (checkActiveState(slug)) {
newActiveItem = slug
return
}
if (subitems) {
newActiveItem = findActiveItem(subitems, false)
}
})
return newActiveItem
}
const newActiveItem = findActiveItem(howToErstiJsonNodes, true)
setActiveMenuItem(newActiveItem)
}
const handleScrollRateLimited = rateLimit(handleScroll, 250)
React.useEffect(() => {
window.addEventListener('scroll', handleScrollRateLimited)
// cleanup this component
return () => {
window.removeEventListener('scroll', handleScroll)
}
}, [])
const createMenuItem = (hierarchyLevel, { title, slug, subitems }) => {
if (!title) return undefined
......@@ -125,17 +182,23 @@ const HowToErstiPage = () => {
if (hierarchyLevel <= 2) {
classNames.push(classes.tableOfContentMainLinkItem)
}
if (activeMenuItem === slug) {
classNames.push(classes.tableOfContentActiveLinkItem)
}
return (
<li>
<TranslatedContent
content={title}
parseMarkdown={false}
component="a"
component={Link}
noEscape
noHint
className={classNames.join(' ')}
href={`#${slug}`}
to={slug}
offset={-theme.shape.headerHeight - 120}
smooth={true}
duration={500}
/>
{subitems && subitems.length > 0 && (
<ul>
......
......@@ -37,11 +37,33 @@ const sleep = milliseconds => {
return new Promise(resolve => setTimeout(resolve, milliseconds))
}
const rateLimit = (func, wait) => {
let timeout
let lastCalled = 0
return function outer(...args) {
const context = this
const callFunc = () => {
timeout = null
lastCalled = Date.now()
func.apply(context, args)
}
const callNow = Date.now() - wait > lastCalled
clearTimeout(timeout)
if (callNow) {
callFunc()
} else {
timeout = setTimeout(callFunc, wait)
}
}
}
export {
isBrowser,
isDevEnvironment,
isObject,
sleep,
rateLimit,
randomString,
translateMessage,
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment