cypress-io/cypress-design

refactor: use component classes for component

Closed this issue · 0 comments

Description

The current CSS model using tailwind poses two issues:

  • When components are server side rendered, their html is made heavy by the amount of repeated classes there is. The weight of the page augments exponentially when adding new properties.
  • Overriding a property for one component (margin, size, white-space, ...) often requires the use of ! to bypass priorities. This does not leave room for later re-override when hacking.

We could solve both those issues by using classes placed in the @components layer of tailwind. The best automated way I could see to do that without changing our dev process would be to generate a tailwind plugin in each constants package along with the current bundle. This plugin would register the current classes as component classes like this:

// written code
export const alertSizesClasses = {
  xs: 'py-[4px] px-[8px] leading-[22px] text-[14px]',
  sm: 'py-[8px] px-[12px] leading-[22px] text-[14px]',
  md: 'py-[12px] px-[16px] leading-[24px] text-[16px]',
  lg: 'p-[16px] leading-[24px] text-[16px]',
} as const
// compiled code
export const alertSizesClasses = {
  xs: "cy-ds-alert-alertSizes-xs",
  sm: "cy-ds-alert-alertSizes-sm",
  md: "cy-ds-alert-alertSizes-md",
  lg: "cy-ds-alert-alertSizes-lg",
}
// tailwind plugin
export default function plugin({ addComponents }) {
  addComponents({
    ".cy-ds-alert-alertSizes-xs": {
      "@apply py-[4px] px-[8px] leading-[22px] text-[14px]" : {},
    },
    ".cy-ds-alert-alertSizes-sm": {
      "@apply py-[8px] px-[12px] leading-[22px] text-[14px]": {},
    },
    ".cy-ds-alert-alertSizes-md": {
      "@apply py-[12px] px-[16px] leading-[24px] text-[16px]": {},
    },
    ".cy-ds-alert-alertSizes-lg": {
      "@apply p-[16px] leading-[24px] text-[16px]": {},
    },
  })
}

How do we do it?

  1. replace all build process for constants with rollup
  2. add a plugin to generate the plugin from the code
    1. Look for all exports ending in ...classes using acorn
    2. If they contain a string, use that string
    3. If they contain an object redo the same process with each of the member
    4. Once all classes gathered, generate the code
  3. make a plugin to replace the classes in the generated bundle after TypeScript transpilation.
    1. Look for all exports ending in ...classes using acorn
    2. if they contain a string generate the class name and replace
    3. if contain an object, redo the work for each member