1

I am using styled-components, prettier and stylelint. Here is my .stylelintrc.json:

{
  "extends": [
    "stylelint-config-standard",
    "stylelint-prettier",
    "stylelint-config-prettier",
    "stylelint-config-rational-order"
  ],
  "plugins": ["stylelint-order", "stylelint-config-rational-order/plugin"],
  "customSyntax": "postcss-styled-syntax"
}

As you can see, I am using stylelint-config-rational-order/plugin and when I am running this command:

stylelint \"src/**/*.tsx\" --fix"

... I am expecting stylelint to automatically fix styles order in all corresponding files, they should approximately look like this:

// Test.tsx -- BEFORE LINTING

import styled from 'styled-components';

export const Test = styled.div<{ active: boolean }>`
  width: 20px;
  height: 20px;

  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1;
  background: ${p => p.active && 'var(--blue)'};
  transition: var(--transition-200);
  flex-shrink: 0;

  &:hover {
    background: ${p => !p.active && 'var(--blue-hover)'};
  }

  cursor: pointer;
  border-radius: 50%;
  margin-right: 8px;
  height: 20px;

  &:last-child {
    margin-right: 0;
  }
`;
// Test.tsx -- AFTER LINTING (desired result)

import styled from 'styled-components';

export const Test = styled.div<{ active: boolean }>`
  height: 20px;
  width: 20px;

  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;

  background: ${p => p.active && 'var(--blue)'};
  transition: var(--transition-200);
  border-radius: 50%;
  margin-right: 8px;

  cursor: pointer;

  &:hover {
    background: ${p => !p.active && 'var(--blue-hover)'};
  }

  &:last-child {
    margin-right: 0;
  }
`;

But in fact I am getting this result:

// Test.tsx -- AFTER LINTING (not desired result)

import styled from 'styled-components';

export const Test = styled.div<{ active: boolean }>`
  width: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1;
  background: ${p => p.active && 'var(--blue)'};
  transition: var(--transition-200);
  flex-shrink: 0;

  &:hover {
    background: ${p => !p.active && 'var(--blue-hover)'};
  }

  cursor: pointer;
  border-radius: 50%;
  margin-right: 8px;
  height: 20px;

  &:last-child {
    margin-right: 0;
  }
`;

As you can see it just removes some breaks and doing absolutely nothing in terms of reordering.

So, my question is – is there a way to make stylelint --fix work with stylelint-config-rational-order/plugin (or similar reordering plugins) and styled-components and automatically fix all css-in-js throughout the app according to mentioned rules?

–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

UPD: I've tried to use more advanced config to make stylelint add empty lines between logical groups, here it is:

// stylelint.config.js

const propertyGroups = require('stylelint-config-recess-order/groups');

module.exports = {
  extends: ['stylelint-config-standard'],
  plugins: ['stylelint-order'],
  customSyntax: 'postcss-styled-syntax',
  rules: {
    // Configure the custom rule manually.
    'order/properties-order': propertyGroups.map(group => ({
      ...group,
      emptyLineBefore: 'always',
    })),
  },
};

However, I still can not achieve desired result, when I run npx stylelint Test.tsx --fix I get this output:

import styled, { css } from 'styled-components';

const Test = styled.div<{ flag: boolean }>`
  display: flex;
  height: 18px;
  background-color: var(--color-primary);
  width: 18px;
  justify-content: center;
  border-radius: 50%;
  font-size: 14px;
  ${p =>
    p.flag &&
    css`
      border-radius: 0;
      background-color: green;
    `}
  line-height: 20px;
  color: var(--color-white);
  align-items: center;
  &:hover {
    background-color: red;
  }
`;

/* Desired result */

// const Test = styled.div<{ flag: boolean }>`
//   height: 18px;
//   width: 18px;

//   display: flex;
//   align-items: center;
//   justify-content: center;

//   font-size: 14px;
//   line-height: 20px;
//   color: var(--color-white);

//   border-radius: 50%;
//   background-color: var(--color-primary);

//   &:hover {
//     background-color: red;
//   }

//   ${p =>
//     p.flag &&
//     css`
//       border-radius: 0;
//       background-color: green;
//     `}
// `;

/* Fact result */

// const Test = styled.div<{ flag: boolean }>`
//   display: flex;
//   height: 18px;
//   background-color: var(--color-primary);
//   width: 18px;
//   justify-content: center;
//   border-radius: 50%;
//   font-size: 14px;
//   ${p =>
//     p.flag &&
//     css`
//       background-color: green;
//       border-radius: 0;
//     `}
//   line-height: 20px;
//   color: var(--color-white);
//   align-items: center;

//   &:hover {
//     background-color: red;
//   }
// `;

1 Answers1

1

Use the stylelint-config-recess-order shared config, rather than stylelint-config-rational-order:

{
  "extends": [
    "stylelint-config-standard",
    "stylelint-config-recess-order"
  ],
  "customSyntax": "postcss-styled-syntax"
}

The recess order config is maintained (last published 2 weeks ago), unlike the rational order config (last published 4 years ago). The recess order config appears compatible with the postcss-styled-syntax custom syntax and supports modern CSS properties.

The two configs have similar groupings, i.e., they start with positioning, box model, typography, etc.

Running npx stylelint test.tsx gives:

import styled from "styled-components";

export const Test = styled.div<{ active: boolean }>`

  display: flex;
  flex: 1;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  margin-right: 8px;
  cursor: pointer;
  background: ${(p) => p.active && "var(--blue)"};
  border-radius: 50%;
  transition: var(--transition-200);

  &:hover {
    background: ${(p) => !p.active && "var(--blue-hover)"};
  }

  &:last-child {
    margin-right: 0;
  }
`;

Stylelint also detected and removed the duplicate height property.

If you want empty lines between groups, you can follow the advanced guidance when to configure the rule:

const propertyGroups = require('stylelint-config-recess-order/groups')

module.exports = {
    extends: ["stylelint-config-standard"],
    plugins: ["stylelint-order"],
    customSyntax: "postcss-styled-syntax",
    rules: {
        // Configure the custom rule manually.
        'order/properties-order': propertyGroups.map((group) => ({
            ...group,
            emptyLineBefore: 'always'
        })),
    },
}

Additionally, you don't need:

  • stylelint-config-prettier as stylelint-config-standard no longer conflicts with Prettier
  • stylelint-prettier as it's recommended to run Prettier as a separate tool
jeddy3
  • 3,451
  • 1
  • 12
  • 21
  • Thanks for your answer, this config actually does group properties similar to the way I need but I am still facing one problem – it does not adding line-breaks after each logic styles group. This is essential for me. Is there any way this can be achieved? – Ilya Kruchinin Jul 24 '23 at 14:21
  • 1
    I've updated the answer to show how. – jeddy3 Jul 25 '23 at 10:45
  • Hey, thanks for your update. However, I'm still not able to achieve desired result, please be kind to read UPD section in my question so you can see the problem. I am not aiming to achieve this specific order of groups but I really want to have empty lines between them. – Ilya Kruchinin Aug 17 '23 at 14:18