implement not variant with @media, @supports and @container variants
This commit is contained in:
parent
5ebd5896d7
commit
5f3eced44c
3 changed files with 125 additions and 3 deletions
|
|
@ -611,14 +611,28 @@ export function parseVariant(variant: string, designSystem: DesignSystem): Varia
|
|||
|
||||
let subVariant = designSystem.parseVariant(value)
|
||||
if (subVariant === null) return null
|
||||
if (subVariant.compounds === false) return null
|
||||
|
||||
let compounds: boolean | null = null
|
||||
|
||||
// Special case: allow compounding in `not` because we can invert
|
||||
// `@media` queries.
|
||||
if (root === 'not' && subVariant.compounds === false) {
|
||||
// However, we do not allow further compounding. E.g.:
|
||||
// `group-not-print` is invalid.
|
||||
compounds = false
|
||||
}
|
||||
|
||||
// Discard the variant if it's not allowed to be compounded.
|
||||
else if (subVariant.compounds === false) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
kind: 'compound',
|
||||
root,
|
||||
modifier: modifier === null ? null : { kind: 'named', value: modifier },
|
||||
variant: subVariant,
|
||||
compounds: designSystem.variants.compounds(root),
|
||||
compounds: compounds ?? designSystem.variants.compounds(root),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1508,6 +1508,89 @@ test('not', () => {
|
|||
expect(run(['not-[:checked]/foo:flex'])).toEqual('')
|
||||
})
|
||||
|
||||
test('not with media queries', () => {
|
||||
expect(
|
||||
compileCss(
|
||||
css`
|
||||
@theme {
|
||||
--breakpoint-lg: 1024px;
|
||||
}
|
||||
@tailwind utilities;
|
||||
`,
|
||||
['not-print:flex', 'not-dark:flex', 'not-lg:flex'],
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
":root {
|
||||
--breakpoint-lg: 1024px;
|
||||
}
|
||||
|
||||
@media not (width >= 1024px) {
|
||||
.not-lg\\:flex {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
@media not (prefers-color-scheme: dark) {
|
||||
.not-dark\\:flex {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
@media not print {
|
||||
.not-print\\:flex {
|
||||
display: flex;
|
||||
}
|
||||
}"
|
||||
`)
|
||||
expect(
|
||||
run(['group-not-dark:flex', 'peer-not-dark:flex', 'not-print/foo:flex', 'not-dark/foo:flex']),
|
||||
).toEqual('')
|
||||
})
|
||||
|
||||
test('not with support queries', () => {
|
||||
expect(run(['not-supports-[display:grid]:flex'])).toMatchInlineSnapshot(`
|
||||
"@supports not (display: grid) {
|
||||
.not-supports-\\[display\\:grid\\]\\:flex {
|
||||
display: flex;
|
||||
}
|
||||
}"
|
||||
`)
|
||||
expect(
|
||||
run([
|
||||
'group-not-supports-[display:grid]:flex',
|
||||
'peer-not-supports-[display:grid]:flex',
|
||||
'not-supports-[display:grid]/foo:flex',
|
||||
]),
|
||||
).toEqual('')
|
||||
})
|
||||
|
||||
test('not with container queries', () => {
|
||||
expect(
|
||||
compileCss(
|
||||
css`
|
||||
@theme {
|
||||
--width-lg: 1024px;
|
||||
}
|
||||
@tailwind utilities;
|
||||
`,
|
||||
['not-@lg:flex', 'not-@lg/foo:flex'],
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
":root {
|
||||
--width-lg: 1024px;
|
||||
}
|
||||
|
||||
@container not (width >= 1024px) {
|
||||
.not-\\@lg\\:flex {
|
||||
display: flex;
|
||||
}
|
||||
}"
|
||||
`)
|
||||
expect(
|
||||
run(['group-not-@lg:flex', 'peer-not-@lg:flex', 'not-@lg/foo:flex', '@lg/foo:flex']),
|
||||
).toEqual('')
|
||||
})
|
||||
|
||||
test('has', () => {
|
||||
expect(
|
||||
run([
|
||||
|
|
|
|||
|
|
@ -209,7 +209,32 @@ export function createVariants(theme: Theme): Variants {
|
|||
|
||||
variants.compound('not', (ruleNode, variant) => {
|
||||
if (variant.modifier) return null
|
||||
ruleNode.selector = `&:not(${ruleNode.selector.replace('&', '*')})`
|
||||
|
||||
// At-rules
|
||||
if (ruleNode.selector[0] === '@') {
|
||||
// @media
|
||||
if (ruleNode.selector.startsWith('@media ')) {
|
||||
let queries = segment(ruleNode.selector.slice(7), ',')
|
||||
ruleNode.selector = `@media ${queries.map((query) => `not ${query}`).join(',')}`
|
||||
}
|
||||
|
||||
// @supports
|
||||
else if (ruleNode.selector.startsWith('@supports ')) {
|
||||
let queries = segment(ruleNode.selector.slice(10), ',')
|
||||
ruleNode.selector = `@supports ${queries.map((query) => `not ${query}`).join(',')}`
|
||||
}
|
||||
|
||||
// @container
|
||||
else if (ruleNode.selector.startsWith('@container ')) {
|
||||
let queries = segment(ruleNode.selector.slice(11), ',')
|
||||
ruleNode.selector = `@container ${queries.map((query) => `not ${query}`).join(',')}`
|
||||
}
|
||||
}
|
||||
|
||||
// Selectors
|
||||
else {
|
||||
ruleNode.selector = `&:not(${ruleNode.selector.replace('&', '*')})`
|
||||
}
|
||||
})
|
||||
|
||||
variants.compound('group', (ruleNode, variant) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue