From 9ef6486b06058a10205e546508571a8fe9e36da1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Bosi?= <71827178+bosiraphael@users.noreply.github.com> Date: Mon, 17 Feb 2025 11:10:39 +0100 Subject: [PATCH] Fix autogrowing input glitch (#10224) - Removed unnecessary resize observer - Removed unused component - Fixed autogrowing input glitch # Before https://github.com/user-attachments/assets/a7de71d5-bc6e-495f-851c-18df596749dd # After https://github.com/user-attachments/assets/63588d0e-1122-43fe-b685-3f3a4ec4114e --- .../components/EntityTitleDoubleTextInput.tsx | 90 ------------------- .../ui/input/components/TextInputV2.tsx | 32 +++---- packages/twenty-front/tsup.ui.index.tsx | 1 - .../dimensions/components/AutogrowWrapper.tsx | 38 ++++++++ .../components/ComputeNodeDimensions.tsx | 67 -------------- packages/twenty-ui/src/utilities/index.ts | 2 +- .../src/content/twenty-ui/input/text.mdx | 59 ------------ 7 files changed, 52 insertions(+), 237 deletions(-) delete mode 100644 packages/twenty-front/src/modules/ui/input/components/EntityTitleDoubleTextInput.tsx create mode 100644 packages/twenty-ui/src/utilities/dimensions/components/AutogrowWrapper.tsx delete mode 100644 packages/twenty-ui/src/utilities/dimensions/components/ComputeNodeDimensions.tsx diff --git a/packages/twenty-front/src/modules/ui/input/components/EntityTitleDoubleTextInput.tsx b/packages/twenty-front/src/modules/ui/input/components/EntityTitleDoubleTextInput.tsx deleted file mode 100644 index 9bffbf8c1..000000000 --- a/packages/twenty-front/src/modules/ui/input/components/EntityTitleDoubleTextInput.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import styled from '@emotion/styled'; -import { ChangeEvent } from 'react'; - -import { StyledTextInput as UIStyledTextInput } from '@/ui/field/input/components/TextInput'; -import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; - -import { ComputeNodeDimensions } from 'twenty-ui'; -import { InputHotkeyScope } from '../types/InputHotkeyScope'; - -export type EntityTitleDoubleTextInputProps = { - firstValue: string; - secondValue: string; - firstValuePlaceholder: string; - secondValuePlaceholder: string; - onChange: (firstValue: string, secondValue: string) => void; - className?: string; -}; - -const StyledDoubleTextContainer = styled.div` - align-items: center; - display: flex; - justify-content: center; - text-align: center; -`; - -const StyledTextInput = styled(UIStyledTextInput)` - margin: 0 ${({ theme }) => theme.spacing(0.5)}; - padding: 0; - width: ${({ width }) => (width ? `${width}px` : 'auto')}; - - &:hover:not(:focus) { - background-color: ${({ theme }) => theme.background.transparent.light}; - border-radius: ${({ theme }) => theme.border.radius.sm}; - cursor: pointer; - padding: 0 ${({ theme }) => theme.spacing(1)}; - } -`; - -export const EntityTitleDoubleTextInput = ({ - firstValue, - secondValue, - firstValuePlaceholder, - secondValuePlaceholder, - onChange, - className, -}: EntityTitleDoubleTextInputProps) => { - const { - goBackToPreviousHotkeyScope, - setHotkeyScopeAndMemorizePreviousScope, - } = usePreviousHotkeyScope(); - const handleFocus = () => { - setHotkeyScopeAndMemorizePreviousScope(InputHotkeyScope.TextInput); - }; - const handleBlur = () => { - goBackToPreviousHotkeyScope(); - }; - - return ( - - - {(nodeDimensions) => ( - ) => { - onChange(event.target.value, secondValue); - }} - /> - )} - - - {(nodeDimensions) => ( - ) => { - onChange(firstValue, event.target.value); - }} - /> - )} - - - ); -}; diff --git a/packages/twenty-front/src/modules/ui/input/components/TextInputV2.tsx b/packages/twenty-front/src/modules/ui/input/components/TextInputV2.tsx index e5a93417a..79460bb40 100644 --- a/packages/twenty-front/src/modules/ui/input/components/TextInputV2.tsx +++ b/packages/twenty-front/src/modules/ui/input/components/TextInputV2.tsx @@ -11,12 +11,7 @@ import { useRef, useState, } from 'react'; -import { - ComputeNodeDimensions, - IconComponent, - IconEye, - IconEyeOff, -} from 'twenty-ui'; +import { AutogrowWrapper, IconComponent, IconEye, IconEyeOff } from 'twenty-ui'; import { useCombinedRefs } from '~/hooks/useCombinedRefs'; import { turnIntoEmptyStringIfWhitespacesOnly } from '~/utils/string/turnIntoEmptyStringIfWhitespacesOnly'; @@ -64,6 +59,8 @@ const StyledInput = styled.input< inheritFontStyles ? 'inherit' : theme.font.weight.regular}; height: ${({ sizeVariant }) => sizeVariant === 'sm' ? '20px' : sizeVariant === 'md' ? '28px' : '32px'}; + line-height: ${({ sizeVariant }) => + sizeVariant === 'sm' ? '20px' : sizeVariant === 'md' ? '28px' : '32px'}; outline: none; padding: ${({ theme, sizeVariant, autoGrow }) => autoGrow @@ -80,7 +77,6 @@ const StyledInput = styled.input< width: ${({ theme, width }) => width ? `calc(${width}px + ${theme.spacing(0.5)})` : '100%'}; max-width: ${({ autoGrow }) => (autoGrow ? '100%' : 'none')}; - &::placeholder, &::-webkit-input-placeholder { color: ${({ theme }) => theme.font.color.light}; @@ -296,13 +292,13 @@ const TextInputV2Component = forwardRef< }, ); -const StyledComputeNodeDimensions = styled(ComputeNodeDimensions)<{ +const StyledAutogrowWrapper = styled(AutogrowWrapper)<{ sizeVariant?: TextInputV2Size; }>` border: 1px solid transparent; height: ${({ sizeVariant }) => sizeVariant === 'sm' ? '20px' : sizeVariant === 'md' ? '28px' : '32px'}; - padding: 0 ${({ theme }) => theme.spacing(1)}; + padding: 0 ${({ theme }) => theme.spacing(1.25)}; box-sizing: border-box; `; @@ -313,19 +309,17 @@ const TextInputV2WithAutoGrowWrapper = forwardRef< return ( <> {props.autoGrow ? ( - - {(nodeDimensions) => ( - - )} - + + ) : ( { + return ( + + {node} + {children} + + ); +}; diff --git a/packages/twenty-ui/src/utilities/dimensions/components/ComputeNodeDimensions.tsx b/packages/twenty-ui/src/utilities/dimensions/components/ComputeNodeDimensions.tsx deleted file mode 100644 index 93afe0c8d..000000000 --- a/packages/twenty-ui/src/utilities/dimensions/components/ComputeNodeDimensions.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import styled from '@emotion/styled'; -import { ReactNode, useLayoutEffect, useRef, useState } from 'react'; -import { isDefined } from 'twenty-shared'; - -type ComputeNodeDimensionsProps = { - children: ( - dimensions: { height: number; width: number } | undefined, - ) => ReactNode; - node?: ReactNode; - className?: string; -}; - -const StyledNodeWrapper = styled.span` - pointer-events: none; - visibility: hidden; -`; - -const StyledDiv = styled.div` - max-width: 100%; - position: relative; -`; - -const StyledChildWrapper = styled.div` - left: 0; - position: absolute; - top: 0; -`; - -export const ComputeNodeDimensions = ({ - children, - node = children(undefined), - className, -}: ComputeNodeDimensionsProps) => { - const nodeWrapperRef = useRef(null); - const [nodeDimensions, setNodeDimensions] = useState< - | { - width: number; - height: number; - } - | undefined - >(undefined); - - useLayoutEffect(() => { - if (!nodeWrapperRef.current) { - return; - } - const resizeObserver = new ResizeObserver(() => { - if (isDefined(nodeWrapperRef.current)) { - setNodeDimensions({ - width: nodeWrapperRef.current.offsetWidth, - height: nodeWrapperRef.current.offsetHeight, - }); - } - }); - resizeObserver.observe(nodeWrapperRef.current); - return () => resizeObserver.disconnect(); - }, [nodeWrapperRef]); - - return ( - - {node} - - {nodeDimensions && children(nodeDimensions)} - - - ); -}; diff --git a/packages/twenty-ui/src/utilities/index.ts b/packages/twenty-ui/src/utilities/index.ts index 189ce4fb5..d9ed28a8d 100644 --- a/packages/twenty-ui/src/utilities/index.ts +++ b/packages/twenty-ui/src/utilities/index.ts @@ -9,7 +9,7 @@ export * from './color/utils/stringToHslColor'; export * from './device/getOsControlSymbol'; export * from './device/getOsShortcutSeparator'; export * from './device/getUserDevice'; -export * from './dimensions/components/ComputeNodeDimensions'; +export * from './dimensions/components/AutogrowWrapper'; export * from './responsive/hooks/useIsMobile'; export * from './screen-size/hooks/useScreenSize'; export * from './state/utils/createState'; diff --git a/packages/twenty-website/src/content/twenty-ui/input/text.mdx b/packages/twenty-website/src/content/twenty-ui/input/text.mdx index 3f7172ca9..3df816908 100644 --- a/packages/twenty-website/src/content/twenty-ui/input/text.mdx +++ b/packages/twenty-website/src/content/twenty-ui/input/text.mdx @@ -112,65 +112,6 @@ export const MyComponent = () => { - -## Entity Title Double Text Input - -Displays a pair of text inputs side by side, allowing the user to edit two related values simultaneously. - - - - - - { - - const [firstValue, setFirstValue] = useState( - "First Value" - ); - const [secondValue, setSecondValue] = useState( - "Second Value" - ); - - const handleInputChange = (newFirstValue, newSecondValue) => { - setFirstValue(newFirstValue); - setSecondValue(newSecondValue); - }; - - - return ( - - - - ); -};`} /> - - - - - - - - - - - - - ## Text Area Allows you to create multi-line text inputs.