CSS Module patterns
CSS module primer
CSS module overview
A processor parses the stylesheet to scan classes and exposes them to JS as a key-value map. While the values are globally unique class names, we only interact with keys.
We should avoid hyphens in the key because it makes it harder to access in it JS, as JS doesn't support hyphens in variable names. We would need to quote the key name on lookup. Instead, we use camelCase for class names.
Note that Vite has an option to automatically transform class names with hyphens to camel case, but this adds a layer of indirection.
Pipeline example:
/* xxx.module.css */
.supercool {
}
.supernice {
}
.superGreat {
}
.super-awesome {
}
We import the map:
import classes from "xxx.module.css";
/* {
supercool: "supercool_5cEkq2n0x1",
supernice: "supernice_1kmox6oL39",
superGreat: "superGreat_1kmox6oL39",
"super-awesome": "super-awesome_1kmox6oL39",
} */
<Button
classNames={{
root: classes.supercool, // "supercool_5cEkq2n0x1"
label: classes.supernice, // "supernice_1kmox6oL39",
section: classes.superGreat,
loader: classes['super-awesome']
}}
>
Mantine pattern
one module for one variant
In this pattern, the module's purpose is to define the style for one Mantine component custom variant. For example, we create a PrimaryButton variant of Button. We name the CSS Module: PrimaryButton.module.css
target inner elements
We name the classes according to the inner-element we target, such as root or label:
/* PrimaryButton.module.css */
.root {
}
.root:hover {
}
.label {
}
We then apply the classes on the Mantine's instance:
import PrimaryButtonClassNames from "PrimaryButton.module.css";
{/* verbose */}
<Button
classNames={{
root: PrimaryButtonClassNames.root,
label: PrimaryButtonClassNames.label,
}}
>
When we follow the inner-element-as-a-classname pattern, we can give the map directly to classNames, since it matches exactly what is expected by classNames:
{/* short */}
<Button classNames={PrimaryButtonClassNames}>