docs/react-v9/contributing/rfcs/react-components/convergence/static-classes-on-slots.md
Contributors: @behowell
History:
This RFC proposes adding a static className to every slot, using the naming format "fui-{ComponentName}__{slotName}".
It can be useful to have a static class name on every slot of a component, both for writing style selectors, and when debugging to tell what slot a given element is.
We currently have a static class name "fui-{ComponentName}" (e.g. "fui-Button") added to the root slot of every component, as described in issue #19937. However, we don't currently have any formal specification of the format of the classNames for other slots, nor any conformance tests ensuring that they are added to every slot.
Some of our components already have static classNames on slots (e.g. Checkbox's indicator slot). However, this patchwork addition of static classes makes it unpredictable for users of our library.
One example of internal usage would be to write a style such as this, which changes the Checkbox indicator slot's backgroundColor when hovering over the root:
const useStyles = makeStyles({
root: {
':hover': {
'& .fui-Checkbox__indicator': {
backgroundColor: tokens.colorCompoundBrandBackgroundHover,
},
},
},
});
The root slot already has a static className with the format fui-{ComponentName}, per #19937. This RFC proposes that every other slot of a component should have a static className added to the start before any other classNames, with the format fui-{ComponentName}__{slot}. This naming convention aligns other libraries' CSS naming conventions, including BEM.
For example, the HTML tree of Checkbox would look like:
<span className="fui-Checkbox ...other classes...">
<span className="fui-Checkbox__indicator ...other classes..."> ... </span>
<input className="fui-Checkbox__input ...other classes..." />
<label className="fui-Checkbox__label ...other classes..."> ... </label>
</span>
These classNames could be exported from each component in an object. This would replace the existing {component}ClassName export.
Although these names could be automatically generated, there is value in having them be explicitly written out in the source code so it can be found via searching.
export const checkboxClassNames: ClassNames<CheckboxSlots> = {
root: 'fui-Checkbox',
label: 'fui-Checkbox__label',
input: 'fui-Checkbox__input',
indicator: 'fui-Checkbox__indicator',
};
With the helper type that ensures every slot type is defined:
export type ClassNames<Slots> = {
[SlotName in keyof Slots]-?: string;
};
There would be a new conformance test that would check that each slot has a static class name. We'd need to figure out the best way to implement it, but it might require passing the {component}ClassNames object so the test knows the names of all of the slots.
.fui-Checkbox:nth-child(3), they can instead use .fui-Checkbox__indicator.