Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
50d7c7d
[TextField] Fix Backspacing after line break in multiline causes heig…
Hukumchand-Narwre Dec 7, 2025
298dd88
Merge branch 'master' into multiline-textfield-height-issues
Hukumchand-Narwre Dec 7, 2025
ee25462
Merge branch 'master' into multiline-textfield-height-issues
Hukumchand-Narwre Dec 8, 2025
2225183
Merge branch 'master' into multiline-textfield-height-issues
Hukumchand-Narwre Dec 10, 2025
21b92c6
Merge branch 'master' into multiline-textfield-height-issues
Hukumchand-Narwre Dec 12, 2025
2ae30dc
Merge branch 'master' into multiline-textfield-height-issues
Hukumchand-Narwre Dec 15, 2025
96e0ad7
Merge branch 'master' into multiline-textfield-height-issues
Hukumchand-Narwre Dec 15, 2025
6dca6e9
Merge branch 'master' into multiline-textfield-height-issues
Hukumchand-Narwre Dec 16, 2025
9980173
comments resolved
Hukumchand-Narwre Dec 17, 2025
dfd60ff
Merge branch 'master' into multiline-textfield-height-issues
Hukumchand-Narwre Dec 17, 2025
f0dc09b
Merge branch 'master' into multiline-textfield-height-issues
Hukumchand-Narwre Dec 17, 2025
d972091
Merge branch 'master' into multiline-textfield-height-issues
Hukumchand-Narwre Dec 18, 2025
0e49052
Merge branch 'master' into multiline-textfield-height-issues
Hukumchand-Narwre Dec 22, 2025
70c45ac
Merge branch 'master' into multiline-textfield-height-issues
Hukumchand-Narwre Dec 26, 2025
71cb972
Merge branch 'master' into multiline-textfield-height-issues
Hukumchand-Narwre Dec 29, 2025
c7742d4
Merge branch 'master' into multiline-textfield-height-issues
Hukumchand-Narwre Dec 30, 2025
4a6c4b5
Merge branch 'master' into multiline-textfield-height-issues
Hukumchand-Narwre Jan 1, 2026
737074e
Merge branch 'master' into multiline-textfield-height-issues
Hukumchand-Narwre Jan 6, 2026
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
100 changes: 100 additions & 0 deletions packages/mui-material/src/TextareaAutosize/TextareaAutosize.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -503,4 +503,104 @@ describe('<TextareaAutosize />', () => {
// and 2 times in a real browser
expect(handleSelectionChange.callCount).to.lessThanOrEqual(3);
});

it('should not lose textarea value during reflow workaround for controlled component', async () => {
function App() {
const [value, setValue] = React.useState<string>(
'some long text that makes the input start with multiple rows',
);

const handleChange = (event: React.ChangeEvent<any>) => {
setValue(event.target.value);
};

return <TextareaAutosize value={value} onChange={handleChange} />;
}

render(<App />);
const textarea = screen.getByRole<HTMLTextAreaElement>('textbox', {
hidden: false,
});

const originalValue = textarea.value;

act(() => {
textarea.focus();
});

// Trigger textarea height changes
fireEvent.change(textarea, {
target: { value: 'some short text' },
});
await raf();

fireEvent.change(textarea, {
target: { value: originalValue },
});
await raf();

expect(textarea.value).to.equal(originalValue);
});
it('should not lose textarea value during reflow workaround for uncontrolled component', async () => {
function App() {
return (
<TextareaAutosize defaultValue="some long text that makes the input start with multiple rows" />
);
}

render(<App />);
const textarea = screen.getByRole<HTMLTextAreaElement>('textbox', {
hidden: false,
});

const originalValue = textarea.value;

act(() => {
textarea.focus();
});

// Trigger textarea height changes
fireEvent.change(textarea, {
target: { value: 'some short text' },
});
await raf();

fireEvent.change(textarea, {
target: { value: originalValue },
});
await raf();

expect(textarea.value).to.equal(originalValue);
});
it('should not restore selection when textarea is not focused', async () => {
function App() {
const [value, setValue] = React.useState('Initial long text');
const handleChange = (event: React.ChangeEvent<any>) => {
setValue(event.target.value);
};
return (
<div>
<TextareaAutosize value={value} onChange={handleChange} />
<button onClick={() => setValue('Short')}>Change</button>
</div>
);
}

render(<App />);
const textarea = screen.getByRole<HTMLTextAreaElement>('textbox', {
hidden: false,
});
const button = screen.getByRole('button');

// Don't focus the textarea
expect(document.activeElement).not.to.equal(textarea);

// Change value programmatically
fireEvent.click(button);
await raf();

// Should update without error
expect(textarea.value).to.equal('Short');
expect(document.activeElement).not.to.equal(textarea);
});
});
22 changes: 22 additions & 0 deletions packages/mui-material/src/TextareaAutosize/TextareaAutosize.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import useForkRef from '@mui/utils/useForkRef';
import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
import useEventCallback from '@mui/utils/useEventCallback';
import ownerWindow from '@mui/utils/ownerWindow';
import ownerDocument from '@mui/utils/ownerDocument';
import { TextareaAutosizeProps } from './TextareaAutosize.types';

function getStyleValue(value: string) {
Expand Down Expand Up @@ -153,6 +154,27 @@ const TextareaAutosize = React.forwardRef(function TextareaAutosize(
if (heightRef.current !== outerHeightStyle) {
heightRef.current = outerHeightStyle;
textarea.style.height = `${outerHeightStyle}px`;

// This is a workaround for Safari/WebKit not reflowing text when the textarea height changes
// Force Safari to reflow the text by manipulating the textarea value
const isWebKit =
typeof CSS === 'undefined' || !CSS.supports
? false
: CSS.supports('-webkit-backdrop-filter:none');

if (isWebKit) {
const containerDocument = ownerDocument(textarea);
const selectionStart = textarea.selectionStart;
const selectionEnd = textarea.selectionEnd;
const tempValue = textarea.value;
textarea.value = '';
void textarea.offsetHeight;
textarea.value = tempValue;
// Restore selection position
if (containerDocument.activeElement === textarea) {
textarea.setSelectionRange(selectionStart, selectionEnd);
}
}
}
textarea.style.overflow = textareaStyles.overflowing ? 'hidden' : '';
}, [calculateTextareaStyles]);
Expand Down
Loading