From 73b45cc3e075fefed2b053bfe0b23260a032bc68 Mon Sep 17 00:00:00 2001 From: unix Date: Mon, 6 Apr 2020 08:56:06 +0800 Subject: [PATCH] docs: add menu bar and optimize navigation --- lib/components/controls.tsx | 84 ++++----- lib/components/layout.tsx | 29 ++- lib/components/menu/index.tsx | 14 ++ lib/components/menu/menu-links.tsx | 33 ++++ lib/components/menu/menu-sticker.tsx | 170 ++++++++++++++++++ lib/components/sidebar/index.tsx | 2 +- lib/config-context.ts | 13 ++ lib/config-provider.tsx | 12 +- next.config.js | 24 ++- pages/_app.tsx | 2 + pages/en-us/components/auto-complete.mdx | 2 +- pages/en-us/components/avatar.mdx | 2 +- pages/en-us/components/badge.mdx | 2 +- pages/en-us/components/button-dropdown.mdx | 2 +- pages/en-us/components/button.mdx | 2 +- pages/en-us/components/capacity.mdx | 2 +- pages/en-us/components/card.mdx | 2 +- pages/en-us/components/checkbox.mdx | 2 +- pages/en-us/components/code.mdx | 8 +- pages/en-us/components/collapse.mdx | 2 +- pages/en-us/components/description.mdx | 4 +- pages/en-us/components/display.mdx | 2 +- pages/en-us/components/dot.mdx | 2 +- pages/en-us/components/fieldset.mdx | 2 +- pages/en-us/components/file-tree.mdx | 2 +- pages/en-us/components/image.mdx | 2 +- pages/en-us/components/input.mdx | 1 + pages/en-us/components/keyboard.mdx | 2 +- pages/en-us/components/layout.mdx | 2 +- pages/en-us/components/link.mdx | 2 +- pages/en-us/components/loading.mdx | 2 +- pages/en-us/components/modal.mdx | 7 +- pages/en-us/components/note.mdx | 2 +- pages/en-us/components/progress.mdx | 1 + pages/en-us/components/radio.mdx | 2 +- pages/en-us/components/select.mdx | 2 +- pages/en-us/components/snippet.mdx | 2 +- pages/en-us/components/spacer.mdx | 2 +- pages/en-us/components/spinner.mdx | 2 +- pages/en-us/components/table.mdx | 1 + pages/en-us/components/tabs.mdx | 1 + pages/en-us/components/tag.mdx | 2 +- pages/en-us/components/text.mdx | 2 +- pages/en-us/components/textarea.mdx | 1 + pages/en-us/components/toast.mdx | 2 +- pages/en-us/components/toggle.mdx | 2 +- .../en-us/{customization => guide}/colors.mdx | 2 +- .../installation.mdx | 2 +- .../introduction.mdx | 1 + .../server-render.mdx | 2 +- .../en-us/{customization => guide}/themes.mdx | 2 +- pages/zh-cn/components/auto-complete.mdx | 3 +- pages/zh-cn/components/avatar.mdx | 4 +- pages/zh-cn/components/badge.mdx | 3 +- pages/zh-cn/components/button-dropdown.mdx | 3 +- pages/zh-cn/components/button.mdx | 3 +- pages/zh-cn/components/capacity.mdx | 3 +- pages/zh-cn/components/card.mdx | 4 +- pages/zh-cn/components/checkbox.mdx | 3 +- pages/zh-cn/components/code.mdx | 9 +- pages/zh-cn/components/collapse.mdx | 3 +- pages/zh-cn/components/description.mdx | 3 +- pages/zh-cn/components/display.mdx | 4 +- pages/zh-cn/components/dot.mdx | 4 +- pages/zh-cn/components/fieldset.mdx | 4 +- pages/zh-cn/components/file-tree.mdx | 4 +- pages/zh-cn/components/image.mdx | 4 +- pages/zh-cn/components/input.mdx | 3 +- pages/zh-cn/components/keyboard.mdx | 4 +- pages/zh-cn/components/layout.mdx | 4 +- pages/zh-cn/components/link.mdx | 4 +- pages/zh-cn/components/loading.mdx | 4 +- pages/zh-cn/components/modal.mdx | 9 +- pages/zh-cn/components/note.mdx | 3 +- pages/zh-cn/components/progress.mdx | 3 +- pages/zh-cn/components/radio.mdx | 3 +- pages/zh-cn/components/select.mdx | 3 +- pages/zh-cn/components/snippet.mdx | 3 +- pages/zh-cn/components/spacer.mdx | 4 +- pages/zh-cn/components/spinner.mdx | 3 +- pages/zh-cn/components/table.mdx | 3 +- pages/zh-cn/components/tabs.mdx | 3 +- pages/zh-cn/components/tag.mdx | 3 +- pages/zh-cn/components/text.mdx | 3 +- pages/zh-cn/components/textarea.mdx | 3 +- pages/zh-cn/components/toast.mdx | 3 +- pages/zh-cn/components/toggle.mdx | 3 +- .../zh-cn/{customization => guide}/colors.mdx | 1 + .../installation.mdx | 1 + .../introduction.mdx | 1 + .../server-render.mdx | 1 + .../zh-cn/{customization => guide}/themes.mdx | 1 + scripts/collect-meta.js | 84 +++++++-- scripts/locales.js | 2 + 94 files changed, 523 insertions(+), 172 deletions(-) create mode 100644 lib/components/menu/index.tsx create mode 100644 lib/components/menu/menu-links.tsx create mode 100644 lib/components/menu/menu-sticker.tsx rename pages/en-us/{customization => guide}/colors.mdx (97%) rename pages/en-us/{getting-started => guide}/installation.mdx (98%) rename pages/en-us/{getting-started => guide}/introduction.mdx (97%) rename pages/en-us/{getting-started => guide}/server-render.mdx (98%) rename pages/en-us/{customization => guide}/themes.mdx (99%) rename pages/zh-cn/{customization => guide}/colors.mdx (98%) rename pages/zh-cn/{getting-started => guide}/installation.mdx (99%) rename pages/zh-cn/{getting-started => guide}/introduction.mdx (98%) rename pages/zh-cn/{getting-started => guide}/server-render.mdx (99%) rename pages/zh-cn/{customization => guide}/themes.mdx (99%) diff --git a/lib/components/controls.tsx b/lib/components/controls.tsx index 81fe304..23338f9 100644 --- a/lib/components/controls.tsx +++ b/lib/components/controls.tsx @@ -1,10 +1,9 @@ import React, { useCallback, useMemo } from 'react' -import { Button, useTheme, Spacer } from 'components' +import { Button, useTheme, Select, Spacer } from 'components' import { useConfigs } from 'lib/config-context' import Router, { useRouter } from 'next/router' import MoonIcon from './icons/moon' import SunIcon from './icons/sun' -import GithubIcon from './icons/github' const Controls: React.FC<{}> = React.memo(({ }) => { @@ -12,14 +11,14 @@ const Controls: React.FC<{}> = React.memo(({ const { onChange, updateChineseState } = useConfigs() const { pathname } = useRouter() const currentLocaleText = useMemo(() => { - return pathname.toLowerCase().includes('zh-cn') ? 'EN' : '中' + return pathname.toLowerCase().includes('zh-cn') ? 'English' : '中文文档' }, [pathname]) const isDark = useMemo(() => theme.type === 'dark', [theme.type]) - const switchThemes = useCallback(() => { - const isDark = theme.type === 'dark' - onChange && onChange(!isDark) - }, [theme.type]) - + const switchThemes = (val: string) => { + const isDark = val === 'dark' + onChange && onChange(isDark) + } + const switchLanguages = useCallback(() => { const currentIsChinese = pathname.toLowerCase().includes('zh-cn') const nextPath = `/${currentIsChinese ? 'en-us' : 'zh-cn'}` @@ -36,39 +35,45 @@ const Controls: React.FC<{}> = React.memo(({ return (
- - - - + + + + +
+ + ) +} + +export default MenuLinks diff --git a/lib/components/menu/menu-sticker.tsx b/lib/components/menu/menu-sticker.tsx new file mode 100644 index 0000000..2d796ba --- /dev/null +++ b/lib/components/menu/menu-sticker.tsx @@ -0,0 +1,170 @@ +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[] +} + +const MenuSticker = () => { + const theme = useTheme() + const { pathname } = useRouter() + const { updateSides, updateTabbarFixed } = useConfigs() + const [fixed, setFixed, fixedRef] = useCurrentState(false) + + useEffect(() => updateTabbarFixed(fixed), [fixed]) + + const tabbarData = useMemo(() => { + const language = pathname + .split('/') + .filter(r => !!r) + const locale: string = language[0] || 'en-us' + return (sides as MultilLocaleMetaInformation)[locale] + }, [pathname, sides]) + + const currentTabValue = useMemo(() => { + const language = pathname + .split('/') + .filter(r => !!r) + return language[1] + }, [pathname]) + + + useEffect(() => { + const scrollHandler = () => { + const shouldFixed = document.documentElement.scrollTop > 60 + if (shouldFixed === fixedRef.current) return + setFixed(shouldFixed) + } + document.addEventListener('scroll', scrollHandler) + return () => document.removeEventListener('scroll', scrollHandler) + }, []) + + const tabChangeHandler = (value: string) => { + const currentTab = tabbarData.find(tab => tab.name === value) + 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) + Router.push(defaultPath) + } + + useEffect(() => { + tabbarData && tabChangeHandler(currentTabValue) + }, []) + + return ( + <> +
+ + + + ) +} + +export default MenuSticker diff --git a/lib/components/sidebar/index.tsx b/lib/components/sidebar/index.tsx index bee74be..5cb90fd 100644 --- a/lib/components/sidebar/index.tsx +++ b/lib/components/sidebar/index.tsx @@ -56,7 +56,7 @@ export const Sidebar: React.FC = React.memo(({ sides }) => { .box { overflow-y: auto; overflow-x: hidden; - height: calc(100vh - 140px); + height: 100%; display: flex; flex-direction: column; align-items: center; diff --git a/lib/config-context.ts b/lib/config-context.ts index 74e2225..64f7907 100644 --- a/lib/config-context.ts +++ b/lib/config-context.ts @@ -1,4 +1,5 @@ import React from 'react' +import { Sides } from 'lib/components/sidebar/side-item' export interface Configs { onChange?: Function @@ -6,12 +7,24 @@ export interface Configs { updateChineseState: Function sidebarScrollHeight: number updateSidebarScrollHeight: Function + + sides: Sides[] + updateSides: Function + + tabbarFixed: boolean + updateTabbarFixed: Function } export const defaultConfigs: Configs = { sidebarScrollHeight: 0, updateSidebarScrollHeight: () => {}, updateChineseState: () => {}, + + sides: [], + updateSides: () => {}, + + tabbarFixed: false, + updateTabbarFixed: () => {}, } export const ConfigContext = React.createContext(defaultConfigs) diff --git a/lib/config-provider.tsx b/lib/config-provider.tsx index 31d8acf..5f5d8f3 100644 --- a/lib/config-provider.tsx +++ b/lib/config-provider.tsx @@ -2,6 +2,7 @@ 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 @@ -18,16 +19,21 @@ const ConfigProvider: React.FC> = R const { pathname } = useRouter() const [isChinese, setIsChinese] = useState(() => pathname.includes('zh-cn')) const [scrollHeight, setScrollHeight] = useState(0) + const [sides, setSides] = useState([] as Sides[]) + const [tabbarFixed, setTabbarFixed] = useState(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(() => ({ - onChange, - isChinese, + onChange, sides, isChinese, tabbarFixed, + updateSides, + updateTabbarFixed, updateChineseState, sidebarScrollHeight: scrollHeight, updateSidebarScrollHeight, - }), [onChange, scrollHeight]) + }), [onChange, scrollHeight, sides, tabbarFixed]) return ( diff --git a/next.config.js b/next.config.js index 9820534..29011b8 100644 --- a/next.config.js +++ b/next.config.js @@ -30,9 +30,29 @@ const nextConfig = { redirects() { return [ { - source: '/docs/:path*', + source: '/docs/getting-started/:path*', permanent: true, - destination: '/en-us/:path*' + destination: '/en-us/guide/:path*' + }, + { + source: '/en-us/getting-started/:path*', + permanent: true, + destination: '/en-us/guide/:path*' + }, + { + source: '/en-us/customization/:path*', + permanent: true, + destination: '/en-us/guide/:path*' + }, + { + source: '/zh-cn/getting-started/:path*', + permanent: true, + destination: '/zh-cn/guide/:path*' + }, + { + source: '/zh-cn/customization/:path*', + permanent: true, + destination: '/zh-cn/guide/:path*' }, { source: '/zh-cn/', diff --git a/pages/_app.tsx b/pages/_app.tsx index 151c4fb..333a8b3 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -3,6 +3,7 @@ import { NextPage } from 'next' import { AppProps } from 'next/app' import { useCallback, useState } from 'react' import { CSSBaseline, ZEITUIProvider, useTheme } from 'components' +import Menu from 'lib/components/menu' import ConfigContext from 'lib/config-provider' const Application: NextPage = ({ Component, pageProps }) => { @@ -33,6 +34,7 @@ const Application: NextPage = ({ Component, pageProps }) => { +