tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 7330b35e77a4f57d5a23e948a139716a94104a25
parent 56fcd87147b4c011be669fb3f7a109fc16121c1e
Author: Jon Oliver <jooliver@mozilla.com>
Date:   Thu, 11 Dec 2025 21:01:08 +0000

Bug 1994263: consolidate use-border-color-tokens stylelint rule with use-design-tokens rule r=mstriemer,frontend-codestyle-reviewers,desktop-theme-reviewers

- converts use-border-color-tokens rule to be configured via use-design-tokens rule
- updates tests and documentation for border-color portion of use-design-tokens rule

Differential Revision: https://phabricator.services.mozilla.com/D273903

Diffstat:
M.stylelintrc.js | 3---
Ddocs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-border-color-tokens.rst | 207-------------------------------------------------------------------------------
Adocs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-design-tokens/border-color.rst | 233+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mstylelint-rollouts.config.js | 166++++++++-----------------------------------------------------------------------
Mtoolkit/content/aboutLogging/aboutLogging.css | 4++--
Mtoolkit/themes/shared/arrowscrollbox.css | 2+-
Mtools/lint/stylelint/stylelint-plugin-mozilla/config.mjs | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtools/lint/stylelint/stylelint-plugin-mozilla/rules/index.mjs | 2--
Dtools/lint/stylelint/stylelint-plugin-mozilla/rules/use-border-color-tokens.mjs | 152-------------------------------------------------------------------------------
Dtools/lint/stylelint/stylelint-plugin-mozilla/tests/use-border-color-tokens.tests.mjs | 298-------------------------------------------------------------------------------
Atools/lint/stylelint/stylelint-plugin-mozilla/tests/use-design-tokens.border-color.tests.mjs | 401+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11 files changed, 770 insertions(+), 816 deletions(-)

