我正在尝试为我的样式化组件实现一个可选的样式覆盖。
目前我拥有的是:
This is a function that will be merging my changed style to the default one from the theme.
const mergeComponentTheme = <T extends object>(mode: ThemeMode, defaultTheme: T, overridingTheme?: CustomComponentStyle<T>): T => {
return Object.keys(defaultTheme).reduce<T>((previousValue, currentValue) => {
const property = currentValue as keyof T;
const themeMode = mode as keyof typeof overridingTheme;
const value = (overridingTheme && overridingTheme[themeMode][property]) || defaultTheme[property];
return { ...previousValue, [currentValue]: value };
}, {} as T);
};
This is how I am using it right now.
const Button = styled.button<CustomStyled<ButtonTheme>>`
${({ theme, customStyle }) => {
const componentStyle = mergeComponentTheme<ButtonTheme>(theme.mode, theme.current.button, customStyle);
return css`
background-color: ${componentStyle.backgroundColor};
color: ${componentStyle.foregroundColor};
padding: ${componentStyle.padding};
margin: ${componentStyle.margin};
border-radius: ${componentStyle.borderRadius};
filter: drop-shadow(0 0 2px ${componentStyle.dropShadowColor});
transition: all 0.2s ease-in-out;
&:hover {
background-color: ${componentStyle.backgroundColorHover};
cursor: pointer;
}
`;
}}
`;
These are all the types used in the example.
type CustomStyled<T> = {
customStyle?: CustomComponentStyle<T>;
};
type CustomComponentStyle<T> = {
light?: Partial<T>;
dark?: Partial<T>;
};
enum ThemeMode {
LIGHT = 'light',
DARK = 'dark',
}
interface ButtonTheme extends GenericTheme {
borderRadius: Radius;
}
type GenericTheme = {
backgroundColor: Color;
foregroundColor: Color;
backgroundColorHover: Color;
foregroundColorHover: Color;
dropShadowColor: Color;
margin: Space;
padding: Space;
};
有没有更简洁的方法做这件事?我愿意听取建议。
问题的标题,差点忘了,所以我的主要问题是,如果我从常量themeMode
中移除这一部分,as keyof typeof overridingTheme;
,overridingTheme[themeMode]
说,即使在检查它之后,它也可能是未定义的。
1条答案
按热度按时间a64a0gku1#
试试看: