diff --git a/CHANGELOG.md b/CHANGELOG.md index 1de21457320f..a264706445bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Apply variants from left to right instead of inside-out ([#13478](https://github.com/tailwindlabs/tailwindcss/pull/13478)) +- Don't special-case `[hidden]` elements in `space-*`/`divide-*` utilities ([#13459](https://github.com/tailwindlabs/tailwindcss/pull/13459)) ## [4.0.0-alpha.13] - 2024-04-04 diff --git a/packages/tailwindcss/src/index.test.ts b/packages/tailwindcss/src/index.test.ts index b31f6c702ff4..8d5cd8f8e7b0 100644 --- a/packages/tailwindcss/src/index.test.ts +++ b/packages/tailwindcss/src/index.test.ts @@ -533,9 +533,9 @@ describe('sorting', () => { gap: var(--spacing-4, 1rem); } - :where(.space-x-2 > :not([hidden]) ~ :not([hidden])) { - margin-inline-start: calc(var(--spacing-2, .5rem) * calc(1 - var(--tw-space-x-reverse))); - margin-inline-end: calc(var(--spacing-2, .5rem) * var(--tw-space-x-reverse)); + :where(.space-x-2 > :not(:last-child)) { + margin-inline-start: calc(var(--spacing-2, .5rem) * var(--tw-space-x-reverse)); + margin-inline-end: calc(var(--spacing-2, .5rem) * calc(1 - var(--tw-space-x-reverse))); } @property --tw-space-x-reverse { diff --git a/packages/tailwindcss/src/utilities.test.ts b/packages/tailwindcss/src/utilities.test.ts index 7ea5213ed06a..2ff35b1cb066 100644 --- a/packages/tailwindcss/src/utilities.test.ts +++ b/packages/tailwindcss/src/utilities.test.ts @@ -5296,19 +5296,19 @@ test('space-x', () => { --spacing-4: 1rem; } - :where(.-space-x-4 > :not([hidden]) ~ :not([hidden])) { - margin-inline-start: calc(calc(var(--spacing-4, 1rem) * -1) * calc(1 - var(--tw-space-x-reverse))); - margin-inline-end: calc(calc(var(--spacing-4, 1rem) * -1) * var(--tw-space-x-reverse)); + :where(.-space-x-4 > :not(:last-child)) { + margin-inline-start: calc(calc(var(--spacing-4, 1rem) * -1) * var(--tw-space-x-reverse)); + margin-inline-end: calc(calc(var(--spacing-4, 1rem) * -1) * calc(1 - var(--tw-space-x-reverse))); } - :where(.space-x-4 > :not([hidden]) ~ :not([hidden])) { - margin-inline-start: calc(var(--spacing-4, 1rem) * calc(1 - var(--tw-space-x-reverse))); - margin-inline-end: calc(var(--spacing-4, 1rem) * var(--tw-space-x-reverse)); + :where(.space-x-4 > :not(:last-child)) { + margin-inline-start: calc(var(--spacing-4, 1rem) * var(--tw-space-x-reverse)); + margin-inline-end: calc(var(--spacing-4, 1rem) * calc(1 - var(--tw-space-x-reverse))); } - :where(.space-x-\\[4px\\] > :not([hidden]) ~ :not([hidden])) { - margin-inline-start: calc(4px * calc(1 - var(--tw-space-x-reverse))); - margin-inline-end: calc(4px * var(--tw-space-x-reverse)); + :where(.space-x-\\[4px\\] > :not(:last-child)) { + margin-inline-start: calc(4px * var(--tw-space-x-reverse)); + margin-inline-end: calc(4px * calc(1 - var(--tw-space-x-reverse))); } @property --tw-space-x-reverse { @@ -5336,19 +5336,19 @@ test('space-y', () => { --spacing-4: 1rem; } - :where(.-space-y-4 > :not([hidden]) ~ :not([hidden])) { - margin-bottom: calc(calc(var(--spacing-4, 1rem) * -1) * var(--tw-space-y-reverse)); - margin-top: calc(calc(var(--spacing-4, 1rem) * -1) * calc(1 - var(--tw-space-y-reverse))); + :where(.-space-y-4 > :not(:last-child)) { + margin-top: calc(calc(var(--spacing-4, 1rem) * -1) * var(--tw-space-y-reverse)); + margin-bottom: calc(calc(var(--spacing-4, 1rem) * -1) * calc(1 - var(--tw-space-y-reverse))); } - :where(.space-y-4 > :not([hidden]) ~ :not([hidden])) { - margin-bottom: calc(var(--spacing-4, 1rem) * var(--tw-space-y-reverse)); - margin-top: calc(var(--spacing-4, 1rem) * calc(1 - var(--tw-space-y-reverse))); + :where(.space-y-4 > :not(:last-child)) { + margin-top: calc(var(--spacing-4, 1rem) * var(--tw-space-y-reverse)); + margin-bottom: calc(var(--spacing-4, 1rem) * calc(1 - var(--tw-space-y-reverse))); } - :where(.space-y-\\[4px\\] > :not([hidden]) ~ :not([hidden])) { - margin-bottom: calc(4px * var(--tw-space-y-reverse)); - margin-top: calc(4px * calc(1 - var(--tw-space-y-reverse))); + :where(.space-y-\\[4px\\] > :not(:last-child)) { + margin-top: calc(4px * var(--tw-space-y-reverse)); + margin-bottom: calc(4px * calc(1 - var(--tw-space-y-reverse))); } @property --tw-space-y-reverse { @@ -5362,7 +5362,7 @@ test('space-y', () => { test('space-x-reverse', () => { expect(run(['space-x-reverse'])).toMatchInlineSnapshot(` - ":where(.space-x-reverse > :not([hidden]) ~ :not([hidden])) { + ":where(.space-x-reverse > :not(:last-child)) { --tw-space-x-reverse: 1; } @@ -5377,7 +5377,7 @@ test('space-x-reverse', () => { test('space-y-reverse', () => { expect(run(['space-y-reverse'])).toMatchInlineSnapshot(` - ":where(.space-y-reverse > :not([hidden]) ~ :not([hidden])) { + ":where(.space-y-reverse > :not(:last-child)) { --tw-space-y-reverse: 1; } @@ -5399,28 +5399,28 @@ test('divide-x', () => { ['divide-x', 'divide-x-4', 'divide-x-123', 'divide-x-[4px]'], ), ).toMatchInlineSnapshot(` - ":where(.divide-x > :not([hidden]) ~ :not([hidden])) { + ":where(.divide-x > :not(:last-child)) { border-inline-style: var(--tw-border-style); - border-inline-end-width: calc(1px * var(--tw-divide-x-reverse)); - border-inline-start-width: calc(1px * calc(1 - var(--tw-divide-x-reverse))); + border-inline-start-width: calc(1px * var(--tw-divide-x-reverse)); + border-inline-end-width: calc(1px * calc(1 - var(--tw-divide-x-reverse))); } - :where(.divide-x-123 > :not([hidden]) ~ :not([hidden])) { + :where(.divide-x-123 > :not(:last-child)) { border-inline-style: var(--tw-border-style); - border-inline-end-width: calc(123px * var(--tw-divide-x-reverse)); - border-inline-start-width: calc(123px * calc(1 - var(--tw-divide-x-reverse))); + border-inline-start-width: calc(123px * var(--tw-divide-x-reverse)); + border-inline-end-width: calc(123px * calc(1 - var(--tw-divide-x-reverse))); } - :where(.divide-x-4 > :not([hidden]) ~ :not([hidden])) { + :where(.divide-x-4 > :not(:last-child)) { border-inline-style: var(--tw-border-style); - border-inline-end-width: calc(4px * var(--tw-divide-x-reverse)); - border-inline-start-width: calc(4px * calc(1 - var(--tw-divide-x-reverse))); + border-inline-start-width: calc(4px * var(--tw-divide-x-reverse)); + border-inline-end-width: calc(4px * calc(1 - var(--tw-divide-x-reverse))); } - :where(.divide-x-\\[4px\\] > :not([hidden]) ~ :not([hidden])) { + :where(.divide-x-\\[4px\\] > :not(:last-child)) { border-inline-style: var(--tw-border-style); - border-inline-end-width: calc(4px * var(--tw-divide-x-reverse)); - border-inline-start-width: calc(4px * calc(1 - var(--tw-divide-x-reverse))); + border-inline-start-width: calc(4px * var(--tw-divide-x-reverse)); + border-inline-end-width: calc(4px * calc(1 - var(--tw-divide-x-reverse))); } @property --tw-divide-x-reverse { @@ -5454,10 +5454,10 @@ test('divide-x with custom default border width', () => { --default-border-width: 2px; } - :where(.divide-x > :not([hidden]) ~ :not([hidden])) { + :where(.divide-x > :not(:last-child)) { border-inline-style: var(--tw-border-style); - border-inline-end-width: calc(2px * var(--tw-divide-x-reverse)); - border-inline-start-width: calc(2px * calc(1 - var(--tw-divide-x-reverse))); + border-inline-start-width: calc(2px * var(--tw-divide-x-reverse)); + border-inline-end-width: calc(2px * calc(1 - var(--tw-divide-x-reverse))); } @property --tw-divide-x-reverse { @@ -5483,32 +5483,32 @@ test('divide-y', () => { ['divide-y', 'divide-y-4', 'divide-y-123', 'divide-y-[4px]'], ), ).toMatchInlineSnapshot(` - ":where(.divide-y > :not([hidden]) ~ :not([hidden])) { - border-top-style: var(--tw-border-style); + ":where(.divide-y > :not(:last-child)) { border-bottom-style: var(--tw-border-style); - border-bottom-width: calc(1px * var(--tw-divide-y-reverse)); - border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); + border-top-style: var(--tw-border-style); + border-top-width: calc(1px * var(--tw-divide-y-reverse)); + border-bottom-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); } - :where(.divide-y-123 > :not([hidden]) ~ :not([hidden])) { - border-top-style: var(--tw-border-style); + :where(.divide-y-123 > :not(:last-child)) { border-bottom-style: var(--tw-border-style); - border-bottom-width: calc(123px * var(--tw-divide-y-reverse)); - border-top-width: calc(123px * calc(1 - var(--tw-divide-y-reverse))); + border-top-style: var(--tw-border-style); + border-top-width: calc(123px * var(--tw-divide-y-reverse)); + border-bottom-width: calc(123px * calc(1 - var(--tw-divide-y-reverse))); } - :where(.divide-y-4 > :not([hidden]) ~ :not([hidden])) { - border-top-style: var(--tw-border-style); + :where(.divide-y-4 > :not(:last-child)) { border-bottom-style: var(--tw-border-style); - border-bottom-width: calc(4px * var(--tw-divide-y-reverse)); - border-top-width: calc(4px * calc(1 - var(--tw-divide-y-reverse))); + border-top-style: var(--tw-border-style); + border-top-width: calc(4px * var(--tw-divide-y-reverse)); + border-bottom-width: calc(4px * calc(1 - var(--tw-divide-y-reverse))); } - :where(.divide-y-\\[4px\\] > :not([hidden]) ~ :not([hidden])) { - border-top-style: var(--tw-border-style); + :where(.divide-y-\\[4px\\] > :not(:last-child)) { border-bottom-style: var(--tw-border-style); - border-bottom-width: calc(4px * var(--tw-divide-y-reverse)); - border-top-width: calc(4px * calc(1 - var(--tw-divide-y-reverse))); + border-top-style: var(--tw-border-style); + border-top-width: calc(4px * var(--tw-divide-y-reverse)); + border-bottom-width: calc(4px * calc(1 - var(--tw-divide-y-reverse))); } @property --tw-divide-y-reverse { @@ -5542,11 +5542,11 @@ test('divide-y with custom default border width', () => { --default-border-width: 2px; } - :where(.divide-y > :not([hidden]) ~ :not([hidden])) { - border-top-style: var(--tw-border-style); + :where(.divide-y > :not(:last-child)) { border-bottom-style: var(--tw-border-style); - border-bottom-width: calc(2px * var(--tw-divide-y-reverse)); - border-top-width: calc(2px * calc(1 - var(--tw-divide-y-reverse))); + border-top-style: var(--tw-border-style); + border-top-width: calc(2px * var(--tw-divide-y-reverse)); + border-bottom-width: calc(2px * calc(1 - var(--tw-divide-y-reverse))); } @property --tw-divide-y-reverse { @@ -5565,7 +5565,7 @@ test('divide-y with custom default border width', () => { test('divide-x-reverse', () => { expect(run(['divide-x-reverse'])).toMatchInlineSnapshot(` - ":where(.divide-x-reverse > :not([hidden]) ~ :not([hidden])) { + ":where(.divide-x-reverse > :not(:last-child)) { --tw-divide-x-reverse: 1; } @@ -5580,7 +5580,7 @@ test('divide-x-reverse', () => { test('divide-y-reverse', () => { expect(run(['divide-y-reverse'])).toMatchInlineSnapshot(` - ":where(.divide-y-reverse > :not([hidden]) ~ :not([hidden])) { + ":where(.divide-y-reverse > :not(:last-child)) { --tw-divide-y-reverse: 1; } @@ -5596,27 +5596,27 @@ test('divide-y-reverse', () => { test('divide-style', () => { expect(run(['divide-solid', 'divide-dashed', 'divide-dotted', 'divide-double', 'divide-none'])) .toMatchInlineSnapshot(` - ":where(.divide-dashed > :not([hidden]) ~ :not([hidden])) { + ":where(.divide-dashed > :not(:last-child)) { --tw-border-style: dashed; border-style: dashed; } - :where(.divide-dotted > :not([hidden]) ~ :not([hidden])) { + :where(.divide-dotted > :not(:last-child)) { --tw-border-style: dotted; border-style: dotted; } - :where(.divide-double > :not([hidden]) ~ :not([hidden])) { + :where(.divide-double > :not(:last-child)) { --tw-border-style: double; border-style: double; } - :where(.divide-none > :not([hidden]) ~ :not([hidden])) { + :where(.divide-none > :not(:last-child)) { --tw-border-style: none; border-style: none; } - :where(.divide-solid > :not([hidden]) ~ :not([hidden])) { + :where(.divide-solid > :not(:last-child)) { --tw-border-style: solid; border-style: solid; }" @@ -5832,59 +5832,59 @@ test('divide-color', () => { --color-red-500: #ef4444; } - :where(.divide-\\[\\#0088cc\\] > :not([hidden]) ~ :not([hidden])) { + :where(.divide-\\[\\#0088cc\\] > :not(:last-child)) { border-color: #08c; } - :where(.divide-\\[\\#0088cc\\]\\/50 > :not([hidden]) ~ :not([hidden])) { + :where(.divide-\\[\\#0088cc\\]\\/50 > :not(:last-child)) { border-color: #0088cc80; } - :where(.divide-\\[\\#0088cc\\]\\/\\[0\\.5\\] > :not([hidden]) ~ :not([hidden])) { + :where(.divide-\\[\\#0088cc\\]\\/\\[0\\.5\\] > :not(:last-child)) { border-color: #0088cc80; } - :where(.divide-\\[\\#0088cc\\]\\/\\[50\\%\\] > :not([hidden]) ~ :not([hidden])) { + :where(.divide-\\[\\#0088cc\\]\\/\\[50\\%\\] > :not(:last-child)) { border-color: #0088cc80; } - :where(.divide-current > :not([hidden]) ~ :not([hidden])) { + :where(.divide-current > :not(:last-child)) { border-color: currentColor; } - :where(.divide-current\\/50 > :not([hidden]) ~ :not([hidden])) { + :where(.divide-current\\/50 > :not(:last-child)) { border-color: color-mix(in srgb, currentColor 50%, transparent); } - :where(.divide-current\\/\\[0\\.5\\] > :not([hidden]) ~ :not([hidden])) { + :where(.divide-current\\/\\[0\\.5\\] > :not(:last-child)) { border-color: color-mix(in srgb, currentColor 50%, transparent); } - :where(.divide-current\\/\\[50\\%\\] > :not([hidden]) ~ :not([hidden])) { + :where(.divide-current\\/\\[50\\%\\] > :not(:last-child)) { border-color: color-mix(in srgb, currentColor 50%, transparent); } - :where(.divide-inherit > :not([hidden]) ~ :not([hidden])) { + :where(.divide-inherit > :not(:last-child)) { border-color: inherit; } - :where(.divide-red-500 > :not([hidden]) ~ :not([hidden])) { + :where(.divide-red-500 > :not(:last-child)) { border-color: var(--color-red-500, #ef4444); } - :where(.divide-red-500\\/50 > :not([hidden]) ~ :not([hidden])) { + :where(.divide-red-500\\/50 > :not(:last-child)) { border-color: color-mix(in srgb, var(--color-red-500, #ef4444) 50%, transparent); } - :where(.divide-red-500\\/\\[0\\.5\\] > :not([hidden]) ~ :not([hidden])) { + :where(.divide-red-500\\/\\[0\\.5\\] > :not(:last-child)) { border-color: color-mix(in srgb, var(--color-red-500, #ef4444) 50%, transparent); } - :where(.divide-red-500\\/\\[50\\%\\] > :not([hidden]) ~ :not([hidden])) { + :where(.divide-red-500\\/\\[50\\%\\] > :not(:last-child)) { border-color: color-mix(in srgb, var(--color-red-500, #ef4444) 50%, transparent); } - :where(.divide-transparent > :not([hidden]) ~ :not([hidden])) { + :where(.divide-transparent > :not(:last-child)) { border-color: #0000; }" `) diff --git a/packages/tailwindcss/src/utilities.ts b/packages/tailwindcss/src/utilities.ts index 30647eb99942..53c4cc835429 100644 --- a/packages/tailwindcss/src/utilities.ts +++ b/packages/tailwindcss/src/utilities.ts @@ -2014,10 +2014,10 @@ export function createUtilities(theme: Theme) { handle: (value) => [ atRoot([property('--tw-space-x-reverse', '0', '')]), - rule(':where(& > :not([hidden]) ~ :not([hidden]))', [ + rule(':where(& > :not(:last-child))', [ decl('--tw-sort', 'row-gap'), - decl('margin-inline-end', `calc(${value} * var(--tw-space-x-reverse))`), - decl('margin-inline-start', `calc(${value} * calc(1 - var(--tw-space-x-reverse)))`), + decl('margin-inline-start', `calc(${value} * var(--tw-space-x-reverse))`), + decl('margin-inline-end', `calc(${value} * calc(1 - var(--tw-space-x-reverse)))`), ]), ], }) @@ -2028,10 +2028,10 @@ export function createUtilities(theme: Theme) { handle: (value) => [ atRoot([property('--tw-space-y-reverse', '0', '')]), - rule(':where(& > :not([hidden]) ~ :not([hidden]))', [ + rule(':where(& > :not(:last-child))', [ decl('--tw-sort', 'column-gap'), - decl('margin-bottom', `calc(${value} * var(--tw-space-y-reverse))`), - decl('margin-top', `calc(${value} * calc(1 - var(--tw-space-y-reverse)))`), + decl('margin-top', `calc(${value} * var(--tw-space-y-reverse))`), + decl('margin-bottom', `calc(${value} * calc(1 - var(--tw-space-y-reverse)))`), ]), ], }) @@ -2039,7 +2039,7 @@ export function createUtilities(theme: Theme) { staticUtility('space-x-reverse', [ () => atRoot([property('--tw-space-x-reverse', '0', '')]), () => - rule(':where(& > :not([hidden]) ~ :not([hidden]))', [ + rule(':where(& > :not(:last-child))', [ decl('--tw-sort', 'row-gap'), decl('--tw-space-x-reverse', '1'), ]), @@ -2048,7 +2048,7 @@ export function createUtilities(theme: Theme) { staticUtility('space-y-reverse', [ () => atRoot([property('--tw-space-y-reverse', '0', '')]), () => - rule(':where(& > :not([hidden]) ~ :not([hidden]))', [ + rule(':where(& > :not(:last-child))', [ decl('--tw-sort', 'column-gap'), decl('--tw-space-y-reverse', '1'), ]), @@ -2067,7 +2067,7 @@ export function createUtilities(theme: Theme) { colorUtility('divide', { themeKeys: ['--divide-color', '--color'], handle: (value) => [ - rule(':where(& > :not([hidden]) ~ :not([hidden]))', [ + rule(':where(& > :not(:last-child))', [ decl('--tw-sort', 'divide-color'), decl('border-color', value), ]), @@ -2377,15 +2377,12 @@ export function createUtilities(theme: Theme) { handle: (value) => [ atRoot([property('--tw-divide-x-reverse', '0', '')]), - rule(':where(& > :not([hidden]) ~ :not([hidden]))', [ + rule(':where(& > :not(:last-child))', [ decl('--tw-sort', 'divide-x-width'), borderProperties(), decl('border-inline-style', 'var(--tw-border-style)'), - decl('border-inline-end-width', `calc(${value} * var(--tw-divide-x-reverse))`), - decl( - 'border-inline-start-width', - `calc(${value} * calc(1 - var(--tw-divide-x-reverse)))`, - ), + decl('border-inline-start-width', `calc(${value} * var(--tw-divide-x-reverse))`), + decl('border-inline-end-width', `calc(${value} * calc(1 - var(--tw-divide-x-reverse)))`), ]), ], }) @@ -2400,13 +2397,13 @@ export function createUtilities(theme: Theme) { handle: (value) => [ atRoot([property('--tw-divide-y-reverse', '0', '')]), - rule(':where(& > :not([hidden]) ~ :not([hidden]))', [ + rule(':where(& > :not(:last-child))', [ decl('--tw-sort', 'divide-y-width'), borderProperties(), - decl('border-top-style', 'var(--tw-border-style)'), decl('border-bottom-style', 'var(--tw-border-style)'), - decl('border-bottom-width', `calc(${value} * var(--tw-divide-y-reverse))`), - decl('border-top-width', `calc(${value} * calc(1 - var(--tw-divide-y-reverse)))`), + decl('border-top-style', 'var(--tw-border-style)'), + decl('border-top-width', `calc(${value} * var(--tw-divide-y-reverse))`), + decl('border-bottom-width', `calc(${value} * calc(1 - var(--tw-divide-y-reverse)))`), ]), ], }) @@ -2429,20 +2426,18 @@ export function createUtilities(theme: Theme) { staticUtility('divide-x-reverse', [ () => atRoot([property('--tw-divide-x-reverse', '0', '')]), - () => - rule(':where(& > :not([hidden]) ~ :not([hidden]))', [decl('--tw-divide-x-reverse', '1')]), + () => rule(':where(& > :not(:last-child))', [decl('--tw-divide-x-reverse', '1')]), ]) staticUtility('divide-y-reverse', [ () => atRoot([property('--tw-divide-y-reverse', '0', '')]), - () => - rule(':where(& > :not([hidden]) ~ :not([hidden]))', [decl('--tw-divide-y-reverse', '1')]), + () => rule(':where(& > :not(:last-child))', [decl('--tw-divide-y-reverse', '1')]), ]) for (let value of ['solid', 'dashed', 'dotted', 'double', 'none']) { staticUtility(`divide-${value}`, [ () => - rule(':where(& > :not([hidden]) ~ :not([hidden]))', [ + rule(':where(& > :not(:last-child))', [ decl('--tw-sort', 'divide-style'), decl('--tw-border-style', value), decl('border-style', value), diff --git a/packages/tailwindcss/tests/ui.spec.ts b/packages/tailwindcss/tests/ui.spec.ts index 66fb34fa309e..90e64d30edcb 100644 --- a/packages/tailwindcss/tests/ui.spec.ts +++ b/packages/tailwindcss/tests/ui.spec.ts @@ -240,15 +240,15 @@ test('dividers can be added without setting border-style', async ({ page }) => { let { getPropertyValue } = await render( page, html`
-
First
-
Second
+
First
+
Second
`, ) - expect(await getPropertyValue('#b', 'border-top')).toEqual('2px dashed rgb(0, 0, 0)') + expect(await getPropertyValue('#b', 'border-bottom')).toEqual('2px dashed rgb(0, 0, 0)') await page.locator('#a').hover() - expect(await getPropertyValue('#b', 'border-top')).toEqual('4px dashed rgb(0, 0, 0)') + expect(await getPropertyValue('#b', 'border-bottom')).toEqual('4px dashed rgb(0, 0, 0)') }) test('scale can be a number or percentage', async ({ page }) => {