Skip to content

Commit

Permalink
Multiline text field component bug (#2511)
Browse files Browse the repository at this point in the history
* chore: fix the odd behaviour of multiline inputs
  • Loading branch information
chloe0592 authored May 12, 2023
1 parent d327adc commit 5469c34
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 41 deletions.
7 changes: 7 additions & 0 deletions .changeset/gold-terms-tell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@commercetools-uikit/localized-multiline-text-input': patch
'@commercetools-uikit/multiline-text-input': patch
'@commercetools-uikit/input-utils': patch
---

Removing resize button of the multiline input and showing 'Expand/Collapse' when there's more than 1 row.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const getTextareaStyles = (props: TMultiLineInputProps) => {
flex: auto;
word-break: break-word;
white-space: pre-wrap;
resize: vertical;
resize: none;
`,
];
return baseStyles;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,35 @@ export type TMultiLineInputProps = {
'aria-errormessage'?: string;
};

// We cache the vertical padding of the element becuase
// it does not change over time so we don't need to
// recalculate it on every height change event.
let _elementVerticalPadding: number | null = null;
const getElementVerticalPadding = (element: Element) => {
if (_elementVerticalPadding === null) {
const computedStyle = getComputedStyle(element);
const paddingTop = parseInt(computedStyle.paddingTop, 10);
const paddingBottom = parseInt(computedStyle.paddingBottom, 10);
_elementVerticalPadding = paddingTop + paddingBottom;
}
return _elementVerticalPadding;
};

const MultilineInput = (props: TMultiLineInputProps) => {
const { onHeightChange } = props;
const ref = useRef<HTMLTextAreaElement | null>(null);

const handleHeightChange = useCallback<
(height: number, meta: TextareaHeightChangeMeta) => void
>(
(height: number, meta: TextareaHeightChangeMeta) => {
const rowCount = Math.floor(
ref.current?.scrollHeight || 0 / meta.rowHeight
);
(_, meta: TextareaHeightChangeMeta) => {
const containerHeight = ref.current!.scrollHeight;
const textHeight =
containerHeight - getElementVerticalPadding(ref.current!);
const rowCount = Math.floor(textHeight / meta.rowHeight);

if (onHeightChange) {
onHeightChange(height, rowCount);
onHeightChange(containerHeight, rowCount);
}
},
[ref, onHeightChange]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,15 @@ const Row = styled.div`
`;

const TranslationInput = (props: TranslationInputProps) => {
const [contentRowCount, setContentRowCount] = useState(
TranslationInput.MIN_ROW_COUNT
);
const [inputHasSeveralRows, setInputHasSeveralRows] = useState(false);

const handleHeightChange = useCallback(
(_, rowCount) => {
setContentRowCount(rowCount);
// This checks if the content in the textarea is greater than one row. If it is, then the toggle button will be shown.
// This is to prevent the toggle button from showing when there is not enough content to expand/collapse.
setInputHasSeveralRows(rowCount > 1);
},
[setContentRowCount]
[setInputHasSeveralRows]
);

const { onChange } = props;
Expand Down Expand Up @@ -122,11 +122,6 @@ const TranslationInput = (props: TranslationInputProps) => {
if (onFocus) onFocus();
}, [props.isCollapsed, onFocus, onToggle]);

// This checks if the content in the textarea overflows the minimum
// amount of lines it should have when collapsed
const contentExceedsShownRows =
contentRowCount > TranslationInput.MIN_ROW_COUNT;

const shouldToggleButtonTakeSpace =
/*
- if hasLanguagesControl and there are no errors/warnings to display
Expand All @@ -136,9 +131,7 @@ const TranslationInput = (props: TranslationInputProps) => {
then it can be placed statically because it will then be a sibling to the error/warning message
and LocalizedInputToggle is placed below the errors/warnings.
*/
(!props.isCollapsed &&
contentExceedsShownRows &&
!props.hasLanguagesControl) ||
(!props.isCollapsed && inputHasSeveralRows && !props.hasLanguagesControl) ||
props.error ||
props.warning;

Expand Down Expand Up @@ -214,7 +207,7 @@ const TranslationInput = (props: TranslationInputProps) => {
);
return null;
})()}
{!props.isCollapsed && contentExceedsShownRows && (
{!props.isCollapsed && inputHasSeveralRows && (
<>
<LeftColumn />
<RightColumn>
Expand Down Expand Up @@ -248,9 +241,4 @@ const TranslationInput = (props: TranslationInputProps) => {

TranslationInput.displayName = 'TranslationInput';

// The minimum ammount of rows the MultilineTextInput will show.
// When the input is closed, this is used as the maximum row count as well
// so that the input "collapses".
TranslationInput.MIN_ROW_COUNT = 1;

export default TranslationInput;
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,8 @@ const defaultProps: Pick<

const MultilineTextInput = (props: TMultilineTextInputProps) => {
const intl = useIntl();

const [contentRowCount, setContentRowCount] = useState<number>(
MultilineTextInput.MIN_ROW_COUNT
);
const [shouldRenderToggleButton, setShouldRenderToggleButton] =
useState(false);

const [isOpen, toggle] = useToggleState(props.defaultExpandMultilineText);

Expand All @@ -130,16 +128,13 @@ const MultilineTextInput = (props: TMultilineTextInputProps) => {
(height: number, rowCount: number) => void
>(
(_, rowCount) => {
setContentRowCount(rowCount);
// This checks if the content in the textarea is greater than one row. If it is, then the toggle button will be shown.
// This is to prevent the toggle button from showing when there is not enough content to expand/collapse.
setShouldRenderToggleButton(rowCount > 1);
},
[setContentRowCount]
[setShouldRenderToggleButton]
);

// This checks if the content in the textarea overflows the minimum
// amount of lines it should have when collapsed
const shouldRenderToggleButton =
contentRowCount > MultilineTextInput.MIN_ROW_COUNT;

return (
<Constraints.Horizontal max={props.horizontalConstraint}>
<Stack scale="xs">
Expand Down Expand Up @@ -196,11 +191,6 @@ const MultilineTextInput = (props: TMultilineTextInputProps) => {

MultilineTextInput.displayName = 'MultilineTextInput';

// The minimum ammount of rows the MultilineTextInput will show.
// When the input is closed, this is used as the maximum row count as well
// so that the input "collapses".
MultilineTextInput.MIN_ROW_COUNT = 1;

MultilineTextInput.isEmpty = (value: TMultilineTextInputProps['value']) =>
!value || value.trim().length === 0;
MultilineTextInput.defaultProps = defaultProps;
Expand Down

1 comment on commit 5469c34

@vercel
Copy link

@vercel vercel bot commented on 5469c34 May 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.