Skip to content

Latest commit

 

History

History

plugins

Primer stylelint plugins

This directory contains all of our custom stylelint plugins, each of which provides a single stylelint rule.

Rules

These were intended for use with Primer CSS and GitHub projects, but you may find them useful elsewhere.

Usage

If you're using or extending @primer/stylelint-config already, then you're using all of these plugins by default. See index.js for the config defaults.

If you're not using or extending @primer/stylelint-config, you can still reference the plugins by referencing their module paths like so:

// stylelint.config.js
module.exports = {
  plugins: ['@primer/stylelint-config/plugins/colors']
}

primer/colors

This variable rule enforces the use of Primer color system variables for color and background-color CSS properties. Generally speaking, variables matching the pattern $text-* are acceptable for color (and fill), and $bg-* are acceptable for background-color. See the configuration for more info.

body {
  color: black;
}
/**           ↑
 *            FAIL: Use a variable. */

body {
  color: $gray-900;
}
/**           ↑
 *            FAIL: Use $text-gray-dark instead. */

primer/spacing

This variable rule enforces the use of Primer spacing variables in margin and padding CSS properties. See the configuration for more info.

ul {
  margin: 0 0 $spacer-3;
}
/**          ↑
 *           OK: "0" and "$spacer-*" are allowed values */

ul {
  margin: 0 0 16px;
}
/**              ↑
 *               FAIL: Use "$spacer-3" (auto-fixable!) */

primer/typography

This variable rule enforces the use of typography variables for font-size, font-weight, and line-height CSS properties. See the configuration for more info.

primer/borders

This variable rule enforces the use of border-specific variables ($border-width, $border-style, and $border-color*, and the $border shorthand) for all border CSS properties (including the border shorthand). The values 0 and none are also allowed; see the configuration for more info.

primer/box-shadow

This variable rule enforces the use of $box-shadow* variables for the box-shadow CSS property. See the configuration for more info.

primer/responsive-widths

This plugin checks for width and min-width declarations that use a value less than the minimum browser size. 320px

Variable rules

Variable rules are created using a general-purpose helper that can validate constraints for matching CSS properties and values. In general, the Primer CSS variable rules enforce two basic principles for custom CSS:

  • Use Primer variables whenever possible.
  • Use functional variables ($text-gray vs. $gray-700) whenever possible.

Validations take the form of an object literal in which each key/value pair defines a set of named constraints that apply to one or more CSS properties:

{
  'background color': {
    props: 'background-color',
    // ...
  },
  'foreground color': {
    props: ['color', 'fill'],
    // ...
  }
}

The objects in each named rule may have the following keys:

  • props is an array or string of glob patterns that match CSS properties. For individual properties like color, a string without any special glob characters works just fine. You can use brace expansion to match directional properties:

    'border width': {
      props: 'border{,-top,-right,-bottom,-left}-width',
      // which expands to:
      props: [
        'border-width',
        'border-top-width',
        'border-right-width',
        'border-bottom-width',
        'border-left-width'
      ]
    }

    Note: if no props are listed, the name of the rule is assumed to be the CSS property.

  • values is, similar to props, an array or string of glob patterns that match individual CSS values in a single property. Property values are parsed with postcss-value-parser, so they respect parentheses, functions, and values within them. If a property has more than one value (e.g. margin: 0 auto), each one is compared against the values list to determine its validity, and a warning is generated for each invalid value.

    For example, if we fleshed out the border width rule defined above with values:

    'border width': {
      props: 'border{,-top,-right,-bottom,-left}-width',
      values: ['$border-*', '0']
    }

    Then the following SCSS checks out:

    .Box {
      border-width: 0 0 $border-width;
      /**             ↑ ↑ ↑
     *              ↑ ↑ OK!
     *              ↑ OK!
     *              OK!                */
    }
  • components tells the rule that multiple values resolve to a list of ordered properties with their own, separately defined rules. This makes it possible for shorthand CSS properties like border, background, or font to "delegate" validation to a rule with more specific constraints. For example, you could enforce different types of border variables for most of the CSS border properties with:

    'border': {
      props: 'border{,-top,-right,-bottom,-left}',
      components: ['border-width', 'border-style', 'border-color']
    },
    'border width': {
      props: 'border{,-top,-right,-bottom,-left}-width',
      values: ['$border-width', '0']
    },
    'border style': {
      props: 'border{,-top,-right,-bottom,-left}-style',
      values: ['$border-style', 'none']
    },
    'border color': {
      props: 'border{,-top,-right,-bottom,-left}-color',
      values: ['$border-*', 'transparent']
    }
  • replacements is an object listing property values that can safely be replaced via stylelint --fix with other variable or static values, as in the Primer CSS font-size rule:

    'font-size': {
      props: 'font-size',
      values: ['$h{0,1,2,3,4,5,6}-size', '$font-size-small'],
      replacements: {
        '40px': '$h0-size',
        '32px': '$h1-size',
        '24px': '$h2-size',
        '20px': '$h3-size',
        '16px': '$h4-size',
        '14px': '$h5-size',
        '12px': '$h6-size'
      }
    }

Variable rule options

All variable rules respect the following rule options, as in:

// stylelint.config.js
module.exports = {
  extends: '@primer/stylelint-config',
  rules: {
    'primer/colors': [true /* options here */]
    /*                ↑
     *                false disables the rule */
  }
}
  • rules extends the validations for the rule, and can be used to disable specific validations, as e.g.

    rules: {
      'primer/colors': [true, {
        rules: {
          'background color': false, // disabled
          'text color': {
            // override the text color validation rules here
          }
      }]
    }
  • verbose is a boolean that enables chatty console.warn() messages that may help you debug more complicated configurations.

  • disableFix is a boolean that can disable auto-fixing of this rule when running stylelint --fix to auto-fix other rules.