feat: dark color algorithm (#36546)

* feat: dark color algorithm

* test: fix lint

* chore: update colorError

* chore: color update
This commit is contained in:
MadCcc 2022-07-15 19:27:29 +08:00 committed by GitHub
parent 99d9d66f3b
commit dc017f5141
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 200 additions and 183 deletions

View File

@ -16,7 +16,7 @@ describe('ConfigProvider.DynamicTheme', () => {
<ConfigProvider
theme={{
token: {
colorPrimary: '#f00',
brandColor: '#f00000',
},
}}
>
@ -30,7 +30,7 @@ describe('ConfigProvider.DynamicTheme', () => {
dynamicStyles.some(style => {
const { innerHTML } = style;
return (
innerHTML.includes('.ant-btn-primary') && innerHTML.includes('background-color:#f00')
innerHTML.includes('.ant-btn-primary') && innerHTML.includes('background-color:#f00000')
);
}),
).toBeTruthy();

View File

@ -69,7 +69,7 @@ describe('ConfigProvider.Theme', () => {
<Demo />
</ConfigProvider>,
);
expect(tokenRef?.colorBgContainer).toBe('#141414');
expect(tokenRef?.colorPrimary).toBe('#177ddc');
});
it('overriding component token should work', () => {

View File

@ -31,7 +31,7 @@ describe('Theme', () => {
<ConfigProvider
theme={{
token: {
colorPrimary: 'red',
brandColor: '#ff0000',
},
}}
>
@ -41,7 +41,7 @@ describe('Theme', () => {
expect(themeRef.current!.token).toEqual(
expect.objectContaining({
colorPrimary: 'red',
colorPrimary: '#ff0000',
colorPrimaryHover: '#ff3029', // It's safe to modify if theme logic changed
}),
);

View File

@ -148,7 +148,7 @@ export type GlobalToken = AliasToken & ComponentTokenMap;
// 🔥🔥🔥🔥🔥🔥🔥 DO NOT MODIFY THIS. PLEASE CONTACT DESIGNER. 🔥🔥🔥🔥🔥🔥🔥
export interface SeedToken extends PresetColorType {
// Color
colorPrimary: string;
brandColor: string;
colorSuccess: string;
colorWarning: string;
colorError: string;
@ -206,26 +206,34 @@ export interface SeedToken extends PresetColorType {
export interface ColorMapToken {
// Color
colorPrimary: string;
colorPrimaryHover: string;
colorPrimaryBg: string;
colorPrimaryBgHover: string;
colorPrimaryActive: string;
colorPrimaryBorder: string; // primary[2]
colorPrimaryBorderHover: string;
colorPrimaryOutline: string;
colorSuccess: string;
colorSuccessBorder: string;
colorSuccessBg: string; // success[0]
colorWarning: string;
colorWarningHover: string;
colorWarningActive: string;
colorWarningBorder: string;
colorWarningBg: string;
colorWarningOutline: string;
colorError: string;
colorErrorHover: string;
colorErrorActive: string;
colorErrorBorder: string;
colorErrorBg: string;
colorErrorOutline: string;
colorInfo: string;
colorInfoBorder: string;
colorInfoBg: string;
@ -317,11 +325,7 @@ export interface CommonMapToken {
// == Map Token ==
// ======================================================================
// 🔥🔥🔥🔥🔥🔥🔥 DO NOT MODIFY THIS. PLEASE CONTACT DESIGNER. 🔥🔥🔥🔥🔥🔥🔥
export interface MapToken extends SeedToken, ColorPalettes, ColorMapToken, CommonMapToken {
colorPrimaryOutline: string;
colorWarningOutline: string;
colorErrorOutline: string;
}
export interface MapToken extends SeedToken, ColorPalettes, ColorMapToken, CommonMapToken {}
// ======================================================================
// == Alias Token ==

View File

@ -76,3 +76,11 @@ export interface BgPalettes {
'light-10'?: string;
base: string;
}
export type GeneratePrimaryPalettes = (primaryBaseColor: string) => PrimaryPalettes;
export type GenerateSuccessPalettes = (successBaseColor: string) => SuccessPalettes;
export type GenerateWarningPalettes = (warningBaseColor: string) => WarningPalettes;
export type GenerateErrorPalettes = (errorBaseColor: string) => ErrorPalettes;
export type GenerateInfoPalettes = (infoBaseColor: string) => InfoPalettes;
export type GenerateTextAlphaPalettes = (textBaseColor: string) => TextAlphaPalettes;
export type GenerateBgPalettes = (bgBaseColor: string) => BgPalettes;

View File

@ -1,5 +1,4 @@
import { generate } from '@ant-design/colors';
import { TinyColor } from '@ctrl/tinycolor';
import type { ColorPalettes, MapToken, PresetColorType, SeedToken } from '../../interface';
import { defaultPresetColors } from '../seed';
import genColorMapToken from '../shared/genColorMapToken';
@ -15,8 +14,6 @@ import {
} from './palettes';
export default function derivative(token: SeedToken): MapToken {
const { colorSuccess, colorWarning, colorError, colorInfo } = token;
const colorPalettes = Object.keys(defaultPresetColors)
.map((colorKey: keyof PresetColorType) => {
const colors = generate(token[colorKey], { theme: 'dark' });
@ -34,36 +31,25 @@ export default function derivative(token: SeedToken): MapToken {
return prev;
}, {} as ColorPalettes);
const colorPrimary = token.colorPrimary || '#177ddc';
const colorBgBase = token.colorBgBase || '#000';
const colorTextBase = token.colorTextBase || '#fff';
const primaryColors = generatePrimaryPalettes(colorPrimary);
const successColors = generateSuccessPalettes(colorSuccess);
const warningColors = generateWarningPalettes(colorWarning);
const errorColors = generateErrorPalettes(colorError);
const infoColors = generateInfoPalettes(colorInfo);
const bgColors = generateBgPalettes(colorBgBase);
const textColors = generateTextAlphaPalettes(colorTextBase);
return {
...token,
...colorPalettes,
colorPrimary,
// Colors
...genColorMapToken({
primaryPalettes: primaryColors,
successPalettes: successColors,
warningPalettes: warningColors,
errorPalettes: errorColors,
infoPalettes: infoColors,
bgPalettes: bgColors,
textAlphaPalettes: textColors,
}),
colorPrimaryOutline: new TinyColor(colorPrimary).setAlpha(0.2).toRgbString(),
colorErrorOutline: new TinyColor(colorError).setAlpha(0.2).toRgbString(),
colorWarningOutline: new TinyColor(colorWarning).setAlpha(0.2).toRgbString(),
...genColorMapToken(
{ ...token, colorBgBase, colorTextBase },
{
generatePrimaryPalettes,
generateErrorPalettes,
generateInfoPalettes,
generateSuccessPalettes,
generateWarningPalettes,
generateBgPalettes,
generateTextAlphaPalettes,
},
),
...genCommonMapToken(token),
};

View File

@ -1,5 +1,4 @@
import { generate } from '@ant-design/colors';
import { TinyColor } from '@ctrl/tinycolor';
import type { ColorPalettes, MapToken, PresetColorType, SeedToken } from '../../interface';
import { defaultPresetColors } from '../seed';
import genColorMapToken from '../shared/genColorMapToken';
@ -15,8 +14,6 @@ import {
} from './palettes';
export default function derivative(token: SeedToken): MapToken {
const { colorSuccess, colorWarning, colorError, colorInfo } = token;
const colorPalettes = Object.keys(defaultPresetColors)
.map((colorKey: keyof PresetColorType) => {
const colors = generate(token[colorKey]);
@ -34,35 +31,25 @@ export default function derivative(token: SeedToken): MapToken {
return prev;
}, {} as ColorPalettes);
const colorPrimary = token.colorPrimary || '#1890ff';
const colorBgBase = token.colorBgBase || '#fff';
const colorTextBase = token.colorTextBase || '#000';
const primaryColors = generatePrimaryPalettes(colorPrimary);
const successColors = generateSuccessPalettes(colorSuccess);
const warningColors = generateWarningPalettes(colorWarning);
const errorColors = generateErrorPalettes(colorError);
const infoColors = generateInfoPalettes(colorInfo);
const bgColors = generateBgPalettes(colorBgBase);
const textColors = generateTextAlphaPalettes(colorTextBase);
return {
...token,
...colorPalettes,
colorPrimary,
// Colors
...genColorMapToken({
primaryPalettes: primaryColors,
successPalettes: successColors,
warningPalettes: warningColors,
errorPalettes: errorColors,
infoPalettes: infoColors,
bgPalettes: bgColors,
textAlphaPalettes: textColors,
}),
colorPrimaryOutline: new TinyColor(colorPrimary).setAlpha(0.2).toRgbString(),
colorErrorOutline: new TinyColor(colorError).setAlpha(0.2).toRgbString(),
colorWarningOutline: new TinyColor(colorWarning).setAlpha(0.2).toRgbString(),
...genColorMapToken(
{ ...token, colorBgBase, colorTextBase },
{
generatePrimaryPalettes,
generateErrorPalettes,
generateInfoPalettes,
generateSuccessPalettes,
generateWarningPalettes,
generateBgPalettes,
generateTextAlphaPalettes,
},
),
...genCommonMapToken(token),
};

View File

@ -1,16 +1,16 @@
import { generate } from '@ant-design/colors';
import type {
BgPalettes,
ErrorPalettes,
InfoPalettes,
PrimaryPalettes,
SuccessPalettes,
TextAlphaPalettes,
WarningPalettes,
GenerateBgPalettes,
GenerateErrorPalettes,
GenerateInfoPalettes,
GeneratePrimaryPalettes,
GenerateSuccessPalettes,
GenerateTextAlphaPalettes,
GenerateWarningPalettes,
} from '../IPalettes';
import { getAlphaColor, getSolidColor } from './colorAlgorithm';
export function generatePrimaryPalettes(primaryBaseColor: string): PrimaryPalettes {
export const generatePrimaryPalettes: GeneratePrimaryPalettes = (primaryBaseColor: string) => {
const primaryColors = generate(primaryBaseColor);
return {
0: primaryBaseColor,
@ -22,18 +22,18 @@ export function generatePrimaryPalettes(primaryBaseColor: string): PrimaryPalett
6: primaryColors[5],
7: primaryColors[6],
};
}
};
export function generateSuccessPalettes(successBaseColor: string): SuccessPalettes {
export const generateSuccessPalettes: GenerateSuccessPalettes = (successBaseColor: string) => {
const successColors = generate(successBaseColor);
return {
1: successColors[0],
3: successColors[2],
6: successColors[5],
};
}
};
export function generateErrorPalettes(errorBaseColor: string): ErrorPalettes {
export const generateErrorPalettes: GenerateErrorPalettes = (errorBaseColor: string) => {
const errorColors = generate(errorBaseColor);
return {
1: errorColors[0],
@ -42,9 +42,9 @@ export function generateErrorPalettes(errorBaseColor: string): ErrorPalettes {
6: errorColors[5],
7: errorColors[6],
};
}
};
export function generateWarningPalettes(warningBaseColor: string): WarningPalettes {
export const generateWarningPalettes: GenerateWarningPalettes = (warningBaseColor: string) => {
const warningColors = generate(warningBaseColor);
return {
1: warningColors[0],
@ -53,44 +53,40 @@ export function generateWarningPalettes(warningBaseColor: string): WarningPalett
6: warningColors[5],
7: warningColors[6],
};
}
};
export function generateInfoPalettes(infoBaseColor: string): InfoPalettes {
export const generateInfoPalettes: GenerateInfoPalettes = (infoBaseColor: string) => {
const infoColors = generate(infoBaseColor);
return {
1: infoColors[0],
3: infoColors[2],
6: infoColors[5],
};
}
};
export function generateBgPalettes(bgBaseColor: string): BgPalettes {
return {
26: getSolidColor(bgBaseColor, 15),
'light-2': getSolidColor(bgBaseColor, 2),
'light-10': getSolidColor(bgBaseColor, 10),
'light-12': getSolidColor(bgBaseColor, 12),
19: getSolidColor(bgBaseColor, 6),
15: getSolidColor(bgBaseColor, 4),
12: getSolidColor(bgBaseColor, 0),
8: getSolidColor(bgBaseColor, 0),
0: getSolidColor(bgBaseColor, 4),
base: getSolidColor(bgBaseColor, 0),
};
}
export const generateBgPalettes: GenerateBgPalettes = (bgBaseColor: string) => ({
26: getSolidColor(bgBaseColor, 15),
'light-2': getSolidColor(bgBaseColor, 2),
'light-10': getSolidColor(bgBaseColor, 10),
'light-12': getSolidColor(bgBaseColor, 12),
19: getSolidColor(bgBaseColor, 6),
15: getSolidColor(bgBaseColor, 4),
12: getSolidColor(bgBaseColor, 0),
8: getSolidColor(bgBaseColor, 0),
0: getSolidColor(bgBaseColor, 4),
base: getSolidColor(bgBaseColor, 0),
});
export function generateTextAlphaPalettes(textBaseColor: string): TextAlphaPalettes {
return {
85: getAlphaColor(textBaseColor, 0.85),
'light-75': getAlphaColor(textBaseColor, 0.75), // 目前只有 Popover 用了
65: getAlphaColor(textBaseColor, 0.65), // 目前只有 Segment Label 用了
45: getAlphaColor(textBaseColor, 0.45),
30: getAlphaColor(textBaseColor, 0.25),
25: getAlphaColor(textBaseColor, 0.25),
// 从 12 往下基本上就是偏背景和装饰性元素了
12: getAlphaColor(textBaseColor, 0.06), // 主要是 Split
8: getAlphaColor(textBaseColor, 0.04),
4: getAlphaColor(textBaseColor, 0.03),
3: getAlphaColor(textBaseColor, 0.02),
};
}
export const generateTextAlphaPalettes: GenerateTextAlphaPalettes = (textBaseColor: string) => ({
85: getAlphaColor(textBaseColor, 0.85),
'light-75': getAlphaColor(textBaseColor, 0.75), // 目前只有 Popover 用了
65: getAlphaColor(textBaseColor, 0.65), // 目前只有 Segment Label 用了
45: getAlphaColor(textBaseColor, 0.45),
30: getAlphaColor(textBaseColor, 0.25),
25: getAlphaColor(textBaseColor, 0.25),
// 从 12 往下基本上就是偏背景和装饰性元素了
12: getAlphaColor(textBaseColor, 0.06), // 主要是 Split
8: getAlphaColor(textBaseColor, 0.04),
4: getAlphaColor(textBaseColor, 0.03),
3: getAlphaColor(textBaseColor, 0.02),
});

View File

@ -21,7 +21,7 @@ const seedToken: SeedToken = {
...defaultPresetColors,
// Color
colorPrimary: '',
brandColor: '#1890ff',
colorSuccess: '#52c41a',
colorWarning: '#faad14',
colorError: '#ff4d4f',

View File

@ -1,96 +1,132 @@
import type { ColorMapToken } from '../../interface';
import { TinyColor } from '@ctrl/tinycolor';
import type { ColorMapToken, SeedToken } from '../../interface';
import type {
BgPalettes,
ErrorPalettes,
InfoPalettes,
PrimaryPalettes,
SuccessPalettes,
TextAlphaPalettes,
WarningPalettes,
GenerateBgPalettes,
GenerateErrorPalettes,
GenerateInfoPalettes,
GeneratePrimaryPalettes,
GenerateSuccessPalettes,
GenerateTextAlphaPalettes,
GenerateWarningPalettes,
} from '../IPalettes';
interface PaletteSheets {
primaryPalettes: PrimaryPalettes;
successPalettes: SuccessPalettes;
errorPalettes: ErrorPalettes;
warningPalettes: WarningPalettes;
infoPalettes: InfoPalettes;
textAlphaPalettes: TextAlphaPalettes;
bgPalettes: BgPalettes;
interface PaletteGenerators {
generatePrimaryPalettes: GeneratePrimaryPalettes;
generateSuccessPalettes: GenerateSuccessPalettes;
generateErrorPalettes: GenerateErrorPalettes;
generateWarningPalettes: GenerateWarningPalettes;
generateInfoPalettes: GenerateInfoPalettes;
generateTextAlphaPalettes: GenerateTextAlphaPalettes;
generateBgPalettes: GenerateBgPalettes;
}
export default function genColorMapToken({
primaryPalettes,
successPalettes,
errorPalettes,
warningPalettes,
infoPalettes,
textAlphaPalettes,
bgPalettes,
}: PaletteSheets): ColorMapToken {
export default function genColorMapToken(
seed: SeedToken,
{
generatePrimaryPalettes,
generateSuccessPalettes,
generateErrorPalettes,
generateWarningPalettes,
generateInfoPalettes,
generateTextAlphaPalettes,
generateBgPalettes,
}: PaletteGenerators,
): ColorMapToken {
const {
colorSuccess: colorSuccessBase,
colorWarning: colorWarningBase,
colorError: colorErrorBase,
colorInfo: colorInfoBase,
brandColor,
colorBgBase,
colorTextBase,
} = seed;
const primaryColors = generatePrimaryPalettes(brandColor);
const successColors = generateSuccessPalettes(colorSuccessBase);
const warningColors = generateWarningPalettes(colorWarningBase);
const errorColors = generateErrorPalettes(colorErrorBase);
const infoColors = generateInfoPalettes(colorInfoBase);
const bgColors = generateBgPalettes(colorBgBase);
const textColors = generateTextAlphaPalettes(colorTextBase);
const colorPrimary = primaryColors['6'];
const colorError = errorColors['5'];
const colorWarning = warningColors['6'];
const colorSuccess = successColors['6'];
const colorInfo = infoColors['6'];
return {
colorPrimaryHover: primaryPalettes['5'],
colorPrimaryBg: primaryPalettes['1'],
colorPrimaryBgHover: primaryPalettes['0'],
colorPrimaryActive: primaryPalettes['7'],
colorPrimaryBorder: primaryPalettes['3'],
colorPrimaryBorderHover: primaryPalettes['4'],
colorPrimary,
colorPrimaryHover: primaryColors['5'],
colorPrimaryBg: primaryColors['1'],
colorPrimaryBgHover: primaryColors['0'],
colorPrimaryActive: primaryColors['7'],
colorPrimaryBorder: primaryColors['3'],
colorPrimaryBorderHover: primaryColors['4'],
colorPrimaryOutline: new TinyColor(colorPrimary).setAlpha(0.2).toRgbString(),
colorSuccessBg: successPalettes['1'],
colorSuccessBorder: successPalettes['3'],
colorSuccess,
colorSuccessBg: successColors['1'],
colorSuccessBorder: successColors['3'],
colorErrorBg: errorPalettes['1'],
colorErrorBorder: errorPalettes['3'],
colorErrorHover: errorPalettes['5'],
colorErrorActive: errorPalettes['7'],
colorError,
colorErrorBg: errorColors['1'],
colorErrorBorder: errorColors['3'],
colorErrorHover: errorColors['5'],
colorErrorActive: errorColors['7'],
colorErrorOutline: new TinyColor(colorError).setAlpha(0.2).toRgbString(),
colorWarningBg: warningPalettes['1'],
colorWarningBorder: warningPalettes['3'],
colorWarningHover: warningPalettes['5'],
colorWarningActive: warningPalettes['7'],
colorWarning,
colorWarningBg: warningColors['1'],
colorWarningBorder: warningColors['3'],
colorWarningHover: warningColors['5'],
colorWarningActive: warningColors['7'],
colorWarningOutline: new TinyColor(colorWarning).setAlpha(0.2).toRgbString(),
colorInfoBg: infoPalettes['1'],
colorInfoBorder: infoPalettes['3'],
colorInfo,
colorInfoBg: infoColors['1'],
colorInfoBorder: infoColors['3'],
colorLink: primaryPalettes['6'],
colorLinkHover: primaryPalettes['5'],
colorLinkActive: primaryPalettes['7'],
colorLink: primaryColors['6'],
colorLinkHover: primaryColors['5'],
colorLinkActive: primaryColors['7'],
// ============== Background ============== //
colorBgLayout: bgPalettes['0'],
colorBgElevated: bgPalettes['12'],
colorBgContainer: bgPalettes['8'],
colorBgContent: bgPalettes['15'],
colorBgLayout: bgColors['0'],
colorBgElevated: bgColors['12'],
colorBgContainer: bgColors['8'],
colorBgContent: bgColors['15'],
colorBgContentHover: bgPalettes['26'],
colorBgContainerSecondary: textAlphaPalettes['4'],
colorBgContainerDisabled: textAlphaPalettes['8'],
colorBgContentHover: bgColors['26'],
colorBgContainerSecondary: textColors['4'],
colorBgContainerDisabled: textColors['8'],
colorBgMask: textAlphaPalettes['45'],
colorBgItemHover: textAlphaPalettes['8'],
colorBgFillTmp: textAlphaPalettes['12'],
colorBgTooltipTmp: textAlphaPalettes['85'],
colorBgMask: textColors['45'],
colorBgItemHover: textColors['8'],
colorBgFillTmp: textColors['12'],
colorBgTooltipTmp: textColors['85'],
// ============== Split ============== //
colorBorder: bgPalettes['26'],
colorBorderSecondary: bgPalettes['19'],
colorBorderBg: bgPalettes.base,
colorSplit: textAlphaPalettes['12'],
colorBorder: bgColors['26'],
colorBorderSecondary: bgColors['19'],
colorBorderBg: bgColors.base,
colorSplit: textColors['12'],
// ============== Text ============== //
colorText: textAlphaPalettes['85'],
colorTextHeading: textAlphaPalettes['85'],
colorTextSecondary: textAlphaPalettes['45'],
colorTextDisabled: textAlphaPalettes['25'],
colorTextLabel: textAlphaPalettes['65'],
colorText: textColors['85'],
colorTextHeading: textColors['85'],
colorTextSecondary: textColors['45'],
colorTextDisabled: textColors['25'],
colorTextLabel: textColors['65'],
colorAction: textAlphaPalettes['45'],
colorActionHover: textAlphaPalettes['85'],
colorAction: textColors['45'],
colorActionHover: textColors['85'],
buttonColorBgTextHover: textAlphaPalettes['3'],
buttonColorBgTextActive: textAlphaPalettes['4'],
segmentedBgColor: textAlphaPalettes['8'],
segmentedBgColorHover: textAlphaPalettes['12'],
segmentedBgColorActive: bgPalettes['8'],
buttonColorBgTextHover: textColors['3'],
buttonColorBgTextActive: textColors['4'],
segmentedBgColor: textColors['8'],
segmentedBgColorHover: textColors['12'],
segmentedBgColorActive: bgColors['8'],
};
}

View File

@ -118,7 +118,7 @@ export default function DynamicTheme({
node = <Input />;
}
const rules: any[] = [{ required: true }];
const rules: any[] = [{ required: key !== 'colorTextBase' && key !== 'colorBgBase' }];
const originColor = new TinyColor(originValue);
if (originValueType === 'string' && originColor.isValid) {
rules.push({