Skip to content

Commit

Permalink
Make dark and rtl/ltr variants insensitive to DOM order (#10766)
Browse files Browse the repository at this point in the history
* Make `dark` and `rtl`/`ltr` variants insensitive to DOM order

* Add explicit test for stacking dark and rtl variants

* Update changelog

---------

Co-authored-by: Adam Wathan <[email protected]>
  • Loading branch information
adamwathan and adamwathan authored Mar 10, 2023
1 parent ba56e42 commit e40b73a
Show file tree
Hide file tree
Showing 12 changed files with 70 additions and 46 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [Oxide] Enable relative content paths for the `oxide` engine ([#10621](https://github.com/tailwindlabs/tailwindcss/pull/10621))
- Mark `rtl` and `ltr` variants as stable and remove warnings ([#10764](https://github.com/tailwindlabs/tailwindcss/pull/10764))
- Use `inset` instead of `top`, `right`, `bottom`, and `left` properties ([#10765](https://github.com/tailwindlabs/tailwindcss/pull/10765))
- Make `dark` and `rtl`/`ltr` variants insensitive to DOM order ([#10766](https://github.com/tailwindlabs/tailwindcss/pull/10766))

## [3.2.7] - 2023-02-16

Expand Down
6 changes: 3 additions & 3 deletions src/corePlugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ export let variantPlugins = {
},

directionVariants: ({ addVariant }) => {
addVariant('ltr', '[dir="ltr"] &')
addVariant('rtl', '[dir="rtl"] &')
addVariant('ltr', ':is([dir="ltr"] &)')
addVariant('rtl', ':is([dir="rtl"] &)')
},

reducedMotionVariants: ({ addVariant }) => {
Expand All @@ -221,7 +221,7 @@ export let variantPlugins = {
}

if (mode === 'class') {
addVariant('dark', `${className} &`)
addVariant('dark', `:is(${className} &)`)
} else if (mode === 'media') {
addVariant('dark', '@media (prefers-color-scheme: dark)')
}
Expand Down
12 changes: 6 additions & 6 deletions tests/apply.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,14 +216,14 @@ crosscheck(({ stable, oxide }) => {
text-align: left;
}
}
.dark .apply-dark-variant {
:is(.dark .apply-dark-variant) {
text-align: center;
}
.dark .apply-dark-variant:hover {
:is(.dark .apply-dark-variant:hover) {
text-align: right;
}
@media (min-width: 1024px) {
.dark .apply-dark-variant {
:is(.dark .apply-dark-variant) {
text-align: left;
}
}
Expand Down Expand Up @@ -513,14 +513,14 @@ crosscheck(({ stable, oxide }) => {
text-align: left;
}
}
.dark .apply-dark-variant {
:is(.dark .apply-dark-variant) {
text-align: center;
}
.dark .apply-dark-variant:hover {
:is(.dark .apply-dark-variant:hover) {
text-align: right;
}
@media (min-width: 1024px) {
.dark .apply-dark-variant {
:is(.dark .apply-dark-variant) {
text-align: left;
}
}
Expand Down
4 changes: 2 additions & 2 deletions tests/custom-separator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ crosscheck(() => {
.group:hover .group-hover_focus-within_text-left:focus-within {
text-align: left;
}
[dir='rtl'] .rtl_active_text-center:active {
:is([dir='rtl'] .rtl_active_text-center:active) {
text-align: center;
}
@media (prefers-reduced-motion: no-preference) {
.motion-safe_hover_text-center:hover {
text-align: center;
}
}
.dark .dark_focus_text-left:focus {
:is(.dark .dark_focus_text-left:focus) {
text-align: left;
}
@media (min-width: 768px) {
Expand Down
4 changes: 2 additions & 2 deletions tests/dark-mode.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ crosscheck(() => {
return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
${defaults}
.dark .dark\:font-bold {
:is(.dark .dark\:font-bold) {
font-weight: 700;
}
`)
Expand All @@ -40,7 +40,7 @@ crosscheck(() => {
return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
${defaults}
.test-dark .dark\:font-bold {
:is(.test-dark .dark\:font-bold) {
font-weight: 700;
}
`)
Expand Down
4 changes: 2 additions & 2 deletions tests/important-boolean.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,15 @@ crosscheck(() => {
.group:hover .group-hover\:focus-within\:text-left:focus-within {
text-align: left !important;
}
[dir='rtl'] .rtl\:active\:text-center:active {
:is([dir='rtl'] .rtl\:active\:text-center:active) {
text-align: center !important;
}
@media (prefers-reduced-motion: no-preference) {
.motion-safe\:hover\:text-center:hover {
text-align: center !important;
}
}
.dark .dark\:focus\:text-left:focus {
:is(.dark .dark\:focus\:text-left:focus) {
text-align: left !important;
}
@media (min-width: 768px) {
Expand Down
4 changes: 2 additions & 2 deletions tests/important-selector.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,15 @@ crosscheck(() => {
#app .group:hover .group-hover\:focus-within\:text-left:focus-within {
text-align: left;
}
#app [dir='rtl'] .rtl\:active\:text-center:active {
#app :is([dir='rtl'] .rtl\:active\:text-center:active) {
text-align: center;
}
@media (prefers-reduced-motion: no-preference) {
#app .motion-safe\:hover\:text-center:hover {
text-align: center;
}
}
#app .dark .dark\:focus\:text-left:focus {
#app :is(.dark .dark\:focus\:text-left:focus) {
text-align: left;
}
@media (min-width: 768px) {
Expand Down
16 changes: 8 additions & 8 deletions tests/kitchen-sink.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ crosscheck(({ stable, oxide }) => {
}
.drop-empty-rules:hover,
.group:hover .apply-group,
.dark .apply-dark-mode {
:is(.dark .apply-dark-mode) {
font-weight: 700;
}
.apply-with-existing:hover {
Expand Down Expand Up @@ -338,7 +338,7 @@ crosscheck(({ stable, oxide }) => {
.apply-order-b {
margin: 1.5rem 1.25rem 1.25rem;
}
.dark .group:hover .apply-dark-group-example-a {
:is(.dark .group:hover .apply-dark-group-example-a) {
--tw-bg-opacity: 1;
background-color: rgb(34 197 94 / var(--tw-bg-opacity));
}
Expand Down Expand Up @@ -715,7 +715,7 @@ crosscheck(({ stable, oxide }) => {
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
}
.dark .dark\:custom-util {
:is(.dark .dark\:custom-util) {
background: #abcdef;
}
@media (min-width: 640px) {
Expand Down Expand Up @@ -762,7 +762,7 @@ crosscheck(({ stable, oxide }) => {
transition-duration: 0.15s;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
.dark .md\:dark\:motion-safe\:foo\:active\:custom-util:active {
:is(.dark .md\:dark\:motion-safe\:foo\:active\:custom-util:active) {
background: #abcdef !important;
}
}
Expand Down Expand Up @@ -849,7 +849,7 @@ crosscheck(({ stable, oxide }) => {
}
.drop-empty-rules:hover,
.group:hover .apply-group,
.dark .apply-dark-mode {
:is(.dark .apply-dark-mode) {
font-weight: 700;
}
.apply-with-existing:hover {
Expand Down Expand Up @@ -883,7 +883,7 @@ crosscheck(({ stable, oxide }) => {
.apply-order-b {
margin: 1.5rem 1.25rem 1.25rem;
}
.dark .group:hover .apply-dark-group-example-a {
:is(.dark .group:hover .apply-dark-group-example-a) {
background-color: #22c55e;
}
@media (min-width: 640px) {
Expand Down Expand Up @@ -1250,7 +1250,7 @@ crosscheck(({ stable, oxide }) => {
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
}
.dark .dark\:custom-util {
:is(.dark .dark\:custom-util) {
background: #abcdef;
}
@media (min-width: 640px) {
Expand Down Expand Up @@ -1297,7 +1297,7 @@ crosscheck(({ stable, oxide }) => {
transition-duration: 0.15s;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
.dark .md\:dark\:motion-safe\:foo\:active\:custom-util:active {
:is(.dark .md\:dark\:motion-safe\:foo\:active\:custom-util:active) {
background: #abcdef !important;
}
}
Expand Down
8 changes: 4 additions & 4 deletions tests/prefix.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ crosscheck(({ stable, oxide }) => {
.custom-component {
font-weight: 700;
}
.tw-dark .tw-group:hover .custom-component {
:is(.tw-dark .tw-group:hover .custom-component) {
font-weight: 400;
}
.tw--ml-4 {
Expand All @@ -155,19 +155,19 @@ crosscheck(({ stable, oxide }) => {
.tw-group:hover .group-hover\:focus-within\:tw-text-left:focus-within {
text-align: left;
}
[dir='rtl'] .rtl\:active\:tw-text-center:active {
:is([dir='rtl'] .rtl\:active\:tw-text-center:active) {
text-align: center;
}
@media (prefers-reduced-motion: no-preference) {
.motion-safe\:hover\:tw-text-center:hover {
text-align: center;
}
}
.tw-dark .dark\:tw-bg-\[rgb\(255\,0\,0\)\] {
:is(.tw-dark .dark\:tw-bg-\[rgb\(255\,0\,0\)\]) {
--tw-bg-opacity: 1;
background-color: rgb(255 0 0 / var(--tw-bg-opacity));
}
.tw-dark .dark\:focus\:tw-text-left:focus {
:is(.tw-dark .dark\:focus\:tw-text-left:focus) {
text-align: left;
}
@media (min-width: 768px) {
Expand Down
17 changes: 8 additions & 9 deletions tests/variants.oxide.test.css
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,8 @@
.peer:disabled ~ .peer-disabled\:shadow-md,
.peer:disabled:focus:hover ~ .peer-disabled\:peer-focus\:peer-hover\:shadow-md,
.peer:disabled:focus:hover ~ .peer-disabled\:peer-focus\:peer-hover\:first\:shadow-md:first-child,
[dir="ltr"] .ltr\:shadow-md,
[dir="rtl"] .rtl\:shadow-md {
:is([dir='ltr'] .ltr\:shadow-md),
:is([dir='rtl'] .rtl\:shadow-md) {
--tw-shadow: 0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
Expand Down Expand Up @@ -318,9 +318,9 @@
background-color: #fde047;
}
}
.dark .dark\:shadow-md,
.dark .group:disabled:focus:hover .dark\:group-disabled\:group-focus\:group-hover\:shadow-md,
.dark .peer:disabled:focus:hover ~ .dark\:peer-disabled\:peer-focus\:peer-hover\:shadow-md {
:is(.dark .dark\:shadow-md),
:is(.dark .group:disabled:focus:hover .dark\:group-disabled\:group-focus\:group-hover\:shadow-md),
:is(.dark .peer:disabled:focus:hover ~ .dark\:peer-disabled\:peer-focus\:peer-hover\:shadow-md) {
--tw-shadow: 0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
Expand Down Expand Up @@ -361,7 +361,7 @@
animation: 1s linear infinite spin;
}
.lg\:shadow-md,
.dark .lg\:dark\:shadow-md {
:is(.dark .lg\:dark\:shadow-md) {
--tw-shadow: 0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color),
0 2px 4px -2px var(--tw-shadow-color);
Expand All @@ -371,7 +371,7 @@
}
@media (min-width: 1280px) {
.xl\:shadow-md,
.dark .xl\:dark\:disabled\:shadow-md:disabled {
:is(.dark .xl\:dark\:disabled\:shadow-md:disabled) {
--tw-shadow: 0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color),
0 2px 4px -2px var(--tw-shadow-color);
Expand All @@ -388,7 +388,7 @@
var(--tw-shadow);
}
@media (prefers-reduced-motion: no-preference) {
.dark .\32 xl\:dark\:motion-safe\:focus-within\:shadow-md:focus-within {
:is(.dark .\32 xl\:dark\:motion-safe\:focus-within\:shadow-md:focus-within) {
--tw-shadow: 0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color),
0 2px 4px -2px var(--tw-shadow-color);
Expand All @@ -407,4 +407,3 @@
background-color: #fde047;
}
}

16 changes: 8 additions & 8 deletions tests/variants.test.css
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,8 @@
.peer:disabled ~ .peer-disabled\:shadow-md,
.peer:disabled:focus:hover ~ .peer-disabled\:peer-focus\:peer-hover\:shadow-md,
.peer:disabled:focus:hover ~ .peer-disabled\:peer-focus\:peer-hover\:first\:shadow-md:first-child,
[dir='ltr'] .ltr\:shadow-md,
[dir='rtl'] .rtl\:shadow-md {
:is([dir='ltr'] .ltr\:shadow-md),
:is([dir='rtl'] .rtl\:shadow-md) {
--tw-shadow: 0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
Expand Down Expand Up @@ -336,9 +336,9 @@
background-color: rgb(253 224 71 / var(--tw-bg-opacity));
}
}
.dark .dark\:shadow-md,
.dark .group:disabled:focus:hover .dark\:group-disabled\:group-focus\:group-hover\:shadow-md,
.dark .peer:disabled:focus:hover ~ .dark\:peer-disabled\:peer-focus\:peer-hover\:shadow-md {
:is(.dark .dark\:shadow-md),
:is(.dark .group:disabled:focus:hover .dark\:group-disabled\:group-focus\:group-hover\:shadow-md),
:is(.dark .peer:disabled:focus:hover ~ .dark\:peer-disabled\:peer-focus\:peer-hover\:shadow-md) {
--tw-shadow: 0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
Expand Down Expand Up @@ -380,7 +380,7 @@
animation: 1s linear infinite spin;
}
.lg\:shadow-md,
.dark .lg\:dark\:shadow-md {
:is(.dark .lg\:dark\:shadow-md) {
--tw-shadow: 0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color),
0 2px 4px -2px var(--tw-shadow-color);
Expand All @@ -390,7 +390,7 @@
}
@media (min-width: 1280px) {
.xl\:shadow-md,
.dark .xl\:dark\:disabled\:shadow-md:disabled {
:is(.dark .xl\:dark\:disabled\:shadow-md:disabled) {
--tw-shadow: 0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color),
0 2px 4px -2px var(--tw-shadow-color);
Expand All @@ -407,7 +407,7 @@
var(--tw-shadow);
}
@media (prefers-reduced-motion: no-preference) {
.dark .\32 xl\:dark\:motion-safe\:focus-within\:shadow-md:focus-within {
:is(.dark .\32 xl\:dark\:motion-safe\:focus-within\:shadow-md:focus-within) {
--tw-shadow: 0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color),
0 2px 4px -2px var(--tw-shadow-color);
Expand Down
24 changes: 24 additions & 0 deletions tests/variants.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1128,4 +1128,28 @@ crosscheck(({ stable, oxide }) => {
}
`)
})

test('stacking dark and rtl variants', async () => {
let config = {
darkMode: 'class',
content: [
{
raw: html` <div class="dark:rtl:italic" /> `,
},
],
corePlugins: { preflight: false },
}

let input = css`
@tailwind utilities;
`

let result = await run(input, config)

expect(result.css).toMatchFormattedCss(css`
:is(.dark :is([dir='rtl'] .dark\:rtl\:italic)) {
font-style: italic;
}
`)
})
})

0 comments on commit e40b73a

Please sign in to comment.