[RFC] Decouple variables passed to child components from parent component's logic #162
Description
from @levithomason post:
Motivation
Any variables or styles used directly in a component's logic implicitly become part of a global theming interface.
All themes will have to implement variables.typePrimaryColor
, for instance, in order for this to work. Additionally, we are removing the styling from the theme and baking it into the component instead.
We would like all theming values and theming logic living in the theme's files. This way, each theme is free to choose the values and logic behind their styles. The question is how?
Proposal 1 - Component part variables
Component variables files could define variables for each component parts as well. Then, variable values and logic for component parts can be left to the theme and not dictated to all themes by the component. Here's an example of the Button theme defining an icon
part in its variables.
// themes/teams/components/Button/buttonVariables.tsx
export default (siteVariables) => {
const variables = {
color: undefined,
typePrimaryColor: siteVariables.white,
typeSecondaryColor: siteVariables.black,
}
variables.icon = {
color:
type === "primary"
? variables.typePrimaryColor
: type === "secondary"
? variables.typeSecondaryColor
: variables.color
}
return variables
}
Now, the component simply implements a contract that says "we pass variables[part] to each component part":
// Button.tsx
Icon.create(icon, {
defaultProps: {
variables: variables.icon
}
})
This would also allow us to do this consistently for all components, including the styles for each component part. That then would allow us to write a conformance test for it. This would make the API easier to understand and work with as well since there is only one concept, "components pass variables/styles to each component part".
Proposal 2 - A high-level theme interface
This proposal would introduce a new concept. Something like a lightweight theme interface that is allowed to pass between components. It would consist of backgroundColor
, foregroundColor
, and perhaps an accentColor
initially (names and keys are inspired by present convergence talks with several teams at Microsoft).
The Button in this case would define these three values for its bounds. Then, they would passed to the Icon.