diff --git a/.dumi/hooks/useMenu.tsx b/.dumi/hooks/useMenu.tsx index 3ff811898..687507cab 100644 --- a/.dumi/hooks/useMenu.tsx +++ b/.dumi/hooks/useMenu.tsx @@ -3,6 +3,7 @@ import { Tag, theme } from '@oceanbase/design'; import { Link, useFullSidebarData, useSidebarData } from 'dumi'; import React, { useMemo } from 'react'; import useLocation from './useLocation'; +import useSiteToken from './useSiteToken'; export interface UseMenuOptions { before?: React.ReactNode; @@ -14,7 +15,7 @@ const useMenu = (options: UseMenuOptions = {}): [MenuProps['items'], string] => const { pathname, search } = useLocation(); const sidebarData = useSidebarData(); const { before, after } = options; - const { token } = theme.useToken(); + const { token } = useSiteToken(); const menuItems = useMemo(() => { const sidebarItems = [...(sidebarData ?? [])]; diff --git a/.dumi/hooks/useSiteToken.ts b/.dumi/hooks/useSiteToken.ts index 8bae2f5f4..28edb9d39 100644 --- a/.dumi/hooks/useSiteToken.ts +++ b/.dumi/hooks/useSiteToken.ts @@ -4,14 +4,13 @@ import { ConfigProvider, theme } from '@oceanbase/design'; const { useToken } = theme; const useSiteToken = () => { - const result = useToken(); + const { token, ...rest } = useToken(); const { getPrefixCls, iconPrefixCls } = useContext(ConfigProvider.ConfigContext); const rootPrefixCls = getPrefixCls(); - const { token } = result; const siteMarkdownCodeBg = token.colorFillTertiary; return { - ...result, + ...rest, token: { ...token, headerHeight: 64, diff --git a/.dumi/theme/SiteThemeProvider.tsx b/.dumi/theme/SiteThemeProvider.tsx index 39053b94b..dca640da9 100644 --- a/.dumi/theme/SiteThemeProvider.tsx +++ b/.dumi/theme/SiteThemeProvider.tsx @@ -1,4 +1,4 @@ -import { ConfigProvider, token } from '@oceanbase/design'; +import { ConfigProvider } from '@oceanbase/design'; import type { ThemeConfig } from '@oceanbase/design'; import { ChartProvider } from '@oceanbase/charts'; import type { ThemeProviderProps } from 'antd-style'; @@ -8,6 +8,7 @@ import React, { useContext } from 'react'; import useLocale from '../hooks/useLocale'; import SiteContext from './slots/SiteContext'; import zhCN from '../../packages/design/src/locale/zh-CN'; +import useSiteToken from '../hooks/useSiteToken'; const SiteThemeProvider: FC< ThemeProviderProps & { @@ -22,6 +23,8 @@ const SiteThemeProvider: FC< const [_, lang] = useLocale(); const { direction } = useContext(SiteContext); + const { token } = useSiteToken(); + return ( = ({ children, tooltip, ...restProps }) => { - const typeList = getTooltipTypeList(); + const typeList = useTooltipTypeList(); // tooltip config if (typeof tooltip === 'object' && !React.isValidElement(tooltip)) { const { icon, type, overlayInnerStyle, ...restTooltipProps } = tooltip as WrapperTooltipProps; diff --git a/packages/design/src/modal/demo/over-height.tsx b/packages/design/src/modal/demo/over-height.tsx index e40821fe5..d38413ab9 100644 --- a/packages/design/src/modal/demo/over-height.tsx +++ b/packages/design/src/modal/demo/over-height.tsx @@ -1,8 +1,9 @@ import React, { useState } from 'react'; -import { Button, Modal, token } from '@oceanbase/design'; +import { Button, Modal, theme } from '@oceanbase/design'; export default () => { const [open, setOpen] = useState(false); + const { token } = theme.useToken(); return ( <> diff --git a/packages/design/src/spin/demo/inside.tsx b/packages/design/src/spin/demo/inside.tsx index 67aa2da46..9e82a8b36 100644 --- a/packages/design/src/spin/demo/inside.tsx +++ b/packages/design/src/spin/demo/inside.tsx @@ -1,19 +1,23 @@ import React from 'react'; -import { Spin, token } from '@oceanbase/design'; +import { Spin, theme } from '@oceanbase/design'; -const App: React.FC = () => ( -
- -
-); +const App: React.FC = () => { + const { token } = theme.useToken(); + + return ( +
+ +
+ ); +}; export default App; diff --git a/packages/design/src/spin/demo/tip.tsx b/packages/design/src/spin/demo/tip.tsx index cd5587bff..160cad79a 100644 --- a/packages/design/src/spin/demo/tip.tsx +++ b/packages/design/src/spin/demo/tip.tsx @@ -1,36 +1,39 @@ import React from 'react'; -import { Alert, Space, Spin, token } from '@oceanbase/design'; +import { Alert, Space, Spin, theme } from '@oceanbase/design'; -const containerStyle = { - padding: 50, - background: token.colorBgLayout, - borderRadius: 4, - width: 120, - height: 120, -}; +const App: React.FC = () => { + const { token } = theme.useToken(); + const containerStyle = { + padding: 50, + background: token.colorBgLayout, + borderRadius: 4, + width: 120, + height: 120, + }; -const App: React.FC = () => ( - - - -
- - -
- - -
+ return ( + + + +
+ + +
+ + +
+ + + + + - - - - - -); + ); +}; export default App; diff --git a/packages/design/src/theme/index.md b/packages/design/src/theme/index.md index 46710b559..31623be14 100644 --- a/packages/design/src/theme/index.md +++ b/packages/design/src/theme/index.md @@ -27,62 +27,39 @@ export default () { ### 在 React 中使用 -- ⭐️ 推荐 通过 `token` 对象来获取 Design Token,和 `useToken` 获取的值完全相同,且有两大优势: - - 使用时不用声明 `useToken`,`@oceanbase/design` 会帮你在 ConfigProvider 中自动注入,以降低业务调用成本。 - - 支持在 React 类组件中使用。 +- 如果是函数组件,推荐使用 `useToken` hook 来获取 Design Token: ```tsx | pure -// 无需声明 useToken,即引即用 -import { Button, ConfigProvider, token } from '@oceanbase/design'; +import { Button, useToken } from '@oceanbase/design'; import React from 'react'; const App: React.FC = () => { - return ( - - - - ); + const { token } = useToken(); + + return ; }; export default App; ``` +- 如果是类组件,可以通过 `token` 对象来获取 Design Token: + ```tsx | pure -// 支持在 React 类组件中使用 import { Button, ConfigProvider, token } from '@oceanbase/design'; import React from 'react'; class App extends React.Component { render() { - return ( - - - - ); + return ; } } export default App; ``` -- 当然,也可以通过 `useToken` hook 来获取 Design Token。只不过在实际的业务场景中会比较繁琐,而且只能在函数组件中使用。 - -```tsx | pure -import { Button, useToken } from '@oceanbase/design'; -import React from 'react'; - -const App: React.FC = () => { - const { token } = useToken(); - - return ; -}; - -export default App; -``` - ### 在非 React 中使用 -- 在常量文件、dva model 等非 React 环境下,也可以使用 `token` 对象来获取 Design Token。 +- 在常量文件、dva model 等非 React 环境下,可以使用 `token` 对象来获取 Design Token。 ```ts import { token } from '@oceanbase/design'; diff --git a/packages/design/src/tooltip/MouseTooltip.tsx b/packages/design/src/tooltip/MouseTooltip.tsx index b39c0f460..7cd30d2d3 100644 --- a/packages/design/src/tooltip/MouseTooltip.tsx +++ b/packages/design/src/tooltip/MouseTooltip.tsx @@ -2,7 +2,7 @@ import { useMouse, useSize } from 'ahooks'; import type { TooltipPropsWithTitle as AntTooltipPropsWithTitle } from 'antd/es/tooltip'; import React, { useRef, useState } from 'react'; import ReactStickyMouseTooltip from 'react-sticky-mouse-tooltip'; -import { token } from '../static-function'; +import theme from '../theme'; interface MouseTooltipProps extends AntTooltipPropsWithTitle { /* 外部传入的 visible 并不完全控制显示和隐藏,只是作为是否显示的前提条件 */ @@ -24,6 +24,7 @@ const MouseTooltip: React.FC = ({ mouseLeaveDelay = 0.1, ...restProps }) => { + const { token } = theme.useToken(); const [visible, setVisible] = useState(false); const { color: textColor, ...restOverlayInnerStyle } = overlayInnerStyle || {}; diff --git a/packages/design/src/tooltip/hooks/useTooltipTypeList.ts b/packages/design/src/tooltip/hooks/useTooltipTypeList.ts new file mode 100644 index 000000000..9fac4f9b1 --- /dev/null +++ b/packages/design/src/tooltip/hooks/useTooltipTypeList.ts @@ -0,0 +1,32 @@ +import theme from '../../theme'; + +export const useTooltipTypeList = () => { + const { token } = theme.useToken(); + return [ + { + type: 'light', + color: token.colorText, + backgroundColor: token.colorBgElevated, + }, + { + type: 'success', + color: token.colorSuccess, + backgroundColor: token.colorSuccessBg, + }, + { + type: 'info', + color: token.colorInfo, + backgroundColor: token.colorInfoBg, + }, + { + type: 'warning', + color: token.colorWarning, + backgroundColor: token.colorWarningBg, + }, + { + type: 'error', + color: token.colorError, + backgroundColor: token.colorErrorBg, + }, + ]; +}; diff --git a/packages/design/src/tooltip/index.tsx b/packages/design/src/tooltip/index.tsx index f179dace5..8356a84e9 100644 --- a/packages/design/src/tooltip/index.tsx +++ b/packages/design/src/tooltip/index.tsx @@ -2,12 +2,13 @@ import { Tooltip as AntTooltip, Space } from 'antd'; import type { TooltipPropsWithTitle as AntTooltipPropsWithTitle } from 'antd/es/tooltip'; import React, { useContext, useEffect, useState } from 'react'; import { CloseOutlined } from '@oceanbase/icons'; +import classNames from 'classnames'; import { isNil } from 'lodash'; import { token } from '../static-function'; import MouseTooltip from './MouseTooltip'; import ConfigProvider from '../config-provider'; import useStyle from './style'; -import classNames from 'classnames'; +import { useTooltipTypeList } from './hooks/useTooltipTypeList'; export * from 'antd/es/tooltip'; @@ -20,34 +21,6 @@ export interface TooltipProps extends AntTooltipPropsWithTitle { onClose?: (e: React.MouseEvent) => void; } -export const getTooltipTypeList = () => [ - { - type: 'light', - color: token.colorText, - backgroundColor: token.colorBgElevated, - }, - { - type: 'success', - color: token.colorSuccess, - backgroundColor: token.colorSuccessBg, - }, - { - type: 'info', - color: token.colorInfo, - backgroundColor: token.colorInfoBg, - }, - { - type: 'warning', - color: token.colorWarning, - backgroundColor: token.colorWarningBg, - }, - { - type: 'error', - color: token.colorError, - backgroundColor: token.colorErrorBg, - }, -]; - type CompoundedComponent = React.FC & { /** @internal */ __ANT_TOOLTIP: boolean; @@ -121,7 +94,7 @@ const Tooltip: CompoundedComponent = ({ titleNode ); - const typeList = getTooltipTypeList(); + const typeList = useTooltipTypeList(); const typeItem = typeList.find(item => item.type === type); return wrapSSR( mouseFollow ? ( diff --git a/packages/ui/src/BasicLayout/index.tsx b/packages/ui/src/BasicLayout/index.tsx index 6b96126ab..3600111af 100644 --- a/packages/ui/src/BasicLayout/index.tsx +++ b/packages/ui/src/BasicLayout/index.tsx @@ -1,6 +1,6 @@ import { CaretRightFilled, LeftOutlined, RightOutlined } from '@oceanbase/icons'; import { setAlpha } from '@ant-design/pro-components'; -import { Typography, token } from '@oceanbase/design'; +import { Typography, theme } from '@oceanbase/design'; import { isNullValue } from '@oceanbase/util'; import { ConfigProvider, Divider, Layout, Menu, Tooltip } from '@oceanbase/design'; import type { BadgeProps } from '@oceanbase/design/es/badge'; @@ -92,6 +92,7 @@ const BasicLayout: React.FC = ({ prefixCls: customizePrefixCls, ...restProps }) => { + const { token } = theme.useToken(); const { getPrefixCls } = useContext(ConfigProvider.ConfigContext); const prefixCls = getPrefixCls('pro-basic-layout', customizePrefixCls); const { wrapSSR } = useStyle(prefixCls); diff --git a/packages/ui/src/Highlight/index.tsx b/packages/ui/src/Highlight/index.tsx index 0b5877427..976212442 100644 --- a/packages/ui/src/Highlight/index.tsx +++ b/packages/ui/src/Highlight/index.tsx @@ -9,7 +9,7 @@ import React, { useEffect, useState } from 'react'; import { default as javascript, default as jsx } from './languages/javascript'; // tsx 本质上也是采用typescript进行解析,hljs做了支持 import { CheckOutlined, CopyOutlined } from '@oceanbase/icons'; -import { token } from '@oceanbase/design'; +import { theme as obTheme } from '@oceanbase/design'; import { message } from '@oceanbase/design'; import classNames from 'classnames'; import CopyToClipboard from 'react-copy-to-clipboard'; @@ -168,6 +168,8 @@ const Highlight: React.FC = props => { // 代码块展示的结构 const [codeBlock, setCodeBlock] = React.useState(); + const { token } = obTheme.useToken(); + // 按需加载语言 useEffect(() => { if (language && languageMap[language]) { diff --git a/packages/ui/src/Login/LoginForm.tsx b/packages/ui/src/Login/LoginForm.tsx index 0339f92e9..6d07b5718 100644 --- a/packages/ui/src/Login/LoginForm.tsx +++ b/packages/ui/src/Login/LoginForm.tsx @@ -8,7 +8,7 @@ import { Alert, Button, Form, Input, Space } from '@oceanbase/design'; import type { FormProps } from '@oceanbase/design/es/form'; import classNames from 'classnames'; import React, { useState } from 'react'; -import { token } from '@oceanbase/design'; +import { theme } from '@oceanbase/design'; import type { LoginLocale } from '.'; import { getPrefix } from '../_util'; import './index.less'; @@ -42,6 +42,7 @@ const Login: React.FC = ({ onAuthCodeImgChange, ...restProps }) => { + const { token } = theme.useToken(); const [focusInput, setFocusInput] = useState(''); return ( diff --git a/packages/ui/src/Password/Content.tsx b/packages/ui/src/Password/Content.tsx index 78f83b9dd..3f6f7151f 100644 --- a/packages/ui/src/Password/Content.tsx +++ b/packages/ui/src/Password/Content.tsx @@ -1,7 +1,7 @@ import { CheckCircleFilled, CloseCircleFilled, LoadingOutlined } from '@oceanbase/icons'; import { Progress, Space } from '@oceanbase/design'; import React from 'react'; -import { token } from '@oceanbase/design'; +import { theme } from '@oceanbase/design'; export interface Validator { validate: (value?: string) => boolean; @@ -18,6 +18,7 @@ const Content: React.FC<{ value?: string; isTouched: boolean; }> = ({ rules, fieldError, isValidating, value, isTouched }) => { + const { token } = theme.useToken(); const statusIconMap = { error: , success: , diff --git a/packages/ui/src/Password/index.tsx b/packages/ui/src/Password/index.tsx index 59d3a9d70..91f63d84a 100644 --- a/packages/ui/src/Password/index.tsx +++ b/packages/ui/src/Password/index.tsx @@ -2,7 +2,7 @@ import { Button, Input, message, Popover } from '@oceanbase/design'; import type { PasswordProps as InputPasswordProps } from '@oceanbase/design/es/input'; import RandExp from 'randexp'; import React, { useState } from 'react'; -import { token } from '@oceanbase/design'; +import { theme } from '@oceanbase/design'; import CopyToClipboard from 'react-copy-to-clipboard'; import type { LocaleWrapperProps } from '../locale/LocaleWrapper'; import LocaleWrapper from '../locale/LocaleWrapper'; @@ -41,6 +41,7 @@ const Password: React.FC = ({ generatePasswordRegex, ...restProps }) => { + const { token } = theme.useToken(); const [fieldError, setFieldError] = useState([]); const [isValidating, setIsValidating] = useState(false); const [isTouched, setIsTouched] = useState(false);