Intro
5 States
The project will adopt a new design model based on five state variables.
- enabled
- hovered
- pressed
- focused
- disabled
All component definitions will be based on these 5 state variables, and the component styles will use the CSS system to identify and generate variable-based code.
Override Styles
The "style overriding" phase has been moved to the definition stage.
Currently, the project uses a runtime-like injection approach, defining and injecting styles in the component's styles. Component styles are stored partly in the definition and partly in the style.
-
Lack of context awareness, high mental burden.
-
Manual hard coding and multiple changes. Changes to the definition and the overridden component's definition require simultaneous modifications to multiple files.
Examples
createStyleSheet
Used to automatically extra 5 states.
Input:
createStyleSheet(ButtonDefinition, () => css`
@anchor .container {
.label {
color: var(--_label-color);
@when(.togglable.selected) {
color: var(--_label-color-toggle-selected);
}
}
}
`)
Output:
.container .label {
color: var(--_enabled-label-color);
}
.container.togglable.selected .label {
color: var(--_enabled-label-color-toggle-selected);
}
.container:hover .label {
color: var(--_hovered-label-color);
}
.container.togglable.selected:hover .label {
color: var(--_hovered-label-color-toggle-selected);
}
.container:focus-within .label {
color: var(--_focused-label-color);
}
.container.togglable.selected:focus-within .label {
color: var(--_focused-label-color-toggle-selected);
}
.container:active .label {
color: var(--_pressed-label-color);
}
.container.togglable.selected:active .label {
color: var(--_pressed-label-color-toggle-selected);
}
.container.disabled .label {
color: var(--_disabled-label-color);
}
.container.disabled.togglable.selected .label {
color: var(--_disabled-label-color-toggle-selected);
}
forwardTokens
Used for style overriding.
const IconDefinition = createStyleDefinition({
'color': ['#000000', null, null, null, null],
'size': ['24px', null, null, null, null],
})
it('allows spreading forwardTokens directly inside createStyleDefinition and expands all 5-state tuples', () => {
const ButtonDefinition = createStyleDefinition({
'container-color': ['#primary', '#hover', '#press', '#focus', '#disabled'],
...forwardTokens(IconDefinition, {
targetPrefix: '--mdc-icon',
name: 'icon',
tokens: {
'color': ['#on-primary', '#on-hover', '#on-press', '#on-focus', '#on-disabled'],
'size': '18px',
},
}),
})
// Verify every single expanded property key and value in ButtonDefinition
expect(ButtonDefinition).toEqual({
'enabled-container-color': '#primary',
'hovered-container-color': '#hover',
'pressed-container-color': '#press',
'focused-container-color': '#focus',
'disabled-container-color': '#disabled',
'enabled-icon-color': '#on-primary',
'hovered-icon-color': '#on-hover',
'pressed-icon-color': '#on-press',
'focused-icon-color': '#on-focus',
'disabled-icon-color': '#on-disabled',
'icon-size': '18px',
})
})
Intro
5 States
The project will adopt a new design model based on five state variables.
All component definitions will be based on these 5 state variables, and the component styles will use the CSS system to identify and generate variable-based code.
Override Styles
The "style overriding" phase has been moved to the definition stage.
Currently, the project uses a runtime-like injection approach, defining and injecting styles in the component's styles. Component styles are stored partly in the definition and partly in the style.
Lack of context awareness, high mental burden.
Manual hard coding and multiple changes. Changes to the definition and the overridden component's definition require simultaneous modifications to multiple files.
Examples
createStyleSheet
Used to automatically extra 5 states.
Input:
Output:
forwardTokens
Used for style overriding.