design-scale-value
| Field | Value |
|---|---|
| Tool | ESLint |
| Enable via | design() factory |
| Rule ID | house-rules/design-scale-value |
| Type | suggestion |
| Autofix | no |
| Source | packages/rules/src/design-scale-value.mjs |
| Docs | packages/rules/docs/design-scale-value.md |
What it catches
Section titled “What it catches”CSS values off a fixed scale.
In one line
Section titled “In one line”Require values of chosen properties to come from a fixed scale or from a token variable.
Messages
Section titled “Messages”offScale: {{property}} “{{value}}” has values off the scale: {{parts}}. Allowed: {{allowed}}.needsVar: {{property}} “{{value}}”: every layer must use var({{prefix}}…).needsVarOrScale: {{property}} “{{value}}”: every layer must use var({{prefix}}…) or be one of: {{allowed}}.
Default options
Section titled “Default options”[ []]Rule docs
Section titled “Rule docs”From packages/rules/docs/design-scale-value.md.
Rule ID: house-rules/design-scale-value
The rule runs on the @eslint/css language. For the properties you list, it requires each value to come from a fixed scale or from a token variable. It does nothing until you configure it. Use the @house-rules/rules/design factory to enable it.
design({ tokenFiles: ["apps/web/src/styles/hosti.css"], rules: { "design-scale-value": [ { property: "^border(-.+)?-radius$", allowed: ["2px", "3px", "4px", "6px", "8px", "999px"] }, { property: "^(box|text)-shadow$", allowed: ["none"] }, { property: "^(transition|animation)(-duration)?$", allowed: ["none"], requireVar: "--t" }, ], },});a { border-radius: 6px; } /* passes */a { border-radius: 2px 2px 0 0; } /* reported: 0 is off the scale */a { transition: color var(--t) ease; } /* passes */a { transition: opacity 420ms ease-out; } /* reported: no var(--t…) */Options
Section titled “Options”The single option is an array of entries:
type Options = [ Array<{ property: string; // a regular expression, tested against the property name allowed?: string[]; // values on the scale requireVar?: string; // a custom-property prefix, starting with "--" }>,];Each entry needs allowed, requireVar, or both. property is not anchored, so write ^ and $ yourself. The first entry whose property matches a declaration applies; later entries are ignored for it. Custom-property declarations are never checked, because they define tokens.
A value always passes when it is a CSS-wide keyword (inherit, initial, unset, revert, revert-layer) or appears whole in allowed. Comparison ignores case and collapses whitespace.
Without requireVar
Section titled “Without requireVar”The value is split on spaces, slashes and commas outside parentheses. Each part must be in allowed, or use any var(). So border-radius: var(--radius) 4px and calc(var(--radius) - 2px) pass when 4px is allowed.
Message: border-radius "2px 2px 0 0" has values off the scale: 0. Allowed: 2px, 3px, ….
With requireVar
Section titled “With requireVar”The value is split into comma-separated layers, such as the transitions in a transition list. Each layer must be in allowed or use a var() whose name starts with the prefix. requireVar: "--t" accepts var(--t) and var(--t-slow). It also accepts var(--text), since this is a prefix match.
Message: transition "opacity 420ms ease-out": every layer must use var(--t…). When allowed is also set, the message lists it.
transition: none has no token. Add "none" to allowed if your code uses it, as in the example above.
The rule reports once per declaration, over the whole value.
Limitations
Section titled “Limitations”0is a value like any other. Add"0"toallowedwhen zero radius is on your scale.- The rule does not check that a
var()it accepts exists.design-no-unknown-tokendoes that. - The rule has no autofix.