docs: optimize the experience of switch of language and tabbar

This commit is contained in:
unix
2020-04-10 09:31:35 +08:00
parent 90fe7f9da6
commit 5441f70653
11 changed files with 53 additions and 72 deletions

View File

@@ -1,6 +1,7 @@
import React, { useMemo } from 'react'
import { Button, useTheme, Select, Spacer } from 'components'
import { useConfigs } from 'lib/config-context'
import useLocale from 'lib/use-locale'
import Router, { useRouter } from 'next/router'
import MoonIcon from './icons/moon'
import SunIcon from './icons/sun'
@@ -10,19 +11,22 @@ const Controls: React.FC<{}> = React.memo(({
const theme = useTheme()
const { onChange, updateChineseState } = useConfigs()
const { pathname } = useRouter()
const isChinese = useMemo(() => pathname.toLowerCase().includes('zh-cn'), [pathname])
const { locale } = useLocale()
const isChinese = useMemo(() => locale === 'zh-cn', [locale])
const isDark = useMemo(() => theme.type === 'dark', [theme.type])
const nextLocalePath = useMemo(() => {
const nextLocale = isChinese ? 'en-us' : 'zh-cn'
return pathname.replace(locale, nextLocale)
}, [locale, pathname])
const switchThemes = (val: string) => {
const isDark = val === 'dark'
onChange && onChange(isDark)
}
const switchLanguages = () => {
const nextPath = `/${isChinese ? 'en-us' : 'zh-cn'}`
updateChineseState(!isChinese)
Router.push(nextPath)
Router.push(nextLocalePath)
}
const redirectGithub = () => {
if (typeof window !== 'undefined') {
window.open('https://github.com/zeit-ui/react')

View File

@@ -1,7 +1,6 @@
import React, { useState } from 'react'
import { useTheme } from 'components'
import Sidebar from './sidebar'
import { Sides } from './sidebar/side-item'
import TabbarMobile from './sidebar/tabbar-mobile'
import useBodyScroll from 'components/utils/use-body-scroll'
import { useConfigs } from '../config-context'
@@ -15,31 +14,26 @@ export interface Props {
getStaticProps?: any
}
export interface MultilLocaleMetaInformation {
[key: string]: Sides[]
}
export const Layout: React.FC<React.PropsWithChildren<Props>> = React.memo(({ children }) => {
const theme = useTheme()
const { sides, tabbarFixed } = useConfigs()
const { tabbarFixed } = useConfigs()
const [, setBodyScroll] = useBodyScroll(null, { scrollLayer: true })
const [expanded, setExpanded] = useState<boolean>(false)
const mobileTabbarClickHandler = () => {
setExpanded(!expanded)
setBodyScroll(!expanded)
}
return (
<div className="layout">
<TabbarMobile onClick={mobileTabbarClickHandler} />
<aside className="sidebar">
<Sidebar sides={sides}/>
<Sidebar />
</aside>
<div className="side-shadow" />
<main className="main">
<div>{children}</div>
</main>
<style jsx>{`
.layout {
min-height: calc(100vh - 108px);

View File

@@ -1,37 +1,22 @@
import React, { useEffect, useMemo } from 'react'
import { Tabs, useTheme } from 'components'
import useCurrentState from 'components/utils/use-current-state'
import sides from 'lib/data/metadata.json'
import { Sides } from 'lib/components/sidebar/side-item'
import Router, { useRouter } from 'next/router'
import { useConfigs } from '../../config-context'
export interface MultilLocaleMetaInformation {
[key: string]: Sides[]
}
import Router from 'next/router'
import Metadatas from 'lib/data'
import useLocale from 'lib/use-locale'
import { useConfigs } from 'lib/config-context'
const MenuSticker = () => {
const theme = useTheme()
const { pathname } = useRouter()
const { updateSides, updateTabbarFixed } = useConfigs()
const { updateTabbarFixed } = useConfigs()
const { tabbar: currentUrlTabValue, locale } = useLocale()
const [tabValue, setTabValue, tabValueRef] = useCurrentState<string>('')
const [fixed, setFixed, fixedRef] = useCurrentState<boolean>(false)
const currentUrlTabValue = useMemo(() => {
return pathname.split('/').filter(r => !!r)[1]
}, [pathname])
const tabbarData = useMemo(() => {
const language = pathname
.split('/')
.filter(r => !!r)
const locale: string = language[0] || 'en-us'
return (sides as MultilLocaleMetaInformation)[locale]
}, [pathname])
const tabbarData = useMemo(() => Metadatas[locale], [locale])
useEffect(() => updateTabbarFixed(fixed), [fixed])
useEffect(() => setTabValue(currentUrlTabValue), [currentUrlTabValue])
useEffect(() => {
const scrollHandler = () => {
const shouldFixed = document.documentElement.scrollTop > 60
@@ -43,22 +28,11 @@ const MenuSticker = () => {
}, [])
useEffect(() => {
const currentTab = tabbarData.find(tab => tab.name === tabValueRef.current)
if (!currentTab || !Array.isArray(currentTab.children)) return
let firstChildren = currentTab.children
if (Array.isArray(firstChildren[0].children)) {
firstChildren = firstChildren[0].children
}
const defaultPath = firstChildren[0].url
if (!defaultPath) return
updateSides(currentTab.children)
const shouldRedirectDefaultPage = currentUrlTabValue !== tabValueRef.current
if (!shouldRedirectDefaultPage) return
const defaultPath = `/${locale}/${tabValueRef.current}`
Router.push(defaultPath)
}, [tabValue, tabbarData, currentUrlTabValue])
}, [tabValue, currentUrlTabValue])
return (
<>

View File

@@ -1,27 +1,34 @@
import React, { useEffect, useRef } from 'react'
import React, { useEffect, useMemo, useRef } from 'react'
import Router from 'next/router'
import { useTheme, Spacer } from 'components'
import SideItem, { SideItemProps, Sides } from './side-item'
import SideItem, { Sides } from './side-item'
import useLocale from 'lib/use-locale'
import { useConfigs } from 'lib/config-context'
import Metadatas from 'lib/data'
export interface Props {
}
export type SideGroupProps = Props & SideItemProps
export type SideChildren = Sides | Array<Sides>
export const SideGroup: React.FC<{ sides?: SideChildren }> = React.memo(({ sides }) => {
if (!sides) return null
sides = Array.isArray(sides) ? sides : [sides]
return <SideItem sides={sides} />
return <SideItem sides={sides} ><SideGroup /></SideItem>
})
export const Sidebar: React.FC<SideGroupProps> = React.memo(({ sides }) => {
export const Sidebar: React.FC<Props> = React.memo(() => {
const theme = useTheme()
const boxRef = useRef<HTMLDivElement>(null)
const { sidebarScrollHeight, updateSidebarScrollHeight } = useConfigs()
const { locale, tabbar } = useLocale()
const tabbarData = useMemo(() => {
const allSides = Metadatas[locale]
const currentSide = allSides.filter(side => side.name === tabbar)[0]
return (currentSide.children || []) as Array<Sides>
}, [locale, tabbar])
useEffect(() => {
Router.events.on('routeChangeStart', () => {
if (!boxRef.current) return
@@ -36,7 +43,7 @@ export const Sidebar: React.FC<SideGroupProps> = React.memo(({ sides }) => {
return (
<div ref={boxRef} className="sides box">
<SideItem sides={sides}>
<SideItem sides={tabbarData}>
<SideGroup />
</SideItem>
<Spacer />

View File

@@ -22,12 +22,13 @@ const SideItem: React.FC<React.PropsWithChildren<SideItemProps>> = React.memo(({
return (
<>
{sides.map((side, index) => {
const showChildren = side.children && children
return (
<div key={`${side.localeName || side.name}-${index}`} className="item">
{!side.url && <ActiveCatalog name={side.name} localeName={side.localeName} />}
{side.url && <ActiveLink href={side.url} text={side.name} />}
{side.children && <div className="children">
{showChildren && <div className="children">
{React.cloneElement(children as ReactElement, {
sides: side.children,
})}

View File

@@ -1,5 +1,4 @@
import React from 'react'
import { Sides } from 'lib/components/sidebar/side-item'
export interface Configs {
onChange?: Function
@@ -8,9 +7,6 @@ export interface Configs {
sidebarScrollHeight: number
updateSidebarScrollHeight: Function
sides: Sides[]
updateSides: Function
tabbarFixed: boolean
updateTabbarFixed: Function
}
@@ -19,9 +15,6 @@ export const defaultConfigs: Configs = {
sidebarScrollHeight: 0,
updateSidebarScrollHeight: () => {},
updateChineseState: () => {},
sides: [],
updateSides: () => {},
tabbarFixed: false,
updateTabbarFixed: () => {},

View File

@@ -2,7 +2,6 @@ import React, { useMemo, useState } from 'react'
import withDefaults from 'components/utils/with-defaults'
import { ConfigContext, Configs } from 'lib/config-context'
import { useRouter } from 'next/router'
import { Sides } from 'lib/components/sidebar/side-item'
interface Props {
onChange?: Function
@@ -19,21 +18,18 @@ const ConfigProvider: React.FC<React.PropsWithChildren<ConfigProviderProps>> = R
const { pathname } = useRouter()
const [isChinese, setIsChinese] = useState<boolean>(() => pathname.includes('zh-cn'))
const [scrollHeight, setScrollHeight] = useState<number>(0)
const [sides, setSides] = useState<Sides[]>([] as Sides[])
const [tabbarFixed, setTabbarFixed] = useState<boolean>(false)
const updateSidebarScrollHeight = (height: number) => setScrollHeight(height)
const updateChineseState = (state: boolean) => setIsChinese(state)
const updateSides = (sides: Sides[]) => setSides(sides)
const updateTabbarFixed = (state: boolean) => setTabbarFixed(state)
const initialValue = useMemo<Configs>(() => ({
onChange, sides, isChinese, tabbarFixed,
updateSides,
onChange, isChinese, tabbarFixed,
updateTabbarFixed,
updateChineseState,
sidebarScrollHeight: scrollHeight,
updateSidebarScrollHeight,
}), [onChange, scrollHeight, sides, tabbarFixed, isChinese])
}), [onChange, scrollHeight, tabbarFixed, isChinese])
return (
<ConfigContext.Provider value={initialValue}>

View File

@@ -0,0 +1,3 @@
import redirect from 'lib/redirect'
export default redirect('/en-us/components/button')

View File

@@ -0,0 +1,3 @@
import redirect from 'lib/redirect'
export default redirect('/en-us/guide/introduction')

View File

@@ -0,0 +1,3 @@
import redirect from 'lib/redirect'
export default redirect('/zh-cn/components/button')

View File

@@ -0,0 +1,3 @@
import redirect from 'lib/redirect'
export default redirect('/zh-cn/guide/introduction')