From 3b00416c1c4a0ad4d87d80bd87feb7b6bd88c2ee Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Thu, 3 Oct 2019 12:10:56 +0200 Subject: [PATCH 1/9] [OutlinedInput] Fix offscreen label strikethrough --- docs/src/pages/components/tabs/SimpleTabs.js | 5 ++-- .../src/OutlinedInput/NotchedOutline.js | 24 +++++++++---------- .../src/OutlinedInput/OutlinedInput.js | 2 ++ .../material-ui/src/TextField/TextField.js | 1 + 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/docs/src/pages/components/tabs/SimpleTabs.js b/docs/src/pages/components/tabs/SimpleTabs.js index 6b46571d534d09..6561c402a9569e 100644 --- a/docs/src/pages/components/tabs/SimpleTabs.js +++ b/docs/src/pages/components/tabs/SimpleTabs.js @@ -4,6 +4,7 @@ import { makeStyles } from '@material-ui/core/styles'; import AppBar from '@material-ui/core/AppBar'; import Tabs from '@material-ui/core/Tabs'; import Tab from '@material-ui/core/Tab'; +import TextField from '@material-ui/core/TextField'; import Typography from '@material-ui/core/Typography'; import Box from '@material-ui/core/Box'; @@ -62,13 +63,13 @@ export default function SimpleTabs() { - Item One + Item Two - Item Three + ); diff --git a/packages/material-ui/src/OutlinedInput/NotchedOutline.js b/packages/material-ui/src/OutlinedInput/NotchedOutline.js index efffa948314600..4f9881539d892f 100644 --- a/packages/material-ui/src/OutlinedInput/NotchedOutline.js +++ b/packages/material-ui/src/OutlinedInput/NotchedOutline.js @@ -33,10 +33,17 @@ export const styles = theme => { textAlign: 'left', padding: 0, lineHeight: '11px', - transition: theme.transitions.create('width', { + fontSize: '0.75rem', + maxWidth: 0, + transition: theme.transitions.create('max-width', { duration: theme.transitions.duration.shorter, easing: theme.transitions.easing.easeOut, }), + visibility: 'hidden', + '& span': { + paddingLeft: 4, + paddingRight: 6, + }, }, }; }; @@ -49,6 +56,7 @@ const NotchedOutline = React.forwardRef(function NotchedOutline(props, ref) { children, classes, className, + label = '\u200B', labelWidth: labelWidthProp, notched, style, @@ -62,25 +70,17 @@ const NotchedOutline = React.forwardRef(function NotchedOutline(props, ref) {
- + {/* Use the nominal use case of the legend, avoid rendering artefacts. */} {/* eslint-disable-next-line react/no-danger */} - + {label}
); diff --git a/packages/material-ui/src/OutlinedInput/OutlinedInput.js b/packages/material-ui/src/OutlinedInput/OutlinedInput.js index 9855e4fef540e8..4cbff10686a367 100644 --- a/packages/material-ui/src/OutlinedInput/OutlinedInput.js +++ b/packages/material-ui/src/OutlinedInput/OutlinedInput.js @@ -103,6 +103,7 @@ const OutlinedInput = React.forwardRef(function OutlinedInput(props, ref) { classes, fullWidth = false, inputComponent = 'input', + label, labelWidth = 0, multiline = false, notched, @@ -115,6 +116,7 @@ const OutlinedInput = React.forwardRef(function OutlinedInput(props, ref) { renderSuffix={state => ( Date: Sun, 24 Nov 2019 00:06:19 +0100 Subject: [PATCH 2/9] push a bit further --- .../pages/components/selects/NativeSelects.js | 12 +- .../components/selects/NativeSelects.tsx | 10 +- .../pages/components/selects/SimpleSelect.js | 12 +- .../pages/components/selects/SimpleSelect.tsx | 10 +- .../text-fields/ComposedTextField.js | 17 +-- .../text-fields/ComposedTextField.tsx | 17 +-- .../components/text-fields/InputAdornments.js | 5 +- .../text-fields/InputAdornments.tsx | 5 +- .../src/OutlinedInput/NotchedOutline.d.ts | 2 +- .../src/OutlinedInput/NotchedOutline.js | 116 +++++++++--------- .../src/OutlinedInput/OutlinedInput.d.ts | 2 +- .../src/OutlinedInput/OutlinedInput.js | 6 +- packages/material-ui/src/Select/Select.d.ts | 2 +- packages/material-ui/src/Select/Select.js | 12 +- .../material-ui/src/TextField/TextField.js | 13 +- 15 files changed, 83 insertions(+), 158 deletions(-) diff --git a/docs/src/pages/components/selects/NativeSelects.js b/docs/src/pages/components/selects/NativeSelects.js index 550e6d4e23ba46..d3945d59fe3056 100644 --- a/docs/src/pages/components/selects/NativeSelects.js +++ b/docs/src/pages/components/selects/NativeSelects.js @@ -23,12 +23,6 @@ export default function NativeSelects() { name: 'hai', }); - const inputLabel = React.useRef(null); - const [labelWidth, setLabelWidth] = React.useState(0); - React.useEffect(() => { - setLabelWidth(inputLabel.current.offsetWidth); - }, []); - const handleChange = name => event => { setState({ ...state, @@ -200,14 +194,12 @@ export default function NativeSelects() { Required - - Age - + Age { - setLabelWidth(inputLabel.current.offsetWidth); - }, []); - const handleChange = event => { setAge(event.target.value); }; @@ -195,15 +189,13 @@ export default function SimpleSelect() { Required - - Age - + Age None diff --git a/docs/src/pages/components/text-fields/ComposedTextField.js b/docs/src/pages/components/text-fields/ComposedTextField.js index 15736801bcd637..fcefa18ed1d52e 100644 --- a/docs/src/pages/components/text-fields/ComposedTextField.js +++ b/docs/src/pages/components/text-fields/ComposedTextField.js @@ -16,15 +16,9 @@ const useStyles = makeStyles(theme => ({ })); export default function ComposedTextField() { - const [labelWidth, setLabelWidth] = React.useState(0); const [name, setName] = React.useState('Composed TextField'); - const labelRef = React.useRef(null); const classes = useStyles(); - React.useEffect(() => { - setLabelWidth(labelRef.current.offsetWidth); - }, []); - const handleChange = event => { setName(event.target.value); }; @@ -61,15 +55,8 @@ export default function ComposedTextField() { Error - - Name - - + Name + Name diff --git a/docs/src/pages/components/text-fields/ComposedTextField.tsx b/docs/src/pages/components/text-fields/ComposedTextField.tsx index fbd114d7fd11ba..e43fd672626b3c 100644 --- a/docs/src/pages/components/text-fields/ComposedTextField.tsx +++ b/docs/src/pages/components/text-fields/ComposedTextField.tsx @@ -18,15 +18,9 @@ const useStyles = makeStyles((theme: Theme) => ); export default function ComposedTextField() { - const [labelWidth, setLabelWidth] = React.useState(0); const [name, setName] = React.useState('Composed TextField'); - const labelRef = React.useRef(null); const classes = useStyles(); - React.useEffect(() => { - setLabelWidth(labelRef.current!.offsetWidth); - }, []); - const handleChange = (event: React.ChangeEvent) => { setName(event.target.value); }; @@ -63,15 +57,8 @@ export default function ComposedTextField() { Error - - Name - - + Name + Name diff --git a/docs/src/pages/components/text-fields/InputAdornments.js b/docs/src/pages/components/text-fields/InputAdornments.js index 3067025bd05222..2adba13ad2990e 100644 --- a/docs/src/pages/components/text-fields/InputAdornments.js +++ b/docs/src/pages/components/text-fields/InputAdornments.js @@ -179,7 +179,6 @@ export default function InputAdornments() { inputProps={{ 'aria-label': 'weight', }} - labelWidth={0} /> Weight @@ -202,7 +201,7 @@ export default function InputAdornments() { } - labelWidth={70} + label="Password" /> @@ -212,7 +211,7 @@ export default function InputAdornments() { value={values.amount} onChange={handleChange('amount')} startAdornment={$} - labelWidth={60} + labelWidth="Amount" /> diff --git a/docs/src/pages/components/text-fields/InputAdornments.tsx b/docs/src/pages/components/text-fields/InputAdornments.tsx index 7b5c4b09976145..2b828179b1d5cf 100644 --- a/docs/src/pages/components/text-fields/InputAdornments.tsx +++ b/docs/src/pages/components/text-fields/InputAdornments.tsx @@ -189,7 +189,6 @@ export default function InputAdornments() { inputProps={{ 'aria-label': 'weight', }} - labelWidth={0} /> Weight @@ -212,7 +211,7 @@ export default function InputAdornments() { } - labelWidth={70} + label="Password" /> @@ -222,7 +221,7 @@ export default function InputAdornments() { value={values.amount} onChange={handleChange('amount')} startAdornment={$} - labelWidth={60} + labelWidth="Amount" /> diff --git a/packages/material-ui/src/OutlinedInput/NotchedOutline.d.ts b/packages/material-ui/src/OutlinedInput/NotchedOutline.d.ts index 8d72fa235ef81d..ddb163e30db876 100644 --- a/packages/material-ui/src/OutlinedInput/NotchedOutline.d.ts +++ b/packages/material-ui/src/OutlinedInput/NotchedOutline.d.ts @@ -6,7 +6,7 @@ export interface NotchedOutlineProps disabled?: boolean; error?: boolean; focused?: boolean; - labelWidth: number; + label?: React.ReactNode; notched: boolean; } diff --git a/packages/material-ui/src/OutlinedInput/NotchedOutline.js b/packages/material-ui/src/OutlinedInput/NotchedOutline.js index 4f9881539d892f..d63483cd3467d8 100644 --- a/packages/material-ui/src/OutlinedInput/NotchedOutline.js +++ b/packages/material-ui/src/OutlinedInput/NotchedOutline.js @@ -3,50 +3,53 @@ import PropTypes from 'prop-types'; import clsx from 'clsx'; import withStyles from '../styles/withStyles'; import useTheme from '../styles/useTheme'; -import capitalize from '../utils/capitalize'; -export const styles = theme => { - const align = theme.direction === 'rtl' ? 'right' : 'left'; - - return { - /* Styles applied to the root element. */ - root: { - position: 'absolute', - bottom: 0, - right: 0, - top: -5, - left: 0, - margin: 0, - padding: 0, - pointerEvents: 'none', - borderRadius: 'inherit', - borderStyle: 'solid', - borderWidth: 1, - // Match the Input Label - transition: theme.transitions.create([`padding-${align}`, 'border-color', 'border-width'], { - duration: theme.transitions.duration.shorter, - easing: theme.transitions.easing.easeOut, - }), - }, - /* Styles applied to the legend element. */ - legend: { - textAlign: 'left', - padding: 0, - lineHeight: '11px', - fontSize: '0.75rem', - maxWidth: 0, - transition: theme.transitions.create('max-width', { - duration: theme.transitions.duration.shorter, - easing: theme.transitions.easing.easeOut, - }), - visibility: 'hidden', - '& span': { - paddingLeft: 4, - paddingRight: 6, - }, +export const styles = theme => ({ + /* Styles applied to the root element. */ + root: { + position: 'absolute', + bottom: 0, + right: 0, + top: -5, + left: 0, + margin: 0, + padding: 0, + paddingLeft: 8, + pointerEvents: 'none', + borderRadius: 'inherit', + borderStyle: 'solid', + borderWidth: 1, + // Match the Input Label + transition: theme.transitions.create(['border-color', 'border-width'], { + duration: theme.transitions.duration.shorter, + easing: theme.transitions.easing.easeOut, + }), + }, + /* Styles applied to the legend element. */ + legend: { + textAlign: 'left', + padding: 0, + lineHeight: '11px', + fontSize: '0.75rem', + visibility: 'hidden', + maxWidth: 0, + transition: theme.transitions.create('max-width', { + duration: 50, + delay: 0, + }), + '& span': { + paddingLeft: 4, + paddingRight: 6, }, - }; -}; + }, + legendNotched: { + maxWidth: 1000, + transition: theme.transitions.create('max-width', { + duration: 100, + delay: 60, + }), + }, +}); /** * @ignore - internal component. @@ -56,31 +59,22 @@ const NotchedOutline = React.forwardRef(function NotchedOutline(props, ref) { children, classes, className, - label = '\u200B', - labelWidth: labelWidthProp, + label, notched, style, ...other } = props; - const theme = useTheme(); - const align = theme.direction === 'rtl' ? 'right' : 'left'; - const labelWidth = labelWidthProp > 0 ? labelWidthProp * 0.75 + 8 : 0; return ( -
- +
+ {/* Use the nominal use case of the legend, avoid rendering artefacts. */} {/* eslint-disable-next-line react/no-danger */} - {label} + {label ? {label} : }
); @@ -101,9 +95,9 @@ NotchedOutline.propTypes = { */ className: PropTypes.string, /** - * The width of the label. + * The label. */ - labelWidth: PropTypes.number.isRequired, + label: PropTypes.node, /** * If `true`, the outline is notched to accommodate the label. */ diff --git a/packages/material-ui/src/OutlinedInput/OutlinedInput.d.ts b/packages/material-ui/src/OutlinedInput/OutlinedInput.d.ts index a05549f52484ea..63c57b3edc2635 100644 --- a/packages/material-ui/src/OutlinedInput/OutlinedInput.d.ts +++ b/packages/material-ui/src/OutlinedInput/OutlinedInput.d.ts @@ -3,8 +3,8 @@ import { StandardProps } from '..'; import { InputBaseProps } from '../InputBase'; export interface OutlinedInputProps extends StandardProps { + label?: React.ReactNode; notched?: boolean; - labelWidth: number; } export type OutlinedInputClassKey = diff --git a/packages/material-ui/src/OutlinedInput/OutlinedInput.js b/packages/material-ui/src/OutlinedInput/OutlinedInput.js index 4cbff10686a367..357e2bf57be439 100644 --- a/packages/material-ui/src/OutlinedInput/OutlinedInput.js +++ b/packages/material-ui/src/OutlinedInput/OutlinedInput.js @@ -104,7 +104,6 @@ const OutlinedInput = React.forwardRef(function OutlinedInput(props, ref) { fullWidth = false, inputComponent = 'input', label, - labelWidth = 0, multiline = false, notched, type = 'text', @@ -117,7 +116,6 @@ const OutlinedInput = React.forwardRef(function OutlinedInput(props, ref) { ; multiple?: boolean; native?: boolean; diff --git a/packages/material-ui/src/Select/Select.js b/packages/material-ui/src/Select/Select.js index ccb1a733f6d49b..e124e9beb8a7d1 100644 --- a/packages/material-ui/src/Select/Select.js +++ b/packages/material-ui/src/Select/Select.js @@ -53,7 +53,7 @@ const Select = React.forwardRef(function Select(props, ref) { input || { standard: , - outlined: , + outlined: , filled: , }[variant]; @@ -141,16 +141,16 @@ Select.propTypes = { * When `native` is `true`, the attributes are applied on the `select` element. */ inputProps: PropTypes.object, + /** + * The label to be used on OutlinedInput. + * This prop is required when the `variant` prop is `outlined`. + */ + label: PropTypes.node, /** * The idea of an element that acts as an additional label. The Select will * be labelled by the additional label and the selected value. */ labelId: PropTypes.string, - /** - * The label width to be used on OutlinedInput. - * This prop is required when the `variant` prop is `outlined`. - */ - labelWidth: PropTypes.number, /** * Props applied to the [`Menu`](/api/menu/) element. */ diff --git a/packages/material-ui/src/TextField/TextField.js b/packages/material-ui/src/TextField/TextField.js index 5901ccaf84a492..1ef15a837c41e5 100644 --- a/packages/material-ui/src/TextField/TextField.js +++ b/packages/material-ui/src/TextField/TextField.js @@ -93,16 +93,6 @@ const TextField = React.forwardRef(function TextField(props, ref) { ...other } = props; - const [labelWidth, setLabelWidth] = React.useState(0); - const labelRef = React.useRef(null); - React.useEffect(() => { - if (variant === 'outlined') { - // #StrictMode ready - const labelNode = ReactDOM.findDOMNode(labelRef.current); - setLabelWidth(labelNode != null ? labelNode.offsetWidth : 0); - } - }, [variant, required, label]); - if (process.env.NODE_ENV !== 'production') { if (select && !children) { console.error( @@ -119,7 +109,6 @@ const TextField = React.forwardRef(function TextField(props, ref) { } InputMore.label = `${label}${required ? ' *' : ''}`; - InputMore.labelWidth = labelWidth; } if (select) { // unset defaults from textbox inputs @@ -171,7 +160,7 @@ const TextField = React.forwardRef(function TextField(props, ref) { {...other} > {label && ( - + {label} )} From 2b9a74474d310e10a6386440b90c235c3aba7136 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Wed, 4 Dec 2019 15:41:24 +0100 Subject: [PATCH 3/9] Non-breaking change --- docs/pages/api/outlined-input.md | 3 +- docs/pages/api/select.md | 3 +- .../pages/components/selects/NativeSelects.js | 12 +- .../components/selects/NativeSelects.tsx | 10 +- .../pages/components/selects/SimpleSelect.js | 12 +- .../pages/components/selects/SimpleSelect.tsx | 10 +- docs/src/pages/components/tabs/SimpleTabs.js | 5 +- .../components/text-fields/InputAdornments.js | 5 +- .../text-fields/InputAdornments.tsx | 5 +- .../src/OutlinedInput/NotchedOutline.d.ts | 2 +- .../src/OutlinedInput/NotchedOutline.js | 143 ++++++++++++------ .../src/OutlinedInput/OutlinedInput.d.ts | 1 + .../src/OutlinedInput/OutlinedInput.js | 12 +- packages/material-ui/src/Select/Select.d.ts | 1 + packages/material-ui/src/Select/Select.js | 10 +- .../material-ui/src/TextField/TextField.js | 1 - .../src/TextField/TextField.test.js | 4 +- 17 files changed, 166 insertions(+), 73 deletions(-) diff --git a/docs/pages/api/outlined-input.md b/docs/pages/api/outlined-input.md index 7b842b286d357e..7eb4733c06abc5 100644 --- a/docs/pages/api/outlined-input.md +++ b/docs/pages/api/outlined-input.md @@ -38,7 +38,8 @@ You can learn more about the difference by [reading this guide](/guides/minimizi | inputComponent | elementType | 'input' | The component used for the native input. Either a string to use a DOM element or a component. | | inputProps | object | | [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Attributes) applied to the `input` element. | | inputRef | ref | | Pass a ref to the `input` element. | -| labelWidth | number | 0 | The width of the label. | +| label | node | | The label of the input. It is only used for layout. The actual labelling is handled by `InputLabel`. If specified `labelWidth` is ignored. | +| labelWidth | number | 0 | The width of the label. Is ignored if `label` is provided. Prefer `label` if the input label appears with a strike through. | | margin | 'dense'
| 'none'
| | If `dense`, will adjust vertical spacing. This is normally obtained via context from FormControl. | | multiline | bool | false | If `true`, a textarea element will be rendered. | | name | string | | Name attribute of the `input` element. | diff --git a/docs/pages/api/select.md b/docs/pages/api/select.md index 226b202613b095..16dd7050562cfb 100644 --- a/docs/pages/api/select.md +++ b/docs/pages/api/select.md @@ -32,8 +32,9 @@ You can learn more about the difference by [reading this guide](/guides/minimizi | IconComponent | elementType | ArrowDropDownIcon | The icon that displays the arrow. | | input | element | | An `Input` element; does not have to be a material-ui specific `Input`. | | inputProps | object | | [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Attributes) applied to the `input` element. When `native` is `true`, the attributes are applied on the `select` element. | +| label | node | | See [OutlinedLabel#label](/api/outlined-input/#props) | | labelId | string | | The idea of an element that acts as an additional label. The Select will be labelled by the additional label and the selected value. | -| labelWidth | number | 0 | The label width to be used on OutlinedInput. This prop is required when the `variant` prop is `outlined`. | +| labelWidth | number | 0 | See OutlinedLabel#label | | MenuProps | object | | Props applied to the [`Menu`](/api/menu/) element. | | multiple | bool | false | If `true`, `value` must be an array and the menu will support multiple selections. | | native | bool | false | If `true`, the component will be using a native `select` element. | diff --git a/docs/src/pages/components/selects/NativeSelects.js b/docs/src/pages/components/selects/NativeSelects.js index d3945d59fe3056..550e6d4e23ba46 100644 --- a/docs/src/pages/components/selects/NativeSelects.js +++ b/docs/src/pages/components/selects/NativeSelects.js @@ -23,6 +23,12 @@ export default function NativeSelects() { name: 'hai', }); + const inputLabel = React.useRef(null); + const [labelWidth, setLabelWidth] = React.useState(0); + React.useEffect(() => { + setLabelWidth(inputLabel.current.offsetWidth); + }, []); + const handleChange = name => event => { setState({ ...state, @@ -194,12 +200,14 @@ export default function NativeSelects() { Required - Age + + Age + { + setLabelWidth(inputLabel.current.offsetWidth); + }, []); + const handleChange = event => { setAge(event.target.value); }; @@ -189,13 +195,15 @@ export default function SimpleSelect() { Required - Age + + Age + None diff --git a/docs/src/pages/components/tabs/SimpleTabs.js b/docs/src/pages/components/tabs/SimpleTabs.js index 6561c402a9569e..6b46571d534d09 100644 --- a/docs/src/pages/components/tabs/SimpleTabs.js +++ b/docs/src/pages/components/tabs/SimpleTabs.js @@ -4,7 +4,6 @@ import { makeStyles } from '@material-ui/core/styles'; import AppBar from '@material-ui/core/AppBar'; import Tabs from '@material-ui/core/Tabs'; import Tab from '@material-ui/core/Tab'; -import TextField from '@material-ui/core/TextField'; import Typography from '@material-ui/core/Typography'; import Box from '@material-ui/core/Box'; @@ -63,13 +62,13 @@ export default function SimpleTabs() { - + Item One Item Two - + Item Three ); diff --git a/docs/src/pages/components/text-fields/InputAdornments.js b/docs/src/pages/components/text-fields/InputAdornments.js index 2adba13ad2990e..3067025bd05222 100644 --- a/docs/src/pages/components/text-fields/InputAdornments.js +++ b/docs/src/pages/components/text-fields/InputAdornments.js @@ -179,6 +179,7 @@ export default function InputAdornments() { inputProps={{ 'aria-label': 'weight', }} + labelWidth={0} /> Weight @@ -201,7 +202,7 @@ export default function InputAdornments() { } - label="Password" + labelWidth={70} /> @@ -211,7 +212,7 @@ export default function InputAdornments() { value={values.amount} onChange={handleChange('amount')} startAdornment={$} - labelWidth="Amount" + labelWidth={60} /> diff --git a/docs/src/pages/components/text-fields/InputAdornments.tsx b/docs/src/pages/components/text-fields/InputAdornments.tsx index 2b828179b1d5cf..7b5c4b09976145 100644 --- a/docs/src/pages/components/text-fields/InputAdornments.tsx +++ b/docs/src/pages/components/text-fields/InputAdornments.tsx @@ -189,6 +189,7 @@ export default function InputAdornments() { inputProps={{ 'aria-label': 'weight', }} + labelWidth={0} /> Weight @@ -211,7 +212,7 @@ export default function InputAdornments() { } - label="Password" + labelWidth={70} /> @@ -221,7 +222,7 @@ export default function InputAdornments() { value={values.amount} onChange={handleChange('amount')} startAdornment={$} - labelWidth="Amount" + labelWidth={60} /> diff --git a/packages/material-ui/src/OutlinedInput/NotchedOutline.d.ts b/packages/material-ui/src/OutlinedInput/NotchedOutline.d.ts index ddb163e30db876..8d72fa235ef81d 100644 --- a/packages/material-ui/src/OutlinedInput/NotchedOutline.d.ts +++ b/packages/material-ui/src/OutlinedInput/NotchedOutline.d.ts @@ -6,7 +6,7 @@ export interface NotchedOutlineProps disabled?: boolean; error?: boolean; focused?: boolean; - label?: React.ReactNode; + labelWidth: number; notched: boolean; } diff --git a/packages/material-ui/src/OutlinedInput/NotchedOutline.js b/packages/material-ui/src/OutlinedInput/NotchedOutline.js index d63483cd3467d8..b2114bbb1f1758 100644 --- a/packages/material-ui/src/OutlinedInput/NotchedOutline.js +++ b/packages/material-ui/src/OutlinedInput/NotchedOutline.js @@ -3,53 +3,67 @@ import PropTypes from 'prop-types'; import clsx from 'clsx'; import withStyles from '../styles/withStyles'; import useTheme from '../styles/useTheme'; +import capitalize from '../utils/capitalize'; -export const styles = theme => ({ - /* Styles applied to the root element. */ - root: { - position: 'absolute', - bottom: 0, - right: 0, - top: -5, - left: 0, - margin: 0, - padding: 0, - paddingLeft: 8, - pointerEvents: 'none', - borderRadius: 'inherit', - borderStyle: 'solid', - borderWidth: 1, - // Match the Input Label - transition: theme.transitions.create(['border-color', 'border-width'], { - duration: theme.transitions.duration.shorter, - easing: theme.transitions.easing.easeOut, - }), - }, - /* Styles applied to the legend element. */ - legend: { - textAlign: 'left', - padding: 0, - lineHeight: '11px', - fontSize: '0.75rem', - visibility: 'hidden', - maxWidth: 0, - transition: theme.transitions.create('max-width', { - duration: 50, - delay: 0, - }), - '& span': { - paddingLeft: 4, - paddingRight: 6, +export const styles = theme => { + const align = theme.direction === 'rtl' ? 'right' : 'left'; + + return { + /* Styles applied to the root element. */ + root: { + position: 'absolute', + bottom: 0, + right: 0, + top: -5, + left: 0, + margin: 0, + padding: 0, + pointerEvents: 'none', + borderRadius: 'inherit', + borderStyle: 'solid', + borderWidth: 1, + // Match the Input Label + transition: theme.transitions.create([`padding-${align}`, 'border-color', 'border-width'], { + duration: theme.transitions.duration.shorter, + easing: theme.transitions.easing.easeOut, + }), }, - }, - legendNotched: { - maxWidth: 1000, - transition: theme.transitions.create('max-width', { - duration: 100, - delay: 60, - }), - }, -}); + /* Styles applied to the legend element when `labelWidth` is provided. */ + legend: { + textAlign: 'left', + padding: 0, + lineHeight: '11px', + transition: theme.transitions.create('width', { + duration: theme.transitions.duration.shorter, + easing: theme.transitions.easing.easeOut, + }), + }, + /* Styles applied to the legend element. */ + legendLabelled: { + textAlign: 'left', + padding: 0, + lineHeight: '11px', + fontSize: '0.75rem', + visibility: 'hidden', + maxWidth: 0, + transition: theme.transitions.create('max-width', { + duration: 50, + delay: 0, + }), + '& span': { + paddingLeft: 4, + paddingRight: 6, + }, + }, + legendNotched: { + maxWidth: 1000, + transition: theme.transitions.create('max-width', { + duration: 100, + delay: 60, + }), + }, + }; +}; /** * @ignore - internal component. @@ -60,15 +74,48 @@ const NotchedOutline = React.forwardRef(function NotchedOutline(props, ref) { classes, className, label, + labelWidth: labelWidthProp, notched, style, ...other } = props; + const theme = useTheme(); + const align = theme.direction === 'rtl' ? 'right' : 'left'; + const labelWidth = labelWidthProp > 0 ? labelWidthProp * 0.75 + 8 : 0; + + if (label === undefined) { + return ( +
+ + {/* Use the nominal use case of the legend, avoid rendering artefacts. */} + {/* eslint-disable-next-line react/no-danger */} + + +
+ ); + } return (
@@ -98,6 +145,10 @@ NotchedOutline.propTypes = { * The label. */ label: PropTypes.node, + /** + * The width of the label. + */ + labelWidth: PropTypes.number.isRequired, /** * If `true`, the outline is notched to accommodate the label. */ diff --git a/packages/material-ui/src/OutlinedInput/OutlinedInput.d.ts b/packages/material-ui/src/OutlinedInput/OutlinedInput.d.ts index 63c57b3edc2635..67f3175264aaf8 100644 --- a/packages/material-ui/src/OutlinedInput/OutlinedInput.d.ts +++ b/packages/material-ui/src/OutlinedInput/OutlinedInput.d.ts @@ -5,6 +5,7 @@ import { InputBaseProps } from '../InputBase'; export interface OutlinedInputProps extends StandardProps { label?: React.ReactNode; notched?: boolean; + labelWidth?: number; } export type OutlinedInputClassKey = diff --git a/packages/material-ui/src/OutlinedInput/OutlinedInput.js b/packages/material-ui/src/OutlinedInput/OutlinedInput.js index 357e2bf57be439..cac03183de5f20 100644 --- a/packages/material-ui/src/OutlinedInput/OutlinedInput.js +++ b/packages/material-ui/src/OutlinedInput/OutlinedInput.js @@ -103,7 +103,7 @@ const OutlinedInput = React.forwardRef(function OutlinedInput(props, ref) { classes, fullWidth = false, inputComponent = 'input', - label, + labelWidth = 0, multiline = false, notched, type = 'text', @@ -115,7 +115,7 @@ const OutlinedInput = React.forwardRef(function OutlinedInput(props, ref) { renderSuffix={state => ( ; multiple?: boolean; native?: boolean; diff --git a/packages/material-ui/src/Select/Select.js b/packages/material-ui/src/Select/Select.js index e124e9beb8a7d1..b6a1d88c445378 100644 --- a/packages/material-ui/src/Select/Select.js +++ b/packages/material-ui/src/Select/Select.js @@ -24,6 +24,7 @@ const Select = React.forwardRef(function Select(props, ref) { id, input, inputProps, + label, labelId, labelWidth = 0, MenuProps, @@ -53,7 +54,7 @@ const Select = React.forwardRef(function Select(props, ref) { input || { standard: , - outlined: , + outlined: , filled: , }[variant]; @@ -142,8 +143,7 @@ Select.propTypes = { */ inputProps: PropTypes.object, /** - * The label to be used on OutlinedInput. - * This prop is required when the `variant` prop is `outlined`. + * See [OutlinedLabel#label](/api/outlined-input/#props) */ label: PropTypes.node, /** @@ -151,6 +151,10 @@ Select.propTypes = { * be labelled by the additional label and the selected value. */ labelId: PropTypes.string, + /** + * See OutlinedLabel#label + */ + labelWidth: PropTypes.number, /** * Props applied to the [`Menu`](/api/menu/) element. */ diff --git a/packages/material-ui/src/TextField/TextField.js b/packages/material-ui/src/TextField/TextField.js index 1ef15a837c41e5..7bed742e9df23a 100644 --- a/packages/material-ui/src/TextField/TextField.js +++ b/packages/material-ui/src/TextField/TextField.js @@ -1,5 +1,4 @@ import React from 'react'; -import ReactDOM from 'react-dom'; import PropTypes from 'prop-types'; import clsx from 'clsx'; import { refType } from '@material-ui/utils'; diff --git a/packages/material-ui/src/TextField/TextField.test.js b/packages/material-ui/src/TextField/TextField.test.js index 28bd6c429fa4f2..f2c561f174c968 100644 --- a/packages/material-ui/src/TextField/TextField.test.js +++ b/packages/material-ui/src/TextField/TextField.test.js @@ -92,9 +92,9 @@ describe('', () => { describe('with an outline', () => { it('should set outline props', () => { - const wrapper = mount(); + const wrapper = mount(); - expect(wrapper.find(OutlinedInput).props()).to.have.property('labelWidth', 0); + expect(wrapper.find(OutlinedInput).props()).to.have.property('label', 'foo'); }); it('should set shrink prop on outline from label', () => { From 0160dc15dcfc9a093e063fd37683422ab0421e40 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Wed, 4 Dec 2019 16:40:01 +0100 Subject: [PATCH 4/9] fix: ReactNode as label --- .../src/OutlinedInput/NotchedOutline.js | 12 +++++++++++- .../material-ui/src/OutlinedInput/OutlinedInput.js | 2 ++ packages/material-ui/src/TextField/TextField.js | 7 ++++++- .../material-ui/src/TextField/TextField.test.js | 14 ++++++++++++-- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/packages/material-ui/src/OutlinedInput/NotchedOutline.js b/packages/material-ui/src/OutlinedInput/NotchedOutline.js index b2114bbb1f1758..fdd75370189311 100644 --- a/packages/material-ui/src/OutlinedInput/NotchedOutline.js +++ b/packages/material-ui/src/OutlinedInput/NotchedOutline.js @@ -18,6 +18,7 @@ export const styles = theme => { left: 0, margin: 0, padding: 0, + paddingLeft: 8, pointerEvents: 'none', borderRadius: 'inherit', borderStyle: 'solid', @@ -113,7 +114,16 @@ const NotchedOutline = React.forwardRef(function NotchedOutline(props, ref) { } return ( -
+
( + {label} + {required && '\u00a0*'} + + ); } if (select) { // unset defaults from textbox inputs diff --git a/packages/material-ui/src/TextField/TextField.test.js b/packages/material-ui/src/TextField/TextField.test.js index f2c561f174c968..cc0d1ba40746aa 100644 --- a/packages/material-ui/src/TextField/TextField.test.js +++ b/packages/material-ui/src/TextField/TextField.test.js @@ -92,9 +92,19 @@ describe('', () => { describe('with an outline', () => { it('should set outline props', () => { - const wrapper = mount(); + const { container, getAllByTestId } = render( + label} + required + variant="outlined" + />, + ); - expect(wrapper.find(OutlinedInput).props()).to.have.property('label', 'foo'); + const [, fakeLabel] = getAllByTestId('label'); + const notch = container.querySelector('.notch legend'); + expect(notch).to.contain(fakeLabel); + expect(notch).to.have.text('label\u00a0*'); }); it('should set shrink prop on outline from label', () => { From 63affe7ad5a41cbbf8161df254629cc206f4a969 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Mon, 13 Jan 2020 15:30:15 +0100 Subject: [PATCH 5/9] minimize diff --- .../src/OutlinedInput/NotchedOutline.js | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/packages/material-ui/src/OutlinedInput/NotchedOutline.js b/packages/material-ui/src/OutlinedInput/NotchedOutline.js index fdd75370189311..f1f4ec041f1bd6 100644 --- a/packages/material-ui/src/OutlinedInput/NotchedOutline.js +++ b/packages/material-ui/src/OutlinedInput/NotchedOutline.js @@ -82,56 +82,57 @@ const NotchedOutline = React.forwardRef(function NotchedOutline(props, ref) { } = props; const theme = useTheme(); const align = theme.direction === 'rtl' ? 'right' : 'left'; - const labelWidth = labelWidthProp > 0 ? labelWidthProp * 0.75 + 8 : 0; - if (label === undefined) { + if (label !== undefined) { return (
{/* Use the nominal use case of the legend, avoid rendering artefacts. */} {/* eslint-disable-next-line react/no-danger */} - + {label ? {label} : }
); } + const labelWidth = labelWidthProp > 0 ? labelWidthProp * 0.75 + 8 : 0; + return (
{/* Use the nominal use case of the legend, avoid rendering artefacts. */} {/* eslint-disable-next-line react/no-danger */} - {label ? {label} : } +
); From e5b3ceb3fd798841d1548b691b4762a23afad808 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 14 Jan 2020 10:24:42 +0100 Subject: [PATCH 6/9] Fix visual regression I don't understand the box size computation if max-width < actual width. Seems like lineHeight is ignored if max-width < width --- packages/material-ui/src/OutlinedInput/NotchedOutline.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/material-ui/src/OutlinedInput/NotchedOutline.js b/packages/material-ui/src/OutlinedInput/NotchedOutline.js index f1f4ec041f1bd6..4774d6fe794523 100644 --- a/packages/material-ui/src/OutlinedInput/NotchedOutline.js +++ b/packages/material-ui/src/OutlinedInput/NotchedOutline.js @@ -33,7 +33,7 @@ export const styles = theme => { legend: { textAlign: 'left', padding: 0, - lineHeight: '11px', + lineHeight: '11px', // sync with `height` in `legend` styles transition: theme.transitions.create('width', { duration: theme.transitions.duration.shorter, easing: theme.transitions.easing.easeOut, @@ -43,7 +43,7 @@ export const styles = theme => { legendLabelled: { textAlign: 'left', padding: 0, - lineHeight: '11px', + height: 11, // sync with `lineHeight` in `legend` styles fontSize: '0.75rem', visibility: 'hidden', maxWidth: 0, From 810d8e7694b16a5ec0b450805289be02d67fd517 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 14 Jan 2020 11:43:00 +0100 Subject: [PATCH 7/9] Use transition duration from theme --- packages/material-ui/src/OutlinedInput/NotchedOutline.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/material-ui/src/OutlinedInput/NotchedOutline.js b/packages/material-ui/src/OutlinedInput/NotchedOutline.js index 4774d6fe794523..c757228019367d 100644 --- a/packages/material-ui/src/OutlinedInput/NotchedOutline.js +++ b/packages/material-ui/src/OutlinedInput/NotchedOutline.js @@ -48,8 +48,8 @@ export const styles = theme => { visibility: 'hidden', maxWidth: 0, transition: theme.transitions.create('max-width', { - duration: 50, - delay: 0, + duration: theme.transitions.duration.shorter, + easing: theme.transitions.easing.easeOut, }), '& span': { paddingLeft: 4, @@ -59,8 +59,8 @@ export const styles = theme => { legendNotched: { maxWidth: 1000, transition: theme.transitions.create('max-width', { - duration: 100, - delay: 60, + duration: theme.transitions.duration.shorter, + easing: theme.transitions.easing.easeOut, }), }, }; From d1c88b577f6e0586c786d105999d05be423c9d73 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Sun, 19 Jan 2020 12:32:27 +0100 Subject: [PATCH 8/9] fix: IE11height issue by adding near 0 maxWidth --- packages/material-ui/src/OutlinedInput/NotchedOutline.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/material-ui/src/OutlinedInput/NotchedOutline.js b/packages/material-ui/src/OutlinedInput/NotchedOutline.js index c757228019367d..833dde3430b908 100644 --- a/packages/material-ui/src/OutlinedInput/NotchedOutline.js +++ b/packages/material-ui/src/OutlinedInput/NotchedOutline.js @@ -46,7 +46,7 @@ export const styles = theme => { height: 11, // sync with `lineHeight` in `legend` styles fontSize: '0.75rem', visibility: 'hidden', - maxWidth: 0, + maxWidth: 0.01, transition: theme.transitions.create('max-width', { duration: theme.transitions.duration.shorter, easing: theme.transitions.easing.easeOut, @@ -89,10 +89,7 @@ const NotchedOutline = React.forwardRef(function NotchedOutline(props, ref) { aria-hidden className={clsx(classes.root, className)} ref={ref} - style={{ - [`padding${capitalize(align)}`]: '8px', - ...style, - }} + style={style} {...other} > 0 ? labelWidthProp * 0.75 + 8 : 0; + const labelWidth = labelWidthProp > 0 ? labelWidthProp * 0.75 + 8 : 0.01; return (
Date: Mon, 20 Jan 2020 14:47:54 +0100 Subject: [PATCH 9/9] fix: showing notch with no label --- packages/material-ui/src/TextField/TextField.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/material-ui/src/TextField/TextField.js b/packages/material-ui/src/TextField/TextField.js index 9f1fa313a6d6cc..908958231cf6f7 100644 --- a/packages/material-ui/src/TextField/TextField.js +++ b/packages/material-ui/src/TextField/TextField.js @@ -107,11 +107,13 @@ const TextField = React.forwardRef(function TextField(props, ref) { InputMore.notched = InputLabelProps.shrink; } - InputMore.label = ( + InputMore.label = label ? ( {label} {required && '\u00a0*'} + ) : ( + label ); } if (select) {