[refacto] Introduce stateless TextInputV2 (#5013)

## Context
As discussed with @lucasbordeau and @charlesBochet we are looking at
making low level UI components stateless when possible.
Therefore TextInput should not handle a hotkey state. Instead hotkeys
should be defined in the parent component (as done here in
CreateProfile).

Introducing here TextInputV2 that is stateless and that can already
replace TextInput without any behaviour change everywhere it is used
with `disableHotkey` prop.

## How was it tested?
Locally + Storybook

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
Marie
2024-04-22 11:19:41 +02:00
committed by GitHub
parent 3e8d42f2ed
commit 68662fa543
7 changed files with 284 additions and 214 deletions

View File

@ -1,8 +1,9 @@
import { useCallback } from 'react';
import { useCallback, useState } from 'react';
import { Controller, SubmitHandler, useForm } from 'react-hook-form';
import styled from '@emotion/styled';
import { zodResolver } from '@hookform/resolvers/zod';
import { useRecoilState } from 'recoil';
import { Key } from 'ts-key-enum';
import { z } from 'zod';
import { SubTitle } from '@/auth/components/SubTitle';
@ -13,10 +14,12 @@ import { OnboardingStatus } from '@/auth/utils/getOnboardingStatus';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { ProfilePictureUploader } from '@/settings/profile/components/ProfilePictureUploader';
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
import { H2Title } from '@/ui/display/typography/components/H2Title';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { MainButton } from '@/ui/input/button/components/MainButton';
import { TextInput } from '@/ui/input/components/TextInput';
import { TextInputV2 } from '@/ui/input/components/TextInputV2';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
const StyledContentContainer = styled.div`
@ -123,17 +126,22 @@ export const CreateProfile = () => {
],
);
const [isEditingMode, setIsEditingMode] = useState(false);
useScopedHotkeys(
Key.Enter,
() => {
if (isEditingMode) {
onSubmit(getValues());
}
},
PageHotkeyScope.CreateProfile,
);
if (onboardingStatus !== OnboardingStatus.OngoingProfileCreation) {
return null;
}
const onNameInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === 'Enter') {
event.preventDefault();
onSubmit(getValues());
}
};
return (
<>
<Title withMarginTop={false}>Create profile</Title>
@ -157,17 +165,19 @@ export const CreateProfile = () => {
field: { onChange, onBlur, value },
fieldState: { error },
}) => (
<TextInput
<TextInputV2
autoFocus
label="First Name"
value={value}
onBlur={onBlur}
onFocus={() => setIsEditingMode(true)}
onBlur={() => {
onBlur();
setIsEditingMode(false);
}}
onChange={onChange}
placeholder="Tim"
error={error?.message}
fullWidth
onKeyDown={onNameInputKeyDown}
disableHotkeys
/>
)}
/>
@ -178,16 +188,18 @@ export const CreateProfile = () => {
field: { onChange, onBlur, value },
fieldState: { error },
}) => (
<TextInput
<TextInputV2
label="Last Name"
value={value}
onBlur={onBlur}
onFocus={() => setIsEditingMode(true)}
onBlur={() => {
onBlur();
setIsEditingMode(false);
}}
onChange={onChange}
placeholder="Cook"
error={error?.message}
fullWidth
onKeyDown={onNameInputKeyDown}
disableHotkeys
/>
)}
/>

View File

@ -20,7 +20,7 @@ import { H2Title } from '@/ui/display/typography/components/H2Title';
import { Loader } from '@/ui/feedback/loader/components/Loader.tsx';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { MainButton } from '@/ui/input/button/components/MainButton';
import { TextInput } from '@/ui/input/components/TextInput';
import { TextInputV2 } from '@/ui/input/components/TextInputV2';
import { useActivateWorkspaceMutation } from '~/generated/graphql';
import { isDefined } from '~/utils/isDefined';
@ -141,7 +141,7 @@ export const CreateWorkspace = () => {
field: { onChange, onBlur, value },
fieldState: { error },
}) => (
<TextInput
<TextInputV2
autoFocus
value={value}
placeholder="Apple"
@ -150,7 +150,6 @@ export const CreateWorkspace = () => {
error={error?.message}
onKeyDown={handleKeyDown}
fullWidth
disableHotkeys
/>
)}
/>

View File

@ -18,7 +18,7 @@ import { PASSWORD_REGEX } from '@/auth/utils/passwordRegex';
import { AppPath } from '@/types/AppPath';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { MainButton } from '@/ui/input/button/components/MainButton';
import { TextInput } from '@/ui/input/components/TextInput';
import { TextInputV2 } from '@/ui/input/components/TextInputV2';
import { AnimatedEaseIn } from '@/ui/utilities/animation/components/AnimatedEaseIn';
import {
useUpdatePasswordViaResetTokenMutation,
@ -191,12 +191,11 @@ export const PasswordReset = () => {
}}
>
<StyledInputContainer>
<TextInput
<TextInputV2
autoFocus
value={email}
placeholder="Email"
fullWidth
disableHotkeys
disabled
/>
</StyledInputContainer>
@ -218,7 +217,7 @@ export const PasswordReset = () => {
fieldState: { error },
}) => (
<StyledInputContainer>
<TextInput
<TextInputV2
autoFocus
value={value}
type="password"
@ -227,7 +226,6 @@ export const PasswordReset = () => {
onChange={onChange}
error={error?.message}
fullWidth
disableHotkeys
/>
</StyledInputContainer>
)}