跳至主要内容

主题化组件

React Strict DOM 提供了一个灵活的主题化 API,可以轻松地使用 CSS 变量将主题化的值应用于整个组件树。

要求

变量必须定义在与以下文件扩展名模式匹配的文件中:.stylex.{js,jsx,mjs,ts,tsx}。 只有 CSS 变量才能在这些文件中定义。 并且每个 css.defineVars 调用都必须是一个命名导出。

定义变量

CSS 变量通过调用 css.defineVars 来定义。 这定义了全局变量,然后可以将其作为常量导入,以用于任何样式规则中。 这些变量及其值本质上是“默认主题”。

tokens.stylex.js
import { css } from 'react-strict-dom';

export const tokens = css.defineVars({
primaryText: 'black',
secondaryText: '#333',
accent: 'blue',
background: 'white',
lineColor: 'gray'
});

任何主题都可以定义“黑暗模式”的替代方案 – 当操作系统主题匹配时会自动应用 – 通过为 prefers-color-scheme 媒体查询指定不同的值

tokens.stylex.js
import { css } from 'react-strict-dom';

const darkMode = '@media (prefers-color-scheme: dark)';

export const colors = css.defineVars({
primaryText: {
default: 'black',
[darkMode]: 'white'
},
secondaryText: {
default: '#333',
[darkMode]: '#ccc'
},
accent: {
default: 'blue',
[darkMode]: 'lightblue'
},
background: {
default: 'white',
[darkMode]: 'black'
},
lineColor: {
default: 'gray',
[darkMode]: 'lightgray'
}
});

在样式中使用变量

一旦定义了变量,就可以将其导入并直接用于使用 css.create 创建的样式规则中。

Component.js
import { css } from 'react-strict-dom';
import { colors } from './tokens.stylex';

const styles = css.create({
container: {
color: colors.primaryText,
backgroundColor: colors.background,
}
});

使用变量创建主题

如果应用程序支持多个主题,则可以通过使用 css.createTheme 为默认主题定义的全局变量定义新值来创建这些主题。 可以导入变量的命名组,并将其传递给 css.createTheme,并指定新值。

可以使用 css.createTheme 在代码库中的任何位置创建主题,并在文件或组件之间传递。

theme.js
import { css } from 'react-strict-dom';
import { colors, spacing } from './tokens.stylex';

const darkMode = '@media (prefers-color-scheme: dark)';

const themeColors = css.createTheme(colors, {
primaryText: {default: 'purple', [darkMode]: 'lightpurple'},
secondaryText: {default: 'pink', [darkMode]: 'hotpink'},
accent: 'red',
background: {default: '#555', [darkMode]: 'black'},
lineColor: 'red',
});

const themeSpacing = css.createTheme(spacing, {
...
});

export const theme = [ themeColors, themeSpacing ];

使用主题

css.createTheme 的返回值是一个样式对象,类似于使用 css.create 创建的对象。 这些主题对象可以使用 style 属性应用于任何元素。 然后,变量的主题化值将应用于子树中所有使用全局变量的元素。

Component.js
import { css, html } from 'react-strict-dom';
import { colors, spacing } from './tokens.stylex';
import { theme } from './theme';

const styles = css.create({
container: {
color: colors.primaryText,
backgroundColor: colors.background,
padding: spacing.medium,
},
});

const Foo = () => (
<html.div style={[ theme, styles.container ]} />
);

这是一种灵活的模式,允许您使用变量来样式化组件,然后通过将主题应用于任何子树根目录中的一个元素来重新主题化整个树。 例如,如果您有多个主题,您可以创建一个 Theme 组件,使产品工程师可以轻松地按名称选择主题。

Theme.js
import { css, html } from 'react-strict-dom';
import { marsTheme } from './marsTheme';
import { venusTheme } from './venusTheme';

const styles = css.create({
displayContents: {
display: 'contents'
}
});

const Theme = (props) => {
const theme = props.name === 'venus' ? venusTheme : marsTheme;
return (
<html.div
children={props.children}
style={[ theme, styles.displayContents ]}
/>
);
}

只需将组件包装在 Theme 组件中,即可确保指定的主题覆盖所有后代元素的变量值。

App.js
import { ProfilePage } from './ProfilePage';
import { Theme } from './Theme';

const App = () => (
<Theme name={app.activeTheme}>
<ProfilePage user={user} />
</Theme>
);