Skip to content

Commit

Permalink
Merge pull request #536 from oceanbase/dengfuping-design
Browse files Browse the repository at this point in the history
feat(design): ConfigProvider add theme.customFont prop to use `Source Sans Pro` font
  • Loading branch information
dengfuping authored Mar 29, 2024
2 parents 9c82fea + dfd22ce commit 4cf2523
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 19 deletions.
4 changes: 1 addition & 3 deletions .dumi/theme/SiteThemeProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ import useSiteToken from '../hooks/useSiteToken';

const SiteThemeProvider: FC<
ThemeProviderProps<any> & {
theme: ThemeConfig & {
isDark?: boolean;
};
theme: ThemeConfig;
}
> = ({ children, theme, ...rest }) => {
const { getPrefixCls, iconPrefixCls } = useContext(ConfigProvider.ConfigContext);
Expand Down
20 changes: 19 additions & 1 deletion .dumi/theme/common/ThemeSwitch/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import { CompactTheme, DarkTheme, Motion } from 'antd-token-previewer/es/icons';
import { FormattedMessage } from 'dumi';
import React from 'react';
import ThemeIcon from './ThemeIcon';
import { FontColorsOutlined } from '@ant-design/icons';

export type ThemeName = 'light' | 'dark' | 'compact' | 'motion-off';
export type ThemeName = 'light' | 'dark' | 'compact' | 'motion-off' | 'custom-font';

export type ThemeSwitchProps = {
value?: ThemeName[];
Expand All @@ -14,6 +15,7 @@ export type ThemeSwitchProps = {
const ThemeSwitch: React.FC<ThemeSwitchProps> = (props: ThemeSwitchProps) => {
const { value = ['light'], onChange } = props;
const isMotionOff = value.includes('motion-off');
const isCustomFont = value.includes('custom-font');

return (
<FloatButton.Group trigger="click" icon={<ThemeIcon />}>
Expand Down Expand Up @@ -57,6 +59,22 @@ const ThemeSwitch: React.FC<ThemeSwitchProps> = (props: ThemeSwitchProps) => {
/>
}
/>
<FloatButton
icon={<FontColorsOutlined />}
type={isCustomFont ? 'primary' : 'default'}
onClick={() => {
if (isCustomFont) {
onChange(value.filter(theme => theme !== 'custom-font'));
} else {
onChange([...value, 'custom-font']);
}
}}
tooltip={
<FormattedMessage
id={isCustomFont ? 'app.theme.switch.font.custom' : 'app.theme.switch.font.default'}
/>
}
/>
</FloatButton.Group>
);
};
Expand Down
1 change: 1 addition & 0 deletions .dumi/theme/layouts/GlobalLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ const GlobalLayout: React.FC = () => {
theme={{
algorithm: getAlgorithm(theme),
isDark: theme.includes('dark'),
customFont: theme.includes('custom-font'),
token: {
motion: !theme.includes('motion-off'),
},
Expand Down
2 changes: 2 additions & 0 deletions .dumi/theme/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"app.theme.switch.compact": "Compact theme",
"app.theme.switch.motion.on": "Motion On",
"app.theme.switch.motion.off": "Motion Off",
"app.theme.switch.font.default": "Default Font",
"app.theme.switch.font.custom": "Custom Font",
"app.header.menu.more": "More",
"app.header.menu.pro.components": "Ant Design Pro Components",
"app.header.menu.charts": "Ant Design Charts",
Expand Down
2 changes: 2 additions & 0 deletions .dumi/theme/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"app.theme.switch.compact": "紧凑主题",
"app.theme.switch.motion.on": "动画开启",
"app.theme.switch.motion.off": "动画关闭",
"app.theme.switch.font.default": "默认字体",
"app.theme.switch.font.custom": "定制字体",
"app.header.menu.more": "更多",
"app.header.menu.pro.components": "Ant Design Pro Components",
"app.header.menu.charts": "Ant Design Charts",
Expand Down
20 changes: 18 additions & 2 deletions packages/design/src/_util/genComponentStyleHook.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { ComponentTokenMap } from 'antd/es/theme/interface';
import type { FullToken, GenerateStyle } from 'antd/es/theme/internal';
import type { DerivativeToken, FullToken, GenerateStyle } from 'antd/es/theme/internal';
import { genComponentStyleHook as antGenComponentStyleHook } from 'antd/es/theme/internal';
import type { GlobalToken } from 'antd/es/theme/interface';
import type { OverrideTokenWithoutDerivative } from 'antd/es/theme/util/genComponentStyleHook';
import { useContext } from 'react';
import ConfigProvider from '../config-provider';
import theme from '../theme';

export type ComponentName = keyof ComponentTokenMap;

export const genCustomFontStyle = (token: DerivativeToken): CSSObject[] => {
return [
{
['@font-face']: {
fontFamily: 'Source Sans Pro',
// 定义三种字体格式,适配不同版本的浏览器,并且最多加载一种字体文件
src: `url('https://mdn.alipayobjects.com/huamei_fhnyvh/afts/file/A*H1MFR42M5PMAAAAAAAAAAAAADmfOAQ/Source%20Sans%20Pro.woff2') format('woff2'), url('https://mdn.alipayobjects.com/huamei_fhnyvh/afts/file/A*jbYLSpw_gfEAAAAAAAAAAAAADmfOAQ/Source%20Sans%20Pro.woff') format('woff'), url('https://mdn.alipayobjects.com/huamei_fhnyvh/afts/file/A*28ClS5qHwQ8AAAAAAAAAAAAADmfOAQ/Source%20Sans%20Pro.ttf') format('truetype')`,
// 定义字体加载策略,外置字体加载前使用默认字体进行兜底
fontDisplay: 'swap',
},
},
];
};

export function genComponentStyleHook(
componentName: ComponentName,
styleFn: GenerateStyle<FullToken<ComponentName>>,
Expand All @@ -17,10 +32,11 @@ export function genComponentStyleHook(
| ((token: GlobalToken) => OverrideTokenWithoutDerivative[ComponentName])
) {
return (prefixCls: string) => {
const { theme: themeConfig } = useContext(ConfigProvider.ConfigContext);
const useStyle = antGenComponentStyleHook(
`OB-${componentName}` as ComponentName,
token => {
return [styleFn(token)];
return [themeConfig?.customFont ? genCustomFontStyle(token) : null, styleFn(token)];
},
getDefaultToken,
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useContext } from 'react';
import { render } from '@testing-library/react';
import { ConfigProvider, useToken } from '@oceanbase/design';
import defaultTheme from '../../theme/default';
Expand Down
2 changes: 2 additions & 0 deletions packages/design/src/config-provider/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ nav:
- 🔥 完全继承 antd [ConfigProvider](https://ant.design/components/config-provider-cn) 的能力和 API,可无缝切换。
- 🌈 定制全局主题和空状态,以符合 OceanBase Design 设计规范。
- 🆕 默认内嵌 [App 包裹组件](https://ant.design/components/app-cn),支持 message, notification 和 Modal 等静态方法消费 ConfigProvider 配置。
- 🆕 新增 `theme.customFont` 属性,用于开启 `Source Sans Pro` 定制字体以提升展示效果,仅支持线上应用和英文环境。
- 🆕 新增 `table.selectionColumnWidth` 属性,用于配置表格的展开列宽度。
- 🆕 新增 `injectStaticFunction` 属性,用于配置 `message`, `notification``Modal` 静态方法是否可以消费全局配置,默认开启。

Expand Down Expand Up @@ -47,6 +48,7 @@ export default App;

| 参数 | 说明 | 类型 | 默认值 | 版本 |
| :-- | :-- | :-- | :-- | :-- |
| theme.customFont | 用于开启 `Source Sans Pro` 定制字体以提升展示效果,仅支持线上应用和英文环境 | boolean | undefined | 0.3.1 |
| spin | Spin 全局配置 | `{ indicator?: ReactNode; className?: string; style?: React.CSSProperties; }` | undefined | - |
| table | Table 全局配置 | `{ selectionColumnWidth?: width; className?: string; style?: React.CSSProperties; }` | undefined | - |
| injectStaticFunction | 用于配置 `message`, `notification``Modal` 静态方法是否可以消费全局配置 <Alert type="warning" showIcon={true} message="📢 注意: 如果有多个 ConfigProvider,建议在最顶层的 ConfigProvider 开启 `injectStaticFunction` 即可,其他 ConfigProvider 则需要关闭该配置,否则静态方法可能会有冲突。"></Alert> | boolean | true | - |
Expand Down
20 changes: 9 additions & 11 deletions packages/design/src/config-provider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export * from 'antd/es/config-provider';

export interface ThemeConfig extends AntThemeConfig {
isDark?: boolean;
/* use custom font or not */
customFont?: boolean;
}

export type SpinConfig = ComponentStyleConfig & {
Expand Down Expand Up @@ -73,8 +75,6 @@ const ExtendedConfigContext = React.createContext<ExtendedConfigConsumerProps>({
hideOnSinglePage: false,
});

const { defaultSeed } = themeConfig;

export type ConfigProviderType = React.FC<ConfigProviderProps> & {
ExtendedConfigContext: typeof ExtendedConfigContext;
} & {
Expand Down Expand Up @@ -103,6 +103,7 @@ const ConfigProvider: ConfigProviderType = ({
React.useContext<ExtendedConfigConsumerProps>(ExtendedConfigContext);
const mergedTheme = merge(parentContext.theme, theme);
const currentTheme = mergedTheme?.isDark ? darkTheme : defaultTheme;
const { token } = themeConfig.useToken();

// inherit from parent StyleProvider
const parentStyleContext = React.useContext<StyleContextProps>(StyleContext);
Expand All @@ -126,16 +127,13 @@ const ConfigProvider: ConfigProviderType = ({
parentContext.tabs,
tabs
)}
theme={merge(
{
token: {
...defaultSeed,
...currentTheme.token,
},
components: currentTheme.components,
theme={merge(currentTheme, mergedTheme, {
token: {
fontFamily: mergedTheme.customFont
? `'Source Sans Pro', ${token.fontFamily}`
: token.fontFamily,
},
mergedTheme
)}
})}
renderEmpty={
parentContext.renderEmpty ||
(componentName => <DefaultRenderEmpty componentName={componentName} />)
Expand Down
2 changes: 1 addition & 1 deletion packages/design/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export { default as Card } from './card';
export type { CardProps } from './card';

export { default as ConfigProvider } from './config-provider';
export type { ConfigProviderProps } from './config-provider';
export type { ConfigProviderProps, ConfigConsumerProps, ThemeConfig } from './config-provider';

export { default as Descriptions } from './descriptions';
export type {
Expand Down

0 comments on commit 4cf2523

Please sign in to comment.