From b7ea2cbd9d9f7e7e4fdd8d6f31b42ff9baf5fef5 Mon Sep 17 00:00:00 2001 From: Brandon McConnell Date: Thu, 11 May 2023 13:59:43 -0700 Subject: [PATCH] Add support for dimension prefix when using dynamic `min-*` and `max-*` --- src/util/buildMediaQuery.js | 27 ++++++- tests/min-max-screen-variants.test.js | 102 ++++++++++++++++++++++++++ 2 files changed, 127 insertions(+), 2 deletions(-) diff --git a/src/util/buildMediaQuery.js b/src/util/buildMediaQuery.js index 8489dd4bc9f4..8b07ae95a59d 100644 --- a/src/util/buildMediaQuery.js +++ b/src/util/buildMediaQuery.js @@ -1,3 +1,23 @@ +/** + * @param {string} value + * @returns {[string, string]} + */ +export function splitVariantPrefix(value) { + if (typeof value !== 'string') return ['', value] + let parts = value.split(':') + return ['', ...parts].slice(-2) +} + +/** + * @param {string} value + * @returns {[string, string]} + */ +function splitDimensionPrefix(value) { + const [prefix, extractedValue] = splitVariantPrefix(value) + const dimension = prefix === 'h' ? 'height' : 'width' + return [dimension, extractedValue] +} + export default function buildMediaQuery(screens) { screens = Array.isArray(screens) ? screens : [screens] @@ -8,9 +28,12 @@ export default function buildMediaQuery(screens) { return screen.raw } + let [minDimension, minValue] = splitDimensionPrefix(screen.min) + let [maxDimension, maxValue] = splitDimensionPrefix(screen.max) + return [ - screen.min && `(min-width: ${screen.min})`, - screen.max && `(max-width: ${screen.max})`, + minValue && `(min-${minDimension}: ${minValue})`, + maxValue && `(max-${maxDimension}: ${maxValue})`, ] .filter(Boolean) .join(' and ') diff --git a/tests/min-max-screen-variants.test.js b/tests/min-max-screen-variants.test.js index a86c6f6cd201..dbd8ec621f7a 100644 --- a/tests/min-max-screen-variants.test.js +++ b/tests/min-max-screen-variants.test.js @@ -261,6 +261,108 @@ crosscheck(() => { }) }) + it('supports min-* and max-* variants with or without arbitrary dimension prefixes', () => { + let config = { + content: [ + { + raw: html` +
+ `, + }, + ], + corePlugins: { preflight: false }, + theme: { + screens: defaultScreens, + }, + } + + let input = css` + @tailwind utilities; + ` + + return run(input, config).then((result) => { + expect(result.css).toMatchFormattedCss(css` + .font-bold { + font-weight: 700; + } + @media (max-width: 100px) { + .max-\[100px\]\:font-bold { + font-weight: 700; + } + } + @media (max-height: 100px) { + .max-\[h\:100px\]\:font-bold { + font-weight: 700; + } + } + @media (max-width: 100px) { + .max-\[w\:100px\]\:font-bold { + font-weight: 700; + } + } + @media (min-width: 100px) { + .min-\[100px\]\:font-bold { + font-weight: 700; + } + } + @media (min-height: 100px) { + .min-\[h\:100px\]\:font-bold { + font-weight: 700; + } + } + @media (min-width: 100px) { + .min-\[w\:100px\]\:font-bold { + font-weight: 700; + } + } + `) + }) + }) + + it('supports min-* and max-* variants being used together with or without arbitrary dimension prefixes', () => { + let config = { + content: [ + { + raw: html` +
+ `, + }, + ], + corePlugins: { preflight: false }, + theme: { + screens: defaultScreens, + }, + } + + let input = css` + @tailwind utilities; + ` + + return run(input, config).then((result) => { + expect(result.css).toMatchFormattedCss(css` + @media (min-width: 100px) { + @media (min-width: 100px) { + @media (min-height: 100px) { + @media (max-width: 100px) { + @media (max-width: 100px) { + @media (max-height: 100px) { + .min-\[100px\]\:min-\[w\:100px\]\:min-\[h\:100px\]\:max-\[100px\]\:max-\[w\:100px\]\:max-\[h\:100px\]\:font-bold { + font-weight: 700; + } + } + } + } + } + } + } + `) + }) + }) + it('warns when using min variants with complex screen configs', async () => { let config = { content: [