Skip to content

Commit 415ec90

Browse files
one textarea, smaller
1 parent ec7ddb1 commit 415ec90

File tree

3 files changed

+58
-132
lines changed

3 files changed

+58
-132
lines changed

packages/material-ui/src/InputBase/Textarea.js

Lines changed: 26 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,6 @@ import PropTypes from 'prop-types';
33
import { useForkRef } from '../utils/reactHelpers';
44
import debounce from 'debounce'; // < 1kb payload overhead when lodash/debounce is > 3kb.
55

6-
const styles = {
7-
/* Styles applied to the shallow textarea element. */
8-
shadow: {
9-
// Visibility needed to hide the extra text area on iPads
10-
visibility: 'hidden',
11-
// Remove from the content flow
12-
position: 'absolute',
13-
// Ignore the scrollbar width
14-
overflow: 'hidden',
15-
height: '0',
16-
},
17-
};
18-
196
function getStyleValue(computedStyle, property) {
207
return parseInt(computedStyle[property], 10) || 0;
218
}
@@ -33,24 +20,27 @@ const Textarea = React.forwardRef(function Textarea(props, ref) {
3320
const { current: isControlled } = React.useRef(value != null);
3421
const inputRef = React.useRef();
3522
const [state, setState] = React.useState({});
36-
const shadowRef = React.useRef();
3723
const handleRef = useForkRef(ref, inputRef);
3824

3925
const syncHeight = React.useCallback(() => {
4026
const input = inputRef.current;
41-
const inputShallow = shadowRef.current;
27+
const savedValue = input.value;
28+
const savedHeight = input.style.height;
29+
const savedOverflow = input.style.overflow;
4230

43-
const computedStyle = window.getComputedStyle(input);
44-
inputShallow.style.width = computedStyle.width;
45-
inputShallow.value = input.value || props.placeholder || 'x';
31+
input.style.overflow = 'hidden';
32+
input.style.height = '0';
4633

4734
// The height of the inner content
48-
const innerHeight = inputShallow.scrollHeight;
35+
input.value = savedValue || props.placeholder || 'x';
36+
const innerHeight = input.scrollHeight;
37+
38+
const computedStyle = window.getComputedStyle(input);
4939
const boxSizing = computedStyle['box-sizing'];
5040

5141
// Measure height of a textarea with a single row
52-
inputShallow.value = 'x';
53-
const singleRowHeight = inputShallow.scrollHeight;
42+
input.value = 'x';
43+
const singleRowHeight = input.scrollHeight;
5444

5545
// The height of the outer content
5646
let outerHeight = innerHeight;
@@ -73,6 +63,10 @@ const Textarea = React.forwardRef(function Textarea(props, ref) {
7363
getStyleValue(computedStyle, 'border-top-width');
7464
}
7565

66+
input.style.overflow = savedOverflow;
67+
input.style.height = savedHeight;
68+
input.value = savedValue;
69+
7670
setState(prevState => {
7771
// Need a large enough different to update the height.
7872
// This prevents infinite rendering loop.
@@ -114,27 +108,17 @@ const Textarea = React.forwardRef(function Textarea(props, ref) {
114108
};
115109

116110
return (
117-
<React.Fragment>
118-
<textarea
119-
value={value}
120-
onChange={handleChange}
121-
ref={handleRef}
122-
style={{
123-
height: state.outerHeight,
124-
overflow: state.outerHeight === state.innerHeight ? 'hidden' : null,
125-
...style,
126-
}}
127-
{...other}
128-
/>
129-
<textarea
130-
aria-hidden="true"
131-
className={props.className}
132-
readOnly
133-
ref={shadowRef}
134-
tabIndex={-1}
135-
style={styles.shadow}
136-
/>
137-
</React.Fragment>
111+
<textarea
112+
value={value}
113+
onChange={handleChange}
114+
ref={handleRef}
115+
style={{
116+
height: state.outerHeight,
117+
overflow: state.outerHeight === state.innerHeight ? 'hidden' : null,
118+
...style,
119+
}}
120+
{...other}
121+
/>
138122
);
139123
});
140124

packages/material-ui/src/InputBase/Textarea.test.js

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ function getHeight(wrapper) {
1111
.props().style.height;
1212
}
1313

14-
describe.only('<Textarea />', () => {
14+
describe('<Textarea />', () => {
1515
let mount;
1616

1717
before(() => {
@@ -37,21 +37,14 @@ describe.only('<Textarea />', () => {
3737

3838
const getComputedStyleStub = {};
3939

40-
function setLayout(wrapper, { getComputedStyle, inputHeight, shadowHeight }) {
41-
const input = wrapper
42-
.find('textarea')
43-
.at(0)
44-
.instance();
45-
const shadow = wrapper
46-
.find('textarea')
47-
.at(1)
48-
.instance();
40+
function setLayout(wrapper, { getComputedStyle, scrollHeight, lineHeight }) {
41+
const input = wrapper.find('textarea').instance();
4942
getComputedStyleStub[input] = getComputedStyle;
5043

51-
let getter = 0;
52-
stub(shadow, 'scrollHeight').get(() => {
53-
getter += 1;
54-
return getter % 2 === 1 ? inputHeight : shadowHeight;
44+
let index = 0;
45+
stub(input, 'scrollHeight').get(() => {
46+
index += 1;
47+
return index % 2 === 1 ? scrollHeight : lineHeight;
5548
});
5649
}
5750

@@ -81,8 +74,8 @@ describe.only('<Textarea />', () => {
8174
getComputedStyle: {
8275
'box-sizing': 'content-box',
8376
},
84-
inputHeight: 30,
85-
shadowHeight: 15,
77+
scrollHeight: 30,
78+
lineHeight: 15,
8679
});
8780
window.dispatchEvent(new window.Event('resize', {}));
8881
clock.tick(166);
@@ -99,8 +92,8 @@ describe.only('<Textarea />', () => {
9992
getComputedStyle: {
10093
'box-sizing': 'content-box',
10194
},
102-
inputHeight: 30,
103-
shadowHeight: 15,
95+
scrollHeight: 30,
96+
lineHeight: 15,
10497
});
10598
wrapper
10699
.find('textarea')
@@ -120,8 +113,8 @@ describe.only('<Textarea />', () => {
120113
'box-sizing': 'border-box',
121114
'border-bottom-width': `${border}px`,
122115
},
123-
inputHeight: 30,
124-
shadowHeight: 15,
116+
scrollHeight: 30,
117+
lineHeight: 15,
125118
});
126119
wrapper.setProps();
127120
wrapper.update();
@@ -136,8 +129,8 @@ describe.only('<Textarea />', () => {
136129
'box-sizing': 'content-box',
137130
'padding-top': `${padding}px`,
138131
},
139-
inputHeight: 30,
140-
shadowHeight: 15,
132+
scrollHeight: 30,
133+
lineHeight: 15,
141134
});
142135
wrapper.setProps();
143136
wrapper.update();
@@ -152,8 +145,8 @@ describe.only('<Textarea />', () => {
152145
getComputedStyle: {
153146
'box-sizing': 'content-box',
154147
},
155-
inputHeight: 30,
156-
shadowHeight: lineHeight,
148+
scrollHeight: 30,
149+
lineHeight,
157150
});
158151
wrapper.setProps();
159152
wrapper.update();
@@ -168,8 +161,8 @@ describe.only('<Textarea />', () => {
168161
getComputedStyle: {
169162
'box-sizing': 'content-box',
170163
},
171-
inputHeight: 100,
172-
shadowHeight: lineHeight,
164+
scrollHeight: 100,
165+
lineHeight,
173166
});
174167
wrapper.setProps();
175168
wrapper.update();

pages/demos/app-bar.js

Lines changed: 13 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,18 @@
1+
import 'docs/src/modules/components/bootstrap';
2+
// --- Post bootstrap -----
13
import React from 'react';
2-
import { makeStyles } from '@material-ui/core/styles';
3-
import Input from '@material-ui/core/Input';
4+
import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs';
45

5-
const useStyles = makeStyles({
6-
input: {
7-
width: 200,
8-
},
9-
input1: {
10-
fontSize: 13,
11-
boxSizing: 'border-box',
12-
border: '10px solid black',
13-
},
14-
input2: {
15-
fontSize: 13,
16-
boxSizing: 'content-box',
17-
padding: 10,
18-
},
19-
});
6+
const req = require.context('docs/src/pages/demos/app-bar', false, /\.(md|js|tsx)$/);
7+
const reqSource = require.context(
8+
'!raw-loader!../../docs/src/pages/demos/app-bar',
9+
false,
10+
/\.(js|tsx)$/,
11+
);
12+
const reqPrefix = 'pages/demos/app-bar';
2013

21-
function Textarea() {
22-
const [value, setValue] = React.useState(
23-
`Hey, sorry for being late to respond. Here is a codesandbox. It actually happens when I reduce the font-size of the input. Try adding some text or paste a long paragraph and you will the bottom margin being increased. It works fine with the default font-size.`,
24-
);
25-
const classes = useStyles();
26-
27-
const handleChange = event => {
28-
setValue(event.target.value);
29-
};
30-
31-
return (
32-
<div>
33-
<Input
34-
className={classes.input}
35-
multiline
36-
value={value}
37-
onChange={handleChange}
38-
classes={{
39-
input: classes.input1,
40-
}}
41-
/>
42-
<Input
43-
className={classes.input}
44-
multiline
45-
value={value}
46-
onChange={handleChange}
47-
classes={{
48-
input: classes.input2,
49-
}}
50-
/>
51-
<Input className={classes.input} multiline placeholder="rowsMin" rowsMin="3" />
52-
<Input
53-
className={classes.input}
54-
multiline
55-
value={value}
56-
onChange={handleChange}
57-
rowsMax="4"
58-
/>
59-
<Input className={classes.input} multiline placeholder="long placeholder long placeholder" />
60-
<Input
61-
className={classes.input}
62-
multiline
63-
defaultValue="long default value long default value"
64-
/>
65-
</div>
66-
);
14+
function Page() {
15+
return <MarkdownDocs req={req} reqSource={reqSource} reqPrefix={reqPrefix} />;
6716
}
6817

69-
export default Textarea;
18+
export default Page;

0 commit comments

Comments
 (0)