mirror of
https://github.com/zhigang1992/react.git
synced 2026-01-31 09:08:41 +08:00
Merge pull request #84 from unix/themes
docs: keep the theme perferences for visitors
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useMemo, useRef, useState } from 'react'
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { NormalSizes } from '../utils/prop-types'
|
||||
import useClickAway from '../utils/use-click-away'
|
||||
import { pickChildByProps, pickChildrenFirst } from '../utils/collections'
|
||||
@@ -12,6 +12,7 @@ import { getSizes } from './styles'
|
||||
interface Props {
|
||||
disabled?: boolean
|
||||
size?: NormalSizes
|
||||
value?: string
|
||||
initialValue?: string
|
||||
placeholder?: React.ReactNode | string
|
||||
icon?: React.ReactNode
|
||||
@@ -32,8 +33,8 @@ type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
|
||||
export type SelectProps = Props & typeof defaultProps & NativeAttrs
|
||||
|
||||
const Select: React.FC<React.PropsWithChildren<SelectProps>> = ({
|
||||
children, size, disabled, initialValue: init, placeholder,
|
||||
icon: Icon, onChange, className, pure, ...props
|
||||
children, size, disabled, initialValue: init, value: customValue,
|
||||
icon: Icon, onChange, className, pure, placeholder, ...props
|
||||
}) => {
|
||||
const theme = useTheme()
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
@@ -63,6 +64,11 @@ const Select: React.FC<React.PropsWithChildren<SelectProps>> = ({
|
||||
|
||||
useClickAway(ref, () => setVisible(false))
|
||||
|
||||
useEffect(() => {
|
||||
if (customValue === undefined) return
|
||||
setValue(customValue)
|
||||
}, [customValue])
|
||||
|
||||
const selectedChild = useMemo(() => {
|
||||
const [, optionChildren] = pickChildByProps(children, 'value', value)
|
||||
const child = pickChildrenFirst(optionChildren)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { MutableRefObject, useState } from 'react'
|
||||
import React, { MutableRefObject, useEffect, useState } from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
import usePortal from '../utils/use-portal'
|
||||
import useResize from '../utils/use-resize'
|
||||
@@ -54,6 +54,14 @@ const Dropdown: React.FC<React.PropsWithChildren<Props>> = React.memo(({
|
||||
if (!shouldUpdatePosition) return
|
||||
updateRect()
|
||||
})
|
||||
useEffect(() => {
|
||||
if (!parent || !parent.current) return
|
||||
parent.current.addEventListener('mouseenter', updateRect)
|
||||
return () => {
|
||||
if (!parent || !parent.current) return
|
||||
parent.current.removeEventListener('mouseenter', updateRect)
|
||||
}
|
||||
}, [parent])
|
||||
|
||||
const clickHandler = (event: React.MouseEvent<HTMLDivElement>) => {
|
||||
event.stopPropagation()
|
||||
|
||||
@@ -21,6 +21,8 @@ const Controls: React.FC<{}> = React.memo(({
|
||||
|
||||
const switchThemes = (type: 'dark' | 'light') => {
|
||||
updateCustomTheme({ type })
|
||||
if (typeof window === 'undefined' || !window.localStorage) return
|
||||
window.localStorage.setItem('theme', type)
|
||||
}
|
||||
const switchLanguages = () => {
|
||||
updateChineseState(!isChinese)
|
||||
@@ -41,7 +43,7 @@ const Controls: React.FC<{}> = React.memo(({
|
||||
onClick={redirectGithub}
|
||||
title={isChinese? '代码仓库' : 'Github Repository'}>{isChinese ? '代码仓库' : 'Github'}</Button>
|
||||
<Spacer x={.75} />
|
||||
<Select size="small" pure onChange={switchThemes} initialValue={isDark ? 'dark' : 'light'}
|
||||
<Select size="small" pure onChange={switchThemes} value={isDark ? 'dark' : 'light'}
|
||||
title={isChinese ? '切换主题' : 'Switch Themes'}>
|
||||
<Select.Option value="light">
|
||||
<div className="select-content">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { useTheme } from 'components'
|
||||
import Sidebar from './sidebar'
|
||||
import TabbarMobile from './sidebar/tabbar-mobile'
|
||||
@@ -16,6 +16,7 @@ export interface Props {
|
||||
|
||||
export const Layout: React.FC<React.PropsWithChildren<Props>> = React.memo(({ children }) => {
|
||||
const theme = useTheme()
|
||||
const [showAfterRender, setShowAfterRender] = useState<boolean>(false)
|
||||
const { tabbarFixed } = useConfigs()
|
||||
const [, setBodyScroll] = useBodyScroll(null, { scrollLayer: true })
|
||||
const [expanded, setExpanded] = useState<boolean>(false)
|
||||
@@ -24,6 +25,9 @@ export const Layout: React.FC<React.PropsWithChildren<Props>> = React.memo(({ ch
|
||||
setBodyScroll(!expanded)
|
||||
}
|
||||
|
||||
useEffect(() => setShowAfterRender(true), [])
|
||||
|
||||
if (!showAfterRender) return null
|
||||
return (
|
||||
<div className="layout">
|
||||
<TabbarMobile onClick={mobileTabbarClickHandler} />
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import React from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import MenuLinks from './menu-links'
|
||||
import MenuSticker from './menu-sticker'
|
||||
|
||||
const Menu = () => {
|
||||
const Menu: React.FC<{}> = () => {
|
||||
const [showAfterRender, setShowAfterRender] = useState<boolean>(false)
|
||||
useEffect(() => setShowAfterRender(true), [])
|
||||
|
||||
if (!showAfterRender) return null
|
||||
return (
|
||||
<div>
|
||||
<MenuLinks />
|
||||
|
||||
@@ -57,6 +57,7 @@ const MenuSticker = () => {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
pointer-events: none;
|
||||
background-color: ${theme.palette.background};
|
||||
}
|
||||
|
||||
.nav-fill.active {
|
||||
|
||||
10
lib/use-dom-clean.ts
Normal file
10
lib/use-dom-clean.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { useEffect } from 'react'
|
||||
|
||||
const useDomClean = (): void => {
|
||||
useEffect(() => {
|
||||
document.documentElement.removeAttribute('style')
|
||||
document.body.removeAttribute('style')
|
||||
}, [])
|
||||
}
|
||||
|
||||
export default useDomClean
|
||||
@@ -60,7 +60,7 @@
|
||||
"eslint-plugin-react": "^7.19.0",
|
||||
"extract-mdx-metadata": "^1.0.0",
|
||||
"fs-extra": "^8.1.0",
|
||||
"next": "^9.3.2",
|
||||
"next": "^9.3.4",
|
||||
"react": "^16.13.0",
|
||||
"react-color": "^2.18.0",
|
||||
"react-dom": "^16.13.0",
|
||||
@@ -71,4 +71,4 @@
|
||||
"webpack-cli": "^3.3.11"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
import Head from 'next/head'
|
||||
import { NextPage } from 'next'
|
||||
import { AppProps } from 'next/app'
|
||||
import { useState } from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { CSSBaseline, ZEITUIProvider, useTheme, ZeitUIThemes } from 'components'
|
||||
import Menu from 'lib/components/menu'
|
||||
import ConfigContext from 'lib/config-provider'
|
||||
import useDomClean from 'lib/use-dom-clean'
|
||||
import { DeepPartial } from 'components/utils/types'
|
||||
|
||||
const Application: NextPage<AppProps> = ({ Component, pageProps }) => {
|
||||
const Application: NextPage<AppProps<{}>> = ({ Component, pageProps }) => {
|
||||
const theme = useTheme()
|
||||
const [customTheme, setCustomTheme] = useState<DeepPartial<ZeitUIThemes>>({})
|
||||
const themeChangeHandle = (theme: DeepPartial<ZeitUIThemes>) => {
|
||||
setCustomTheme(theme)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const theme = window.localStorage.getItem('theme')
|
||||
if (theme !== 'dark') return
|
||||
themeChangeHandle({ type: 'dark' })
|
||||
}, [])
|
||||
useDomClean()
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -22,20 +22,29 @@ class MyDocument extends Document {
|
||||
<Html>
|
||||
<Head />
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
<script async src={`https://www.googletagmanager.com/gtag/js?id=UA-110371817-12`} />
|
||||
<script
|
||||
async
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'UA-110371817-12');
|
||||
`
|
||||
}}
|
||||
/>
|
||||
<script dangerouslySetInnerHTML={{ __html: `
|
||||
(function(){
|
||||
if (!window.localStorage) return;
|
||||
if (window.localStorage.getItem('theme') === 'dark') {
|
||||
document.documentElement.style.background = '#000';
|
||||
document.body.style.background = '#000';
|
||||
};
|
||||
})()
|
||||
`}} />
|
||||
<Main />
|
||||
<NextScript />
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-110371817-12" />
|
||||
<script
|
||||
async
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'UA-110371817-12');
|
||||
`
|
||||
}}
|
||||
/>
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
|
||||
@@ -167,7 +167,7 @@ Retrieve text input from a user.
|
||||
| Attribute | Description | Type | Accepted values | Default
|
||||
| ---------- | ---------- | ---- | -------------- | ------ |
|
||||
| **value** | input value | `string` | - | - |
|
||||
| **initialValue** | inital value | `string` | - | - |
|
||||
| **initialValue** | initial value | `string` | - | - |
|
||||
| **placeholder** | placeholder | `string` | - | - |
|
||||
| **size** | input size | `NormalSizes` | `'mini', 'small', 'medium', 'large'` | `medium` |
|
||||
| **status** | current status | `NormalTypes` | `'default', 'secondary', 'success', 'warning', 'error'` | `default` |
|
||||
|
||||
@@ -75,7 +75,8 @@ Display a dropdown list of items.
|
||||
|
||||
| Attribute | Description | Type | Accepted values | Default
|
||||
| ---------- | ---------- | ---- | -------------- | ------ |
|
||||
| **initialValue** | selected value | `string` | - | - |
|
||||
| **value** | selected value | `string` | - | - |
|
||||
| **initialValue** | initial value | `string` | - | - |
|
||||
| **placeholder** | placeholder string | `string` | - | - |
|
||||
| **size** | select component size | `NormalSizes` | `'mini', 'small', 'medium', 'large'` | `medium` |
|
||||
| **icon** | icon component | `ReactNode` | - | `SVG Component` |
|
||||
|
||||
@@ -74,6 +74,7 @@ export const meta = {
|
||||
|
||||
| 属性 | 描述 | 类型 | 推荐值 | 默认
|
||||
| ---------- | ---------- | ---- | -------------- | ------ |
|
||||
| **value** | 手动设置选择器的值 | `string` | - | - |
|
||||
| **initialValue** | 选择器初始值 | `string` | - | - |
|
||||
| **placeholder** | 占位文本内容 | `string` | - | - |
|
||||
| **size** | 选择器组件大小 | `NormalSizes` | `'mini', 'small', 'medium', 'large'` | `medium` |
|
||||
|
||||
Reference in New Issue
Block a user