From 4f5ec0a5810b9e6a141e3335e2be5272379edd10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=AB=E9=9B=A8=E6=B0=B4=E8=BF=87=E6=BB=A4=E7=9A=84?= =?UTF-8?q?=E7=A9=BA=E6=B0=94-Rain?= <958414905@qq.com> Date: Fri, 21 Jul 2023 10:38:56 +0800 Subject: [PATCH] feat(theme-editor): support to config Header's color and Settings button's color (#2263) * feat: add color options to theme editor * feat: add default theme * refactor: optimize * feat: support to change color of UI settings * fix: fix menu background color * fix: fix color of UI settings * feat: support to set alpha * refactor: migrate style to a file * feat: support colorBgSettingsHover and colorBorderSettingsHover * feat: adapt settings color * fix: should be reset together * feat: compat old theme --- .../src/css-variable/CSSVariableProvider.tsx | 6 + .../client/src/global-theme/defaultTheme.ts | 22 + .../core/client/src/global-theme/index.tsx | 13 +- packages/core/client/src/global-theme/type.ts | 36 + .../route-switch/antd/admin-layout/index.tsx | 17 +- .../antd/__builtins__/hooks/useToken.ts | 14 +- .../antd/__builtins__/style.ts | 5 +- .../antd/action/Action.style.ts | 57 + .../schema-component/antd/action/Action.tsx | 97 +- .../AssociationFilter.Item.style.ts | 6 +- .../association-filter/AssociationFilter.tsx | 6 +- .../antd/block-item/BlockItem.tsx | 6 +- .../antd/expand-action/Expand.Action.tsx | 4 +- .../antd/filter/FilterAction.tsx | 4 +- .../antd/filter/SaveDefaultValue.tsx | 4 +- .../antd/grid-card/GridCard.tsx | 4 +- .../schema-component/antd/grid/Grid.style.ts | 2 +- .../src/schema-component/antd/grid/Grid.tsx | 7 +- .../antd/kanban/Kanban.Card.Designer.tsx | 2 +- .../schema-component/antd/list/List.style.ts | 4 +- .../src/schema-component/antd/menu/Menu.tsx | 8 +- .../src/schema-component/antd/page/style.ts | 10 +- .../antd/table-v2/Table.Column.ActionBar.tsx | 4 +- .../schema-component/antd/table-v2/Table.tsx | 33 +- .../antd/table/Table.Array.tsx | 5 +- .../antd/table/Table.Column.ActionBar.tsx | 4 +- .../src/schema-component/antd/tabs/Tabs.tsx | 7 +- .../common/sortable-item/SortableItem.tsx | 7 +- .../core/DesignableSwitch.tsx | 2 +- .../schema-initializer/SchemaInitializer.tsx | 8 +- .../buttons/TabPaneInitializers.tsx | 4 +- .../components/CreateRecordAction.tsx | 4 +- .../schema-settings/GeneralSchemaDesigner.tsx | 4 +- packages/core/client/src/style/useToken.ts | 14 +- .../plugins/export/src/client/useShared.ts | 8 +- .../plugins/import/src/client/useShared.ts | 8 +- .../container/Container.Designer.tsx | 4 +- .../schema/components/menu/Menu.Designer.tsx | 10 +- .../schema/components/page/Page.Designer.tsx | 4 +- .../src/client/router/Application.tsx | 2 +- packages/plugins/theme-editor/package.json | 3 +- .../hooks/useControlledTheme.tsx | 14 + .../antd-token-previewer/meta/category.ts | 58 +- .../antd-token-previewer/meta/interface.ts | 2 + .../token-panel-pro/TokenContent.tsx | 11 +- .../token-panel-pro/TokenDetail.tsx | 2 +- .../token-panel-pro/calcCustomToken.ts | 18 + .../token-panel-pro/token-meta.json | 1715 +++++++++++++++++ .../src/client/components/InitializeTheme.tsx | 10 +- .../src/client/components/ThemeCard.tsx | 12 +- .../src/client/components/ToEditTheme.tsx | 9 +- .../src/client/utils/compatOldTheme.ts | 12 + packages/plugins/theme-editor/src/types.ts | 2 +- 53 files changed, 2138 insertions(+), 196 deletions(-) create mode 100644 packages/core/client/src/global-theme/defaultTheme.ts create mode 100644 packages/core/client/src/global-theme/type.ts create mode 100644 packages/core/client/src/schema-component/antd/action/Action.style.ts create mode 100644 packages/plugins/theme-editor/src/client/antd-token-previewer/token-panel-pro/calcCustomToken.ts create mode 100644 packages/plugins/theme-editor/src/client/antd-token-previewer/token-panel-pro/token-meta.json create mode 100644 packages/plugins/theme-editor/src/client/utils/compatOldTheme.ts diff --git a/packages/core/client/src/css-variable/CSSVariableProvider.tsx b/packages/core/client/src/css-variable/CSSVariableProvider.tsx index f12a557fc..e4c49a035 100644 --- a/packages/core/client/src/css-variable/CSSVariableProvider.tsx +++ b/packages/core/client/src/css-variable/CSSVariableProvider.tsx @@ -38,6 +38,9 @@ const CSSVariableProvider = ({ children }) => { document.body.style.setProperty('--colorBgScrollBarHover', colorBgScrollBarHover); document.body.style.setProperty('--colorBgScrollBarActive', colorBgScrollBarActive); document.body.style.setProperty('--colorBgDrawer', colorBgDrawer); + document.body.style.setProperty('--colorSettings', token.colorSettings); + document.body.style.setProperty('--colorBgSettingsHover', token.colorBgSettingsHover); + document.body.style.setProperty('--colorBorderSettingsHover', token.colorBorderSettingsHover); // 设置登录页面的背景色 document.body.style.setProperty('background-color', token.colorBgContainer); @@ -65,6 +68,9 @@ const CSSVariableProvider = ({ children }) => { token.colorPrimaryText, token.colorPrimaryTextActive, token.colorPrimaryTextHover, + token.colorSettings, + token.colorBgSettingsHover, + token.colorBorderSettingsHover, ]); return children; diff --git a/packages/core/client/src/global-theme/defaultTheme.ts b/packages/core/client/src/global-theme/defaultTheme.ts new file mode 100644 index 000000000..3e9ff030c --- /dev/null +++ b/packages/core/client/src/global-theme/defaultTheme.ts @@ -0,0 +1,22 @@ +import { ThemeConfig } from './type'; + +const defaultTheme: ThemeConfig = { + name: '', + token: { + // 顶部导航栏 + colorPrimaryHeader: '#001529', + colorBgHeader: '#001529', + colorBgHeaderMenuHover: '#ffffff1a', + colorBgHeaderMenuActive: '#ffffff1a', + colorTextHeaderMenu: '#ffffffa6', + colorTextHeaderMenuHover: '#ffffff', + colorTextHeaderMenuActive: '#ffffff', + + // UI 配置组件 + colorSettings: '#F18B62', + colorBgSettingsHover: 'rgba(241, 139, 98, 0.06)', + colorBorderSettingsHover: 'rgba(241, 139, 98, 0.3)', + }, +}; + +export default defaultTheme; diff --git a/packages/core/client/src/global-theme/index.tsx b/packages/core/client/src/global-theme/index.tsx index 661ef909d..f61e77a14 100644 --- a/packages/core/client/src/global-theme/index.tsx +++ b/packages/core/client/src/global-theme/index.tsx @@ -1,8 +1,8 @@ -import { ConfigProvider, theme as antdTheme, type ThemeConfig as Config } from 'antd'; +import { ConfigProvider, theme as antdTheme } from 'antd'; import _ from 'lodash'; import React, { createContext, useCallback, useMemo, useRef } from 'react'; - -type ThemeConfig = Config & { name?: string; algorithm?: string | Config['algorithm'] }; +import defaultTheme from './defaultTheme'; +import { ThemeConfig } from './type'; interface ThemeItem { id: number; @@ -27,8 +27,8 @@ export const useGlobalTheme = () => { return React.useContext(GlobalThemeContext); }; -export const GlobalThemeProvider = ({ children, theme: defaultTheme }) => { - const [theme, setTheme] = React.useState(defaultTheme || { name: 'Custom theme' }); +export const GlobalThemeProvider = ({ children, theme: themeFromProps }) => { + const [theme, setTheme] = React.useState(themeFromProps || defaultTheme); const currentSettingThemeRef = useRef(null); const currentEditingThemeRef = useRef(null); @@ -83,3 +83,6 @@ export const GlobalThemeProvider = ({ children, theme: defaultTheme }) => { }; export { default as AntdAppProvider } from './AntdAppProvider'; +export * from './type'; +export { defaultTheme }; + diff --git a/packages/core/client/src/global-theme/type.ts b/packages/core/client/src/global-theme/type.ts new file mode 100644 index 000000000..014de5344 --- /dev/null +++ b/packages/core/client/src/global-theme/type.ts @@ -0,0 +1,36 @@ +import { MappingAlgorithm } from 'antd/es/config-provider/context'; +import { OverrideToken } from 'antd/es/theme/interface'; +import { AliasToken } from 'antd/es/theme/internal'; + +export interface CustomToken extends AliasToken { + /** 顶部导航栏主色 */ + colorPrimaryHeader: string; + /** 导航栏背景色 */ + colorBgHeader: string; + /** 导航栏菜单背景色悬浮态 */ + colorBgHeaderMenuHover: string; + /** 导航栏菜单背景色激活态 */ + colorBgHeaderMenuActive: string; + /** 导航栏菜单文本色 */ + colorTextHeaderMenu: string; + /** 导航栏菜单文本色悬浮态 */ + colorTextHeaderMenuHover: string; + /** 导航栏菜单文本色激活态 */ + colorTextHeaderMenuActive: string; + + /** UI 配置色 */ + colorSettings: string; + /** 鼠标悬浮时显示的背景色 */ + colorBgSettingsHover: string; + /** 鼠标悬浮时显示的边框色 */ + colorBorderSettingsHover: string; +} + +export interface ThemeConfig { + name?: string; + token?: Partial; + components?: OverrideToken; + algorithm?: MappingAlgorithm | MappingAlgorithm[]; + hashed?: boolean; + inherit?: boolean; +} diff --git a/packages/core/client/src/route-switch/antd/admin-layout/index.tsx b/packages/core/client/src/route-switch/antd/admin-layout/index.tsx index 42b5f7233..50fabb1af 100644 --- a/packages/core/client/src/route-switch/antd/admin-layout/index.tsx +++ b/packages/core/client/src/route-switch/antd/admin-layout/index.tsx @@ -19,6 +19,7 @@ import { useDocumentTitle, useRequest, useSystemSettings, + useToken, } from '../../../'; import { Plugin } from '../../../application/Plugin'; import { useCollectionManager } from '../../../collection-manager'; @@ -153,6 +154,7 @@ export const InternalAdminLayout = (props: any) => { const result = useSystemSettings(); const { service } = useCollectionManager(); const params = useParams(); + const { token } = useToken(); return ( @@ -161,10 +163,12 @@ export const InternalAdminLayout = (props: any) => { .ant-menu.ant-menu-dark .ant-menu-item-selected, .ant-menu-submenu-popup.ant-menu-dark .ant-menu-item-selected, .ant-menu-submenu-horizontal.ant-menu-submenu-selected { - background-color: rgba(255, 255, 255, 0.1); + background-color: ${token.colorBgHeaderMenuActive}; + color: ${token.colorTextHeaderMenuActive}; } .ant-menu-dark.ant-menu-horizontal > .ant-menu-item:hover { - background-color: rgba(255, 255, 255, 0.1); + background-color: ${token.colorBgHeaderMenuHover}; + color: ${token.colorTextHeaderMenuHover}; } position: fixed; @@ -174,6 +178,15 @@ export const InternalAdminLayout = (props: any) => { line-height: var(--nb-header-height); padding: 0; z-index: 100; + background-color: ${token.colorBgHeader}; + + .ant-menu { + background-color: transparent; + } + + .ant-menu-item { + color: ${token.colorTextHeaderMenu}; + } `} >
{ + token: CustomToken; +} + +const useToken = () => { + const result = useAntdToken(); + return result as Result; +}; + export { useToken }; diff --git a/packages/core/client/src/schema-component/antd/__builtins__/style.ts b/packages/core/client/src/schema-component/antd/__builtins__/style.ts index dd69d2caf..b8e9efc1d 100644 --- a/packages/core/client/src/schema-component/antd/__builtins__/style.ts +++ b/packages/core/client/src/schema-component/antd/__builtins__/style.ts @@ -2,6 +2,7 @@ import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs'; import { useStyleRegister } from '@ant-design/cssinjs'; import { merge } from '@formily/shared'; import type { ComponentTokenMap, GlobalToken } from 'antd/es/theme/interface'; +import { CustomToken } from '../../../global-theme'; import { useConfig, usePrefixCls, useToken } from './hooks'; export type OverrideComponent = keyof ComponentTokenMap | string; @@ -62,7 +63,7 @@ export type UseComponentStyleResult = { export const genStyleHook = ( component: ComponentName, - styleFn: (token: TokenWithCommonCls, props: any, info: StyleInfo) => CSSInterpolation, + styleFn: (token: TokenWithCommonCls, props: any, info: StyleInfo) => CSSInterpolation, ) => { return (props?: any): UseComponentStyleResult => { const { theme, token, hashId } = useToken(); @@ -80,7 +81,7 @@ export const genStyleHook = ( }, () => { const componentCls = `.${prefixCls}`; - const mergedToken: TokenWithCommonCls = merge(token, { + const mergedToken: TokenWithCommonCls = merge(token, { componentCls, prefixCls, iconCls: `.${iconPrefixCls}`, diff --git a/packages/core/client/src/schema-component/antd/action/Action.style.ts b/packages/core/client/src/schema-component/antd/action/Action.style.ts new file mode 100644 index 000000000..0c89a1290 --- /dev/null +++ b/packages/core/client/src/schema-component/antd/action/Action.style.ts @@ -0,0 +1,57 @@ +import { genStyleHook } from '../__builtins__'; + +const useStyles = genStyleHook('nb-action', (token) => { + const { componentCls } = token; + + return { + [componentCls]: { + '.renderButton': { + position: 'relative', + '&:hover': { '> .general-schema-designer': { display: 'block' } }, + '&.nb-action-link': { + '> .general-schema-designer': { + top: '-10px', + bottom: '-10px', + left: '-10px', + right: '-10px', + }, + }, + '> .general-schema-designer': { + position: 'absolute', + zIndex: 999, + top: '0', + bottom: '0', + left: '0', + right: '0', + display: 'none', + background: 'var(--colorBgSettingsHover)', + border: '0', + pointerEvents: 'none', + '> .general-schema-designer-icons': { + position: 'absolute', + right: '2px', + top: '2px', + lineHeight: '16px', + pointerEvents: 'all', + '.ant-space-item': { + backgroundColor: token.colorSettings, + color: '#fff', + lineHeight: '16px', + width: '16px', + paddingLeft: '1px', + alignSelf: 'stretch', + }, + }, + }, + }, + + '.popover': { + display: 'flex', + justifyContent: 'flex-end', + width: '100%', + }, + }, + }; +}); + +export default useStyles; diff --git a/packages/core/client/src/schema-component/antd/action/Action.tsx b/packages/core/client/src/schema-component/antd/action/Action.tsx index 2f43696dc..e68dfdb37 100644 --- a/packages/core/client/src/schema-component/antd/action/Action.tsx +++ b/packages/core/client/src/schema-component/antd/action/Action.tsx @@ -1,4 +1,3 @@ -import { css } from '@emotion/css'; import { observer, RecursionField, useField, useFieldSchema, useForm } from '@formily/react'; import { App, Button, Popover } from 'antd'; import classnames from 'classnames'; @@ -17,56 +16,13 @@ import { ActionDrawer } from './Action.Drawer'; import { ActionLink } from './Action.Link'; import { ActionModal } from './Action.Modal'; import { ActionPage } from './Action.Page'; +import useStyles from './Action.style'; import { ActionContextProvider } from './context'; import { useA } from './hooks'; import { ComposedAction } from './types'; import { linkageAction } from './utils'; import { lodash } from '@nocobase/utils'; -export const actionDesignerCss = css` - position: relative; - &:hover { - > .general-schema-designer { - display: block; - } - } - &.nb-action-link { - > .general-schema-designer { - top: -10px; - bottom: -10px; - left: -10px; - right: -10px; - } - } - > .general-schema-designer { - position: absolute; - z-index: 999; - top: 0; - bottom: 0; - left: 0; - right: 0; - display: none; - background: rgba(241, 139, 98, 0.06); - border: 0; - pointer-events: none; - > .general-schema-designer-icons { - position: absolute; - right: 2px; - top: 2px; - line-height: 16px; - pointer-events: all; - .ant-space-item { - background-color: #f18b62; - color: #fff; - line-height: 16px; - width: 16px; - padding-left: 1px; - align-self: stretch; - } - } - } -`; - export const Action: ComposedAction = observer( (props: any) => { const { @@ -81,6 +37,7 @@ export const Action: ComposedAction = observer( title, ...others } = props; + const { wrapSSR, componentCls, hashId } = useStyles(); const { t } = useTranslation(); const { onClick } = useProps(props); const [visible, setVisible] = useState(false); @@ -148,7 +105,7 @@ export const Action: ComposedAction = observer( } }} component={tarComponent || Button} - className={classnames(actionDesignerCss, className)} + className={classnames('renderButton', className)} type={props.type === 'danger' ? undefined : props.type} > {actionTitle} @@ -157,23 +114,25 @@ export const Action: ComposedAction = observer( ); }; - return ( - - {popover && } - {!popover && renderButton()} - {!popover &&
e.stopPropagation()}>{props.children}
} - {element} -
+ return wrapSSR( +
+ + {popover && } + {!popover && renderButton()} + {!popover &&
e.stopPropagation()}>{props.children}
} + {element} +
+
, ); }, { displayName: 'Action' }, @@ -201,17 +160,7 @@ Action.Popover = observer( Action.Popover.Footer = observer( (props) => { - return ( -
- {props.children} -
- ); + return
{props.children}
; }, { displayName: 'Action.Popover.Footer' }, ); diff --git a/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.Item.style.ts b/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.Item.style.ts index 94c4a7a05..cd100fd3f 100644 --- a/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.Item.style.ts +++ b/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.Item.style.ts @@ -10,7 +10,7 @@ const useStyles = genStyleHook('nb-association-filter-item', (token) => { '&:hover': { '> .general-schema-designer': { display: 'block' } }, '&.nb-form-item:hover': { '> .general-schema-designer': { - background: 'rgba(241, 139, 98, 0.06) !important', + background: 'var(--colorBgSettingsHover) !important', border: '0 !important', top: `-${token.sizeXXS}px !important`, bottom: `-${token.sizeXXS}px !important`, @@ -26,7 +26,7 @@ const useStyles = genStyleHook('nb-association-filter-item', (token) => { left: '0', right: '0', display: 'none', - border: '2px solid rgba(241, 139, 98, 0.3)', + border: '2px solid var(--colorBorderSettingsHover)', pointerEvents: 'none', '> .general-schema-designer-icons': { position: 'absolute', @@ -35,7 +35,7 @@ const useStyles = genStyleHook('nb-association-filter-item', (token) => { lineHeight: '16px', pointerEvents: 'all', '.ant-space-item': { - backgroundColor: '#f18b62', + backgroundColor: 'var(--colorSettings)', color: '#fff', lineHeight: '16px', width: '16px', diff --git a/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.tsx b/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.tsx index 2195b5564..7c2b1d58b 100644 --- a/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.tsx +++ b/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.tsx @@ -39,7 +39,7 @@ export const AssociationFilter = (props) => { } &.nb-form-item:hover { > .general-schema-designer { - background: rgba(241, 139, 98, 0.06) !important; + background: var(--colorBgSettingsHover) !important; border: 0 !important; top: -5px !important; bottom: -5px !important; @@ -55,7 +55,7 @@ export const AssociationFilter = (props) => { left: 0; right: 0; display: none; - border: 2px solid rgba(241, 139, 98, 0.3); + border: 2px solid var(--colorBorderSettingsHover); pointer-events: none; > .general-schema-designer-icons { position: absolute; @@ -64,7 +64,7 @@ export const AssociationFilter = (props) => { line-height: 16px; pointer-events: all; .ant-space-item { - background-color: #f18b62; + background-color: var(--colorSettings); color: #fff; line-height: 16px; width: 16px; diff --git a/packages/core/client/src/schema-component/antd/block-item/BlockItem.tsx b/packages/core/client/src/schema-component/antd/block-item/BlockItem.tsx index 27057a924..7cf28d052 100644 --- a/packages/core/client/src/schema-component/antd/block-item/BlockItem.tsx +++ b/packages/core/client/src/schema-component/antd/block-item/BlockItem.tsx @@ -21,7 +21,7 @@ export const BlockItem: React.FC = (props) => { } &.nb-form-item:hover { > .general-schema-designer { - background: rgba(241, 139, 98, 0.06) !important; + background: var(--colorBgSettingsHover) !important; border: 0 !important; top: -5px !important; bottom: -5px !important; @@ -37,7 +37,7 @@ export const BlockItem: React.FC = (props) => { left: 0; right: 0; display: none; - border: 2px solid rgba(241, 139, 98, 0.3); + border: 2px solid var(--colorBorderSettingsHover); pointer-events: none; > .general-schema-designer-icons { position: absolute; @@ -46,7 +46,7 @@ export const BlockItem: React.FC = (props) => { line-height: 16px; pointer-events: all; .ant-space-item { - background-color: #f18b62; + background-color: var(--colorSettings); color: #fff; line-height: 16px; width: 16px; diff --git a/packages/core/client/src/schema-component/antd/expand-action/Expand.Action.tsx b/packages/core/client/src/schema-component/antd/expand-action/Expand.Action.tsx index ab330d11e..640e28378 100644 --- a/packages/core/client/src/schema-component/antd/expand-action/Expand.Action.tsx +++ b/packages/core/client/src/schema-component/antd/expand-action/Expand.Action.tsx @@ -20,7 +20,7 @@ const actionDesignerCss = css` left: 0; right: 0; display: none; - background: rgba(241, 139, 98, 0.06); + background: var(--colorBgSettingsHover); border: 0; top: 0; bottom: 0; @@ -34,7 +34,7 @@ const actionDesignerCss = css` line-height: 16px; pointer-events: all; .ant-space-item { - background-color: #f18b62; + background-color: var(--colorSettings); color: #fff; line-height: 16px; width: 16px; diff --git a/packages/core/client/src/schema-component/antd/filter/FilterAction.tsx b/packages/core/client/src/schema-component/antd/filter/FilterAction.tsx index c55432f24..2faac33c2 100644 --- a/packages/core/client/src/schema-component/antd/filter/FilterAction.tsx +++ b/packages/core/client/src/schema-component/antd/filter/FilterAction.tsx @@ -103,8 +103,8 @@ const SaveConditions = () => {