diff --git a/src/components/controls/TextArea/TextArea.scss b/src/components/controls/TextArea/TextArea.scss index 72dc5a1ca7..9fea7b8fe9 100644 --- a/src/components/controls/TextArea/TextArea.scss +++ b/src/components/controls/TextArea/TextArea.scss @@ -95,7 +95,7 @@ $block: '.#{variables.$ns}text-area'; &_size { &_s { #{$block}__control { - @include control-mixins.input-control(s); + @include control-mixins.input-control-min-height(s); } &#{$block}_has-clear #{$block}__control { @@ -107,7 +107,7 @@ $block: '.#{variables.$ns}text-area'; &_m { #{$block}__control { - @include control-mixins.input-control(m); + @include control-mixins.input-control-min-height(m); } &#{$block}_has-clear #{$block}__control { @@ -119,7 +119,7 @@ $block: '.#{variables.$ns}text-area'; &_l { #{$block}__control { - @include control-mixins.input-control(l); + @include control-mixins.input-control-min-height(l); } &#{$block}_has-clear #{$block}__control { @@ -131,7 +131,7 @@ $block: '.#{variables.$ns}text-area'; &_xl { #{$block}__control { - @include control-mixins.input-control(xl); + @include control-mixins.input-control-min-height(xl); } &#{$block}_has-clear #{$block}__control { diff --git a/src/components/controls/TextArea/TextAreaControl.tsx b/src/components/controls/TextArea/TextAreaControl.tsx index ad9bbfce6d..adae386307 100644 --- a/src/components/controls/TextArea/TextAreaControl.tsx +++ b/src/components/controls/TextArea/TextAreaControl.tsx @@ -15,19 +15,16 @@ type Props = Omit & const b = block('text-area'); -const calculateLinesByScrollHeight = (args: { - height: number; - paddingTop: number; - paddingBottom: number; - lineHeight: number; -}) => { - const {height, lineHeight} = args; - const paddingTop = Number.isNaN(args.paddingTop) ? 0 : args.paddingTop; - const paddingBottom = Number.isNaN(args.paddingBottom) ? 0 : args.paddingBottom; +const getRowsNumber = (textArea: HTMLTextAreaElement) => { + const lineHeight = parseInt(getComputedStyle(textArea, null).lineHeight, 10); - return (height - paddingTop - paddingBottom) / lineHeight; + return Math.floor(textArea.scrollHeight / lineHeight); }; +// by default this number is 2, but in our component is 1 +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#rows +const DEFAULT_TEXT_AREA_ROWS_NUMBER = 1; + export function TextAreaControl(props: Props) { const { name, @@ -39,7 +36,6 @@ export function TextAreaControl(props: Props) { defaultValue, controlRef, controlProps, - size, rows, minRows = 1, maxRows, @@ -54,38 +50,20 @@ export function TextAreaControl(props: Props) { } = props; const innerControlRef = React.useRef(null); const handleRef = useForkRef(controlRef, innerControlRef); - const textareaRows = rows || minRows; - const innerValue = value || innerControlRef?.current?.value; - const resizeHeight = React.useCallback(() => { - const control = innerControlRef?.current; + const innerValue = value || innerControlRef?.current?.value; - if (control && !rows) { - const controlStyles = getComputedStyle(control); - const lineHeight = parseInt(controlStyles.getPropertyValue('line-height'), 10); - const paddingTop = parseInt(controlStyles.getPropertyValue('padding-top'), 10); - const paddingBottom = parseInt(controlStyles.getPropertyValue('padding-bottom'), 10); - const linesWithCarriageReturn = (innerValue?.match(/\n/g) || []).length + 1; - const linesByScrollHeight = calculateLinesByScrollHeight({ - height: control.scrollHeight, - paddingTop, - paddingBottom, - lineHeight, - }); + React.useEffect(() => { + if (rows || !innerControlRef.current) return; - control.style.height = 'auto'; + innerControlRef.current.setAttribute('rows', DEFAULT_TEXT_AREA_ROWS_NUMBER.toString()); + let currentRowsNumber = getRowsNumber(innerControlRef.current); - if (maxRows && maxRows < Math.max(linesByScrollHeight, linesWithCarriageReturn)) { - control.style.height = `${maxRows * lineHeight + 2 * paddingTop}px`; - } else if (linesWithCarriageReturn > 1 || linesByScrollHeight > 1) { - control.style.height = `${control.scrollHeight}px`; - } - } - }, [rows, maxRows, innerValue]); + if (minRows !== undefined && currentRowsNumber < minRows) currentRowsNumber = minRows; + if (maxRows !== undefined && currentRowsNumber > maxRows) currentRowsNumber = maxRows; - React.useEffect(() => { - resizeHeight(); - }, [resizeHeight, size, value]); + innerControlRef.current.setAttribute('rows', currentRowsNumber.toString()); + }, [rows, minRows, maxRows, innerValue]); return (