feat(Theme): add some tokens (#4137)

* chore: use token better

* chore: use rgba

* feat: add some custom tokens

* Revert "chore: use rgba"

This reverts commit dac660f6936ab795d52561ce79d0e6a7a721cc71.

* feat: adaptor tokens

* chore: adjust details

* chore: fix unit tests

* chore: remove box shadow from buttons in the upper right corner of the page

* fix: font size
This commit is contained in:
Zeke Zhang 2024-04-23 21:17:20 +08:00 committed by GitHub
parent b0ba197915
commit 785cc525c4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 302 additions and 119 deletions

View File

@ -65,6 +65,9 @@ export function withInitializer<T>(C: ComponentType<T>) {
.ant-menu-submenu-title { .ant-menu-submenu-title {
margin-block: 0; margin-block: 0;
} }
.ant-popover-inner-content {
padding: 0;
}
} }
`; `;
}, [token.paddingXXS]); }, [token.paddingXXS]);

View File

@ -1,5 +1,5 @@
import { TinyColor } from '@ctrl/tinycolor'; import { TinyColor } from '@ctrl/tinycolor';
import { useEffect, useMemo } from 'react'; import { useEffect } from 'react';
import { defaultTheme } from '../global-theme'; import { defaultTheme } from '../global-theme';
import { useToken } from '../style'; import { useToken } from '../style';
@ -14,11 +14,6 @@ export const CSSVariableProvider = ({ children }) => {
.onBackground(token.colorFill) .onBackground(token.colorFill)
.toHexShortString(); .toHexShortString();
const colorBgDrawer = useMemo(() => {
const colorBgElevated = new TinyColor(token.colorBgElevated);
return colorBgElevated.isDark() ? token.colorBgElevated : colorBgElevated.darken(4).toHexString();
}, [token.colorBgElevated]);
useEffect(() => { useEffect(() => {
document.body.style.setProperty('--nb-spacing', `${token.marginLG}px`); document.body.style.setProperty('--nb-spacing', `${token.marginLG}px`);
document.body.style.setProperty('--nb-designer-offset', `${token.marginXS}px`); document.body.style.setProperty('--nb-designer-offset', `${token.marginXS}px`);
@ -40,7 +35,6 @@ export const CSSVariableProvider = ({ children }) => {
document.body.style.setProperty('--colorBgScrollBar', colorBgScrollBar); document.body.style.setProperty('--colorBgScrollBar', colorBgScrollBar);
document.body.style.setProperty('--colorBgScrollBarHover', colorBgScrollBarHover); document.body.style.setProperty('--colorBgScrollBarHover', colorBgScrollBarHover);
document.body.style.setProperty('--colorBgScrollBarActive', colorBgScrollBarActive); document.body.style.setProperty('--colorBgScrollBarActive', colorBgScrollBarActive);
document.body.style.setProperty('--colorBgDrawer', colorBgDrawer);
document.body.style.setProperty('--colorSettings', token.colorSettings || defaultTheme.token.colorSettings); document.body.style.setProperty('--colorSettings', token.colorSettings || defaultTheme.token.colorSettings);
document.body.style.setProperty('--colorBgSettingsHover', token.colorBgSettingsHover); document.body.style.setProperty('--colorBgSettingsHover', token.colorBgSettingsHover);
document.body.style.setProperty('--colorBorderSettingsHover', token.colorBorderSettingsHover); document.body.style.setProperty('--colorBorderSettingsHover', token.colorBorderSettingsHover);
@ -48,32 +42,29 @@ export const CSSVariableProvider = ({ children }) => {
// 设置登录页面的背景色 // 设置登录页面的背景色
document.body.style.setProperty('background-color', token.colorBgContainer); document.body.style.setProperty('background-color', token.colorBgContainer);
}, [ }, [
token.marginLG, colorBgScrollBar,
colorBgScrollBarActive,
colorBgScrollBarHover,
colorBgScrollTrack,
token.colorBgContainer,
token.colorBgLayout, token.colorBgLayout,
token.sizeXXL, token.colorBgSettingsHover,
token.marginXS, token.colorBorderSettingsHover,
token.controlHeightLG,
token.paddingContentVerticalSM,
token.marginSM,
token.colorInfoBg, token.colorInfoBg,
token.colorInfoBorder, token.colorInfoBorder,
token.colorText,
token.colorBgContainer,
token.colorFillQuaternary,
token.colorFillSecondary,
token.colorFill,
token.colorFillTertiary,
colorBgScrollTrack,
colorBgScrollBar,
colorBgScrollBarHover,
colorBgScrollBarActive,
colorBgDrawer,
token.colorPrimaryText, token.colorPrimaryText,
token.colorPrimaryTextActive, token.colorPrimaryTextActive,
token.colorPrimaryTextHover, token.colorPrimaryTextHover,
token.colorSettings, token.colorSettings,
token.colorBgSettingsHover, token.colorText,
token.colorBorderSettingsHover, token.colorWarningBg,
token.colorWarningBorder,
token.controlHeightLG,
token.marginLG,
token.marginSM,
token.marginXS,
token.paddingContentVerticalSM,
token.sizeXXL,
]); ]);
return children; return children;

View File

@ -0,0 +1,42 @@
import { MappingAlgorithm, theme } from 'antd';
import { ThemeConfig } from './type';
/**
* token
*/
export const customAlgorithm: MappingAlgorithm = (designToken, derivativeToken) => {
const result: ThemeConfig['token'] = derivativeToken || theme.defaultAlgorithm(designToken);
if (result.paddingPageHorizontal === undefined) {
result.paddingPageHorizontal = result.sizeLG;
}
if (result.paddingPageVertical === undefined) {
result.paddingPageVertical = result.sizeLG;
}
if (result.paddingPopupHorizontal === undefined) {
result.paddingPopupHorizontal = result.sizeLG;
}
if (result.paddingPopupVertical === undefined) {
result.paddingPopupVertical = result.size;
}
if (result.marginBlock === undefined) {
result.marginBlock = result.sizeLG;
}
if (result.borderRadiusBlock === undefined) {
result.borderRadiusBlock = result.borderRadiusLG;
}
return result as any;
};
export const addCustomAlgorithmToTheme = (theme: ThemeConfig) => {
if (Array.isArray(theme.algorithm)) {
if (!theme.algorithm.includes(customAlgorithm)) {
theme.algorithm.push(customAlgorithm);
}
} else {
theme.algorithm = [theme.algorithm, customAlgorithm].filter(Boolean);
}
theme.algorithm = theme.algorithm.filter(Boolean);
return theme;
};

View File

@ -16,6 +16,8 @@ const defaultTheme: ThemeConfig = {
colorSettings: '#F18B62', colorSettings: '#F18B62',
colorBgSettingsHover: 'rgba(241, 139, 98, 0.06)', colorBgSettingsHover: 'rgba(241, 139, 98, 0.06)',
colorBorderSettingsHover: 'rgba(241, 139, 98, 0.3)', colorBorderSettingsHover: 'rgba(241, 139, 98, 0.3)',
// 动画相关
motionUnit: 0.03, motionUnit: 0.03,
motion: !process.env.__E2E__, motion: !process.env.__E2E__,
}, },

View File

@ -2,6 +2,7 @@ import { ConfigProvider, theme as antdTheme } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
import React, { createContext, useCallback, useMemo, useRef } from 'react'; import React, { createContext, useCallback, useMemo, useRef } from 'react';
import compatOldTheme from './compatOldTheme'; import compatOldTheme from './compatOldTheme';
import { addCustomAlgorithmToTheme } from './customAlgorithm';
import defaultTheme from './defaultTheme'; import defaultTheme from './defaultTheme';
import { ThemeConfig } from './type'; import { ThemeConfig } from './type';
@ -62,7 +63,7 @@ export const GlobalThemeProvider = ({ children, theme: themeFromProps }) => {
const value = useMemo(() => { const value = useMemo(() => {
return { return {
theme, theme: addCustomAlgorithmToTheme(theme),
setTheme, setTheme,
setCurrentSettingTheme, setCurrentSettingTheme,
getCurrentSettingTheme, getCurrentSettingTheme,
@ -81,7 +82,7 @@ export const GlobalThemeProvider = ({ children, theme: themeFromProps }) => {
return ( return (
<GlobalThemeContext.Provider value={value}> <GlobalThemeContext.Provider value={value}>
<ConfigProvider theme={compatOldTheme(theme)}>{children}</ConfigProvider> <ConfigProvider theme={compatOldTheme(value.theme)}>{children}</ConfigProvider>
</GlobalThemeContext.Provider> </GlobalThemeContext.Provider>
); );
}; };

View File

@ -23,6 +23,21 @@ export interface CustomToken extends AliasToken {
colorBgSettingsHover: string; colorBgSettingsHover: string;
/** 鼠标悬浮时显示的边框色 */ /** 鼠标悬浮时显示的边框色 */
colorBorderSettingsHover: string; colorBorderSettingsHover: string;
/** 页面左右内边距 */
paddingPageHorizontal: number;
/** 页面上下内边距 */
paddingPageVertical: number;
/** 弹窗左右内边距 */
paddingPopupHorizontal: number;
/** 弹窗上下内边距 */
paddingPopupVertical: number;
/** 区块之间的间隔 */
marginBlock: number;
/** 区块的圆角 */
borderRadiusBlock: number;
} }
export interface ThemeConfig extends _ThemeConfig { export interface ThemeConfig extends _ThemeConfig {

View File

@ -36,6 +36,10 @@ export const PinnedPluginList = () => {
background: rgba(255, 255, 255, 0.1) !important; background: rgba(255, 255, 255, 0.1) !important;
} }
} }
.ant-btn-default {
box-shadow: none;
}
`} `}
style={{ display: 'inline-block' }} style={{ display: 'inline-block' }}
> >

View File

@ -9,14 +9,14 @@ export const useStyles = genStyleHook('nb-action-drawer', (token) => {
'&.reset': { '&.reset': {
'&.nb-action-popup': { '&.nb-action-popup': {
'.ant-drawer-header': { display: 'none' }, '.ant-drawer-header': { display: 'none' },
'.ant-drawer-body': { paddingTop: token.paddingContentVerticalLG, backgroundColor: 'var(--colorBgDrawer)' }, '.ant-drawer-body': { paddingTop: token.paddingContentVerticalLG, backgroundColor: token.colorBgLayout },
}, },
'&.nb-record-picker-selector': { '&.nb-record-picker-selector': {
'.ant-drawer-wrapper-body': { '.ant-drawer-wrapper-body': {
backgroundColor: 'var(--colorBgDrawer)', backgroundColor: token.colorBgLayout,
}, },
'.nb-block-item': { '.nb-block-item': {
marginBottom: token.marginLG, marginBottom: token.marginBlock,
'.general-schema-designer': { '.general-schema-designer': {
top: -token.sizeXS, top: -token.sizeXS,
bottom: -token.sizeXS, bottom: -token.sizeXS,
@ -35,7 +35,20 @@ export const useStyles = genStyleHook('nb-action-drawer', (token) => {
}, },
'.ant-drawer-content-wrapper': { '.ant-drawer-content-wrapper': {
borderLeft: `1px solid ${token.colorBorder}`, borderLeft: `1px solid rgba(255, 255, 255, 0.1)`,
},
// 这里的样式是为了保证页面 tabs 标签下面的分割线和页面内容对齐(页面内边距可以通过主题编辑器调节)
'.ant-tabs-nav': {
paddingLeft: token.paddingLG - token.paddingPageHorizontal,
paddingRight: token.paddingLG - token.paddingPageHorizontal,
marginLeft: token.paddingPageHorizontal - token.paddingLG,
marginRight: token.paddingPageHorizontal - token.paddingLG,
},
'.ant-tabs-content-holder': {
padding: `${token.paddingPopupVertical}px ${token.paddingPopupHorizontal}px`,
margin: `-${token.size}px -${token.paddingLG}px -${token.paddingLG}px`,
}, },
}, },
}; };

View File

@ -4,6 +4,7 @@ import { Modal, ModalProps } from 'antd';
import classNames from 'classnames'; import classNames from 'classnames';
import React from 'react'; import React from 'react';
import { OpenSize, useActionContext } from '.'; import { OpenSize, useActionContext } from '.';
import { useToken } from '../../../style';
import { useSetAriaLabelForModal } from './hooks/useSetAriaLabelForModal'; import { useSetAriaLabelForModal } from './hooks/useSetAriaLabelForModal';
import { ComposedActionDrawer } from './types'; import { ComposedActionDrawer } from './types';
@ -19,13 +20,14 @@ export const ActionModal: ComposedActionDrawer<ModalProps> = observer(
const actualWidth = width ?? openSizeWidthMap.get(openSize); const actualWidth = width ?? openSizeWidthMap.get(openSize);
const schema = useFieldSchema(); const schema = useFieldSchema();
const field = useField(); const field = useField();
const { token } = useToken();
const footerSchema = schema.reduceProperties((buf, s) => { const footerSchema = schema.reduceProperties((buf, s) => {
if (s['x-component'] === footerNodeName) { if (s['x-component'] === footerNodeName) {
return s; return s;
} }
return buf; return buf;
}); });
const showFooter = !!footerSchema;
if (process.env.__E2E__) { if (process.env.__E2E__) {
useSetAriaLabelForModal(visible); useSetAriaLabelForModal(visible);
} }
@ -54,12 +56,30 @@ export const ActionModal: ComposedActionDrawer<ModalProps> = observer(
.ant-modal-content { .ant-modal-content {
background: var(--nb-box-bg); background: var(--nb-box-bg);
border: 1px solid rgba(255, 255, 255, 0.1);
}
// 这里的样式是为了保证页面 tabs 标签下面的分割线和页面内容对齐(页面内边距可以通过主题编辑器调节)
.ant-tabs-nav {
padding-left: ${token.paddingLG - token.paddingPageHorizontal}px;
padding-right: ${token.paddingLG - token.paddingPageHorizontal}px;
margin-left: ${token.paddingPageHorizontal - token.paddingLG}px;
margin-right: ${token.paddingPageHorizontal - token.paddingLG}px;
}
.ant-tabs-content-holder {
padding: ${token.paddingPopupVertical}px ${token.paddingPopupHorizontal}px;
margin: -${token.size}px -${token.paddingLG}px -${token.paddingLG}px;
}
.ant-modal-footer {
display: ${showFooter ? 'block' : 'none'};
} }
} }
`, `,
)} )}
footer={ footer={
footerSchema ? ( showFooter ? (
<RecursionField <RecursionField
basePath={field.address} basePath={field.address}
schema={schema} schema={schema}

View File

@ -1,13 +1,14 @@
import { css } from '@emotion/css'; import { useFieldSchema } from '@formily/react';
import cls from 'classnames'; import cls from 'classnames';
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
import { CustomCreateStylesUtils, createStyles } from '../../../style';
import { SortableItem } from '../../common'; import { SortableItem } from '../../common';
import { useDesigner, useProps } from '../../hooks'; import { useDesigner, useProps } from '../../hooks';
import { useGetAriaLabelOfBlockItem } from './hooks/useGetAriaLabelOfBlockItem'; import { useGetAriaLabelOfBlockItem } from './hooks/useGetAriaLabelOfBlockItem';
import { useFieldSchema } from '@formily/react';
import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
const blockItemCss = css` const useStyles = createStyles(({ css, token }: CustomCreateStylesUtils) => {
return css`
position: relative; position: relative;
&:hover { &:hover {
> .general-schema-designer { > .general-schema-designer {
@ -50,12 +51,18 @@ const blockItemCss = css`
} }
} }
} }
`;
.ant-card {
border-radius: ${token.borderRadiusBlock};
}
`;
});
export const BlockItem: React.FC<any> = withDynamicSchemaProps( export const BlockItem: React.FC<any> = withDynamicSchemaProps(
(props) => { (props) => {
// 新版 UISchema1.0 之后)中已经废弃了 useProps这里之所以继续保留是为了兼容旧版的 UISchema // 新版 UISchema1.0 之后)中已经废弃了 useProps这里之所以继续保留是为了兼容旧版的 UISchema
const { className, children } = useProps(props); const { className, children } = useProps(props);
const { styles: blockItemCss } = useStyles();
const Designer = useDesigner(); const Designer = useDesigner();
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();

View File

@ -1,11 +1,12 @@
import { Card, CardProps } from 'antd';
import React from 'react'; import React from 'react';
import { Card, CardProps, theme } from 'antd'; import { useToken } from '../../../style';
export const BlockItemCard = React.forwardRef<HTMLDivElement, CardProps>(({ children, ...props }, ref) => { export const BlockItemCard = React.forwardRef<HTMLDivElement, CardProps>(({ children, ...props }, ref) => {
const { token } = theme.useToken(); const { token } = useToken();
return ( return (
<Card ref={ref} bordered={false} style={{ marginBottom: token.marginLG }} {...props}> <Card ref={ref} bordered={false} style={{ marginBottom: token.marginBlock }} {...props}>
{children} {children}
</Card> </Card>
); );

View File

@ -5,7 +5,7 @@ const useStyles = genStyleHook('nb-card-item', (token) => {
return { return {
[componentCls]: { [componentCls]: {
marginBottom: token.marginLG, marginBottom: token.marginBlock,
}, },
}; };
}); });

View File

@ -36,16 +36,16 @@ describe('CollectionSelect', () => {
expect(container).toMatchInlineSnapshot(` expect(container).toMatchInlineSnapshot(`
<div> <div>
<div <div
class="css-dev-only-do-not-override-1mw46su ant-app" class="css-dev-only-do-not-override-wwtqkl ant-app"
style="height: 100%;" style="height: 100%;"
> >
<div <div
aria-label="block-item-demo title" aria-label="block-item-demo title"
class="nb-sortable-designer nb-block-item nb-form-item css-1hvilub" class="nb-sortable-designer nb-block-item nb-form-item acss-gw2dva"
role="button" role="button"
> >
<div <div
class="css-1nrq807 ant-formily-item ant-formily-item-layout-horizontal ant-formily-item-feedback-layout-loose ant-formily-item-label-align-right ant-formily-item-control-align-left css-dev-only-do-not-override-1mw46su" class="css-1nrq807 ant-formily-item ant-formily-item-layout-horizontal ant-formily-item-feedback-layout-loose ant-formily-item-label-align-right ant-formily-item-control-align-left css-dev-only-do-not-override-wwtqkl"
> >
<div <div
class="ant-formily-item-label" class="ant-formily-item-label"
@ -75,7 +75,7 @@ describe('CollectionSelect', () => {
class="ant-formily-item-control-content-component" class="ant-formily-item-control-content-component"
> >
<div <div
class="ant-select css-dev-only-do-not-override-1mw46su ant-select-focused ant-select-single ant-select-show-arrow ant-select-show-search" class="ant-select css-dev-only-do-not-override-wwtqkl ant-select-focused ant-select-single ant-select-show-arrow ant-select-show-search"
data-testid="select-collection" data-testid="select-collection"
role="button" role="button"
> >
@ -173,16 +173,16 @@ describe('CollectionSelect', () => {
expect(container).toMatchInlineSnapshot(` expect(container).toMatchInlineSnapshot(`
<div> <div>
<div <div
class="css-dev-only-do-not-override-1mw46su ant-app" class="css-dev-only-do-not-override-wwtqkl ant-app"
style="height: 100%;" style="height: 100%;"
> >
<div <div
aria-label="block-item-demo title" aria-label="block-item-demo title"
class="nb-sortable-designer nb-block-item nb-form-item css-1hvilub" class="nb-sortable-designer nb-block-item nb-form-item acss-gw2dva"
role="button" role="button"
> >
<div <div
class="css-1nrq807 ant-formily-item ant-formily-item-layout-horizontal ant-formily-item-feedback-layout-loose ant-formily-item-label-align-right ant-formily-item-control-align-left css-dev-only-do-not-override-1mw46su" class="css-1nrq807 ant-formily-item ant-formily-item-layout-horizontal ant-formily-item-feedback-layout-loose ant-formily-item-label-align-right ant-formily-item-control-align-left css-dev-only-do-not-override-wwtqkl"
> >
<div <div
class="ant-formily-item-label" class="ant-formily-item-label"
@ -213,7 +213,7 @@ describe('CollectionSelect', () => {
> >
<div> <div>
<span <span
class="ant-tag css-dev-only-do-not-override-1mw46su" class="ant-tag css-dev-only-do-not-override-wwtqkl"
> >
Users Users
</span> </span>

View File

@ -17,7 +17,7 @@ describe('ColorPicker', () => {
expect(container).toMatchInlineSnapshot(` expect(container).toMatchInlineSnapshot(`
<div> <div>
<div <div
class="css-dev-only-do-not-override-1mw46su ant-app" class="css-dev-only-do-not-override-wwtqkl ant-app"
style="height: 100%;" style="height: 100%;"
> >
<div <div
@ -26,7 +26,7 @@ describe('ColorPicker', () => {
style="display: inline-block;" style="display: inline-block;"
> >
<div <div
class="ant-color-picker-trigger css-dev-only-do-not-override-1mw46su" class="ant-color-picker-trigger css-dev-only-do-not-override-wwtqkl"
> >
<div <div
class="ant-color-picker-color-block" class="ant-color-picker-color-block"
@ -81,7 +81,7 @@ describe('ColorPicker', () => {
expect(container).toMatchInlineSnapshot(` expect(container).toMatchInlineSnapshot(`
<div> <div>
<div <div
class="css-dev-only-do-not-override-1mw46su ant-app" class="css-dev-only-do-not-override-wwtqkl ant-app"
style="height: 100%;" style="height: 100%;"
> >
<div <div
@ -90,7 +90,7 @@ describe('ColorPicker', () => {
role="button" role="button"
> >
<div <div
class="ant-color-picker-trigger ant-color-picker-sm css-dev-only-do-not-override-1mw46su ant-color-picker-trigger-disabled" class="ant-color-picker-trigger ant-color-picker-sm css-dev-only-do-not-override-wwtqkl ant-color-picker-trigger-disabled"
> >
<div <div
class="ant-color-picker-color-block" class="ant-color-picker-color-block"

View File

@ -7,7 +7,7 @@ const useStyles = genStyleHook('nb-grid', (token) => {
[componentCls]: { [componentCls]: {
'.ColDivider': { '.ColDivider': {
flexShrink: 0, flexShrink: 0,
width: token.marginLG, width: token.marginBlock,
'.DraggableNode': { '.DraggableNode': {
'&::before': { '&::before': {
@ -20,7 +20,7 @@ const useStyles = genStyleHook('nb-grid', (token) => {
'&:hover': { '&:hover': {
'&::before': { background: 'var(--colorBgSettingsHover) !important' }, '&::before': { background: 'var(--colorBgSettingsHover) !important' },
}, },
width: token.marginLG, width: token.marginBlock,
height: '100%', height: '100%',
position: 'absolute', position: 'absolute',
cursor: 'col-resize', cursor: 'col-resize',
@ -28,10 +28,10 @@ const useStyles = genStyleHook('nb-grid', (token) => {
}, },
'.RowDivider': { '.RowDivider': {
height: token.marginLG, height: token.marginBlock,
width: '100%', width: '100%',
position: 'absolute', position: 'absolute',
marginTop: `calc(-1 * ${token.marginLG}px)`, marginTop: `calc(-1 * ${token.marginBlock}px)`,
}, },
'.CardRow': { '.CardRow': {
@ -40,7 +40,7 @@ const useStyles = genStyleHook('nb-grid', (token) => {
}, },
'.showDivider': { '.showDivider': {
margin: `0 calc(-1 * ${token.marginLG}px)`, margin: `0 calc(-1 * ${token.marginBlock}px)`,
}, },
}, },
}; };

View File

@ -485,7 +485,7 @@ Grid.Col = observer(
let width = ''; let width = '';
if (cols?.length) { if (cols?.length) {
const w = schema?.['x-component-props']?.['width'] || 100 / cols.length; const w = schema?.['x-component-props']?.['width'] || 100 / cols.length;
width = `calc(${w}% - ${token.marginLG}px * ${(showDivider ? cols.length + 1 : 0) / cols.length})`; width = `calc(${w}% - ${token.marginBlock}px * ${(showDivider ? cols.length + 1 : 0) / cols.length})`;
} }
return { width }; return { width };
}, [cols?.length, schema?.['x-component-props']?.['width']]); }, [cols?.length, schema?.['x-component-props']?.['width']]);

View File

@ -10,6 +10,7 @@ import { useTranslation } from 'react-i18next';
import { useSearchParams } from 'react-router-dom'; import { useSearchParams } from 'react-router-dom';
import { FormDialog } from '..'; import { FormDialog } from '..';
import { useStyles as useAClStyles } from '../../../acl/style'; import { useStyles as useAClStyles } from '../../../acl/style';
import { useRequest } from '../../../api-client';
import { useAppSpin } from '../../../application/hooks/useAppSpin'; import { useAppSpin } from '../../../application/hooks/useAppSpin';
import { useDocumentTitle } from '../../../document-title'; import { useDocumentTitle } from '../../../document-title';
import { useGlobalTheme } from '../../../global-theme'; import { useGlobalTheme } from '../../../global-theme';
@ -24,7 +25,6 @@ import { ErrorFallback } from '../error-fallback';
import FixedBlock from './FixedBlock'; import FixedBlock from './FixedBlock';
import { PageDesigner, PageTabDesigner } from './PageTabDesigner'; import { PageDesigner, PageTabDesigner } from './PageTabDesigner';
import { useStyles } from './style'; import { useStyles } from './style';
import { useRequest } from '../../../api-client';
export const Page = (props) => { export const Page = (props) => {
const { children, ...others } = props; const { children, ...others } = props;
@ -62,6 +62,7 @@ export const Page = (props) => {
const [height, setHeight] = useState(0); const [height, setHeight] = useState(0);
const { wrapSSR, hashId, componentCls } = useStyles(); const { wrapSSR, hashId, componentCls } = useStyles();
const aclStyles = useAClStyles(); const aclStyles = useAClStyles();
const { token } = useToken();
const pageHeaderTitle = hidePageTitle ? undefined : fieldSchema.title || compile(title); const pageHeaderTitle = hidePageTitle ? undefined : fieldSchema.title || compile(title);
@ -103,6 +104,13 @@ export const Page = (props) => {
size={'small'} size={'small'}
animated={hasMounted} animated={hasMounted}
activeKey={activeKey} activeKey={activeKey}
// 这里的样式是为了保证页面 tabs 标签下面的分割线和页面内容对齐(页面内边距可以通过主题编辑器调节)
tabBarStyle={{
paddingLeft: token.paddingLG - token.paddingPageHorizontal,
paddingRight: token.paddingLG - token.paddingPageHorizontal,
marginLeft: token.paddingPageHorizontal - token.paddingLG,
marginRight: token.paddingPageHorizontal - token.paddingLG,
}}
onTabClick={(activeKey) => { onTabClick={(activeKey) => {
setLoading(true); setLoading(true);
setSearchParams([['tab', activeKey]]); setSearchParams([['tab', activeKey]]);
@ -219,7 +227,7 @@ function PageContent(
if (schema.name !== activeKey) return null; if (schema.name !== activeKey) return null;
return ( return (
<FixedBlock key={schema.name} height={`calc(${height}px + 46px + ${token.marginLG}px * 2)`}> <FixedBlock key={schema.name} height={`calc(${height}px + 46px + ${token.paddingPageVertical}px * 2)`}>
<SchemaComponent <SchemaComponent
distributed distributed
schema={ schema={
@ -234,7 +242,7 @@ function PageContent(
); );
}) })
) : ( ) : (
<FixedBlock height={`calc(${height}px + 46px + ${token.marginLG}px * 2)`}> <FixedBlock height={`calc(${height}px + 46px + ${token.paddingPageVertical}px * 2)`}>
<div className={`pageWithFixedBlockCss nb-page-content`}> <div className={`pageWithFixedBlockCss nb-page-content`}>
<SchemaComponent schema={fieldSchema} distributed /> <SchemaComponent schema={fieldSchema} distributed />
</div> </div>

View File

@ -111,7 +111,7 @@ export const useStyles = genStyleHook('nb-page', (token) => {
}, },
'.nb-page-wrapper': { '.nb-page-wrapper': {
margin: token.marginLG, padding: `${token.paddingPageVertical}px ${token.paddingPageHorizontal}px`,
flex: 1, flex: 1,
}, },
}, },

View File

@ -12,12 +12,12 @@ describe('Pagination', () => {
expect(container).toMatchInlineSnapshot(` expect(container).toMatchInlineSnapshot(`
<div> <div>
<div <div
class="css-dev-only-do-not-override-1mw46su ant-app" class="css-dev-only-do-not-override-wwtqkl ant-app"
style="height: 100%;" style="height: 100%;"
> >
<div> <div>
<ul <ul
class="ant-pagination css-dev-only-do-not-override-1mw46su" class="ant-pagination css-dev-only-do-not-override-wwtqkl"
> >
<li <li
aria-disabled="true" aria-disabled="true"
@ -122,7 +122,7 @@ describe('Pagination', () => {
expect(container).toMatchInlineSnapshot(` expect(container).toMatchInlineSnapshot(`
<div> <div>
<div <div
class="css-dev-only-do-not-override-1mw46su ant-app" class="css-dev-only-do-not-override-wwtqkl ant-app"
style="height: 100%;" style="height: 100%;"
/> />
</div> </div>

View File

@ -10,11 +10,11 @@ describe('UnixTimestamp', () => {
expect(container).toMatchInlineSnapshot(` expect(container).toMatchInlineSnapshot(`
<div> <div>
<div <div
class="css-dev-only-do-not-override-1mw46su ant-app" class="css-dev-only-do-not-override-wwtqkl ant-app"
style="height: 100%;" style="height: 100%;"
> >
<div <div
class="ant-picker css-dev-only-do-not-override-1mw46su" class="ant-picker css-dev-only-do-not-override-wwtqkl"
> >
<div <div
class="ant-picker-input" class="ant-picker-input"
@ -123,7 +123,7 @@ describe('UnixTimestamp', () => {
expect(container).toMatchInlineSnapshot(` expect(container).toMatchInlineSnapshot(`
<div> <div>
<div <div
class="css-dev-only-do-not-override-1mw46su ant-app" class="css-dev-only-do-not-override-wwtqkl ant-app"
style="height: 100%;" style="height: 100%;"
> >
<div <div

View File

@ -1,3 +1,7 @@
export { createStyles } from 'antd-style'; import { CreateStylesUtils, createStyles } from 'antd-style';
import { CustomToken } from '../global-theme';
export * from './useToken'; export * from './useToken';
export { createStyles };
export interface CustomCreateStylesUtils extends CreateStylesUtils {
token: CustomToken;
}

View File

@ -185,7 +185,17 @@ const category: TokenTree<keyof AliasToken | string> = [
nameEn: 'Margin', nameEn: 'Margin',
desc: '', desc: '',
descEn: '', descEn: '',
mapToken: ['marginXXS', 'marginXS', 'marginSM', 'margin', 'marginMD', 'marginLG', 'marginXL', 'marginXXL'], mapToken: [
'marginXXS',
'marginXS',
'marginSM',
'margin',
'marginMD',
'marginLG',
'marginXL',
'marginXXL',
'marginBlock',
],
}, },
{ {
key: 'padding', key: 'padding',
@ -194,7 +204,19 @@ const category: TokenTree<keyof AliasToken | string> = [
nameEn: 'Padding', nameEn: 'Padding',
desc: '', desc: '',
descEn: '', descEn: '',
mapToken: ['paddingXXS', 'paddingXS', 'paddingSM', 'padding', 'paddingMD', 'paddingLG', 'paddingXL'], mapToken: [
'paddingXXS',
'paddingXS',
'paddingSM',
'padding',
'paddingMD',
'paddingLG',
'paddingXL',
'paddingPageHorizontal',
'paddingPageVertical',
'paddingPopupHorizontal',
'paddingPopupVertical',
],
aliasToken: [ aliasToken: [
'paddingContentHorizontal', 'paddingContentHorizontal',
'paddingContentVertical', 'paddingContentVertical',
@ -222,7 +244,7 @@ const category: TokenTree<keyof AliasToken | string> = [
desc: '', desc: '',
descEn: '', descEn: '',
seedToken: ['borderRadius'], seedToken: ['borderRadius'],
mapToken: ['borderRadius', 'borderRadiusSM', 'borderRadiusLG', 'borderRadiusXS'], mapToken: ['borderRadius', 'borderRadiusSM', 'borderRadiusLG', 'borderRadiusXS', 'borderRadiusBlock'],
}, },
{ {
key: 'boxShadow', key: 'boxShadow',

View File

@ -1711,5 +1711,53 @@
"descEn": "Text color of settings", "descEn": "Text color of settings",
"type": "string", "type": "string",
"source": "seed" "source": "seed"
},
"paddingPageHorizontal": {
"name": "页面左右内边距",
"nameEn": "Horizontal padding of page",
"desc": "用于单独设置页面左右内边距",
"descEn": "Used to set the horizontal padding of the page separately",
"type": "number",
"source": "map"
},
"paddingPageVertical": {
"name": "页面上下内边距",
"nameEn": "Vertical padding of page",
"desc": "用于单独设置页面上下内边距",
"descEn": "Used to set the vertical padding of the page separately",
"type": "number",
"source": "map"
},
"paddingPopupHorizontal": {
"name": "弹窗左右内边距",
"nameEn": "Horizontal padding of popup",
"desc": "用于单独设置弹窗左右内边距",
"descEn": "Used to set the horizontal padding of the popup separately",
"type": "number",
"source": "map"
},
"paddingPopupVertical": {
"name": "弹窗上下内边距",
"nameEn": "Vertical padding of popup",
"desc": "用于单独设置弹窗上下内边距",
"descEn": "Used to set the vertical padding of the popup separately",
"type": "number",
"source": "map"
},
"marginBlock": {
"name": "区块之间的间隔",
"nameEn": "Spacing between blocks",
"desc": "用于设置区块之间的间隔",
"descEn": "Used to set the spacing between blocks",
"type": "number",
"source": "map"
},
"borderRadiusBlock": {
"name": "区块的圆角",
"nameEn": "Radius of block",
"desc": "用于设置区块的圆角",
"descEn": "Used to set the radius of the block",
"type": "number",
"source": "map"
} }
} }

View File

@ -26,7 +26,7 @@ const ThemeList = () => {
} }
return ( return (
<Space size={token.sizeLG} wrap> <Space size={token.marginLG} wrap>
{data?.map((item) => { {data?.map((item) => {
return <ThemeCard item={item} key={item.id} onChange={handleChange} />; return <ThemeCard item={item} key={item.id} onChange={handleChange} />;
})} })}

View File

@ -9,10 +9,13 @@ export function changeAlgorithmFromFunctionToString(themeConfig: any) {
return themeConfig; return themeConfig;
} }
if (Array.isArray(themeConfig.algorithm)) { if (Array.isArray(themeConfig.algorithm)) {
themeConfig.algorithm = themeConfig.algorithm.map((algorithm) => parseAlgorithm(algorithm)); themeConfig.algorithm = themeConfig.algorithm.map((algorithm) => parseAlgorithm(algorithm)).filter(Boolean);
} else { } else {
themeConfig.algorithm = parseAlgorithm(themeConfig.algorithm); themeConfig.algorithm = parseAlgorithm(themeConfig.algorithm);
} }
if (_.isEmpty(themeConfig.algorithm)) {
delete themeConfig.algorithm;
}
return themeConfig; return themeConfig;
} }
@ -26,5 +29,4 @@ function parseAlgorithm(algorithm: ThemeConfig['algorithm']): string {
if (algorithm.toString() === antdTheme.compactAlgorithm.toString()) { if (algorithm.toString() === antdTheme.compactAlgorithm.toString()) {
return 'compactAlgorithm'; return 'compactAlgorithm';
} }
return algorithm.toString();
} }