diff --git a/.stylelintrc.js b/.stylelintrc.js @@ -275,7 +275,6 @@ module.exports = { "csstools/use-logical": null, "stylelint-plugin-mozilla/no-base-design-tokens": true, "stylelint-plugin-mozilla/use-design-tokens": true, - "stylelint-plugin-mozilla/use-border-color-tokens": true, "stylelint-plugin-mozilla/use-border-radius-tokens": true, "stylelint-plugin-mozilla/use-space-tokens": true, "stylelint-plugin-mozilla/no-non-semantic-token-usage": true, @@ -428,7 +427,6 @@ module.exports = { ], rules: { "stylelint-plugin-mozilla/use-design-tokens": null, - "stylelint-plugin-mozilla/use-border-color-tokens": null, "stylelint-plugin-mozilla/use-border-radius-tokens": null, "stylelint-plugin-mozilla/use-space-tokens": null, "stylelint-plugin-mozilla/no-non-semantic-token-usage": null, @@ -443,7 +441,6 @@ module.exports = { ], rules: { "stylelint-plugin-mozilla/use-design-tokens": true, - "stylelint-plugin-mozilla/use-border-color-tokens": true, "stylelint-plugin-mozilla/use-border-radius-tokens": true, "stylelint-plugin-mozilla/use-space-tokens": true, "stylelint-plugin-mozilla/no-non-semantic-token-usage": true, diff --git a/docs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-border-color-tokens.rst b/docs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-border-color-tokens.rst @@ -1,207 +0,0 @@ -======================= -use-border-color-tokens -======================= - -This rule checks that CSS declarations use border-color design token variables -instead of hard-coded values. This ensures consistent border-color across -the application and makes it easier to maintain design system adoption. - -Examples of incorrect code for this rule: ------------------------------------------ - -.. code-block:: css - - .card { - border-color: #191919; - } - -.. code-block:: css - - .custom-button { - border: 3px dashed rgba(42 42 42 / 0.15); - } - -.. code-block:: css - - button:hover { - outline-color: rgba(0 0 0 / 0.25); - } - -.. code-block:: css - - :root { - --my-token: blue; - } - - .my-button { - border: 1px solid var(--my-token, oklch(55% 0.21 15)); - } - -Examples of correct token usage for this rule: ----------------------------------------------- - -.. code-block:: css - - .card { - border-color: var(--border-color); - } - -.. code-block:: css - - .custom-button { - border: 3px dashed var(--border-color); - } - -.. code-block:: css - - button:hover { - outline-color: --outline-color; - } - -.. code-block:: css - - /* You may set a fallback for a token. */ - - .my-button { - border: 1px solid var(--border-color, oklch(55% 0.21 15)); - } - -.. code-block:: css - - /* Local CSS variables that reference valid border-radius tokens are allowed */ - - :root { - --my-token: var(--border-color); - } - - .my-button { - border: 1px solid var(--my-token, oklch(55% 0.21 15)); - } - -The rule also allows these values non-token values: - -.. code-block:: css - - .transparent-border-color { - border-color: transparent; - } - -.. code-block:: css - - .current-border-color { - border-color: currentColor; - } - -.. code-block:: css - - .white-border-color { - border-color: white; - } - -.. code-block:: css - - .black-border-color { - border-color: black; - } - -.. code-block:: css - - .inherited-border-color{ - border-colors: inherit; - } - -.. code-block:: css - - .unset-border-color { - border-color: unset; - } - -.. code-block:: css - - .initial-border-color { - border-color: initial; - } - -.. code-block:: css - - .current-border-color { - border-color: currentColor; - } - -Autofix functionality ---------------------- - -This rule can automatically fix some violations by replacing hex color values with -appropriate color names. Examples of autofixable violations: - -.. code-block:: css - - /* Before */ - .a { - border-color: #fff; - } - - /* After autofix */ - .a { - border-color: white; - } - -.. code-block:: css - - /* Before */ - .a { - border-color: #ffffff; - } - - /* After autofix */ - .a { - border-color: white; - } - -.. code-block:: css - - /* Before */ - .a { - border-color: #FFF; - } - - /* After autofix */ - .a { - border-color: white; - } - -.. code-block:: css - - /* Before */ - .a { - border-color: #FFFFFF; - } - - /* After autofix */ - .a { - border-color: white; - } - -.. code-block:: css - - /* Before */ - .a { - border-color: #000; - } - - /* After autofix */ - .a { - border-color: black; - } - -.. code-block:: css - - /* Before */ - .a { - border-color: #000000; - } - - /* After autofix */ - .a { - border-color: black; - } diff --git a/docs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-design-tokens/border-color.rst b/docs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-design-tokens/border-color.rst @@ -0,0 +1,233 @@ +============ +border-color +============ + +The ``use-design-tokens`` rule checks that CSS border-color related declarations +(border-color, border, outline, outline-color, and their variants) use design +token variables instead of hardcoded values. This ensures consistent border-color +usage across the application and makes it easier to maintain design system +consistency. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: css + + .card { + border-color: #191919; + } + +.. code-block:: css + + .custom-button { + border: 3px dashed rgba(42 42 42 / 0.15); + } + +.. code-block:: css + + .error { + outline-color: rgba(255 0 0 / 0.25); + } + +.. code-block:: css + + .element { + border-top-color: oklch(69% 0.19 15); + } + +.. code-block:: css + + :root { + --my-token: blue; + } + + .my-button { + border: 1px solid var(--my-token, oklch(55% 0.21 15)); + } + +Examples of correct token usage for this rule: +---------------------------------------------- + +.. code-block:: css + + .card { + border-color: var(--border-color); + } + +.. code-block:: css + + .custom-button { + border: 3px dashed var(--border-color); + } + +.. code-block:: css + + .error { + outline-color: var(--outline-color-error); + } + +.. code-block:: css + + /* You may set a fallback for a token. */ + + .my-button { + border: 1px solid var(--border-color, oklch(55% 0.21 15)); + } + +.. code-block:: css + + /* Local CSS variables that reference valid border-color tokens are allowed */ + + :root { + --my-token: var(--border-color); + } + + .my-button { + border: 1px solid var(--my-token); + } + +The rule also allows these non-token values: + +.. code-block:: css + + .transparent-border-color { + border-color: transparent; + } + +.. code-block:: css + + .current-border-color { + border-color: currentColor; + } + +.. code-block:: css + + .white-border-color { + border-color: white; + } + +.. code-block:: css + + .black-border-color { + border-color: black; + } + +.. code-block:: css + + .inherited-border-color { + border-color: inherit; + } + +.. code-block:: css + + .initial-border-color { + border-color: initial; + } + +.. code-block:: css + + .revert-border-color { + border-color: revert; + } + +.. code-block:: css + + .revert-layer-border-color { + border-color: revert-layer; + } + +.. code-block:: css + + .unset-border-color { + border-color: unset; + } + +.. code-block:: css + + .border-none { + border: none; + } + +.. code-block:: css + + .border-zero { + border: 0; + } + +Autofix functionality +--------------------- + +This rule can automatically fix some violations by replacing hex color values with +appropriate color names. Examples of autofixable violations: + +.. code-block:: css + + /* Before */ + .a { + border-color: #fff; + } + + /* After autofix */ + .a { + border-color: white; + } + +.. code-block:: css + + /* Before */ + .a { + border-color: #ffffff; + } + + /* After autofix */ + .a { + border-color: white; + } + +.. code-block:: css + + /* Before */ + .a { + border-color: #FFF; + } + + /* After autofix */ + .a { + border-color: white; + } + +.. code-block:: css + + /* Before */ + .a { + border-color: #FFFFFF; + } + + /* After autofix */ + .a { + border-color: white; + } + +.. code-block:: css + + /* Before */ + .a { + border-color: #000; + } + + /* After autofix */ + .a { + border-color: black; + } + +.. code-block:: css + + /* Before */ + .a { + border-color: #000000; + } + + /* After autofix */ + .a { + border-color: black; + } diff --git a/stylelint-rollouts.config.js b/stylelint-rollouts.config.js @@ -678,157 +678,6 @@ module.exports = [ ], }, { - name: "rollout-use-border-color-tokens", - rules: { - "stylelint-plugin-mozilla/use-border-color-tokens": null, - }, - files: [ - "browser/components/aboutlogins/content/components/confirmation-dialog.css", - "browser/components/aboutlogins/content/components/generic-dialog.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/enterprisepolicies/content/aboutPolicies.css", - "browser/components/firefoxview/card-container.css", - "browser/components/firefoxview/fxview-tab-row.css", - "browser/components/firefoxview/opentabs-tab-row.css", - "browser/components/firefoxview/view-syncedtabs.css", - "browser/components/genai/content/link-preview-card.css", - "browser/components/genai/content/model-optin.css", - "browser/components/ipprotection/content/ipprotection-content.css", - "browser/components/profiles/content/avatar.css", - "browser/components/profiles/content/profile-avatar-selector.css", - "browser/components/profiles/content/profile-card.css", - "browser/components/profiles/content/profiles-pages.css", - "browser/components/profiles/content/profiles-theme-card.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-customize.css", - "browser/components/sidebar/sidebar-main.css", - "browser/components/sidebar/sidebar-pins-promo.css", - "browser/components/textrecognition/textrecognition.css", - "browser/extensions/newtab/content-src/components/Card/_Card.scss", - "browser/extensions/newtab/content-src/components/ConfirmDialog/_ConfirmDialog.scss", - "browser/extensions/newtab/content-src/components/ContextMenu/_ContextMenu.scss", - "browser/extensions/newtab/content-src/components/CustomizeMenu/_CustomizeMenu.scss", - "browser/extensions/newtab/content-src/components/DiscoveryStreamAdmin/DiscoveryStreamAdmin.scss", - "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/DSCard/_DSCard.scss", - "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/DSEmptyState/_DSEmptyState.scss", - "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/InterestPicker/_InterestPicker.scss", - "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/Navigation/_Navigation.scss", - "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/ReportContent/ReportContent.scss", - "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/TopicSelection/_TopicSelection.scss", - "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/TopicsWidget/_TopicsWidget.scss", - "browser/extensions/newtab/content-src/components/ModalOverlay/_ModalOverlay.scss", - "browser/extensions/newtab/content-src/components/Search/_Search.scss", - "browser/extensions/newtab/content-src/components/Sections/_Sections.scss", - "browser/extensions/newtab/content-src/components/TopSites/_TopSites.scss", - "browser/extensions/newtab/content-src/components/WallpaperCategories/_WallpaperCategories.scss", - "browser/extensions/newtab/content-src/components/Weather/_Weather.scss", - "browser/extensions/newtab/content-src/styles/_mixins.scss", - "browser/extensions/newtab/content-src/styles/_variables.scss", - "browser/extensions/newtab/content-src/styles/activity-stream.scss", - "browser/themes/linux/browser.css", - "browser/themes/osx/browser.css", - "browser/themes/osx/places/organizer.css", - "browser/themes/shared/UITour.css", - "browser/themes/shared/addons/unified-extensions.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/downloads.inc.css", - "browser/themes/shared/identity-block/identity-block.css", - "browser/themes/shared/identity-credential-notification.css", - "browser/themes/shared/migration/migration-wizard.css", - "browser/themes/shared/pageInfo.css", - "browser/themes/shared/places/editBookmark.css", - "browser/themes/shared/places/sidebar.css", - "browser/themes/shared/preferences/containers-dialog.css", - "browser/themes/shared/preferences/preferences.css", - "browser/themes/shared/privatebrowsing/aboutPrivateBrowsing.css", - "browser/themes/shared/search/searchbar.css", - "browser/themes/shared/sidebar.css", - "browser/themes/shared/syncedtabs/sidebar.css", - "browser/themes/shared/tabbrowser/content-area.css", - "browser/themes/shared/tabbrowser/ctrlTab.css", - "browser/themes/shared/tabbrowser/tab-hover-preview.css", - "browser/themes/shared/tabbrowser/tabs.css", - "browser/themes/shared/toolbarbuttons.css", - "browser/themes/shared/urlbar-dynamic-results.css", - "browser/themes/shared/urlbar-searchbar.css", - "browser/themes/shared/urlbarView.css", - "browser/themes/shared/webRTC-indicator.css", - "browser/themes/windows/browser.css", - "browser/themes/windows/downloads/allDownloadsView.css", - "browser/themes/windows/downloads/downloads.css", - "browser/themes/windows/places/organizer.css", - "browser/tools/mozscreenshots/mozscreenshots/extension/lib/mozscreenshots-style.css", - "devtools/client/aboutdebugging/src/base.css", - "devtools/client/aboutdebugging/src/components/connect/ConnectSection.css", - "devtools/client/aboutdebugging/src/components/connect/NetworkLocationsList.css", - "devtools/client/aboutdebugging/src/components/debugtarget/DebugTargetItem.css", - "devtools/client/aboutdebugging/src/components/debugtarget/FieldPair.css", - "devtools/client/aboutdebugging/src/components/shared/Message.css", - "gfx/layers/layerviewer/tree.css", - "toolkit/components/aboutinference/content/aboutInference.css", - "toolkit/components/aboutinference/content/model-files-view.css", - "toolkit/components/aboutprocesses/content/aboutProcesses.css", - "toolkit/components/normandy/content/about-studies/about-studies.css", - "toolkit/components/printing/content/printPagination.css", - "toolkit/components/resistfingerprinting/content/usercharacteristics.css", - "toolkit/components/satchel/megalist/content/components/login-form/login-form.css", - "toolkit/components/satchel/megalist/content/components/password-card/password-card.css", - "toolkit/components/satchel/megalist/content/megalist.css", - "toolkit/content/aboutLogging/aboutLogging.css", - "toolkit/content/aboutTelemetry.css", - "toolkit/content/widgets/moz-card/moz-card.css", - "toolkit/content/widgets/moz-page-nav/moz-page-nav-button.css", - "toolkit/content/widgets/moz-toggle/moz-toggle.css", - "toolkit/content/xul.css", - "toolkit/mozapps/extensions/content/aboutaddons.css", - "toolkit/mozapps/extensions/content/shortcuts.css", - "toolkit/themes/linux/global/global.css", - "toolkit/themes/linux/global/richlistbox.css", - "toolkit/themes/linux/mozapps/update/updates.css", - "toolkit/themes/mobile/global/aboutMemory.css", - "toolkit/themes/mobile/global/aboutSupport.css", - "toolkit/themes/osx/global/global.css", - "toolkit/themes/osx/global/richlistbox.css", - "toolkit/themes/osx/global/wizard.css", - "toolkit/themes/osx/mozapps/update/updates.css", - "toolkit/themes/shared/aboutReader.css", - "toolkit/themes/shared/alert.css", - "toolkit/themes/shared/close-icon.css", - "toolkit/themes/shared/datetimeinputpickers.css", - "toolkit/themes/shared/design-system/storybook/tokens-table.css", - "toolkit/themes/shared/dirListing/dirListing.css", - "toolkit/themes/shared/findbar.css", - "toolkit/themes/shared/global-shared.css", - "toolkit/themes/shared/in-content/common-shared.css", - "toolkit/themes/shared/in-content/info-pages.css", - "toolkit/themes/shared/menu.css", - "toolkit/themes/shared/menulist.css", - "toolkit/themes/shared/narrate.css", - "toolkit/themes/shared/pictureinpicture/player.css", - "toolkit/themes/shared/splitter.css", - "toolkit/themes/shared/tabbox.css", - "toolkit/themes/shared/toolbar.css", - "toolkit/themes/shared/tree/tree.css", - "toolkit/themes/windows/global/button.css", - "toolkit/themes/windows/global/global.css", - "toolkit/themes/windows/global/printPageSetup.css", - "toolkit/themes/windows/global/richlistbox.css", - "toolkit/themes/windows/global/wizard.css", - "toolkit/themes/windows/mozapps/update/updates.css", - ], - }, - { name: "rollout-no-non-semantic-token-usage", rules: { "stylelint-plugin-mozilla/no-non-semantic-token-usage": null, @@ -946,12 +795,16 @@ module.exports = [ "browser/components/firefoxview/view-syncedtabs.css", "browser/components/genai/chat.css", "browser/components/genai/content/link-preview-card.css", + "browser/components/genai/content/model-optin.css", "browser/components/genai/content/smart-assist.css", + "browser/components/ipprotection/content/ipprotection-content.css", "browser/components/messagepreview/messagepreview.css", "browser/components/preferences/widgets/nav-notice/nav-notice.css", "browser/components/profiles/content/avatar.css", "browser/components/profiles/content/edit-profile-card.css", "browser/components/profiles/content/profile-avatar-selector.css", + "browser/components/profiles/content/profile-card.css", + "browser/components/profiles/content/profiles-pages.css", "browser/components/profiles/content/profiles-theme-card.css", "browser/components/protections/content/protections.css", "browser/components/screenshots/overlay/overlay.css", @@ -1039,6 +892,7 @@ module.exports = [ "browser/themes/shared/places/editBookmarkPanel.css", "browser/themes/shared/places/sidebar.css", "browser/themes/shared/places/tree-icons.css", + "browser/themes/shared/preferences/containers-dialog.css", "browser/themes/shared/preferences/fxaPairDevice.css", "browser/themes/shared/preferences/preferences.css", "browser/themes/shared/preferences/privacy.css", @@ -1052,6 +906,7 @@ module.exports = [ "browser/themes/shared/tabbrowser/content-area.css", "browser/themes/shared/tabbrowser/ctrlTab.css", "browser/themes/shared/tabbrowser/fullscreen-and-pointerlock.css", + "browser/themes/shared/tabbrowser/tab-hover-preview.css", "browser/themes/shared/tabbrowser/tabs.css", "browser/themes/shared/toolbarbutton-icons.css", "browser/themes/shared/toolbarbuttons.css", @@ -1069,6 +924,8 @@ module.exports = [ "devtools/client/aboutdebugging/src/components/App.css", "devtools/client/aboutdebugging/src/components/ProfilerDialog.css", "devtools/client/aboutdebugging/src/components/connect/ConnectPage.css", + "devtools/client/aboutdebugging/src/components/connect/ConnectSection.css", + "devtools/client/aboutdebugging/src/components/connect/NetworkLocationsList.css", "devtools/client/aboutdebugging/src/components/debugtarget/DebugTargetItem.css", "devtools/client/aboutdebugging/src/components/debugtarget/ExtensionDetail.css", "devtools/client/aboutdebugging/src/components/debugtarget/FieldPair.css", @@ -1107,6 +964,7 @@ module.exports = [ "toolkit/components/printing/content/printPreview.css", "toolkit/components/printing/content/simplifyMode.css", "toolkit/components/resistfingerprinting/content/letterboxing.css", + "toolkit/components/resistfingerprinting/content/usercharacteristics.css", "toolkit/components/satchel/megalist/content/components/login-form/login-form.css", "toolkit/components/satchel/megalist/content/components/login-line/login-line.css", "toolkit/components/satchel/megalist/content/components/password-card/password-card.css", @@ -1132,13 +990,16 @@ module.exports = [ "toolkit/mozapps/extensions/content/aboutaddons.css", "toolkit/mozapps/extensions/content/shortcuts.css", "toolkit/themes/linux/global/autocomplete.css", + "toolkit/themes/linux/global/global.css", "toolkit/themes/linux/global/richlistbox.css", "toolkit/themes/linux/mozapps/update/updates.css", "toolkit/themes/mobile/global/aboutMemory.css", "toolkit/themes/mobile/global/aboutSupport.css", "toolkit/themes/osx/global/autocomplete.css", "toolkit/themes/osx/global/button.css", + "toolkit/themes/osx/global/global.css", "toolkit/themes/osx/global/richlistbox.css", + "toolkit/themes/osx/global/wizard.css", "toolkit/themes/osx/mozapps/handling/handling.css", "toolkit/themes/osx/mozapps/update/updates.css", "toolkit/themes/shared/aboutCache.css", @@ -1148,6 +1009,7 @@ module.exports = [ "toolkit/themes/shared/aboutSupport.css", "toolkit/themes/shared/alert.css", "toolkit/themes/shared/checkbox.css", + "toolkit/themes/shared/close-icon.css", "toolkit/themes/shared/datetimeinputpickers.css", "toolkit/themes/shared/design-system/storybook/tokens-table.css", "toolkit/themes/shared/dirListing/dirListing.css", @@ -1166,12 +1028,14 @@ module.exports = [ "toolkit/themes/shared/popupnotification.css", "toolkit/themes/shared/radio.css", "toolkit/themes/shared/splitter.css", + "toolkit/themes/shared/tabbox.css", "toolkit/themes/shared/toolbar.css", "toolkit/themes/shared/toolbarbutton.css", "toolkit/themes/shared/tree/tree.css", "toolkit/themes/windows/global/autocomplete.css", "toolkit/themes/windows/global/button.css", "toolkit/themes/windows/global/global.css", + "toolkit/themes/windows/global/printPageSetup.css", "toolkit/themes/windows/global/richlistbox.css", "toolkit/themes/windows/global/wizard.css", "toolkit/themes/windows/mozapps/handling/handling.css", diff --git a/toolkit/content/aboutLogging/aboutLogging.css b/toolkit/content/aboutLogging/aboutLogging.css @@ -35,7 +35,7 @@ color: var(--text-color); text-align: center; /* Bug 1986645: Border radius tokens are not shipped in Android, so we use a variable with fallback */ - /* stylelint-disable-next-line stylelint-plugin-mozilla/use-border-radius-tokens */ + /* stylelint-disable-next-line stylelint-plugin-mozilla/use-design-tokens */ border-radius: var(--aboutlogging-border-radius-small); padding: var(--space-medium); opacity: 0; @@ -158,7 +158,7 @@ input[type="text"] { margin-bottom: 0.5em; border: 1px solid var(--aboutlogging-box-border-color); /* Bug 1986645: Border radius tokens are not shipped in Android, so we use a variable with fallback */ - /* stylelint-disable-next-line stylelint-plugin-mozilla/use-border-radius-tokens */ + /* stylelint-disable-next-line stylelint-plugin-mozilla/use-design-tokens */ border-radius: var(--aboutlogging-border-radius-small); background-color: var(--aboutlogging-box-background); } diff --git a/toolkit/themes/shared/arrowscrollbox.css b/toolkit/themes/shared/arrowscrollbox.css @@ -38,7 +38,7 @@ toolbarbutton { > .toolbarbutton-icon { padding: var(--arrowscrollbox-scrollicon-padding, 0); - /* stylelint-disable-next-line stylelint-plugin-mozilla/use-border-radius-tokens */ + /* stylelint-disable-next-line stylelint-plugin-mozilla/use-design-tokens */ border-radius: var(--arrowscrollbox-scrollicon-border-radius, 0); background-color: var(--arrowscrollbox-scrollicon-background-color, transparent); transition: var(--arrowscrollbox-scrollicon-transition, none); diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/config.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/config.mjs @@ -123,6 +123,40 @@ const FontWeight = { }; /** @type {PropertyTypeConfig} */ +const BorderColor = { + allow: [ + "transparent", + "currentColor", + "white", + "black", + "auto", + "normal", + "none", + "0", + ], + tokenTypes: ["border-color", "border", "outline"], + customFixes: customColorFixes, +}; + +/** @type {PropertyTypeConfig} */ +const BorderWidth = { + allow: [ + "solid", + "dashed", + "dotted", + "double", + "groove", + "ridge", + "inset", + "outset", + "none", + "hidden", + ], + tokenTypes: ["border-width"], + allowUnits: true, +}; + +/** @type {PropertyTypeConfig} */ const TextColor = { allow: ["currentColor", "white", "black"], tokenTypes: ["text-color"], @@ -160,6 +194,90 @@ export const propertyConfig = { validTypes: [BoxShadow], multiple: true, }, + border: { + validTypes: [BorderColor, BorderWidth], + shorthand: true, + }, + "border-block": { + validTypes: [BorderColor, BorderWidth], + shorthand: true, + }, + "border-block-color": { + validTypes: [BorderColor], + }, + "border-block-end": { + validTypes: [BorderColor, BorderWidth], + shorthand: true, + }, + "border-block-end-color": { + validTypes: [BorderColor], + }, + "border-block-start": { + validTypes: [BorderColor, BorderWidth], + shorthand: true, + }, + "border-block-start-color": { + validTypes: [BorderColor], + }, + "border-color": { + validTypes: [BorderColor], + }, + "border-inline": { + validTypes: [BorderColor, BorderWidth], + shorthand: true, + }, + "border-inline-color": { + validTypes: [BorderColor], + }, + "border-inline-end": { + validTypes: [BorderColor, BorderWidth], + shorthand: true, + }, + "border-inline-end-color": { + validTypes: [BorderColor], + }, + "border-inline-start": { + validTypes: [BorderColor, BorderWidth], + shorthand: true, + }, + "border-inline-start-color": { + validTypes: [BorderColor], + }, + "border-bottom": { + validTypes: [BorderColor, BorderWidth], + shorthand: true, + }, + "border-bottom-color": { + validTypes: [BorderColor], + }, + "border-left": { + validTypes: [BorderColor, BorderWidth], + shorthand: true, + }, + "border-left-color": { + validTypes: [BorderColor], + }, + "border-right": { + validTypes: [BorderColor, BorderWidth], + shorthand: true, + }, + "border-right-color": { + validTypes: [BorderColor], + }, + "border-top": { + validTypes: [BorderColor, BorderWidth], + shorthand: true, + }, + "border-top-color": { + validTypes: [BorderColor], + }, + outline: { + validTypes: [BorderColor, BorderWidth], + shorthand: true, + }, + "outline-color": { + validTypes: [BorderColor], + }, color: { validTypes: [TextColor], }, diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/rules/index.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/rules/index.mjs @@ -7,7 +7,6 @@ import noBaseDesignTokens from "./no-base-design-tokens.mjs"; import noBrowserRefsInToolkit from "./no-browser-refs-in-toolkit.mjs"; import useBorderRadiusTokens from "./use-border-radius-tokens.mjs"; -import useBorderColorTokens from "./use-border-color-tokens.mjs"; import useSpaceTokens from "./use-space-tokens.mjs"; import useDesignTokens from "./use-design-tokens.mjs"; import noNonSemanticTokenUsage from "./no-non-semantic-token-usage.mjs"; @@ -17,7 +16,6 @@ export default { "no-base-design-tokens": noBaseDesignTokens, "no-browser-refs-in-toolkit": noBrowserRefsInToolkit, "use-border-radius-tokens": useBorderRadiusTokens, - "use-border-color-tokens": useBorderColorTokens, "use-space-tokens": useSpaceTokens, "use-design-tokens": useDesignTokens, "no-non-semantic-token-usage": noNonSemanticTokenUsage, diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/rules/use-border-color-tokens.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/rules/use-border-color-tokens.mjs @@ -1,152 +0,0 @@ -/* 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 valueParser from "postcss-value-parser"; -import { - namespace, - createTokenNamesArray, - isValidTokenUsage, - usesRawColors, - createAllowList, - getLocalCustomProperties, -} from "../helpers.mjs"; - -const { - utils: { report, ruleMessages, validateOptions }, -} = stylelint; - -// Name our rule, set the error message, and link to meta -const ruleName = namespace("use-border-color-tokens"); - -const messages = ruleMessages(ruleName, { - rejected: value => `${value} should use a border-color design token.`, -}); - -const meta = { - url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-border-color-tokens.html", - fixable: true, -}; - -// Gather an array of the ready css `['var(--token-name)']` -const INCLUDE_CATEGORIES = ["border-color", "border", "outline"]; - -const tokenCSS = createTokenNamesArray(INCLUDE_CATEGORIES); - -// Allowed border-color values in CSS -const ALLOW_LIST = createAllowList([ - "transparent", - "currentColor", - "white", - "black", - "auto", - "normal", - "none", - "0", -]); - -const SHORTHAND_CSS_PROPERTIES = [ - "border", - "border-top", - "border-right", - "border-bottom", - "border-left", - "border-block", - "border-block-start", - "border-block-end", - "border-inline", - "border-inline-start", - "border-inline-end", - "outline", -]; - -const CSS_PROPERTIES = [ - "border-color", - "outline-color", - "border-top-color", - "border-right-color", - "border-bottom-color", - "border-left-color", - "border-block-color", - "border-block-start-color", - "border-block-end-color", - "border-inline-color", - "border-inline-start-color", - "border-inline-end-color", - ...SHORTHAND_CSS_PROPERTIES, -]; - -const VIOLATION_AUTOFIX_MAP = { - "#fff": "white", - "#ffffff": "white", - "#000": "black", - "#000000": "black", -}; - -const ruleFunction = primaryOption => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primaryOption, - possible: [true], - }); - - if (!validOptions) { - return; - } - - // The first time through gathers our custom properties - const cssCustomProperties = getLocalCustomProperties(root); - - // And then we validate our properties - root.walkDecls(declarations => { - // If the property is not in our list to check, skip it - if (!CSS_PROPERTIES.includes(declarations.prop)) { - return; - } - - // Otherwise, see if we are using the tokens correctly - if ( - isValidTokenUsage( - declarations.value, - tokenCSS, - cssCustomProperties, - ALLOW_LIST - ) && - !usesRawColors(declarations.value) - ) { - return; - } - - report({ - message: messages.rejected(declarations.value), - node: declarations, - result, - ruleName, - fix: () => { - const val = valueParser(declarations.value); - let hasFixes = false; - val.walk(node => { - if (node.type == "word") { - const token = - VIOLATION_AUTOFIX_MAP[node.value.trim().toLowerCase()]; - if (token) { - hasFixes = true; - node.value = token; - } - } - }); - if (hasFixes) { - declarations.value = val.toString(); - } - }, - }); - }); - }; -}; - -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,298 +0,0 @@ -/** - * 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 useBorderColorTokens from "../rules/use-border-color-tokens.mjs"; - -let plugin = stylelint.createPlugin( - useBorderColorTokens.ruleName, - useBorderColorTokens -); -let { - ruleName, - rule: { messages }, -} = plugin; - -testRule({ - plugins: [plugin], - ruleName, - config: true, - fix: false, - accept: [ - // allowed token values - { - code: ".a { border: 2px solid var(--border-color); }", - description: "Using border token in border shorthand is valid.", - }, - { - code: ".a { border-color: var(--border-color); }", - description: "Using border-color token is valid.", - }, - { - code: ".a { border-top: 2px solid var(--border-color); }", - description: "Using border token in border-top is valid.", - }, - { - code: ".a { border-right: 2px solid var(--border-color); }", - description: "Using border token in border-right is valid.", - }, - { - code: ".a { border-bottom: 2px solid var(--border-color); }", - description: "Using border token in border-bottom is valid.", - }, - { - code: ".a { border-left: 2px solid var(--border-color); }", - description: "Using border token in border-left is valid.", - }, - { - code: ".a { border-top-color: var(--border-color); }", - description: "Using border token in border-top-color is valid.", - }, - { - code: ".a { border-right-color: var(--border-color); }", - description: "Using border token in border-right-color is valid.", - }, - { - code: ".a { border-bottom-color: var(--border-color); }", - description: "Using border token in border-bottom-color is valid.", - }, - { - code: ".a { border-left-color: var(--border-color); }", - description: "Using border token in border-left-color is valid.", - }, - { - code: ".a { outline: 1px solid var(--border-color); }", - description: "Using border token in outline shorthand is valid.", - }, - { - code: ".a { outline-color: var(--border-color); }", - description: "Using border token in outline-color is valid.", - }, - // allowed CSS values - { - code: ".a { border-color: currentColor; }", - description: "Using currentColor is valid.", - }, - { - code: ".a { border-color: white; }", - description: "Using white is valid.", - }, - { - code: ".a { border-color: black; }", - description: "Using black is valid.", - }, - { - code: ".a { border: none; }", - description: "Using none is valid.", - }, - { - code: ".a { border: 0; }", - description: "Using 0 is valid.", - }, - { - code: ".a { border: 1px solid transparent; }", - description: "Using transparent in shorthand is valid.", - }, - { - code: ".a { border-color: var(--border-color, var(--another-property)); }", - description: "Using a fallback value with two tokens is valid.", - }, - { - code: ".a { border: 1px solid var(--border-color, transparent); }", - description: "Using a fallback value with an allowed value is valid", - }, - { - code: ".a { border: 1px solid var(--border-color, #666); }", - description: "Using a fallback value with an color value is valid", - }, - { - code: ` - :root { --custom-token: var(--border-color); } - .a { border-color: var(--custom-token); } - `, - description: "Using a local custom property (in the same file) is valid.", - }, - { - code: ` - :root { --custom-token: var(--border-color); } - .a { border: 1px solid var(--custom-token); } - `, - description: - "Using a local custom property (in the same file) in shorthand is valid.", - }, - { - code: "outline: var(--focus-outline);", - description: "Using a focus-outline token in outline is valid.", - }, - { - code: ` - :root { --custom-token: var(--border-width) solid var(--border-color); } - .a { border: var(--custom-token); } - `, - }, - ], - - reject: [ - { - code: ".a { border-color: #666; }", - message: messages.rejected("#666"), - description: "#666 should use a border-color design token.", - }, - { - code: ".a { border: 2px solid #666; }", - message: messages.rejected("2px solid #666"), - description: "2px solid #666 should use a border-color design token.", - }, - { - code: ".a { border-color: oklch(69% 0.19 15); }", - message: messages.rejected("oklch(69% 0.19 15)"), - description: "oklch(69% 0.19 15) should use a border-color design token.", - }, - { - code: ".a { border: 3px dashed oklch(42 42 42); }", - message: messages.rejected("3px dashed oklch(42 42 42)"), - description: - "3px dashed oklch(42 42 42) should use a border-color design token.", - }, - { - code: ".a { border-color: rgba(42 42 42 / 0.15); }", - message: messages.rejected("rgba(42 42 42 / 0.15)"), - description: - "rgba(42 42 42 / 0.15) should use a border-color design token.", - }, - { - code: ".a { border: 3px dashed rgba(42 42 42 / 0.15); }", - message: messages.rejected("3px dashed rgba(42 42 42 / 0.15)"), - description: - "3px dashed rgba(42 42 42 / 0.15) should use a border-color design token.", - }, - { - code: ".a { border-top: 1px solid #666666; }", - message: messages.rejected("1px solid #666666"), - description: "1px solid #666666 should use a border-color design token.", - }, - { - code: ".a { border-top-color: rgb(10 20 30); }", - message: messages.rejected("rgb(10 20 30)"), - description: "rgb(10 20 30) should use a border-color design token.", - }, - { - code: ".a { border-right: 4px dotted #666; }", - message: messages.rejected("4px dotted #666"), - description: "4px dotted #666 should use a border-color design token.", - }, - { - code: ".a { border-right-color: oklch(69% 0.19 15); }", - message: messages.rejected("oklch(69% 0.19 15)"), - description: "oklch(69% 0.19 15) should use a border-color design token.", - }, - { - code: ".a { border-bottom: medium solid color-mix(in srgb, red, blue); }", - message: messages.rejected("medium solid color-mix(in srgb, red, blue)"), - description: - "color-mix(in srgb, red, blue) should use a border-color design token.", - }, - { - code: ".a { border-bottom-color: oklch(69% 0.19 15); }", - message: messages.rejected("oklch(69% 0.19 15)"), - description: "oklch(69% 0.19 15) should use a border-color design token.", - }, - { - code: ".a { border-left: thin double #191919; }", - message: messages.rejected("thin double #191919"), - description: - "thin double #989898 should use a border-color design token.", - }, - { - code: ".a { border-left-color: oklch(69% 0.19 15); }", - message: messages.rejected("oklch(69% 0.19 15)"), - description: "oklch(69% 0.19 15) should use a border-color design token.", - }, - { - code: ".a { outline: 2px solid #666; }", - message: messages.rejected("2px solid #666"), - description: "2px solid #616263 should use a border-color design token.", - }, - { - code: ".a { outline-color: rgba(0 0 0 / 0.25); }", - message: messages.rejected("rgba(0 0 0 / 0.25)"), - description: "rgba(0 0 0 / 0.25) should use a border-color design token.", - }, - { - code: ".a { border: 1px solid var(--random-token, #666); }", - message: messages.rejected("1px solid var(--random-token, #666)"), - description: - "1px solid var(--random-token, #666) should use a border-color design token.", - }, - { - code: ` - :root { --custom-token: #666; } - .a { border-color: var(--custom-token); } - `, - message: messages.rejected("var(--custom-token)"), - description: - "var(--custom-token) should use a border-color design token.", - }, - { - code: ` - :root { --custom-token: oklch(69% 0.19 15); } - .a { border: 1px solid var(--custom-token); } - `, - message: messages.rejected("1px solid var(--custom-token)"), - description: - "1px solid var(--custom-token) should use a border-color design token.", - }, - ], -}); - -testRule({ - plugins: [plugin], - ruleName, - config: true, - fix: true, - reject: [ - { - code: ".a { border-color: #fff; }", - fixed: ".a { border-color: white; }", - message: messages.rejected("#fff"), - description: "#fff should be fixed to white", - }, - { - code: ".a { border: 1px solid #ffffff; }", - fixed: ".a { border: 1px solid white; }", - message: messages.rejected("1px solid #ffffff"), - description: "#ffffff should be fixed to white", - }, - { - code: ".a { outline-color: #FFF; }", - fixed: ".a { outline-color: white; }", - message: messages.rejected("#FFF"), - description: "#FFF should be fixed to white", - }, - { - code: ".a { border-left-color: #FFFFFF; }", - fixed: ".a { border-left-color: white; }", - message: messages.rejected("#FFFFFF"), - description: "#FFFFFF should be fixed to white", - }, - { - code: ".a { outline: 1px solid #000; }", - fixed: ".a { outline: 1px solid black; }", - message: messages.rejected("1px solid #000"), - description: "#000 should be fixed to black", - }, - { - code: ".a { border-block-end-color: #000000; }", - fixed: ".a { border-block-end-color: black; }", - message: messages.rejected("#000000"), - description: "#000000 should be fixed to black", - }, - ], -}); diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/tests/use-design-tokens.border-color.tests.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/tests/use-design-tokens.border-color.tests.mjs @@ -0,0 +1,401 @@ +/** + * 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 useDesignTokens from "../rules/use-design-tokens.mjs"; + +let plugin = stylelint.createPlugin(useDesignTokens.ruleName, useDesignTokens); +let { + ruleName, + rule: { messages }, +} = plugin; + +testRule({ + plugins: [plugin], + ruleName, + config: true, + fix: false, + accept: [ + // allowed token values + { + code: ".a { border: 2px solid var(--border-color); }", + description: "Using border token in border shorthand is valid.", + }, + { + code: ".a { border-color: var(--border-color); }", + description: "Using border-color token is valid.", + }, + { + code: ".a { border-top: 2px solid var(--border-color); }", + description: "Using border token in border-top is valid.", + }, + { + code: ".a { border-right: 2px solid var(--border-color); }", + description: "Using border token in border-right is valid.", + }, + { + code: ".a { border-bottom: 2px solid var(--border-color); }", + description: "Using border token in border-bottom is valid.", + }, + { + code: ".a { border-left: 2px solid var(--border-color); }", + description: "Using border token in border-left is valid.", + }, + { + code: ".a { border-top-color: var(--border-color); }", + description: "Using border token in border-top-color is valid.", + }, + { + code: ".a { border-right-color: var(--border-color); }", + description: "Using border token in border-right-color is valid.", + }, + { + code: ".a { border-bottom-color: var(--border-color); }", + description: "Using border token in border-bottom-color is valid.", + }, + { + code: ".a { border-left-color: var(--border-color); }", + description: "Using border token in border-left-color is valid.", + }, + { + code: ".a { outline: 1px solid var(--border-color); }", + description: "Using border token in outline shorthand is valid.", + }, + { + code: ".a { outline-color: var(--border-color); }", + description: "Using border token in outline-color is valid.", + }, + // allowed CSS values + { + code: ".a { border-color: currentColor; }", + description: "Using currentColor is valid.", + }, + { + code: ".a { border-color: white; }", + description: "Using white is valid.", + }, + { + code: ".a { border-color: black; }", + description: "Using black is valid.", + }, + { + code: ".a { border: none; }", + description: "Using none is valid.", + }, + { + code: ".a { border: 0; }", + description: "Using 0 is valid.", + }, + { + code: ".a { border: 1px solid transparent; }", + description: "Using transparent in shorthand is valid.", + }, + { + code: ".a { border-color: var(--border-color, var(--another-property)); }", + description: "Using a fallback value with two tokens is valid.", + }, + { + code: ".a { border: 1px solid var(--border-color, transparent); }", + description: "Using a fallback value with an allowed value is valid", + }, + { + code: ".a { border: 1px solid var(--border-color, #666); }", + description: "Using a fallback value with an color value is valid", + }, + { + code: ` + :root { --custom-token: var(--border-color); } + .a { border-color: var(--custom-token); } + `, + description: "Using a local custom property (in the same file) is valid.", + }, + { + code: ` + :root { --custom-token: var(--border-color); } + .a { border: 1px solid var(--custom-token); } + `, + description: + "Using a local custom property (in the same file) in shorthand is valid.", + }, + { + code: "outline: var(--focus-outline);", + description: "Using a focus-outline token in outline is valid.", + }, + { + code: ` + :root { --custom-token: var(--border-width) solid var(--border-color); } + .a { border: var(--custom-token); } + `, + }, + ], + + reject: [ + { + code: ".a { border-color: #666; }", + message: messages.rejected("#666", ["border-color", "border", "outline"]), + description: "#666 should use a border-color design token.", + }, + { + code: ".a { border: 2px solid #666; }", + message: messages.rejected("2px solid #666", [ + "border-color", + "border", + "outline", + "border-width", + ]), + description: "2px solid #666 should use a border-color design token.", + }, + { + code: ".a { border-color: oklch(69% 0.19 15); }", + message: messages.rejected("oklch(69% 0.19 15)", [ + "border-color", + "border", + "outline", + ]), + description: "oklch(69% 0.19 15) should use a border-color design token.", + }, + { + code: ".a { border: 3px dashed oklch(42 42 42); }", + message: messages.rejected("3px dashed oklch(42 42 42)", [ + "border-color", + "border", + "outline", + "border-width", + ]), + description: + "3px dashed oklch(42 42 42) should use a border-color design token.", + }, + { + code: ".a { border-color: rgba(42 42 42 / 0.15); }", + message: messages.rejected("rgba(42 42 42 / 0.15)", [ + "border-color", + "border", + "outline", + ]), + description: + "rgba(42 42 42 / 0.15) should use a border-color design token.", + }, + { + code: ".a { border: 3px dashed rgba(42 42 42 / 0.15); }", + message: messages.rejected("3px dashed rgba(42 42 42 / 0.15)", [ + "border-color", + "border", + "outline", + "border-width", + ]), + description: + "3px dashed rgba(42 42 42 / 0.15) should use a border-color design token.", + }, + { + code: ".a { border-top: 1px solid #666666; }", + message: messages.rejected("1px solid #666666", [ + "border-color", + "border", + "outline", + "border-width", + ]), + description: "1px solid #666666 should use a border-color design token.", + }, + { + code: ".a { border-top-color: rgb(10 20 30); }", + message: messages.rejected("rgb(10 20 30)", [ + "border-color", + "border", + "outline", + ]), + description: "rgb(10 20 30) should use a border-color design token.", + }, + { + code: ".a { border-right: 4px dotted #666; }", + message: messages.rejected("4px dotted #666", [ + "border-color", + "border", + "outline", + "border-width", + ]), + description: "4px dotted #666 should use a border-color design token.", + }, + { + code: ".a { border-right-color: oklch(69% 0.19 15); }", + message: messages.rejected("oklch(69% 0.19 15)", [ + "border-color", + "border", + "outline", + ]), + description: "oklch(69% 0.19 15) should use a border-color design token.", + }, + { + code: ".a { border-bottom: medium solid color-mix(in srgb, red, blue); }", + message: messages.rejected("medium solid color-mix(in srgb, red, blue)", [ + "border-color", + "border", + "outline", + "border-width", + ]), + description: + "color-mix(in srgb, red, blue) should use a border-color design token.", + }, + { + code: ".a { border-bottom-color: oklch(69% 0.19 15); }", + message: messages.rejected("oklch(69% 0.19 15)", [ + "border-color", + "border", + "outline", + ]), + description: "oklch(69% 0.19 15) should use a border-color design token.", + }, + { + code: ".a { border-left: thin double #191919; }", + message: messages.rejected("thin double #191919", [ + "border-color", + "border", + "outline", + "border-width", + ]), + description: + "thin double #989898 should use a border-color design token.", + }, + { + code: ".a { border-left-color: oklch(69% 0.19 15); }", + message: messages.rejected("oklch(69% 0.19 15)", [ + "border-color", + "border", + "outline", + ]), + description: "oklch(69% 0.19 15) should use a border-color design token.", + }, + { + code: ".a { outline: 2px solid #666; }", + message: messages.rejected("2px solid #666", [ + "border-color", + "border", + "outline", + "border-width", + ]), + description: "2px solid #616263 should use a border-color design token.", + }, + { + code: ".a { outline-color: rgba(0 0 0 / 0.25); }", + message: messages.rejected("rgba(0 0 0 / 0.25)", [ + "border-color", + "border", + "outline", + ]), + description: "rgba(0 0 0 / 0.25) should use a border-color design token.", + }, + { + code: ".a { border: 1px solid var(--random-token, #666); }", + message: messages.rejected("1px solid var(--random-token, #666)", [ + "border-color", + "border", + "outline", + "border-width", + ]), + description: + "1px solid var(--random-token, #666) should use a border-color design token.", + }, + { + code: ` + :root { --custom-token: #666; } + .a { border-color: var(--custom-token); } + `, + message: messages.rejected("var(--custom-token)", [ + "border-color", + "border", + "outline", + ]), + description: + "var(--custom-token) should use a border-color design token.", + }, + { + code: ` + :root { --custom-token: oklch(69% 0.19 15); } + .a { border: 1px solid var(--custom-token); } + `, + message: messages.rejected("1px solid var(--custom-token)", [ + "border-color", + "border", + "outline", + "border-width", + ]), + description: + "1px solid var(--custom-token) should use a border-color design token.", + }, + ], +}); + +testRule({ + plugins: [plugin], + ruleName, + config: true, + fix: true, + reject: [ + { + code: ".a { border-color: #fff; }", + fixed: ".a { border-color: white; }", + message: messages.rejected( + "#fff", + ["border-color", "border", "outline"], + "white" + ), + description: "#fff should be fixed to white", + }, + { + code: ".a { border: 1px solid #ffffff; }", + fixed: ".a { border: 1px solid white; }", + message: messages.rejected( + "1px solid #ffffff", + ["border-color", "border", "outline", "border-width"], + "1px solid white" + ), + description: "#ffffff should be fixed to white", + }, + { + code: ".a { outline-color: #FFF; }", + fixed: ".a { outline-color: white; }", + message: messages.rejected( + "#FFF", + ["border-color", "border", "outline"], + "white" + ), + description: "#FFF should be fixed to white", + }, + { + code: ".a { border-left-color: #FFFFFF; }", + fixed: ".a { border-left-color: white; }", + message: messages.rejected( + "#FFFFFF", + ["border-color", "border", "outline"], + "white" + ), + description: "#FFFFFF should be fixed to white", + }, + { + code: ".a { outline: 1px solid #000; }", + fixed: ".a { outline: 1px solid black; }", + message: messages.rejected( + "1px solid #000", + ["border-color", "border", "outline", "border-width"], + "1px solid black" + ), + description: "#000 should be fixed to black", + }, + { + code: ".a { border-block-end-color: #000000; }", + fixed: ".a { border-block-end-color: black; }", + message: messages.rejected( + "#000000", + ["border-color", "border", "outline"], + "black" + ), + description: "#000000 should be fixed to black", + }, + ], +});