[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

@ -5,7 +5,7 @@ import { Key } from 'ts-key-enum';
import { FieldAddressDraftValue } from '@/object-record/record-field/types/FieldInputDraftValue'; import { FieldAddressDraftValue } from '@/object-record/record-field/types/FieldInputDraftValue';
import { FieldAddressValue } from '@/object-record/record-field/types/FieldMetadata'; import { FieldAddressValue } from '@/object-record/record-field/types/FieldMetadata';
import { CountrySelect } from '@/ui/input/components/internal/country/components/CountrySelect'; import { CountrySelect } from '@/ui/input/components/internal/country/components/CountrySelect';
import { TextInput } from '@/ui/input/components/TextInput'; import { TextInputV2 } from '@/ui/input/components/TextInputV2';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener'; import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener';
import { isDefined } from '~/utils/isDefined'; import { isDefined } from '~/utils/isDefined';
@ -179,7 +179,7 @@ export const AddressInput = ({
return ( return (
<StyledAddressContainer ref={wrapperRef}> <StyledAddressContainer ref={wrapperRef}>
<TextInput <TextInputV2
autoFocus autoFocus
value={internalValue.addressStreet1 ?? ''} value={internalValue.addressStreet1 ?? ''}
ref={inputRefs['addressStreet1']} ref={inputRefs['addressStreet1']}
@ -187,46 +187,41 @@ export const AddressInput = ({
fullWidth fullWidth
onChange={getChangeHandler('addressStreet1')} onChange={getChangeHandler('addressStreet1')}
onFocus={getFocusHandler('addressStreet1')} onFocus={getFocusHandler('addressStreet1')}
disableHotkeys
/> />
<TextInput <TextInputV2
value={internalValue.addressStreet2 ?? ''} value={internalValue.addressStreet2 ?? ''}
ref={inputRefs['addressStreet2']} ref={inputRefs['addressStreet2']}
label="ADDRESS 2" label="ADDRESS 2"
fullWidth fullWidth
onChange={getChangeHandler('addressStreet2')} onChange={getChangeHandler('addressStreet2')}
onFocus={getFocusHandler('addressStreet2')} onFocus={getFocusHandler('addressStreet2')}
disableHotkeys
/> />
<StyledHalfRowContainer> <StyledHalfRowContainer>
<TextInput <TextInputV2
value={internalValue.addressCity ?? ''} value={internalValue.addressCity ?? ''}
ref={inputRefs['addressCity']} ref={inputRefs['addressCity']}
label="CITY" label="CITY"
fullWidth fullWidth
onChange={getChangeHandler('addressCity')} onChange={getChangeHandler('addressCity')}
onFocus={getFocusHandler('addressCity')} onFocus={getFocusHandler('addressCity')}
disableHotkeys
/> />
<TextInput <TextInputV2
value={internalValue.addressState ?? ''} value={internalValue.addressState ?? ''}
ref={inputRefs['addressState']} ref={inputRefs['addressState']}
label="STATE" label="STATE"
fullWidth fullWidth
onChange={getChangeHandler('addressState')} onChange={getChangeHandler('addressState')}
onFocus={getFocusHandler('addressState')} onFocus={getFocusHandler('addressState')}
disableHotkeys
/> />
</StyledHalfRowContainer> </StyledHalfRowContainer>
<StyledHalfRowContainer> <StyledHalfRowContainer>
<TextInput <TextInputV2
value={internalValue.addressPostcode ?? ''} value={internalValue.addressPostcode ?? ''}
ref={inputRefs['addressPostcode']} ref={inputRefs['addressPostcode']}
label="POST CODE" label="POST CODE"
fullWidth fullWidth
onChange={getChangeHandler('addressPostcode')} onChange={getChangeHandler('addressPostcode')}
onFocus={getFocusHandler('addressPostcode')} onFocus={getFocusHandler('addressPostcode')}
disableHotkeys
/> />
<CountrySelect <CountrySelect
onChange={getChangeHandler('addressCountry')} onChange={getChangeHandler('addressCountry')}

View File

@ -1,141 +1,26 @@
import { import { FocusEventHandler, forwardRef, useRef } from 'react';
ChangeEvent,
FocusEventHandler,
ForwardedRef,
forwardRef,
InputHTMLAttributes,
useRef,
useState,
} from 'react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { Key } from 'ts-key-enum'; import { Key } from 'ts-key-enum';
import { IconAlertCircle, IconComponent, IconEye, IconEyeOff } from 'twenty-ui';
import {
TextInputV2,
TextInputV2ComponentProps,
} from '@/ui/input/components/TextInputV2';
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useCombinedRefs } from '~/hooks/useCombinedRefs';
import { InputHotkeyScope } from '../types/InputHotkeyScope'; import { InputHotkeyScope } from '../types/InputHotkeyScope';
const StyledContainer = styled.div<Pick<TextInputComponentProps, 'fullWidth'>>` export type TextInputComponentProps = TextInputV2ComponentProps & {
display: inline-flex;
flex-direction: column;
width: ${({ fullWidth }) => (fullWidth ? `100%` : 'auto')};
`;
const StyledLabel = styled.span`
color: ${({ theme }) => theme.font.color.light};
font-size: ${({ theme }) => theme.font.size.xs};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
margin-bottom: ${({ theme }) => theme.spacing(1)};
`;
const StyledInputContainer = styled.div`
display: flex;
flex-direction: row;
width: 100%;
`;
const StyledInput = styled.input<Pick<TextInputComponentProps, 'fullWidth'>>`
background-color: ${({ theme }) => theme.background.transparent.lighter};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-bottom-left-radius: ${({ theme }) => theme.border.radius.sm};
border-right: none;
border-top-left-radius: ${({ theme }) => theme.border.radius.sm};
box-sizing: border-box;
color: ${({ theme }) => theme.font.color.primary};
display: flex;
flex-grow: 1;
font-family: ${({ theme }) => theme.font.family};
font-weight: ${({ theme }) => theme.font.weight.regular};
height: 32px;
outline: none;
padding: ${({ theme }) => theme.spacing(2)};
width: 100%;
&::placeholder,
&::-webkit-input-placeholder {
color: ${({ theme }) => theme.font.color.light};
font-family: ${({ theme }) => theme.font.family};
font-weight: ${({ theme }) => theme.font.weight.medium};
}
&:disabled {
color: ${({ theme }) => theme.font.color.tertiary};
}
`;
const StyledErrorHelper = styled.div`
color: ${({ theme }) => theme.color.red};
font-size: ${({ theme }) => theme.font.size.xs};
padding: ${({ theme }) => theme.spacing(1)};
`;
const StyledTrailingIconContainer = styled.div`
align-items: center;
background-color: ${({ theme }) => theme.background.transparent.lighter};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-bottom-right-radius: ${({ theme }) => theme.border.radius.sm};
border-left: none;
border-top-right-radius: ${({ theme }) => theme.border.radius.sm};
display: flex;
justify-content: center;
padding-right: ${({ theme }) => theme.spacing(1)};
`;
const StyledTrailingIcon = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.light};
cursor: ${({ onClick }) => (onClick ? 'pointer' : 'default')};
display: flex;
justify-content: center;
`;
const INPUT_TYPE_PASSWORD = 'password';
export type TextInputComponentProps = Omit<
InputHTMLAttributes<HTMLInputElement>,
'onChange' | 'onKeyDown'
> & {
className?: string;
label?: string;
onChange?: (text: string) => void;
fullWidth?: boolean;
disableHotkeys?: boolean; disableHotkeys?: boolean;
error?: string;
RightIcon?: IconComponent;
onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void;
onBlur?: () => void;
}; };
const TextInputComponent = ( const TextInputComponent = ({
{ onFocus,
className, onBlur,
label, disableHotkeys = false,
value, ...props
onChange, }: TextInputComponentProps): JSX.Element => {
onFocus,
onBlur,
onKeyDown,
fullWidth,
error,
required,
type,
disableHotkeys = false,
autoFocus,
placeholder,
disabled,
tabIndex,
RightIcon,
}: TextInputComponentProps,
// eslint-disable-next-line @nx/workspace-component-props-naming
ref: ForwardedRef<HTMLInputElement>,
): JSX.Element => {
const theme = useTheme();
const inputRef = useRef<HTMLInputElement>(null); const inputRef = useRef<HTMLInputElement>(null);
const combinedRef = useCombinedRefs(ref, inputRef);
const { const {
goBackToPreviousHotkeyScope, goBackToPreviousHotkeyScope,
@ -167,57 +52,8 @@ const TextInputComponent = (
{ enabled: !disableHotkeys }, { enabled: !disableHotkeys },
); );
const [passwordVisible, setPasswordVisible] = useState(false); // eslint-disable-next-line react/jsx-props-no-spreading
return <TextInputV2 {...props} onFocus={handleFocus} onBlur={handleBlur} />;
const handleTogglePasswordVisibility = () => {
setPasswordVisible(!passwordVisible);
};
return (
<StyledContainer className={className} fullWidth={fullWidth ?? false}>
{label && <StyledLabel>{label + (required ? '*' : '')}</StyledLabel>}
<StyledInputContainer>
<StyledInput
autoComplete="off"
ref={combinedRef}
tabIndex={tabIndex ?? 0}
onFocus={handleFocus}
onBlur={handleBlur}
type={passwordVisible ? 'text' : type}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
onChange?.(event.target.value);
}}
onKeyDown={onKeyDown}
{...{ autoFocus, disabled, placeholder, required, value }}
/>
<StyledTrailingIconContainer>
{error && (
<StyledTrailingIcon>
<IconAlertCircle size={16} color={theme.color.red} />
</StyledTrailingIcon>
)}
{!error && type === INPUT_TYPE_PASSWORD && (
<StyledTrailingIcon
onClick={handleTogglePasswordVisibility}
data-testid="reveal-password-button"
>
{passwordVisible ? (
<IconEyeOff size={theme.icon.size.md} />
) : (
<IconEye size={theme.icon.size.md} />
)}
</StyledTrailingIcon>
)}
{!error && type !== INPUT_TYPE_PASSWORD && !!RightIcon && (
<StyledTrailingIcon>
<RightIcon size={theme.icon.size.md} />
</StyledTrailingIcon>
)}
</StyledTrailingIconContainer>
</StyledInputContainer>
{error && <StyledErrorHelper>{error}</StyledErrorHelper>}
</StyledContainer>
);
}; };
export const TextInput = forwardRef(TextInputComponent); export const TextInput = forwardRef(TextInputComponent);

View File

@ -0,0 +1,188 @@
import {
ChangeEvent,
FocusEventHandler,
ForwardedRef,
forwardRef,
InputHTMLAttributes,
useRef,
useState,
} from 'react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { IconAlertCircle, IconComponent, IconEye, IconEyeOff } from 'twenty-ui';
import { useCombinedRefs } from '~/hooks/useCombinedRefs';
const StyledContainer = styled.div<
Pick<TextInputV2ComponentProps, 'fullWidth'>
>`
display: inline-flex;
flex-direction: column;
width: ${({ fullWidth }) => (fullWidth ? `100%` : 'auto')};
`;
const StyledLabel = styled.span`
color: ${({ theme }) => theme.font.color.light};
font-size: ${({ theme }) => theme.font.size.xs};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
margin-bottom: ${({ theme }) => theme.spacing(1)};
`;
const StyledInputContainer = styled.div`
display: flex;
flex-direction: row;
width: 100%;
`;
const StyledInput = styled.input<Pick<TextInputV2ComponentProps, 'fullWidth'>>`
background-color: ${({ theme }) => theme.background.transparent.lighter};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-bottom-left-radius: ${({ theme }) => theme.border.radius.sm};
border-right: none;
border-top-left-radius: ${({ theme }) => theme.border.radius.sm};
box-sizing: border-box;
color: ${({ theme }) => theme.font.color.primary};
display: flex;
flex-grow: 1;
font-family: ${({ theme }) => theme.font.family};
font-weight: ${({ theme }) => theme.font.weight.regular};
height: 32px;
outline: none;
padding: ${({ theme }) => theme.spacing(2)};
width: 100%;
&::placeholder,
&::-webkit-input-placeholder {
color: ${({ theme }) => theme.font.color.light};
font-family: ${({ theme }) => theme.font.family};
font-weight: ${({ theme }) => theme.font.weight.medium};
}
&:disabled {
color: ${({ theme }) => theme.font.color.tertiary};
}
`;
const StyledErrorHelper = styled.div`
color: ${({ theme }) => theme.color.red};
font-size: ${({ theme }) => theme.font.size.xs};
padding: ${({ theme }) => theme.spacing(1)};
`;
const StyledTrailingIconContainer = styled.div`
align-items: center;
background-color: ${({ theme }) => theme.background.transparent.lighter};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-bottom-right-radius: ${({ theme }) => theme.border.radius.sm};
border-left: none;
border-top-right-radius: ${({ theme }) => theme.border.radius.sm};
display: flex;
justify-content: center;
padding-right: ${({ theme }) => theme.spacing(1)};
`;
const StyledTrailingIcon = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.light};
cursor: ${({ onClick }) => (onClick ? 'pointer' : 'default')};
display: flex;
justify-content: center;
`;
const INPUT_TYPE_PASSWORD = 'password';
export type TextInputV2ComponentProps = Omit<
InputHTMLAttributes<HTMLInputElement>,
'onChange' | 'onKeyDown'
> & {
className?: string;
label?: string;
onChange?: (text: string) => void;
fullWidth?: boolean;
error?: string;
RightIcon?: IconComponent;
onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void;
onBlur?: FocusEventHandler<HTMLInputElement>;
};
const TextInputV2Component = (
{
className,
label,
value,
onChange,
onFocus,
onBlur,
onKeyDown,
fullWidth,
error,
required,
type,
autoFocus,
placeholder,
disabled,
tabIndex,
RightIcon,
}: TextInputV2ComponentProps,
// eslint-disable-next-line @nx/workspace-component-props-naming
ref: ForwardedRef<HTMLInputElement>,
): JSX.Element => {
const theme = useTheme();
const inputRef = useRef<HTMLInputElement>(null);
const combinedRef = useCombinedRefs(ref, inputRef);
const [passwordVisible, setPasswordVisible] = useState(false);
const handleTogglePasswordVisibility = () => {
setPasswordVisible(!passwordVisible);
};
return (
<StyledContainer className={className} fullWidth={fullWidth ?? false}>
{label && <StyledLabel>{label + (required ? '*' : '')}</StyledLabel>}
<StyledInputContainer>
<StyledInput
autoComplete="off"
ref={combinedRef}
tabIndex={tabIndex ?? 0}
onFocus={onFocus}
onBlur={onBlur}
type={passwordVisible ? 'text' : type}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
onChange?.(event.target.value);
}}
onKeyDown={onKeyDown}
{...{ autoFocus, disabled, placeholder, required, value }}
/>
<StyledTrailingIconContainer>
{error && (
<StyledTrailingIcon>
<IconAlertCircle size={16} color={theme.color.red} />
</StyledTrailingIcon>
)}
{!error && type === INPUT_TYPE_PASSWORD && (
<StyledTrailingIcon
onClick={handleTogglePasswordVisibility}
data-testid="reveal-password-button"
>
{passwordVisible ? (
<IconEyeOff size={theme.icon.size.md} />
) : (
<IconEye size={theme.icon.size.md} />
)}
</StyledTrailingIcon>
)}
{!error && type !== INPUT_TYPE_PASSWORD && !!RightIcon && (
<StyledTrailingIcon>
<RightIcon size={theme.icon.size.md} />
</StyledTrailingIcon>
)}
</StyledTrailingIconContainer>
</StyledInputContainer>
{error && <StyledErrorHelper>{error}</StyledErrorHelper>}
</StyledContainer>
);
};
export const TextInputV2 = forwardRef(TextInputV2Component);

View File

@ -0,0 +1,42 @@
import { useState } from 'react';
import { Meta, StoryObj } from '@storybook/react';
import { ComponentDecorator } from 'twenty-ui';
import {
TextInputV2,
TextInputV2ComponentProps,
} from '@/ui/input/components/TextInputV2';
type RenderProps = TextInputV2ComponentProps;
const Render = (args: RenderProps) => {
const [value, setValue] = useState(args.value);
const handleChange = (text: string) => {
args.onChange?.(text);
setValue(text);
};
// eslint-disable-next-line react/jsx-props-no-spreading
return <TextInputV2 {...args} value={value} onChange={handleChange} />;
};
const meta: Meta<typeof TextInputV2> = {
title: 'UI/Input/TextInputV2',
component: TextInputV2,
decorators: [ComponentDecorator],
args: { placeholder: 'Tim' },
render: Render,
};
export default meta;
type Story = StoryObj<typeof TextInputV2>;
export const Default: Story = {};
export const Filled: Story = {
args: { value: 'Tim' },
};
export const Disabled: Story = {
args: { disabled: true, value: 'Tim' },
};

View File

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

View File

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