From 4e35b6947f3249ec56c3407746fd4a4060812e3d Mon Sep 17 00:00:00 2001 From: duganbrett <44508924+duganbrett@users.noreply.github.com> Date: Tue, 26 Jan 2021 16:38:51 -0700 Subject: [PATCH 01/11] [TextField] Migrate Input component to emotion --- docs/pages/api-docs/input.json | 3 +- docs/translations/api-docs/input/input.json | 1 + .../src/Autocomplete/Autocomplete.js | 12 +- packages/material-ui/src/Input/Input.d.ts | 7 +- packages/material-ui/src/Input/Input.js | 121 ++++++++++-------- packages/material-ui/src/Input/Input.test.js | 16 +-- packages/material-ui/src/Input/index.d.ts | 2 + packages/material-ui/src/Input/index.js | 2 + .../material-ui/src/Input/inputClasses.d.ts | 11 ++ .../material-ui/src/Input/inputClasses.js | 9 ++ .../src/TextField/TextField.test.js | 10 +- 11 files changed, 117 insertions(+), 77 deletions(-) create mode 100644 packages/material-ui/src/Input/inputClasses.d.ts create mode 100644 packages/material-ui/src/Input/inputClasses.js diff --git a/docs/pages/api-docs/input.json b/docs/pages/api-docs/input.json index 384770ff5d4672..2bb728714f2725 100644 --- a/docs/pages/api-docs/input.json +++ b/docs/pages/api-docs/input.json @@ -25,6 +25,7 @@ "required": { "type": { "name": "bool" } }, "rows": { "type": { "name": "union", "description": "number
| string" } }, "startAdornment": { "type": { "name": "node" } }, + "sx": { "type": { "name": "object" } }, "type": { "type": { "name": "string" }, "default": "'text'" }, "value": { "type": { "name": "any" } } }, @@ -54,6 +55,6 @@ "filename": "/packages/material-ui/src/Input/Input.js", "inheritance": { "component": "InputBase", "pathname": "/api/input-base/" }, "demos": "", - "styledComponent": false, + "styledComponent": true, "cssComponent": false } diff --git a/docs/translations/api-docs/input/input.json b/docs/translations/api-docs/input/input.json index 17040b0c5c0f5b..98ccc1d5cdd383 100644 --- a/docs/translations/api-docs/input/input.json +++ b/docs/translations/api-docs/input/input.json @@ -26,6 +26,7 @@ "required": "If true, the input element is required. The prop defaults to the value (false) inherited from the parent FormControl component.", "rows": "Number of rows to display when multiline option is set to true.", "startAdornment": "Start InputAdornment for this component.", + "sx": "The system prop that allows defining system overrides as well as additional CSS styles. See the `sx` page for more details.", "type": "Type of the input element. It should be a valid HTML5 input type.", "value": "The value of the input element, required for a controlled component." }, diff --git a/packages/material-ui/src/Autocomplete/Autocomplete.js b/packages/material-ui/src/Autocomplete/Autocomplete.js index 918afdaacd9620..6a8632b35e4b9e 100644 --- a/packages/material-ui/src/Autocomplete/Autocomplete.js +++ b/packages/material-ui/src/Autocomplete/Autocomplete.js @@ -61,20 +61,20 @@ export const styles = (theme) => ({ width: 0, minWidth: 30, }, - '&[class*="MuiInput-root"]': { + '.MuiInput-root': { paddingBottom: 1, - '& $input': { + '& .MuiInput-input': { padding: 4, }, - '& $input:first-child': { + '& .MuiInput-input:first-child': { padding: '6px 0', }, }, - '&[class*="MuiInput-root"][class*="MuiInput-sizeSmall"]': { - '& $input': { + '&.MuiInput-root.MuiInput-sizeSmall': { + '& .MuiInput-input': { padding: '2px 4px 3px', }, - '& $input:first-child': { + '& .MuiInput-input:first-child': { padding: '1px 0 4px', }, }, diff --git a/packages/material-ui/src/Input/Input.d.ts b/packages/material-ui/src/Input/Input.d.ts index 131b8715ce1779..125e5ff8bfffab 100644 --- a/packages/material-ui/src/Input/Input.d.ts +++ b/packages/material-ui/src/Input/Input.d.ts @@ -1,4 +1,5 @@ -import { InternalStandardProps as StandardProps } from '..'; +import { SxProps } from '@material-ui/system'; +import { InternalStandardProps as StandardProps, Theme } from '..'; import { InputBaseProps } from '../InputBase'; export interface InputProps extends StandardProps { @@ -39,6 +40,10 @@ export interface InputProps extends StandardProps { * If `true`, the `input` will not have an underline. */ disableUnderline?: boolean; + /** + * The system prop that allows defining system overrides as well as additional CSS styles. + */ + sx?: SxProps; } export type InputClassKey = keyof NonNullable; diff --git a/packages/material-ui/src/Input/Input.js b/packages/material-ui/src/Input/Input.js index 756b3e570ffa0b..85c62ae479088f 100644 --- a/packages/material-ui/src/Input/Input.js +++ b/packages/material-ui/src/Input/Input.js @@ -1,37 +1,49 @@ import * as React from 'react'; import PropTypes from 'prop-types'; -import clsx from 'clsx'; -import { refType } from '@material-ui/utils'; +import { unstable_composeClasses as composeClasses } from '@material-ui/unstyled'; +import { deepmerge, refType } from '@material-ui/utils'; import InputBase from '../InputBase'; -import withStyles from '../styles/withStyles'; +import experimentalStyled, { shouldForwardProp } from '../styles/experimentalStyled'; +import useThemeProps from '../styles/useThemeProps'; +import { getInputUtilityClass } from './inputClasses'; +import { + overridesResolver as inputBaseOverridesResolver, + InputBaseRoot, +} from '../InputBase/InputBase'; -export const styles = (theme) => { +const overridesResolver = (props, styles) => { + const { styleProps } = props; + return deepmerge(inputBaseOverridesResolver(props, styles), { + ...(!styleProps.disableUnderline && styles.underline), + }); +}; + +const useUtilityClasses = (styleProps) => { + const { classes, disableUnderline } = styleProps; + + const slots = { + root: ['root', !disableUnderline && 'underline'], + input: ['input'], + }; + + return composeClasses(slots, getInputUtilityClass, classes); +}; + +const InputRoot = experimentalStyled( + InputBaseRoot, + { shouldForwardProp: (prop) => shouldForwardProp(prop) || prop === 'classes' }, + { name: 'MuiInput', slot: 'Root', overridesResolver }, +)(({ theme, styleProps }) => { const light = theme.palette.mode === 'light'; const bottomLineColor = light ? 'rgba(0, 0, 0, 0.42)' : 'rgba(255, 255, 255, 0.7)'; - return { - /* Styles applied to the root element. */ - root: { - position: 'relative', - }, - /* Styles applied to the root element if the component is a descendant of `FormControl`. */ - formControl: { + position: 'relative', + ...(styleProps.formControl && { 'label + &': { marginTop: 16, }, - }, - /* Styles applied to the root element if the component is focused. */ - focused: {}, - /* Styles applied to the root element if `disabled={true}`. */ - disabled: {}, - /* Styles applied to the root element if color secondary. */ - colorSecondary: { - '&$underline:after': { - borderBottomColor: theme.palette.secondary.main, - }, - }, - /* Styles applied to the root element unless `disableUnderline={true}`. */ - underline: { + }), + ...(!styleProps.disableUnderline && { '&:after': { borderBottom: `2px solid ${theme.palette.primary.main}`, left: 0, @@ -46,11 +58,14 @@ export const styles = (theme) => { easing: theme.transitions.easing.easeOut, }), pointerEvents: 'none', // Transparent to the hover style. + ...(styleProps.color === 'secondary' && { + borderBottomColor: theme.palette.secondary.main, + }), }, - '&$focused:after': { + '&.Mui-focused:after': { transform: 'scaleX(1)', }, - '&$error:after': { + '&.Mui-error:after': { borderBottomColor: theme.palette.error.main, transform: 'scaleX(1)', // error is always underlined in red }, @@ -67,40 +82,24 @@ export const styles = (theme) => { }), pointerEvents: 'none', // Transparent to the hover style. }, - '&:hover:not($disabled):before': { + '&:hover:not(.Mui-disabled):before': { borderBottom: `2px solid ${theme.palette.text.primary}`, // Reset on touch devices, it doesn't add specificity '@media (hover: none)': { borderBottom: `1px solid ${bottomLineColor}`, }, }, - '&$disabled:before': { + '&.Mui-disabled:before': { borderBottomStyle: 'dotted', }, - }, - /* Pseudo-class applied to the root element if `error={true}`. */ - error: {}, - /* Styles applied to the input element if `size="small"`. */ - sizeSmall: {}, - /* Styles applied to the root element if `multiline={true}`. */ - multiline: {}, - /* Styles applied to the root element if `fullWidth={true}`. */ - fullWidth: {}, - /* Styles applied to the input element. */ - input: {}, - /* Styles applied to the input element if `size="small"`. */ - inputSizeSmall: {}, - /* Styles applied to the input element if `multiline={true}`. */ - inputMultiline: {}, - /* Styles applied to the input element if `type="search"`. */ - inputTypeSearch: {}, + }), }; -}; +}); -const Input = React.forwardRef(function Input(props, ref) { +const Input = React.forwardRef(function Input(inProps, ref) { + const props = useThemeProps({ props: inProps, name: 'MuiInput' }); const { disableUnderline, - classes, fullWidth = false, inputComponent = 'input', multiline = false, @@ -108,21 +107,27 @@ const Input = React.forwardRef(function Input(props, ref) { ...other } = props; + const styleProps = { + ...props, + fullWidth, + inputComponent, + multiline, + type, + }; + + const classes = useUtilityClasses(props); + return ( ); }); @@ -249,6 +254,10 @@ Input.propTypes = { * Start `InputAdornment` for this component. */ startAdornment: PropTypes.node, + /** + * The system prop that allows defining system overrides as well as additional CSS styles. + */ + sx: PropTypes.object, /** * Type of the `input` element. It should be [a valid HTML5 input type](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Form_%3Cinput%3E_types). * @default 'text' @@ -262,4 +271,4 @@ Input.propTypes = { Input.muiName = 'Input'; -export default withStyles(styles, { name: 'MuiInput' })(Input); +export default Input; diff --git a/packages/material-ui/src/Input/Input.test.js b/packages/material-ui/src/Input/Input.test.js index 09fecb9c63608f..996f0ffd75f8a7 100644 --- a/packages/material-ui/src/Input/Input.test.js +++ b/packages/material-ui/src/Input/Input.test.js @@ -1,21 +1,21 @@ import * as React from 'react'; -import { getClasses, createMount, describeConformance } from 'test/utils'; +import { createMount, describeConformanceV5 } from 'test/utils'; import Input from './Input'; import InputBase from '../InputBase'; +import classes from './inputClasses'; describe('', () => { - let classes; const mount = createMount(); - before(() => { - classes = getClasses(); - }); - - describeConformance(, () => ({ + describeConformanceV5(, () => ({ classes, inheritComponent: InputBase, mount, refInstanceof: window.HTMLDivElement, - skip: ['componentProp'], + muiName: 'MuiInput', + testDeepOverrides: { slotName: 'input', slotClassName: classes.input }, + testVariantProps: { variant: 'contained', fullWidth: true }, + testStateOverrides: { prop: 'size', value: 'small', styleKey: 'sizeSmall' }, + skip: ['componentProp', 'componentsProp'], })); }); diff --git a/packages/material-ui/src/Input/index.d.ts b/packages/material-ui/src/Input/index.d.ts index 8ce98e8789f2c7..bcb7f9544db7f0 100644 --- a/packages/material-ui/src/Input/index.d.ts +++ b/packages/material-ui/src/Input/index.d.ts @@ -1,2 +1,4 @@ export { default } from './Input'; export * from './Input'; +export { default as inputClasses } from './inputClasses'; +export * from './inputClasses'; diff --git a/packages/material-ui/src/Input/index.js b/packages/material-ui/src/Input/index.js index a2e60496d02c31..b32ad177dd8e11 100644 --- a/packages/material-ui/src/Input/index.js +++ b/packages/material-ui/src/Input/index.js @@ -1 +1,3 @@ export { default } from './Input'; +export { default as inputClasses } from './inputClasses'; +export * from './inputClasses'; diff --git a/packages/material-ui/src/Input/inputClasses.d.ts b/packages/material-ui/src/Input/inputClasses.d.ts new file mode 100644 index 00000000000000..61979e72aa0d33 --- /dev/null +++ b/packages/material-ui/src/Input/inputClasses.d.ts @@ -0,0 +1,11 @@ +export interface FilledInputClasses { + root: string; + underline: string; + input: string; +} + +declare const filledInputClasses: FilledInputClasses; + +export function getFilledInputUtilityClass(slot: string): string; + +export default filledInputClasses; diff --git a/packages/material-ui/src/Input/inputClasses.js b/packages/material-ui/src/Input/inputClasses.js new file mode 100644 index 00000000000000..5120b2561ca098 --- /dev/null +++ b/packages/material-ui/src/Input/inputClasses.js @@ -0,0 +1,9 @@ +import { generateUtilityClasses, generateUtilityClass } from '@material-ui/unstyled'; + +export function getInputUtilityClass(slot) { + return generateUtilityClass('MuiInput', slot); +} + +const inputClasses = generateUtilityClasses('MuiInput', ['root', 'underline', 'input']); + +export default inputClasses; diff --git a/packages/material-ui/src/TextField/TextField.test.js b/packages/material-ui/src/TextField/TextField.test.js index 59d3a739be66a4..0a189e3b9e354f 100644 --- a/packages/material-ui/src/TextField/TextField.test.js +++ b/packages/material-ui/src/TextField/TextField.test.js @@ -2,10 +2,10 @@ import * as React from 'react'; import { expect } from 'chai'; import { getClasses, createMount, createClientRender, describeConformance } from 'test/utils'; import FormControl from '../FormControl'; -import Input from '../Input'; import OutlinedInput from '../OutlinedInput'; import TextField from './TextField'; import MenuItem from '../MenuItem'; +import { inputBaseClasses } from '../InputBase'; describe('', () => { let classes; @@ -32,14 +32,14 @@ describe('', () => { }); it('should forward the multiline prop to Input', () => { - const inputClasses = getClasses(); const { getByRole } = render(); - expect(getByRole('textbox', { hidden: false })).to.have.class(inputClasses.inputMultiline); + expect(getByRole('textbox', { hidden: false })).to.have.class( + inputBaseClasses.inputMultiline, + ); }); it('should forward the fullWidth prop to Input', () => { - const inputClasses = getClasses(); const { getByTestId } = render( ', () => { />, ); - expect(getByTestId('mui-input-base-root')).to.have.class(inputClasses.fullWidth); + expect(getByTestId('mui-input-base-root')).to.have.class(inputBaseClasses.fullWidth); }); }); From 5184b06a183bb1939f83085789ac1286f9d2ff19 Mon Sep 17 00:00:00 2001 From: duganbrett <44508924+duganbrett@users.noreply.github.com> Date: Tue, 26 Jan 2021 16:53:56 -0700 Subject: [PATCH 02/11] Fixed type names --- packages/material-ui/src/Input/Input.js | 2 +- packages/material-ui/src/Input/inputClasses.d.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/material-ui/src/Input/Input.js b/packages/material-ui/src/Input/Input.js index 85c62ae479088f..dabf795b87ee87 100644 --- a/packages/material-ui/src/Input/Input.js +++ b/packages/material-ui/src/Input/Input.js @@ -120,7 +120,7 @@ const Input = React.forwardRef(function Input(inProps, ref) { return ( Date: Tue, 26 Jan 2021 16:59:29 -0700 Subject: [PATCH 03/11] Fix failing NativeSelect unit test --- packages/material-ui/src/NativeSelect/NativeSelect.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/material-ui/src/NativeSelect/NativeSelect.test.js b/packages/material-ui/src/NativeSelect/NativeSelect.test.js index 9e4cf835408b41..4fe2f802fc5960 100644 --- a/packages/material-ui/src/NativeSelect/NativeSelect.test.js +++ b/packages/material-ui/src/NativeSelect/NativeSelect.test.js @@ -2,11 +2,12 @@ import * as React from 'react'; import { expect } from 'chai'; import { getClasses, createMount, createClientRender, describeConformance } from 'test/utils'; import Input from '../Input'; +import { inputClasses } from '../Input' import NativeSelect from './NativeSelect'; describe('', () => { let classes; - let inputClasses; + const mount = createMount(); const render = createClientRender(); const defaultProps = { @@ -23,7 +24,6 @@ describe('', () => { before(() => { classes = getClasses(); - inputClasses = getClasses(); }); describeConformance(, () => ({ From 3f341f3106e2ecf6598e821c7d16b078bee88473 Mon Sep 17 00:00:00 2001 From: duganbrett <44508924+duganbrett@users.noreply.github.com> Date: Tue, 26 Jan 2021 17:02:06 -0700 Subject: [PATCH 04/11] Fixed imports --- packages/material-ui/src/NativeSelect/NativeSelect.test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/material-ui/src/NativeSelect/NativeSelect.test.js b/packages/material-ui/src/NativeSelect/NativeSelect.test.js index 4fe2f802fc5960..a393af5c7744a5 100644 --- a/packages/material-ui/src/NativeSelect/NativeSelect.test.js +++ b/packages/material-ui/src/NativeSelect/NativeSelect.test.js @@ -1,8 +1,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { getClasses, createMount, createClientRender, describeConformance } from 'test/utils'; -import Input from '../Input'; -import { inputClasses } from '../Input' +import Input, { inputClasses } from '../Input'; import NativeSelect from './NativeSelect'; describe('', () => { From 53b32b5d40fd0e6a7c5f17251bb0eb757ef1b566 Mon Sep 17 00:00:00 2001 From: duganbrett <44508924+duganbrett@users.noreply.github.com> Date: Tue, 26 Jan 2021 17:35:36 -0700 Subject: [PATCH 05/11] Fix argos --- packages/material-ui/src/Autocomplete/Autocomplete.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/material-ui/src/Autocomplete/Autocomplete.js b/packages/material-ui/src/Autocomplete/Autocomplete.js index 6a8632b35e4b9e..fc8a1470584731 100644 --- a/packages/material-ui/src/Autocomplete/Autocomplete.js +++ b/packages/material-ui/src/Autocomplete/Autocomplete.js @@ -102,7 +102,7 @@ export const styles = (theme) => ({ padding: '2.5px 4px', }, }, - '&.MuiFilledInput-root': { + '&[class*="MuiFilledInput-root"]': { paddingTop: 19, paddingLeft: 8, '$hasPopupIcon &, $hasClearIcon &': { @@ -111,16 +111,16 @@ export const styles = (theme) => ({ '$hasPopupIcon$hasClearIcon &': { paddingRight: 52 + 4 + 9, }, - '& .MuiFilledInput-input': { + '& $input': { padding: '7px 4px', }, '& $endAdornment': { right: 9, }, }, - '&.MuiFilledInput-root.MuiInputBase-sizeSmall': { + '&[class*="MuiFilledInput-root"][class*="MuiFilledInput-sizeSmall"]': { paddingBottom: 1, - '& .MuiFilledInput-input': { + '& $input': { padding: '2.5px 4px', }, }, From b62f203f356198763cf2373cfe836b531683f725 Mon Sep 17 00:00:00 2001 From: duganbrett <44508924+duganbrett@users.noreply.github.com> Date: Tue, 26 Jan 2021 17:57:20 -0700 Subject: [PATCH 06/11] Fix broken css --- packages/material-ui/src/Autocomplete/Autocomplete.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/material-ui/src/Autocomplete/Autocomplete.js b/packages/material-ui/src/Autocomplete/Autocomplete.js index fc8a1470584731..8118cf462baefc 100644 --- a/packages/material-ui/src/Autocomplete/Autocomplete.js +++ b/packages/material-ui/src/Autocomplete/Autocomplete.js @@ -61,7 +61,7 @@ export const styles = (theme) => ({ width: 0, minWidth: 30, }, - '.MuiInput-root': { + '&.MuiInput-root': { paddingBottom: 1, '& .MuiInput-input': { padding: 4, From 6976b02a65adbb8deefecbcb5723c8036b1df8d1 Mon Sep 17 00:00:00 2001 From: duganbrett <44508924+duganbrett@users.noreply.github.com> Date: Tue, 26 Jan 2021 18:28:09 -0700 Subject: [PATCH 07/11] rerun ci From 4a690b93491f62fd7cbf6403df8e7ab65ceb0763 Mon Sep 17 00:00:00 2001 From: duganbrett <44508924+duganbrett@users.noreply.github.com> Date: Tue, 26 Jan 2021 18:50:26 -0700 Subject: [PATCH 08/11] rerun ci From 91c94f750eb2c1f4c4a05fafd7b5dc444c75f09d Mon Sep 17 00:00:00 2001 From: duganbrett <44508924+duganbrett@users.noreply.github.com> Date: Tue, 26 Jan 2021 19:08:58 -0700 Subject: [PATCH 09/11] Fix argos --- packages/material-ui/src/Autocomplete/Autocomplete.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/material-ui/src/Autocomplete/Autocomplete.js b/packages/material-ui/src/Autocomplete/Autocomplete.js index 8118cf462baefc..96b49bc28f44ea 100644 --- a/packages/material-ui/src/Autocomplete/Autocomplete.js +++ b/packages/material-ui/src/Autocomplete/Autocomplete.js @@ -70,7 +70,7 @@ export const styles = (theme) => ({ padding: '6px 0', }, }, - '&.MuiInput-root.MuiInput-sizeSmall': { + '&.MuiInput-root.MuiInputBase-sizeSmall': { '& .MuiInput-input': { padding: '2px 4px 3px', }, From 373e29af02a254ea540eae2401c12eb2b86ed6c6 Mon Sep 17 00:00:00 2001 From: duganbrett <44508924+duganbrett@users.noreply.github.com> Date: Wed, 27 Jan 2021 09:22:30 -0700 Subject: [PATCH 10/11] rerun ci From e9c7a83251a5fdaa9bc793e03381bc80d2e7280d Mon Sep 17 00:00:00 2001 From: duganbrett <44508924+duganbrett@users.noreply.github.com> Date: Wed, 27 Jan 2021 09:34:27 -0700 Subject: [PATCH 11/11] Removed changes to FilledInput auto complete styles --- packages/material-ui/src/Autocomplete/Autocomplete.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/material-ui/src/Autocomplete/Autocomplete.js b/packages/material-ui/src/Autocomplete/Autocomplete.js index 96b49bc28f44ea..531551f4030f5c 100644 --- a/packages/material-ui/src/Autocomplete/Autocomplete.js +++ b/packages/material-ui/src/Autocomplete/Autocomplete.js @@ -102,7 +102,7 @@ export const styles = (theme) => ({ padding: '2.5px 4px', }, }, - '&[class*="MuiFilledInput-root"]': { + '&.MuiFilledInput-root': { paddingTop: 19, paddingLeft: 8, '$hasPopupIcon &, $hasClearIcon &': { @@ -111,16 +111,16 @@ export const styles = (theme) => ({ '$hasPopupIcon$hasClearIcon &': { paddingRight: 52 + 4 + 9, }, - '& $input': { + '& .MuiFilledInput-input': { padding: '7px 4px', }, '& $endAdornment': { right: 9, }, }, - '&[class*="MuiFilledInput-root"][class*="MuiFilledInput-sizeSmall"]': { + '&.MuiFilledInput-root.MuiInputBase-sizeSmall': { paddingBottom: 1, - '& $input': { + '& .MuiFilledInput-input': { padding: '2.5px 4px', }, },