Ant Design offers a CSS-in-JS approach for styling your custom components. But how can developers use its Design System tokens in CSS or preprocessors (SASS, LESS)?
Letβs take a look at a small example with a set of panels with buttons in a row.
export const Test: React.FC = () => (
<div className="app">
{map(range(4), (index) => (
<div
key={index}
className='container'
>
<Button type='primary'>
Button {index}
</Button>
</div>
))}
</div>
);
Application component is wrapped with ConfigProvider component to set a custom theme.
const App: React.FC = () => (
<ConfigProvider theme={customTheme}>
<CssTokenBridge />
<Test />
</ConfigProvider>
);
CssTokenBridge is a component for passing token values to CSS variables:
import { theme } from 'antd';
import { forEach, includes, isNumber, isString, kebabCase } from 'lodash';
import React from 'react';
function saveToken(value, tokenName) {
const isPrivateField = tokenName.startsWith('_');
if (isPrivateField) return;
const variableName = `--antd-${kebabCase(tokenName)}`;
if (isString(value)) document.documentElement.style.setProperty(variableName, value);
if (isNumber(value)) {
const propertyValue = isPureNumberProperty(tokenName) ? value : `${value}px`;
document.documentElement.style.setProperty(variableName, propertyValue);
}
}
const isPureNumberProperty = (tokenName) =>
includes(tokenName, 'zIndex') ||
includes(tokenName, 'Weight') ||
includes(tokenName, 'motion') ||
includes(tokenName, 'opacity') ||
includes(tokenName, 'lineHeight');
export const CssTokenBridge = () => {
const { token } = theme.useToken();
React.useLayoutEffect(() => {
forEach(token, saveToken);
}, [ token ]);
return null;
};
I use kebab case names for CSS variable names and add an antd prefix. So, the colorPrimary token is saved to the β antd-color-primary CSS variable. There is a workaround for defining units of token value. Most of the numeric tokens use px units, but some of them should be just numbers (like zIndex, lineHeight). The isPureNumberProperty function should return true for such tokens.
Now, we can easily use Design System token values without hard-coded values in styles.
.app {
display: flex;
gap: var(--antd-padding-content-horizontal);
.container {
background-color: var(--antd-green-1);
border-radius: var(--antd-border-radius);
box-shadow: var(--antd-box-shadow);
padding: var(--antd-padding);
}
}
One of the advantages of this approach is that itβs easy to supervise design. Token name and its value is available in DevTools.
Hope the next versions of AntD will support css variables for dynamically changed custom themes out of the box.
Repository https://github.com/mvp-v/antd-css-vars
Top comments (0)