mirror of
https://github.com/lingble/twenty.git
synced 2025-10-31 20:57:55 +00:00
Add blue focus on text inputs (#8343)
We removed the blue focus on phone/domain/array/email floating inputs but we want to keep it in the app settings. <img width="644" alt="Screenshot 2024-11-05 at 15 55 04" src="https://github.com/user-attachments/assets/afcbe6b2-2d6b-4e0d-8397-4268d529127c"> <img width="606" alt="Screenshot 2024-11-05 at 15 55 23" src="https://github.com/user-attachments/assets/004becf8-41e7-45d6-9ad9-9e487b8db8f3"> <img width="351" alt="Screenshot 2024-11-05 at 15 55 33" src="https://github.com/user-attachments/assets/6a4c06e6-04d3-46bf-940b-9fd61ee91995"> <img width="330" alt="Screenshot 2024-11-05 at 15 55 41" src="https://github.com/user-attachments/assets/e6fc8bbd-eca3-47bc-93f1-d6ff8d3d8a13"> <img width="588" alt="Screenshot 2024-11-05 at 15 56 07" src="https://github.com/user-attachments/assets/0d0f5e80-3501-4346-94a1-6ea4b77ee7ba"> <img width="211" alt="Screenshot 2024-11-05 at 15 56 31" src="https://github.com/user-attachments/assets/9cd85f4d-8052-4c6b-a694-84c691c6217d">
This commit is contained in:
@@ -73,6 +73,15 @@ export const SignInUpForm = () => {
|
|||||||
submitSSOEmail,
|
submitSSOEmail,
|
||||||
} = useSignInUp(form);
|
} = useSignInUp(form);
|
||||||
|
|
||||||
|
if (
|
||||||
|
signInUpStep === SignInUpStep.Init &&
|
||||||
|
!authProviders.google &&
|
||||||
|
!authProviders.microsoft &&
|
||||||
|
!authProviders.sso
|
||||||
|
) {
|
||||||
|
continueWithEmail();
|
||||||
|
}
|
||||||
|
|
||||||
const toggleSSOMode = () => {
|
const toggleSSOMode = () => {
|
||||||
if (signInUpStep === SignInUpStep.SSOEmail) {
|
if (signInUpStep === SignInUpStep.SSOEmail) {
|
||||||
continueWithEmail();
|
continueWithEmail();
|
||||||
@@ -155,6 +164,9 @@ export const SignInUpForm = () => {
|
|||||||
Icon={() => <IconGoogle size={theme.icon.size.lg} />}
|
Icon={() => <IconGoogle size={theme.icon.size.lg} />}
|
||||||
title="Continue with Google"
|
title="Continue with Google"
|
||||||
onClick={signInWithGoogle}
|
onClick={signInWithGoogle}
|
||||||
|
variant={
|
||||||
|
signInUpStep === SignInUpStep.Init ? undefined : 'secondary'
|
||||||
|
}
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
<HorizontalSeparator visible={false} />
|
<HorizontalSeparator visible={false} />
|
||||||
@@ -167,6 +179,9 @@ export const SignInUpForm = () => {
|
|||||||
Icon={() => <IconMicrosoft size={theme.icon.size.lg} />}
|
Icon={() => <IconMicrosoft size={theme.icon.size.lg} />}
|
||||||
title="Continue with Microsoft"
|
title="Continue with Microsoft"
|
||||||
onClick={signInWithMicrosoft}
|
onClick={signInWithMicrosoft}
|
||||||
|
variant={
|
||||||
|
signInUpStep === SignInUpStep.Init ? undefined : 'secondary'
|
||||||
|
}
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
<HorizontalSeparator visible={false} />
|
<HorizontalSeparator visible={false} />
|
||||||
@@ -176,6 +191,9 @@ export const SignInUpForm = () => {
|
|||||||
<>
|
<>
|
||||||
<MainButton
|
<MainButton
|
||||||
Icon={() => <IconKey size={theme.icon.size.lg} />}
|
Icon={() => <IconKey size={theme.icon.size.lg} />}
|
||||||
|
variant={
|
||||||
|
signInUpStep === SignInUpStep.Init ? undefined : 'secondary'
|
||||||
|
}
|
||||||
title={
|
title={
|
||||||
signInUpStep === SignInUpStep.SSOEmail
|
signInUpStep === SignInUpStep.SSOEmail
|
||||||
? 'Continue with email'
|
? 'Continue with email'
|
||||||
@@ -282,9 +300,11 @@ export const SignInUpForm = () => {
|
|||||||
</StyledFullWidthMotionDiv>
|
</StyledFullWidthMotionDiv>
|
||||||
)}
|
)}
|
||||||
<MainButton
|
<MainButton
|
||||||
variant="secondary"
|
|
||||||
title={buttonTitle}
|
title={buttonTitle}
|
||||||
type="submit"
|
type="submit"
|
||||||
|
variant={
|
||||||
|
signInUpStep === SignInUpStep.Init ? 'secondary' : 'primary'
|
||||||
|
}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
if (signInUpStep === SignInUpStep.Init) {
|
if (signInUpStep === SignInUpStep.Init) {
|
||||||
continueWithEmail();
|
continueWithEmail();
|
||||||
@@ -301,7 +321,7 @@ export const SignInUpForm = () => {
|
|||||||
setShowErrors(true);
|
setShowErrors(true);
|
||||||
form.handleSubmit(submitCredentials)();
|
form.handleSubmit(submitCredentials)();
|
||||||
}}
|
}}
|
||||||
Icon={() => form.formState.isSubmitting && <Loader />}
|
Icon={() => (form.formState.isSubmitting ? <Loader /> : null)}
|
||||||
disabled={isSubmitButtonDisabled}
|
disabled={isSubmitButtonDisabled}
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export const MultipleFiltersDropdownFilterOnFilterChangedEffect = ({
|
|||||||
setDropdownWidth(280);
|
setDropdownWidth(280);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
setDropdownWidth(160);
|
setDropdownWidth(200);
|
||||||
}
|
}
|
||||||
}, [filterDefinitionUsedInDropdownType, setDropdownWidth]);
|
}, [filterDefinitionUsedInDropdownType, setDropdownWidth]);
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { IconComponent, IconEye, IconEyeOff } from 'twenty-ui';
|
import { IconComponent, IconEye, IconEyeOff, RGBA } from 'twenty-ui';
|
||||||
import { useCombinedRefs } from '~/hooks/useCombinedRefs';
|
import { useCombinedRefs } from '~/hooks/useCombinedRefs';
|
||||||
import { turnIntoEmptyStringIfWhitespacesOnly } from '~/utils/string/turnIntoEmptyStringIfWhitespacesOnly';
|
import { turnIntoEmptyStringIfWhitespacesOnly } from '~/utils/string/turnIntoEmptyStringIfWhitespacesOnly';
|
||||||
|
|
||||||
@@ -33,6 +33,7 @@ const StyledInputContainer = styled.div`
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledInput = styled.input<
|
const StyledInput = styled.input<
|
||||||
@@ -42,12 +43,7 @@ const StyledInput = styled.input<
|
|||||||
border: 1px solid
|
border: 1px solid
|
||||||
${({ theme, error }) =>
|
${({ theme, error }) =>
|
||||||
error ? theme.border.color.danger : theme.border.color.medium};
|
error ? theme.border.color.danger : theme.border.color.medium};
|
||||||
border-bottom-left-radius: ${({ theme, LeftIcon }) =>
|
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||||
!LeftIcon && theme.border.radius.sm};
|
|
||||||
border-right: none;
|
|
||||||
border-left: ${({ LeftIcon }) => LeftIcon && 'none'};
|
|
||||||
border-top-left-radius: ${({ theme, LeftIcon }) =>
|
|
||||||
!LeftIcon && theme.border.radius.sm};
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -57,6 +53,8 @@ const StyledInput = styled.input<
|
|||||||
height: 32px;
|
height: 32px;
|
||||||
outline: none;
|
outline: none;
|
||||||
padding: ${({ theme }) => theme.spacing(2)};
|
padding: ${({ theme }) => theme.spacing(2)};
|
||||||
|
padding-left: ${({ theme, LeftIcon }) =>
|
||||||
|
LeftIcon ? `calc(${theme.spacing(4)} + 16px)` : theme.spacing(2)};
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
&::placeholder,
|
&::placeholder,
|
||||||
@@ -69,6 +67,13 @@ const StyledInput = styled.input<
|
|||||||
&:disabled {
|
&:disabled {
|
||||||
color: ${({ theme }) => theme.font.color.tertiary};
|
color: ${({ theme }) => theme.font.color.tertiary};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
${({ theme }) => {
|
||||||
|
return `box-shadow: 0px 0px 0px 3px ${RGBA(theme.color.blue, 0.1)};
|
||||||
|
border-color: ${theme.color.blue};`;
|
||||||
|
}};
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledErrorHelper = styled.div`
|
const StyledErrorHelper = styled.div`
|
||||||
@@ -79,30 +84,27 @@ const StyledErrorHelper = styled.div`
|
|||||||
|
|
||||||
const StyledLeftIconContainer = styled.div`
|
const StyledLeftIconContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
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};
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding-left: ${({ theme }) => theme.spacing(2)};
|
padding-left: ${({ theme }) => theme.spacing(2)};
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
margin: auto 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledTrailingIconContainer = styled.div<
|
const StyledTrailingIconContainer = styled.div<
|
||||||
Pick<TextInputV2ComponentProps, 'error'>
|
Pick<TextInputV2ComponentProps, 'error'>
|
||||||
>`
|
>`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: ${({ theme }) => theme.background.transparent.lighter};
|
|
||||||
border: 1px solid
|
|
||||||
${({ theme, error }) =>
|
|
||||||
error ? theme.border.color.danger : 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;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding-right: ${({ theme }) => theme.spacing(1)};
|
padding-right: ${({ theme }) => theme.spacing(1)};
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
margin: auto 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledTrailingIcon = styled.div`
|
const StyledTrailingIcon = styled.div`
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const StyledDropdownMenu = styled.div<{
|
|||||||
|
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
z-index: 30;
|
z-index: 30;
|
||||||
width: ${({ width = 160 }) =>
|
width: ${({ width = 200 }) =>
|
||||||
typeof width === 'number' ? `${width}px` : width};
|
typeof width === 'number' ? `${width}px` : width};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { act } from 'react-dom/test-utils';
|
|
||||||
import { expect } from '@storybook/test';
|
import { expect } from '@storybook/test';
|
||||||
import { renderHook } from '@testing-library/react';
|
import { renderHook } from '@testing-library/react';
|
||||||
|
import { act } from 'react-dom/test-utils';
|
||||||
import { RecoilRoot } from 'recoil';
|
import { RecoilRoot } from 'recoil';
|
||||||
|
|
||||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||||
@@ -57,7 +57,7 @@ describe('useDropdown', () => {
|
|||||||
wrapper: Wrapper,
|
wrapper: Wrapper,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result.current.dropdownWidth).toBe(160);
|
expect(result.current.dropdownWidth).toBe(200);
|
||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
result.current.setDropdownWidth(220);
|
result.current.setDropdownWidth(220);
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ export const dropdownWidthComponentState = createComponentState<
|
|||||||
number | undefined
|
number | undefined
|
||||||
>({
|
>({
|
||||||
key: 'dropdownWidthComponentState',
|
key: 'dropdownWidthComponentState',
|
||||||
defaultValue: 160,
|
defaultValue: 200,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import { IconLayoutKanban, IconTable, IconX } from 'twenty-ui';
|
|||||||
|
|
||||||
import { IconPicker } from '@/ui/input/components/IconPicker';
|
import { IconPicker } from '@/ui/input/components/IconPicker';
|
||||||
import { Select } from '@/ui/input/components/Select';
|
import { Select } from '@/ui/input/components/Select';
|
||||||
|
import { TextInputV2 } from '@/ui/input/components/TextInputV2';
|
||||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
|
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
|
||||||
import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput';
|
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
@@ -120,11 +120,11 @@ export const ViewPickerContentCreateMode = () => {
|
|||||||
disableBlur
|
disableBlur
|
||||||
onClose={() => setHotkeyScope(ViewsHotkeyScope.ListDropdown)}
|
onClose={() => setHotkeyScope(ViewsHotkeyScope.ListDropdown)}
|
||||||
/>
|
/>
|
||||||
<DropdownMenuInput
|
<TextInputV2
|
||||||
value={viewPickerInputName}
|
value={viewPickerInputName}
|
||||||
onChange={(event) => {
|
onChange={(value) => {
|
||||||
setViewPickerIsDirty(true);
|
setViewPickerIsDirty(true);
|
||||||
setViewPickerInputName(event.target.value);
|
setViewPickerInputName(value);
|
||||||
}}
|
}}
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { Key } from 'ts-key-enum';
|
|||||||
import { IconChevronLeft } from 'twenty-ui';
|
import { IconChevronLeft } from 'twenty-ui';
|
||||||
|
|
||||||
import { IconPicker } from '@/ui/input/components/IconPicker';
|
import { IconPicker } from '@/ui/input/components/IconPicker';
|
||||||
|
import { TextInputV2 } from '@/ui/input/components/TextInputV2';
|
||||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
|
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
|
||||||
import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput';
|
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
@@ -79,11 +79,11 @@ export const ViewPickerContentEditMode = () => {
|
|||||||
disableBlur
|
disableBlur
|
||||||
onClose={() => setHotkeyScope(ViewsHotkeyScope.ListDropdown)}
|
onClose={() => setHotkeyScope(ViewsHotkeyScope.ListDropdown)}
|
||||||
/>
|
/>
|
||||||
<DropdownMenuInput
|
<TextInputV2
|
||||||
value={viewPickerInputName}
|
value={viewPickerInputName}
|
||||||
onChange={(event) => {
|
onChange={(value) => {
|
||||||
setViewPickerIsDirty(true);
|
setViewPickerIsDirty(true);
|
||||||
setViewPickerInputName(event.target.value);
|
setViewPickerInputName(value);
|
||||||
}}
|
}}
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import { SignInUpForm } from '@/auth/sign-in-up/components/SignInUpForm';
|
|||||||
import { SignInUpMode, useSignInUp } from '@/auth/sign-in-up/hooks/useSignInUp';
|
import { SignInUpMode, useSignInUp } from '@/auth/sign-in-up/hooks/useSignInUp';
|
||||||
import { useSignInUpForm } from '@/auth/sign-in-up/hooks/useSignInUpForm';
|
import { useSignInUpForm } from '@/auth/sign-in-up/hooks/useSignInUpForm';
|
||||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||||
import { AnimatedEaseIn } from 'twenty-ui';
|
|
||||||
import { isDefined } from '~/utils/isDefined';
|
|
||||||
import { SignInUpStep } from '@/auth/states/signInUpStepState';
|
import { SignInUpStep } from '@/auth/states/signInUpStepState';
|
||||||
import { IconLockCustom } from '@ui/display/icon/components/IconLock';
|
import { IconLockCustom } from '@ui/display/icon/components/IconLock';
|
||||||
|
import { AnimatedEaseIn } from 'twenty-ui';
|
||||||
|
import { isDefined } from '~/utils/isDefined';
|
||||||
import { SSOWorkspaceSelection } from './SSOWorkspaceSelection';
|
import { SSOWorkspaceSelection } from './SSOWorkspaceSelection';
|
||||||
|
|
||||||
export const SignInUp = () => {
|
export const SignInUp = () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user