diff --git a/packages/mui-system/src/createStyled.js b/packages/mui-system/src/createStyled.js index ee5c9fb06a6ebc..f4c86e0a7755bf 100644 --- a/packages/mui-system/src/createStyled.js +++ b/packages/mui-system/src/createStyled.js @@ -8,6 +8,17 @@ function isEmpty(obj) { return Object.keys(obj).length === 0; } +// https://github.com/emotion-js/emotion/blob/26ded6109fcd8ca9875cc2ce4564fee678a3f3c5/packages/styled/src/utils.js#L40 +function isStringTag(tag) { + return ( + typeof tag === 'string' && + // 96 is one less than the char code + // for "a" so this is checking that + // it's a lowercase character + tag.charCodeAt(0) > 96 + ); +} + const getStyleOverrides = (name, theme) => { if (theme.components && theme.components[name] && theme.components[name].styleOverrides) { return theme.components[name].styleOverrides; @@ -104,6 +115,9 @@ export default function createStyled(input = {}) { } else if (componentSlot) { // any other slot specified shouldForwardPropOption = slotShouldForwardProp; + } else if (isStringTag(tag)) { + // for string (html) tag, preserve the behavior in emotion & styled-components. + shouldForwardPropOption = undefined; } const defaultStyledResolver = styledEngineStyled(tag, { diff --git a/packages/mui-system/src/createStyled.test.js b/packages/mui-system/src/createStyled.test.js index 39be9742a592f6..a664ad3208556b 100644 --- a/packages/mui-system/src/createStyled.test.js +++ b/packages/mui-system/src/createStyled.test.js @@ -281,4 +281,57 @@ describe('createStyled', () => { }); }); }); + + it('does not spread `sx` prop to DOM', () => { + const styled = createStyled({}); + const Button = styled('button')({}); + + const { container } = render(); + expect(container.firstChild).not.to.have.attribute('sx'); + }); + + it('does not forward `ownerState` prop to DOM', () => { + const styled = createStyled({}); + const Button = styled('button')({}); + + const { container } = render(, + ); + expect(container.firstChild.getAttribute('data-foo')).to.equal('bar'); + expect(container.firstChild.getAttribute('color')).to.equal('red'); // color is for Safari mask-icon link + expect(container.firstChild.getAttribute('shouldBeRemoved')).not.to.equal('true'); + }); + + it('can use `as` prop', () => { + const styled = createStyled({}); + const Button = styled('button')({}); + + const { container } = render(