Skip to content

Commit 128030f

Browse files
adamwathanbrowner12RobinMalfait
authored
Only apply hover styles when supported (future) (#8394)
* Only apply hover styles when supported (future) Co-Authored-By: Andrew Brown <[email protected]> * update changelog Co-authored-by: Andrew Brown <[email protected]> Co-authored-by: Robin Malfait <[email protected]>
1 parent bb4f5da commit 128030f

File tree

4 files changed

+57
-14
lines changed

4 files changed

+57
-14
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2828
### Changed
2929

3030
- Try using local `postcss` installation first in the CLI ([#8270](https://github.com/tailwindlabs/tailwindcss/pull/8270))
31+
- Only apply hover styles when supported (future) ([#8394](https://github.com/tailwindlabs/tailwindcss/pull/8394))
3132

3233
### Added
3334

src/corePlugins.js

+19-13
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { version as tailwindVersion } from '../package.json'
1414
import log from './util/log'
1515
import { normalizeScreens } from './util/normalizeScreens'
1616
import { formatBoxShadowValue, parseBoxShadowValue } from './util/parseBoxShadowValue'
17+
import { flagEnabled } from './featureFlags'
1718

1819
export let variantPlugins = {
1920
pseudoElementVariants: ({ addVariant }) => {
@@ -60,14 +61,14 @@ export let variantPlugins = {
6061
})
6162
},
6263

63-
pseudoClassVariants: ({ addVariant }) => {
64+
pseudoClassVariants: ({ addVariant, config }) => {
6465
let pseudoVariants = [
6566
// Positional
66-
['first', ':first-child'],
67-
['last', ':last-child'],
68-
['only', ':only-child'],
69-
['odd', ':nth-child(odd)'],
70-
['even', ':nth-child(even)'],
67+
['first', '&:first-child'],
68+
['last', '&:last-child'],
69+
['only', '&:only-child'],
70+
['odd', '&:nth-child(odd)'],
71+
['even', '&:nth-child(even)'],
7172
'first-of-type',
7273
'last-of-type',
7374
'only-of-type',
@@ -92,11 +93,11 @@ export let variantPlugins = {
9293
}
9394
})
9495

95-
return ':visited'
96+
return '&:visited'
9697
},
9798
],
9899
'target',
99-
['open', '[open]'],
100+
['open', '&[open]'],
100101

101102
// Forms
102103
'default',
@@ -116,35 +117,40 @@ export let variantPlugins = {
116117

117118
// Interactive
118119
'focus-within',
119-
'hover',
120+
[
121+
'hover',
122+
!flagEnabled(config(), 'hoverOnlyWhenSupported')
123+
? '&:hover'
124+
: '@media (hover: hover) and (pointer: fine) { &:hover }',
125+
],
120126
'focus',
121127
'focus-visible',
122128
'active',
123129
'enabled',
124130
'disabled',
125-
].map((variant) => (Array.isArray(variant) ? variant : [variant, `:${variant}`]))
131+
].map((variant) => (Array.isArray(variant) ? variant : [variant, `&:${variant}`]))
126132

127133
for (let [variantName, state] of pseudoVariants) {
128134
addVariant(variantName, (ctx) => {
129135
let result = typeof state === 'function' ? state(ctx) : state
130136

131-
return `&${result}`
137+
return result
132138
})
133139
}
134140

135141
for (let [variantName, state] of pseudoVariants) {
136142
addVariant(`group-${variantName}`, (ctx) => {
137143
let result = typeof state === 'function' ? state(ctx) : state
138144

139-
return `:merge(.group)${result} &`
145+
return result.replace(/&(\S+)/, ':merge(.group)$1 &')
140146
})
141147
}
142148

143149
for (let [variantName, state] of pseudoVariants) {
144150
addVariant(`peer-${variantName}`, (ctx) => {
145151
let result = typeof state === 'function' ? state(ctx) : state
146152

147-
return `:merge(.peer)${result} ~ &`
153+
return result.replace(/&(\S+)/, ':merge(.peer)$1 ~ &')
148154
})
149155
}
150156
},

src/featureFlags.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ let defaults = {
66
}
77

88
let featureFlags = {
9-
future: [],
9+
future: ['hoverOnlyWhenSupported'],
1010
experimental: ['optimizeUniversalDefaults'],
1111
}
1212

tests/variants.test.js

+36
Original file line numberDiff line numberDiff line change
@@ -769,3 +769,39 @@ it('variants only picks the used selectors in a group (apply)', () => {
769769
`)
770770
})
771771
})
772+
773+
test('hoverOnlyWhenSupported adds hover and pointer media features by default', () => {
774+
let config = {
775+
future: {
776+
hoverOnlyWhenSupported: true,
777+
},
778+
content: [
779+
{ raw: html`<div class="hover:underline group-hover:underline peer-hover:underline"></div>` },
780+
],
781+
corePlugins: { preflight: false },
782+
}
783+
784+
let input = css`
785+
@tailwind base;
786+
@tailwind components;
787+
@tailwind utilities;
788+
`
789+
790+
return run(input, config).then((result) => {
791+
expect(result.css).toMatchFormattedCss(css`
792+
${defaults}
793+
794+
@media (hover: hover) and (pointer: fine) {
795+
.hover\:underline:hover {
796+
text-decoration-line: underline;
797+
}
798+
.group:hover .group-hover\:underline {
799+
text-decoration-line: underline;
800+
}
801+
.peer:hover ~ .peer-hover\:underline {
802+
text-decoration-line: underline;
803+
}
804+
}
805+
`)
806+
})
807+
})

0 commit comments

Comments
 (0)