docs: add menu bar and optimize navigation

This commit is contained in:
unix
2020-04-06 08:56:06 +08:00
parent 565cc8f2b9
commit 73b45cc3e0
94 changed files with 523 additions and 172 deletions

View File

@@ -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 (
<div className="controls">
<div className="tools">
<Spacer x={.5} />
<Button className="button" auto type="abort"
onClick={switchThemes}>
{isDark ? <SunIcon width={16} height={16} /> : <MoonIcon width={16} height={16} />}
</Button>
<Button className="button" auto type="abort"
onClick={redirectGithub}>
<GithubIcon width={16} height={16} />
</Button>
<Button className="button" auto type="abort"
onClick={switchLanguages}>
<span>{currentLocaleText}</span>
</Button>
<Button auto type="abort" size="small" onClick={redirectGithub}>Github</Button>
<Spacer x={.25} />
<Button auto type="abort" size="small" onClick={switchLanguages}>{currentLocaleText}</Button>
<Spacer x={.75} />
<Select size="small" pure onChange={switchThemes} initialValue={isDark ? 'dark' : 'light'}>
<Select.Option value="light">
<div className="select-content">
<SunIcon width={16} height={16} /> Light
</div>
</Select.Option>
<Select.Option value="dark">
<div className="select-content">
<MoonIcon width={16} height={16} /> Dark
</div>
</Select.Option>
</Select>
</div>
<style jsx>{`
.controls {
height: 110px;
height: 100%;
display: flex;
align-items: flex-start;
flex-direction: column-reverse;
margin: 0;
padding-bottom: ${theme.layout.gapHalf};
position: relative;
}
.controls :global(.button) {
width: 40px;
height: 40px;
padding: 0;
.controls :global(.select) {
width: min-content;
min-width: unset;
}
.select-content {
width: auto;
display: inline-flex;
justify-content: center;
align-items: center;
margin-right: 5px;
}
.select-content :global(svg) {
margin-right: .5rem;
}
.tools {
@@ -78,25 +83,6 @@ const Controls: React.FC<{}> = React.memo(({
align-items: center;
}
.tools:before {
content: "";
display: inline-block;
height: 1.25rem;
width: .3125rem;
background-color: ${theme.palette.accents_2};
}
.controls :global(.line) {
width: 150px;
height: 55px;
cursor: pointer;
background-color: ${theme.palette.background};
position: relative;
z-index: 100;
transition: all 200ms ease;
overflow: hidden;
}
@media only screen and (max-width: 767px) {
.controls {
display: none;

View File

@@ -1,12 +1,10 @@
import React, { useMemo, useState } from 'react'
import { useRouter } from 'next/router'
import React, { useState } from 'react'
import { useTheme } from 'components'
import Controls from './controls'
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 sides from 'lib/data/metadata.json'
import { useConfigs } from '../config-context'
export interface Meta {
title: string
@@ -23,27 +21,19 @@ export interface MultilLocaleMetaInformation {
export const Layout: React.FC<React.PropsWithChildren<Props>> = React.memo(({ children }) => {
const theme = useTheme()
const { pathname } = useRouter()
const { sides, tabbarFixed } = useConfigs()
const [, setBodyScroll] = useBodyScroll(null, { scrollLayer: true })
const [expanded, setExpanded] = useState<boolean>(false)
const mobileTabbarClickHandler = () => {
setExpanded(!expanded)
setBodyScroll(!expanded)
}
const sideData = useMemo(() => {
const language = pathname
.split('/')
.filter(r => !!r)
const locale: string = language[0] || 'en-us'
return (sides as MultilLocaleMetaInformation)[locale]
}, [pathname, sides])
return (
<div className="layout">
<TabbarMobile onClick={mobileTabbarClickHandler} />
<aside className="sidebar">
<Controls />
<Sidebar sides={sideData}/>
<Sidebar sides={sides}/>
</aside>
<div className="side-shadow" />
<main className="main">
@@ -52,7 +42,7 @@ export const Layout: React.FC<React.PropsWithChildren<Props>> = React.memo(({ ch
<style jsx>{`
.layout {
min-height: 100vh;
min-height: calc(100vh - 108px);
max-width: 1000px;
margin: 0 auto;
padding: 0 ${theme.layout.gap};
@@ -65,10 +55,15 @@ export const Layout: React.FC<React.PropsWithChildren<Props>> = React.memo(({ ch
margin-right: 20px;
-webkit-overflow-scrolling: touch;
-webkit-flex-shrink: 0;
height: 100%;
height: calc(100% - 2rem - 140px + ${tabbarFixed ? '60px' : 0});
position: fixed;
top: 140px;
bottom: 2rem;
transform: translateY(${tabbarFixed ? '-60px' : 0});
transition: transform 200ms ease-out;
z-index: 100;
}
.side-shadow {
width: 220px;
flex-shrink: 0;

View File

@@ -0,0 +1,14 @@
import React from 'react'
import MenuLinks from './menu-links'
import MenuSticker from './menu-sticker'
const Menu = () => {
return (
<div>
<MenuLinks />
<MenuSticker />
</div>
)
}
export default Menu

View File

@@ -0,0 +1,33 @@
import React from 'react'
import { useTheme } from 'components'
import Controls from 'lib/components/controls'
const MenuLinks = () => {
const theme = useTheme()
return (
<nav>
<div className="site-name">
<h3>ZEIT UI - React</h3>
</div>
<div className="links">
<Controls />
</div>
<style jsx>{`
nav {
display: flex;
align-items: center;
justify-content: space-between;
max-width: 1000px;
user-select: none;
position: relative;
margin: 0 auto;
padding: 0 ${theme.layout.gap};
height: 60px;
}
`}</style>
</nav>
)
}
export default MenuLinks

View File

@@ -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<boolean>(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 (
<>
<div className={`nav-fill ${fixed ? 'active' : ''}`} />
<nav className={fixed ? 'fixed' : ''}>
<div className="sticker">
<div className="inner">
<Tabs value={currentTabValue} onChange={tabChangeHandler}>
{tabbarData ? tabbarData.map(tab => (
<Tabs.Item label={tab.localeName || tab.name}
value={tab.name}
key={tab.name} />
)) : null}
</Tabs>
</div>
</div>
</nav>
<style jsx>{`
.nav-fill {
width: 0;
height: 0;
opacity: 0;
visibility: hidden;
pointer-events: none;
}
.nav-fill.active {
height: 48px;
visibility: visible;
}
nav {
position: relative;
width: 100%;
height: 48px;
background-color: ${theme.palette.background};
}
nav.fixed {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 3000;
background-color: ${theme.palette.background};
box-shadow: rgba(0, 0, 0, 0.1) 0 0 15px 0;
}
.sticker {
position: relative;
height: 100%;
width: 100%;
}
.sticker:before {
position: absolute;
content: '';
height: 1px;
left: 0;
right: 0;
bottom: 0;
background-color: ${theme.palette.border};
}
.inner {
max-width: 1000px;
padding: 0 ${theme.layout.gap};
width: 100%;
display: flex;
align-items: flex-end;
height: 100%;
overflow: auto;
z-index: 1000;
margin: 0 auto;
}
.inner :global(.content) {
display: none;
}
.inner :global(.tabs), .inner :global(header) {
height: 100%;
border: none;
}
.inner :global(.tab) {
height: calc(100% - 2px);
padding-top: 0;
padding-bottom: 0;
color: ${theme.palette.accents_5};
font-size: .875rem;
}
.inner :global(.tab):hover {
color: ${theme.palette.foreground};
}
.inner :global(.active) {
color: ${theme.palette.foreground};
}
`}</style>
</>
)
}
export default MenuSticker

View File

@@ -56,7 +56,7 @@ export const Sidebar: React.FC<SideGroupProps> = React.memo(({ sides }) => {
.box {
overflow-y: auto;
overflow-x: hidden;
height: calc(100vh - 140px);
height: 100%;
display: flex;
flex-direction: column;
align-items: center;

View File

@@ -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<Configs>(defaultConfigs)

View File

@@ -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<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,
isChinese,
onChange, sides, isChinese, tabbarFixed,
updateSides,
updateTabbarFixed,
updateChineseState,
sidebarScrollHeight: scrollHeight,
updateSidebarScrollHeight,
}), [onChange, scrollHeight])
}), [onChange, scrollHeight, sides, tabbarFixed])
return (
<ConfigContext.Provider value={initialValue}>

View File

@@ -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/',

View File

@@ -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<AppProps> = ({ Component, pageProps }) => {
@@ -33,6 +34,7 @@ const Application: NextPage<AppProps> = ({ Component, pageProps }) => {
<ZEITUIProvider theme={{ type: themeType }}>
<CSSBaseline />
<ConfigContext onChange={changeHandle}>
<Menu />
<Component {...pageProps} />
</ConfigContext>
<style global jsx>{`

View File

@@ -4,7 +4,7 @@ import { useState, useRef, useEffect } from 'react'
export const meta = {
title: 'Auto-Complete',
description: 'auto-complete',
group: 'Data Entry',
}
## Auto Complete

View File

@@ -3,7 +3,7 @@ import { Avatar, Spacer } from 'components'
export const meta = {
title: 'avatar',
description: 'avatar',
group: 'Data Display',
}
## Avatar

View File

@@ -3,7 +3,7 @@ import { Badge, Spacer } from 'components'
export const meta = {
title: 'Badge',
description: 'Badge',
group: 'Data Display',
}
## Badge

View File

@@ -5,7 +5,7 @@ import { ButtonDropdown, Spacer } from 'components'
export const meta = {
title: 'button-dropdown',
description: 'tenotext',
group: 'Navigation',
index: 101,
}

View File

@@ -4,7 +4,7 @@ import Router from 'next/router'
export const meta = {
title: 'button',
description: 'tenotext',
group: 'General',
}
## Button

View File

@@ -3,7 +3,7 @@ import { Capacity, Spacer, useTheme } from 'components'
export const meta = {
title: 'Capacity',
description: 'tenotext',
group: 'Data Display'
}
## Capacity

View File

@@ -3,7 +3,7 @@ import { Card } from 'components'
export const meta = {
title: 'card',
description: 'tenotext',
group: 'Surfaces',
}
## Card

View File

@@ -3,7 +3,7 @@ import { Checkbox, Spacer } from 'components'
export const meta = {
title: 'checkbox',
description: 'tenotext',
group: 'Data Entry',
}
## Checkbox

View File

@@ -1,16 +1,20 @@
import { Layout, Playground, Attributes } from 'lib/components'
import { Code, Note, Link } from 'components'
import NextLink from 'next/link'
export const meta = {
title: 'Code',
description: 'tenotext',
group: 'General',
}
## Code
Show source code in a standardized way.
<Note>Want to display <Code>shell</Code> code snippets? Try <Link pure color href="/en-us/components/snippet">Snippet</Link>.</Note>
<Note>
Want to display <Code>shell</Code> code snippets?
Try <NextLink href="/en-us/components/snippet"><Link pure color>Snippet</Link></NextLink>.
</Note>
<Playground
desc="Basic inline codes."

View File

@@ -3,7 +3,7 @@ import { Collapse, Spacer, Text } from 'components'
export const meta = {
title: 'collapse',
description: 'collapse',
group: 'Surfaces',
}
## Collapse

View File

@@ -2,8 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Description, Code } from 'components'
export const meta = {
title: 'description',
description: 'tenotext',
title: 'Description',
group: 'Data Display',
}
## Description

View File

@@ -3,7 +3,7 @@ import { Display, Code, Snippet } from 'components'
export const meta = {
title: 'Display',
description: 'tenotext',
group: 'Data Display',
}
## Display

View File

@@ -3,7 +3,7 @@ import { Dot } from 'components'
export const meta = {
title: 'Dot',
description: 'tenotext',
group: 'Data Display',
}
## Dot

View File

@@ -3,7 +3,7 @@ import { Card, Fieldset, Button, Text } from 'components'
export const meta = {
title: 'fieldset',
description: 'tenotext',
group: 'Surfaces',
}
## Fieldset

View File

@@ -3,7 +3,7 @@ import { Tree, useToasts } from 'components'
export const meta = {
title: 'File-Tree',
description: 'File-Tree',
group: 'Data Display',
}
## File Tree

View File

@@ -3,7 +3,7 @@ import { Image, Display, Code } from 'components'
export const meta = {
title: 'Image',
description: 'tenotext',
group: 'Data Display'
}
## Image

View File

@@ -5,6 +5,7 @@ import { useState, useEffect } from 'react'
export const meta = {
title: 'Input',
group: 'Data Entry',
}
## Input

View File

@@ -3,7 +3,7 @@ import { Keyboard } from 'components'
export const meta = {
title: 'keyboard',
description: 'tenotext',
group: 'Data Display',
}
## Keyboard

View File

@@ -3,7 +3,7 @@ import { Row, Col } from 'components'
export const meta = {
title: 'layout',
description: 'tenotext',
group: 'layout',
}
## Layout

View File

@@ -4,7 +4,7 @@ import NextLink from 'next/link'
export const meta = {
title: 'link',
description: 'tenotext',
group: 'Navigation',
}
## Link

View File

@@ -3,7 +3,7 @@ import { Loading, Spacer, Row } from 'components'
export const meta = {
title: 'Loading',
description: 'Loading',
group: 'Feedback',
}
## Loading

View File

@@ -1,16 +1,21 @@
import { Layout, Playground, Attributes } from 'lib/components'
import { Modal, Button, Code, useModal, Note, Link } from 'components'
import NextLink from 'next/link'
import { useState } from 'react'
export const meta = {
title: 'modal',
group: 'Feedback',
}
## Modal
Display popup content that requires attention or provides additional information.
<Note>Just want a text notification? Try <Link pure color href="/en-us/components/toast">Toast component</Link>.</Note>
<Note>
Just want a text notification?
Try <NextLink href="/en-us/components/toast"><Link pure color>Toast component</Link></NextLink>.
</Note>
<Playground
title="Basic"

View File

@@ -3,7 +3,7 @@ import { Note } from 'components'
export const meta = {
title: 'note',
description: 'tenotext',
group: 'Feedback',
}
## Note

View File

@@ -4,6 +4,7 @@ import { useState } from 'react'
export const meta = {
title: 'Progress',
group: 'Feedback',
}
## Progress

View File

@@ -4,7 +4,7 @@ import { useState } from 'react'
export const meta = {
title: 'radio',
description: 'avatar',
group: 'Data Entry',
}
## Radio

View File

@@ -3,7 +3,7 @@ import { Select, Spacer, Code } from 'components'
export const meta = {
title: 'select',
description: 'select',
group: 'Data Entry',
}
## Select

View File

@@ -3,7 +3,7 @@ import { Snippet, Spacer, Code } from 'components'
export const meta = {
title: 'Snippet',
description: 'Snippet',
group: 'Others',
}
## Snippet

View File

@@ -3,7 +3,7 @@ import { Spacer, Container, Col } from 'components'
export const meta = {
title: 'Spacer',
description: 'tenotext',
group: 'General',
}
## Spacer

View File

@@ -4,7 +4,7 @@ import NextLink from 'next/link'
export const meta = {
title: 'Spinner',
description: 'tenotext',
group: 'Feedback',
}
## Spinner

View File

@@ -3,6 +3,7 @@ import { Table, Spacer, Code, Text, Button } from 'components'
export const meta = {
title: 'Table',
group: 'Data Display',
}
## Table

View File

@@ -7,6 +7,7 @@ import ReactIcon from 'lib/components/icons/react'
export const meta = {
title: 'tabs',
group: 'Navigation',
}
## Tabs

View File

@@ -3,7 +3,7 @@ import { Tag } from 'components'
export const meta = {
title: 'Tag',
description: 'tenotext',
group: 'Data Display',
}
## Tag

View File

@@ -3,7 +3,7 @@ import { Text } from 'components'
export const meta = {
title: 'text',
description: 'text',
group: 'General',
}
## Text

View File

@@ -4,6 +4,7 @@ import { useState } from 'react'
export const meta = {
title: 'textarea',
group: 'Data Entry',
}
## Textarea

View File

@@ -3,7 +3,7 @@ import { useToasts, Button, Spacer } from 'components'
export const meta = {
title: 'toast',
description: 'tenotext',
group: 'Feedback',
}
## Toast

View File

@@ -3,7 +3,7 @@ import { Toggle, Spacer } from 'components'
export const meta = {
title: 'Toggle',
description: 'Toggle',
group: 'Data Entry',
}
## Toggle

View File

@@ -5,7 +5,7 @@ import Colors from 'lib/components/displays/colors'
export const meta = {
title: 'Colors',
description: 'description',
group: 'customization',
}
## Colors

View File

@@ -3,7 +3,7 @@ import { Note, Link, Code, Spacer, Tabs, Row, Dot, Display, Snippet } from 'comp
export const meta = {
title: 'installation',
description: 'description',
group: 'getting-started',
index: 10,
}

View File

@@ -3,6 +3,7 @@ import { Code, Link, Text, Spacer, Note } from 'components'
export const meta = {
title: 'introduction',
group: 'getting-started',
index: 5,
}

View File

@@ -3,7 +3,7 @@ import { Code, Link, Text, Spacer, Note } from 'components'
export const meta = {
title: 'Server Render',
description: 'description',
group: 'getting-started',
index: 15,
}

View File

@@ -3,7 +3,7 @@ import { Note, Code, Spacer, Link } from 'components'
export const meta = {
title: 'Themes',
description: 'description',
group: 'customization',
}
## Themes

View File

@@ -3,7 +3,8 @@ import { AutoComplete, Spacer, Badge, Row } from 'components'
import { useState, useRef, useEffect } from 'react'
export const meta = {
title: 'Auto-Complete / 自动完成',
title: '自动完成 Auto-Complete',
group: '数据录入',
index: 104,
}

View File

@@ -2,8 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Avatar, Spacer } from 'components'
export const meta = {
title: 'avatar / 头像',
description: 'avatar',
title: '头像 Avatar',
group: '数据展示',
}
## Avatar / 头像

View File

@@ -2,7 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Badge, Spacer } from 'components'
export const meta = {
title: 'Badge / 徽章',
title: '徽章 Badge',
group: '数据展示',
}
## Badge / 徽章

View File

@@ -4,7 +4,8 @@ import Playground from 'lib/components/playground'
import { ButtonDropdown, Spacer } from 'components'
export const meta = {
title: 'Btn-Dropdown / 下拉按钮',
title: '下拉按钮 Btn Dropdown',
group: '导航',
index: 105,
}

View File

@@ -3,7 +3,8 @@ import { Button, Spacer } from 'components'
import Router from 'next/router'
export const meta = {
title: 'Button / 按钮',
title: '按钮 Button',
group: '通用',
}
## Button / 按钮

View File

@@ -2,7 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Capacity, Spacer, useTheme } from 'components'
export const meta = {
title: 'Capacity / 容量',
title: '容量 Capacity',
group: '数据展示',
}
## Capacity / 容量

View File

@@ -2,8 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Card } from 'components'
export const meta = {
title: 'Card / 卡片',
description: 'tenotext',
title: '卡片 Card',
group: '表面',
}
## Card / 卡片

View File

@@ -2,7 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Checkbox, Spacer } from 'components'
export const meta = {
title: 'Checkbox / 复选框',
title: '复选框 Checkbox',
group: '数据录入',
}
## Checkbox / 复选框

View File

@@ -1,15 +1,20 @@
import { Layout, Playground, Attributes } from 'lib/components'
import { Code, Note, Link } from 'components'
import NextLink from 'next/link'
export const meta = {
title: 'Code / 代码',
title: '代码 Code',
group: '通用',
}
## Code / 代码
以标准化的方式展示源代码。
<Note label="提示">想要展示 <Code>Shell</Code> 代码片段或一个命令?可以试试 <Link pure color href="/zh-cn/components/snippet">Snippet / 片段</Link> 组件。</Note>
<Note label="提示">
想要展示 <Code>Shell</Code> 代码片段或一个命令?
可以试试 <NextLink href="/zh-cn/components/snippet"><Link pure color>Snippet / 片段</Link></NextLink> 组件。
</Note>
<Playground
desc="基础的行内代码。"

View File

@@ -2,7 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Collapse, Spacer, Text, Code } from 'components'
export const meta = {
title: 'Collapse / 折叠框',
title: '折叠框 Collapse',
group: '表面',
}
## Collapse / 折叠框

View File

@@ -2,7 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Description, Code } from 'components'
export const meta = {
title: 'Description / 描述',
title: '描述 Description',
group: '数据展示',
}
## Description / 描述

View File

@@ -2,8 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Display, Code, Snippet } from 'components'
export const meta = {
title: 'Display / 陈列框',
description: 'tenotext',
title: '陈列框 Display',
group: '数据展示',
}
## Display / 陈列框

View File

@@ -2,8 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Dot } from 'components'
export const meta = {
title: 'Dot / 点',
description: 'tenotext',
title: 'Dot',
group: '数据展示',
}
## Dot / 点

View File

@@ -2,8 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Card, Fieldset, Button, Text } from 'components'
export const meta = {
title: 'Fieldset / 控件组',
description: 'tenotext',
title: '控件组 Fieldset',
group: '表面',
}
## Fieldset / 控件组

View File

@@ -2,8 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Tree, useToasts } from 'components'
export const meta = {
title: 'File-Tree / 文件树',
description: 'File-Tree',
title: '文件树 File Tree',
group: '数据展示',
}
## File-Tree / 文件树

View File

@@ -2,8 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Image, Display, Code } from 'components'
export const meta = {
title: 'Image / 图片',
description: 'tenotext',
title: '图片 Image',
group: '数据展示',
}
## Image / 图片

View File

@@ -4,7 +4,8 @@ import { Input, Spacer, useInput, Button, Code, Text, Dot } from 'components'
import { useState, useEffect } from 'react'
export const meta = {
title: 'Input / 输入框',
title: '输入框 Input',
group: '数据录入',
}
## Input / 输入框

View File

@@ -2,8 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Keyboard } from 'components'
export const meta = {
title: 'keyboard / 键盘',
description: 'tenotext',
title: '键盘 keyboard',
group: '数据展示',
}
## Keyboard / 键盘

View File

@@ -2,8 +2,8 @@ import { Layout, Playground, ExampleBlock, Attributes } from 'lib/components'
import { Row, Col } from 'components'
export const meta = {
title: 'Layout / 布局',
description: 'tenotext',
title: '布局 Layout',
group: '布局',
}
## Layout / 布局

View File

@@ -3,8 +3,8 @@ import { Link, Text, Code } from 'components'
import NextLink from 'next/link'
export const meta = {
title: 'Link / 链接',
description: 'tenotext',
title: '链接 Link',
group: '导航',
}
## Link / 链接

View File

@@ -2,8 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Loading, Spacer, Row } from 'components'
export const meta = {
title: 'Loading / 加载中',
description: 'Loading',
title: '加载中 Loading',
group: '反馈',
}
## Loading / 加载中

View File

@@ -1,16 +1,21 @@
import { Layout, Playground, Attributes } from 'lib/components'
import { Modal, Button, Code, useModal, Note, Link } from 'components'
import NextLink from 'next/link'
import { useState } from 'react'
export const meta = {
title: 'Modal / 对话框',
title: '对话框 Modal',
group: '反馈',
}
## Modal / 对话框
弹出显示需要额外注意或重要的内容。
<Note>仅仅需要弹出文本信息?试试 <Link pure color href="/zh-cn/components/toast">Toast / 通知</Link> 组件。</Note>
<Note>
仅仅需要弹出文本信息?
试试 <NextLink href="/zh-cn/components/toast"><Link pure color>Toast / 通知</Link></NextLink> 组件。
</Note>
<Playground
desc="使用 `open` 属性控制何时显示对话框。"

View File

@@ -2,7 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Note, Code } from 'components'
export const meta = {
title: 'Note / 提示',
title: '提示 Note',
group: '反馈',
}
## Note / 提示

View File

@@ -3,7 +3,8 @@ import { Progress, Spacer, useTheme, Button } from 'components'
import { useState } from 'react'
export const meta = {
title: 'Progress / 进度条',
title: '进度条 Progress',
group: '反馈',
}
## Progress / 进度条

View File

@@ -3,7 +3,8 @@ import { Radio, Spacer, Code, Text } from 'components'
import { useState } from 'react'
export const meta = {
title: 'Radio / 单选框',
title: '单选框 Radio',
group: '数据录入',
}
## Radio / 单选框

View File

@@ -2,7 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Select, Spacer, Code } from 'components'
export const meta = {
title: 'Select / 选择器',
title: '选择器 Select',
group: '数据录入',
}
## Select / 选择器

View File

@@ -2,7 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Snippet, Spacer, Code } from 'components'
export const meta = {
title: 'Snippet / 片段',
title: '片段 Snippet',
group: '其他',
}
## Snippet / 片段

View File

@@ -2,8 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Spacer, Container, Col } from 'components'
export const meta = {
title: 'Spacer / 间距',
description: 'tenotext',
title: 'Spacer 间距',
group: '通用',
}
## Spacer / 间距

View File

@@ -3,7 +3,8 @@ import { Spinner, Spacer, Note, Code, Link } from 'components'
import NextLink from 'next/link'
export const meta = {
title: 'Spinner / 指示器',
title: '指示器 Spinner',
group: '反馈',
}
## Spinner / 指示器

View File

@@ -2,7 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Table, Spacer, Code, Text, Button } from 'components'
export const meta = {
title: 'Table / 表格',
title: '表格 Table',
group: '数据展示',
}
## Table / 表格

View File

@@ -6,7 +6,8 @@ import ZeitIcon from 'lib/components/icons/zeit'
import ReactIcon from 'lib/components/icons/react'
export const meta = {
title: 'Tabs / 选项卡',
title: '选项卡 Tabs',
group: '导航',
}
## Tabs / 选项卡

View File

@@ -2,7 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Tag, Spacer } from 'components'
export const meta = {
title: 'Tag / 标签',
title: '标签 Tag',
group: '数据展示',
}
## Tag / 标签

View File

@@ -2,7 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Text } from 'components'
export const meta = {
title: 'Text / 文本',
title: '文本 Text',
group: '通用',
}
## Text / 文本

View File

@@ -3,7 +3,8 @@ import { Textarea, Spacer, useInput, Button, Code } from 'components'
import { useState } from 'react'
export const meta = {
title: 'Textarea / 文本输入框',
title: '文本输入框 Textarea',
group: '数据录入',
}
## Textarea / 文本输入框

View File

@@ -2,7 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { useToasts, Button, Spacer } from 'components'
export const meta = {
title: 'Toast / 通知',
title: '通知 Toast',
group: '反馈',
}
## Toast / 通知

View File

@@ -2,7 +2,8 @@ import { Layout, Playground, Attributes } from 'lib/components'
import { Toggle, Spacer } from 'components'
export const meta = {
title: 'Toggle / 开关',
title: '开关 Toggle',
group: '数据录入',
}
## Toggle / 开关

View File

@@ -5,6 +5,7 @@ import Colors from 'lib/components/displays/colors'
export const meta = {
title: '色彩',
group: '定制化',
}
## 色彩

View File

@@ -3,6 +3,7 @@ import { Note, Link, Code, Spacer, Tabs, Row, Dot, Display, Snippet } from 'comp
export const meta = {
title: '安装',
group: '快速上手',
index: 10,
}

View File

@@ -3,6 +3,7 @@ import { Code, Link, Text, Spacer, Note } from 'components'
export const meta = {
title: '什么是 ZEIT UI',
group: '快速上手',
index: 5,
}

View File

@@ -3,6 +3,7 @@ import { Code, Link, Text, Spacer, Note } from 'components'
export const meta = {
title: '服务端渲染',
group: '快速上手',
index: 15,
}

View File

@@ -3,6 +3,7 @@ import { Note, Code, Spacer, Link } from 'components'
export const meta = {
title: '主题',
group: '定制化',
}
## 主题

View File

@@ -5,9 +5,32 @@ const metaLocales = require('./locales')
const pagePrefix = path.join(__dirname, '../pages')
const targetPath = path.join(__dirname, '../lib/data/metadata.json')
const weights = {
'getting-started': 1,
'customization': 2,
'components': 3,
'guide': 1,
'docs': 2,
'getting-started': 3,
'customization': 4,
'components': 5,
}
const groupWeights = {
'快速上手': 1,
'起步': 2,
'定制化': 5,
'general': 1,
'通用': 1,
'layout': 2,
'布局': 2,
'surfaces': 3,
'表面': 3,
'data entry': 4,
'数据录入': 4,
'data display': 5,
'数据展示': 5,
'feedback': 6,
'反馈': 6,
'navigation': 7,
'导航': 7,
'others': 8,
'其他': 8,
}
const getMetadata = async (files, parentPath) => {
@@ -21,6 +44,27 @@ const getMetadata = async (files, parentPath) => {
const children = await fs.readdir(filePath)
const childrenMetadata = await getMetadata(children, filePath)
const sorted = childrenMetadata.sort((a, b) => a.index - b.index)
// grouping
const childrenHasGroup = sorted.find(item => item.group)
if (childrenHasGroup) {
const groups = [...new Set(sorted.map(item => item.group || 'others'))]
const groupChildren = groups
.map(groupName => ({
name: groupName,
children: sorted.filter(item => (item.group || 'others') === groupName)
}))
.sort((a, b) => {
const pre = a.name.toLowerCase()
const current = b.name.toLowerCase()
return groupWeights[pre] - groupWeights[current]
})
return {
name: file,
children: groupChildren,
}
}
return { name: file, children: sorted }
}
const content = await fs.readFile(filePath, 'utf-8')
@@ -28,11 +72,32 @@ const getMetadata = async (files, parentPath) => {
const url = filePath
.replace(pagePrefix, '')
.replace('.mdx', '')
return { name: meta.title || file, url, index: meta.index || 100 }
return {
name: meta.title || file,
url,
index: meta.index || 100,
group: meta.group || null,
}
})
)
}
const deepTranslate = (metadata, locales) => {
if (!metadata || !Array.isArray(metadata)) return metadata
return metadata.map(data => {
if (typeof data !== 'object') return data
if (data.children) {
data.children = deepTranslate(data.children, locales)
}
const localeName = locales[data.name]
if (!localeName) return data
return {
...data,
localeName,
}
})
}
;(async () => {
try {
const locales = (await fs.readdir(pagePrefix))
@@ -49,18 +114,11 @@ const getMetadata = async (files, parentPath) => {
const data = await getMetadata(childDirs, dir)
const sorted = data
.sort((a, b) => weights[a.name] - weights[b.name])
.map(item => {
const localeName = currentLocale[item.name]
if (!localeName) return item
return {
...item,
localeName: localeName
}
})
const translatedData = deepTranslate(sorted, currentLocale)
return {
name,
content: sorted
content: translatedData
}
}))

View File

@@ -3,6 +3,8 @@ module.exports = {
'getting-started': '快速开始',
customization: '定制化',
components: '所有组件',
guide: '上手指南',
docs: '文档',
},
'en-us': {