diff --git a/packages/material-ui/src/TextareaAutosize/TextareaAutosize.js b/packages/material-ui/src/TextareaAutosize/TextareaAutosize.js index 4a0cf1d992f019..67691d68c3fd7f 100644 --- a/packages/material-ui/src/TextareaAutosize/TextareaAutosize.js +++ b/packages/material-ui/src/TextareaAutosize/TextareaAutosize.js @@ -47,15 +47,14 @@ const TextareaAutosize = React.forwardRef(function TextareaAutosize(props, ref) getStyleValue(computedStyle, 'border-top-width'); // The height of the inner content - const innerHeight = inputShallow.scrollHeight; + const innerHeight = inputShallow.scrollHeight - padding; // Measure height of a textarea with a single row inputShallow.value = 'x'; - let singleRowHeight = inputShallow.scrollHeight; - singleRowHeight -= padding; + const singleRowHeight = inputShallow.scrollHeight - padding; // The height of the outer content - let outerHeight = innerHeight - padding; + let outerHeight = innerHeight; if (rows != null) { outerHeight = Math.max(Number(rows) * singleRowHeight, outerHeight); @@ -65,15 +64,20 @@ const TextareaAutosize = React.forwardRef(function TextareaAutosize(props, ref) } outerHeight = Math.max(outerHeight, singleRowHeight); - outerHeight += boxSizing === 'border-box' ? padding + border : 0; + // Take the box sizing into account for applying this value as a style. + const outerHeightStyle = outerHeight + (boxSizing === 'border-box' ? padding + border : 0); setState(prevState => { // Need a large enough different to update the height. // This prevents infinite rendering loop. - if (outerHeight > 0 && Math.abs((prevState.outerHeight || 0) - outerHeight) > 1) { + if ( + outerHeightStyle > 0 && + Math.abs((prevState.outerHeightStyle || 0) - outerHeightStyle) > 1 + ) { return { innerHeight, outerHeight, + outerHeightStyle, }; } @@ -116,7 +120,7 @@ const TextareaAutosize = React.forwardRef(function TextareaAutosize(props, ref) // Apply the rows prop to get a "correct" first SSR paint rows={rows || 1} style={{ - height: state.outerHeight, + height: state.outerHeightStyle, // Need a large enough different to allow scrolling. // This prevents infinite rendering loop. overflow: Math.abs(state.outerHeight - state.innerHeight) <= 1 ? 'hidden' : null, diff --git a/packages/material-ui/src/TextareaAutosize/TextareaAutosize.test.js b/packages/material-ui/src/TextareaAutosize/TextareaAutosize.test.js index 9334d9497e21a0..389e37be8a6fd7 100644 --- a/packages/material-ui/src/TextareaAutosize/TextareaAutosize.test.js +++ b/packages/material-ui/src/TextareaAutosize/TextareaAutosize.test.js @@ -5,11 +5,11 @@ import { createMount } from '@material-ui/core/test-utils'; import describeConformance from '@material-ui/core/test-utils/describeConformance'; import TextareaAutosize from './TextareaAutosize'; -function getHeight(wrapper) { +function getStyle(wrapper) { return wrapper .find('textarea') .at(0) - .props().style.height; + .props().style; } describe('', () => { @@ -78,7 +78,10 @@ describe('', () => { it('should handle the resize event', () => { const wrapper = mount(); - assert.strictEqual(getHeight(wrapper), undefined); + assert.deepEqual(getStyle(wrapper), { + height: undefined, + overflow: null, + }); setLayout(wrapper, { getComputedStyle: { 'box-sizing': 'content-box', @@ -89,14 +92,17 @@ describe('', () => { window.dispatchEvent(new window.Event('resize', {})); clock.tick(166); wrapper.update(); - assert.strictEqual(getHeight(wrapper), 30); + assert.deepEqual(getStyle(wrapper), { + height: 30, + overflow: 'hidden', + }); }); }); it('should update when uncontrolled', () => { const handleChange = spy(); const wrapper = mount(); - assert.strictEqual(getHeight(wrapper), undefined); + assert.deepEqual(getStyle(wrapper), { height: undefined, overflow: null }); setLayout(wrapper, { getComputedStyle: { 'box-sizing': 'content-box', @@ -109,14 +115,14 @@ describe('', () => { .at(0) .simulate('change'); wrapper.update(); - assert.strictEqual(getHeight(wrapper), 30); + assert.deepEqual(getStyle(wrapper), { height: 30, overflow: 'hidden' }); assert.strictEqual(handleChange.callCount, 1); }); it('should take the border into account with border-box', () => { const border = 5; const wrapper = mount(); - assert.strictEqual(getHeight(wrapper), undefined); + assert.deepEqual(getStyle(wrapper), { height: undefined, overflow: null }); setLayout(wrapper, { getComputedStyle: { 'box-sizing': 'border-box', @@ -127,7 +133,7 @@ describe('', () => { }); wrapper.setProps(); wrapper.update(); - assert.strictEqual(getHeight(wrapper), 30 + border); + assert.deepEqual(getStyle(wrapper), { height: 30 + border, overflow: 'hidden' }); }); it('should take the padding into account with content-box', () => { @@ -143,7 +149,7 @@ describe('', () => { }); wrapper.setProps(); wrapper.update(); - assert.strictEqual(getHeight(wrapper), 30 - padding); + assert.deepEqual(getStyle(wrapper), { height: 30 - padding, overflow: 'hidden' }); }); it('should have at least height of "rows"', () => { @@ -159,7 +165,7 @@ describe('', () => { }); wrapper.setProps(); wrapper.update(); - assert.strictEqual(getHeight(wrapper), lineHeight * rows); + assert.deepEqual(getStyle(wrapper), { height: lineHeight * rows, overflow: null }); }); it('should have at max "rowsMax" rows', () => { @@ -175,7 +181,7 @@ describe('', () => { }); wrapper.setProps(); wrapper.update(); - assert.strictEqual(getHeight(wrapper), lineHeight * rowsMax); + assert.deepEqual(getStyle(wrapper), { height: lineHeight * rowsMax, overflow: null }); }); it('should update its height when the "rowsMax" prop changes', () => { @@ -190,10 +196,10 @@ describe('', () => { }); wrapper.setProps(); wrapper.update(); - assert.strictEqual(getHeight(wrapper), lineHeight * 3); + assert.deepEqual(getStyle(wrapper), { height: lineHeight * 3, overflow: null }); wrapper.setProps({ rowsMax: 2 }); wrapper.update(); - assert.strictEqual(getHeight(wrapper), lineHeight * 2); + assert.deepEqual(getStyle(wrapper), { height: lineHeight * 2, overflow: null }); }); }); });