Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: remove css safelist and add IconExtractor #20

Merged
merged 11 commits into from Jun 21, 2022
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