material-ui
material-ui copied to clipboard
[RFC] CSS variables naming for components
Motivation
With the support in most modern browsers, CSS variables are an important key to improving the customization and styling experience (compare the at Grid v2 and Grid v1 to see the differences).
With the growing list of components, we need a guide/pattern to define those variables for consistency across MUI products.
Questions
1. Does the variable need a prefix?
The current variables in Joy UI and Material UI do not have prefixes.
- https://mui.com/material-ui/react-grid2/
--Grid-columns: ...;
- https://mui.com/joy-ui/react-button/
--Button-gap: ...;
At this point, I don't see a need for the prefix.
2. The structure of the variable?
I think the PascalCase should be used as a starting point to differentiate from the CSS theme variables.
Option 1 (current):
A pascal case starts with the parent component name, then the slot name (or a child component of the same category) and the last part is the modifier (quite similar to BEM).
// defined on the List component
--List-radius: ...;
--List-item-radius: ...; // used by ListItem
--List-decorator-size: ...; // used by ListItemDecorator
Option 2:
Starts with the full component name (a pascal case) and uses the specific component name.
// defined on the List component
--List-radius: ...;
--ListItem-radius: ...; // used by ListItem
--ListItemDecorator-size: ...; // used by ListItemDecorator
3. What should be the prefix for private variables?
use cases for private variables:
- Some component contains some private variables that take care of some calculation and are then used by the public variables.
- Act as an intermediate variables for setting default value and lets parent components override the value.
Options:
-
Option 1:
--private-...
https://github.com/mui/mui-x/issues/5463 -
Option 2:
--unstable-...
-
Option 3:
--internal-...
Feel free to comment or suggest more options.
@siriwatknp can you add some benchmark of how the CSS variables look like in other frameworks?
From a first glance
Option 2: "Starts with the full component name (a pascal case) and uses the specific component name."
sounds great.
- What should be the prefix for private variables?
Can you elaborate on the need of private CSS variables?
Can you elaborate on the need of private CSS variables?
For example, the Tooltip contains --unstable_Tooltip-arrow-rotation
to calculate the inset value for different placements.
// the Tooltip arrow styles
'--unstable_Tooltip-arrow-rotation': 0,
width: 'var(--Tooltip-arrow-size)',
height: 'var(--Tooltip-arrow-size)',
boxSizing: 'border-box',
// use psuedo element because Popper controls the `transform` property of the arrow.
'&:before': {
...
transformOrigin: 'center center',
transform: 'rotate(calc(-45deg + 90deg * var(--unstable_Tooltip-arrow-rotation)))',
},
'[data-popper-placement*="bottom"] &': {
top: 'calc(0.5px + var(--Tooltip-arrow-size) * -1 / 2)', // 0.5px is for perfect overlap with the Tooltip
},
'[data-popper-placement*="top"] &': {
'--unstable_Tooltip-arrow-rotation': 2,
bottom: 'calc(0.5px + var(--Tooltip-arrow-size) * -1 / 2)',
},
'[data-popper-placement*="left"] &': {
'--unstable_Tooltip-arrow-rotation': 1,
right: 'calc(0.5px + var(--Tooltip-arrow-size) * -1 / 2)',
},
'[data-popper-placement*="right"] &': {
'--unstable_Tooltip-arrow-rotation': 3,
left: 'calc(0.5px + var(--Tooltip-arrow-size) * -1 / 2)',
},
I can take this up and then I'll raise a PR and let you guys know. Is that okay or do you have any other suggestions or feedback? @siriwatknp @mnajdova
I can take this up and then I'll raise a PR and let you guys know. Is that okay or do you have any other suggestions or feedback? @siriwatknp @mnajdova
Thanks for your interest! let's wait for a few weeks until we are all agreed on the format. I will tag you when it is ready to submit a PR!
Jun and I agreed on using <ComponentName>-<slot><Property>
(e.g., Slider-trackRadius
) for CSS variable naming when it includes slots. Otherwise, it will be <ComponentName>-<property>
(e.g., ListItem-radius
)
I am taking this task.
As a note on why using <ComponentName>-<slot><Property>
instead of <ComponentName>-<slot>-<property>
:
The variables are mostly hoisted at the root slot, so I don't see why we need to separate the slot with -
.
const Root = styled('div')({
'--ComponentName-radius': '...',
'--ComponentName-trackRadius': '...',
})
const Track = styled('div')({
borderRadius: 'var(--ComponentName-trackRadius'),
})
@hbjORbj @siriwatknp may I take this up if we have come to a decision on the naming convention. Thanks