Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TextField] Migrate FilledInput to emotion #24634

Merged
merged 8 commits into from
Jan 27, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/pages/api-docs/filled-input.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"required": { "type": { "name": "bool" } },
"rows": { "type": { "name": "union", "description": "number<br>&#124;&nbsp;string" } },
"startAdornment": { "type": { "name": "node" } },
"sx": { "type": { "name": "object" } },
"type": { "type": { "name": "string" }, "default": "'text'" },
"value": { "type": { "name": "any" } }
},
Expand Down Expand Up @@ -57,6 +58,6 @@
"filename": "/packages/material-ui/src/FilledInput/FilledInput.js",
"inheritance": { "component": "InputBase", "pathname": "/api/input-base/" },
"demos": "<ul><li><a href=\"/components/text-fields/\">Text Fields</a></li></ul>",
"styledComponent": false,
"styledComponent": true,
"cssComponent": false
}
5 changes: 5 additions & 0 deletions docs/pages/api-docs/input-base.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
"autoFocus": { "type": { "name": "bool" } },
"classes": { "type": { "name": "object" } },
"color": { "type": { "name": "enum", "description": "'primary'<br>&#124;&nbsp;'secondary'" } },
"components": {
"type": { "name": "shape", "description": "{ Input?: elementType, Root?: elementType }" },
"default": "{}"
},
"componentsProps": { "type": { "name": "object" }, "default": "{}" },
"defaultValue": { "type": { "name": "any" } },
"disabled": { "type": { "name": "bool" } },
"endAdornment": { "type": { "name": "node" } },
Expand Down
1 change: 1 addition & 0 deletions docs/translations/api-docs/filled-input/filled-input.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"required": "If <code>true</code>, the <code>input</code> element is required. The prop defaults to the value (<code>false</code>) inherited from the parent FormControl component.",
"rows": "Number of rows to display when multiline option is set to true.",
"startAdornment": "Start <code>InputAdornment</code> for this component.",
"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.",
"type": "Type of the <code>input</code> element. It should be <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Form_%3Cinput%3E_types\">a valid HTML5 input type</a>.",
"value": "The value of the <code>input</code> element, required for a controlled component."
},
Expand Down
2 changes: 2 additions & 0 deletions docs/translations/api-docs/input-base/input-base.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"autoFocus": "If <code>true</code>, the <code>input</code> element is focused during the first mount.",
"classes": "Override or extend the styles applied to the component. See <a href=\"#css\">CSS API</a> below for more details.",
"color": "The color of the component. It supports those theme colors that make sense for this component. The prop defaults to the value (<code>&#39;primary&#39;</code>) inherited from the parent FormControl component.",
"components": "The components used for each slot inside the InputBase. Either a string to use a HTML element or a component.",
"componentsProps": "The props used for each slot inside the Input.",
"defaultValue": "The default value. Use when the component is not controlled.",
"disabled": "If <code>true</code>, the component is disabled. The prop defaults to the value (<code>false</code>) inherited from the parent FormControl component.",
"endAdornment": "End <code>InputAdornment</code> for this component.",
Expand Down
7 changes: 6 additions & 1 deletion packages/material-ui/src/FilledInput/FilledInput.d.ts
Original file line number Diff line number Diff line change
@@ -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 FilledInputProps extends StandardProps<InputBaseProps> {
Expand Down Expand Up @@ -45,6 +46,10 @@ export interface FilledInputProps extends StandardProps<InputBaseProps> {
* 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<Theme>;
}

export type FilledInputClassKey = keyof NonNullable<FilledInputProps['classes']>;
Expand Down
245 changes: 136 additions & 109 deletions packages/material-ui/src/FilledInput/FilledInput.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,67 @@
import * as React from 'react';
import { deepmerge, refType } from '@material-ui/utils';
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 InputBase from '../InputBase';
import withStyles from '../styles/withStyles';
import experimentalStyled, { shouldForwardProp } from '../styles/experimentalStyled';
import useThemeProps from '../styles/useThemeProps';
import { getFilledInputUtilityClass } from './filledInputClasses';
import {
overridesResolver as inputBaseOverridesResolver,
InputBaseRoot,
InputBaseComponent as InputBaseInput,
} from '../InputBase/InputBase';

export const styles = (theme) => {
const overridesResolver = (props, styles) => {
const { styleProps } = props;
return deepmerge(inputBaseOverridesResolver(props, styles), {
...(!styleProps.disableUnderline && styles.undeline),
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
});
};

const useUtilityClasses = (styleProps) => {
const { classes, disableUnderline } = styleProps;

const slots = {
root: ['root', !disableUnderline && 'underline'],
input: ['input'],
};

return composeClasses(slots, getFilledInputUtilityClass, classes);
};

const FilledInputRoot = experimentalStyled(
InputBaseRoot,
{ shouldForwardProp: (prop) => shouldForwardProp(prop) || prop === 'classes' },
{ name: 'MuiFilledInput', 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)';
const backgroundColor = light ? 'rgba(0, 0, 0, 0.09)' : 'rgba(255, 255, 255, 0.09)';

return {
/* Styles applied to the root element. */
root: {
position: 'relative',
backgroundColor,
borderTopLeftRadius: theme.shape.borderRadius,
borderTopRightRadius: theme.shape.borderRadius,
transition: theme.transitions.create('background-color', {
duration: theme.transitions.duration.shorter,
easing: theme.transitions.easing.easeOut,
}),
'&:hover': {
backgroundColor: light ? 'rgba(0, 0, 0, 0.13)' : 'rgba(255, 255, 255, 0.13)',
// Reset on touch devices, it doesn't add specificity
'@media (hover: none)': {
backgroundColor,
},
},
'&$focused': {
backgroundColor: light ? 'rgba(0, 0, 0, 0.09)' : 'rgba(255, 255, 255, 0.09)',
},
'&$disabled': {
backgroundColor: light ? 'rgba(0, 0, 0, 0.12)' : 'rgba(255, 255, 255, 0.12)',
position: 'relative',
backgroundColor,
borderTopLeftRadius: theme.shape.borderRadius,
borderTopRightRadius: theme.shape.borderRadius,
transition: theme.transitions.create('background-color', {
duration: theme.transitions.duration.shorter,
easing: theme.transitions.easing.easeOut,
}),
'&:hover': {
backgroundColor: light ? 'rgba(0, 0, 0, 0.13)' : 'rgba(255, 255, 255, 0.13)',
// Reset on touch devices, it doesn't add specificity
'@media (hover: none)': {
backgroundColor,
},
},
/* Styles applied to the root element if color secondary. */
colorSecondary: {
'&$underline:after': {
borderBottomColor: theme.palette.secondary.main,
},
'&.Mui-focused': {
backgroundColor: light ? 'rgba(0, 0, 0, 0.09)' : 'rgba(255, 255, 255, 0.09)',
},
'&.Mui-disabled': {
backgroundColor: light ? 'rgba(0, 0, 0, 0.12)' : 'rgba(255, 255, 255, 0.12)',
},
/* Styles applied to the root element unless `disableUnderline={true}`. */
underline: {
...(!styleProps.disableUnderline && {
'&:after': {
borderBottom: `2px solid ${theme.palette.primary.main}`,
left: 0,
Expand All @@ -57,11 +76,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
},
Expand All @@ -78,109 +100,110 @@ export const styles = (theme) => {
}),
pointerEvents: 'none', // Transparent to the hover style.
},
'&:hover:not($disabled):before': {
'&:hover:not(.Mui-disabled):before': {
borderBottom: `1px solid ${theme.palette.text.primary}`,
},
'&$disabled:before': {
'&.Mui-disabled:before': {
borderBottomStyle: 'dotted',
},
},
/* Pseudo-class applied to the root element if the component is focused. */
focused: {},
/* Pseudo-class applied to the root element if `disabled={true}`. */
disabled: {},
/* Styles applied to the root element if `startAdornment` is provided. */
adornedStart: {
}),
...(styleProps.startAdornment && {
paddingLeft: 12,
},
/* Styles applied to the root element if `endAdornment` is provided. */
adornedEnd: {
}),
...(styleProps.endAdornment && {
paddingRight: 12,
},
/* 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: {
}),
...(styleProps.multiline && {
padding: '25px 12px 8px',
'&$sizeSmall': {
...(styleProps.size === 'small' && {
paddingTop: 21,
paddingBottom: 4,
},
'&$hiddenLabel': {
}),
...(styleProps.hiddenLabel && {
paddingTop: 16,
paddingBottom: 17,
},
},
/* Styles applied to the root element if `hiddenLabel={true}`. */
hiddenLabel: {},
/* Styles applied to the input element. */
input: {
padding: '25px 12px 8px',
'&:-webkit-autofill': {
WebkitBoxShadow: theme.palette.mode === 'light' ? null : '0 0 0 100px #266798 inset',
WebkitTextFillColor: theme.palette.mode === 'light' ? null : '#fff',
caretColor: theme.palette.mode === 'light' ? null : '#fff',
borderTopLeftRadius: 'inherit',
borderTopRightRadius: 'inherit',
},
},
/* Styles applied to the input element if `size="small"`. */
inputSizeSmall: {
paddingTop: 21,
paddingBottom: 4,
},
/* Styles applied to the `input` if in `<FormControl hiddenLabel />`. */
inputHiddenLabel: {
paddingTop: 16,
paddingBottom: 17,
'&$inputSizeSmall': {
paddingTop: 8,
paddingBottom: 9,
},
},
/* Styles applied to the input element if `multiline={true}`. */
inputMultiline: {
padding: 0,
},
/* Styles applied to the input element if `startAdornment` is provided. */
inputAdornedStart: {
paddingLeft: 0,
},
/* Styles applied to the input element if `endAdornment` is provided. */
inputAdornedEnd: {
paddingRight: 0,
},
}),
}),
};
};
});

const FilledInputInput = experimentalStyled(
InputBaseInput,
{ shouldForwardProp: (prop) => shouldForwardProp(prop) || prop === 'classes' },
{ name: 'MuiFilledInput', slot: 'Input' },
)(({ theme, styleProps }) => ({
padding: '25px 12px 8px',
'&:-webkit-autofill': {
WebkitBoxShadow: theme.palette.mode === 'light' ? null : '0 0 0 100px #266798 inset',
WebkitTextFillColor: theme.palette.mode === 'light' ? null : '#fff',
caretColor: theme.palette.mode === 'light' ? null : '#fff',
borderTopLeftRadius: 'inherit',
borderTopRightRadius: 'inherit',
},
...(styleProps.size === 'small' && {
paddingTop: 21,
paddingBottom: 4,
}),
...(styleProps.hiddenLabel && {
paddingTop: 16,
paddingBottom: 17,
...(styleProps.size === 'small' && {
paddingTop: 8,
paddingBottom: 9,
}),
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
}),
/* Styles applied to the input element if `multiline={true}`. */
...(styleProps.multiline && {
padding: 0,
}),
/* Styles applied to the input element if `startAdornment` is provided. */
...(styleProps.startAdornment && {
paddingLeft: 0,
}),
/* Styles applied to the input element if `endAdornment` is provided. */
...(styleProps.endAdornment && {
paddingRight: 0,
}),
...(styleProps.hiddenLabel &&
styleProps.size === 'small' && {
paddingTop: 8,
paddingBottom: 9,
}),
}));

const FilledInput = React.forwardRef(function FilledInput(inProps, ref) {
const props = useThemeProps({ props: inProps, name: 'MuiFilledInput' });

const FilledInput = React.forwardRef(function FilledInput(props, ref) {
const {
disableUnderline,
classes,
fullWidth = false,
inputComponent = 'input',
multiline = false,
type = 'text',
...other
} = props;

const styleProps = {
...other,
fullWidth,
inputComponent,
multiline,
type,
};

const classes = useUtilityClasses(props);

return (
<InputBase
classes={{
...classes,
root: clsx(classes.root, {
[classes.underline]: !disableUnderline,
}),
underline: null,
}}
components={{ Root: FilledInputRoot, Input: FilledInputInput }}
componentsProps={{ root: { styleProps }, input: { styleProps } }}
fullWidth={fullWidth}
inputComponent={inputComponent}
multiline={multiline}
ref={ref}
type={type}
{...other}
classes={classes}
/>
);
});
Expand Down Expand Up @@ -307,6 +330,10 @@ FilledInput.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'
Expand All @@ -320,4 +347,4 @@ FilledInput.propTypes = {

FilledInput.muiName = 'Input';

export default withStyles(styles, { name: 'MuiFilledInput' })(FilledInput);
export default FilledInput;
Loading