Script that generates ant design theme overwtires based on the configuration object.
import { writeFileSync } from 'fs';
import { resolve } from 'path';
import { theme } from './theme';
const lessVariablesOverwrite = `${`
module.exports = {
'@primary-color': '${theme.colors.primary.main}',
'@info-color': '${theme.colors.info.main}',
'@success-color': '${theme.colors.success.main}',
'@error-color': '${theme.colors.error.main}',
'@warning-color': '${theme.colors.warning.main}',
'@white': '${theme.colors.common.white}',
'@black': '${theme.colors.common.black}',
'@shadow-color': '${theme.colors.shadow}',
'@primary-1': '${theme.colors.primary.background}',
'@primary-3': '${theme.colors.primary.border}',
'@primary-5': '${theme.colors.primary.light}',
'@primary-6': '${theme.colors.primary.main}',
'@primary-7': '${theme.colors.primary.dark}',
'@heading-color': '${theme.colors.text.heading}',
'@text-color': '${theme.colors.text.primary}',
'@text-color-secondary': '${theme.colors.text.secondary}',
'@disabled-color': '${theme.colors.text.disabled}',
'@border-color-base': '${theme.colors.border.base}',
'@border-color-split': '${theme.colors.border.split}',
'@background-color-light': '${theme.colors.background.light}',
'@background-color-base': '${theme.colors.background.base}',
'@alert-success-border-color': '${theme.colors.success.border}',
'@alert-success-bg-color': '${theme.colors.success.background}',
'@alert-info-border-color': '${theme.colors.info.border}',
'@alert-info-bg-color': '${theme.colors.info.background}',
'@alert-warning-border-color': '${theme.colors.warning.border}',
'@alert-warning-bg-color': '${theme.colors.warning.background}',
'@alert-error-border-color': '${theme.colors.error.border}',
'@alert-error-bg-color': '${theme.colors.error.background}',
'@font-family':
'${theme.fonts.fontFamily}',
'@code-family': '${theme.fonts.codeFamily}',
'@heading-1-size': '${theme.fontSizes.h1}',
'@heading-2-size': '${theme.fontSizes.h2}',
'@heading-3-size': '${theme.fontSizes.h3}',
'@heading-4-size': '${theme.fontSizes.h4}',
'@font-size-lg': '${theme.fontSizes.large}',
'@font-size-base': '${theme.fontSizes.normal}',
'@font-size-sm': '${theme.fontSizes.small}',
'@card-shadow': '${theme.shadows.card}',
'@box-shadow-base': '${theme.shadows.base}',
'@shadow-1-up': '${theme.shadows.up}',
'@shadow-1-down': '${theme.shadows.down}',
'@shadow-1-left': '${theme.shadows.left}',
'@shadow-1-right': '${theme.shadows.right}',
'@shadow-2': '${theme.shadows.large}',
};
`.trim()}\n`;
writeFileSync(resolve(__dirname, '..', 'src', 'generated', 'customizeTheme.js'), lessVariablesOverwrite, 'utf8');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const generate = (obj: any, path = ''): any =>
Object.keys(obj).map(key => {
if (typeof obj[key] === 'object') return generate(obj[key], `${key}.`);
return path + key;
});
const colorKeys = []
.concat(...generate(theme.colors))
.map(key => `'${key}'`)
.join('\n | ');
writeFileSync(
resolve(__dirname, '..', 'src', 'generated', 'ColorKeys.ts'),
`export type ColorKeys =\n | ${colorKeys};\n`,
'utf8',
);
const colors = {
primary: {
dark: '#096DD9',
main: '#1890FF',
light: '#40A9FF',
border: '#91D5FF',
background: '#E6F7FF',
},
text: {
heading: 'rgba(0, 0, 0, 0.85)',
primary: 'rgba(0, 0, 0, 0.65)',
secondary: 'rgba(0, 0, 0, 0.45)',
disabled: 'rgba(0, 0, 0, 0.25)',
},
border: {
base: '#D9D9D9',
split: '#E8E8E8',
},
background: {
base: '#F5F5F5',
light: '#FAFAFA',
body: '#F0F2F5',
component: '#FFFFFF',
},
error: {
dark: '#CF1322',
main: '#F5222D',
light: '#FF4D4F',
border: '#FFA39E',
background: '#FFF1F0',
},
warning: {
main: '#FAAD14',
border: '#FFE58F',
background: '#FFFBE6',
},
info: {
main: '#13C2C2',
border: '#87E8DE',
background: '#E6FFFB',
},
success: {
main: '#52C41A',
border: '#B7EB8F',
background: '#F6FFED',
},
common: {
black: '#000000',
white: '#FFFFFF',
},
shadow: 'rgba(0, 0, 0, 0.15)',
};
const shadows = {
button: '0 2px 0 rgba(0, 0, 0, 0.015)',
card: '0 2px 8px rgba(0, 0, 0, 0.09)',
base: `0 -2px 8px ${colors.shadow}`,
up: `0 -2px 8px ${colors.shadow}`,
down: `0 2px 8px ${colors.shadow}`,
left: `-2px 0 8px ${colors.shadow}`,
right: `2px 0 8px ${colors.shadow}`,
large: `0 4px 12px ${colors.shadow}`,
};
const fonts = {
fontFamily:
'-apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"',
codeFamily: '"SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace',
};
const fontSizes = {
h1: '38px',
h2: '30px',
h3: '24px',
h4: '20px',
large: '16px',
normal: '14px',
small: '12px',
};
const lineHeights = {
h1: '48px',
h2: '40px',
h3: '32px',
h4: '28px',
large: '24px',
normal: '20px',
small: '12px',
};
export const breakpoints = {
xs: '480px',
sm: '576px',
md: '768px',
lg: '992px',
xl: '1200px',
xxl: '1600px',
};
export const space = {};
export const theme = {
space,
colors,
fonts,
fontSizes,
lineHeights,
shadows,
breakpoints,
};
import React from 'react';
import { ThemeProvider as EmotionThemeProvider } from 'emotion-theming';
import { theme } from './theme';
export const ThemeProvider: React.FC = ({ children }) => {
return <EmotionThemeProvider theme={theme}>{children}</EmotionThemeProvider>;
};
import { useTheme as useEmotionTheme } from 'emotion-theming';
import { theme } from './theme';
export const useTheme = (): typeof theme => useEmotionTheme<typeof theme>();
const CracoAntDesignPlugin = require('craco-antd');
const customizeTheme = require('./src/generated/customizeTheme');
module.exports = {
plugins: [
{ plugin: CracoAntDesignPlugin, options: { customizeTheme } },
],
babel: {
plugins: ['emotion'],
},
};