Skip to content

Commit 5be4cd9

Browse files
authored
[TextField] Migrate InputAdornment to emotion (#25279)
1 parent 89f610f commit 5be4cd9

File tree

10 files changed

+142
-63
lines changed

10 files changed

+142
-63
lines changed

docs/pages/api-docs/input-adornment.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"disablePointerEvents": { "type": { "name": "bool" } },
77
"disableTypography": { "type": { "name": "bool" } },
88
"position": { "type": { "name": "enum", "description": "'end'<br>&#124;&nbsp;'start'" } },
9+
"sx": { "type": { "name": "object" } },
910
"variant": {
1011
"type": {
1112
"name": "enum",
@@ -32,6 +33,6 @@
3233
"filename": "/packages/material-ui/src/InputAdornment/InputAdornment.js",
3334
"inheritance": null,
3435
"demos": "<ul><li><a href=\"/components/text-fields/\">Text Fields</a></li></ul>",
35-
"styledComponent": false,
36+
"styledComponent": true,
3637
"cssComponent": false
3738
}

docs/translations/api-docs/input-adornment/input-adornment.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"disablePointerEvents": "Disable pointer events on the root. This allows for the content of the adornment to focus the <code>input</code> on click.",
88
"disableTypography": "If children is a string then disable wrapping in a Typography component.",
99
"position": "The position this adornment should appear relative to the <code>Input</code>.",
10+
"sx": "The system prop that allows defining system overrides as well as additional CSS styles. See the <a href=\"/system/basics/#the-sx-prop\">`sx` page</a> for more details.",
1011
"variant": "The variant to use. Note: If you are using the <code>TextField</code> component or the <code>FormControl</code> component you do not have to set this manually."
1112
},
1213
"classDescriptions": {

packages/material-ui/src/ButtonGroup/ButtonGroup.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ const ButtonGroup = React.forwardRef(function ButtonGroup(inProps, ref) {
191191
children,
192192
className,
193193
color = 'primary',
194-
component: Component = 'div',
194+
component = 'div',
195195
disabled = false,
196196
disableElevation = false,
197197
disableFocusRipple = false,
@@ -206,7 +206,7 @@ const ButtonGroup = React.forwardRef(function ButtonGroup(inProps, ref) {
206206
const styleProps = {
207207
...props,
208208
color,
209-
component: Component,
209+
component,
210210
disabled,
211211
disableElevation,
212212
disableFocusRipple,
@@ -221,7 +221,7 @@ const ButtonGroup = React.forwardRef(function ButtonGroup(inProps, ref) {
221221

222222
return (
223223
<ButtonGroupRoot
224-
as={Component}
224+
as={component}
225225
role="group"
226226
className={clsx(classes.root, className)}
227227
ref={ref}

packages/material-ui/src/InputAdornment/InputAdornment.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import * as React from 'react';
2+
import { SxProps } from '@material-ui/system';
23
import { OverridableComponent, OverrideProps } from '../OverridableComponent';
4+
import { Theme } from '..';
35

46
export interface InputAdornmentTypeMap<P = {}, D extends React.ElementType = 'div'> {
57
props: P & {
@@ -41,6 +43,10 @@ export interface InputAdornmentTypeMap<P = {}, D extends React.ElementType = 'di
4143
* The position this adornment should appear relative to the `Input`.
4244
*/
4345
position?: 'start' | 'end';
46+
/**
47+
* The system prop that allows defining system overrides as well as additional CSS styles.
48+
*/
49+
sx?: SxProps<Theme>;
4450
/**
4551
* The variant to use.
4652
* Note: If you are using the `TextField` component or the `FormControl` component

packages/material-ui/src/InputAdornment/InputAdornment.js

Lines changed: 86 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,99 @@
11
import * as React from 'react';
22
import PropTypes from 'prop-types';
33
import clsx from 'clsx';
4+
import { deepmerge } from '@material-ui/utils';
5+
import { unstable_composeClasses as composeClasses } from '@material-ui/unstyled';
6+
import capitalize from '../utils/capitalize';
47
import Typography from '../Typography';
5-
import withStyles from '../styles/withStyles';
68
import FormControlContext, { useFormControl } from '../FormControl/FormControlContext';
9+
import experimentalStyled from '../styles/experimentalStyled';
10+
import inputAdornmentClasses, { getInputAdornmentUtilityClass } from './inputAdornmentClasses';
11+
import useThemeProps from '../styles/useThemeProps';
712

8-
export const styles = (theme) => ({
9-
/* Styles applied to the root element. */
10-
root: {
11-
display: 'flex',
12-
height: '0.01em', // Fix IE11 flexbox alignment. To remove at some point.
13-
maxHeight: '2em',
14-
alignItems: 'center',
15-
whiteSpace: 'nowrap',
16-
color: theme.palette.action.active,
13+
const overridesResolver = (props, styles) => {
14+
const { styleProps } = props;
15+
16+
return deepmerge(
17+
{
18+
...styles[`position${capitalize(styleProps.position)}`],
19+
...(styleProps.disablePointerEvents === true && styles.disablePointerEvents),
20+
...(styleProps.variant === 'filled' && styles.filled),
21+
},
22+
styles.root || {},
23+
);
24+
};
25+
26+
const useUtilityClasses = (styleProps) => {
27+
const { classes, disablePointerEvents, position, variant } = styleProps;
28+
const slots = {
29+
root: [
30+
'root',
31+
disablePointerEvents && 'disablePointerEvents',
32+
position && `position${capitalize(position)}`,
33+
variant,
34+
'hiddenLabel',
35+
'sizeSmall',
36+
],
37+
};
38+
39+
return composeClasses(slots, getInputAdornmentUtilityClass, classes);
40+
};
41+
42+
const InputAdornmentRoot = experimentalStyled(
43+
'div',
44+
{},
45+
{
46+
name: 'MuiInputAdornment',
47+
slot: 'Root',
48+
overridesResolver,
1749
},
18-
/* Styles applied to the root element if `variant="filled"`. */
19-
filled: {
20-
'&$positionStart:not($hiddenLabel)': {
50+
)(({ theme, styleProps }) => ({
51+
display: 'flex',
52+
height: '0.01em', // Fix IE11 flexbox alignment. To remove at some point.
53+
maxHeight: '2em',
54+
alignItems: 'center',
55+
whiteSpace: 'nowrap',
56+
color: theme.palette.action.active,
57+
...(styleProps.variant === 'filled' && {
58+
// Styles applied to the root element if `variant="filled"`.
59+
[`&.${inputAdornmentClasses.positionStart}&:not(.Mui-hiddenLabel)`]: {
2160
marginTop: 16,
2261
},
23-
},
24-
/* Styles applied to the root element if `position="start"`. */
25-
positionStart: {
62+
}),
63+
...(styleProps.position === 'start' && {
64+
// Styles applied to the root element if `position="start"`.
2665
marginRight: 8,
27-
},
28-
/* Styles applied to the root element if `position="end"`. */
29-
positionEnd: {
66+
}),
67+
...(styleProps.position === 'end' && {
68+
// Styles applied to the root element if `position="end"`.
3069
marginLeft: 8,
31-
},
32-
/* Styles applied to the root element if `disablePointerEvents={true}`. */
33-
disablePointerEvents: {
70+
}),
71+
...(styleProps.disablePointerEvents === true && {
72+
// Styles applied to the root element if `disablePointerEvents={true}`.
3473
pointerEvents: 'none',
35-
},
36-
/* Styles applied if the adornment is used inside <FormControl hiddenLabel />. */
37-
hiddenLabel: {},
38-
/* Styles applied if the adornment is used inside <FormControl size="small" />. */
39-
sizeSmall: {},
40-
});
74+
}),
75+
}));
4176

42-
const InputAdornment = React.forwardRef(function InputAdornment(props, ref) {
77+
const InputAdornment = React.forwardRef(function InputAdornment(inProps, ref) {
78+
const props = useThemeProps({ props: inProps, name: 'MuiInputAdornment' });
4379
const {
4480
children,
45-
classes,
4681
className,
47-
component: Component = 'div',
82+
component = 'div',
4883
disablePointerEvents = false,
4984
disableTypography = false,
5085
position,
5186
variant: variantProp,
5287
...other
5388
} = props;
89+
90+
const styleProps = {
91+
...props,
92+
disablePointerEvents,
93+
position,
94+
variant: variantProp,
95+
};
96+
5497
const muiFormControl = useFormControl() || {};
5598

5699
let variant = variantProp;
@@ -68,23 +111,16 @@ const InputAdornment = React.forwardRef(function InputAdornment(props, ref) {
68111

69112
if (muiFormControl && !variant) {
70113
variant = muiFormControl.variant;
114+
styleProps.variant = variant;
71115
}
116+
const classes = useUtilityClasses(styleProps);
72117

73118
return (
74119
<FormControlContext.Provider value={null}>
75-
<Component
76-
className={clsx(
77-
classes.root,
78-
{
79-
[classes.filled]: variant === 'filled',
80-
[classes.positionStart]: position === 'start',
81-
[classes.positionEnd]: position === 'end',
82-
[classes.disablePointerEvents]: disablePointerEvents,
83-
[classes.sizeSmall]: muiFormControl.size === 'small',
84-
[classes.hiddenLabel]: muiFormControl.hiddenLabel,
85-
},
86-
className,
87-
)}
120+
<InputAdornmentRoot
121+
as={component}
122+
styleProps={styleProps}
123+
className={clsx(classes.root, className)}
88124
ref={ref}
89125
{...other}
90126
>
@@ -101,7 +137,7 @@ const InputAdornment = React.forwardRef(function InputAdornment(props, ref) {
101137
{children}
102138
</React.Fragment>
103139
)}
104-
</Component>
140+
</InputAdornmentRoot>
105141
</FormControlContext.Provider>
106142
);
107143
});
@@ -143,6 +179,10 @@ InputAdornment.propTypes /* remove-proptypes */ = {
143179
* The position this adornment should appear relative to the `Input`.
144180
*/
145181
position: PropTypes.oneOf(['end', 'start']),
182+
/**
183+
* The system prop that allows defining system overrides as well as additional CSS styles.
184+
*/
185+
sx: PropTypes.object,
146186
/**
147187
* The variant to use.
148188
* Note: If you are using the `TextField` component or the `FormControl` component
@@ -151,4 +191,4 @@ InputAdornment.propTypes /* remove-proptypes */ = {
151191
variant: PropTypes.oneOf(['filled', 'outlined', 'standard']),
152192
};
153193

154-
export default withStyles(styles, { name: 'MuiInputAdornment' })(InputAdornment);
194+
export default InputAdornment;

packages/material-ui/src/InputAdornment/InputAdornment.test.js

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,25 @@
11
import * as React from 'react';
22
import { expect } from 'chai';
3-
import { getClasses, createMount, createClientRender, describeConformance } from 'test/utils';
4-
import { typographyClasses } from '../Typography';
5-
import InputAdornment from './InputAdornment';
6-
import TextField from '../TextField';
7-
import FormControl from '../FormControl';
8-
import Input from '../Input';
3+
import { createMount, createClientRender, describeConformanceV5 } from 'test/utils';
4+
import { typographyClasses } from '@material-ui/core/Typography';
5+
import InputAdornment, { inputAdornmentClasses as classes } from '@material-ui/core/InputAdornment';
6+
import TextField from '@material-ui/core/TextField';
7+
import FormControl from '@material-ui/core/FormControl';
8+
import Input from '@material-ui/core/Input';
99

1010
describe('<InputAdornment />', () => {
1111
const mount = createMount();
1212
const render = createClientRender();
13-
let classes;
1413

15-
before(() => {
16-
classes = getClasses(<InputAdornment position="start">foo</InputAdornment>);
17-
});
18-
19-
describeConformance(<InputAdornment position="start">foo</InputAdornment>, () => ({
14+
describeConformanceV5(<InputAdornment position="start">foo</InputAdornment>, () => ({
2015
classes,
2116
inheritComponent: 'div',
2217
mount,
18+
render,
19+
muiName: 'MuiInputAdornment',
20+
testVariantProps: { color: 'primary' },
2321
refInstanceof: window.HTMLDivElement,
22+
skip: ['componentsProp'],
2423
testComponentPropWith: 'span',
2524
}));
2625

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
export { default } from './InputAdornment';
21
export * from './InputAdornment';
2+
export { default } from './InputAdornment';
3+
4+
export { default as inputAdornmentClasses } from './inputAdornmentClasses';
5+
export * from './inputAdornmentClasses';
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
export { default } from './InputAdornment';
2+
3+
export { default as inputAdornmentClasses } from './inputAdornmentClasses';
4+
export * from './inputAdornmentClasses';
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { InputAdornmentClassKey } from './InputAdornment';
2+
3+
export type InputAdornmentClasses = Record<InputAdornmentClassKey, string>;
4+
5+
declare const inputAdornmentClasses: InputAdornmentClasses;
6+
7+
export function getInputAdornmentUtilityClass(slot: string): string;
8+
9+
export default inputAdornmentClasses;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { generateUtilityClass, generateUtilityClasses } from '@material-ui/unstyled';
2+
3+
export function getInputAdornmentUtilityClass(slot) {
4+
return generateUtilityClass('MuiInputAdornment', slot);
5+
}
6+
7+
const inputAdornmentClasses = generateUtilityClasses('MuiInputAdornment', [
8+
'root',
9+
'filled',
10+
'positionStart',
11+
'positionEnd',
12+
'disablePointerEvents',
13+
'hiddenLabel',
14+
'sizeSmall',
15+
]);
16+
17+
export default inputAdornmentClasses;

0 commit comments

Comments
 (0)