commit 56fcd87147b4c011be669fb3f7a109fc16121c1e parent 22e0c5413db16d56b4fcd665c99a64e517625d98 Author: Jon Oliver <jooliver@mozilla.com> Date: Thu, 11 Dec 2025 21:01:08 +0000 Bug 1994263: consolidate use-background-color-tokens stylelint rule with use-design-tokens rule r=mstriemer,frontend-codestyle-reviewers - converts use-background-color-tokens rule to be configured via use-design-tokens rule - updates tests and documentation for background-color portion of use-design-tokens rule Differential Revision: https://phabricator.services.mozilla.com/D273878 Diffstat:
12 files changed, 852 insertions(+), 916 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-background-color-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, @@ -429,7 +428,6 @@ module.exports = { ], rules: { "stylelint-plugin-mozilla/use-design-tokens": null, - "stylelint-plugin-mozilla/use-background-color-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, @@ -445,7 +443,6 @@ module.exports = { ], rules: { "stylelint-plugin-mozilla/use-design-tokens": true, - "stylelint-plugin-mozilla/use-background-color-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, diff --git a/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/ReportContent/ReportContent.scss b/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/ReportContent/ReportContent.scss @@ -4,7 +4,7 @@ box-shadow: var(--box-shadow-level-4); border-radius: var(--border-radius-medium); border: 1px solid var(--newtab-border-color); - /* stylelint-disable-next-line stylelint-plugin-mozilla/use-background-color-tokens */ + /* stylelint-disable-next-line stylelint-plugin-mozilla/use-design-tokens */ background-color: var(--newtab-background-color-secondary); form { diff --git a/browser/extensions/newtab/content-src/components/Widgets/_Widgets.scss b/browser/extensions/newtab/content-src/components/Widgets/_Widgets.scss @@ -21,7 +21,7 @@ // known transparency issue with color-mix syntax when a wallpaper is set .lightWallpaper &, .darkWallpaper & { - background-color: var(--newtab-weather-background-color); // stylelint-disable-line stylelint-plugin-mozilla/use-background-color-tokens + background-color: var(--newtab-weather-background-color); // stylelint-disable-line stylelint-plugin-mozilla/use-design-tokens @media (prefers-contrast) { background-color: var(--background-color-box); diff --git a/browser/extensions/newtab/css/activity-stream.css b/browser/extensions/newtab/css/activity-stream.css @@ -8904,7 +8904,7 @@ dialog:dir(rtl)::after { box-shadow: var(--box-shadow-level-4); border-radius: var(--border-radius-medium); border: 1px solid var(--newtab-border-color); - /* stylelint-disable-next-line stylelint-plugin-mozilla/use-background-color-tokens */ + /* stylelint-disable-next-line stylelint-plugin-mozilla/use-design-tokens */ background-color: var(--newtab-background-color-secondary); } .report-content-form form { diff --git a/docs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-background-color-tokens.rst b/docs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-background-color-tokens.rst @@ -1,183 +0,0 @@ -=========================== -use-background-color-tokens -=========================== - -This rule checks that CSS declarations use background-color design token variables -instead of hard-coded values. This ensures consistent background-color across -the application and makes it easier to maintain design system adoption. - -Examples of incorrect code for this rule: ------------------------------------------ - -.. code-block:: css - - .card { - background-color: #191919; - } - -.. code-block:: css - - .custom-button { - background: url('image.png') rgba(42 42 42 / 0.15); - } - -.. code-block:: css - - button:hover { - background: rgba(0 0 0 / 0.25); - } - -.. code-block:: css - - :root { - --my-token: blue; - } - - .my-button { - background: url('image.png') no-repeat center center / auto var(--my-token, oklch(55% 0.21 15)); - } - -.. code-block:: css - - .accent-background-color { - background-color: AccentColor; - } - -Examples of correct token usage for this rule: ----------------------------------------------- - -.. code-block:: css - - .card { - background-color: var(--background-color-box); - } - -.. code-block:: css - - .custom-button { - background: url('image.png') var(--background-color-box); - } - -.. code-block:: css - - button:hover { - background: var(--background-color-box); - } - -.. code-block:: css - - /* You may set a fallback for a token. */ - - .my-button { - background: var(--background-color-box, oklch(55% 0.21 15)); - } - -.. code-block:: css - - /* Local CSS variables that reference valid border-radius tokens are allowed */ - - :root { - --my-token: var(--background-color-box); - } - - .my-button { - background-color: var(--my-token, oklch(55% 0.21 15)); - } - -The rule also allows these non-token values: - -.. code-block:: css - - .transparent-background-color { - background-color: transparent; - } - -.. code-block:: css - - .inherited-background-color{ - background-color: inherit; - } - -.. code-block:: css - - .unset-background-color { - background-color: unset; - } - -.. code-block:: css - - .initial-background-color { - background-color: initial; - } - -.. code-block:: css - - .current-background-color { - background-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 */ - .white-background { - background-color: #fff; - } - - /* After autofix */ - .white-background { - background-color: white; - } - -.. code-block:: css - - /* Before */ - .white-background { - background-color: #ffffff; - } - - /* After autofix */ - .white-background { - background-color: white; - } - -.. code-block:: css - - /* Before */ - .black-background { - background-color: #000; - } - - /* After autofix */ - .black-background { - background-color: black; - } - -.. code-block:: css - - /* Before */ - .black-background { - background-color: #000000; - } - - /* After autofix */ - .black-background { - background-color: black; - } - -.. code-block:: css - - /* Before */ - .custom-background { - background: url('image.png') #fff; - } - - /* After autofix */ - .custom-background { - background: url('image.png') white; - } diff --git a/docs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-design-tokens/background-color.rst b/docs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-design-tokens/background-color.rst @@ -0,0 +1,184 @@ +================ +background-color +================ + +The ``use-design-tokens`` rule checks that CSS ``background-color`` and +``background`` declarations use design token variables instead of hardcoded +values. This ensures consistent background-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 { + background-color: #191919; + } + +.. code-block:: css + + .custom-button { + background: url('image.png') rgba(42 42 42 / 0.15); + } + +.. code-block:: css + + button:hover { + background: rgba(0 0 0 / 0.25); + } + +.. code-block:: css + + :root { + --my-token: blue; + } + + .my-button { + background: url('image.png') no-repeat center center / auto var(--my-token, oklch(55% 0.21 15)); + } + +.. code-block:: css + + .accent-background-color { + background-color: AccentColor; + } + +Examples of correct token usage for this rule: +---------------------------------------------- + +.. code-block:: css + + .card { + background-color: var(--background-color-box); + } + +.. code-block:: css + + .custom-button { + background: url('image.png') var(--background-color-box); + } + +.. code-block:: css + + button:hover { + background: var(--background-color-box); + } + +.. code-block:: css + + /* You may set a fallback for a token. */ + + .my-button { + background: var(--background-color-box, oklch(55% 0.21 15)); + } + +.. code-block:: css + + /* Local CSS variables that reference valid background-color tokens are allowed */ + + :root { + --my-token: var(--background-color-box); + } + + .my-button { + background-color: var(--my-token, oklch(55% 0.21 15)); + } + +The rule also allows these non-token values: + +.. code-block:: css + + .transparent-background-color { + background-color: transparent; + } + +.. code-block:: css + + .inherited-background-color { + background-color: inherit; + } + +.. code-block:: css + + .unset-background-color { + background-color: unset; + } + +.. code-block:: css + + .initial-background-color { + background-color: initial; + } + +.. code-block:: css + + .current-background-color { + background-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 */ + .white-background { + background-color: #fff; + } + + /* After autofix */ + .white-background { + background-color: white; + } + +.. code-block:: css + + /* Before */ + .white-background { + background-color: #ffffff; + } + + /* After autofix */ + .white-background { + background-color: white; + } + +.. code-block:: css + + /* Before */ + .black-background { + background-color: #000; + } + + /* After autofix */ + .black-background { + background-color: black; + } + +.. code-block:: css + + /* Before */ + .black-background { + background-color: #000000; + } + + /* After autofix */ + .black-background { + background-color: black; + } + +.. code-block:: css + + /* Before */ + .custom-background { + background: url('image.png') #fff; + } + + /* After autofix */ + .custom-background { + background: url('image.png') white; + } diff --git a/stylelint-rollouts.config.js b/stylelint-rollouts.config.js @@ -678,193 +678,6 @@ module.exports = [ ], }, { - name: "rollout-use-background-color-tokens", - rules: { - "stylelint-plugin-mozilla/use-background-color-tokens": null, - }, - files: [ - "browser/components/aboutlogins/content/aboutLogins.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-timeline.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/contextualidentity/content/usercontext.css", - "browser/components/enterprisepolicies/content/aboutPolicies.css", - "browser/components/firefoxview/card-container.css", - "browser/components/firefoxview/firefoxview.css", - "browser/components/firefoxview/fxview-tab-row.css", - "browser/components/firefoxview/opentabs-tab-row.css", - "browser/components/genai/chat.css", - "browser/components/genai/content/link-preview-card.css", - "browser/components/preferences/widgets/nav-notice/nav-notice.css", - "browser/components/profiles/content/avatar.css", - "browser/components/profiles/content/profile-avatar-selector.css", - "browser/components/profiles/content/profiles-theme-card.css", - "browser/components/protections/content/protections.css", - "browser/components/screenshots/overlay/overlay.css", - "browser/components/screenshots/screenshots-buttons.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/sidebar/sidebar.css", - "browser/components/textrecognition/textrecognition.css", - "browser/components/urlbar/tests/browser/dynamicResult0.css", - "browser/components/urlbar/tests/browser/dynamicResult1.css", - "browser/extensions/newtab/content-src/components/Base/_Base.scss", - "browser/extensions/newtab/content-src/components/Card/_Card.scss", - "browser/extensions/newtab/content-src/components/CollapsibleSection/_CollapsibleSection.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/CardGrid/_CardGrid.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/DSImage/_DSImage.scss", - "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/_FeatureHighlight.scss", - "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/Highlights/_Highlights.scss", - "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/InterestPicker/_InterestPicker.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/DownloadModalToggle/_DownloadModalToggle.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/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/components/Widgets/FocusTimer/_FocusTimer.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/extensions/webcompat/about-compat/aboutCompat.css", - "browser/themes/linux/browser.css", - "browser/themes/linux/places/organizer.css", - "browser/themes/osx/browser.css", - "browser/themes/osx/downloads/allDownloadsView.css", - "browser/themes/shared/UITour.css", - "browser/themes/shared/addons/unified-extensions.css", - "browser/themes/shared/aiWindowSidebar.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/downloads/progressmeter.css", - "browser/themes/shared/formautofill-notification.css", - "browser/themes/shared/identity-block/identity-block.css", - "browser/themes/shared/identity-credential-notification.css", - "browser/themes/shared/notification-icons.css", - "browser/themes/shared/pageInfo.css", - "browser/themes/shared/places/editBookmark.css", - "browser/themes/shared/places/sidebar.css", - "browser/themes/shared/preferences/preferences.css", - "browser/themes/shared/preferences/privacy.css", - "browser/themes/shared/preferences/search.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/fullscreen-and-pointerlock.css", - "browser/themes/shared/tabbrowser/tabs.css", - "browser/themes/shared/toolbarbutton-icons.css", - "browser/themes/shared/toolbarbuttons.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/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/ProfilerDialog.css", - "devtools/client/aboutdebugging/src/components/debugtarget/ExtensionDetail.css", - "devtools/client/aboutdebugging/src/components/debugtarget/ServiceWorkerAction.css", - "devtools/client/aboutdebugging/src/components/shared/Message.css", - "devtools/client/aboutdebugging/src/components/sidebar/SidebarItem.css", - "gfx/layers/layerviewer/tree.css", - "security/manager/ssl/tests/mochitest/mixedcontent/somestyle.css", - "toolkit/components/aboutconfig/content/aboutconfig.css", - "toolkit/components/aboutinference/content/aboutInference.css", - "toolkit/components/aboutinference/content/model-files-view.css", - "toolkit/components/aboutprocesses/content/aboutProcesses.css", - "toolkit/components/aboutwebauthn/content/aboutWebauthn.css", - "toolkit/components/certviewer/content/components/info-item.css", - "toolkit/components/certviewer/content/components/list-item.css", - "toolkit/components/cleardata/tests/browser/file_css_cache.css", - "toolkit/components/normandy/content/about-studies/about-studies.css", - "toolkit/components/printing/content/printPagination.css", - "toolkit/components/resistfingerprinting/content/letterboxing.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/aboutMozilla.css", - "toolkit/content/aboutTelemetry.css", - "toolkit/content/aboutwebrtc/aboutWebrtc.css", - "toolkit/content/tests/widgets/videomask.css", - "toolkit/content/widgets/infobar.css", - "toolkit/content/widgets/moz-button/moz-button.css", - "toolkit/content/widgets/moz-input-text/moz-input-text.css", - "toolkit/content/widgets/moz-page-nav/moz-page-nav-button.css", - "toolkit/content/widgets/moz-page-nav/moz-page-nav.css", - "toolkit/content/widgets/moz-reorderable-list/moz-reorderable-list.css", - "toolkit/content/widgets/moz-toggle/moz-toggle.css", - "toolkit/content/widgets/panel-list/panel-item.css", - "toolkit/content/widgets/panel-list/panel-list.css", - "toolkit/content/xul.css", - "toolkit/mozapps/extensions/content/aboutaddons.css", - "toolkit/mozapps/extensions/content/shortcuts.css", - "toolkit/themes/linux/global/autocomplete.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/richlistbox.css", - "toolkit/themes/shared/aboutCache.css", - "toolkit/themes/shared/aboutNetError.css", - "toolkit/themes/shared/aboutReader.css", - "toolkit/themes/shared/aboutSupport.css", - "toolkit/themes/shared/alert.css", - "toolkit/themes/shared/arrowscrollbox.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/narrate.css", - "toolkit/themes/shared/pictureinpicture/player.css", - "toolkit/themes/shared/popup.css", - "toolkit/themes/shared/splitter.css", - "toolkit/themes/shared/tabbox.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/richlistbox.css", - "toolkit/themes/windows/global/wizard.css", - "toolkit/themes/windows/mozapps/update/updates.css", - "tools/tryselect/selectors/chooser/static/style.css", - ], - }, - { name: "rollout-use-border-color-tokens", rules: { "stylelint-plugin-mozilla/use-border-color-tokens": null, @@ -1104,6 +917,7 @@ module.exports = [ }, files: [ "browser/base/content/aboutDialog.css", + "browser/components/aboutlogins/content/aboutLogins.css", "browser/components/aboutlogins/content/aboutLoginsImportReport.css", "browser/components/aboutlogins/content/components/confirmation-dialog.css", "browser/components/aboutlogins/content/components/generic-dialog.css", @@ -1114,6 +928,7 @@ module.exports = [ "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/login-timeline.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", @@ -1134,6 +949,7 @@ module.exports = [ "browser/components/genai/content/smart-assist.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/profiles-theme-card.css", @@ -1143,9 +959,11 @@ module.exports = [ "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-panel-header.css", "browser/components/sidebar/sidebar-pins-promo.css", "browser/components/sidebar/sidebar.css", + "browser/components/textrecognition/textrecognition.css", "browser/components/urlbar/tests/browser/dynamicResult0.css", "browser/components/urlbar/tests/browser/dynamicResult1.css", "browser/extensions/formautofill/skin/shared/editAddress.css", @@ -1165,16 +983,20 @@ module.exports = [ "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/DSCard/_DSCard.scss", "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/DSContextFooter/_DSContextFooter.scss", "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/DSEmptyState/_DSEmptyState.scss", + "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/DSImage/_DSImage.scss", "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/DSMessage/_DSMessage.scss", "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/_DownloadMobilePromoHighlight.scss", "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/_FeatureHighlight.scss", "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/_WallpaperFeatureHighlight.scss", + "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/Highlights/_Highlights.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/PromoCard/_PromoCard.scss", + "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/ReportContent/ReportContent.scss", "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/SectionTitle/_SectionTitle.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/DownloadModalToggle/_DownloadModalToggle.scss", "browser/extensions/newtab/content-src/components/ErrorBoundary/_ErrorBoundary.scss", "browser/extensions/newtab/content-src/components/ModalOverlay/_ModalOverlay.scss", "browser/extensions/newtab/content-src/components/Search/_Search.scss", @@ -1182,7 +1004,9 @@ module.exports = [ "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/components/Widgets/FocusTimer/_FocusTimer.scss", "browser/extensions/newtab/content-src/components/Widgets/Lists/_Lists.scss", + "browser/extensions/newtab/content-src/components/Widgets/_Widgets.scss", "browser/extensions/newtab/content-src/styles/_icons.scss", "browser/extensions/newtab/content-src/styles/_mixins.scss", "browser/extensions/newtab/content-src/styles/_variables.scss", @@ -1192,9 +1016,11 @@ module.exports = [ "browser/themes/linux/places/organizer.css", "browser/themes/osx/browser.css", "browser/themes/osx/customizableui/panelUI.css", + "browser/themes/osx/downloads/allDownloadsView.css", "browser/themes/osx/places/organizer.css", "browser/themes/shared/UITour.css", "browser/themes/shared/addons/unified-extensions.css", + "browser/themes/shared/aiWindowSidebar.css", "browser/themes/shared/autocomplete.css", "browser/themes/shared/browser-shared.css", "browser/themes/shared/controlcenter/panel.css", @@ -1202,6 +1028,7 @@ module.exports = [ "browser/themes/shared/customizableui/panelUI-shared.css", "browser/themes/shared/downloads/allDownloadsView.inc.css", "browser/themes/shared/downloads/downloads.inc.css", + "browser/themes/shared/downloads/progressmeter.css", "browser/themes/shared/formautofill-notification.css", "browser/themes/shared/identity-block/identity-block.css", "browser/themes/shared/identity-credential-notification.css", @@ -1215,6 +1042,7 @@ module.exports = [ "browser/themes/shared/preferences/fxaPairDevice.css", "browser/themes/shared/preferences/preferences.css", "browser/themes/shared/preferences/privacy.css", + "browser/themes/shared/preferences/search.css", "browser/themes/shared/preferences/siteDataSettings.css", "browser/themes/shared/privatebrowsing/aboutPrivateBrowsing.css", "browser/themes/shared/search/searchbar.css", @@ -1225,6 +1053,7 @@ module.exports = [ "browser/themes/shared/tabbrowser/ctrlTab.css", "browser/themes/shared/tabbrowser/fullscreen-and-pointerlock.css", "browser/themes/shared/tabbrowser/tabs.css", + "browser/themes/shared/toolbarbutton-icons.css", "browser/themes/shared/toolbarbuttons.css", "browser/themes/shared/translations/panel.css", "browser/themes/shared/urlbar-dynamic-results.css", @@ -1232,6 +1061,8 @@ module.exports = [ "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", @@ -1239,7 +1070,9 @@ module.exports = [ "devtools/client/aboutdebugging/src/components/ProfilerDialog.css", "devtools/client/aboutdebugging/src/components/connect/ConnectPage.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", + "devtools/client/aboutdebugging/src/components/debugtarget/ServiceWorkerAction.css", "devtools/client/aboutdebugging/src/components/shared/IconLabel.css", "devtools/client/aboutdebugging/src/components/shared/Message.css", "devtools/client/aboutdebugging/src/components/sidebar/Sidebar.css", @@ -1248,6 +1081,7 @@ module.exports = [ "devtools/client/aboutdebugging/src/components/sidebar/SidebarRuntimeItem.css", "gfx/layers/layerviewer/tree.css", "netwerk/test/browser/res.css", + "security/manager/ssl/tests/mochitest/mixedcontent/somestyle.css", "toolkit/components/aboutcheckerboard/content/aboutCheckerboard.css", "toolkit/components/aboutconfig/content/aboutconfig.css", "toolkit/components/aboutinference/content/aboutInference.css", @@ -1260,6 +1094,7 @@ module.exports = [ "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/cleardata/tests/browser/file_css_cache.css", "toolkit/components/extensions/test/mochitest/file_style_bad.css", "toolkit/components/extensions/test/mochitest/file_style_good.css", "toolkit/components/extensions/test/mochitest/file_style_redirect.css", @@ -1271,6 +1106,7 @@ module.exports = [ "toolkit/components/printing/content/printPagination.css", "toolkit/components/printing/content/printPreview.css", "toolkit/components/printing/content/simplifyMode.css", + "toolkit/components/resistfingerprinting/content/letterboxing.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", @@ -1279,11 +1115,18 @@ module.exports = [ "toolkit/content/aboutMozilla.css", "toolkit/content/aboutTelemetry.css", "toolkit/content/aboutwebrtc/aboutWebrtc.css", + "toolkit/content/tests/widgets/videomask.css", "toolkit/content/widgets/infobar.css", + "toolkit/content/widgets/moz-button/moz-button.css", "toolkit/content/widgets/moz-input-common.css", "toolkit/content/widgets/moz-input-text/moz-input-text.css", "toolkit/content/widgets/moz-message-bar/moz-message-bar.css", "toolkit/content/widgets/moz-page-nav/moz-page-nav-button.css", + "toolkit/content/widgets/moz-page-nav/moz-page-nav.css", + "toolkit/content/widgets/moz-reorderable-list/moz-reorderable-list.css", + "toolkit/content/widgets/moz-toggle/moz-toggle.css", + "toolkit/content/widgets/panel-list/panel-item.css", + "toolkit/content/widgets/panel-list/panel-list.css", "toolkit/content/xul.css", "toolkit/crashreporter/content/crashes.css", "toolkit/mozapps/extensions/content/aboutaddons.css", @@ -1298,6 +1141,7 @@ module.exports = [ "toolkit/themes/osx/global/richlistbox.css", "toolkit/themes/osx/mozapps/handling/handling.css", "toolkit/themes/osx/mozapps/update/updates.css", + "toolkit/themes/shared/aboutCache.css", "toolkit/themes/shared/aboutHttpsOnlyError.css", "toolkit/themes/shared/aboutNetError.css", "toolkit/themes/shared/aboutReader.css", @@ -1321,6 +1165,7 @@ module.exports = [ "toolkit/themes/shared/popup.css", "toolkit/themes/shared/popupnotification.css", "toolkit/themes/shared/radio.css", + "toolkit/themes/shared/splitter.css", "toolkit/themes/shared/toolbar.css", "toolkit/themes/shared/toolbarbutton.css", "toolkit/themes/shared/tree/tree.css", diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/config.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/config.mjs @@ -15,6 +15,72 @@ import { createRawValuesObject } from "./helpers.mjs"; * @property {Record<string, string>} [customFixes] Map of raw values to their token replacements for autofix */ +const customColorFixes = { + "#000": "black", + "#000000": "black", + "#fff": "white", + "#ffffff": "white", +}; + +/** @type {PropertyTypeConfig} */ +const BackgroundColor = { + allow: [ + "transparent", + "currentColor", + "auto", + "normal", + "none", + "white", + "black", + ], + tokenTypes: ["background-color"], + customFixes: customColorFixes, +}; + +/** @type {PropertyTypeConfig} */ +const BackgroundAttachment = { + allow: ["scroll", "fixed", "local"], +}; + +/** @type {PropertyTypeConfig} */ +const BackgroundImage = { + allow: ["none"], + allowFunctions: [ + "url", + "linear-gradient", + "radial-gradient", + "conic-gradient", + "repeating-linear-gradient", + "repeating-radial-gradient", + "repeating-conic-gradient", + "image-set", + ], +}; + +/** @type {PropertyTypeConfig} */ +const BackgroundPosition = { + allow: ["top", "bottom", "left", "right", "center"], + tokenTypes: ["size", "space"], + allowUnits: true, +}; + +/** @type {PropertyTypeConfig} */ +const BackgroundSize = { + allow: ["auto", "cover", "contain"], + tokenTypes: ["size", "space", "icon-size"], + allowUnits: true, +}; + +/** @type {PropertyTypeConfig} */ +const BackgroundRepeat = { + allow: ["repeat", "repeat-x", "repeat-y", "no-repeat", "space", "round"], +}; + +/** @type {PropertyTypeConfig} */ +const BackgroundClip = { + allow: ["border-box", "padding-box", "content-box"], +}; + /** @type {PropertyTypeConfig} */ const BoxShadow = { allow: ["none"], @@ -60,12 +126,7 @@ const FontWeight = { const TextColor = { allow: ["currentColor", "white", "black"], tokenTypes: ["text-color"], - customFixes: { - "#000": "black", - "#000000": "black", - "#fff": "white", - "#ffffff": "white", - }, + customFixes: customColorFixes, }; /** @@ -78,6 +139,23 @@ const TextColor = { /** @type {Record<string, PropertyConfig>} */ export const propertyConfig = { + "background-color": { + validTypes: [BackgroundColor], + }, + background: { + validTypes: [ + BackgroundColor, + BackgroundImage, + BackgroundPosition, + BackgroundSize, + BackgroundRepeat, + BackgroundAttachment, + BackgroundClip, + ], + shorthand: true, + multiple: true, + slash: true, + }, "box-shadow": { validTypes: [BoxShadow], multiple: true, diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/rules/index.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/rules/index.mjs @@ -9,7 +9,6 @@ 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 useBackgroundColorTokens from "./use-background-color-tokens.mjs"; import useDesignTokens from "./use-design-tokens.mjs"; import noNonSemanticTokenUsage from "./no-non-semantic-token-usage.mjs"; import useSizeTokens from "./use-size-tokens.mjs"; @@ -20,7 +19,6 @@ export default { "use-border-radius-tokens": useBorderRadiusTokens, "use-border-color-tokens": useBorderColorTokens, "use-space-tokens": useSpaceTokens, - "use-background-color-tokens": useBackgroundColorTokens, "use-design-tokens": useDesignTokens, "no-non-semantic-token-usage": noNonSemanticTokenUsage, "use-size-tokens": useSizeTokens, diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/rules/use-background-color-tokens.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/rules/use-background-color-tokens.mjs @@ -1,121 +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, - createAllowList, - getLocalCustomProperties, - getColorProperties, - isValidValue, -} from "../helpers.mjs"; - -const { - utils: { report, ruleMessages, validateOptions }, -} = stylelint; - -// Name our rule, set the error message, and link to meta -const ruleName = namespace("use-background-color-tokens"); - -const messages = ruleMessages(ruleName, { - rejected: value => `${value} should use a background-color design token.`, -}); - -const meta = { - url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-background-color-tokens.html", - fixable: true, -}; - -// Gather an array of the ready css `['var(--token-name)']` -const INCLUDE_CATEGORIES = ["background-color"]; - -const tokenCSS = createTokenNamesArray(INCLUDE_CATEGORIES); - -// Allowed border-color values in CSS -const ALLOW_LIST = createAllowList([ - "transparent", - "currentColor", - "auto", - "normal", - "none", - "white", - "black", -]); - -const CSS_PROPERTIES = ["background", "background-color"]; - -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 => { - const { prop, value } = declarations; - - // If the property is not in our list to check, skip it - if (!CSS_PROPERTIES.includes(prop)) { - return; - } - - // This rule only cares about colors, so all other shorthand properties are ignored - const colorProperties = getColorProperties(value); - const allColorsAreValid = colorProperties.every(property => - isValidValue(property, tokenCSS, cssCustomProperties, ALLOW_LIST) - ); - - if (allColorsAreValid) { - 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-background-color-tokens.tests.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/tests/use-background-color-tokens.tests.mjs @@ -1,411 +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/PL/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 useBackgroundColorTokens from "../rules/use-background-color-tokens.mjs"; - -let plugin = stylelint.createPlugin( - useBackgroundColorTokens.ruleName, - useBackgroundColorTokens -); -let { - ruleName, - rule: { messages }, -} = plugin; - -testRule({ - plugins: [plugin], - ruleName, - config: true, - fix: false, - accept: [ - { - code: ".bg { background-color: var(--background-color-box); }", - description: "Using background-color token is valid.", - }, - { - code: ".bg { background-color: var(--background-color-box, #666); }", - description: - "Using background-color token with a raw color fallback is valid.", - }, - { - code: ".bg { background-color: var(--background-color-box, var(--another-token)); }", - description: - "Using background-color token with a variable fallback is valid.", - }, - { - code: ` - :root { --custom-token: var(--background-color-box); } - .bg { background-color: var(--custom-token); } - `, - description: - "Using a custom token that resolves to a background-color token is valid.", - }, - { - code: ".bg { background-color: inherit; }", - description: "Using a keyword is valid.", - }, - { - code: ".bg { background-color: initial; }", - description: "Using a keyword is valid.", - }, - { - code: ".bg { background-color: revert; }", - description: "Using a keyword is valid.", - }, - { - code: ".bg { background-color: revert-layer; }", - description: "Using a keyword is valid.", - }, - { - code: ".bg { background-color: unset; }", - description: "Using a keyword is valid.", - }, - { - code: ".bg { background-color: transparent; }", - description: "Using a keyword is valid.", - }, - { - code: ".bg { background-color: currentColor; }", - description: "Using a keyword is valid.", - }, - { - code: ".bg { background-color: auto; }", - description: "Using a keyword is valid.", - }, - { - code: ".bg { background-color: normal; }", - description: "Using a keyword is valid.", - }, - { - code: ".bg { background-color: none; }", - description: "Using a keyword is valid.", - }, - { - code: ".bg { background: var(--background-color-box); }", - description: "Using background-color token is valid in the shorthand.", - }, - { - code: ".bg { background: var(--background-color-box, #666); }", - description: - "Using background-color token with a raw color fallback is valid in the shorthand.", - }, - { - code: ".bg { background: var(--background-color-box, var(--another-token)); }", - description: - "Using background-color token with a token fallback is valid in the shorthand.", - }, - { - code: ` - :root { --custom-token: var(--background-color-box); } - .bg { background: var(--custom-token); } - `, - description: - "Using a custom token that resolves to a background-color token is valid in the shorthand.", - }, - { - code: ".bg { background: url('image.png'); }", - description: - "Using the background shorthand without any color declarations is valid.", - }, - { - code: ".bg { background: linear-gradient(to bottom, #fff, #000) var(--background-color-box); }", - description: - "Using the background shorthand, other properties plus a background-color token is valid.", - }, - { - code: ".bg { background: url('image.png') no-repeat center center / auto var(--background-color-box, oklch(69% 0.19 15)); }", - description: - "Using a background-color token with a raw color value fallback is valid in the shorthand.", - }, - { - code: ".bg { background: url('image.png') fixed content-box var(--background-color-box, var(--another-token)); }", - description: - "Using a background-color token with another token fallback is valid in the shorthand.", - }, - { - code: ` - :root { --custom-token: var(--background-color-box); } - .bg { background: url('image.png') var(--custom-token) repeat-y fixed; } - `, - description: - "Using a custom token that resolves to a background-color token is valid in the shorthand.", - }, - { - code: ".bg { background: inherit; }", - description: "Using a keyword is valid in the shorthand.", - }, - { - code: ".bg { background: initial; }", - description: "Using a keyword is valid in the shorthand.", - }, - { - code: ".bg { background: revert; }", - description: "Using a keyword is valid in the shorthand.", - }, - { - code: ".bg { background: revert-layer; }", - description: "Using a keyword is valid in the shorthand.", - }, - { - code: ".bg { background: unset; }", - description: "Using a keyword is valid in the shorthand.", - }, - { - code: ".bg { background: transparent; }", - description: "Using a keyword is valid in the shorthand.", - }, - { - code: ".bg { background: currentColor; }", - description: "Using a keyword is valid in the shorthand.", - }, - { - code: ".bg { background: auto; }", - description: "Using a keyword is valid in the shorthand.", - }, - { - code: ".bg { background: normal; }", - description: "Using a keyword is valid in the shorthand.", - }, - { - code: ".bg { background: none; }", - description: "Using a keyword is valid in the shorthand.", - }, - ], - - reject: [ - { - code: ".bg { background-color: #666; }", - message: messages.rejected("#666"), - description: "#666 should use a background-color design token.", - }, - { - code: ".bg { background-color: #fff0; }", - message: messages.rejected("#fff0"), - description: "#fff0 should use a background-color design token.", - }, - { - code: ".bg { background-color: #666666; }", - message: messages.rejected("#666666"), - description: "#666666 should use a background-color design token.", - }, - { - code: ".bg { background-color: #ffffff00; }", - message: messages.rejected("#ffffff00"), - description: "#ffffff00 should use a background-color design token.", - }, - { - code: ".bg { background-color: oklch(69% 0.19 15); }", - message: messages.rejected("oklch(69% 0.19 15)"), - description: - "oklch(69% 0.19 15) should use a background-color design token.", - }, - { - code: ".bg { background-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 background-color design token.", - }, - { - code: ".bg { background-color: ButtonFace; }", - message: messages.rejected("ButtonFace"), - description: "ButtonFace should use a background-color design token.", - }, - { - code: ".bg { background-color: var(--random-token, oklch(69% 0.19 15)); }", - message: messages.rejected("var(--random-token, oklch(69% 0.19 15))"), - description: - "var(--random-token, oklch(69% 0.19 15)) should use a background-color design token.", - }, - { - code: ` - :root { --custom-token: #666; } - .bg { background-color: var(--custom-token); } - `, - message: messages.rejected("var(--custom-token)"), - description: - "var(--custom-token) should use a background-color design token.", - }, - { - code: ".bg { background: #666; }", - message: messages.rejected("#666"), - description: "#666 should use a background-color design token.", - }, - { - code: ".bg { background: #fff0; }", - message: messages.rejected("#fff0"), - description: "#fff0 should use a background-color design token.", - }, - { - code: ".bg { background: #666666; }", - message: messages.rejected("#666666"), - description: "#666666 should use a background-color design token.", - }, - { - code: ".bg { background: #ffffff00; }", - message: messages.rejected("#ffffff00"), - description: "#ffffff00 should use a background-color design token.", - }, - { - code: ".bg { background: oklch(69% 0.19 15); }", - message: messages.rejected("oklch(69% 0.19 15)"), - description: - "oklch(69% 0.19 15) should use a background-color design token.", - }, - { - code: ".bg { background: 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 background-color design token.", - }, - { - code: ".bg { background: border-box #666; }", - message: messages.rejected("border-box #666"), - description: - "border-box #666 should use a background-color design token.", - }, - { - code: ".bg { background: url('image.png') #fff0, #666; }", - message: messages.rejected("url('image.png') #fff0, #666"), - description: - "url('image.png') #fff0, #666 should use a background-color design token.", - }, - { - code: ".bg { background: url('image.png') oklch(69% 0.19 15) repeat-y; }", - message: messages.rejected( - "url('image.png') oklch(69% 0.19 15) repeat-y" - ), - description: - "url('image.png') oklch(69% 0.19 15) repeat-y should use a background-color design token.", - }, - { - code: ".bg { background: url('image.png') top center fixed #ffffff00; }", - message: messages.rejected("url('image.png') top center fixed #ffffff00"), - description: - "url('image.png') top center fixed #ffffff00 should use a background-color design token.", - }, - { - code: ".bg { background: url('image.png') center left / auto no-repeat scroll content-box padding-box red, rgba(42 42 42 / 0.15); }", - message: messages.rejected( - "url('image.png') center left / auto no-repeat scroll content-box padding-box red, rgba(42 42 42 / 0.15)" - ), - description: - "url('image.png') center left / auto no-repeat scroll content-box padding-box red, rgba(42 42 42 / 0.15) should use a background-color design token.", - }, - { - code: ".bg { background: url('image.png') var(--random-token, rgba(42 42 42 / 0.15)); }", - message: messages.rejected( - "url('image.png') var(--random-token, rgba(42 42 42 / 0.15))" - ), - description: - "url('image.png') var(--random-token, rgba(42 42 42 / 0.15)) should use a background-color design token.", - }, - { - code: ".bg { background: url('image.png') Canvas; }", - message: messages.rejected("url('image.png') Canvas"), - description: - "url('image.png') Canvas should use a background-color design token.", - }, - { - code: ` - :root { --custom-token: #666666; } - .bg { background: url('image.png') no-repeat center / auto var(--custom-token); } - `, - message: messages.rejected( - "url('image.png') no-repeat center / auto var(--custom-token)" - ), - description: - "url('image.png') no-repeat center / auto var(--custom-token) should use a background-color design token.", - }, - ], -}); - -testRule({ - plugins: [plugin], - ruleName, - config: true, - fix: true, - reject: [ - { - code: ".bg { background-color: #fff; }", - fixed: ".bg { background-color: white; }", - message: messages.rejected("#fff"), - description: "#fff should be fixed to white.", - }, - { - code: ".bg { background-color: #ffffff; }", - fixed: ".bg { background-color: white; }", - message: messages.rejected("#ffffff"), - description: "#ffffff should be fixed to white.", - }, - { - code: ".bg { background-color: #FFF; }", - fixed: ".bg { background-color: white; }", - message: messages.rejected("#FFF"), - description: "#FFF should be fixed to white.", - }, - { - code: ".bg { background-color: #FFFFFF; }", - fixed: ".bg { background-color: white; }", - message: messages.rejected("#FFFFFF"), - description: "#FFFFFF should be fixed to white.", - }, - { - code: ".bg { background-color: #000; }", - fixed: ".bg { background-color: black; }", - message: messages.rejected("#000"), - description: "#000 should be fixed to black.", - }, - { - code: ".bg { background-color: #000000; }", - fixed: ".bg { background-color: black; }", - message: messages.rejected("#000000"), - description: "#000000 should be fixed to black.", - }, - { - code: ".bg { background: #fff; }", - fixed: ".bg { background: white; }", - message: messages.rejected("#fff"), - description: "#fff should be fixed to white in background shorthand.", - }, - { - code: ".bg { background: #ffffff; }", - fixed: ".bg { background: white; }", - message: messages.rejected("#ffffff"), - description: "#ffffff should be fixed to white in background shorthand.", - }, - { - code: ".bg { background: #000; }", - fixed: ".bg { background: black; }", - message: messages.rejected("#000"), - description: "#000 should be fixed to black in background shorthand.", - }, - { - code: ".bg { background: #000000; }", - fixed: ".bg { background: black; }", - message: messages.rejected("#000000"), - description: "#000000 should be fixed to black in background shorthand.", - }, - { - code: ".bg { background: url('image.png') #fff; }", - fixed: ".bg { background: url('image.png') white; }", - message: messages.rejected("url('image.png') #fff"), - description: - "#fff should be fixed to white in background shorthand with other properties.", - }, - { - code: ".bg { background: url('image.png') #000 repeat-y; }", - fixed: ".bg { background: url('image.png') black repeat-y; }", - message: messages.rejected("url('image.png') #000 repeat-y"), - description: - "#000 should be fixed to black in background shorthand with other properties.", - }, - ], -}); diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/tests/use-design-tokens.background-color.tests.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/tests/use-design-tokens.background-color.tests.mjs @@ -0,0 +1,549 @@ +/** + * 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/. + */ + +// 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: [ + { + code: ".bg { background-color: var(--background-color-box); }", + description: "Using background-color token is valid.", + }, + { + code: ".bg { background-color: var(--background-color-box, #666); }", + description: + "Using background-color token with a raw color fallback is valid.", + }, + { + code: ".bg { background-color: var(--background-color-box, var(--another-token)); }", + description: + "Using background-color token with a variable fallback is valid.", + }, + { + code: ` + :root { --custom-token: var(--background-color-box); } + .bg { background-color: var(--custom-token); } + `, + description: + "Using a custom token that resolves to a background-color token is valid.", + }, + { + code: ".bg { background-color: inherit; }", + description: "Using a keyword is valid.", + }, + { + code: ".bg { background-color: initial; }", + description: "Using a keyword is valid.", + }, + { + code: ".bg { background-color: revert; }", + description: "Using a keyword is valid.", + }, + { + code: ".bg { background-color: revert-layer; }", + description: "Using a keyword is valid.", + }, + { + code: ".bg { background-color: unset; }", + description: "Using a keyword is valid.", + }, + { + code: ".bg { background-color: transparent; }", + description: "Using a keyword is valid.", + }, + { + code: ".bg { background-color: currentColor; }", + description: "Using a keyword is valid.", + }, + { + code: ".bg { background-color: auto; }", + description: "Using a keyword is valid.", + }, + { + code: ".bg { background-color: normal; }", + description: "Using a keyword is valid.", + }, + { + code: ".bg { background-color: none; }", + description: "Using a keyword is valid.", + }, + { + code: ".bg { background: var(--background-color-box); }", + description: "Using background-color token is valid in the shorthand.", + }, + { + code: ".bg { background: var(--background-color-box, #666); }", + description: + "Using background-color token with a raw color fallback is valid in the shorthand.", + }, + { + code: ".bg { background: var(--background-color-box, var(--another-token)); }", + description: + "Using background-color token with a token fallback is valid in the shorthand.", + }, + { + code: ` + :root { --custom-token: var(--background-color-box); } + .bg { background: var(--custom-token); } + `, + description: + "Using a custom token that resolves to a background-color token is valid in the shorthand.", + }, + { + code: ".bg { background: url('image.png'); }", + description: + "Using the background shorthand without any color declarations is valid.", + }, + { + code: ".bg { background: linear-gradient(to bottom, #fff, #000) var(--background-color-box); }", + description: + "Using the background shorthand, other properties plus a background-color token is valid.", + }, + { + code: ".bg { background: url('image.png') no-repeat center center / auto var(--background-color-box, oklch(69% 0.19 15)); }", + description: + "Using a background-color token with a raw color value fallback is valid in the shorthand.", + }, + { + code: ".bg { background: url('image.png') fixed content-box var(--background-color-box, var(--another-token)); }", + description: + "Using a background-color token with another token fallback is valid in the shorthand.", + }, + { + code: ` + :root { --custom-token: var(--background-color-box); } + .bg { background: url('image.png') var(--custom-token) repeat-y fixed; } + `, + description: + "Using a custom token that resolves to a background-color token is valid in the shorthand.", + }, + { + code: ".bg { background: inherit; }", + description: "Using a keyword is valid in the shorthand.", + }, + { + code: ".bg { background: initial; }", + description: "Using a keyword is valid in the shorthand.", + }, + { + code: ".bg { background: revert; }", + description: "Using a keyword is valid in the shorthand.", + }, + { + code: ".bg { background: revert-layer; }", + description: "Using a keyword is valid in the shorthand.", + }, + { + code: ".bg { background: unset; }", + description: "Using a keyword is valid in the shorthand.", + }, + { + code: ".bg { background: transparent; }", + description: "Using a keyword is valid in the shorthand.", + }, + { + code: ".bg { background: currentColor; }", + description: "Using a keyword is valid in the shorthand.", + }, + { + code: ".bg { background: auto; }", + description: "Using a keyword is valid in the shorthand.", + }, + { + code: ".bg { background: normal; }", + description: "Using a keyword is valid in the shorthand.", + }, + { + code: ".bg { background: none; }", + description: "Using a keyword is valid in the shorthand.", + }, + { + code: ".bg { background-color: calc(2 * var(--background-color-box)); }", + description: "Using calc() with a valid token inside is valid.", + }, + { + code: ".bg { background-color: calc(var(--background-color-box) * -1); }", + description: + "Using calc() with negative number and background-color token is valid.", + }, + { + code: ".bg { background-color: calc(var(--background-color-box) * -0.5); }", + description: + "Using calc() with negative decimal and background-color token is valid.", + }, + { + code: ".bg { background-color: light-dark(var(--background-color-box), var(--background-color-box)); }", + description: "Using light-dark() with valid tokens is valid.", + }, + { + code: ".bg { background-color: light-dark(transparent, transparent); }", + description: "Using light-dark() with valid keywords is valid.", + }, + { + code: ".bg { background-color: color-mix(in srgb, currentColor 10%, transparent); }", + description: "Using color-mix() with valid colors is valid.", + }, + { + code: ".bg { background-color: color-mix(in srgb, var(--background-color-box) 20%, transparent); }", + description: "Using color-mix() with valid token and keyword is valid.", + }, + ], + + reject: [ + { + code: ".bg { background-color: #666; }", + message: messages.rejected("#666", ["background-color"]), + description: "#666 should use a background-color design token.", + }, + { + code: ".bg { background-color: #fff0; }", + message: messages.rejected("#fff0", ["background-color"]), + description: "#fff0 should use a background-color design token.", + }, + { + code: ".bg { background-color: #666666; }", + message: messages.rejected("#666666", ["background-color"]), + description: "#666666 should use a background-color design token.", + }, + { + code: ".bg { background-color: #ffffff00; }", + message: messages.rejected("#ffffff00", ["background-color"]), + description: "#ffffff00 should use a background-color design token.", + }, + { + code: ".bg { background-color: oklch(69% 0.19 15); }", + message: messages.rejected("oklch(69% 0.19 15)", ["background-color"]), + description: + "oklch(69% 0.19 15) should use a background-color design token.", + }, + { + code: ".bg { background-color: rgba(42 42 42 / 0.15); }", + message: messages.rejected("rgba(42 42 42 / 0.15)", ["background-color"]), + description: + "rgba(42 42 42 / 0.15) should use a background-color design token.", + }, + { + code: ".bg { background-color: ButtonFace; }", + message: messages.rejected("ButtonFace", ["background-color"]), + description: "ButtonFace should use a background-color design token.", + }, + { + code: ".bg { background-color: var(--random-token, oklch(69% 0.19 15)); }", + message: messages.rejected("var(--random-token, oklch(69% 0.19 15))", [ + "background-color", + ]), + description: + "var(--random-token, oklch(69% 0.19 15)) should use a background-color design token.", + }, + { + code: ` + :root { --custom-token: #666; } + .bg { background-color: var(--custom-token); } + `, + message: messages.rejected("var(--custom-token)", ["background-color"]), + description: + "var(--custom-token) should use a background-color design token.", + }, + { + code: ".bg { background: #666; }", + message: messages.rejected("#666", [ + "background-color", + "size", + "space", + "icon-size", + ]), + description: "#666 should use a background design token.", + }, + { + code: ".bg { background: #fff0; }", + message: messages.rejected("#fff0", [ + "background-color", + "size", + "space", + "icon-size", + ]), + description: "#fff0 should use a background design token.", + }, + { + code: ".bg { background: #666666; }", + message: messages.rejected("#666666", [ + "background-color", + "size", + "space", + "icon-size", + ]), + description: "#666666 should use a background design token.", + }, + { + code: ".bg { background: #ffffff00; }", + message: messages.rejected("#ffffff00", [ + "background-color", + "size", + "space", + "icon-size", + ]), + description: "#ffffff00 should use a background design token.", + }, + { + code: ".bg { background: oklch(69% 0.19 15); }", + message: messages.rejected("oklch(69% 0.19 15)", [ + "background-color", + "size", + "space", + "icon-size", + ]), + description: "oklch(69% 0.19 15) should use a background design token.", + }, + { + code: ".bg { background: rgba(42 42 42 / 0.15); }", + message: messages.rejected("rgba(42 42 42 / 0.15)", [ + "background-color", + "size", + "space", + "icon-size", + ]), + description: + "rgba(42 42 42 / 0.15) should use a background design token.", + }, + { + code: ".bg { background: border-box #666; }", + message: messages.rejected("border-box #666", [ + "background-color", + "size", + "space", + "icon-size", + ]), + description: "border-box #666 should use a background design token.", + }, + { + code: ".bg { background: url('image.png') #fff0, #666; }", + message: messages.rejected("url('image.png') #fff0, #666", [ + "background-color", + "size", + "space", + "icon-size", + ]), + description: + "url('image.png') #fff0, #666 should use a background design token.", + }, + { + code: ".bg { background: url('image.png') oklch(69% 0.19 15) repeat-y; }", + message: messages.rejected( + "url('image.png') oklch(69% 0.19 15) repeat-y", + ["background-color", "size", "space", "icon-size"] + ), + description: + "url('image.png') oklch(69% 0.19 15) repeat-y should use a background design token.", + }, + { + code: ".bg { background: url('image.png') top center fixed #ffffff00; }", + message: messages.rejected( + "url('image.png') top center fixed #ffffff00", + ["background-color", "size", "space", "icon-size"] + ), + description: + "url('image.png') top center fixed #ffffff00 should use a background design token.", + }, + { + code: ".bg { background: url('image.png') center left / auto no-repeat scroll content-box padding-box red, rgba(42 42 42 / 0.15); }", + message: messages.rejected( + "url('image.png') center left / auto no-repeat scroll content-box padding-box red, rgba(42 42 42 / 0.15)", + ["background-color", "size", "space", "icon-size"] + ), + description: + "url('image.png') center left / auto no-repeat scroll content-box padding-box red, rgba(42 42 42 / 0.15) should use a background design token.", + }, + { + code: ".bg { background: url('image.png') var(--random-token, rgba(42 42 42 / 0.15)); }", + message: messages.rejected( + "url('image.png') var(--random-token, rgba(42 42 42 / 0.15))", + ["background-color", "size", "space", "icon-size"] + ), + description: + "url('image.png') var(--random-token, rgba(42 42 42 / 0.15)) should use a background design token.", + }, + { + code: ".bg { background: url('image.png') Canvas; }", + message: messages.rejected("url('image.png') Canvas", [ + "background-color", + "size", + "space", + "icon-size", + ]), + description: + "url('image.png') Canvas should use a background design token.", + }, + { + code: ` + :root { --custom-token: #666666; } + .bg { background: url('image.png') no-repeat center / auto var(--custom-token); } + `, + message: messages.rejected( + "url('image.png') no-repeat center / auto var(--custom-token)", + ["background-color", "size", "space", "icon-size"] + ), + description: + "url('image.png') no-repeat center / auto var(--custom-token) should use a background design token.", + }, + { + code: ".bg { background-color: calc(2 * #666); }", + message: messages.rejected("calc(2 * #666)", ["background-color"]), + description: "calc() with invalid color inside should be rejected.", + }, + { + code: ".bg { background-color: light-dark(#666, var(--background-color-box)); }", + message: messages.rejected( + "light-dark(#666, var(--background-color-box))", + ["background-color"] + ), + description: "light-dark() with invalid first color should be rejected.", + }, + { + code: ".bg { background-color: light-dark(var(--background-color-box), #666); }", + message: messages.rejected( + "light-dark(var(--background-color-box), #666)", + ["background-color"] + ), + description: "light-dark() with invalid second color should be rejected.", + }, + { + code: ".bg { background-color: color-mix(in srgb, #666 10%, transparent); }", + message: messages.rejected("color-mix(in srgb, #666 10%, transparent)", [ + "background-color", + ]), + description: "color-mix() with invalid first color should be rejected.", + }, + { + code: ".bg { background-color: color-mix(in srgb, currentColor 10%, #666); }", + message: messages.rejected("color-mix(in srgb, currentColor 10%, #666)", [ + "background-color", + ]), + description: "color-mix() with invalid second color should be rejected.", + }, + ], +}); + +testRule({ + plugins: [plugin], + ruleName, + config: true, + fix: true, + reject: [ + { + code: ".bg { background-color: #fff; }", + fixed: ".bg { background-color: white; }", + message: messages.rejected("#fff", ["background-color"], "white"), + description: "#fff should be fixed to white.", + }, + { + code: ".bg { background-color: #ffffff; }", + fixed: ".bg { background-color: white; }", + message: messages.rejected("#ffffff", ["background-color"], "white"), + description: "#ffffff should be fixed to white.", + }, + { + code: ".bg { background-color: #FFF; }", + fixed: ".bg { background-color: white; }", + message: messages.rejected("#FFF", ["background-color"], "white"), + description: "#FFF should be fixed to white.", + }, + { + code: ".bg { background-color: #FFFFFF; }", + fixed: ".bg { background-color: white; }", + message: messages.rejected("#FFFFFF", ["background-color"], "white"), + description: "#FFFFFF should be fixed to white.", + }, + { + code: ".bg { background-color: #000; }", + fixed: ".bg { background-color: black; }", + message: messages.rejected("#000", ["background-color"], "black"), + description: "#000 should be fixed to black.", + }, + { + code: ".bg { background-color: #000000; }", + fixed: ".bg { background-color: black; }", + message: messages.rejected("#000000", ["background-color"], "black"), + description: "#000000 should be fixed to black.", + }, + { + code: ".bg { background: #fff; }", + fixed: ".bg { background: white; }", + message: messages.rejected( + "#fff", + ["background-color", "size", "space", "icon-size"], + "white" + ), + description: "#fff should be fixed to white in background shorthand.", + }, + { + code: ".bg { background: #ffffff; }", + fixed: ".bg { background: white; }", + message: messages.rejected( + "#ffffff", + ["background-color", "size", "space", "icon-size"], + "white" + ), + description: "#ffffff should be fixed to white in background shorthand.", + }, + { + code: ".bg { background: #000; }", + fixed: ".bg { background: black; }", + message: messages.rejected( + "#000", + ["background-color", "size", "space", "icon-size"], + "black" + ), + description: "#000 should be fixed to black in background shorthand.", + }, + { + code: ".bg { background: #000000; }", + fixed: ".bg { background: black; }", + message: messages.rejected( + "#000000", + ["background-color", "size", "space", "icon-size"], + "black" + ), + description: "#000000 should be fixed to black in background shorthand.", + }, + { + code: ".bg { background: url('image.png') #fff; }", + fixed: ".bg { background: url('image.png') white; }", + message: messages.rejected( + "url('image.png') #fff", + ["background-color", "size", "space", "icon-size"], + "url('image.png') white" + ), + description: + "#fff should be fixed to white in background shorthand with other properties.", + }, + { + code: ".bg { background: url('image.png') #000 repeat-y; }", + fixed: ".bg { background: url('image.png') black repeat-y; }", + message: messages.rejected( + "url('image.png') #000 repeat-y", + ["background-color", "size", "space", "icon-size"], + "url('image.png') black repeat-y" + ), + description: + "#000 should be fixed to black in background shorthand with other properties.", + }, + ], +});