diff --git a/__tests__/responsiveAtRule.test.js b/__tests__/responsiveAtRule.test.js index db54f04e8..ae9f18c9b 100644 --- a/__tests__/responsiveAtRule.test.js +++ b/__tests__/responsiveAtRule.test.js @@ -172,6 +172,136 @@ test('responsive variants are grouped', () => { }) }) +test('it can generate responsive variants for nested at-rules', () => { + const input = ` + @responsive { + .banana { color: yellow; } + + @supports(display: grid) { + .grid\\:banana { color: blue; } + } + } + ` + + const output = ` + .banana { + color: yellow; + } + + @supports(display: grid) { + .grid\\:banana { + color: blue; + } + } + + @media (min-width: 500px) { + .sm\\:banana { + color: yellow; + } + + @supports(display: grid) { + .sm\\:grid\\:banana { + color: blue; + } + } + } + + @media (min-width: 1000px) { + .lg\\:banana { + color: yellow; + } + + @supports(display: grid) { + .lg\\:grid\\:banana { + color: blue; + } + } + } + ` + + return run(input, { + theme: { + screens: { + sm: '500px', + lg: '1000px', + }, + }, + separator: ':', + }).then(result => { + expect(result.css).toMatchCss(output) + expect(result.warnings().length).toBe(0) + }) +}) + +test('it can generate responsive variants for deeply nested at-rules', () => { + const input = ` + @responsive { + .banana { color: yellow; } + + @supports(display: grid) { + @supports(display: flex) { + .flex-grid\\:banana { color: blue; } + } + } + } + ` + + const output = ` + .banana { + color: yellow; + } + + @supports(display: grid) { + @supports(display: flex) { + .flex-grid\\:banana { + color: blue; + } + } + } + + @media (min-width: 500px) { + .sm\\:banana { + color: yellow; + } + + @supports(display: grid) { + @supports(display: flex) { + .sm\\:flex-grid\\:banana { + color: blue; + } + } + } + } + + @media (min-width: 1000px) { + .lg\\:banana { + color: yellow; + } + + @supports(display: grid) { + @supports(display: flex) { + .lg\\:flex-grid\\:banana { + color: blue; + } + } + } + } + ` + + return run(input, { + theme: { + screens: { + sm: '500px', + lg: '1000px', + }, + }, + separator: ':', + }).then(result => { + expect(result.css).toMatchCss(output) + expect(result.warnings().length).toBe(0) + }) +}) + test('screen prefix is only applied to the last class in a selector', () => { const input = ` @responsive { diff --git a/defaultTheme.js b/defaultTheme.js index a6ae40461..d940c29ae 100644 --- a/defaultTheme.js +++ b/defaultTheme.js @@ -155,6 +155,17 @@ module.exports = function() { }, textColors: theme => theme.colors, backgroundColors: theme => theme.colors, + backgroundPosition: { + bottom: 'bottom', + center: 'center', + left: 'left', + 'left-bottom': 'left bottom', + 'left-top': 'left top', + right: 'right', + 'right-bottom': 'right bottom', + 'right-top': 'right top', + top: 'top', + }, backgroundSize: { auto: 'auto', cover: 'cover', diff --git a/src/lib/substituteResponsiveAtRules.js b/src/lib/substituteResponsiveAtRules.js index 6d6b8163a..04e9b687f 100644 --- a/src/lib/substituteResponsiveAtRules.js +++ b/src/lib/substituteResponsiveAtRules.js @@ -10,12 +10,12 @@ export default function(config) { theme: { screens }, separator, } = config - const responsiveRules = [] + const responsiveRules = postcss.root() const finalRules = [] css.walkAtRules('responsive', atRule => { const nodes = atRule.nodes - responsiveRules.push(...cloneNodes(nodes)) + responsiveRules.append(...cloneNodes(nodes)) atRule.before(nodes) atRule.remove() }) @@ -27,14 +27,14 @@ export default function(config) { }) mediaQuery.append( - responsiveRules.map(rule => { - const cloned = rule.clone() - cloned.selectors = _.map(rule.selectors, selector => - buildSelectorVariant(selector, screen, separator, message => { - throw rule.error(message) - }) - ) - return cloned + _.tap(responsiveRules.clone(), clonedRoot => { + clonedRoot.walkRules(rule => { + rule.selectors = _.map(rule.selectors, selector => + buildSelectorVariant(selector, screen, separator, message => { + throw rule.error(message) + }) + ) + }) }) ) diff --git a/src/plugins/backgroundPosition.js b/src/plugins/backgroundPosition.js index c8f6e6508..92df71400 100644 --- a/src/plugins/backgroundPosition.js +++ b/src/plugins/backgroundPosition.js @@ -1,18 +1,18 @@ -export default function({ variants }) { - return function({ addUtilities }) { - addUtilities( - { - '.bg-bottom': { 'background-position': 'bottom' }, - '.bg-center': { 'background-position': 'center' }, - '.bg-left': { 'background-position': 'left' }, - '.bg-left-bottom': { 'background-position': 'left bottom' }, - '.bg-left-top': { 'background-position': 'left top' }, - '.bg-right': { 'background-position': 'right' }, - '.bg-right-bottom': { 'background-position': 'right bottom' }, - '.bg-right-top': { 'background-position': 'right top' }, - '.bg-top': { 'background-position': 'top' }, - }, - variants +import _ from 'lodash' + +export default function({ values, variants }) { + return function({ addUtilities, e }) { + const utilities = _.fromPairs( + _.map(values, (value, modifier) => { + return [ + `.${e(`bg-${modifier}`)}`, + { + 'background-position': value, + }, + ] + }) ) + + addUtilities(utilities, variants) } }