mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
Only apply hover on devices that support hover (#14500)
This PR updates the `hover` variant to only apply when `@media (hover:
hover)` matches.
```diff
.hover\:bg-black {
&:hover {
+ @media (hover: hover) {
background: black;
+ }
}
}
```
This is technically a breaking change because you may have built your
site in a way where some interactions depend on hover (like opening a
dropdown menu), and were relying on the fact that tapping on mobile
triggers hover.
To bring back the old hover behavior, users can override the `hover`
variant in their CSS file back to the simpler implementation:
```css
@import "tailwindcss";
@variant hover (&:hover);
```
I've opted to go with just `@media (hover: hover)` for this because it
seems like the best trade-off between the available options. Using
`(any-hover: hover)` would mean users would get sticky hover states when
tapping on an iPad if they have a mouse or trackpad connected, which
feels wrong to me because in those cases touch is still likely the
primary method of interaction.
Sites built with this feature in mind will be treating hover styles as
progressive enhancement, so it seems better to me that using an iPad
with a mouse would not have hover styles, vs. having sticky hover styles
in the same situation.
Of course users can always override this with whatever they want, so
making this the default isn't locking anyone in to a particular choice.
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
This commit is contained in:
parent
a270e2c8f1
commit
abde4c9694
@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Preserve explicit transition duration and timing function when overriding transition property ([#14490](https://github.com/tailwindlabs/tailwindcss/pull/14490))
|
||||
- Change the implementation for `@import` resolution to speed up initial builds ([#14446](https://github.com/tailwindlabs/tailwindcss/pull/14446))
|
||||
- Remove automatic `var(…)` injection ([#13657](https://github.com/tailwindlabs/tailwindcss/pull/13657))
|
||||
- Only apply `:hover` states on devices that support `@media (hover: hover)` ([#14500](https://github.com/tailwindlabs/tailwindcss/pull/14500))
|
||||
|
||||
## [4.0.0-alpha.24] - 2024-09-11
|
||||
|
||||
|
||||
@ -42,7 +42,31 @@ export default defineConfig({
|
||||
},
|
||||
{
|
||||
name: 'firefox',
|
||||
use: { ...devices['Desktop Firefox'] },
|
||||
use: {
|
||||
...devices['Desktop Firefox'],
|
||||
// https://playwright.dev/docs/test-use-options#more-browser-and-context-options
|
||||
launchOptions: {
|
||||
// https://playwright.dev/docs/api/class-browsertype#browser-type-launch-option-firefox-user-prefs
|
||||
firefoxUserPrefs: {
|
||||
// By default, headless Firefox runs as though no pointers
|
||||
// capabilities are available.
|
||||
// https://github.com/microsoft/playwright/issues/7769#issuecomment-966098074
|
||||
//
|
||||
// This impacts our `hover` variant implementation which uses an
|
||||
// '(hover: hover)' media query to determine if hover is available.
|
||||
//
|
||||
// Available values for pointer capabilities:
|
||||
// NO_POINTER = 0x00;
|
||||
// COARSE_POINTER = 0x01;
|
||||
// FINE_POINTER = 0x02;
|
||||
// HOVER_CAPABLE_POINTER = 0x04;
|
||||
//
|
||||
// Setting to 0x02 | 0x04 says the system supports a mouse
|
||||
'ui.primaryPointerCapabilities': 0x02 | 0x04,
|
||||
'ui.allPointerCapabilities': 0x02 | 0x04,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
/* Test against mobile viewports. */
|
||||
|
||||
@ -1919,8 +1919,10 @@ describe('matchVariant', () => {
|
||||
"@layer utilities {
|
||||
@media (width >= 100px) {
|
||||
@media (width <= 200px) {
|
||||
.testmin-\\[100px\\]\\:testmax-\\[200px\\]\\:hover\\:underline:hover {
|
||||
text-decoration-line: underline;
|
||||
@media (hover: hover) {
|
||||
.testmin-\\[100px\\]\\:testmax-\\[200px\\]\\:hover\\:underline:hover {
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,8 +35,10 @@ describe('compiling CSS', () => {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.hover\\:underline:hover {
|
||||
text-decoration-line: underline;
|
||||
@media (hover: hover) {
|
||||
.hover\\:underline:hover {
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
}
|
||||
|
||||
@media (width >= 768px) {
|
||||
@ -193,8 +195,10 @@ describe('@apply', () => {
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
|
||||
.foo:hover {
|
||||
background-color: var(--color-blue-500, #3b82f6);
|
||||
@media (hover: hover) {
|
||||
.foo:hover {
|
||||
background-color: var(--color-blue-500, #3b82f6);
|
||||
}
|
||||
}
|
||||
|
||||
@media (width >= 768px) {
|
||||
@ -390,16 +394,20 @@ describe('arbitrary variants', () => {
|
||||
describe('variant stacking', () => {
|
||||
it('should stack simple variants', async () => {
|
||||
expect(await run(['focus:hover:flex'])).toMatchInlineSnapshot(`
|
||||
".focus\\:hover\\:flex:focus:hover {
|
||||
display: flex;
|
||||
"@media (hover: hover) {
|
||||
.focus\\:hover\\:flex:focus:hover {
|
||||
display: flex;
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
it('should stack arbitrary variants and simple variants', async () => {
|
||||
expect(await run(['[&_p]:hover:flex'])).toMatchInlineSnapshot(`
|
||||
".\\[\\&_p\\]\\:hover\\:flex p:hover {
|
||||
display: flex;
|
||||
"@media (hover: hover) {
|
||||
.\\[\\&_p\\]\\:hover\\:flex p:hover {
|
||||
display: flex;
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
@ -420,13 +428,17 @@ describe('variant stacking', () => {
|
||||
content: var(--tw-content);
|
||||
}
|
||||
|
||||
.before\\:hover\\:flex:before:hover {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.before\\:hover\\:flex:before:hover {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.hover\\:before\\:flex:hover:before {
|
||||
content: var(--tw-content);
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.hover\\:before\\:flex:hover:before {
|
||||
content: var(--tw-content);
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
@supports (-moz-orient: inline) {
|
||||
@ -627,22 +639,24 @@ describe('sorting', () => {
|
||||
),
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
".pointer-events-none {
|
||||
pointer-events: none;
|
||||
}
|
||||
".pointer-events-none {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
.hover\\:flex:hover {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.focus\\:pointer-events-none:focus {
|
||||
pointer-events: none;
|
||||
}"
|
||||
`)
|
||||
.focus\\:pointer-events-none:focus {
|
||||
pointer-events: none;
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
/**
|
||||
@ -672,16 +686,20 @@ describe('sorting', () => {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.hover\\:flex:hover {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.hover\\:flex:hover {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.focus\\:flex:focus {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.hover\\:focus\\:flex:hover:focus {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.hover\\:focus\\:flex:hover:focus {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.disabled\\:flex:disabled {
|
||||
@ -715,44 +733,64 @@ describe('sorting', () => {
|
||||
].sort(() => Math.random() - 0.5),
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
".group-hover\\:flex:is(:where(.group):hover *) {
|
||||
display: flex;
|
||||
"@media (hover: hover) {
|
||||
.group-hover\\:flex:is(:where(.group):hover *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.group-focus\\:flex:is(:where(.group):focus *) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.peer-hover\\:flex:is(:where(.peer):hover ~ *) {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.peer-hover\\:flex:is(:where(.peer):hover ~ *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.group-hover\\:peer-hover\\:flex:is(:where(.group):hover *):is(:where(.peer):hover ~ *) {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
@media (hover: hover) {
|
||||
.group-hover\\:peer-hover\\:flex:is(:where(.group):hover *):is(:where(.peer):hover ~ *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.peer-hover\\:group-hover\\:flex:is(:where(.peer):hover ~ *):is(:where(.group):hover *) {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
@media (hover: hover) {
|
||||
.peer-hover\\:group-hover\\:flex:is(:where(.peer):hover ~ *):is(:where(.group):hover *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.group-focus\\:peer-hover\\:flex:is(:where(.group):focus *):is(:where(.peer):hover ~ *) {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.group-focus\\:peer-hover\\:flex:is(:where(.group):focus *):is(:where(.peer):hover ~ *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.peer-hover\\:group-focus\\:flex:is(:where(.peer):hover ~ *):is(:where(.group):focus *) {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.peer-hover\\:group-focus\\:flex:is(:where(.peer):hover ~ *):is(:where(.group):focus *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.peer-focus\\:flex:is(:where(.peer):focus ~ *) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.group-hover\\:peer-focus\\:flex:is(:where(.group):hover *):is(:where(.peer):focus ~ *) {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.group-hover\\:peer-focus\\:flex:is(:where(.group):hover *):is(:where(.peer):focus ~ *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.peer-focus\\:group-hover\\:flex:is(:where(.peer):focus ~ *):is(:where(.group):hover *) {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.peer-focus\\:group-hover\\:flex:is(:where(.peer):focus ~ *):is(:where(.group):hover *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.group-focus\\:peer-focus\\:flex:is(:where(.group):focus *):is(:where(.peer):focus ~ *) {
|
||||
@ -763,8 +801,10 @@ describe('sorting', () => {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.hover\\:flex:hover {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.hover\\:flex:hover {
|
||||
display: flex;
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
@ -2104,8 +2144,10 @@ describe('@variant', () => {
|
||||
expect(optimizeCss(compiled).trim()).toMatchInlineSnapshot(`
|
||||
"@layer utilities {
|
||||
@media (any-hover: hover) {
|
||||
.any-hover\\:hover\\:underline:hover {
|
||||
text-decoration-line: underline;
|
||||
@media (hover: hover) {
|
||||
.any-hover\\:hover\\:underline:hover {
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}"
|
||||
|
||||
@ -15660,10 +15660,12 @@ describe('custom utilities', () => {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.hover\\:foo:hover {
|
||||
flex-direction: column;
|
||||
text-decoration-line: underline;
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.hover\\:foo:hover {
|
||||
flex-direction: column;
|
||||
text-decoration-line: underline;
|
||||
display: flex;
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
@ -581,16 +581,22 @@ test('focus-within', async () => {
|
||||
|
||||
test('hover', async () => {
|
||||
expect(await run(['hover:flex', 'group-hover:flex', 'peer-hover:flex'])).toMatchInlineSnapshot(`
|
||||
".group-hover\\:flex:is(:where(.group):hover *) {
|
||||
display: flex;
|
||||
"@media (hover: hover) {
|
||||
.group-hover\\:flex:is(:where(.group):hover *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.peer-hover\\:flex:is(:where(.peer):hover ~ *) {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.peer-hover\\:flex:is(:where(.peer):hover ~ *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.hover\\:flex:hover {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.hover\\:flex:hover {
|
||||
display: flex;
|
||||
}
|
||||
}"
|
||||
`)
|
||||
expect(await run(['hover/foo:flex'])).toEqual('')
|
||||
@ -615,8 +621,10 @@ test('focus', async () => {
|
||||
|
||||
test('group-hover group-focus sorting', async () => {
|
||||
expect(await run(['group-hover:flex', 'group-focus:flex'])).toMatchInlineSnapshot(`
|
||||
".group-hover\\:flex:is(:where(.group):hover *) {
|
||||
display: flex;
|
||||
"@media (hover: hover) {
|
||||
.group-hover\\:flex:is(:where(.group):hover *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.group-focus\\:flex:is(:where(.group):focus *) {
|
||||
@ -624,8 +632,10 @@ test('group-hover group-focus sorting', async () => {
|
||||
}"
|
||||
`)
|
||||
expect(await run(['group-focus:flex', 'group-hover:flex'])).toMatchInlineSnapshot(`
|
||||
".group-hover\\:flex:is(:where(.group):hover *) {
|
||||
display: flex;
|
||||
"@media (hover: hover) {
|
||||
.group-hover\\:flex:is(:where(.group):hover *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.group-focus\\:flex:is(:where(.group):focus *) {
|
||||
@ -741,16 +751,24 @@ test('group-[...]', async () => {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.group-\\[\\&_p\\]\\:hover\\:flex:is(:where(.group) p *):hover {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.group-\\[\\&_p\\]\\:hover\\:flex:is(:where(.group) p *):hover {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.hover\\:group-\\[\\&_p\\]\\:flex:hover:is(:where(.group) p *) {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.hover\\:group-\\[\\&_p\\]\\:flex:hover:is(:where(.group) p *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.hover\\:group-\\[\\&_p\\]\\:hover\\:flex:hover:is(:where(.group) p *):hover {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
@media (hover: hover) {
|
||||
.hover\\:group-\\[\\&_p\\]\\:hover\\:flex:hover:is(:where(.group) p *):hover {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}"
|
||||
`)
|
||||
|
||||
@ -786,20 +804,26 @@ test('group-*', async () => {
|
||||
],
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
".group-hover\\:flex:is(:where(.group):hover *) {
|
||||
display: flex;
|
||||
"@media (hover: hover) {
|
||||
.group-hover\\:flex:is(:where(.group):hover *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.group-focus\\:flex:is(:where(.group):focus *) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.group-focus\\:group-hover\\:flex:is(:where(.group):focus *):is(:where(.group):hover *) {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.group-focus\\:group-hover\\:flex:is(:where(.group):focus *):is(:where(.group):hover *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.group-hover\\:group-focus\\:flex:is(:where(.group):hover *):is(:where(.group):focus *) {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.group-hover\\:group-focus\\:flex:is(:where(.group):hover *):is(:where(.group):focus *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.group-hocus\\:flex:is(:is(:where(.group):hover, :where(.group):focus) *) {
|
||||
@ -843,16 +867,22 @@ test('peer-[...]', async () => {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.hover\\:peer-\\[\\&_p\\]\\:flex:hover:is(:where(.peer) p ~ *) {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.hover\\:peer-\\[\\&_p\\]\\:flex:hover:is(:where(.peer) p ~ *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.peer-\\[\\&_p\\]\\:hover\\:flex:is(:where(.peer) p ~ *):hover {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.peer-\\[\\&_p\\]\\:hover\\:flex:is(:where(.peer) p ~ *):hover {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.hover\\:peer-\\[\\&_p\\]\\:focus\\:flex:hover:is(:where(.peer) p ~ *):focus {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.hover\\:peer-\\[\\&_p\\]\\:focus\\:flex:hover:is(:where(.peer) p ~ *):focus {
|
||||
display: flex;
|
||||
}
|
||||
}"
|
||||
`)
|
||||
|
||||
@ -887,20 +917,26 @@ test('peer-*', async () => {
|
||||
],
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
".peer-hover\\:flex:is(:where(.peer):hover ~ *) {
|
||||
display: flex;
|
||||
"@media (hover: hover) {
|
||||
.peer-hover\\:flex:is(:where(.peer):hover ~ *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.peer-focus\\:flex:is(:where(.peer):focus ~ *) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.peer-focus\\:peer-hover\\:flex:is(:where(.peer):focus ~ *):is(:where(.peer):hover ~ *) {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.peer-focus\\:peer-hover\\:flex:is(:where(.peer):focus ~ *):is(:where(.peer):hover ~ *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.peer-hover\\:peer-focus\\:flex:is(:where(.peer):hover ~ *):is(:where(.peer):focus ~ *) {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.peer-hover\\:peer-focus\\:flex:is(:where(.peer):hover ~ *):is(:where(.peer):focus ~ *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.peer-hocus\\:flex:is(:is(:where(.peer):hover, :where(.peer):focus) ~ *) {
|
||||
@ -2479,12 +2515,16 @@ test('variant order', async () => {
|
||||
--breakpoint-2xl: 1536px;
|
||||
}
|
||||
|
||||
.group-hover\\:flex:is(:where(.group):hover *) {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.group-hover\\:flex:is(:where(.group):hover *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.peer-hover\\:flex:is(:where(.peer):hover ~ *) {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.peer-hover\\:flex:is(:where(.peer):hover ~ *) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.first-letter\\:flex:first-letter {
|
||||
@ -2625,8 +2665,10 @@ test('variant order', async () => {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.hover\\:flex:hover {
|
||||
display: flex;
|
||||
@media (hover: hover) {
|
||||
.hover\\:flex:hover {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.focus\\:flex:focus {
|
||||
|
||||
@ -413,65 +413,48 @@ export function createVariants(theme: Theme): Variants {
|
||||
)
|
||||
}
|
||||
|
||||
let pseudos: [name: string, selector: string][] = [
|
||||
// Positional
|
||||
['first', '&:first-child'],
|
||||
['last', '&:last-child'],
|
||||
['only', '&:only-child'],
|
||||
['odd', '&:nth-child(odd)'],
|
||||
['even', '&:nth-child(even)'],
|
||||
['first-of-type', '&:first-of-type'],
|
||||
['last-of-type', '&:last-of-type'],
|
||||
['only-of-type', '&:only-of-type'],
|
||||
// Positional
|
||||
staticVariant('first', ['&:first-child'])
|
||||
staticVariant('last', ['&:last-child'])
|
||||
staticVariant('only', ['&:only-child'])
|
||||
staticVariant('odd', ['&:nth-child(odd)'])
|
||||
staticVariant('even', ['&:nth-child(even)'])
|
||||
staticVariant('first-of-type', ['&:first-of-type'])
|
||||
staticVariant('last-of-type', ['&:last-of-type'])
|
||||
staticVariant('only-of-type', ['&:only-of-type'])
|
||||
|
||||
// State
|
||||
// TODO: Remove alpha vars or no?
|
||||
['visited', '&:visited'],
|
||||
// State
|
||||
staticVariant('visited', ['&:visited'])
|
||||
staticVariant('target', ['&:target'])
|
||||
staticVariant('open', ['&:is([open], :popover-open)'])
|
||||
|
||||
['target', '&:target'],
|
||||
['open', '&:is([open], :popover-open)'],
|
||||
// Forms
|
||||
staticVariant('default', ['&:default'])
|
||||
staticVariant('checked', ['&:checked'])
|
||||
staticVariant('indeterminate', ['&:indeterminate'])
|
||||
staticVariant('placeholder-shown', ['&:placeholder-shown'])
|
||||
staticVariant('autofill', ['&:autofill'])
|
||||
staticVariant('optional', ['&:optional'])
|
||||
staticVariant('required', ['&:required'])
|
||||
staticVariant('valid', ['&:valid'])
|
||||
staticVariant('invalid', ['&:invalid'])
|
||||
staticVariant('in-range', ['&:in-range'])
|
||||
staticVariant('out-of-range', ['&:out-of-range'])
|
||||
staticVariant('read-only', ['&:read-only'])
|
||||
|
||||
// Forms
|
||||
['default', '&:default'],
|
||||
['checked', '&:checked'],
|
||||
['indeterminate', '&:indeterminate'],
|
||||
['placeholder-shown', '&:placeholder-shown'],
|
||||
['autofill', '&:autofill'],
|
||||
['optional', '&:optional'],
|
||||
['required', '&:required'],
|
||||
['valid', '&:valid'],
|
||||
['invalid', '&:invalid'],
|
||||
['in-range', '&:in-range'],
|
||||
['out-of-range', '&:out-of-range'],
|
||||
['read-only', '&:read-only'],
|
||||
// Content
|
||||
staticVariant('empty', ['&:empty'])
|
||||
|
||||
// Content
|
||||
['empty', '&:empty'],
|
||||
|
||||
// Interactive
|
||||
['focus-within', '&:focus-within'],
|
||||
[
|
||||
'hover',
|
||||
'&:hover',
|
||||
// TODO: Update tests for this:
|
||||
// v => {
|
||||
// v.nodes = [
|
||||
// rule('@media (hover: hover) and (pointer: fine)', [
|
||||
// rule('&:hover', v.nodes),
|
||||
// ]),
|
||||
// ]
|
||||
// }
|
||||
],
|
||||
['focus', '&:focus'],
|
||||
['focus-visible', '&:focus-visible'],
|
||||
['active', '&:active'],
|
||||
['enabled', '&:enabled'],
|
||||
['disabled', '&:disabled'],
|
||||
]
|
||||
|
||||
for (let [key, value] of pseudos) {
|
||||
staticVariant(key, [value])
|
||||
}
|
||||
// Interactive
|
||||
staticVariant('focus-within', ['&:focus-within'])
|
||||
variants.static('hover', (r) => {
|
||||
r.nodes = [rule('&:hover', [rule('@media (hover: hover)', r.nodes)])]
|
||||
})
|
||||
staticVariant('focus', ['&:focus'])
|
||||
staticVariant('focus-visible', ['&:focus-visible'])
|
||||
staticVariant('active', ['&:active'])
|
||||
staticVariant('enabled', ['&:enabled'])
|
||||
staticVariant('disabled', ['&:disabled'])
|
||||
|
||||
staticVariant('inert', ['&:is([inert], [inert] *)'])
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user