prefer-resolved-vars

Github

Disallow reading a component's public CSS var as a value.


A component's public vars are for overriding it: an app sets them, the component never does. Reading one as a value gives you nothing unless an app has set it. To use a component's current value, such as an icon's size or a panel's padding, read resolvedVars, which falls back to the component's own default.

The rule fixes X.vars.y to X.resolvedVars.y when the component has that resolved var. When it doesn't, set the value you need directly.

Incorrect

import { style } from '@vanilla-extract/css';
import { calc } from '@vanilla-extract/css-utils';
import { PlumaIcon, PlumaModal, PlumaPanel } from '@customerio/pluma-components/css/components';

export const icon = style({ fontSize: `${PlumaIcon.vars.size} !important` });
export const toolbar = style({ borderTopRightRadius: PlumaPanel.vars.panelBorderRadius });
export const bleed = style({ marginInline: calc(PlumaModal.vars.modalPadding).negate().toString() });
import { PlumaModal as PlumaModalCss } from '@customerio/pluma-components/css/components';

<template>
	<div style='margin-inline: calc(-1 * {{PlumaModalCss.vars.modalPadding}});'>…</div>
</template>

Correct

import { style } from '@vanilla-extract/css';
import { calc } from '@vanilla-extract/css-utils';
import { PlumaIcon, PlumaModal, PlumaPanel } from '@customerio/pluma-components/css/components';

export const icon = style({ fontSize: `${PlumaIcon.resolvedVars.size} !important` });
export const toolbar = style({ borderTopRightRadius: PlumaPanel.resolvedVars.panelBorderRadius });
export const bleed = style({ marginInline: calc(PlumaModal.resolvedVars.modalPadding).negate().toString() });

// Setting a public var is what it is for.
export const largeIcons = style({ vars: { [PlumaIcon.vars.size]: '24px' } });
import { PlumaModal as PlumaModalCss } from '@customerio/pluma-components/css/components';

<template>
	<div style='margin-inline: calc(-1 * {{PlumaModalCss.resolvedVars.modalPadding}});'>…</div>
</template>

What is checked

The rule looks at the vars of the style exports imported from @customerio/pluma-components/css/components, including renamed imports (PlumaIcon as PlumaIconCss), namespace imports, aliases such as const iconVars = PlumaIcon.vars, and paths in Ember templates.

A var is allowed where the code uses its name:

  • as a computed key, which sets it: { [PlumaIcon.vars.size]: '20px' } in style, vars, assignInlineVars or a style prop, and styles[PlumaIcon.vars.size] = '20px';
  • as the argument to getVarName;
  • with a string method called on it, such as PlumaIcon.vars.size.slice(4, -1).

Every other use is reported, including a property value, a template literal, a calc or fallbackVar argument, and an Ember template. A const that holds a var is reported where it's declared when any of its uses is a value. An exported const is reported with a suggestion in place of a fix, because another file may use it to set the var.

A var inside fallbackVar(...) is not fixed automatically. The rule suggests replacing the whole call with the resolved var, which uses the component's default in place of yours.

On this page