@tenphi/eslint-plugin-tasty 1.18.0 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -45
- package/docs/rules/consistent-token-usage.md +72 -0
- package/docs/rules/known-property.md +55 -0
- package/docs/rules/no-classname-prop.md +60 -0
- package/docs/rules/no-ignored-pseudo-element-state.md +97 -0
- package/docs/rules/no-important.md +25 -0
- package/docs/rules/no-nested-selector.md +39 -0
- package/docs/rules/no-nested-state-map.md +33 -0
- package/docs/rules/no-own-at-root.md +57 -0
- package/docs/rules/no-protected-restyle.md +192 -0
- package/docs/rules/no-raw-color-values.md +49 -0
- package/docs/rules/no-raw-motion-duration.md +50 -0
- package/docs/rules/no-raw-transition-duration.md +56 -0
- package/docs/rules/no-runtime-styles-mutation.md +58 -0
- package/docs/rules/no-state-in-selector.md +142 -0
- package/docs/rules/no-style-prop.md +127 -0
- package/docs/rules/no-style-spread.md +53 -0
- package/docs/rules/no-styles-prop.md +57 -0
- package/docs/rules/no-unknown-state-alias.md +45 -0
- package/docs/rules/prefer-auto-calc.md +30 -0
- package/docs/rules/prefer-custom-property-syntax.md +56 -0
- package/docs/rules/prefer-directional-shorthand.md +46 -0
- package/docs/rules/prefer-element-selector.md +77 -0
- package/docs/rules/prefer-fill-mix.md +119 -0
- package/docs/rules/prefer-hide.md +31 -0
- package/docs/rules/prefer-longhand-property.md +25 -0
- package/docs/rules/prefer-shorthand-property.md +194 -0
- package/docs/rules/prefer-state-negation.md +44 -0
- package/docs/rules/require-default-state.md +50 -0
- package/docs/rules/static-no-dynamic-values.md +32 -0
- package/docs/rules/static-valid-selector.md +36 -0
- package/docs/rules/valid-boolean-property.md +39 -0
- package/docs/rules/valid-color-token.md +64 -0
- package/docs/rules/valid-custom-property.md +36 -0
- package/docs/rules/valid-custom-unit.md +34 -0
- package/docs/rules/valid-default-state-order.md +44 -0
- package/docs/rules/valid-directional-modifier.md +46 -0
- package/docs/rules/valid-preset.md +35 -0
- package/docs/rules/valid-radius-shape.md +31 -0
- package/docs/rules/valid-recipe.md +35 -0
- package/docs/rules/valid-state-definition.md +46 -0
- package/docs/rules/valid-state-key.md +62 -0
- package/docs/rules/valid-styles-structure.md +48 -0
- package/docs/rules/valid-sub-element.md +100 -0
- package/docs/rules/valid-transition.md +46 -0
- package/docs/rules/valid-value.md +65 -0
- package/harness/dev.harnesspm/hooks.json +12 -0
- package/harness/dev.harnesspm/rules/usage.md +11 -0
- package/harness/dev.harnesspm/scripts/check-edit.mjs +127 -0
- package/harness/dev.harnesspm/scripts/check.mjs +159 -0
- package/harness/dev.harnesspm/scripts/lint.mjs +236 -0
- package/harness/plugin.json +23 -0
- package/package.json +11 -7
package/README.md
CHANGED
|
@@ -226,59 +226,61 @@ not matched.
|
|
|
226
226
|
|
|
227
227
|
## Rules
|
|
228
228
|
|
|
229
|
+
Every rule has a page in [`docs/rules/`](docs/rules/) with examples and options. The pages ship in the package.
|
|
230
|
+
|
|
229
231
|
### Recommended
|
|
230
232
|
|
|
231
233
|
| Rule | Severity | Description |
|
|
232
234
|
|------|----------|-------------|
|
|
233
|
-
| `tasty/known-property` | warn | Unknown style property names (checked against the full MDN/W3C CSS property set) |
|
|
234
|
-
| `tasty/valid-value` | error | Malformed style values (unbalanced parens, !important) |
|
|
235
|
-
| `tasty/valid-color-token` | error | Invalid color token syntax or unknown tokens |
|
|
236
|
-
| `tasty/valid-custom-unit` | error | Unknown custom units |
|
|
237
|
-
| `tasty/valid-boolean-property` | error | `true` on properties that don't support it, in a state map as well as on a direct value. Includes `fill`, which tasty documents as taking `true` but currently renders as `background-color: true` |
|
|
238
|
-
| `tasty/valid-state-key` | error | Invalid state key syntax in style mappings (including misuse of the `_` fallback floor) |
|
|
239
|
-
| `tasty/valid-styles-structure` | error | Invalid styles object structure, and the v2 at-rule key spellings (auto-fixable) |
|
|
240
|
-
| `tasty/no-nested-state-map` | error | Nested state maps (not supported) |
|
|
241
|
-
| `tasty/no-important` | error | `!important` usage (breaks tasty specificity) |
|
|
242
|
-
| `tasty/valid-sub-element` | error | Sub-element values must be style objects; `$` selectors must not target the root element
|
|
243
|
-
| `tasty/valid-directional-modifier` | error | Directional modifiers on wrong properties, and more than one value in a group that names directions. Physical properties take `top`/`right`/`bottom`/`left`, logical ones `start`/`end`, and mixing the two is reported in either direction |
|
|
244
|
-
| `tasty/valid-radius-shape` | error | Unknown radius shape keywords |
|
|
245
|
-
| `tasty/valid-preset` | error | Unknown preset names |
|
|
246
|
-
| `tasty/valid-recipe` | error | Unknown recipe names |
|
|
247
|
-
| `tasty/valid-transition` | warn | Unknown transition names, and camelCase CSS names that Tasty would emit as no property (`gridTemplateColumns` → `grid-template-columns`) |
|
|
248
|
-
| `tasty/no-nested-selector` | warn | `&`-prefixed nested selectors (use sub-elements) |
|
|
249
|
-
| `tasty/no-state-in-selector` | warn | Pseudo-class and attribute conditions in sub-element `$` selectors; put conditions in property state maps
|
|
250
|
-
| `tasty/prefer-element-selector` | warn | Prefer element names such as `Primary > Search` over exact `data-element` attributes in sub-element `$` selectors (safely autofixable
|
|
251
|
-
| `tasty/static-no-dynamic-values` | error | Dynamic values in `tastyStatic()` |
|
|
252
|
-
| `tasty/static-valid-selector` | error | Invalid selector in `tastyStatic(selector, ...)` |
|
|
253
|
-
| `tasty/require-default-state` | error | Missing default (`''`) or fallback floor (`_`) key in state mappings (skipped for extending calls and maps that spread another) |
|
|
254
|
-
| `tasty/no-own-at-root` | warn | `@own()` used at root level where it is redundant (not in shared style constants, which may be spread into a sub-element) |
|
|
255
|
-
| `tasty/no-ignored-pseudo-element-state` | error | States Tasty ignores on a pseudo-element, such as `@own([open])` on `$: 'a::before'`: attributes, modifiers, classes, and tree-structural pseudo-classes
|
|
256
|
-
| `tasty/valid-default-state-order` | warn | Misplaced default (`''`) or redundant `''` when only `_` is present |
|
|
257
|
-
| `tasty/prefer-shorthand-property` | warn | Use Tasty shorthand instead of native CSS properties (`backgroundColor` → `fill`, `paddingBlock` → `blockPadding`, etc.). Report-only warnings explain how to override one part through a token, with concrete min/max dimension examples. Extension warnings point at the base component and are skipped over bases you cannot edit (see `ownedSources
|
|
258
|
-
| `tasty/no-raw-color-values` | warn | Raw hex/rgb/`okhsl`/`okhst`/`oklch`/named colors instead of `#color` tokens |
|
|
259
|
-
| `tasty/no-raw-transition-duration` | warn | Hardcoded `transition` duration (`fill 0.2s`) in Tasty styles or a local `tasty()` component's `transition` prop. Suggests a configured duration token or the implicit per-name timing; zero and delays are left alone |
|
|
260
|
-
| `tasty/no-runtime-styles-mutation` | warn | Render-time JavaScript in Tasty style values (props, state, hook results, parameters, local bindings, calls, computed keys); use states and tokens instead. A style object no function encloses is built once at load and not checked; inside a function, module-scope constants, imports, `undefined` and static `mergeStyles(...)` calls are fixed at load and allowed |
|
|
261
|
-
| `tasty/no-style-spread` | warn | Object or array spreads inside runtime Tasty styles; recommends `mergeStyles` for multiple root spreads; intentional spreads need a per-line suppression and reason |
|
|
262
|
-
| `tasty/no-style-prop` | warn | `style` on recognized Tasty components; use token references and the `tokens` prop. The `elements` option covers every component or element, so it can replace React's `style` restriction; `values: 'static'` reports only static styles. Tasty syntax in `style` is always reported
|
|
263
|
-
| `tasty/no-classname-prop` | warn | `className` on recognized Tasty components; keep styling in Tasty or use `data-element` for sub-elements
|
|
264
|
-
| `tasty/no-styles-prop` | warn | Instance `styles` on recognized Tasty components; use `tokens`, `mods`, exposed props/variants, or `tasty(Component, { styles })`
|
|
265
|
-
| `tasty/no-protected-restyle` | warn | Restyling a design system's `protectedComponents`: instance `styles` and `*Styles`, appearance style props, and `tasty()` wrappers that restyle them, followed through aliases, wrappers and relative re-exports. `usages: 'wrappers'` reports only the wrappers. Inactive without the config
|
|
266
|
-
| `tasty/consistent-token-usage` | warn | Nonzero raw pixel lengths, including compounds, expressions and numeric inputs to enhanced length handlers. The `pixels: 'replaceable'` option reports only lengths with an exact unit, such as `8px` → `1x`
|
|
267
|
-
| `tasty/prefer-auto-calc` | warn | `calc(...)` instead of Tasty auto-calc `(...)` |
|
|
268
|
-
| `tasty/prefer-state-negation` | warn | Top-level `:not(...)` in state keys instead of the `!` prefix (autofixable; nested CSS selectors stay intact) |
|
|
269
|
-
| `tasty/prefer-custom-property-syntax` | warn | `var(--prop)` / `$x-color` / `transparent` / `currentColor` instead of `$prop` / `#color` / `#clear` / `#current` |
|
|
270
|
-
| `tasty/prefer-hide` | warn | `display: 'none'` instead of `hide: true` |
|
|
271
|
-
| `tasty/prefer-fill-mix` | warn | Deprecated two-color `fill`, space-separated (`'#surface #dark.04'`) or comma-mixed (`'#dark 4%, #surface'`), instead of a compound color (`'#surface+#dark.04'`) or `color-mix()`, autofixed when the result is the same color; mix parts weighted by their opacity (`'#dark.04, #surface'`). Needs `@tenphi/tasty` 3.15, and 3.16 for compound colors
|
|
272
|
-
| `tasty/prefer-directional-shorthand` | warn | 4-value `margin`/`padding`/`inset`/`radius`/`fade`/`border` with placeholder positions instead of directional form |
|
|
273
|
-
| `tasty/prefer-longhand-property` | error | Lossy `flex` shorthand instead of `flexGrow` / `flexShrink` / `flexBasis` |
|
|
235
|
+
| [`tasty/known-property`](docs/rules/known-property.md) | warn | Unknown style property names (checked against the full MDN/W3C CSS property set) |
|
|
236
|
+
| [`tasty/valid-value`](docs/rules/valid-value.md) | error | Malformed style values (unbalanced parens, !important) |
|
|
237
|
+
| [`tasty/valid-color-token`](docs/rules/valid-color-token.md) | error | Invalid color token syntax or unknown tokens |
|
|
238
|
+
| [`tasty/valid-custom-unit`](docs/rules/valid-custom-unit.md) | error | Unknown custom units |
|
|
239
|
+
| [`tasty/valid-boolean-property`](docs/rules/valid-boolean-property.md) | error | `true` on properties that don't support it, in a state map as well as on a direct value. Includes `fill`, which tasty documents as taking `true` but currently renders as `background-color: true` |
|
|
240
|
+
| [`tasty/valid-state-key`](docs/rules/valid-state-key.md) | error | Invalid state key syntax in style mappings (including misuse of the `_` fallback floor) |
|
|
241
|
+
| [`tasty/valid-styles-structure`](docs/rules/valid-styles-structure.md) | error | Invalid styles object structure, and the v2 at-rule key spellings (auto-fixable) |
|
|
242
|
+
| [`tasty/no-nested-state-map`](docs/rules/no-nested-state-map.md) | error | Nested state maps (not supported) |
|
|
243
|
+
| [`tasty/no-important`](docs/rules/no-important.md) | error | `!important` usage (breaks tasty specificity) |
|
|
244
|
+
| [`tasty/valid-sub-element`](docs/rules/valid-sub-element.md) | error | Sub-element values must be style objects; `$` selectors must not target the root element |
|
|
245
|
+
| [`tasty/valid-directional-modifier`](docs/rules/valid-directional-modifier.md) | error | Directional modifiers on wrong properties, and more than one value in a group that names directions. Physical properties take `top`/`right`/`bottom`/`left`, logical ones `start`/`end`, and mixing the two is reported in either direction |
|
|
246
|
+
| [`tasty/valid-radius-shape`](docs/rules/valid-radius-shape.md) | error | Unknown radius shape keywords |
|
|
247
|
+
| [`tasty/valid-preset`](docs/rules/valid-preset.md) | error | Unknown preset names |
|
|
248
|
+
| [`tasty/valid-recipe`](docs/rules/valid-recipe.md) | error | Unknown recipe names |
|
|
249
|
+
| [`tasty/valid-transition`](docs/rules/valid-transition.md) | warn | Unknown transition names, and camelCase CSS names that Tasty would emit as no property (`gridTemplateColumns` → `grid-template-columns`) |
|
|
250
|
+
| [`tasty/no-nested-selector`](docs/rules/no-nested-selector.md) | warn | `&`-prefixed nested selectors (use sub-elements) |
|
|
251
|
+
| [`tasty/no-state-in-selector`](docs/rules/no-state-in-selector.md) | warn | Pseudo-class and attribute conditions in sub-element `$` selectors; put conditions in property state maps |
|
|
252
|
+
| [`tasty/prefer-element-selector`](docs/rules/prefer-element-selector.md) | warn | Prefer element names such as `Primary > Search` over exact `data-element` attributes in sub-element `$` selectors (safely autofixable) |
|
|
253
|
+
| [`tasty/static-no-dynamic-values`](docs/rules/static-no-dynamic-values.md) | error | Dynamic values in `tastyStatic()` |
|
|
254
|
+
| [`tasty/static-valid-selector`](docs/rules/static-valid-selector.md) | error | Invalid selector in `tastyStatic(selector, ...)` |
|
|
255
|
+
| [`tasty/require-default-state`](docs/rules/require-default-state.md) | error | Missing default (`''`) or fallback floor (`_`) key in state mappings (skipped for extending calls and maps that spread another) |
|
|
256
|
+
| [`tasty/no-own-at-root`](docs/rules/no-own-at-root.md) | warn | `@own()` used at root level where it is redundant (not in shared style constants, which may be spread into a sub-element) |
|
|
257
|
+
| [`tasty/no-ignored-pseudo-element-state`](docs/rules/no-ignored-pseudo-element-state.md) | error | States Tasty ignores on a pseudo-element, such as `@own([open])` on `$: 'a::before'`: attributes, modifiers, classes, and tree-structural pseudo-classes |
|
|
258
|
+
| [`tasty/valid-default-state-order`](docs/rules/valid-default-state-order.md) | warn | Misplaced default (`''`) or redundant `''` when only `_` is present |
|
|
259
|
+
| [`tasty/prefer-shorthand-property`](docs/rules/prefer-shorthand-property.md) | warn | Use Tasty shorthand instead of native CSS properties (`backgroundColor` → `fill`, `paddingBlock` → `blockPadding`, etc.). Report-only warnings explain how to override one part through a token, with concrete min/max dimension examples. Extension warnings point at the base component and are skipped over bases you cannot edit (see `ownedSources`) |
|
|
260
|
+
| [`tasty/no-raw-color-values`](docs/rules/no-raw-color-values.md) | warn | Raw hex/rgb/`okhsl`/`okhst`/`oklch`/named colors instead of `#color` tokens |
|
|
261
|
+
| [`tasty/no-raw-transition-duration`](docs/rules/no-raw-transition-duration.md) | warn | Hardcoded `transition` duration (`fill 0.2s`) in Tasty styles or a local `tasty()` component's `transition` prop. Suggests a configured duration token or the implicit per-name timing; zero and delays are left alone |
|
|
262
|
+
| [`tasty/no-runtime-styles-mutation`](docs/rules/no-runtime-styles-mutation.md) | warn | Render-time JavaScript in Tasty style values (props, state, hook results, parameters, local bindings, calls, computed keys); use states and tokens instead. A style object no function encloses is built once at load and not checked; inside a function, module-scope constants, imports, `undefined` and static `mergeStyles(...)` calls are fixed at load and allowed |
|
|
263
|
+
| [`tasty/no-style-spread`](docs/rules/no-style-spread.md) | warn | Object or array spreads inside runtime Tasty styles; recommends `mergeStyles` for multiple root spreads; intentional spreads need a per-line suppression and reason |
|
|
264
|
+
| [`tasty/no-style-prop`](docs/rules/no-style-prop.md) | warn | `style` on recognized Tasty components; use token references and the `tokens` prop. The `elements` option covers every component or element, so it can replace React's `style` restriction; `values: 'static'` reports only static styles. Tasty syntax in `style` is always reported |
|
|
265
|
+
| [`tasty/no-classname-prop`](docs/rules/no-classname-prop.md) | warn | `className` on recognized Tasty components; keep styling in Tasty or use `data-element` for sub-elements |
|
|
266
|
+
| [`tasty/no-styles-prop`](docs/rules/no-styles-prop.md) | warn | Instance `styles` on recognized Tasty components; use `tokens`, `mods`, exposed props/variants, or `tasty(Component, { styles })` |
|
|
267
|
+
| [`tasty/no-protected-restyle`](docs/rules/no-protected-restyle.md) | warn | Restyling a design system's `protectedComponents`: instance `styles` and `*Styles`, appearance style props, and `tasty()` wrappers that restyle them, followed through aliases, wrappers and relative re-exports. `usages: 'wrappers'` reports only the wrappers. Inactive without the config |
|
|
268
|
+
| [`tasty/consistent-token-usage`](docs/rules/consistent-token-usage.md) | warn | Nonzero raw pixel lengths, including compounds, expressions and numeric inputs to enhanced length handlers. The `pixels: 'replaceable'` option reports only lengths with an exact unit, such as `8px` → `1x` |
|
|
269
|
+
| [`tasty/prefer-auto-calc`](docs/rules/prefer-auto-calc.md) | warn | `calc(...)` instead of Tasty auto-calc `(...)` |
|
|
270
|
+
| [`tasty/prefer-state-negation`](docs/rules/prefer-state-negation.md) | warn | Top-level `:not(...)` in state keys instead of the `!` prefix (autofixable; nested CSS selectors stay intact) |
|
|
271
|
+
| [`tasty/prefer-custom-property-syntax`](docs/rules/prefer-custom-property-syntax.md) | warn | `var(--prop)` / `$x-color` / `transparent` / `currentColor` instead of `$prop` / `#color` / `#clear` / `#current` |
|
|
272
|
+
| [`tasty/prefer-hide`](docs/rules/prefer-hide.md) | warn | `display: 'none'` instead of `hide: true` |
|
|
273
|
+
| [`tasty/prefer-fill-mix`](docs/rules/prefer-fill-mix.md) | warn | Deprecated two-color `fill`, space-separated (`'#surface #dark.04'`) or comma-mixed (`'#dark 4%, #surface'`), instead of a compound color (`'#surface+#dark.04'`) or `color-mix()`, autofixed when the result is the same color; mix parts weighted by their opacity (`'#dark.04, #surface'`). Needs `@tenphi/tasty` 3.15, and 3.16 for compound colors |
|
|
274
|
+
| [`tasty/prefer-directional-shorthand`](docs/rules/prefer-directional-shorthand.md) | warn | 4-value `margin`/`padding`/`inset`/`radius`/`fade`/`border` with placeholder positions instead of directional form |
|
|
275
|
+
| [`tasty/prefer-longhand-property`](docs/rules/prefer-longhand-property.md) | error | Lossy `flex` shorthand instead of `flexGrow` / `flexShrink` / `flexBasis` |
|
|
274
276
|
|
|
275
277
|
### Strict (includes all recommended rules)
|
|
276
278
|
|
|
277
279
|
| Rule | Severity | Description |
|
|
278
280
|
|------|----------|-------------|
|
|
279
|
-
| `tasty/valid-custom-property` | warn | Unknown `$name` custom properties |
|
|
280
|
-
| `tasty/valid-state-definition` | warn | Invalid state definition values in `configure()` or `tasty.config` |
|
|
281
|
-
| `tasty/no-unknown-state-alias` | warn | Unknown `@name` state aliases |
|
|
281
|
+
| [`tasty/valid-custom-property`](docs/rules/valid-custom-property.md) | warn | Unknown `$name` custom properties |
|
|
282
|
+
| [`tasty/valid-state-definition`](docs/rules/valid-state-definition.md) | warn | Invalid state definition values in `configure()` or `tasty.config` |
|
|
283
|
+
| [`tasty/no-unknown-state-alias`](docs/rules/no-unknown-state-alias.md) | warn | Unknown `@name` state aliases |
|
|
282
284
|
|
|
283
285
|
### Structural selectors and state maps
|
|
284
286
|
|
|
@@ -360,7 +362,7 @@ suppressed, run ESLint with `--max-warnings=0`.
|
|
|
360
362
|
|
|
361
363
|
### Optional motion duration rule
|
|
362
364
|
|
|
363
|
-
Enable `tasty/no-raw-motion-duration` as a warning if your design system uses
|
|
365
|
+
Enable [`tasty/no-raw-motion-duration`](docs/rules/no-raw-motion-duration.md) as a warning if your design system uses
|
|
364
366
|
tokens for animation timing and explicit CSS durations:
|
|
365
367
|
|
|
366
368
|
```js
|
|
@@ -635,6 +637,23 @@ your installed version — and on 3.7 and below `blockPadding` is not a style ta
|
|
|
635
637
|
(an unhandled camelCase key renders through to `block-padding`, which the browser drops).
|
|
636
638
|
The peer range floor is 3.8.0 for that reason.
|
|
637
639
|
|
|
640
|
+
## AI agents
|
|
641
|
+
|
|
642
|
+
The package ships an agent harness for [harnesspm](https://www.npmjs.com/package/@tenphi/harnesspm), as plugin `tasty-lint`. In a project that uses harnesspm, agents get:
|
|
643
|
+
|
|
644
|
+
- a short always-on rule: lint the files you change and fix every `tasty/*` problem;
|
|
645
|
+
- the rule pages of the installed version, in the docs index;
|
|
646
|
+
- `npx harnesspm run tasty-lint:check <files> [--strict] [--json]`, which runs only the `tasty/*` rules with the project's `tasty.config.*` and prints each problem with its rule's page;
|
|
647
|
+
- a Claude Code hook that lints each file the agent edits, when it imports Tasty or a configured `importSources` module, and hands the new problems back to the agent.
|
|
648
|
+
|
|
649
|
+
The tool and the hook run only in projects that trust the package, in `harnesspm.json`:
|
|
650
|
+
|
|
651
|
+
```json
|
|
652
|
+
{ "trust": { "@tenphi/eslint-plugin-tasty": true } }
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
They need `eslint`, and `typescript-eslint` or `@typescript-eslint/parser` for TypeScript files. They do not read the project's ESLint or Oxlint config, so other plugins, rule options and settings such as `typeAwareJSX` do not apply there.
|
|
656
|
+
|
|
638
657
|
## License
|
|
639
658
|
|
|
640
659
|
MIT
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# tasty/consistent-token-usage
|
|
2
|
+
|
|
3
|
+
Warn about pixel lengths in Tasty styles.
|
|
4
|
+
|
|
5
|
+
**Presets:** warning in recommended and strict. **Fix:** editor suggestions.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
A design system sizes things with its units (`x`, `r`, `bw`) and tokens, so a layout follows its scale. A raw `8px` stays put when the scale changes.
|
|
10
|
+
|
|
11
|
+
## Checks
|
|
12
|
+
|
|
13
|
+
The rule reports every nonzero pixel length in recognized style objects and JSX
|
|
14
|
+
style props: compound values, comma-separated groups, function arguments, and
|
|
15
|
+
numeric inputs to enhanced handlers that convert them to pixels, such as
|
|
16
|
+
`gap={17}`. Unitless properties such as `opacity` and `zIndex` are not checked.
|
|
17
|
+
Zero, token definitions (`$name` and `#name` keys), quoted CSS text, and URLs
|
|
18
|
+
are allowed.
|
|
19
|
+
|
|
20
|
+
A pixel length with an exact unit gets a suggestion that replaces it:
|
|
21
|
+
|
|
22
|
+
| Pixels | Replacement |
|
|
23
|
+
| --------------------------- | --------------- |
|
|
24
|
+
| `8px` to `64px`, step `8px` | `1x` to `8x` |
|
|
25
|
+
| `6px` in `radius` | `1r` |
|
|
26
|
+
| `1px` in a border width | `1bw` |
|
|
27
|
+
|
|
28
|
+
These replacements assume Tasty's default scale. Review them against your
|
|
29
|
+
design system. Any other pixel length, such as `17px` or `520px`, is reported
|
|
30
|
+
without a suggestion: the rule does not invent a token. A `fontSize`,
|
|
31
|
+
`lineHeight` or `letterSpacing` length never gets an `x` suggestion: it is on
|
|
32
|
+
the type scale, which presets set, and `x` is the spacing scale.
|
|
33
|
+
|
|
34
|
+
A suggestion keeps the rest of the value as written. It is withheld when
|
|
35
|
+
JavaScript escapes or JSX entities make the source differ from the value.
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import { tasty } from '@tenphi/tasty';
|
|
39
|
+
|
|
40
|
+
// ❌ '1x' and '1bw' replace these exactly.
|
|
41
|
+
const Card = tasty({ styles: { padding: '8px', border: '1px solid #border' } });
|
|
42
|
+
|
|
43
|
+
// ✅ Preferred.
|
|
44
|
+
const Card = tasty({ styles: { padding: '1x', border: '1bw solid #border' } });
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
For an intentional pixel length, add an explicit local ignore with a reason:
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
const Rule = tasty({
|
|
51
|
+
styles: {
|
|
52
|
+
// eslint-disable-next-line tasty/consistent-token-usage -- aligns with the 3px focus ring
|
|
53
|
+
inset: '-3px',
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Options
|
|
59
|
+
|
|
60
|
+
```js
|
|
61
|
+
'tasty/consistent-token-usage': ['error', { pixels: 'replaceable' }],
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
| `pixels` | Reports |
|
|
65
|
+
| ----------------- | ------------------------------------------------------------------------------ |
|
|
66
|
+
| `'all'` (default) | Every nonzero pixel length |
|
|
67
|
+
| `'replaceable'` | Only a pixel length with an exact unit in the table above, with its suggestion |
|
|
68
|
+
|
|
69
|
+
Use `'replaceable'` when your layout sizes are in pixels on purpose, such as
|
|
70
|
+
`width: 'max 520px'`. The rule then reports only a length that a unit replaces
|
|
71
|
+
exactly, so every finding has a fix and the rule can run as an error. In
|
|
72
|
+
`padding: '8px 17px'` it reports `8px` and leaves `17px` alone.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# tasty/known-property
|
|
2
|
+
|
|
3
|
+
Reports a style property name that is neither a Tasty style nor a CSS property, such as a typo.
|
|
4
|
+
|
|
5
|
+
**Presets:** warning in recommended and strict. **Fix:** none.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
Tasty passes an unknown key through as a CSS declaration, which the browser drops. A typo such as `colour` or `boarder` fails silently at runtime.
|
|
10
|
+
|
|
11
|
+
## Examples
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
// ✅ Valid
|
|
15
|
+
tasty({ styles: { fill: '#purple', padding: '2x' } });
|
|
16
|
+
|
|
17
|
+
// ❌ Unknown style property 'colour'
|
|
18
|
+
tasty({ styles: { colour: '#purple' } });
|
|
19
|
+
|
|
20
|
+
// ❌ Unknown style property 'boarder'
|
|
21
|
+
tasty({ styles: { boarder: true } });
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## What counts as known
|
|
25
|
+
|
|
26
|
+
- **Tasty styles:** `display`, `font`, `preset`, `hide`, `whiteSpace`, `opacity`, `transition`, `gridArea`, `order`, `gridColumn`, `gridRow`, `placeSelf`, `alignSelf`, `justifySelf`, `zIndex`, `margin`, `inset`, `position`, `padding`, `overflow`, `scrollbar`, `textAlign`, `scrollMargin`, `scrollPadding`, `border`, `radius`, `shadow`, `outline`, `color`, `fill`, `svgFill`, `fade`, `image`, `textTransform`, `fontWeight`, `fontStyle`, `width`, `height`, `flexBasis`, `flexGrow`, `flexShrink`, `flex`, `flow`, `placeItems`, `placeContent`, `alignItems`, `alignContent`, `justifyItems`, `justifyContent`, `align`, `justify`, `gap`, `columnGap`, `rowGap`, `gridColumns`, `gridRows`, `gridTemplate`, `gridAreas`, `recipe`, `textOverflow`.
|
|
27
|
+
- **Enhanced logical styles** (Tasty 3.8 and later), one per axis and category:
|
|
28
|
+
|
|
29
|
+
| Category | Block axis | Inline axis |
|
|
30
|
+
| --- | --- | --- |
|
|
31
|
+
| Size | `blockSize` (+ `minBlockSize`, `maxBlockSize`) | `inlineSize` (+ `minInlineSize`, `maxInlineSize`) |
|
|
32
|
+
| Padding | `blockPadding` | `inlinePadding` |
|
|
33
|
+
| Margin | `blockMargin` | `inlineMargin` |
|
|
34
|
+
| Inset | `blockInset` | `inlineInset` |
|
|
35
|
+
| Scroll margin | `blockScrollMargin` | `inlineScrollMargin` |
|
|
36
|
+
| Scroll padding | `blockScrollPadding` | `inlineScrollPadding` |
|
|
37
|
+
| Border | `blockBorder` | `inlineBorder` |
|
|
38
|
+
|
|
39
|
+
- **CSS properties.** The list is generated from `known-css-properties`, the MDN/W3C dataset that stylelint uses for `property-no-unknown`. It covers modern properties (`maskSize`, `anchorName`, `fieldSizing`, `viewTransitionName`, `textBox`) and SVG presentation and geometry properties. A small hand-kept supplement adds properties that ship before the dataset has them. At-rule descriptors that the specs (through `@webref/css`) do not also define as properties, such as `src`, `prefix`, `suffix`, `syntax`, `symbols` and `unicodeRange`, are left out: a style rule cannot declare them. Regenerate the list with `pnpm generate:css-properties`.
|
|
40
|
+
- **Names from your config:** the `styles` list in `tasty.config.*`, for handlers added through `configure({ handlers })`.
|
|
41
|
+
|
|
42
|
+
The native logical spellings (`paddingBlock`, `insetInlineStart`, `borderBlockColor`, …) stay valid as CSS properties. They are no longer Tasty styles: Tasty 3.8 stopped reading `paddingBlock`, `paddingInline`, `insetBlock` and `insetInline` in its physical handlers. [`tasty/prefer-shorthand-property`](prefer-shorthand-property.md) reports them with a migration.
|
|
43
|
+
|
|
44
|
+
## Keys this rule skips
|
|
45
|
+
|
|
46
|
+
- A key that starts with an uppercase letter is a sub-element ([`tasty/valid-sub-element`](valid-sub-element.md)).
|
|
47
|
+
- A key that starts with `@` is an at-rule key (`@keyframes`, `@property`, …) or a local state alias.
|
|
48
|
+
- A key that starts with `$` or `$$` defines a custom property (`$name` is `--name`).
|
|
49
|
+
- A key that starts with `#` or `##` defines a color token (`#name` is `--name-color`).
|
|
50
|
+
- `--name` custom properties and vendor-prefixed properties (`-webkit-…`).
|
|
51
|
+
- A key that starts with `&` is a nested selector, which [`tasty/no-nested-selector`](no-nested-selector.md) reports.
|
|
52
|
+
|
|
53
|
+
## Options
|
|
54
|
+
|
|
55
|
+
None.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# tasty/no-classname-prop
|
|
2
|
+
|
|
3
|
+
Warn about `className` on recognized Tasty components.
|
|
4
|
+
|
|
5
|
+
**Presets:** warning in recommended and strict. **Fix:** none.
|
|
6
|
+
|
|
7
|
+
Keep styling in Tasty rather than attaching external styling classes. When a
|
|
8
|
+
class identifies a sub-element for its parent to style, replace that identity
|
|
9
|
+
with `data-element="Name"` and a matching capitalized sub-element key:
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import { tasty } from '@tenphi/tasty';
|
|
13
|
+
|
|
14
|
+
const Card = tasty({ styles: { Body: { padding: '2x' } } });
|
|
15
|
+
const Box = tasty({ as: 'div' });
|
|
16
|
+
|
|
17
|
+
// ❌ Avoid external class-based styling.
|
|
18
|
+
<Card>
|
|
19
|
+
<Box className="card-body" />
|
|
20
|
+
</Card>;
|
|
21
|
+
|
|
22
|
+
// ✅ Preferred: Card's Body styles target this element.
|
|
23
|
+
<Card>
|
|
24
|
+
<Box data-element="Body" />
|
|
25
|
+
</Card>;
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
For general root styling, define styles on the component or use a styled wrapper.
|
|
29
|
+
`data-element` is an identity for parent sub-element styling, not a replacement
|
|
30
|
+
for an arbitrary list of CSS classes.
|
|
31
|
+
|
|
32
|
+
The rule checks every explicit attribute value and visible `className` keys in
|
|
33
|
+
inline object spreads. It has no automatic fix because external classes can have
|
|
34
|
+
multiple styling or behavior roles.
|
|
35
|
+
|
|
36
|
+
A third-party library may require a class for its stylesheet or behavior. Keep
|
|
37
|
+
that integration and acknowledge the exception with an explicit local ignore and
|
|
38
|
+
a reason:
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
const libraryElement = (
|
|
42
|
+
// eslint-disable-next-line tasty/no-classname-prop -- library stylesheet requires this class
|
|
43
|
+
<Box className={libraryClassName} />
|
|
44
|
+
);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Place the directive immediately before the reported attribute line. It suppresses
|
|
48
|
+
only this rule for that line. The warning message includes this exception path;
|
|
49
|
+
the plugin does not silently exempt library-provided values or enforce reasons.
|
|
50
|
+
|
|
51
|
+
Recognition uses local `const` Tasty/configured-options factory results, their
|
|
52
|
+
`const` aliases/sub-elements, and imports from `importSources`. Exports of relative modules (`import { Panel } from './styled'`) count when they
|
|
53
|
+
resolve to one of these, through re-exports too; following them needs the
|
|
54
|
+
`typescript` package. Native elements,
|
|
55
|
+
unrelated components, type-only imports, shadowed bindings, mutable aliases, and
|
|
56
|
+
opaque spread bindings are excluded.
|
|
57
|
+
|
|
58
|
+
## Options
|
|
59
|
+
|
|
60
|
+
None.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# tasty/no-ignored-pseudo-element-state
|
|
2
|
+
|
|
3
|
+
Report states that Tasty ignores because they test a pseudo-element for
|
|
4
|
+
something it cannot have. The reported state never applies.
|
|
5
|
+
|
|
6
|
+
**Presets:** error in recommended and strict. **Fix:** none.
|
|
7
|
+
|
|
8
|
+
When a sub-element's `$` ends in a pseudo-element, Tasty applies `@own(...)` to
|
|
9
|
+
the pseudo-element itself: `$: '@::part(label)'` with `@own(:focus)` becomes
|
|
10
|
+
`::part(label):where(:focus)`. A pseudo-element has no attributes, classes, IDs,
|
|
11
|
+
or place in the DOM tree, so a state that tests one of those can never match.
|
|
12
|
+
Tasty drops such a state at runtime with a `PSEUDO_ELEMENT_STATE_IGNORED`
|
|
13
|
+
warning. This rule reports the same state keys while you edit.
|
|
14
|
+
|
|
15
|
+
## Reported
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
const Pagination = tasty({
|
|
19
|
+
styles: {
|
|
20
|
+
NextArrow: {
|
|
21
|
+
$: 'a::before',
|
|
22
|
+
content: {
|
|
23
|
+
'': 'none',
|
|
24
|
+
'@own([rel="next"])': '"→"', // attributes
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
Marker: {
|
|
28
|
+
$: 'li::marker',
|
|
29
|
+
color: {
|
|
30
|
+
'': '#text',
|
|
31
|
+
'@own(:last-child)': '#accent', // position in the DOM tree
|
|
32
|
+
'@own(selected)': '#active', // modifiers
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Tasty ignores these states on a pseudo-element:
|
|
40
|
+
|
|
41
|
+
- Modifiers: `@own(hovered)`, `@own(theme=dark)`.
|
|
42
|
+
- Attributes: `@own([open])`, `@own(:not([open]))`.
|
|
43
|
+
- Classes and IDs: `@own(.active)`.
|
|
44
|
+
- Tree-structural pseudo-classes: `:root`, `:scope`, `:empty`, `:has()`,
|
|
45
|
+
`:first-child`, `:last-child`, `:only-child`, their `-of-type` forms, and
|
|
46
|
+
`:nth-*()`.
|
|
47
|
+
- Any key that combines one of these with other states, such as
|
|
48
|
+
`@own(:hover | [open])` or `:focus & @own([open])`. Tasty drops the whole key.
|
|
49
|
+
|
|
50
|
+
## Preferred
|
|
51
|
+
|
|
52
|
+
Write a condition on the element the pseudo-element belongs to in `$`, before
|
|
53
|
+
the pseudo-element. `tasty/no-state-in-selector` accepts these selectors.
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
const Pagination = tasty({
|
|
57
|
+
styles: {
|
|
58
|
+
NextArrow: { $: 'a[rel="next"]::before', content: '"→"' },
|
|
59
|
+
Marker: { $: 'li:last-child::marker', color: '#accent' },
|
|
60
|
+
Label: {
|
|
61
|
+
$: '@::part(label)',
|
|
62
|
+
color: { '': '#text', '@own(:hover)': '#active' },
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
A pseudo-element can be in a pseudo-class state such as `:hover` or `:focus`, so
|
|
69
|
+
those still belong in `@own(...)`. Root states, `@parent(...)`, `@root(...)`, and
|
|
70
|
+
at-rule conditions describe other elements and are not reported.
|
|
71
|
+
|
|
72
|
+
## Where it applies
|
|
73
|
+
|
|
74
|
+
- A sub-element `$` item that ends in a pseudo-element: the first `::name`, or a
|
|
75
|
+
legacy `:before`, `:after`, `:first-line`, or `:first-letter`, in its last
|
|
76
|
+
compound. Each item of a `$` list is judged on its own. With
|
|
77
|
+
`$: 'summary::marker, summary'`, Tasty ignores `@own([open])` only on
|
|
78
|
+
`summary::marker`, and the message names that item.
|
|
79
|
+
- `&` keys and `&`-prefixed `$` values extend their owner's selector. `'&::before'`
|
|
80
|
+
at the root, and `'&:hover'` under `$: 'a::before'`, are pseudo-element targets.
|
|
81
|
+
- A selector-mode call whose literal selector ends in a pseudo-element, such as
|
|
82
|
+
`useGlobalStyles('.card::before', styles)` or `tastyStatic('.card::before',
|
|
83
|
+
styles)`. There, root states describe the pseudo-element too, so
|
|
84
|
+
`[data-on]`, `selected`, and `.dark` are reported, while `:hover` is not.
|
|
85
|
+
|
|
86
|
+
## Limits
|
|
87
|
+
|
|
88
|
+
- `@name` state aliases are not resolved. Tasty may still ignore a state an
|
|
89
|
+
alias expands to.
|
|
90
|
+
- Dynamic `$` values and selector arguments are skipped. Malformed state keys
|
|
91
|
+
are left to `tasty/valid-state-key`.
|
|
92
|
+
- The rule has no autofix. Moving a condition into `$` changes which element
|
|
93
|
+
every property of that sub-element applies to, so the author must choose.
|
|
94
|
+
|
|
95
|
+
## Options
|
|
96
|
+
|
|
97
|
+
None.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# tasty/no-important
|
|
2
|
+
|
|
3
|
+
Reports `!important` in a style value.
|
|
4
|
+
|
|
5
|
+
**Presets:** error in recommended and strict. **Fix:** autofix (removes `!important`).
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
Tasty manages specificity itself, through doubled class selectors and the order of states. `!important` overrides that system: states and extensions can no longer win where they should.
|
|
10
|
+
|
|
11
|
+
## Examples
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
// ❌ Do not use !important in tasty styles.
|
|
15
|
+
fill: '#red !important'
|
|
16
|
+
|
|
17
|
+
// ✅ After the autofix
|
|
18
|
+
fill: '#red'
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
To make a state win, give it a later place in the state map, or combine conditions in its key.
|
|
22
|
+
|
|
23
|
+
## Options
|
|
24
|
+
|
|
25
|
+
None.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# tasty/no-nested-selector
|
|
2
|
+
|
|
3
|
+
Reports `&`-prefixed nested selectors, such as `'& img'` or `'&:hover'`, as keys of a style object.
|
|
4
|
+
|
|
5
|
+
**Presets:** error in recommended and strict. **Fix:** none.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
Nested selectors are legacy syntax. Sub-elements (capitalized keys that target `data-element`) and state maps are more explicit and compose: Tasty resolves their priority, and `mergeStyles` and extensions merge them per key.
|
|
10
|
+
|
|
11
|
+
## Examples
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
// ❌ Avoid nested selectors. Use sub-element styling instead.
|
|
15
|
+
tasty({
|
|
16
|
+
styles: {
|
|
17
|
+
'& img': { width: '100%' },
|
|
18
|
+
'&:hover': { fill: '#blue' },
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// ✅ A sub-element
|
|
23
|
+
tasty({
|
|
24
|
+
styles: {
|
|
25
|
+
Image: { width: '100%' },
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// ✅ A state map for a pseudo-class
|
|
30
|
+
tasty({
|
|
31
|
+
styles: {
|
|
32
|
+
fill: { '': '#white', ':hover': '#blue' },
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Options
|
|
38
|
+
|
|
39
|
+
None.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# tasty/no-nested-state-map
|
|
2
|
+
|
|
3
|
+
Reports a state map inside another state map.
|
|
4
|
+
|
|
5
|
+
**Presets:** error in recommended and strict. **Fix:** none.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
A state map's keys are states and its values are style values. Tasty does not read a map as a value, so the nested map renders nothing. Combine the states in one key instead.
|
|
10
|
+
|
|
11
|
+
## Examples
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
// ❌ Nested state maps are not allowed. Use combined state keys instead.
|
|
15
|
+
fill: {
|
|
16
|
+
'': '#white',
|
|
17
|
+
hovered: {
|
|
18
|
+
'': '#blue',
|
|
19
|
+
pressed: '#red',
|
|
20
|
+
},
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ✅ Combined states
|
|
24
|
+
fill: {
|
|
25
|
+
'': '#white',
|
|
26
|
+
hovered: '#blue',
|
|
27
|
+
'hovered & pressed': '#red',
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Options
|
|
32
|
+
|
|
33
|
+
None.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# tasty/no-own-at-root
|
|
2
|
+
|
|
3
|
+
Reports `@own(...)` in a state key of the root styles, where it is redundant.
|
|
4
|
+
|
|
5
|
+
**Presets:** warning in recommended and strict. **Fix:** autofix.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
`@own(...)` says "this state belongs to the sub-element itself, not to the root". At the root, the element is the root, so `@own(:hover)` means the same as `:hover`. Writing it there suggests a difference that does not exist.
|
|
10
|
+
|
|
11
|
+
## Examples
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
// ❌ @own() is redundant outside sub-element styles.
|
|
15
|
+
tasty({
|
|
16
|
+
styles: {
|
|
17
|
+
fill: { '': '#white', '@own(:hover)': '#blue' },
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// ✅ After the autofix
|
|
22
|
+
tasty({
|
|
23
|
+
styles: {
|
|
24
|
+
fill: { '': '#white', ':hover': '#blue' },
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// ✅ In a sub-element, @own() is the sub-element's own state
|
|
29
|
+
tasty({
|
|
30
|
+
styles: {
|
|
31
|
+
Icon: {
|
|
32
|
+
fill: { '': '#white', '@own(:hover)': '#blue' },
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Autofix
|
|
39
|
+
|
|
40
|
+
The fix unwraps every `@own(...)` term of the key and keeps a term with operators inside grouped:
|
|
41
|
+
|
|
42
|
+
| Before | After |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| `'@parent(:hover) & !@own(:hover)'` | `'@parent(:hover) & !:hover'` |
|
|
45
|
+
| `'@own(pin=start \| pin=end)'` | `'pin=start \| pin=end'` |
|
|
46
|
+
| `'@own(hovered \| focused) & active'` | `'(hovered \| focused) & active'` |
|
|
47
|
+
|
|
48
|
+
A key with a comma inside `@own(...)` is reported without a fix.
|
|
49
|
+
|
|
50
|
+
## Not reported
|
|
51
|
+
|
|
52
|
+
- Sub-element styles, at any depth.
|
|
53
|
+
- Shared style objects, such as a `const CELL_STYLES: Styles = { … }` that may be spread into a sub-element, where `@own(...)` matters.
|
|
54
|
+
|
|
55
|
+
## Options
|
|
56
|
+
|
|
57
|
+
None.
|