Skip to content

Commit

Permalink
refactor: remove css safelist and add IconExtractor (#20)
Browse files Browse the repository at this point in the history
* remove safelist and add IconExtractor

* update storybook

* update cypress

* Add changeset

* update cypress

* export icon class definitions for DRY
  • Loading branch information
elevatebart committed Jun 21, 2022
1 parent ff7a75a commit 14dd0f5
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 50 deletions.
6 changes: 6 additions & 0 deletions .changeset/many-bottles-hope.md
@@ -0,0 +1,6 @@
---
"@cypress-design/css": patch
---

To avoid having every color in the universe in the **safelist**, add the IconExtractor.
Also, remove the entire safelist from the css plugins windi config.
48 changes: 48 additions & 0 deletions css/src/icon-color-plugins.ts
Expand Up @@ -8,6 +8,8 @@
import createPlugin from 'windicss/plugin'
import { reduce, kebabCase, isObject } from 'lodash'
import { colors } from './colors'
import { DefaultExtractor } from 'vite-plugin-windicss'
import { Extractor } from 'windicss/types/interfaces'

interface RuleConfig {
name: string
Expand Down Expand Up @@ -157,3 +159,49 @@ export const IconDuotoneColorsPlugin = createPlugin(
addUtilities(addIconUtilityClasses(theme))
}
)

export const ICON_ATTRIBUTE_NAMES_TO_CLASS_GENERATOR = {
fillColor: (attrValue: string) => `icon-light-${attrValue}`,
strokeColor: (attrValue: string) => `icon-dark-${attrValue}`,
secondaryFillColor: (attrValue: string) =>
`icon-light-secondary-${attrValue}`,
secondaryStrokeColor: (attrValue: string) =>
`icon-dark-secondary-${attrValue}`,
} as const

function isIconAttribute(
attrName: string
): attrName is keyof typeof ICON_ATTRIBUTE_NAMES_TO_CLASS_GENERATOR {
return ICON_ATTRIBUTE_NAMES_TO_CLASS_GENERATOR.hasOwnProperty(attrName)
}

/**
* transforms the attributes of icons into classes
* to be kept in the windicss css file after purgecss
*/
export const IconExtractor: Extractor = {
extensions: ['vue', 'js', 'ts', 'tsx'],
extractor: (code, id) => {
const { tags, classes = [], attributes } = DefaultExtractor(code, id)

const additionalColorClasses =
attributes?.names.reduce((set, attrName, index) => {
if (isIconAttribute(attrName)) {
set.add(
ICON_ATTRIBUTE_NAMES_TO_CLASS_GENERATOR[attrName](
attributes.values[index]
)
)
}
return set
}, new Set<string>()) ?? new Set<string>()

return {
tags,
get classes() {
return [...classes, ...Array.from(additionalColorClasses)]
},
attributes,
}
},
}
2 changes: 2 additions & 0 deletions css/src/index.ts
Expand Up @@ -31,3 +31,5 @@ export const CyCSSWebpackPlugin = (options: UserOptions) =>
new WebpackPlugin(getConfig(options))

export * from './colors'

export { ICON_ATTRIBUTE_NAMES_TO_CLASS_GENERATOR } from './icon-color-plugins'
41 changes: 0 additions & 41 deletions css/src/safelist.ts

This file was deleted.

5 changes: 2 additions & 3 deletions css/src/windi.config.ts
@@ -1,8 +1,7 @@
import { defineConfig } from 'windicss/helpers'
// @ts-ignore
import InteractionVariants from '@windicss/plugin-interaction-variants'
import { IconDuotoneColorsPlugin } from './icon-color-plugins'
import { safelist } from './safelist'
import { IconDuotoneColorsPlugin, IconExtractor } from './icon-color-plugins'
import { colors } from './colors'
import { shortcuts } from './shortcuts'

Expand All @@ -29,7 +28,6 @@ export default defineConfig({
},
},
},
safelist,
variants: {
// What's hocus?
// Hocus is a portmanteau of hover + focus. This is useful because
Expand All @@ -54,5 +52,6 @@ export default defineConfig({
shortcuts,
extract: {
exclude: ['node_modules/**/*', '.git/**/*'],
extractors: [IconExtractor],
},
})
6 changes: 2 additions & 4 deletions package.json
Expand Up @@ -50,6 +50,7 @@
"concurrently": "^7.1.0",
"cypress": "^10.1.0",
"cypress-axe": "^0.14.0",
"cypress-real-events": "^1.7.0",
"eslint": "^8.17.0",
"eslint-plugin-no-only-tests": "^2.6.0",
"execa": "^6.1.0",
Expand All @@ -69,8 +70,5 @@
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"devDependencies": {
"cypress-real-events": "^1.7.0"
}
}
}
25 changes: 23 additions & 2 deletions storybook/intro/.storybook/main.js
@@ -1,4 +1,5 @@
const { CyCSSWebpackPlugin } = require('@cypress-design/css')
const { CyCSSWebpackPlugin, colors } = require('@cypress-design/css')
const { map, reduce, kebabCase } = require('lodash')
const path = require('path')
const CopyWebpackPlugin = require('copy-webpack-plugin')

Expand All @@ -8,7 +9,6 @@ module.exports = {
'@storybook/addon-links',
'@storybook/addon-essentials',
'storybook-addon-designs',
// "@storybook/addon-interactions",
],
framework: '@storybook/react',
refs: (config, { configType }) => {
Expand Down Expand Up @@ -78,6 +78,27 @@ module.exports = {
path.resolve(__dirname, '../stories/src/*.tsx'),
],
},
safelist: reduce(
{ ...colors, transparent: { ONLY: true }, current: { ONLY: true } },
(acc, variants, colorName) => {
const name = kebabCase(colorName)

return `${acc}
${map(variants, (_, k) => {
if (k === 'DEFAULT') return ``
const variantName = k === 'ONLY' ? name : `${name}-${k}`
return `
bg-${variantName}
text-${variantName}
before:bg-${variantName}
before:text-${variantName}
icon-light-${variantName}
icon-dark-${variantName}
icon-light-secondary-${variantName}
icon-dark-secondary-${variantName}`
}).join(' ')}`
}
),
})
)
return config
Expand Down

1 comment on commit 14dd0f5

@vercel
Copy link

@vercel vercel bot commented on 14dd0f5 Jun 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

cypress-design – ./

cypress-design.vercel.app
cypress-design-git-main-cypress-io.vercel.app
cypress-design-cypress-io.vercel.app

Please sign in to comment.