From 7991646eff732248a25ba779650dab26249ee5b7 Mon Sep 17 00:00:00 2001 From: Adam Wathan Date: Tue, 11 May 2021 15:25:25 -0400 Subject: [PATCH] Add `screen` function (#4318) --- src/lib/evaluateTailwindFunctions.js | 10 ++ ...t.js => evaluateTailwindFunctions.test.js} | 126 ++++++++++++++++++ 2 files changed, 136 insertions(+) rename tests/{themeFunction.test.js => evaluateTailwindFunctions.test.js} (78%) diff --git a/src/lib/evaluateTailwindFunctions.js b/src/lib/evaluateTailwindFunctions.js index dc991b38bf33..9b7dcbdb48e8 100644 --- a/src/lib/evaluateTailwindFunctions.js +++ b/src/lib/evaluateTailwindFunctions.js @@ -2,6 +2,7 @@ import _ from 'lodash' import didYouMean from 'didyoumean' import transformThemeValue from '../util/transformThemeValue' import parseValue from 'postcss-value-parser' +import buildMediaQuery from '../util/buildMediaQuery' function findClosestExistingPath(theme, path) { const parts = _.toPath(path) @@ -163,6 +164,15 @@ export default function (config) { return value }, + screen: (node, screen) => { + screen = _.trim(screen, `'"`) + + if (config.theme.screens[screen] === undefined) { + throw node.error(`The '${screen}' screen does not exist in your theme.`) + } + + return buildMediaQuery(config.theme.screens[screen]) + }, } return (root) => { root.walk((node) => { diff --git a/tests/themeFunction.test.js b/tests/evaluateTailwindFunctions.test.js similarity index 78% rename from tests/themeFunction.test.js rename to tests/evaluateTailwindFunctions.test.js index ae4eea4619be..3d2f174aa2f8 100644 --- a/tests/themeFunction.test.js +++ b/tests/evaluateTailwindFunctions.test.js @@ -401,3 +401,129 @@ test('transition-duration values are joined when an array', () => { expect(result.warnings().length).toBe(0) }) }) + +test('basic screen function calls are expanded', () => { + const input = ` + @media screen(sm) { + .foo {} + } + ` + + const output = ` + @media (min-width: 600px) { + .foo {} + } + ` + + return run(input, { + theme: { screens: { sm: '600px' } }, + }).then((result) => { + expect(result.css).toMatchCss(output) + expect(result.warnings().length).toBe(0) + }) +}) + +test('screen function supports max-width screens', () => { + const input = ` + @media screen(sm) { + .foo {} + } + ` + + const output = ` + @media (max-width: 600px) { + .foo {} + } + ` + + return run(input, { + theme: { screens: { sm: { max: '600px' } } }, + }).then((result) => { + expect(result.css).toMatchCss(output) + expect(result.warnings().length).toBe(0) + }) +}) + +test('screen function supports min-width screens', () => { + const input = ` + @media screen(sm) { + .foo {} + } + ` + + const output = ` + @media (min-width: 600px) { + .foo {} + } + ` + + return run(input, { + theme: { screens: { sm: { min: '600px' } } }, + }).then((result) => { + expect(result.css).toMatchCss(output) + expect(result.warnings().length).toBe(0) + }) +}) + +test('screen function supports min-width and max-width screens', () => { + const input = ` + @media screen(sm) { + .foo {} + } + ` + + const output = ` + @media (min-width: 600px) and (max-width: 700px) { + .foo {} + } + ` + + return run(input, { + theme: { screens: { sm: { min: '600px', max: '700px' } } }, + }).then((result) => { + expect(result.css).toMatchCss(output) + expect(result.warnings().length).toBe(0) + }) +}) + +test('screen function supports raw screens', () => { + const input = ` + @media screen(mono) { + .foo {} + } + ` + + const output = ` + @media monochrome { + .foo {} + } + ` + + return run(input, { + theme: { screens: { mono: { raw: 'monochrome' } } }, + }).then((result) => { + expect(result.css).toMatchCss(output) + expect(result.warnings().length).toBe(0) + }) +}) + +test('screen arguments can be quoted', () => { + const input = ` + @media screen('sm') { + .foo {} + } + ` + + const output = ` + @media (min-width: 600px) { + .foo {} + } + ` + + return run(input, { + theme: { screens: { sm: '600px' } }, + }).then((result) => { + expect(result.css).toMatchCss(output) + expect(result.warnings().length).toBe(0) + }) +})