From 36bcaaef858fe9a77b50e24b09d84d92dc55d163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Wed, 1 Sep 2021 10:56:50 +0800 Subject: [PATCH] Add `variable.less` to support css variable (#31496) * chore: use varaible.less * chore: basic primary varaible * chore: Move to variable * chore: align active color * chore: global fix of css variable * chore: primary colors * chore: button danger * chore: btn default error color * chore: button series * chore: More examples * chore: More components * chore: Form demo * chore: form style * fix: Tag & Alert variable * chore: update footer * chore: rm tmp code * chore: transfer * fix: picker column active color * chore: Adjust active bg color * chore: table hover color * chore: all css variables * chore: Global using variables * chore: Test case * chore: Update test logic * chore: back of default less * chore: entry of site use proxy style * chore: update entry * chore: split of variables * refactor: quick dist speed * fix: site use variable version * chore: Update less config * chore: add mv script * chore: Update repalcement script * chore: Add inject variables * chore: Update script * fix: script path * chore: Move to component instead * chore: fix condition * chore: update config * chore: Update in less transform * chore: Modify logic * chore: change to variables * chore: Update name * fix: script name * chore: do inject * revert: back of path * chore: 2 way of generate * bump tools * chore: Add auto replacement script * chore: auto genrate less file * chore: fix test * test: More test case * chore: Update limit config * test: coverage * docs: Update doc --- .antd-tools.config.js | 49 + components/affix/__tests__/Affix.test.tsx | 9 +- components/button/style/index.less | 8 +- components/button/style/mixin.less | 319 +++-- .../config-provider/__tests__/theme.test.ts | 23 + components/config-provider/context.tsx | 9 + components/config-provider/cssVariables.tsx | 97 ++ components/config-provider/demo/theme.md | 633 ++++++++++ components/config-provider/index.tsx | 31 +- components/date-picker/style/panel.less | 2 +- components/descriptions/index.en-US.md | 12 +- components/form/style/mixin.less | 12 +- components/form/style/status.less | 18 +- components/input/style/mixin.less | 21 +- components/menu/style/index.less | 2 +- components/radio/style/index.less | 2 +- components/result/style/index.less | 2 +- components/style/compact.less | 2 + components/style/dark.less | 2 + components/style/mixins/operation-unit.less | 2 +- components/style/themes/default.less | 46 +- components/style/themes/index.less | 8 +- components/style/themes/variable.less | 1113 +++++++++++++++++ components/style/variable.less | 4 + components/switch/style/index.less | 2 +- components/tag/style/index.less | 22 +- components/transfer/style/index.less | 2 +- docs/react/customize-theme-variable.en-US.md | 72 ++ docs/react/customize-theme-variable.zh-CN.md | 72 ++ docs/react/replace-moment.en-US.md | 2 +- docs/react/replace-moment.zh-CN.md | 2 +- index-style-only.js | 24 + index.js | 24 +- package.json | 12 +- scripts/css-variable-sync.js | 221 ++++ site/antd.js | 29 + site/bisheng.config.js | 6 +- site/theme/en-US.js | 1 + site/theme/static/header.less | 2 +- site/theme/static/index.less | 2 +- site/theme/static/responsive.less | 2 +- site/theme/static/theme.less | 2 +- .../template/Content/ComponentOverview.less | 2 +- .../template/Home/Banner/Background.less | 2 +- site/theme/template/Home/Banner/Logo.less | 2 +- site/theme/template/Home/Banner/index.less | 2 +- .../theme/template/Home/DesignPage/index.less | 2 +- site/theme/template/Home/MorePage.less | 2 +- site/theme/template/Home/RecommendPage.less | 2 +- site/theme/template/Home/index.less | 2 +- site/theme/template/Layout/Footer.tsx | 9 +- site/theme/template/Layout/Header/Github.less | 2 +- site/theme/template/Layout/Header/Logo.less | 2 +- .../template/Layout/Header/Navigation.less | 2 +- .../template/Layout/Header/SearchBar.less | 2 +- site/theme/template/Layout/Header/index.less | 2 +- site/theme/template/Resources/AffixTabs.less | 2 +- site/theme/template/Resources/index.less | 2 +- site/theme/zh-CN.js | 1 + webpack.config.js | 69 +- 60 files changed, 2760 insertions(+), 274 deletions(-) create mode 100644 components/config-provider/__tests__/theme.test.ts create mode 100644 components/config-provider/cssVariables.tsx create mode 100644 components/config-provider/demo/theme.md create mode 100644 components/style/themes/variable.less create mode 100644 components/style/variable.less create mode 100644 docs/react/customize-theme-variable.en-US.md create mode 100644 docs/react/customize-theme-variable.zh-CN.md create mode 100644 index-style-only.js create mode 100644 scripts/css-variable-sync.js create mode 100644 site/antd.js diff --git a/.antd-tools.config.js b/.antd-tools.config.js index 6a229451ca..e5f3f34030 100644 --- a/.antd-tools.config.js +++ b/.antd-tools.config.js @@ -90,6 +90,7 @@ function finalizeDist() { buildThemeFile('default', defaultVars); buildThemeFile('dark', darkVars); buildThemeFile('compact', compactVars); + buildThemeFile('variable', {}); fs.writeFileSync( path.join(process.cwd(), 'dist', `theme.js`), ` @@ -125,8 +126,56 @@ module.exports = { } } +function isComponentStyle(file) { + return file.path.match(/style(\/|\\)index\.tsx/); +} + +function needTransformStyle(content) { + return content.includes('./index.less'); +} + module.exports = { compile: { + transformTSFile(file) { + if (isComponentStyle(file)) { + let content = file.contents.toString(); + + if (needTransformStyle(content)) { + const cloneFile = file.clone(); + + // Origin + content = content.replace('./index.less', './index-default.less'); + cloneFile.contents = Buffer.from(content); + + return cloneFile; + } + } + }, + transformFile(file) { + if (isComponentStyle(file)) { + const content = file.contents.toString(); + + if (needTransformStyle(content)) { + const cloneFile = file.clone(); + cloneFile.contents = Buffer.from( + [ + // Inject variable + '@root-entry-name: default', + // Point to origin file + "@import './index';", + ].join('\n\n'), + ); + cloneFile.path = cloneFile.path.replace('index.tsx', 'index-default.less'); + return cloneFile; + } + } + return []; + }, + lessConfig: { + modifyVars: { + 'root-entry-name': 'default', + }, + }, finalize: finalizeCompile, }, dist: { diff --git a/components/affix/__tests__/Affix.test.tsx b/components/affix/__tests__/Affix.test.tsx index 6a9dcaa17f..51a44031b4 100644 --- a/components/affix/__tests__/Affix.test.tsx +++ b/components/affix/__tests__/Affix.test.tsx @@ -206,11 +206,8 @@ describe('Affix Render', () => { // Mock trigger resize updateCalled.mockReset(); - const resizeObserverInstance: ReactWrapper< - HTMLAttributes, - unknown, - ResizeObserverImpl - > = affixMounterWrapper.find('ResizeObserver') as any; + const resizeObserverInstance: ReactWrapper = + affixMounterWrapper.find('ResizeObserver') as any; resizeObserverInstance .at(index) .instance() @@ -225,7 +222,7 @@ describe('Affix Render', () => { contentBoxSize: [], }, ], - ({} as unknown) as ResizeObserver, + {} as unknown as ResizeObserver, ); await sleep(20); diff --git a/components/button/style/index.less b/components/button/style/index.less index 2a5737b31f..38a7802cc8 100644 --- a/components/button/style/index.less +++ b/components/button/style/index.less @@ -207,19 +207,19 @@ } &-background-ghost&-primary { - .button-variant-ghost(@btn-primary-bg); + .button-variant-ghost(@btn-primary-bg, @btn-primary-bg, @primary-color-hover, @primary-color-active); } &-background-ghost&-danger { - .button-variant-ghost(@btn-danger-border); + .button-variant-ghost(@btn-danger-border, @btn-danger-border, @error-color-hover, @error-color-active); } &-background-ghost&-dangerous { - .button-variant-ghost(@btn-danger-border); + .button-variant-ghost(@btn-danger-border, @btn-danger-border, @error-color-hover, @error-color-active); } &-background-ghost&-dangerous&-link { - .button-variant-ghost(@btn-danger-border, transparent); + .button-variant-ghost(@btn-danger-border, transparent, @error-color-hover, @error-color-active); } &-two-chinese-chars::first-letter { diff --git a/components/button/style/mixin.less b/components/button/style/mixin.less index f34c991a87..5aa3322f37 100644 --- a/components/button/style/mixin.less +++ b/components/button/style/mixin.less @@ -11,134 +11,6 @@ border-radius: @border-radius; } -.button-disabled(@color: @btn-disable-color; @background: @btn-disable-bg; @border: @btn-disable-border) { - &[disabled] { - &, - &:hover, - &:focus, - &:active { - .button-color(@color; @background; @border); - - text-shadow: none; - box-shadow: none; - } - } -} - -.button-variant-primary(@color; @background) { - .button-color(@color; @background; @background); - - text-shadow: @btn-text-shadow; - box-shadow: @btn-primary-shadow; - - &:hover, - &:focus { - & when (@theme = dark) { - .button-color( - @color; ~`colorPalette('@{background}', 7) `; ~`colorPalette('@{background}', 7) ` - ); - } - & when not (@theme = dark) { - .button-color( - @color; ~`colorPalette('@{background}', 5) `; ~`colorPalette('@{background}', 5) ` - ); - } - } - - &:active { - & when (@theme = dark) { - .button-color( - @color; ~`colorPalette('@{background}', 5) `; ~`colorPalette('@{background}', 5) ` - ); - } - & when not (@theme = dark) { - .button-color( - @color; ~`colorPalette('@{background}', 7) `; ~`colorPalette('@{background}', 7) ` - ); - } - } - - .button-disabled(); -} - -.button-variant-other(@color; @background; @border) { - .button-color(@color; @background; @border); - - &:hover, - &:focus { - & when (@theme = dark) { - .button-color(@primary-5; @background; @primary-5); - } - & when not (@theme = dark) { - .button-color( - ~`colorPalette('@{btn-primary-bg}', 5) `; @background; - ~`colorPalette('@{btn-primary-bg}', 5) ` - ); - } - } - &:active { - & when (@theme = dark) { - .button-color(@primary-7; @background; @primary-7); - } - & when not (@theme = dark) { - .button-color( - ~`colorPalette('@{btn-primary-bg}', 7) `; @background; - ~`colorPalette('@{btn-primary-bg}', 7) ` - ); - } - } - .button-disabled(); -} -.button-variant-ghost(@color; @border: @color) { - .button-color(@color; null; @border); - text-shadow: none; - &:hover, - &:focus { - & when (@border = transparent) { - & when (@theme = dark) { - .button-color(~`colorPalette('@{color}', 7) `; null; transparent); - } - & when not (@theme = dark) { - .button-color(~`colorPalette('@{color}', 5) `; null; transparent); - } - } - & when not (@border = transparent) { - & when (@theme = dark) { - .button-color( - ~`colorPalette('@{color}', 7) `; null; ~`colorPalette('@{color}', 7) ` - ); - } - & when not (@theme = dark) { - .button-color( - ~`colorPalette('@{color}', 5) `; null; ~`colorPalette('@{color}', 5) ` - ); - } - } - } - &:active { - & when (@border = transparent) { - & when (@theme = dark) { - .button-color(~`colorPalette('@{color}', 5) `; null; transparent); - } - & when not (@theme = dark) { - .button-color(~`colorPalette('@{color}', 7) `; null; transparent); - } - } - & when not (@border = transparent) { - & when (@theme = dark) { - .button-color( - ~`colorPalette('@{color}', 5) `; null; ~`colorPalette('@{color}', 5) ` - ); - } - & when not (@theme = dark) { - .button-color( - ~`colorPalette('@{color}', 7) `; null; ~`colorPalette('@{color}', 7) ` - ); - } - } - } - .button-disabled(); -} .button-color(@color; @background; @border) { color: @color; border-color: @border; // a inside Button which only work in Chrome @@ -159,6 +31,161 @@ } } } + +.button-disabled(@color: @btn-disable-color; @background: @btn-disable-bg; @border: @btn-disable-border) { + &[disabled] { + &, + &:hover, + &:focus, + &:active { + .button-color(@color; @background; @border); + + text-shadow: none; + box-shadow: none; + } + } +} + +.button-variant-primary(@color; @background; @backgroundHover: yellow; @backgroundActive: yellow) { + .button-color(@color; @background; @background); + + text-shadow: @btn-text-shadow; + box-shadow: @btn-primary-shadow; + + &:hover, + &:focus { + & when (@theme = dark) { + .button-color( + @color; ~`colorPalette('@{background}', 7) `; ~`colorPalette('@{background}', 7) ` + ); + } + & when (not (@theme = dark) and not (@theme = variable)) { + .button-color( + @color; ~`colorPalette('@{background}', 5) `; ~`colorPalette('@{background}', 5) ` + ); + } + & when (@theme = variable) { + .button-color(@color; @backgroundHover; @backgroundHover); + } + } + + &:active { + & when (@theme = dark) { + .button-color( + @color; ~`colorPalette('@{background}', 5) `; ~`colorPalette('@{background}', 5) ` + ); + } + & when (not (@theme = dark) and not (@theme = variable)) { + .button-color( + @color; ~`colorPalette('@{background}', 7) `; ~`colorPalette('@{background}', 7) ` + ); + } + & when (@theme = variable) { + .button-color(@color; @backgroundActive; @backgroundActive); + } + } + + .button-disabled(); +} + +.button-variant-other(@color; @background; @border) { + .button-color(@color; @background; @border); + + &:hover, + &:focus { + & when (@theme = dark) { + .button-color(@primary-5; @background; @primary-5); + } + & when (not (@theme = dark) and not (@theme = variable)) { + .button-color( + ~`colorPalette('@{btn-primary-bg}', 5) `; @background; + ~`colorPalette('@{btn-primary-bg}', 5) ` + ); + } + & when (@theme = variable) { + .button-color(@primary-color-hover; @background; @primary-color-hover); + } + } + &:active { + & when (@theme = dark) { + .button-color(@primary-7; @background; @primary-7); + } + & when (not (@theme = dark) and not (@theme = variable)) { + .button-color( + ~`colorPalette('@{btn-primary-bg}', 7) `; @background; + ~`colorPalette('@{btn-primary-bg}', 7) ` + ); + } + & when (@theme = variable) { + .button-color(@primary-color-active; @background; @primary-color-active); + } + } + .button-disabled(); +} + +.button-variant-ghost(@color; @border; @borderHover: yellow; @borderActive: yellow) { + .button-color(@color; null; @border); + text-shadow: none; + &:hover, + &:focus { + & when (@border = transparent) { + & when (@theme = dark) { + .button-color(~`colorPalette('@{color}', 7) `; null; transparent); + } + & when (not (@theme = dark) and not (@theme = variable)) { + .button-color(~`colorPalette('@{color}', 5) `; null; transparent); + } + & when (@theme = variable) { + .button-color(@borderActive; transparent; transparent); + } + } + & when not (@border = transparent) { + & when (@theme = dark) { + .button-color( + ~`colorPalette('@{color}', 7) `; null; ~`colorPalette('@{color}', 7) ` + ); + } + & when (not (@theme = dark) and not (@theme = variable)) { + .button-color( + ~`colorPalette('@{color}', 5) `; null; ~`colorPalette('@{color}', 5) ` + ); + } + & when (@theme = variable) { + .button-color(@borderHover; transparent; @borderHover); + } + } + } + &:active { + & when (@border = transparent) { + & when (@theme = dark) { + .button-color(~`colorPalette('@{color}', 5) `; null; transparent); + } + & when (not (@theme = dark) and not (@theme = variable)) { + .button-color(~`colorPalette('@{color}', 7) `; null; transparent); + } + & when (@theme = variable) { + .button-color(@borderActive; transparent; transparent); + } + } + & when not (@border = transparent) { + & when (@theme = dark) { + .button-color( + ~`colorPalette('@{color}', 5) `; null; ~`colorPalette('@{color}', 5) ` + ); + } + & when (not (@theme = dark) and not (@theme = variable)) { + .button-color( + ~`colorPalette('@{color}', 7) `; null; ~`colorPalette('@{color}', 7) ` + ); + } + & when (@theme = variable) { + .button-color(@borderActive; transparent; @borderActive); + } + } + } + .button-disabled(); +} + .button-group-base(@btnClassName) { position: relative; display: inline-flex; @@ -252,11 +279,11 @@ } // primary button style .btn-primary() { - .button-variant-primary(@btn-primary-color; @btn-primary-bg); + .button-variant-primary(@btn-primary-color; @btn-primary-bg; @primary-color-hover; @primary-color-active); } // default button style .btn-default() { - .button-variant-other(@btn-default-color; @btn-default-bg; @btn-default-border); + .button-variant-other(@btn-default-color; @btn-default-bg; @btn-default-border; ); &:hover, &:focus, &:active { @@ -275,7 +302,7 @@ } // danger button style .btn-danger() { - .button-variant-primary(@btn-danger-color, @btn-danger-bg); + .button-variant-primary(@btn-danger-color, @btn-danger-bg, @error-color-hover, @error-color-active); } // danger default button style .btn-danger-default() { @@ -288,12 +315,15 @@ ` ); } - & when not (@theme = dark) { + & when (not (@theme = dark) and not (@theme = variable)) { .button-color( ~`colorPalette('@{error-color}', 5) `; @btn-default-bg; ~`colorPalette('@{error-color}', 5) ` ); } + & when (@theme = variable) { + .button-color(@error-color-hover, @btn-default-bg, @error-color-hover); + } } &:active { & when (@theme = dark) { @@ -302,12 +332,15 @@ ` ); } - & when not (@theme = dark) { + & when (not (@theme = dark) and not (@theme = variable)) { .button-color( ~`colorPalette('@{error-color}', 7) `; @btn-default-bg; ~`colorPalette('@{error-color}', 7) ` ); } + & when (@theme = variable) { + .button-color(@error-color-active, @btn-default-bg, @error-color-active); + } } .button-disabled(); } @@ -320,17 +353,23 @@ & when (@theme = dark) { .button-color(~`colorPalette('@{error-color}', 7) `; transparent; transparent); } - & when not (@theme = dark) { + & when (not (@theme = dark) and not (@theme = variable)) { .button-color(~`colorPalette('@{error-color}', 5) `; transparent; transparent); } + & when (@theme = variable) { + .button-color(@error-color-hover; transparent; transparent); + } } &:active { & when (@theme = dark) { .button-color(~`colorPalette('@{error-color}', 5) `; transparent; transparent); } - & when not (@theme = dark) { + & when (not (@theme = dark) and not (@theme = variable)) { .button-color(~`colorPalette('@{error-color}', 7) `; transparent; transparent); } + & when (@theme = variable) { + .button-color(@error-color-active; transparent; transparent); + } } .button-disabled(@disabled-color; transparent; transparent); } @@ -375,18 +414,24 @@ & when (@theme = dark) { .button-color(~`colorPalette('@{error-color}', 7) `; @btn-text-hover-bg; transparent); } - & when not (@theme = dark) { + & when (not (@theme = dark) and not (@theme = variable)) { .button-color(~`colorPalette('@{error-color}', 5) `; @btn-text-hover-bg; transparent); } + & when (@theme = variable) { + .button-color(@error-color-hover; @btn-text-hover-bg; transparent); + } } &:active { & when (@theme = dark) { .button-color(~`colorPalette('@{error-color}', 5) `; fadein(@btn-text-hover-bg, 1%); transparent); } - & when not (@theme = dark) { + & when (not (@theme = dark) and not (@theme = variable)) { .button-color(~`colorPalette('@{error-color}', 7) `; fadein(@btn-text-hover-bg, 1%); transparent); } + & when (@theme = variable) { + .button-color(@error-color-active; fadein(@btn-text-hover-bg, 1%); transparent); + } } .button-disabled(@disabled-color; transparent; transparent); } diff --git a/components/config-provider/__tests__/theme.test.ts b/components/config-provider/__tests__/theme.test.ts new file mode 100644 index 0000000000..cde86a2ede --- /dev/null +++ b/components/config-provider/__tests__/theme.test.ts @@ -0,0 +1,23 @@ +import { kebabCase } from 'lodash'; +import ConfigProvider from '..'; + +describe('ConfigProvider.Theme', () => { + const colorList = ['primaryColor', 'successColor', 'warningColor', 'errorColor', 'infoColor']; + + colorList.forEach(colorName => { + it(colorName, () => { + ConfigProvider.config({ + prefixCls: 'bamboo', + theme: { + [colorName]: '#0000FF', + }, + }); + + const styles: any[] = Array.from(document.querySelectorAll('style')); + const themeStyle = styles.find(style => style['rc-util-key'].includes('-dynamic-theme')); + expect(themeStyle).toBeTruthy(); + + expect(themeStyle.innerHTML).toContain(`--bamboo-${kebabCase(colorName)}: rgb(0, 0, 255)`); + }); + }); +}); diff --git a/components/config-provider/context.tsx b/components/config-provider/context.tsx index 25bb15ffb7..6f42ebeb45 100644 --- a/components/config-provider/context.tsx +++ b/components/config-provider/context.tsx @@ -4,6 +4,15 @@ import { Locale } from '../locale-provider'; import { SizeType } from './SizeContext'; import { RequiredMark } from '../form/Form'; +export interface Theme { + primaryColor?: string; + infoColor?: string; + successColor?: string; + processingColor?: string; + errorColor?: string; + warningColor?: string; +} + export interface CSPConfig { nonce?: string; } diff --git a/components/config-provider/cssVariables.tsx b/components/config-provider/cssVariables.tsx new file mode 100644 index 0000000000..96f3dde0a8 --- /dev/null +++ b/components/config-provider/cssVariables.tsx @@ -0,0 +1,97 @@ +/* eslint-disable import/prefer-default-export, prefer-destructuring */ + +import { updateCSS } from 'rc-util/lib/Dom/dynamicCSS'; +import { TinyColor } from '@ctrl/tinycolor'; +import { generate } from '@ant-design/colors'; +import { Theme } from './context'; + +const dynamicStyleMark = `-ant-${Date.now()}-${Math.random()}`; + +export function registerTheme(globalPrefixCls: string, theme: Theme) { + const variables: Record = {}; + + const formatColor = ( + color: TinyColor, + updater?: (cloneColor: TinyColor) => TinyColor | undefined, + ) => { + let clone = color.clone(); + clone = updater?.(clone) || clone; + return clone.toRgbString(); + }; + + const fillColor = (colorVal: string, type: string) => { + const baseColor = new TinyColor(colorVal); + const colorPalettes = generate(baseColor.toRgbString()); + + variables[`${type}-color`] = formatColor(baseColor); + variables[`${type}-color-disabled`] = colorPalettes[1]; + variables[`${type}-color-hover`] = colorPalettes[4]; + variables[`${type}-color-active`] = colorPalettes[7]; + variables[`${type}-color-outline`] = baseColor.clone().setAlpha(0.2).toRgbString(); + variables[`${type}-color-deprecated-bg`] = colorPalettes[1]; + variables[`${type}-color-deprecated-border`] = colorPalettes[3]; + }; + + // ================ Primary Color ================ + if (theme.primaryColor) { + fillColor(theme.primaryColor, 'primary'); + + const primaryColor = new TinyColor(theme.primaryColor); + const primaryColors = generate(primaryColor.toRgbString()); + + // Legacy - We should use semantic naming standard + primaryColors.forEach((color, index) => { + variables[`primary-${index + 1}`] = color; + }); + // Deprecated + variables['primary-color-deprecated-l-35'] = formatColor(primaryColor, c => c.lighten(35)); + variables['primary-color-deprecated-l-20'] = formatColor(primaryColor, c => c.lighten(20)); + variables['primary-color-deprecated-t-20'] = formatColor(primaryColor, c => c.tint(20)); + variables['primary-color-deprecated-t-50'] = formatColor(primaryColor, c => c.tint(50)); + variables['primary-color-deprecated-f-12'] = formatColor(primaryColor, c => + c.setAlpha(c.getAlpha() * 0.12), + ); + + const primaryActiveColor = new TinyColor(primaryColors[0]); + variables['primary-color-active-deprecated-f-30'] = formatColor(primaryActiveColor, c => + c.setAlpha(c.getAlpha() * 0.3), + ); + variables['primary-color-active-deprecated-d-02'] = formatColor(primaryActiveColor, c => + c.darken(2), + ); + } + + // ================ Success Color ================ + if (theme.successColor) { + fillColor(theme.successColor, 'success'); + } + + // ================ Warning Color ================ + if (theme.warningColor) { + fillColor(theme.warningColor, 'warning'); + } + + // ================= Error Color ================= + if (theme.errorColor) { + fillColor(theme.errorColor, 'error'); + } + + // ================= Info Color ================== + if (theme.infoColor) { + fillColor(theme.infoColor, 'info'); + } + + // Convert to css variables + const cssList = Object.keys(variables).map( + key => `--${globalPrefixCls}-${key}: ${variables[key]};`, + ); + + updateCSS( + ` + :root { + ${cssList.join('\n')} + } + `, + `${dynamicStyleMark}-dynamic-theme`, + ); +} diff --git a/components/config-provider/demo/theme.md b/components/config-provider/demo/theme.md new file mode 100644 index 0000000000..1066a9ed7e --- /dev/null +++ b/components/config-provider/demo/theme.md @@ -0,0 +1,633 @@ +--- +order: 5 +title: + zh-CN: 全局样式 + en-US: Global Theme +--- + +## zh-CN + +通过 css variable 修改全局主题色(你可以切换到组件页面查看更详细的样式展示),不支持 IE。自动生成的变量可能会根据设计调整,请勿直接依赖。详细配置请[点击查看](/docs/react/customize-theme-variable)。 + +## en-US + +Modify global theme color by css variable which IE not support. Css variable depends on the design, it may adjust so please do not directly use it. You can go to other components page for more detail style. [Check this](/docs/react/customize-theme-variable) to view detail. + +```jsx +import { SketchPicker } from 'react-color'; +import React, { useState } from 'react'; +import { + DownOutlined, + MailOutlined, + SettingOutlined, + ClockCircleOutlined, +} from '@ant-design/icons'; +import { + ConfigProvider, + Tag, + Mentions, + Steps, + Button, + Radio, + Space, + Form, + Input, + Row, + Col, + Typography, + Menu, + Dropdown, + Divider, + Pagination, + Select, + Checkbox, + DatePicker, + TimePicker, + InputNumber, + Slider, + Switch, + TreeSelect, + Card, + Table, + Tabs, + Timeline, + Tree, + Alert, + Progress, + Spin, + Transfer, +} from 'antd'; + +const SplitSpace = props => } size={4} {...props} />; + +const inputProps = { + style: { width: 128 }, +}; + +const selectProps = { + ...inputProps, + options: [ + { value: 'light', label: 'Light' }, + { value: 'bamboo', label: 'Bamboo' }, + { value: 'little', label: 'Little' }, + ], +}; + +const treeData = [ + { + value: 'little', + key: 'little', + label: 'Little', + title: 'Little', + children: [ + { value: 'light', key: 'light', label: 'Light', title: 'Light' }, + { value: 'bamboo', key: 'bamboo', label: 'Bamboo', title: 'Bamboo' }, + ], + }, +]; + +const treeSelectProps = { + ...inputProps, + treeCheckable: true, + maxTagCount: 'responsive', + treeData, +}; + +const carTabListNoTitle = [ + { + key: 'article', + tab: 'article', + }, + { + key: 'app', + tab: 'app', + }, + { + key: 'project', + tab: 'project', + }, +]; + +const MyTransfer = () => { + const mockData = []; + for (let i = 0; i < 20; i++) { + mockData.push({ + key: i.toString(), + title: `content${i + 1}`, + description: `description of content${i + 1}`, + }); + } + + return ( + item.title} + /> + ); +}; + +const FormSizeDemo = () => { + const [color, setColor] = useState({ + primaryColor: '#1890ff', + errorColor: '#ff4d4f', + warningColor: '#faad14', + successColor: '#52c41a', + infoColor: '#1890ff', + }); + + function onColorChange(nextColor) { + const mergedNextColor = { + ...color, + ...nextColor, + }; + setColor(mergedNextColor); + ConfigProvider.config({ + theme: mergedNextColor, + }); + } + + return ( + + + + {/* Primary Color */} + { + onColorChange({ + primaryColor: hex, + }); + }} + /> + + var(`--ant-primary-color`) + + {/* Error Color */} + { + onColorChange({ + errorColor: hex, + }); + }} + /> + + var(`--ant-error-color`) + + {/* Warning Color */} + { + onColorChange({ + warningColor: hex, + }); + }} + /> + + var(`--ant-warning-color`) + + {/* Success Color */} + { + onColorChange({ + successColor: hex, + }); + }} + /> + + var(`--ant-success-color`) + + {/* Info Color */} + { + onColorChange({ + infoColor: hex, + }); + }} + /> + + var(`--ant-info-color`) + + + + + } style={{ width: '100%' }} size={0}> + {/* Primary Button */} + + + + + + + + + {/* Danger Button */} + + + + + + + + + {/* Ghost Button */} + + + + + + + + + + {/* Typography */} + + Text (success) + Text(warning) + Text(danger) + + Link + + Text + + {/* Dropdown */} + + 1st menu item + a danger item + + } + > + e.preventDefault()}> + Hover me + + + + {/* Spin */} + + + + {/* Menu - horizontal */} + + + + }> + Mail + + } title="Submenu"> + + Option 1 + Option 2 + + + + + + + }> + Mail + + } title="Submenu"> + + Option 1 + Option 2 + + + + + + + {/* Menu - vertical */} + + + + }> + Mail + + } title="Submenu"> + + Option 1 + Option 2 + + + + + + + }> + Mail + + } title="Submenu"> + + Option 1 + Option 2 + + + + + + + {/* Pagination */} + + + {/* Steps */} + + + + + + + {/* Steps - dot */} + + + + + + + + {/* Form - Input */} +
+ + + + + + + + + + + + + + + + + +
+ + {/* Form - Select */} +
+ + + + + + + + +