Просмотр исходного кода

Upgrade to latest Sass and stylelint configuration, with needed refactorings

- Tweak stylesheets for compatibility with latest stylelint configuration
- Move stylelint config to JS for ease of copying rules with main config
- Enforce scss/no-global-function-names by refactoring code with sass-migrator
- Run Sass code through sass-migrator
- Change stylelint configuration and code to enforce font-family-no-missing-generic-family-keyword
- Manually switch to math.div where migrator used * 0.5
Thibaud Colas 3 лет назад
Родитель
Сommit
23bc6b2670
45 измененных файлов с 226 добавлено и 183 удалено
  1. 3 0
      .stylelintignore
  2. 7 0
      .stylelintrc.js
  3. 0 6
      .stylelintrc.yaml
  4. 3 7
      client/scss/components/_button.scss
  5. 1 1
      client/scss/components/_chooser.scss
  6. 1 0
      client/scss/components/_dropdown.legacy.scss
  7. 3 1
      client/scss/components/_footer.scss
  8. 13 9
      client/scss/components/_forms.scss
  9. 4 2
      client/scss/components/_header.scss
  10. 9 7
      client/scss/components/_help-block.scss
  11. 6 2
      client/scss/components/_icons.scss
  12. 2 1
      client/scss/components/_indicator.scss
  13. 3 3
      client/scss/components/_listing.scss
  14. 3 2
      client/scss/components/_loading-mask.scss
  15. 6 2
      client/scss/components/_main-nav.scss
  16. 0 1
      client/scss/components/_messages.scss
  17. 4 2
      client/scss/components/_status-tag.scss
  18. 3 4
      client/scss/components/_switch.scss
  19. 3 3
      client/scss/components/_tag.scss
  20. 6 5
      client/scss/elements/_forms.scss
  21. 8 6
      client/scss/overrides/_vendor.datetimepicker.scss
  22. 3 2
      client/scss/overrides/_vendor.tagit.scss
  23. 4 3
      client/scss/settings/_variables.icons.scss
  24. 24 21
      client/scss/settings/_variables.scss
  25. 6 8
      client/scss/tools/_functions.breakpoints.scss
  26. 0 1
      client/scss/tools/_mixins.breakpoints.scss
  27. 1 7
      client/scss/tools/_mixins.general.scss
  28. 9 7
      client/scss/tools/_mixins.grid.scss
  29. 30 25
      client/scss/tools/_various.colors.scss
  30. 1 0
      client/src/components/CommentApp/main.scss
  31. 2 1
      client/src/components/Draftail/blocks/ImageBlock.scss
  32. 4 2
      client/src/components/Explorer/Explorer.scss
  33. 1 0
      client/src/components/Hallo/_halloeditor.scss
  34. 0 1
      client/src/components/Hallo/_richtext-image.scss
  35. 4 2
      client/src/components/PageExplorer/PageExplorer.scss
  36. 1 1
      client/src/components/Sidebar/Sidebar.scss
  37. 3 1
      client/src/components/StreamField/scss/_variables.scss
  38. 6 4
      client/src/components/StreamField/scss/components/c-sf-add-panel.scss
  39. 2 2
      client/src/components/StreamField/scss/components/c-sf-block.scss
  40. 5 3
      client/src/components/StreamField/scss/components/c-sf-container.scss
  41. 17 13
      wagtail/admin/static_src/wagtailadmin/scss/layouts/page-editor.scss
  42. 0 3
      wagtail/admin/static_src/wagtailadmin/scss/layouts/report.scss
  43. 12 7
      wagtail/admin/static_src/wagtailadmin/scss/userbar.scss
  44. 0 4
      wagtail/contrib/styleguide/static_src/wagtailstyleguide/scss/styleguide.scss
  45. 3 1
      wagtail/images/static_src/wagtailimages/scss/add-multiple.scss

+ 3 - 0
.stylelintignore

@@ -0,0 +1,3 @@
+node_modules
+venv
+build

+ 7 - 0
.stylelintrc.js

@@ -0,0 +1,7 @@
+module.exports = {
+  extends: '@wagtail/stylelint-config-wagtail',
+  rules: {
+    // Would be valuable for strict BEM components but is too hard to enforce with legacy code.
+    'no-descending-specificity': null,
+  },
+};

+ 0 - 6
.stylelintrc.yaml

@@ -1,6 +0,0 @@
-ignoreFiles:
-  - node_modules
-  - build/**/*
-  - venv/**/*
-extends:
-  - '@wagtail/stylelint-config-wagtail'

+ 3 - 7
client/scss/components/_button.scss

@@ -1,3 +1,4 @@
+@use "sass:color";
 // Core button style
 // Note that these styles include methods to render buttons the same x-browser, described here:
 // http: //cbjdigital.com/blog/2010/08/bulletproof_css_input_button_heights
@@ -214,6 +215,7 @@
         }
     }
 
+    // stylelint-disable-next-line no-duplicate-selectors
     &:hover {
         background-color: $color-button-hover;
         color: $color-white;
@@ -302,12 +304,6 @@
         border: 0;
     }
 
