commit 1fd5f4ea8bc7ac5c731a59a5b20f83a78c1ea418
parent 3a85ab8934c58e7de653013d6679bd6072f39d99
Author: Jon Oliver <jooliver@mozilla.com>
Date: Mon, 6 Oct 2025 17:20:53 +0000
Bug 1984177 - add font-size stylelint rule r=frontend-codestyle-reviewers,akulyk
- Add use-font-size-tokens stylelint rule
- Add tests for use-font-size-tokens rule
- Add docs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-font-size-tokens.rst
- Update stylelint rollouts with exclusions for use-font-size-tokens rule
Differential Revision: https://phabricator.services.mozilla.com/D267249
Diffstat:
9 files changed, 625 insertions(+), 2 deletions(-)
diff --git a/.stylelintrc.js b/.stylelintrc.js
@@ -272,6 +272,7 @@ module.exports = {
"stylelint-plugin-mozilla/no-base-design-tokens": true,
"stylelint-plugin-mozilla/use-border-radius-tokens": true,
"stylelint-plugin-mozilla/use-border-color-tokens": true,
+ "stylelint-plugin-mozilla/use-font-size-tokens": true,
},
overrides: [
@@ -414,6 +415,7 @@ module.exports = {
rules: {
"stylelint-plugin-mozilla/use-border-radius-tokens": false,
"stylelint-plugin-mozilla/use-border-color-tokens": false,
+ "stylelint-plugin-mozilla/use-font-size-tokens": false,
},
},
{
diff --git a/docs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-font-size-tokens.rst b/docs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-font-size-tokens.rst
@@ -0,0 +1,200 @@
+========================
+use-font-size-tokens
+========================
+
+This rule checks that CSS declarations use font-size design token variables
+instead of hardcoded values. This ensures consistent font-size usage across
+the application and makes it easier to maintain design system consistency.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: css
+
+ .custom-text {
+ font-size: 12px;
+ }
+
+.. code-block:: css
+
+ .heading {
+ font-size: 1rem;
+ }
+
+.. code-block:: css
+
+ .small-text {
+ font-size: 0.867rem;
+ }
+
+.. code-block:: css
+
+ .large-text {
+ font-size: 1.2em;
+ }
+
+.. code-block:: css
+
+ .percentage-text {
+ font-size: 100%;
+ }
+
+.. code-block:: css
+
+ .point-text {
+ font-size: 16pt;
+ }
+
+Examples of correct token usage for this rule:
+----------------------------------------------
+
+.. code-block:: css
+
+ .custom-text {
+ font-size: var(--font-size-root);
+ }
+
+.. code-block:: css
+
+ .small-text {
+ font-size: var(--font-size-small);
+ }
+
+.. code-block:: css
+
+ .large-text {
+ font-size: var(--font-size-large);
+ }
+
+.. code-block:: css
+
+ .xlarge-text {
+ font-size: var(--font-size-xlarge);
+ }
+
+.. code-block:: css
+
+ .xxlarge-text {
+ font-size: var(--font-size-xxlarge);
+ }
+
+.. code-block:: css
+
+ .xxxlarge-text {
+ font-size: var(--font-size-xxxlarge);
+ }
+
+.. code-block:: css
+
+ .heading-medium {
+ font-size: var(--heading-font-size-medium);
+ }
+
+.. code-block:: css
+
+ .heading-large {
+ font-size: var(--heading-font-size-large);
+ }
+
+.. code-block:: css
+
+ .heading-xlarge {
+ font-size: var(--heading-font-size-xlarge);
+ }
+
+.. code-block:: css
+
+ /* Local CSS variables that reference valid font-size tokens are allowed */
+ :root {
+ --custom-font-size: var(--font-size-small);
+ }
+
+ .custom-text {
+ font-size: var(--custom-font-size);
+ }
+
+.. code-block:: css
+
+ .custom-text {
+ font-size: var(--custom-font-size, var(--font-size-small));
+ }
+
+The rule also allows these non-token values:
+
+.. code-block:: css
+
+ .xxsmall-text {
+ font-size: xxsmall;
+ }
+
+.. code-block:: css
+
+ .xsmall-text {
+ font-size: xsmall;
+ }
+
+.. code-block:: css
+
+ .small-text {
+ font-size: small;
+ }
+
+.. code-block:: css
+
+ .medium-text {
+ font-size: medium;
+ }
+
+.. code-block:: css
+
+ .large-text {
+ font-size: large;
+ }
+
+.. code-block:: css
+
+ .xlarge-text {
+ font-size: x-large;
+ }
+
+.. code-block:: css
+
+ .xxlarge-text {
+ font-size: xx-large;
+ }
+
+.. code-block:: css
+
+ .xxxlarge-text {
+ font-size: xxx-large;
+ }
+
+.. code-block:: css
+
+ .smaller-text {
+ font-size: smaller;
+ }
+
+.. code-block:: css
+
+ .larger-text {
+ font-size: larger;
+ }
+
+.. code-block:: css
+
+ .inherited-text {
+ font-size: inherit;
+ }
+
+.. code-block:: css
+
+ .initial-text {
+ font-size: initial;
+ }
+
+.. code-block:: css
+
+ .unset-text {
+ font-size: unset;
+ }
diff --git a/stylelint-rollouts.config.js b/stylelint-rollouts.config.js
@@ -324,4 +324,138 @@ module.exports = [
"toolkit/themes/windows/mozapps/update/updates.css",
],
},
+ {
+ // stylelint fixes for this rule will be addressed in Bug 1992411
+ name: "rollout-use-font-size-tokens",
+ rules: {
+ "stylelint-plugin-mozilla/use-font-size-tokens": null,
+ },
+ files: [
+ "browser/base/content/aboutDialog.css",
+ "browser/branding/aurora/stubinstaller/installing_page.css",
+ "browser/branding/aurora/stubinstaller/profile_cleanup_page.css",
+ "browser/branding/nightly/stubinstaller/installing_page.css",
+ "browser/branding/nightly/stubinstaller/profile_cleanup_page.css",
+ "browser/branding/official/stubinstaller/installing_page.css",
+ "browser/branding/official/stubinstaller/profile_cleanup_page.css",
+ "browser/branding/unofficial/stubinstaller/installing_page.css",
+ "browser/branding/unofficial/stubinstaller/profile_cleanup_page.css",
+ "browser/components/aboutlogins/content/aboutLoginsImportReport.css",
+ "browser/components/aboutlogins/content/components/confirmation-dialog.css",
+ "browser/components/aboutlogins/content/components/generic-dialog.css",
+ "browser/components/aboutlogins/content/components/login-alert.css",
+ "browser/components/aboutlogins/content/components/login-item.css",
+ "browser/components/aboutlogins/content/components/login-list-lit-item.css",
+ "browser/components/aboutlogins/content/components/login-list.css",
+ "browser/components/aboutlogins/content/components/login-message-popup.css",
+ "browser/components/aboutlogins/content/components/remove-logins-dialog.css",
+ "browser/components/aboutwelcome/content-src/aboutwelcome.scss",
+ "browser/components/asrouter/content-src/components/ASRouterAdmin/ASRouterAdmin.scss",
+ "browser/components/asrouter/content-src/styles/_feature-callout.scss",
+ "browser/components/backup/content/password-rules-tooltip.css",
+ "browser/components/firefoxview/card-container.css",
+ "browser/components/firefoxview/history.css",
+ "browser/components/firefoxview/view-syncedtabs.css",
+ "browser/components/genai/chat.css",
+ "browser/components/genai/content/link-preview-card.css",
+ "browser/components/messagepreview/messagepreview.css",
+ "browser/components/protections/content/protections.css",
+ "browser/components/screenshots/overlay/overlay.css",
+ "browser/components/search/content/contentSearchUI.css",
+ "browser/components/search/test/browser/telemetry/serp.css",
+ "browser/components/sidebar/sidebar-panel-header.css",
+ "browser/components/urlbar/tests/browser/dynamicResult0.css",
+ "browser/components/urlbar/tests/browser/dynamicResult1.css",
+ "browser/extensions/formautofill/skin/shared/editAddress.css",
+ "browser/extensions/formautofill/skin/shared/editDialog-shared.css",
+ "browser/extensions/newtab/content-src/components/Card/_Card.scss",
+ "browser/extensions/newtab/content-src/components/CollapsibleSection/_CollapsibleSection.scss",
+ "browser/extensions/newtab/content-src/components/ContextMenu/_ContextMenu.scss",
+ "browser/extensions/newtab/content-src/components/DiscoveryStreamBase/_DiscoveryStreamBase.scss",
+ "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/DSCard/_DSCard.scss",
+ "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/DSMessage/_DSMessage.scss",
+ "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/PromoCard/_PromoCard.scss",
+ "browser/extensions/newtab/content-src/components/ErrorBoundary/_ErrorBoundary.scss",
+ "browser/extensions/newtab/content-src/components/TopSites/_TopSites.scss",
+ "browser/extensions/newtab/content-src/components/Weather/_Weather.scss",
+ "browser/extensions/newtab/content-src/styles/_mixins.scss",
+ "browser/extensions/webcompat/about-compat/aboutCompat.css",
+ "browser/themes/linux/browser.css",
+ "browser/themes/osx/browser.css",
+ "browser/themes/osx/customizableui/panelUI.css",
+ "browser/themes/shared/UITour.css",
+ "browser/themes/shared/autocomplete.css",
+ "browser/themes/shared/browser-shared.css",
+ "browser/themes/shared/controlcenter/panel.css",
+ "browser/themes/shared/customizableui/customizeMode.css",
+ "browser/themes/shared/customizableui/panelUI-shared.css",
+ "browser/themes/shared/downloads/allDownloadsView.inc.css",
+ "browser/themes/shared/downloads/downloads.inc.css",
+ "browser/themes/shared/formautofill-notification.css",
+ "browser/themes/shared/identity-credential-notification.css",
+ "browser/themes/shared/migration/migration-wizard.css",
+ "browser/themes/shared/notification-icons.css",
+ "browser/themes/shared/places/editBookmark.css",
+ "browser/themes/shared/places/editBookmarkPanel.css",
+ "browser/themes/shared/places/sidebar.css",
+ "browser/themes/shared/preferences/fxaPairDevice.css",
+ "browser/themes/shared/preferences/preferences.css",
+ "browser/themes/shared/preferences/privacy.css",
+ "browser/themes/shared/preferences/siteDataSettings.css",
+ "browser/themes/shared/privatebrowsing/aboutPrivateBrowsing.css",
+ "browser/themes/shared/sidebar.css",
+ "browser/themes/shared/syncedtabs/sidebar.css",
+ "browser/themes/shared/tabbrowser/fullscreen-and-pointerlock.css",
+ "browser/themes/shared/tabbrowser/tabs.css",
+ "browser/themes/shared/translations/panel.css",
+ "browser/themes/shared/urlbar-dynamic-results.css",
+ "browser/themes/shared/urlbar-searchbar.css",
+ "browser/themes/shared/urlbarView.css",
+ "browser/themes/windows/browser.css",
+ "dom/crypto/test/test_WebCrypto.css",
+ "dom/xml/test/old/books/classic.css",
+ "dom/xml/test/old/books/common.css",
+ "dom/xml/test/old/books/list.css",
+ "layout/generic/test/frame_selection_underline.css",
+ "layout/mathml/mathml.css",
+ "layout/style/res/html.css",
+ "layout/style/res/ua.css",
+ "testing/mochitest/static/harness.css",
+ "testing/mozbase/mozlog/mozlog/formatters/html/style.css",
+ "testing/talos/talos/tests/scroll/reader.css",
+ "toolkit/components/aboutinference/content/aboutInference.css",
+ "toolkit/components/aboutmemory/content/aboutMemory.css",
+ "toolkit/components/aboutprocesses/content/aboutProcesses.css",
+ "toolkit/components/aboutthirdparty/content/aboutThirdParty.css",
+ "toolkit/components/aboutwebauthn/content/aboutWebauthn.css",
+ "toolkit/components/certviewer/content/components/certificate-section.css",
+ "toolkit/components/certviewer/content/components/info-group.css",
+ "toolkit/components/certviewer/content/components/info-item.css",
+ "toolkit/components/certviewer/content/components/list-item.css",
+ "toolkit/components/normandy/content/about-studies/about-studies.css",
+ "toolkit/components/printing/content/simplifyMode.css",
+ "toolkit/components/satchel/megalist/content/components/login-line/login-line.css",
+ "toolkit/content/aboutLogging/aboutLogging.css",
+ "toolkit/content/aboutMozilla.css",
+ "toolkit/content/aboutTelemetry.css",
+ "toolkit/content/aboutwebrtc/aboutWebrtc.css",
+ "toolkit/content/widgets/moz-input-text/moz-input-text.css",
+ "toolkit/mozapps/extensions/content/aboutaddons.css",
+ "toolkit/themes/mobile/global/aboutMemory.css",
+ "toolkit/themes/shared/aboutHttpsOnlyError.css",
+ "toolkit/themes/shared/aboutNetError.css",
+ "toolkit/themes/shared/aboutReader.css",
+ "toolkit/themes/shared/alert.css",
+ "toolkit/themes/shared/datetimeinputpickers.css",
+ "toolkit/themes/shared/dirListing/dirListing.css",
+ "toolkit/themes/shared/error-pages.css",
+ "toolkit/themes/shared/in-content/common-shared.css",
+ "toolkit/themes/shared/narrate.css",
+ "toolkit/themes/shared/offlineSupportPages.css",
+ "toolkit/themes/shared/pictureinpicture/player.css",
+ "toolkit/themes/shared/pictureinpicture/texttracks.css",
+ "toolkit/themes/shared/toolbarbutton.css",
+ "tools/tryselect/selectors/chooser/static/style.css",
+ ],
+ },
];
diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/helpers.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/helpers.mjs
@@ -10,6 +10,13 @@ import valueParser from "postcss-value-parser";
import { tokensTable } from "../../../../toolkit/themes/shared/design-system/tokens-table.mjs";
/**
+ * Allows rules to access the tokens table without hard-coding the import path in multiple files.
+ *
+ * @returns {object}
+ */
+export const getTokensTable = () => tokensTable;
+
+/**
* Our namespace used to prefix Mozilla stylelint rules.
*/
const MOZILLA_NAMESPACE = "stylelint-plugin-mozilla";
diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/rules/index.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/rules/index.mjs
@@ -9,9 +9,11 @@
import noBaseDesignTokens from "./no-base-design-tokens.mjs";
import useBorderRadiusTokens from "./use-border-radius-tokens.mjs";
import useBorderColorTokens from "./use-border-color-tokens.mjs";
+import useFontSizeTokens from "./use-font-size-tokens.mjs";
export default {
"no-base-design-tokens": noBaseDesignTokens,
"use-border-radius-tokens": useBorderRadiusTokens,
"use-border-color-tokens": useBorderColorTokens,
+ "use-font-size-tokens": useFontSizeTokens,
};
diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/rules/use-font-size-tokens.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/rules/use-font-size-tokens.mjs
@@ -0,0 +1,93 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import stylelint from "stylelint";
+import {
+ createTokenNamesArray,
+ createAllowList,
+ getLocalCustomProperties,
+ isValidTokenUsage,
+ namespace,
+} from "../helpers.mjs";
+
+const {
+ utils: { report, ruleMessages, validateOptions },
+} = stylelint;
+
+const ruleName = namespace("use-font-size-tokens");
+
+const messages = ruleMessages(ruleName, {
+ rejected: value => `${value} should use a font-size design token.`,
+});
+
+const meta = {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-font-size-tokens.html",
+ fixable: false,
+};
+
+const PROPERTY_NAME = "font-size";
+
+const tokenCSS = createTokenNamesArray([PROPERTY_NAME]);
+
+const ALLOW_LIST = createAllowList([
+ "xx-small",
+ "x-small",
+ "small",
+ "medium",
+ "large",
+ "x-large",
+ "xx-large",
+ "xxx-large",
+ "smaller",
+ "larger",
+ "inherit",
+ "initial",
+ "unset",
+]);
+
+const ruleFunction = primaryOption => {
+ return (root, result) => {
+ const validOptions = validateOptions(result, ruleName, {
+ actual: primaryOption,
+ possible: [true],
+ });
+
+ if (!validOptions) {
+ return;
+ }
+
+ const cssCustomProperties = getLocalCustomProperties(root);
+
+ root.walkDecls(declarations => {
+ // ignore properties other than font-size
+ if (declarations.prop !== PROPERTY_NAME) {
+ return;
+ }
+
+ if (
+ isValidTokenUsage(
+ declarations.value,
+ tokenCSS,
+ cssCustomProperties,
+ ALLOW_LIST
+ )
+ ) {
+ return;
+ }
+
+ report({
+ message: messages.rejected(declarations.value),
+ node: declarations,
+ result,
+ ruleName,
+ });
+ });
+ };
+};
+
+ruleFunction.ruleName = ruleName;
+ruleFunction.messages = messages;
+ruleFunction.meta = meta;
+
+export default ruleFunction;
diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/tests/use-border-color-tokens.tests.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/tests/use-border-color-tokens.tests.mjs
@@ -1,7 +1,7 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/PL/2.0/.
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// Bug 1948378: remove this exception when the eslint import plugin fully
diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/tests/use-border-radius-tokens.tests.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/tests/use-border-radius-tokens.tests.mjs
@@ -1,7 +1,7 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/PL/2.0/.
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// Bug 1948378: remove this exception when the eslint import plugin fully
diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/tests/use-font-size-tokens.tests.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/tests/use-font-size-tokens.tests.mjs
@@ -0,0 +1,185 @@
+/**
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+// Bug 1948378: remove this exception when the eslint import plugin fully
+// supports exports in package.json files
+// eslint-disable-next-line import/no-unresolved
+import { testRule } from "stylelint-test-rule-node";
+import stylelint from "stylelint";
+import useFontSizeTokens from "../rules/use-font-size-tokens.mjs";
+
+let plugin = stylelint.createPlugin(
+ useFontSizeTokens.ruleName,
+ useFontSizeTokens
+);
+let {
+ ruleName,
+ rule: { messages },
+} = plugin;
+
+testRule({
+ plugins: [plugin],
+ ruleName,
+ config: [true, { tokenType: "brand" }],
+ fix: false,
+ accept: [
+ // allowed token values
+ {
+ code: ".a { font-size: var(--font-size-root); }",
+ description: "Using root font-size token is valid.",
+ },
+ {
+ code: ".a { font-size: var(--font-size-xsmall); }",
+ description: "Using xsmall font-size token is valid.",
+ },
+ {
+ code: ".a { font-size: var(--font-size-small); }",
+ description: "Using small font-size token is valid.",
+ },
+ {
+ code: ".a { font-size: var(--font-size-large); }",
+ description: "Using large font-size token is valid.",
+ },
+ {
+ code: ".a { font-size: var(--font-size-xlarge); }",
+ description: "Using xlarge font-size token is valid.",
+ },
+ {
+ code: ".a { font-size: var(--font-size-xxlarge); }",
+ description: "Using xxlarge font-size token is valid.",
+ },
+ {
+ code: ".a { font-size: var(--font-size-xxxlarge); }",
+ description: "Using xxxlarge font-size token is valid.",
+ },
+ {
+ code: ".a { font-size: var(--heading-font-size-medium); }",
+ description: "Using heading-font-size-medium token is valid.",
+ },
+ {
+ code: ".a { font-size: var(--heading-font-size-large); }",
+ description: "Using heading-font-size-large token is valid.",
+ },
+ {
+ code: ".a { font-size: var(--heading-font-size-xlarge); }",
+ description: "Using heading-font-size-xlarge token is valid.",
+ },
+ // allowed CSS values
+ {
+ code: ".a { font-size: xx-small; }",
+ description: "Using xx-small keyword is valid.",
+ },
+ {
+ code: ".a { font-size: x-small; }",
+ description: "Using x-small keyword is valid.",
+ },
+ {
+ code: ".a { font-size: small; }",
+ description: "Using small keyword is valid.",
+ },
+ {
+ code: ".a { font-size: medium; }",
+ description: "Using medium keyword is valid.",
+ },
+ {
+ code: ".a { font-size: large; }",
+ description: "Using large keyword is valid.",
+ },
+ {
+ code: ".a { font-size: x-large; }",
+ description: "Using x-large keyword is valid.",
+ },
+ {
+ code: ".a { font-size: xx-large; }",
+ description: "Using xx-large keyword is valid.",
+ },
+ {
+ code: ".a { font-size: xxx-large; }",
+ description: "Using xxx-large keyword is valid.",
+ },
+ {
+ code: ".a { font-size: smaller; }",
+ description: "Using smaller keyword is valid.",
+ },
+ {
+ code: ".a { font-size: larger; }",
+ description: "Using larger keyword is valid.",
+ },
+ {
+ code: ".a { font-size: inherit; }",
+ description: "Using inherit is valid.",
+ },
+ {
+ code: ".a { font-size: initial; }",
+ description: "Using initial is valid.",
+ },
+ {
+ code: ".a { font-size: unset; }",
+ description: "Using unset is valid.",
+ },
+ {
+ code: ".a { font-size:var(--my-local, var(--font-size-small)); }",
+ description:
+ "Using a custom property with fallback to design token is valid.",
+ },
+ {
+ code: `
+ :root { --custom-token: var(--font-size-small); }
+ .a { font-size: var(--custom-token); }
+ `,
+ description:
+ "Using a custom property with fallback to a design token is valid.",
+ },
+ ],
+
+ reject: [
+ {
+ code: ".a { font-size: 12px; }",
+ message: messages.rejected("12px"),
+ description: "Using a pixel value should use a design token.",
+ },
+ {
+ code: ".a { font-size: 1rem; }",
+ message: messages.rejected("1rem"),
+ description: "Using a rem value should use a design token.",
+ },
+ {
+ code: ".a { font-size: 1.2em; }",
+ message: messages.rejected("1.2em"),
+ description: "Using an em value should use a design token.",
+ },
+ {
+ code: ".a { font-size: 100%; }",
+ message: messages.rejected("100%"),
+ description: "Using a percentage value should use a design token.",
+ },
+ {
+ code: ".a { font-size: 16pt; }",
+ message: messages.rejected("16pt"),
+ description: "Using a pt value should use a design token.",
+ },
+ {
+ code: ".a { font-size: calc(var(--my-local) + 2px); }",
+ message: messages.rejected("calc(var(--my-local) + 2px)"),
+ description:
+ "Using a calc() with custom variables should use a design token.",
+ },
+ {
+ code: ".a { font-size: var(--random-token, 14px); }",
+ message: messages.rejected("var(--random-token, 14px)"),
+ description: "Using a custom property should use a design token.",
+ },
+ {
+ code: `
+ :root { --custom-token: 14px; }
+ .a { font-size: var(--custom-token); }
+ `,
+ message: messages.rejected("var(--custom-token)"),
+ description:
+ "Using a custom property that does not resolve to a design token should use a design token.",
+ },
+ ],
+});