docs: restore the scroll bar of the menu when hash changed

This commit is contained in:
unix
2020-04-04 05:55:00 +08:00
parent 6bd8448cb2
commit 3e659bac2c
8 changed files with 53 additions and 58 deletions

View File

@@ -0,0 +1,16 @@
import React from 'react'
export interface Configs {
onChange?: Function
sidebarScrollHeight: number
updateSidebarScrollHeight: Function
}
export const defaultConfigs: Configs = {
sidebarScrollHeight: 0,
updateSidebarScrollHeight: () => {},
}
export const ConfigContext = React.createContext<Configs>(defaultConfigs)
export const useConfigs = (): Configs => React.useContext(ConfigContext)

View File

@@ -1,6 +1,6 @@
import React, { useMemo, useState } from 'react'
import withDefaults from 'components/utils/with-defaults'
import { ConfigContext } from 'lib/states/config-context'
import { ConfigContext, Configs } from './config-context'
interface Props {
onChange?: Function
@@ -14,15 +14,15 @@ export type ConfigProviderProps = Props & typeof defaultProps
const ConfigProvider: React.FC<React.PropsWithChildren<ConfigProviderProps>> = React.memo(({
onChange, children,
}) => {
const [shouldScroll, setShouldScroll] = useState<boolean>(false)
const updateShouldScroll = (next: boolean) => {
setShouldScroll(next)
const [scrollHeight, setScrollHeight] = useState<number>(0)
const updateSidebarScrollHeight = (height: number) => {
setScrollHeight(height)
}
const initialValue = useMemo(() => ({
const initialValue = useMemo<Configs>(() => ({
onChange,
shouldScroll,
updateShouldScroll,
}), [onChange, shouldScroll])
sidebarScrollHeight: scrollHeight,
updateSidebarScrollHeight,
}), [onChange, scrollHeight])
return (
<ConfigContext.Provider value={initialValue}>

View File

@@ -1,6 +1,6 @@
import React, { useCallback, useMemo } from 'react'
import { Button, useTheme, Spacer } from 'components'
import useConfigs from 'lib/states/use-config'
import { useConfigs } from './config-context'
import MoonIcon from './icons/moon'
import SunIcon from './icons/sun'
import GithubIcon from './icons/github'

View File

@@ -1,27 +1,17 @@
import React, { Children, useEffect } from 'react'
import React, { Children } from 'react'
import Link from 'next/link'
import { useRouter } from 'next/router'
import useConfigs from 'lib/states/use-config'
export interface Props {
onAcitve?: Function
index: number
total: number
href: string
}
const ActiveLink: React.FC<React.PropsWithChildren<Props>> = React.memo(
({ children, index, href }) => {
const { updateShouldScroll } = useConfigs()
({ children, href }) => {
const { pathname } = useRouter()
const isActive = pathname === href
const child = Children.only(children)
useEffect(() => {
if (!isActive) return
updateShouldScroll && updateShouldScroll(index > 16)
}, [isActive])
return (
<Link href={href}>

View File

@@ -1,17 +1,23 @@
import React, { useEffect, useMemo, useRef } from 'react'
import { withRouter, Router } from 'next/router'
import React, { PropsWithChildren, useEffect, useRef } from 'react'
import Router from 'next/router'
import { useTheme, Spacer } from 'components'
import SideItem, { SideItemProps, Sides } from './side-item'
import useConfigs from 'lib/states/use-config'
import { useConfigs } from '../config-context'
export interface Props {
router: Router
}
export type SideGroupProps = Props & SideItemProps
export type SideChildren = Sides | Array<Sides>
const areEqual = (
preProps: Readonly<PropsWithChildren<SideGroupProps>>,
nextProps: Readonly<PropsWithChildren<SideGroupProps>>,
): boolean => {
return preProps.sides.length === nextProps.sides.length
}
export const SideGroup: React.FC<{ sides?: SideChildren }> = React.memo(({ sides }) => {
if (!sides) return null
sides = Array.isArray(sides) ? sides : [sides]
@@ -21,17 +27,19 @@ export const SideGroup: React.FC<{ sides?: SideChildren }> = React.memo(({ sides
export const Sidebar: React.FC<SideGroupProps> = React.memo(({ sides }) => {
const theme = useTheme()
const boxRef = useRef<HTMLDivElement>(null)
const { shouldScroll, updateShouldScroll } = useConfigs()
const totalHeight = useMemo<number>(() => {
if (!sides || !Array.isArray(sides)) return 0
return sides.length * 36
}, [sides])
const { sidebarScrollHeight, updateSidebarScrollHeight } = useConfigs()
useEffect(() => {
if (!boxRef.current || !shouldScroll) return
updateShouldScroll && updateShouldScroll(false)
boxRef.current.scrollTo({ top: boxRef.current.scrollHeight })
}, [shouldScroll])
Router.events.on('routeChangeStart', () => {
if (!boxRef.current) return
updateSidebarScrollHeight(boxRef.current.scrollTop || 0)
})
}, [])
useEffect(() => {
if (!boxRef.current) return
boxRef.current.scrollTo({ top: sidebarScrollHeight })
}, [boxRef.current])
return (
<div ref={boxRef} className="sides box">
@@ -41,11 +49,10 @@ export const Sidebar: React.FC<SideGroupProps> = React.memo(({ sides }) => {
<Spacer />
<style jsx>{`
.sides {
height: ${totalHeight}px;
width: 100%;
padding-bottom: ${theme.layout.gap};
}
.box {
overflow-y: auto;
overflow-x: hidden;
@@ -74,6 +81,6 @@ export const Sidebar: React.FC<SideGroupProps> = React.memo(({ sides }) => {
`}</style>
</div>
)
})
}, areEqual)
export default withRouter(Sidebar)
export default Sidebar

View File

@@ -26,9 +26,7 @@ const SideItem: React.FC<React.PropsWithChildren<SideItemProps>> = React.memo(({
{!side.url && <ActiveCatalog name={side.name} />}
{side.url && (
<div className="link">
<ActiveLink href={side.url} index={index} total={sides.length}>
<a>{side.name}</a>
</ActiveLink>
<ActiveLink href={side.url}><a>{side.name}</a></ActiveLink>
</div>
)}

View File

@@ -1,10 +0,0 @@
import React from 'react'
export interface Configs {
onChange?: Function
shouldScroll?: boolean
updateShouldScroll?: Function
}
export const ConfigContext = React.createContext<Configs>({})

View File

@@ -1,6 +0,0 @@
import React from 'react'
import { ConfigContext, Configs } from './config-context'
const useConfigs = (): Configs => React.useContext(ConfigContext)
export default useConfigs