From bfca706be93ee568573e8c5dd63f6b79b59e60ca Mon Sep 17 00:00:00 2001 From: Siriwat K Date: Mon, 6 May 2024 19:36:46 +0700 Subject: [PATCH] Support array for `sx` prop (#52) --- .../pigment-css-react/src/processors/sx.ts | 11 +- packages/pigment-css-react/src/sx.d.ts | 2 +- packages/pigment-css-react/src/sx.js | 26 +++- .../src/utils/cssFunctionTransformerPlugin.ts | 4 +- .../src/utils/spreadSxProp.ts | 37 ++++- .../pigment-css-react/src/utils/sx-plugin.ts | 3 + .../src/utils/sxPropConverter.ts | 24 +++- .../tests/sx/fixtures/sx-array.input.js | 95 +++++++++++++ .../tests/sx/fixtures/sx-array.output.css | 49 +++++++ .../tests/sx/fixtures/sx-array.output.js | 127 ++++++++++++++++++ .../tests/sx/fixtures/sx-jsx.input.js | 17 +++ .../tests/sx/fixtures/sx-jsx.output.css | 22 +++ .../tests/sx/fixtures/sx-jsx.output.js | 20 ++- .../tests/sx/fixtures/sx-shorthand.input.js | 12 ++ .../tests/sx/fixtures/sx-shorthand.output.css | 4 + .../tests/sx/fixtures/sx-shorthand.output.js | 21 +++ .../tests/sx/fixtures/sxProps.input.js | 12 ++ .../tests/sx/fixtures/sxProps.output.css | 22 +++ .../tests/sx/fixtures/sxProps.output.js | 8 ++ .../tests/sx/sx-runtime.test.js | 49 +++++++ .../pigment-css-react/tests/sx/sx.test.ts | 42 ++++++ .../tests/sx/visuallyHidden.js | 13 ++ 22 files changed, 605 insertions(+), 15 deletions(-) create mode 100644 packages/pigment-css-react/tests/sx/fixtures/sx-array.input.js create mode 100644 packages/pigment-css-react/tests/sx/fixtures/sx-array.output.css create mode 100644 packages/pigment-css-react/tests/sx/fixtures/sx-array.output.js create mode 100644 packages/pigment-css-react/tests/sx/fixtures/sx-shorthand.input.js create mode 100644 packages/pigment-css-react/tests/sx/fixtures/sx-shorthand.output.css create mode 100644 packages/pigment-css-react/tests/sx/fixtures/sx-shorthand.output.js create mode 100644 packages/pigment-css-react/tests/sx/sx-runtime.test.js create mode 100644 packages/pigment-css-react/tests/sx/visuallyHidden.js diff --git a/packages/pigment-css-react/src/processors/sx.ts b/packages/pigment-css-react/src/processors/sx.ts index 614d3d53..d5a81273 100644 --- a/packages/pigment-css-react/src/processors/sx.ts +++ b/packages/pigment-css-react/src/processors/sx.ts @@ -145,13 +145,22 @@ export class SxProcessor extends BaseProcessor { /** * Replace the sx prop with runtime sx */ + let pathToReplace: undefined | NodePath; this.replacer((_tagPath) => { const tagPath = _tagPath as NodePath; - spreadSxProp(tagPath); + const isArrayArgument = spreadSxProp(tagPath); + if (isArrayArgument) { + pathToReplace = tagPath; + } return tagPath.node; }, false); + + if (pathToReplace) { + // need to replace outside of `this.replacer` to preserve the import statement + pathToReplace.replaceWith(pathToReplace.node.arguments[0]); + } } get asSelector(): string { diff --git a/packages/pigment-css-react/src/sx.d.ts b/packages/pigment-css-react/src/sx.d.ts index 317ecf71..8f49a4ae 100644 --- a/packages/pigment-css-react/src/sx.d.ts +++ b/packages/pigment-css-react/src/sx.d.ts @@ -3,4 +3,4 @@ import type { ThemeArgs } from './theme'; export type SxProp = CSSObjectNoCallback | ((themeArgs: ThemeArgs) => CSSObjectNoCallback); -export default function sx(arg: SxProp, componentClass?: string): string; +export default function sx(arg: SxProp | Array, componentClass?: string): string; diff --git a/packages/pigment-css-react/src/sx.js b/packages/pigment-css-react/src/sx.js index ee0bcfe0..318f67da 100644 --- a/packages/pigment-css-react/src/sx.js +++ b/packages/pigment-css-react/src/sx.js @@ -1,7 +1,25 @@ export default function sx(transformedSx, { className, style }) { - const sxClass = typeof transformedSx === 'string' ? transformedSx : transformedSx?.className; - const sxVars = - transformedSx && typeof transformedSx !== 'string' ? transformedSx.vars : undefined; + let sxClass = ''; + let sxVars = {}; + + function iterateSx(element) { + if (element) { + sxClass += `${typeof element === 'string' ? element : element.className} `; + sxVars = { + ...sxVars, + ...(element && typeof element !== 'string' ? element.vars : undefined), + }; + } + } + + if (Array.isArray(transformedSx)) { + transformedSx.forEach((element) => { + iterateSx(element); + }); + } else { + iterateSx(transformedSx); + } + const varStyles = {}; if (sxVars) { @@ -15,7 +33,7 @@ export default function sx(transformedSx, { className, style }) { } return { - className: `${sxClass}${className ? ` ${className}` : ''}`, + className: `${sxClass.trim()}${className ? ` ${className}` : ''}`, style: { ...varStyles, ...style, diff --git a/packages/pigment-css-react/src/utils/cssFunctionTransformerPlugin.ts b/packages/pigment-css-react/src/utils/cssFunctionTransformerPlugin.ts index 1a4985c5..59602e77 100644 --- a/packages/pigment-css-react/src/utils/cssFunctionTransformerPlugin.ts +++ b/packages/pigment-css-react/src/utils/cssFunctionTransformerPlugin.ts @@ -54,7 +54,9 @@ const cssFunctionTransformerPlugin = declare((api, pluginOpt } const themeKeyArr = val.split('.').join('-'); path.replaceWith( - t.stringLiteral(`var(--${finalPrefix}${propertyThemeKey}-${themeKeyArr})`), + t.stringLiteral( + `var(--${finalPrefix ? `${finalPrefix}-` : ''}${propertyThemeKey}-${themeKeyArr})`, + ), ); }, }, diff --git a/packages/pigment-css-react/src/utils/spreadSxProp.ts b/packages/pigment-css-react/src/utils/spreadSxProp.ts index 57caff21..4f5f6218 100644 --- a/packages/pigment-css-react/src/utils/spreadSxProp.ts +++ b/packages/pigment-css-react/src/utils/spreadSxProp.ts @@ -1,5 +1,6 @@ import { NodePath, types as astService } from '@babel/core'; import { + ArrayExpression, CallExpression, Expression, JSXAttribute, @@ -100,7 +101,7 @@ export default function spreadSxProp(tagPath: NodePath) { | NodePath | null; if (!target) { - return; + return false; } let paths: | NodePath[] @@ -112,19 +113,45 @@ export default function spreadSxProp(tagPath: NodePath) { paths = target.get('properties'); } const { props, sxPath } = getProps(paths); + let spreadSxNode: undefined | SpreadElement | JSXSpreadAttribute; if (sxPath) { const expression = sxPath.get('value'); if ('node' in expression) { if (target.isObjectExpression()) { - target.node.properties.push(astService.spreadElement(expression.node as Expression)); + spreadSxNode = astService.spreadElement(expression.node as Expression); + target.node.properties.push(spreadSxNode); } if (target.isJSXOpeningElement() && expression.isJSXExpressionContainer()) { - target.node.attributes.push( - astService.jsxSpreadAttribute(expression.node.expression as Expression), - ); + spreadSxNode = astService.jsxSpreadAttribute(expression.node.expression as Expression); + target.node.attributes.push(spreadSxNode); } } sxPath.remove(); } tagPath.node.arguments.push(astService.objectExpression(props)); + + if (spreadSxNode?.argument.type === 'ArrayExpression') { + spreadSxNode.argument = astService.callExpression(tagPath.node.callee, [ + spreadSxNode.argument, + astService.objectExpression(props), + ]); + } + + // This step is required to pass information about the array argument to the outer function + // to replace the `tagPath` with its first argument. + // + // Check if the sx value is an array expression + let arrayPath: NodePath | null = null; + if (tagPath.parentPath.isArrayExpression()) { + // sx call is a direct child, e.g. [_sx(...), _sx(...)] + arrayPath = tagPath.parentPath; + } else if (tagPath.parentPath.parentPath?.isArrayExpression()) { + // sx call inside a conditional/logical expression, e.g. [true ? _sx(...) : _sx(...), prop && _sx(...)] + arrayPath = tagPath.parentPath.parentPath; + } + if (arrayPath) { + return true; + } + + return false; } diff --git a/packages/pigment-css-react/src/utils/sx-plugin.ts b/packages/pigment-css-react/src/utils/sx-plugin.ts index 145b12e5..50807c36 100644 --- a/packages/pigment-css-react/src/utils/sx-plugin.ts +++ b/packages/pigment-css-react/src/utils/sx-plugin.ts @@ -92,6 +92,9 @@ export const babelPlugin = declare<{ } const valuePath = path.get('value'); if ( + !valuePath.isIdentifier() && + !valuePath.isMemberExpression() && + !valuePath.isArrayExpression() && !valuePath.isObjectExpression() && !valuePath.isArrowFunctionExpression() && !valuePath.isConditionalExpression() && diff --git a/packages/pigment-css-react/src/utils/sxPropConverter.ts b/packages/pigment-css-react/src/utils/sxPropConverter.ts index 83818423..a308ef9c 100644 --- a/packages/pigment-css-react/src/utils/sxPropConverter.ts +++ b/packages/pigment-css-react/src/utils/sxPropConverter.ts @@ -5,14 +5,22 @@ import { sxObjectExtractor } from './sxObjectExtractor'; function isAllowedExpression( node: NodePath, ): node is NodePath | NodePath { - return node.isObjectExpression() || node.isArrowFunctionExpression(); + return ( + node.isObjectExpression() || node.isArrowFunctionExpression() || node.isFunctionExpression() + ); } export function sxPropConverter( node: NodePath, wrapWithSxCall: (expPath: NodePath) => void, ) { - if (node.isConditionalExpression()) { + if (node.isArrayExpression()) { + node.get('elements').forEach((element) => { + if (element.isExpression()) { + sxPropConverter(element, wrapWithSxCall); + } + }); + } else if (node.isConditionalExpression()) { const consequent = node.get('consequent'); const alternate = node.get('alternate'); @@ -41,5 +49,17 @@ export function sxPropConverter( if (binding?.scope === rootScope) { wrapWithSxCall(node); } + } else if (node.isMemberExpression()) { + let current: NodePath = node; + while (current.isMemberExpression()) { + current = current.get('object'); + } + if (current.isIdentifier()) { + const rootScope = current.scope.getProgramParent(); + const binding = current.scope.getBinding(current.node.name); + if (binding?.scope === rootScope) { + wrapWithSxCall(node); + } + } } } diff --git a/packages/pigment-css-react/tests/sx/fixtures/sx-array.input.js b/packages/pigment-css-react/tests/sx/fixtures/sx-array.input.js new file mode 100644 index 00000000..c5c83762 --- /dev/null +++ b/packages/pigment-css-react/tests/sx/fixtures/sx-array.input.js @@ -0,0 +1,95 @@ +import { jsx as _jsx } from 'react/jsx-runtime'; + +
; + +
; + +function App(props) { + return ( + ({ + border: `1px solid ${theme.palette.primary.main}`, + }), + ]} + /> + ); +} + +function App2(props) { + return ( + + ); +} + +_jsx('div', { + sx: [ + { + opacity: 1, + }, + ], +}); + +_jsx('div', { + className: 'foo', + style: { + opacity: 1, + }, + sx: [ + { + color: 'red', + }, + { + color: 'green', + }, + ], +}); + +function App3(props) { + return _jsx('div', { + sx: [ + (theme) => ({ + border: `1px solid ${theme.palette.primary.main}`, + }), + props.disabled + ? { + opacity: 0.4, + } + : { + color: 'red', + }, + ], + children: 'test', + ...props, + }); +} + +function App4(props) { + return _jsx('div', { + sx: [ + (theme) => ({ + border: `1px solid ${theme.palette.primary.main}`, + }), + props.variant === 'secondary' && { color: props.isRed ? 'red' : 'blue' }, + ], + className: `foo ${props.className}`, + style: { + color: 'red', + ...props.style, + }, + }); +} diff --git a/packages/pigment-css-react/tests/sx/fixtures/sx-array.output.css b/packages/pigment-css-react/tests/sx/fixtures/sx-array.output.css new file mode 100644 index 00000000..0c6400b6 --- /dev/null +++ b/packages/pigment-css-react/tests/sx/fixtures/sx-array.output.css @@ -0,0 +1,49 @@ +.dnf03uj { + opacity: 1; +} +.dsvwfmp { + color: red; +} +.d121rcfp { + color: green; +} +.schfkcb { + color: var(--schfkcb-0); +} +.s1cp79ho { + background-color: blue; + color: white; +} +.soyt4ij { + border: 1px solid red; +} +.sr48wd1 { + color: green; +} +.s6s70bv { + color: var(--s6s70bv-0); +} +.s1v8upwb { + opacity: 1; +} +.sjtfjpx { + color: red; +} +.s1r80n7h { + color: green; +} +.s1gu7ed8 { + border: 1px solid red; +} +.s1h4vmh2 { + opacity: 0.4; +} +.s1oy2sl1 { + color: red; +} +.s14d8kn5 { + border: 1px solid red; +} +.s1su4mia { + color: var(--s1su4mia-0); +} diff --git a/packages/pigment-css-react/tests/sx/fixtures/sx-array.output.js b/packages/pigment-css-react/tests/sx/fixtures/sx-array.output.js new file mode 100644 index 00000000..9b20565e --- /dev/null +++ b/packages/pigment-css-react/tests/sx/fixtures/sx-array.output.js @@ -0,0 +1,127 @@ +import { + sx as _sx, + sx as _sx2, + sx as _sx3, + sx as _sx4, + sx as _sx5, + sx as _sx6, + sx as _sx7, + sx as _sx8, +} from '@pigment-css/react'; +import { jsx as _jsx } from 'react/jsx-runtime'; +
; +
; +function App(props) { + return ( + + ); +} +function App2(props) { + return ( + + ); +} +_jsx('div', { + ..._sx5(['s1v8upwb'], {}), +}); +_jsx('div', { + className: 'foo', + style: { + opacity: 1, + }, + ..._sx6(['sjtfjpx', 's1r80n7h'], { + className: 'foo', + style: { + opacity: 1, + }, + }), +}); +function App3(props) { + return _jsx('div', { + children: 'test', + ...props, + ..._sx7(['s1gu7ed8', props.disabled ? 's1h4vmh2' : 's1oy2sl1'], { + ...props, + }), + }); +} +function App4(props) { + return _jsx('div', { + className: `foo ${props.className}`, + style: { + color: 'red', + ...props.style, + }, + ..._sx8( + [ + 's14d8kn5', + props.variant === 'secondary' && { + className: 's1su4mia', + vars: { + 's1su4mia-0': [props.isRed ? 'red' : 'blue', false], + }, + }, + ], + { + className: `foo ${props.className}`, + style: { + color: 'red', + ...props.style, + }, + }, + ), + }); +} diff --git a/packages/pigment-css-react/tests/sx/fixtures/sx-jsx.input.js b/packages/pigment-css-react/tests/sx/fixtures/sx-jsx.input.js index dea2842e..d0ae37d2 100644 --- a/packages/pigment-css-react/tests/sx/fixtures/sx-jsx.input.js +++ b/packages/pigment-css-react/tests/sx/fixtures/sx-jsx.input.js @@ -1,3 +1,5 @@ +import visuallyHidden from '../visuallyHidden'; + function App() { return /*#__PURE__*/ _jsx( 'div', @@ -63,3 +65,18 @@ function App4(props) { children: 'test', }); } + +function App5(props) { + return /*#__PURE__*/ _jsx('div', { + sx: visuallyHidden, + }); +} + +const styles = { + visuallyHidden, +}; +function App6(props) { + return /*#__PURE__*/ _jsx('div', { + sx: styles.visuallyHidden, + }); +} diff --git a/packages/pigment-css-react/tests/sx/fixtures/sx-jsx.output.css b/packages/pigment-css-react/tests/sx/fixtures/sx-jsx.output.css index 35b51edb..55668b6c 100644 --- a/packages/pigment-css-react/tests/sx/fixtures/sx-jsx.output.css +++ b/packages/pigment-css-react/tests/sx/fixtures/sx-jsx.output.css @@ -23,3 +23,25 @@ .swssabr { color: var(--swssabr-0); } +.sblg7d5 { + border: 0px solid; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + white-space: nowrap; + width: 1px; +} +.s1xq3929 { + border: 0px solid; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + white-space: nowrap; + width: 1px; +} diff --git a/packages/pigment-css-react/tests/sx/fixtures/sx-jsx.output.js b/packages/pigment-css-react/tests/sx/fixtures/sx-jsx.output.js index 3277161a..dfd53daa 100644 --- a/packages/pigment-css-react/tests/sx/fixtures/sx-jsx.output.js +++ b/packages/pigment-css-react/tests/sx/fixtures/sx-jsx.output.js @@ -1,4 +1,12 @@ -import { sx as _sx, sx as _sx2, sx as _sx3, sx as _sx4, sx as _sx5 } from '@pigment-css/react'; +import { + sx as _sx, + sx as _sx2, + sx as _sx3, + sx as _sx4, + sx as _sx5, + sx as _sx6, + sx as _sx7, +} from '@pigment-css/react'; function App() { return /*#__PURE__*/ _jsx( 'div', @@ -72,3 +80,13 @@ function App4(props) { )), }); } +function App5(props) { + return /*#__PURE__*/ _jsx('div', { + ..._sx6('sblg7d5', {}), + }); +} +function App6(props) { + return /*#__PURE__*/ _jsx('div', { + ..._sx7('s1xq3929', {}), + }); +} diff --git a/packages/pigment-css-react/tests/sx/fixtures/sx-shorthand.input.js b/packages/pigment-css-react/tests/sx/fixtures/sx-shorthand.input.js new file mode 100644 index 00000000..a0def372 --- /dev/null +++ b/packages/pigment-css-react/tests/sx/fixtures/sx-shorthand.input.js @@ -0,0 +1,12 @@ +function App(props) { + return ( +
+
+
+ ); +} diff --git a/packages/pigment-css-react/tests/sx/fixtures/sx-shorthand.output.css b/packages/pigment-css-react/tests/sx/fixtures/sx-shorthand.output.css new file mode 100644 index 00000000..b9186b8b --- /dev/null +++ b/packages/pigment-css-react/tests/sx/fixtures/sx-shorthand.output.css @@ -0,0 +1,4 @@ +.d1h14by3 { + color: var(--d1h14by3-0); + margin-bottom: 8px; +} diff --git a/packages/pigment-css-react/tests/sx/fixtures/sx-shorthand.output.js b/packages/pigment-css-react/tests/sx/fixtures/sx-shorthand.output.js new file mode 100644 index 00000000..ae37c3e3 --- /dev/null +++ b/packages/pigment-css-react/tests/sx/fixtures/sx-shorthand.output.js @@ -0,0 +1,21 @@ +import { sx as _sx } from '@pigment-css/react'; +function App(props) { + return ( +
+
+
+ ); +} diff --git a/packages/pigment-css-react/tests/sx/fixtures/sxProps.input.js b/packages/pigment-css-react/tests/sx/fixtures/sxProps.input.js index 3bc08e0e..f8a380eb 100644 --- a/packages/pigment-css-react/tests/sx/fixtures/sxProps.input.js +++ b/packages/pigment-css-react/tests/sx/fixtures/sxProps.input.js @@ -1,4 +1,5 @@ import { styled } from '@pigment-css/react'; +import visuallyHidden from '../visuallyHidden'; export const SliderRail = styled('span', { name: 'MuiSlider', @@ -51,3 +52,14 @@ const styles4 = { function App4(props) { return ; } + +function App5(props) { + return ; +} + +const styles = { + visuallyHidden, +}; +function App6(props) { + return ; +} diff --git a/packages/pigment-css-react/tests/sx/fixtures/sxProps.output.css b/packages/pigment-css-react/tests/sx/fixtures/sxProps.output.css index 6bb6b310..c468bbd7 100644 --- a/packages/pigment-css-react/tests/sx/fixtures/sxProps.output.css +++ b/packages/pigment-css-react/tests/sx/fixtures/sxProps.output.css @@ -26,3 +26,25 @@ margin-bottom: 8px; text-align: center; } +.s1v3ec1v { + border: 0px solid; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + white-space: nowrap; + width: 1px; +} +.s1ojh0i1 { + border: 0px solid; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + white-space: nowrap; + width: 1px; +} diff --git a/packages/pigment-css-react/tests/sx/fixtures/sxProps.output.js b/packages/pigment-css-react/tests/sx/fixtures/sxProps.output.js index 3cf5b0e3..a63dd55b 100644 --- a/packages/pigment-css-react/tests/sx/fixtures/sxProps.output.js +++ b/packages/pigment-css-react/tests/sx/fixtures/sxProps.output.js @@ -3,6 +3,8 @@ import { sx as _sx2, sx as _sx3, sx as _sx4, + sx as _sx5, + sx as _sx6, styled as _styled, } from '@pigment-css/react'; export const SliderRail = /*#__PURE__*/ _styled('span', { @@ -79,3 +81,9 @@ function App3(props) { function App4(props) { return ; } +function App5(props) { + return ; +} +function App6(props) { + return ; +} diff --git a/packages/pigment-css-react/tests/sx/sx-runtime.test.js b/packages/pigment-css-react/tests/sx/sx-runtime.test.js new file mode 100644 index 00000000..12af3871 --- /dev/null +++ b/packages/pigment-css-react/tests/sx/sx-runtime.test.js @@ -0,0 +1,49 @@ +import { expect } from 'chai'; +import sx from '../../src/sx'; + +describe('Pigment CSS - sx runtime', () => { + it('merge className and style', () => { + expect(sx('foo', { className: 'bar', style: { color: 'red' } })).to.deep.equal({ + className: 'foo bar', + style: { color: 'red' }, + }); + }); + + it('merge vars', () => { + expect( + sx( + { className: 'foo', vars: { foo: ['foo'] } }, + { className: 'bar', style: { color: 'red' } }, + ), + ).to.deep.equal({ + className: 'foo bar', + style: { '--foo': 'foo', color: 'red' }, + }); + }); + + it('support array', () => { + const disabled = false; + const color = 'secondary'; + expect( + sx( + [ + 'foo', + disabled + ? { className: 'bar', vars: { bar: ['bar', false] } } + : { className: 'baz', vars: { baz: ['baz', false] } }, + color === 'primary' && 'red', + ], + { + className: 'root', + style: { color: 'blue' }, + }, + ), + ).to.deep.equal({ + className: 'foo baz root', + style: { + color: 'blue', + '--baz': 'baz', + }, + }); + }); +}); diff --git a/packages/pigment-css-react/tests/sx/sx.test.ts b/packages/pigment-css-react/tests/sx/sx.test.ts index a61bf45a..b35c23bb 100644 --- a/packages/pigment-css-react/tests/sx/sx.test.ts +++ b/packages/pigment-css-react/tests/sx/sx.test.ts @@ -73,4 +73,46 @@ describe('Pigment CSS - sx prop', () => { expect(output.js).to.equal(fixture.js); expect(output.css).to.equal(fixture.css); }); + + it('sx prop support array', async () => { + const { output, fixture } = await runTransformation( + path.join(__dirname, 'fixtures/sx-array.input.js'), + { + themeArgs: { + theme, + }, + }, + ); + + expect(output.js).to.equal(fixture.js); + expect(output.css).to.equal(fixture.css); + }); + + it('sx prop shorthand', async () => { + const { output, fixture } = await runTransformation( + path.join(__dirname, 'fixtures/sx-shorthand.input.js'), + { + themeArgs: { + theme: { + cssVarPrefix: 'mui', + palette: { + grey: { + 50: '#FBFCFE', + }, + }, + vars: { + palette: { + grey: { + 50: 'var(--mui-palette-grey-50)', + }, + }, + }, + }, + }, + }, + ); + + expect(output.js).to.equal(fixture.js); + expect(output.css).to.equal(fixture.css); + }); }); diff --git a/packages/pigment-css-react/tests/sx/visuallyHidden.js b/packages/pigment-css-react/tests/sx/visuallyHidden.js new file mode 100644 index 00000000..9e9ccfc0 --- /dev/null +++ b/packages/pigment-css-react/tests/sx/visuallyHidden.js @@ -0,0 +1,13 @@ +const visuallyHidden = { + border: 0, + clip: 'rect(0 0 0 0)', + height: '1px', + margin: '-1px', + overflow: 'hidden', + padding: 0, + position: 'absolute', + whiteSpace: 'nowrap', + width: '1px', +}; + +export default visuallyHidden;