Skip to content

Commit 2cdf841

Browse files
committed
refactor: remove concept of "direct assignments"
BREAKING CHANGE: this was prevent legit use of custom properties to override children: ```css .root { position: relative; --SomeChild-width: 960px; } ``` Instead we now just care about "API declarations"
1 parent 3671804 commit 2cdf841

File tree

3 files changed

+109
-165
lines changed

3 files changed

+109
-165
lines changed

README.md

Lines changed: 47 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ Stylelint plugin that validates CSS custom properties in CSS modules to ensure t
1818
- [Disable the rule](#disable-the-rule)
1919
- [How it works](#how-it-works)
2020
- [What gets validated](#what-gets-validated)
21-
- [Direct assignments](#direct-assignments)
22-
- [Fallback declarations](#fallback-declarations)
23-
- [What's ignored](#whats-ignored)
21+
- [API declarations (validated)](#api-declarations-validated)
22+
- [Private properties (ignored)](#private-properties-ignored)
23+
- [Property consumption (ignored)](#property-consumption-ignored)
2424
- [Examples](#examples)
2525
- [Valid](#valid)
2626
- [Invalid](#invalid)
@@ -32,32 +32,26 @@ Stylelint plugin that validates CSS custom properties in CSS modules to ensure t
3232

3333
## Why?
3434

35-
When working with CSS modules, it's common to use custom properties that are scoped to a specific component. This plugin enforces a naming convention where custom properties must be prefixed with the component name derived from the CSS module filename.
35+
When working with CSS modules, components often expose custom properties as a public API that can be overridden by parent components. This plugin validates that these **public** custom properties follow a consistent naming convention based on the component name.
3636

37-
For example, if your CSS module is named `Button.module.css`, all custom properties should be prefixed with `--Button-`:
38-
39-
```css
40-
.button {
41-
--Button-primary-color: #007bff;
42-
--Button-padding: 0.5rem 1rem;
43-
}
44-
```
45-
46-
The validation is also applied to declaring custom properties with a fallback as this is seen as providing an API that is designed to be overridden:
37+
For example, if your CSS module is named `Button.module.css`:
4738

4839
```css
4940
.button {
41+
/* Public API - validated */
5042
background-color: var(--Button-primary-color, #007bff);
43+
44+
/* Private properties - not validated */
45+
--internal-state: active;
5146
}
5247
```
5348

54-
See [how it works](#how-it-works) for more
55-
5649
This convention helps with:
5750

58-
- **Consistency**: All custom properties follow the same naming pattern
59-
- **Clarity**: It's immediately clear which component a custom property belongs to
60-
- **Avoiding conflicts**: Prevents naming collisions when components are nested or used together, since CSS custom properties inherit through the DOM tree
51+
- **Consistency**: All public custom properties follow the same naming pattern
52+
- **Clarity**: It's immediately clear which properties are part of the component's public API
53+
- **Avoiding conflicts**: Prevents naming collisions when components are nested
54+
- **API documentation**: Fallback values serve as default values and documentation
6155

6256
## Installation
6357

@@ -151,25 +145,15 @@ Use your own regular expression for suffix validation:
151145
The plugin:
152146

153147
- **Only applies to CSS modules** - files ending with `.module.css`
154-
- **Validates custom properties** - ensures they start with `--ComponentName-`
155-
- **Autofix** - can automatically correct invalid prefixes
148+
- **Validates public API custom properties** - ensures they start with `--ComponentName-`
149+
- **Ignores private custom properties** - allows any naming for internal use
150+
- **Autofix** - can automatically correct invalid prefixes in API declarations
156151

157152
### What gets validated
158153

159-
The plugin validates custom properties in two specific scenarios:
160-
161-
#### Direct assignments
162-
163-
Direct custom property usage is always validated:
154+
The plugin validates custom properties only when they're used as **public API declarations**.
164155

165-
```css
166-
:root {
167-
--Button-color: red;
168-
--Button-padding: 1rem;
169-
}
170-
```
171-
172-
#### Fallback declarations
156+
#### API declarations (validated)
173157

174158
Custom properties used in `var()` functions **with fallback values** are treated as component API declarations:
175159

@@ -180,22 +164,20 @@ Custom properties used in `var()` functions **with fallback values** are treated
180164
}
181165
```
182166

183-
This usage allows a user to override the custom properties from a parent
184-
component
167+
#### Private properties (ignored)
168+
169+
Direct custom property assignments are considered private implementation details:
185170

186171
```css
187-
/* parent component can override `Button` spacing */
188-
.parent {
189-
--Button-spacing: 2rem;
190-
--Button-max-width: 400px;
172+
.button {
173+
--internal-state: hover;
174+
--computed-size: calc(100% - 2rem);
191175
}
192176
```
193177

194-
This distinction ensures the plugin only validates properties that are being "declared" as part of the component's API, rather than properties being consumed from elsewhere.
178+
#### Property consumption (ignored)
195179

196-
#### What's ignored
197-
198-
Custom properties used without fallbacks are considered consumption of existing properties and are ignored:
180+
Custom properties used without fallbacks are considered consumption of existing properties:
199181

200182
```css
201183
.button {
@@ -212,20 +194,23 @@ Custom properties used without fallbacks are considered consumption of existing
212194

213195
```css
214196
.button {
215-
--Button-primary-color: #007bff;
216-
--Button-secondary-color: #6c757d;
217-
--Button-padding: 0.5rem 1rem;
218-
}
197+
/* Public API declarations - validated */
198+
background-color: var(--Button-primary-color, #007bff);
199+
padding: var(--Button-padding, 0.5rem 1rem);
219200

220-
/* Using existing custom properties is fine */
221-
.button {
222-
color: var(--some-global-color);
201+
/* Private properties - not validated */
202+
--internal-state: default;
203+
--computed-width: calc(100% - 2rem);
204+
205+
/* Consuming existing properties - not validated */
206+
margin: var(--global-spacing);
207+
font-family: var(--theme-font);
223208
}
224209

225-
/* API declarations with fallbacks are validated */
226-
.container {
227-
gap: var(--Button-spacing, 1rem);
228-
max-width: var(--Button-max-width, 320px);
210+
/* Overriding child component APIs - not validated */
211+
.button-container {
212+
--Icon-size: 16px;
213+
--Tooltip-background: var(--Button-primary-color);
229214
}
230215
```
231216

@@ -235,14 +220,11 @@ Custom properties used without fallbacks are considered consumption of existing
235220

236221
```css
237222
.button {
238-
--wrong-color: red; /* Should be --Button-color */
239-
--color: blue; /* Should be --Button-color */
240-
}
223+
/* Wrong prefix in API declaration */
224+
background: var(--wrong-color, red);
241225

242-
/* Invalid prefixes in var() with fallbacks */
243-
.container {
244-
gap: var(--wrong-spacing, 1rem); /* Should be --Button-spacing */
245-
width: var(--Container-width, 100%); /* Should be --Button-width */
226+
/* No prefix in API declaration */
227+
padding: var(--spacing, 1rem);
246228
}
247229
```
248230

@@ -254,13 +236,14 @@ If your CSS module filename isn't in PascalCase, you'll get a warning:
254236

255237
```css
256238
.profile {
257-
--UserProfile-avatar-size: 50px; /* Valid property, but filename warning */
239+
/* Valid API declaration, but filename warning */
240+
gap: var(--UserProfile-avatar-size, 50px);
258241
}
259242
```
260243

261244
## Autofix
262245

263-
The plugin supports stylelint's `--fix` option and will automatically correct invalid custom property prefixes:
246+
The plugin supports stylelint's `--fix` option and will automatically correct invalid custom property prefixes in API declarations:
264247

265248
```bash
266249
stylelint "**/*.module.css" --fix

0 commit comments

Comments
 (0)