CSS 变量 能轻松实现主题。使用 Gem 提供的主题模块将有更多当优势:
- TypeScript 集成
- 防止多个主题 CSS 自定义属性名冲突
- 可观察的
ThemeStore 对象
import { createTheme } from '@mantou/gem/helper/theme';
const theme = createTheme({
primaryColor: '#eee',
});
const styles = css`
div {
border: 2px solid ${theme.primaryColor};
}
`;
@customElement('app-root')
@adoptedStyle(styles)
class App extends GemElement {}从上面的用法可以看出,一旦一个对象被创建成主题,从主题中读取的字段即为 CSS 变量:
console.log(theme.primaryColor);
// => var(--primary-color-xxxxx)有时候可能需要读取原始对象,比如将主题打印到元素中:
import { createTheme, getThemeStore } from '@mantou/gem/helper/theme';
const theme = createTheme({
primaryColor: '#eee',
});
const themeStore = getThemeStore(theme);
const styles = css`
div {
border: 2px solid ${theme.primaryColor};
}
`;
@customElement('app-root')
@adoptedStyle(styles)
@connectStore(themeStore)
class App extends GemElement {
render = () => {
return html`
<div>primaryColor: ${themeStore.primaryColor}</div>
`;
}
}如果想要支持暗模式,你可以利用 matchMedia 进行媒体查询,然后使用不同的主题,例如:
import { createTheme } from '@mantou/gem/helper/theme';
const lightTheme = {
primaryColor: '#333',
};
const darkTheme = {
primaryColor: '#eee',
};
const theme = createTheme(matchMedia('(prefers-color-scheme: dark)').matches ? darkTheme : lightTheme);
const styles = css`
div {
border: 2px solid ${theme.primaryColor};
}
`;
@customElement('app-root')
@adoptedStyle(styles)
class App extends GemElement {}v1 只支持全局主题,v2 支持范围主题,并且支持主题覆盖:
// 全局主题将自动添加到 `document`
const theme = createTheme({ textColor: '#eee' });
const scopedTheme = createScopedTheme({ scopeTextColor: '#333' });
const overrideTheme = createOverrideTheme(theme, { textColor: '#eff' })
const styles = css`
:scope {
color: ${theme.textColor};
background: ${scopedTheme.scopeTextColor};
}
`;
@customElement('my-element')
@adoptedStyle(styles)
@adoptedStyle(scopedTheme)
@adoptedStyle(overrideTheme)
class MyElement extends GemElement {}此外,得益于相对颜色语法,主题中以 Color 结尾的颜色直接支持使用“重量”(类似字重)调节亮度:theme.textColor500,这是一个比原 textColor 稍亮的颜色。
主题是使用 CSS 变量实现的,在渲染时可能需要动态设置 CSS 变量,这同样可以通过主题来完成,和其他类型的主题不一样,需要使用装饰器来应用和更新主题:
import { createDecoratorTheme } from '@mantou/gem/helper/theme';
const elementTheme = createDecoratorTheme({ color: '' });
const style = css`
:host(:where(:not([hidden]))) {
border-color: ${elementTheme.color};
}
`;
@customElement('app-root')
class App extends GemElement {
@attribute color;
@elementTheme()
#theme = () => ({ color: this.color })
render = () => {
return html``;
}
}