-    &.button--icon {
-        .icon {
-            @include svg-icon(1.5em);
-        }
-    }
-
     &.button-strokeonhover {
         border: 1px solid transparent;
 
@@ -597,7 +593,7 @@ button {
         background-color: $color-white;
         padding: 1em 10em 1em 1.5em; // 10em padding leaves room for controls
         margin-bottom: 1em;
-        border: 1px solid lighten($color-grey-4, 3%); // really trying to avoid creating more greys, but this one is better than grey 4 or 5
+        border: 1px solid color.adjust($color-grey-4, $lightness: 3%); // really trying to avoid creating more greys, but this one is better than grey 4 or 5
     }
 
     &.moving {

+ 1 - 1
client/scss/components/_chooser.scss

@@ -36,7 +36,7 @@ overridden here? hmm.
         // TODO: [icon-font] remove when the Wagtail icon font is removed
         &:before {
             vertical-align: middle;
-            font-family: wagtail;
+            font-family: $font-wagtail-icons;
             content: '';
             // position: relative
             display: inline-block;

+ 1 - 0
client/scss/components/_dropdown.legacy.scss

@@ -329,6 +329,7 @@
 }
 
 // Transitions
+// stylelint-disable-next-line no-duplicate-selectors
 .dropdown ul {
     @include transition(opacity 0.2s linear);
 }

+ 3 - 1
client/scss/components/_footer.scss

@@ -1,3 +1,5 @@
+@use "sass:math";
+
 .footer {
     $border-curvature: 3px;
     @include transition(bottom 0.5s ease 1s);
@@ -82,7 +84,7 @@
     .meta {
         float: right;
         text-align: right;
-        padding: 7px $grid-gutter-width / 2;
+        padding: 7px math.div($grid-gutter-width, 2);
         font-size: 0.85em;
 
         p {

+ 13 - 9
client/scss/components/_forms.scss

@@ -1,3 +1,6 @@
+@use "sass:map";
+@use "sass:math";
+// stylelint-disable scss/comment-no-empty
 // These are the generic stylings for forms of any type.
 // If you're styling something specific to the page editing interface,
 // it probably ought to go in layouts/page-editor.scss
@@ -92,8 +95,8 @@ select::-ms-expand {
         top: 1px;
         bottom: 0;
         width: 1.5em;
-        font-family: wagtail;
-        content: map-get($icons, 'arrow-down');
+        font-family: $font-wagtail-icons;
+        content: map.get($icons, 'arrow-down');
         border: 1px solid $color-input-border;
         border-width: 0 0 0 1px;
         text-align: center;
@@ -134,9 +137,9 @@ select::-ms-expand {
     }
 
     &::before {
-        font-family: wagtail;
+        font-family: $font-wagtail-icons;
         vertical-align: -10%;
-        content: map-get($icons, 'cross');
+        content: map.get($icons, 'cross');
     }
 }
 
@@ -191,7 +194,7 @@ label.required:after {
 
         &:before,
         &:after {
-            font-family: wagtail;
+            font-family: $font-wagtail-icons;
             position: absolute;
             top: 0.5em;
             line-height: 100%;
@@ -246,19 +249,19 @@ label.required:after {
 .date_field,
 .date_time_field {
     .input:before {
-        content: map-get($icons, 'date');
+        content: map.get($icons, 'date');
     }
 }
 
 .time_field {
     .input:before {
-        content: map-get($icons, 'time');
+        content: map.get($icons, 'time');
     }
 }
 
 .url_field {
     .input:before {
-        content: map-get($icons, 'link');
+        content: map.get($icons, 'link');
     }
 }
 
@@ -345,7 +348,7 @@ li.inline .field {
 // solve gutter issues of inline fields
 ul.inline li:first-child,
 li.inline:first-child {
-    margin-left: -$grid-gutter-width / 2;
+    margin-left: math.div(-$grid-gutter-width, 2);
 }
 
 // search-bars
@@ -380,6 +383,7 @@ li.inline:first-child {
 }
 
 // Transitions
+// stylelint-disable-next-line no-duplicate-selectors
 .help {
     @include transition(opacity 0.2s ease);
 }

+ 4 - 2
client/scss/components/_header.scss

@@ -1,3 +1,5 @@
+@use "sass:math";
+
 header {
     padding-top: 1em;
     padding-bottom: 1em;
@@ -67,7 +69,7 @@ header {
             .breadcrumb {
                 margin-left: -$desktop-nice-padding;
                 margin-right: -$desktop-nice-padding;
-                padding-left: $desktop-nice-padding / 2;
+                padding-left: math.div($desktop-nice-padding, 2);
             }
         }
     }
@@ -77,7 +79,7 @@ header {
 
         .breadcrumb {
             margin-bottom: 1rem;
-            padding-left: $desktop-nice-padding / 2; // rather than padding-left: revert;
+            padding-left: math.div($desktop-nice-padding, 2); // rather than padding-left: revert;
         }
     }
 

+ 9 - 7
client/scss/components/_help-block.scss

@@ -1,3 +1,5 @@
+@use "sass:color";
+@use "sass:map";
 // Help text formatters
 .help-block {
     padding: 1em;
@@ -26,17 +28,17 @@
     position: relative;
 
     &:before {
-        font-family: wagtail;
+        font-family: $font-wagtail-icons;
         position: absolute;
         left: 1em;
         top: 0.7em;
-        content: map-get($icons, 'help');
+        content: map.get($icons, 'help');
         font-size: 1.4em;
     }
 }
 
 .help-info {
-    background-color: lighten($color-blue, 30%);
+    background-color: color.adjust($color-blue, $lightness: 30%);
 
     &:before {
         color: $color-blue;
@@ -44,20 +46,20 @@
 }
 
 .help-warning {
-    background-color: lighten($color-orange, 30%);
+    background-color: color.adjust($color-orange, $lightness: 30%);
 
     &:before {
         color: $color-orange;
-        content: map-get($icons, 'warning');
+        content: map.get($icons, 'warning');
     }
 }
 
 .help-critical {
-    background-color: lighten($color-red, 40%);
+    background-color: color.adjust($color-red, $lightness: 40%);
 
     &:before {
         color: $color-red;
-        content: map-get($icons, 'warning');
+        content: map.get($icons, 'warning');
     }
 }
 

+ 6 - 2
client/scss/components/_icons.scss

@@ -1,3 +1,4 @@
+@use "sass:string";
 // The wagtail font isn't available in WOFF2, so a @font-face is set here without a mixin.
 @font-face {
     font-family: 'wagtail';
@@ -29,12 +30,14 @@
     @include icon(); // from _mixins.scss
 }
 
+// stylelint-disable-next-line no-duplicate-selectors
 .icon:after,
 .hallotoolbar [class^='icon-']:after,
 .hallotoolbar [class^='icon-']:after {
     text-align: right;
 }
 
+// stylelint-disable-next-line no-duplicate-selectors
 .hallotoolbar [class^='icon-'],
 .hallotoolbar [class*=' icon-']:before,
 .hallotoolbar [class*=' icon-']:before,
@@ -50,13 +53,13 @@
 
 @each $icon, $content in $icons {
     .icon-#{$icon}:before {
-        content: quote(#{$content});
+        content: string.quote(#{$content});
     }
 }
 
 @each $icon, $content in $icons-after {
     .icon-#{$icon}:after {
-        content: quote(#{$content});
+        content: string.quote(#{$content});
     }
 }
 
@@ -155,6 +158,7 @@ svg.icon-spinner { // TODO: leave only class when iconfont styles are removed
     }
 }
 
+// stylelint-disable-next-line no-duplicate-selectors
 .icon {
     &.initial {
         @include svg-icon(1em);

+ 2 - 1
client/scss/components/_indicator.scss

@@ -1,3 +1,4 @@
+@use "sass:math";
 // =============================================================================
 // Indicator light
 // =============================================================================
@@ -42,7 +43,7 @@ $c-indicator-margin: 0.25rem;
 
     &:before {
         content: '';
-        width: $c-indicator-size / 2;
+        width: math.div($c-indicator-size, 2);
         height: $c-indicator-size;
         position: absolute;
         top: 0;

+ 3 - 3
client/scss/components/_listing.scss

@@ -253,6 +253,7 @@ ul.listing {
         }
     }
 
+    // stylelint-disable-next-line no-duplicate-selectors
     .button-secondary {
         background-color: $color-white;
     }
@@ -450,6 +451,7 @@ ul.listing {
     word-wrap: break-word;
 }
 
+// stylelint-disable-next-line no-duplicate-selectors
 ul.listing {
     border-top: 1px dashed $color-input-border;
     margin-bottom: 2em;
@@ -534,9 +536,6 @@ table.listing {
 
     ul {
         @include unlist();
-    }
-
-    ul {
         margin-top: -1.7em;
     }
 
@@ -739,6 +738,7 @@ table.listing {
     }
 }
 
+// stylelint-disable no-duplicate-selectors
 
 // Transitions
 .listing {

+ 3 - 2
client/scss/components/_loading-mask.scss

@@ -1,3 +1,4 @@
+@use "sass:map";
 // Loading mask: overlays a certain area with a loading spinner and a faded out cover to prevent interaction
 .loading-mask {
     &.loading {
@@ -26,9 +27,9 @@
             left: 50%;
             top: 50%;
             margin: -15px 0 0 -15px;
-            font-family: wagtail;
+            font-family: $font-wagtail-icons;
             animation: spin-wag 0.5s infinite linear;
-            content: map-get($icons, 'spinner');
+            content: map.get($icons, 'spinner');
             z-index: 2;
             color: $color-teal;
         }

+ 6 - 2
client/scss/components/_main-nav.scss

@@ -1,3 +1,5 @@
+@use "sass:map";
+
 .nav-wrapper {
     position: relative;
     margin-left: -$menu-width;
@@ -257,10 +259,10 @@
         }
 
         &:before {
-            font-family: wagtail;
+            font-family: $font-wagtail-icons;
             font-weight: 200;
             text-transform: none;
-            content: map-get($icons, 'search');
+            content: map.get($icons, 'search');
             display: block;
             height: 100%;
             line-height: 3.3em;
@@ -508,6 +510,7 @@ body.explorer-open {
     z-index: 5;
 }
 
+// stylelint-disable-next-line no-duplicate-selectors
 .nav-wrapper {
     z-index: 2;
 }
@@ -520,6 +523,7 @@ body.explorer-open {
 // .content-wrapper {
 // z-index: 3;
 // }
+// stylelint-disable-next-line no-duplicate-selectors
 .nav-submenu {
     z-index: 6;
 }

+ 0 - 1
client/scss/components/_messages.scss

@@ -1,6 +1,5 @@
 // Messages are specific to Django's 'Messaging' system which adds messages into the session,
 // for display on the next page visited. These appear as an animated banner at the top of the page.
-//
 // For inline help text, see typography.scss
 .messages {
     position: relative;

+ 4 - 2
client/scss/components/_status-tag.scss

@@ -1,11 +1,13 @@
+@use "sass:color";
+
 .status-tag {
     border-radius: 2px;
     text-align: center;
     display: inline-block;
     text-transform: uppercase;
     padding: 0 0.5em;
-    border: 1px solid lighten($color-grey-2, 30%);
-    color: lighten($color-grey-2, 30%);
+    border: 1px solid color.adjust($color-grey-2, $lightness: 30%);
+    color: color.adjust($color-grey-2, $lightness: 30%);
     -webkit-font-smoothing: auto;
     line-height: 19px;
     font-size: 0.8em;

+ 3 - 4
client/scss/components/_switch.scss

@@ -1,9 +1,11 @@
+@use "sass:math";
+
 $switch-width: 40px;
 $switch-height: 20px;
 $switch-border: 2px;
 $switch-outline: 3px;
 
-$switch-border-radius: ($switch-height + $switch-border * 2) / 2;
+$switch-border-radius: math.div(($switch-height + $switch-border * 2), 2);
 $switch-outline-radius: $switch-border-radius + $switch-outline;
 
 // All the greys in Wagtail are really dark or really bright
@@ -67,9 +69,6 @@ $switch-color-middle-grey: #777;
 
     [type=checkbox]:disabled + &__toggle::after {
         opacity: 0.5;
-    }
-
-    [type=checkbox]:disabled + &__toggle::after {
         box-shadow: none;
     }
 

+ 3 - 3
client/scss/components/_tag.scss

@@ -1,18 +1,18 @@
+@use "sass:map";
 // free tagging tags from taggit
 .tag {
     border-radius: 2px;
     background-color: $color-teal;
-    padding-right: 0.5em;
     padding: 0.2em 0.5em;
     color: $color-white;
     line-height: 2em;
     white-space: nowrap;
 
     &:before {
-        font-family: wagtail;
+        font-family: $font-wagtail-icons;
         display: inline-block;
         color: $color-white;
-        content: map-get($icons, 'tag');
+        content: map.get($icons, 'tag');
         padding-right: 0.5em;
     }
 

+ 6 - 5
client/scss/elements/_forms.scss

@@ -1,3 +1,4 @@
+@use "sass:map";
 // These are the generic stylings for forms of any type.
 // If you're styling something specific to the page editing interface,
 // it probably ought to go in layouts/page-editor.scss
@@ -168,7 +169,7 @@ input[type=radio] {
 
 input[type=radio]:before {
     border-radius: 100%;
-    font-family: wagtail;
+    font-family: $font-wagtail-icons;
     font-style: normal;
     text-align: center;
     position: absolute;
@@ -176,7 +177,7 @@ input[type=radio]:before {
     left: -2px;
     cursor: pointer;
     display: block;
-    content: map-get($icons, 'radio-full');
+    content: map.get($icons, 'radio-full');
     width: 1em;
     height: 1em;
     line-height: 1.1em;
@@ -187,7 +188,7 @@ input[type=radio]:before {
 }
 
 input[type=radio]:checked:before {
-    content: map-get($icons, 'radio-full');
+    content: map.get($icons, 'radio-full');
     color: $color-teal;
 }
 
@@ -199,7 +200,7 @@ input[type=checkbox] {
 }
 
 input[type=checkbox]:before {
-    font-family: wagtail;
+    font-family: $font-wagtail-icons;
     font-style: normal;
     text-align: center;
     position: absolute;
@@ -216,7 +217,7 @@ input[type=checkbox]:before {
 }
 
 input[type=checkbox]:checked:before {
-    content: map-get($icons, 'tick');
+    content: map.get($icons, 'tick');
 }
 
 input[type=checkbox][disabled]:before {

+ 8 - 6
client/scss/overrides/_vendor.datetimepicker.scss

@@ -1,3 +1,5 @@
+@use "sass:map";
+
 .xdsoft_datetimepicker {
     box-shadow: 0 5px 10px -5px rgba(0, 0, 0, 0.4);
     background: $color-white;
@@ -68,7 +70,7 @@
 
         &:before {
             font-size: 1.5em;
-            font-family: wagtail;
+            font-family: $font-wagtail-icons;
             width: 1em;
             line-height: 1.3em;
             text-align: center;
@@ -84,7 +86,7 @@
         float: left;
 
         &:before {
-            content: map-get($icons, 'arrow-left');
+            content: map.get($icons, 'arrow-left');
         }
     }
 
@@ -93,7 +95,7 @@
         margin-left: 5px;
 
         &:before {
-            content: map-get($icons, 'home');
+            content: map.get($icons, 'home');
         }
     }
 
@@ -101,7 +103,7 @@
         float: right;
 
         &:before {
-            content: map-get($icons, 'arrow-right');
+            content: map.get($icons, 'arrow-right');
         }
     }
 
@@ -127,11 +129,11 @@
         }
 
         .xdsoft_prev:before {
-            content: map-get($icons, 'arrow-up');
+            content: map.get($icons, 'arrow-up');
         }
 
         .xdsoft_next:before {
-            content: map-get($icons, 'arrow-down');
+            content: map.get($icons, 'arrow-down');
         }
 
         .xdsoft_time_box {

+ 3 - 2
client/scss/overrides/_vendor.tagit.scss

@@ -1,3 +1,4 @@
+@use "sass:map";
 // taggit tagging
 .tagit {
     padding: 0.6em 1.2em;
@@ -31,10 +32,10 @@
     }
 
     .ui-icon-close:before {
-        font-family: wagtail;
+        font-family: $font-wagtail-icons;
         display: block;
         color: $color-grey-3;
-        content: map-get($icons, 'cross');
+        content: map.get($icons, 'cross');
     }
 
     .ui-icon-close:hover:before {

+ 4 - 3
client/scss/settings/_variables.icons.scss

@@ -1,3 +1,4 @@
+@use "sass:map";
 $icons: (
     'arrow-down-big': '\e030',
     'arrow-down': '\e01a',
@@ -84,7 +85,7 @@ $icons: (
 );
 
 $icons-after: (
-    'arrow-down-after': map-get($icons, 'arrow-down'),
-    'arrow-right-after': map-get($icons, 'arrow-right'),
-    'arrow-up-after': map-get($icons, 'arrow-up'),
+    'arrow-down-after': map.get($icons, 'arrow-down'),
+    'arrow-right-after': map.get($icons, 'arrow-right'),
+    'arrow-up-after': map.get($icons, 'arrow-up'),
 );

+ 24 - 21
client/scss/settings/_variables.scss

@@ -1,3 +1,4 @@
+@use "sass:color";
 // paths
 
 // We can't use absolute paths here, because those are dependent on Django's
@@ -48,13 +49,13 @@ $color-white: #fff;
 $color-black: #000;
 
 // darker to lighter
-$color-grey-1: darken($color-white, 80);
-$color-grey-2: darken($color-white, 70);
-$color-grey-3: darken($color-white, 15);
-$color-grey-4: darken($color-white, 10);
-$color-grey-5: darken($color-white, 2);
+$color-grey-1: color.adjust($color-white, $lightness: -80%);
+$color-grey-2: color.adjust($color-white, $lightness: -70%);
+$color-grey-3: color.adjust($color-white, $lightness: -15%);
+$color-grey-4: color.adjust($color-white, $lightness: -10%);
+$color-grey-5: color.adjust($color-white, $lightness: -2%);
 
-$color-menu-text: darken($color-white, 20);
+$color-menu-text: color.adjust($color-white, $lightness: -20%);
 
 $color-thead-bg: $color-grey-5;
 $color-header-bg: $color-teal;
@@ -63,16 +64,16 @@ $color-fieldset-hover: $color-grey-5;
 $color-input-border: $color-grey-4;
 $color-input-focus: var(--color-input-focus);
 $color-input-focus-border: var(--color-input-focus-border);
-$color-input-error-bg: lighten(saturate($color-red, 28), 45);
+$color-input-error-bg: color.adjust(color.adjust($color-red, $saturation: 28%), $lightness: 45%);
 
 $color-button: $color-teal;
 $color-button-hover: $color-teal-darker;
 $color-button-yes: $color-green-dark;
-$color-button-yes-hover: darken($color-button-yes, 8%);
+$color-button-yes-hover: color.adjust($color-button-yes, $lightness: -8%);
 $color-button-no: $color-red-dark;
-$color-button-no-hover: darken($color-button-no, 20%);
+$color-button-no-hover: color.adjust($color-button-no, $lightness: -20%);
 $color-button-warning: $color-orange-dark;
-$color-button-warning-hover: darken($color-button-warning, 20%);
+$color-button-warning-hover: color.adjust($color-button-warning, $lightness: -20%);
 
 $color-link: $color-teal-darker;
 $color-link-hover: $color-teal-dark;
@@ -81,8 +82,8 @@ $color-link-hover: $color-teal-dark;
 // because it shouldn’t be reused for anything else in the UI.
 $color-focus-outline: #ffbf47;
 
-$color-text-base: darken($color-white, 85);
-$color-text-input: darken($color-white, 90);
+$color-text-base: color.adjust($color-white, $lightness: -85%);
+$color-text-input: color.adjust($color-white, $lightness: -90%);
 
 // Color states
 $color-state-live: #59b524;
@@ -98,6 +99,8 @@ $system-color-button-text: ButtonText;
 // Fonts
 $font-sans: Open Sans, Arial, sans-serif;
 $font-serif: Roboto Slab, Georgia, serif;
+// Legacy icon font, to be removed in the near future.
+$font-wagtail-icons: wagtail;
 
 // misc sizing
 $thumbnail-width: 130px;
@@ -123,12 +126,12 @@ $draftail-editor-z-index: $nav-wrapper-inner-z-index + 1;
 $object-title-height: 40px;
 
 // Nav
-$nav-grey-1: darken($color-white, 80);
-$nav-grey-2: darken($color-white, 60);
+$nav-grey-1: color.adjust($color-white, $lightness: -80%);
+$nav-grey-2: color.adjust($color-white, $lightness: -60%);
 $nav-grey-3: #262626;
 $nav-item-hover-bg: rgba(100, 100, 100, 0.15);
-$nav-item-active-bg: darken($color-white, 90);
-$nav-submenu-bg: darken($color-white, 85);
+$nav-item-active-bg: color.adjust($color-white, $lightness: -90%);
+$nav-submenu-bg: color.adjust($color-white, $lightness: -85%);
 $nav-footer-account-bg: $nav-item-active-bg;
 $nav-footer-submenu-bg: $nav-submenu-bg;
 $nav-footer-closed-height: 50px;
@@ -136,14 +139,14 @@ $nav-footer-submenu-height: 77px;
 $nav-footer-open-height: $nav-footer-closed-height + $nav-footer-submenu-height;
 
 // Nav search
-$nav-search-color: darken($color-white, 20);
-$nav-search-border: darken($color-white, 40);
+$nav-search-color: color.adjust($color-white, $lightness: -20%);
+$nav-search-border: color.adjust($color-white, $lightness: -40%);
 $nav-search-bg: $nav-grey-1;
 $nav-search-hover-bg: $nav-item-hover-bg;
 $nav-search-focus-color: $color-white;
 $nav-search-focus-bg: $nav-item-hover-bg;
 
 // Form Errors
-$color-text-error: change-color($color-red, $saturation: 69, $lightness: 52);
-$color-text-error-forced-color: change-color($color-red, $saturation: 100, $lightness: 50);
-$color-text-warning-forced-color: change-color($color-orange, $saturation: 100, $lightness: 70);
+$color-text-error: color.change($color-red, $saturation: 69%, $lightness: 52%);
+$color-text-error-forced-color: color.change($color-red, $saturation: 100%, $lightness: 50%);
+$color-text-warning-forced-color: color.change($color-orange, $saturation: 100%, $lightness: 70%);

+ 6 - 8
client/scss/tools/_functions.breakpoints.scss

@@ -1,30 +1,28 @@
+@use "sass:list";
+@use "sass:map";
 // Based upon the fine work and thoughts from Bootstrap v4.
-//
 // Copyright 2011-2018 The Bootstrap Authors
 // Copyright 2011-2018 Twitter, Inc.
 // Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
 
 // Name of the next breakpoint, or null for the last breakpoint.
-//
 //    >> breakpoint-next(sm)
 //    md
 @function breakpoint-next($name) {
-    $breakpoint-names: map-keys($breakpoints);
-    $n: index($breakpoint-names, $name);
-    @return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);
+    $breakpoint-names: map.keys($breakpoints);
+    $n: list.index($breakpoint-names, $name);
+    @return if($n < list.length($breakpoint-names), list.nth($breakpoint-names, $n + 1), null);
 }
 
 // Minimum breakpoint width. Null for the smallest (first) breakpoint.
-//
 //    >> breakpoint-min(sm)
 //    50em
 @function breakpoint-min($name) {
-    $min: map-get($breakpoints, $name);
+    $min: map.get($breakpoints, $name);
     @return if($min != 0, $min, null);
 }
 
 // Maximum breakpoint width. Null for the largest (last) breakpoint.
-//
 //    >> breakpoint-max(sm)
 //    56.1875em
 @function breakpoint-max($name) {

+ 0 - 1
client/scss/tools/_mixins.breakpoints.scss

@@ -1,5 +1,4 @@
 // Based upon the fine work and thoughts from Bootstrap v4.
-//
 // Copyright 2011-2018 The Bootstrap Authors
 // Copyright 2011-2018 Twitter, Inc.
 // Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)

+ 1 - 7
client/scss/tools/_mixins.general.scss

@@ -87,7 +87,7 @@
 
 @mixin icon () {
     @include font-smoothing;
-    font-family: 'wagtail';
+    font-family: $font-wagtail-icons;
     font-style: normal;
     font-weight: normal;
     font-variant: normal;
@@ -101,12 +101,6 @@
     margin-right: 0.2em;
 }
 
-@mixin svg-icon ($size: 1.5em, $position: text-top) {
-    width: $size;
-    height: $size;
-    vertical-align: $position;
-}
-
 // Applies given rules on hover, except for touch screens.
 // Relies on feature detection to add a no-touch class on the html element.
 @mixin hover {

+ 9 - 7
client/scss/tools/_mixins.grid.scss

@@ -1,5 +1,7 @@
+@use "sass:math";
+
 // Utility variable - you should never need to modify this
-$padding: $grid-gutter-width * 0.5;
+$padding: math.div($grid-gutter-width, 2);
 
 // Our row container
 @mixin row($padding: 0) {
@@ -22,32 +24,32 @@ $padding: $grid-gutter-width * 0.5;
     box-sizing: border-box;
     display: inline;
     float: left;
-    width: 100% * ($x / $grid-columns);
+    width: 100% * math.div($x, $grid-columns);
     padding-right: $padding;
     padding-left: $padding;
 }
 
 @mixin table-column($x, $padding: $padding, $grid-columns: $grid-columns) {
     box-sizing: border-box;
-    width: 100% * ($x / $grid-columns);
+    width: 100% * math.div($x, $grid-columns);
 }
 
 // Push adds left padding
 @mixin push($offset: 1, $grid-columns: $grid-columns) {
-    margin-left: 100% * ($offset / $grid-columns);
+    margin-left: 100% * math.div($offset, $grid-columns);
 }
 
 @mixin push-padding($offset: 1, $grid-columns: $grid-columns) {
-    padding-left: 100% * ($offset / $grid-columns);
+    padding-left: 100% * math.div($offset, $grid-columns);
 }
 
 // Pull adds right padding
 @mixin pull($offset: 1, $grid-columns: $grid-columns) {
-    margin-right: 100% * ($offset / $grid-columns);
+    margin-right: 100% * math.div($offset, $grid-columns);
 }
 
 @mixin pull-padding($offset: 1, $grid-columns: $grid-columns) {
-    padding-right: 100% * ($offset / $grid-columns);
+    padding-right: 100% * math.div($offset, $grid-columns);
 }
 
 // only used in places where padding not applied to same elements as row or row-flush

+ 30 - 25
client/scss/tools/_various.colors.scss

@@ -1,17 +1,22 @@
+@use "sass:math";
+@use "sass:color";
+@use "sass:list";
+@use "sass:meta";
+
 // $color is either a color or an hsl tuple
 @mixin define-color($name, $color) {
     $h: null;
     $s: null;
     $l: null;
 
-    @if type-of($color) == color {
-        $h: hue($color) / 1deg; // Cast to unitless
-        $s: saturation($color);
-        $l: lightness($color);
+    @if meta.type-of($color) == color {
+        $h: math.div(color.hue($color), 1deg); // Cast to unitless
+        $s: color.saturation($color);
+        $l: color.lightness($color);
     } @else {
-        $h: nth($color, 1);
-        $s: nth($color, 2);
-        $l: nth($color, 3);
+        $h: list.nth($color, 1);
+        $s: list.nth($color, 2);
+        $l: list.nth($color, 3);
     }
 
     --#{$name}-hue: #{$h};
@@ -25,38 +30,38 @@
 }
 
 @function css-darken($hsl-tuple, $darken-by) {
-    $h: nth($hsl-tuple, 1);
-    $s: nth($hsl-tuple, 2);
-    $l: nth($hsl-tuple, 3);
+    $h: list.nth($hsl-tuple, 1);
+    $s: list.nth($hsl-tuple, 2);
+    $l: list.nth($hsl-tuple, 3);
     @return ($h, $s, calc(#{$l} - #{$darken-by + 0%}));
 }
 @function css-lighten($hsl-tuple, $lighten-by) {
-    $h: nth($hsl-tuple, 1);
-    $s: nth($hsl-tuple, 2);
-    $l: nth($hsl-tuple, 3);
+    $h: list.nth($hsl-tuple, 1);
+    $s: list.nth($hsl-tuple, 2);
+    $l: list.nth($hsl-tuple, 3);
     @return ($h, $s, calc(#{$l} + #{$lighten-by + 0%}));
 }
 @function css-saturate($hsl-tuple, $saturate-by) {
-    $h: nth($hsl-tuple, 1);
-    $s: nth($hsl-tuple, 2);
-    $l: nth($hsl-tuple, 3);
+    $h: list.nth($hsl-tuple, 1);
+    $s: list.nth($hsl-tuple, 2);
+    $l: list.nth($hsl-tuple, 3);
     @return ($h, calc(#{$s} + #{$saturate-by + 0%}), $l);
 }
 @function css-desaturate($hsl-tuple, $desaturate-by) {
-    $h: nth($hsl-tuple, 1);
-    $s: nth($hsl-tuple, 2);
-    $l: nth($hsl-tuple, 3);
+    $h: list.nth($hsl-tuple, 1);
+    $s: list.nth($hsl-tuple, 2);
+    $l: list.nth($hsl-tuple, 3);
     @return ($h, calc(#{$s} - #{$desaturate-by + 0%}), $l);
 }
 @function css-adjust-hue($hsl-tuple, $adjust-by) {
-    $h: nth($hsl-tuple, 1);
-    $s: nth($hsl-tuple, 2);
-    $l: nth($hsl-tuple, 3);
+    $h: list.nth($hsl-tuple, 1);
+    $s: list.nth($hsl-tuple, 2);
+    $l: list.nth($hsl-tuple, 3);
     @return (calc(#{$h} + #{$adjust-by}), $s, $l);
 }
 @function css-transparentize($hsl-tuple, $alpha) {
-    $h: nth($hsl-tuple, 1);
-    $s: nth($hsl-tuple, 2);
-    $l: nth($hsl-tuple, 3);
+    $h: list.nth($hsl-tuple, 1);
+    $s: list.nth($hsl-tuple, 2);
+    $l: list.nth($hsl-tuple, 3);
     @return ($h, $s, $l, $alpha);
 }

+ 1 - 0
client/src/components/CommentApp/main.scss

@@ -144,6 +144,7 @@ $box-padding: 10px;
     pointer-events: none;
 }
 
+// stylelint-disable no-invalid-position-at-import-rule
 @import 'components/CommentHeader/style';
 @import 'components/Comment/style';
 @import 'components/CommentReply/style';

+ 2 - 1
client/src/components/Draftail/blocks/ImageBlock.scss

@@ -1,3 +1,4 @@
+@use "sass:color";
 @mixin wagtail-label-overrides {
     float: none;
     width: initial;
@@ -24,7 +25,7 @@
     color: $color-text-base;
 
     &[readonly] {
-        color: transparentize($color-text-base, 0.5);
+        color: color.adjust($color-text-base, $alpha: -0.5);
     }
 }
 

+ 4 - 2
client/src/components/Explorer/Explorer.scss

@@ -5,6 +5,8 @@ $c-explorer-secondary: #a5a5a5;
 $c-explorer-easing: cubic-bezier(0.075, 0.82, 0.165, 1);
 $menu-footer-height: 50px;
 
+@use "sass:map";
+
 @import 'ExplorerItem';
 
 .explorer__wrapper,
@@ -181,8 +183,8 @@ $menu-footer-height: 50px;
         top: $margin + 3px;
         bottom: 0;
         width: 2em;
-        font-family: wagtail;
-        content: map-get($icons, 'arrow-down');
+        font-family: $font-wagtail-icons;
+        content: map.get($icons, 'arrow-down');
         text-align: center;
         font-size: 1.2em;
         pointer-events: none;

+ 1 - 0
client/src/components/Hallo/_halloeditor.scss

@@ -55,6 +55,7 @@
         font-family: inherit;
     }
 
+    // stylelint-disable-next-line no-duplicate-selectors
     h2 {
         font-size: 2em;
         line-height: 1.2em;

+ 0 - 1
client/src/components/Hallo/_richtext-image.scss

@@ -1,7 +1,6 @@
 // These styles correspond to the image formats defined in wagtailimages/formats.py,
 // so that images displayed in the rich text field receive more or less the same
 // styling that they would receive on the site front-end.
-//
 // Wagtail installations that define their own image formats (in a myapp.image_formats module)
 // should ideally use the insert_editor_css hook to pass in their own custom CSS to have those
 // images render within the rich text area in the same styles that would appear on the front-end.

+ 4 - 2
client/src/components/PageExplorer/PageExplorer.scss

@@ -5,6 +5,8 @@ $c-page-explorer-secondary: #a5a5a5;
 $c-page-explorer-easing: cubic-bezier(0.075, 0.82, 0.165, 1);
 $menu-footer-height: 50px;
 
+@use "sass:map";
+
 @import 'PageExplorerItem';
 
 .c-page-explorer {
@@ -141,8 +143,8 @@ $explorer-header-horizontal-padding: 10px;
         top: $margin + 3px;
         bottom: 0;
         width: 2em;
-        font-family: wagtail;
-        content: map-get($icons, 'arrow-down');
+        font-family: $font-wagtail-icons;
+        content: map.get($icons, 'arrow-down');
         text-align: center;
         font-size: 1.2em;
         pointer-events: none;

+ 1 - 1
client/src/components/Sidebar/Sidebar.scss

@@ -113,7 +113,7 @@
     }
 }
 
-
+// stylelint-disable no-invalid-position-at-import-rule
 @import 'SidebarPanel';
 @import 'menu/MenuItem';
 @import 'menu/SubMenuItem';

+ 3 - 1
client/src/components/StreamField/scss/_variables.scss

@@ -1,3 +1,5 @@
+@use "sass:math";
+
 $grid-gutter-width: 30px !default;
 $header-padding-horizontal: 4px !default;
 $header-padding-vertical: 6px;
@@ -9,7 +11,7 @@ $add-button-size: 34px !default;
 $add-button-font-size: 24px !default;
 $type-button-padding-vertical: 10px !default;
 $type-button-padding-horizontal: 10px !default;
-$children-container-padding: $add-button-size / 2 !default;
+$children-container-padding: math.div($add-button-size, 2) !default;
 $content-padding-horizontal: 24px !default;
 $content-padding-vertical: 16px !default;
 $action-font-size: 18px;

+ 6 - 4
client/src/components/StreamField/scss/components/c-sf-add-panel.scss

@@ -1,15 +1,17 @@
+@use "sass:math";
+
 .c-sf-add-panel {
     position: relative;
-    padding: $grid-gutter-width / 4
+    padding: $grid-gutter-width * 0.25
         0
         $grid-gutter-width;
     border-radius: $border-radius;
     user-select: none;
 
     @media (min-width: $screen-l-min) {
-        padding: $grid-gutter-width / 4
+        padding: $grid-gutter-width * 0.25
             $grid-gutter-width * 2
-            $add-button-size - $grid-gutter-width / 2;
+            $add-button-size - math.div($grid-gutter-width, 2);
     }
 
     &__group-title {
@@ -22,7 +24,7 @@
         flex-flow: row wrap;
         margin-left: -$add-panel-gutter;
         margin-right: -$add-panel-gutter;
-        margin-bottom: $grid-gutter-width / 2;
+        margin-bottom: math.div($grid-gutter-width, 2);
 
         &:last-child {
             margin-bottom: 0;

+ 2 - 2
client/src/components/StreamField/scss/components/c-sf-block.scss

@@ -1,11 +1,11 @@
 // TODO: Reduce nesting further by splitting out more components.
-//
+// ---
 // There's quite a lot of nesting in here which makes parsing some segments difficult.
 // Some of this is to deal with the fact that .c-sf-block can contain many .c-sf-block's and so is
 // legitimate. A lot of these would ideally be their own components (eg the actions) however there
 // is a lot of interdependency of the elements which makes this hard
 // without fairly intensive rethinking of the HTML.
-//
+// ---
 // However, the new classes adequately sanitise streamfield only CSS so am leaving this for
 // now to avoid blocking the release of the new Streamfield. -@jonnyscholes
 .c-sf-block {

+ 5 - 3
client/src/components/StreamField/scss/components/c-sf-container.scss

@@ -1,3 +1,5 @@
+@use "sass:math";
+
 .c-sf-container {
     position: relative;
     display: flex;
@@ -26,7 +28,7 @@
             .c-sf-add-button {
                 width: $add-button-size;
                 height: 0;
-                transform: translate(-100%, -$add-button-size / 2);
+                transform: translate(-100%, math.div(-$add-button-size, 2));
                 overflow: visible;
             }
         }
@@ -36,7 +38,7 @@
     // opportunity for this is probably as part of Wagtails general CSS overhaul. -@jonnyscholes
     .field {
         + .field {
-            padding-top: $grid-gutter-width / 2;
+            padding-top: math.div($grid-gutter-width, 2);
         }
 
         // TODO: #CSSoverhaul global label styles need to be removed. These styles come from global
@@ -65,7 +67,7 @@
         &__label {
             display: block;
             font-weight: bold;
-            margin-bottom: $grid-gutter-width / 4;
+            margin-bottom: $grid-gutter-width * 0.25;
         }
 
         &.required > label::after {

+ 17 - 13
wagtail/admin/static_src/wagtailadmin/scss/layouts/page-editor.scss

@@ -1,3 +1,7 @@
+@use "sass:color";
+@use "sass:map";
+@use "sass:math";
+
 @import 'wagtailadmin/scss/helpers';
 
 .page-editor {
@@ -176,7 +180,7 @@
         top: $object-title-height;
         margin-top: 0;
         margin-bottom: -1em;
-        padding: 1em ($grid-gutter-width / 2) 1em 3em;
+        padding: 1em math.div($grid-gutter-width, 2) 1em 3em;
         opacity: 1;
 
         .icon-help {
@@ -220,9 +224,9 @@
         &:before {
             @include font-smoothing;
             text-shadow: none;
-            font-family: wagtail;
+            font-family: $font-wagtail-icons;
             text-transform: none;
-            content: map-get($icons, 'arrow-down');
+            content: map.get($icons, 'arrow-down');
             text-align: center;
             display: block;
             position: absolute;
@@ -320,7 +324,7 @@
     // special panel for the publishing fields, requires a bit more pizzazz
     &.publishing {
         > .title-wrapper:before {
-            content: map-get($icons, 'date');
+            content: map.get($icons, 'date');
             font-size: 1.8rem;
             line-height: 1.4em;
             width: 1.4em;
@@ -329,7 +333,7 @@
 
     &.privacy {
         > .title-wrapper:before {
-            content: map-get($icons, 'view');
+            content: map.get($icons, 'view');
         }
     }
 
@@ -393,7 +397,7 @@
                 }
 
                 &:hover:before {
-                    background-color: darken($color-salmon, 5%);
+                    background-color: color.adjust($color-salmon, $lightness: -5%);
                 }
             }
         }
@@ -410,7 +414,7 @@
 
         .title-wrapper {
             &:before {
-                content: map-get($icons, 'collapse-up');
+                content: map.get($icons, 'collapse-up');
                 cursor: pointer;
             }
         }
@@ -418,7 +422,7 @@
         &.collapsed {
             .title-wrapper {
                 &:before {
-                    content: map-get($icons, 'collapse-down');
+                    content: map.get($icons, 'collapse-down');
                 }
             }
         }
@@ -472,8 +476,8 @@ footer .preview {
             height: 3em;
         }
 
-        background-color: lighten($color-grey-2, 10%);
-        border-color: lighten($color-grey-2, 10%);
+        background-color: color.adjust($color-grey-2, $lightness: 10%);
+        border-color: color.adjust($color-grey-2, $lightness: 10%);
 
         &:hover {
             background-color: $color-grey-2;
@@ -486,8 +490,8 @@ footer .preview {
         input[type=submit],
         button,
         .button {
-            background-color: lighten($color-grey-2, 10%);
-            border-color: lighten($color-grey-2, 10%);
+            background-color: color.adjust($color-grey-2, $lightness: 10%);
+            border-color: color.adjust($color-grey-2, $lightness: 10%);
 
             &:hover {
                 background-color: $color-grey-2;
@@ -497,7 +501,7 @@ footer .preview {
 
         ul,
         .dropdown-toggle {
-            background-color: lighten($color-grey-2, 10%);
+            background-color: color.adjust($color-grey-2, $lightness: 10%);
         }
 
         .dropdown-toggle:hover,

+ 0 - 3
wagtail/admin/static_src/wagtailadmin/scss/layouts/report.scss

@@ -47,9 +47,6 @@
             float: unset;
             display: block;
             width: unset;
-        }
-
-        label {
             padding-top: 1.2em;
         }
     }

+ 12 - 7
wagtail/admin/static_src/wagtailadmin/scss/userbar.scss

@@ -1,3 +1,8 @@
+@use "sass:color";
+@use "sass:map";
+@use "sass:math";
+@use "sass:string";
+
 @import 'wagtailadmin/scss/helpers';
 
 // =============================================================================
@@ -70,13 +75,13 @@ $positions: (
 
 @each $icon, $content in $icons {
     .#{$namespace}-icon-#{$icon}:before {
-        content: quote(#{$content});
+        content: string.quote(#{$content});
     }
 }
 
 @each $icon, $content in $icons-after {
     .#{$namespace}-icon-#{$icon}:after {
-        content: quote(#{$content});
+        content: string.quote(#{$content});
     }
 }
 
@@ -247,7 +252,7 @@ $positions: (
     }
 
     & + & {
-        border-top: 1px solid darken($color-grey-1, 3%);
+        border-top: 1px solid color.adjust($color-grey-1, $lightness: -3%);
     }
 
 
@@ -318,9 +323,9 @@ $positions: (
 // =============================================================================
 
 @each $pos, $attrs in $positions {
-    $vertical: map-get($attrs, vertical);
-    $horizontal: map-get($attrs, horizontal);
-    $arrow: map-get($attrs, arrow);
+    $vertical: map.get($attrs, vertical);
+    $horizontal: map.get($attrs, horizontal);
+    $arrow: map.get($attrs, arrow);
 
     .#{$namespace}-userbar--#{$pos} {
         #{$vertical}: $position;
@@ -342,7 +347,7 @@ $positions: (
 
         .#{$namespace}-userbar-items:after {
             #{$vertical}: 2px;
-            #{$horizontal}: $size-home-button / 2 - $width-arrow / 2;
+            #{$horizontal}: math.div($size-home-button, 2) - math.div($width-arrow, 2);
             border-#{$arrow}-color: $color-grey-1;
 
             @if $vertical == 'bottom' {

+ 0 - 4
wagtail/contrib/styleguide/static_src/wagtailstyleguide/scss/styleguide.scss

@@ -59,10 +59,6 @@ section {
         color: $color-salmon-light;
     }
 
-    .color-red-text {
-        color: $color-red;
-    }
-
     .color-green-text {
         color: $color-green;
     }

+ 3 - 1
wagtail/images/static_src/wagtailimages/scss/add-multiple.scss

@@ -1,3 +1,5 @@
+@use "sass:color";
+
 @import 'wagtailadmin/scss/helpers';
 
 .replace-file-input {
@@ -94,7 +96,7 @@
         width: 1em;
         font-size: 10em;
         line-height: 1.4em;
-        color: lighten($color-grey-4, 4%);
+        color: color.adjust($color-grey-4, $lightness: 4%);
     }
 
     canvas,