Skip to content

Commit

Permalink
fix(plugin): improve classes generation when a pseudo class is present
Browse files Browse the repository at this point in the history
Uses the same approach as Tailwind CSS for variants generation.

fix #2
  • Loading branch information
estevanmaito committed Jun 12, 2020
1 parent 0b5a4dd commit 80bfade
Showing 1 changed file with 37 additions and 71 deletions.
108 changes: 37 additions & 71 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const selectorParser = require('postcss-selector-parser')

module.exports = ({ addVariant, theme, e }) => {
module.exports = ({ addVariant, theme }) => {
const themeVariants = theme('themeVariants')
if (!themeVariants) {
throw new Error('tailwindcss-multi-theme expects a themeVariants property in theme.')
Expand All @@ -16,96 +16,62 @@ module.exports = ({ addVariant, theme, e }) => {
)
}

themeVariants.forEach((tv) => {
const root = `.theme-${tv} `

addVariant(`${tv}`, ({ modifySelectors, separator }) => {
function generatePseudoClassVariant(themeVariant, pseudoClass, selectorPrefix = pseudoClass) {
const root = `.theme-${themeVariant} `
addVariant(`${themeVariant}:${selectorPrefix}`, ({ modifySelectors, separator }) => {
modifySelectors(({ selector }) => {
return selectorParser((selectors) => {
selectors.walkClasses((sel) => {
sel.value = `${tv}${separator}${sel.value}`
sel.value = `${themeVariant}${separator}${selectorPrefix}${separator}${sel.value}`
sel.parent.insertBefore(sel, selectorParser().astSync(root))
sel.parent.insertAfter(sel, selectorParser.pseudo({ value: `:${pseudoClass}` }))
})
}).processSync(selector)
})
})
}

addVariant(`${tv}:group-hover`, ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `${root} .group:hover .${e(`${tv}${separator}group-hover${separator}${className}`)}`
})
})

addVariant(`${tv}:group-focus`, ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `${root} .group:focus .${e(`${tv}${separator}group-focus${separator}${className}`)}`
})
})

addVariant(`${tv}:focus-within`, ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `${root}.${e(`${tv}${separator}focus-within${separator}${className}`)}:focus-within`
})
})

addVariant(`${tv}:first`, ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `${root}.${e(`${tv}${separator}first${separator}${className}`)}:first-child`
})
})

addVariant(`${tv}:last`, ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `${root}.${e(`${tv}${separator}last${separator}${className}`)}:last-child`
})
})

addVariant(`${tv}:odd`, ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `${root}.${e(`${tv}${separator}odd${separator}${className}`)}:nth-child(odd)`
})
})

addVariant(`${tv}:even`, ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `${root}.${e(`${tv}${separator}even${separator}${className}`)}:nth-child(even)`
})
})

addVariant(`${tv}:hover`, ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `${root}.${e(`${tv}${separator}hover${separator}${className}`)}:hover`
function generateGroupVariant(themeVariant, pseudoClass, selectorPrefix) {
const root = `.theme-${themeVariant} `
addVariant(`${themeVariant}:${selectorPrefix}`, ({ modifySelectors, separator }) => {
modifySelectors(({ selector }) => {
return selectorParser((selectors) => {
selectors.walkClasses((sel) => {
sel.value = `${themeVariant}${separator}${selectorPrefix}${separator}${sel.value}`
sel.parent.insertBefore(sel, selectorParser().astSync(`${root}.${pseudoClass} `))
})
}).processSync(selector)
})
})
}

addVariant(`${tv}:focus`, ({ modifySelectors, separator }) => {
function generateDefaultVariant(themeVariant) {
const root = `.theme-${themeVariant} `
addVariant(`${themeVariant}`, ({ modifySelectors, separator }) => {
modifySelectors(({ selector }) => {
return selectorParser((selectors) => {
selectors.walkClasses((sel) => {
sel.value = `${tv}${separator}focus${separator}${sel.value}`
sel.value = `${themeVariant}${separator}${sel.value}`
sel.parent.insertBefore(sel, selectorParser().astSync(root))
sel.parent.insertAfter(sel, selectorParser.pseudo({ value: ':focus' }))
})
}).processSync(selector)
})
})
}

addVariant(`${tv}:active`, ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `${root}.${e(`${tv}${separator}active${separator}${className}`)}:active`
})
})

addVariant(`${tv}:visited`, ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `${root}.${e(`${tv}${separator}visited${separator}${className}`)}:visited`
})
})

addVariant(`${tv}:disabled`, ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `${root}.${e(`${tv}${separator}disabled${separator}${className}`)}:disabled`
})
})
themeVariants.forEach((tv) => {
generateDefaultVariant(tv)
generateGroupVariant(tv, 'group:hover', 'group-hover')
generateGroupVariant(tv, 'group:focus', 'group-focus')
generatePseudoClassVariant(tv, 'focus')
generatePseudoClassVariant(tv, 'hover')
generatePseudoClassVariant(tv, 'active')
generatePseudoClassVariant(tv, 'visited')
generatePseudoClassVariant(tv, 'disabled')
generatePseudoClassVariant(tv, 'focus-within')
generatePseudoClassVariant(tv, 'first-child', 'first')
generatePseudoClassVariant(tv, 'last-child', 'last')
generatePseudoClassVariant(tv, 'nth-child(even)', 'even')
generatePseudoClassVariant(tv, 'nth-child(odd)', 'odd')
})
}

1 comment on commit 80bfade

@vercel
Copy link

@vercel vercel bot commented on 80bfade Jun 12, 2020

Choose a reason for hiding this comment

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

Please sign in to comment.