mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 05:27:52 +00:00
Final style edits to the login and signup flows
This commit is contained in:
Generated
+2325
-4352
File diff suppressed because it is too large
Load Diff
@@ -134,7 +134,7 @@
|
|||||||
"error-login": "Wrong credentials.",
|
"error-login": "Wrong credentials.",
|
||||||
"continue-with-google": "Continue with Google",
|
"continue-with-google": "Continue with Google",
|
||||||
"continue-with-email": "Continue with Email",
|
"continue-with-email": "Continue with Email",
|
||||||
"other-option": "Log in with other option"
|
"other-option": "Log in with another option"
|
||||||
},
|
},
|
||||||
"mfa": {
|
"mfa": {
|
||||||
"title": "Sign Up",
|
"title": "Sign Up",
|
||||||
|
|||||||
@@ -17,28 +17,28 @@ export default function InitialLoginStep({
|
|||||||
<h1 className='text-xl font-medium text-transparent bg-clip-text bg-gradient-to-b from-white to-bunker-200 text-center mb-8' >Login to Infisical</h1>
|
<h1 className='text-xl font-medium text-transparent bg-clip-text bg-gradient-to-b from-white to-bunker-200 text-center mb-8' >Login to Infisical</h1>
|
||||||
<div className='lg:w-1/6 w-1/4 min-w-[20rem] rounded-md'>
|
<div className='lg:w-1/6 w-1/4 min-w-[20rem] rounded-md'>
|
||||||
<Button
|
<Button
|
||||||
colorSchema="primary"
|
colorSchema="primary"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.open('/api/v1/oauth/redirect/google')
|
window.open('/api/v1/oauth/redirect/google')
|
||||||
}}
|
}}
|
||||||
leftIcon={<FontAwesomeIcon icon={faGoogle} className="mr-1" />}
|
leftIcon={<FontAwesomeIcon icon={faGoogle} className="mr-1" />}
|
||||||
className="h-14 w-full mx-0"
|
className="h-14 w-full mx-0"
|
||||||
>
|
>
|
||||||
{t('login.continue-with-google')}
|
{t('login.continue-with-google')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className='lg:w-1/6 w-1/4 min-w-[20rem] text-center rounded-md mt-4'>
|
<div className='lg:w-1/6 w-1/4 min-w-[20rem] text-center rounded-md mt-4'>
|
||||||
<Button
|
<Button
|
||||||
colorSchema="primary"
|
colorSchema="primary"
|
||||||
variant="outline_bg"
|
variant="outline_bg"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsLoginWithEmail(true);
|
setIsLoginWithEmail(true);
|
||||||
}}
|
}}
|
||||||
isFullWidth
|
isFullWidth
|
||||||
className="h-14 w-full mx-0"
|
className="h-14 w-full mx-0"
|
||||||
>
|
>
|
||||||
{t('login.continue-with-email')}
|
{t('login.continue-with-email')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4 text-bunker-400 text-sm flex flex-row">
|
<div className="mt-4 text-bunker-400 text-sm flex flex-row">
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import { useRouter } from 'next/router';
|
|||||||
import attemptLoginMfa from '@app/components/utilities/attemptLoginMfa';
|
import attemptLoginMfa from '@app/components/utilities/attemptLoginMfa';
|
||||||
import { useSendMfaToken } from '@app/hooks/api/auth';
|
import { useSendMfaToken } from '@app/hooks/api/auth';
|
||||||
|
|
||||||
import Button from '../basic/buttons/Button';
|
|
||||||
import Error from '../basic/Error';
|
import Error from '../basic/Error';
|
||||||
|
import { Button } from '../v2';
|
||||||
|
|
||||||
// The style for the verification code input
|
// The style for the verification code input
|
||||||
const props = {
|
const props = {
|
||||||
@@ -115,10 +115,10 @@ export default function MFAStep({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className="h-7/12 mx-auto mb-64 w-max rounded-xl bg-bunker px-8 pt-10 pb-4 drop-shadow-xl md:mb-16">
|
<form className="mx-auto w-max px-8 pb-4 pt-4 md:mb-16">
|
||||||
<p className="text-l flex justify-center text-bunker-300">{t('mfa.step2-message')}</p>
|
<p className="text-l flex justify-center text-bunker-300">{t('mfa.step2-message')}</p>
|
||||||
<p className="text-l my-2 flex justify-center font-semibold text-bunker-300">{email} </p>
|
<p className="text-l my-1 flex justify-center font-semibold text-bunker-300">{email} </p>
|
||||||
<div className="hidden md:block">
|
<div className="hidden md:block w-max min-w-[20rem] mx-auto">
|
||||||
<ReactCodeInput
|
<ReactCodeInput
|
||||||
name=""
|
name=""
|
||||||
inputMode="tel"
|
inputMode="tel"
|
||||||
@@ -129,27 +129,46 @@ export default function MFAStep({
|
|||||||
className="mt-6 mb-2"
|
className="mt-6 mb-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="block md:hidden w-max mt-4 mx-auto">
|
||||||
|
<ReactCodeInput
|
||||||
|
name=""
|
||||||
|
inputMode="tel"
|
||||||
|
type="text"
|
||||||
|
fields={6}
|
||||||
|
onChange={setMfaCode}
|
||||||
|
{...props}
|
||||||
|
className="mt-2 mb-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
{typeof triesLeft === 'number' && (
|
{typeof triesLeft === 'number' && (
|
||||||
<Error text={`${t('mfa.step2-code-error')} ${triesLeft}`} />
|
<Error text={`${t('mfa.step2-code-error')} ${triesLeft}`} />
|
||||||
)}
|
)}
|
||||||
<div className="min-w-28 mx-auto mt-4 mb-2 flex max-h-24 max-w-max flex-col items-center justify-center px-4 text-lg md:p-2">
|
<div className="flex flex-col mt-6 items-center justify-center lg:w-[19%] w-1/4 min-w-[20rem] mt-2 max-w-xs md:max-w-md mx-auto text-sm text-center md:text-left">
|
||||||
<Button text={t('mfa.verify') ?? ''} onButtonPressed={() => handleLoginMfa()} size="lg" />
|
<div className="text-l py-1 text-lg w-full">
|
||||||
</div>
|
<Button
|
||||||
<div className="mx-auto flex max-h-24 w-full max-w-md flex-col items-center justify-center pt-2">
|
onClick={() => handleLoginMfa()}
|
||||||
<div className="flex flex-row items-baseline gap-1 text-sm">
|
size="sm"
|
||||||
<span className="text-bunker-400">{t('mfa.step2-resend-alert')}</span>
|
isFullWidth
|
||||||
<u
|
className='h-14'
|
||||||
className={`font-normal ${isLoadingResend
|
colorSchema="primary"
|
||||||
? 'text-bunker-400'
|
variant="outline_bg"
|
||||||
: 'text-primary-700 duration-200 hover:text-primary'
|
> {String(t('mfa.verify'))} </Button>
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<button disabled={isLoading} onClick={() => handleResendMfaCode()} type="button">
|
|
||||||
{isLoadingResend ? t('mfa.step2-resend-progress') : t('mfa.step2-resend-submit')}
|
|
||||||
</button>
|
|
||||||
</u>
|
|
||||||
</div>
|
</div>
|
||||||
<p className="pb-2 text-sm text-bunker-400">{t('mfa.step2-spam-alert')}</p>
|
</div>
|
||||||
|
<div className="flex flex-col items-center justify-center w-full max-h-24 max-w-md mx-auto pt-2">
|
||||||
|
<div className="flex flex-row items-baseline gap-1 text-sm">
|
||||||
|
<span className="text-bunker-400">{t('signup.step2-resend-alert')}</span>
|
||||||
|
<div className="mt-2 text-bunker-400 text-md flex flex-row">
|
||||||
|
<button disabled={isLoading} onClick={handleResendMfaCode} type="button">
|
||||||
|
<span className='hover:underline hover:underline-offset-4 hover:decoration-primary-700 hover:text-bunker-200 duration-200 cursor-pointer'>
|
||||||
|
{isLoadingResend
|
||||||
|
? t('signup.step2-resend-progress')
|
||||||
|
: t('signup.step2-resend-submit')}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-bunker-400 pb-2">{t('signup.step2-spam-alert')}</p>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,12 +3,11 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
import Button from '@app/components/basic/buttons/Button';
|
|
||||||
import Error from '@app/components/basic/Error';
|
import Error from '@app/components/basic/Error';
|
||||||
import InputField from '@app/components/basic/InputField';
|
|
||||||
import attemptLogin from '@app/components/utilities/attemptLogin';
|
import attemptLogin from '@app/components/utilities/attemptLogin';
|
||||||
|
|
||||||
import SecurityClient from '../utilities/SecurityClient';
|
import SecurityClient from '../utilities/SecurityClient';
|
||||||
|
import { Button, Input } from '../v2';
|
||||||
|
|
||||||
export default function PasswordInputStep({
|
export default function PasswordInputStep({
|
||||||
email,
|
email,
|
||||||
@@ -62,69 +61,58 @@ export default function PasswordInputStep({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={(e) => e.preventDefault()}>
|
<form onSubmit={(e) => e.preventDefault()}>
|
||||||
<div className="h-7/12 mx-auto w-full max-w-md rounded-xl bg-bunker py-4 px-6 pt-8 drop-shadow-xl">
|
<div className="h-full mx-auto w-full max-w-md px-6 pt-8">
|
||||||
<p className="mx-auto mb-6 flex w-max justify-center text-3xl font-semibold text-bunker-100">
|
<p className="mx-auto mb-6 flex w-max justify-center text-xl font-medium text-transparent bg-clip-text bg-gradient-to-b from-white to-bunker-200 text-center mb-8">
|
||||||
{t('login.login')}
|
What’s your Infisical Password?
|
||||||
</p>
|
</p>
|
||||||
<div className="relative mt-6 flex max-h-24 w-full items-center justify-center rounded-lg md:mt-2 md:max-h-28 md:p-2">
|
<div className="relative flex items-center justify-center lg:w-1/6 w-1/4 min-w-[22rem] mx-auto w-full rounded-lg max-h-24 md:max-h-28">
|
||||||
<InputField
|
<div className="flex items-center justify-center w-full rounded-lg max-h-24 md:max-h-28">
|
||||||
label={t('common.password')}
|
<Input
|
||||||
onChangeHandler={setPassword}
|
value={password}
|
||||||
type="password"
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
value={password}
|
type="password"
|
||||||
placeholder=""
|
placeholder="Enter your password..."
|
||||||
isRequired
|
isRequired
|
||||||
autoComplete="current-password"
|
autoComplete="current-password"
|
||||||
id="current-password"
|
id="current-password"
|
||||||
/>
|
className="h-12"
|
||||||
<div className="absolute top-2 right-3 cursor-pointer text-sm text-primary-700 duration-200 hover:text-primary">
|
|
||||||
<Link href="/verify-email">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="ml-1.5 text-sm font-normal text-primary-700 underline-offset-4 duration-200 hover:text-primary"
|
|
||||||
>
|
|
||||||
{t('login.forgot-password')}
|
|
||||||
</button>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{!isLoading && loginError && <Error text={t('login.error-login') ?? ''} />}
|
|
||||||
<div className="mx-auto mt-4 flex max-h-20 w-full max-w-md flex-col items-center justify-center text-sm md:p-2">
|
|
||||||
<div className="text-l m-8 mt-6 px-8 py-3 text-lg">
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
text={t('login.login') ?? ''}
|
|
||||||
onButtonPressed={async () => handleLogin()}
|
|
||||||
loading={isLoading}
|
|
||||||
size="lg"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{!isLoading && loginError && <Error text={t('login.error-login') ?? ''} />}
|
||||||
<div className="mt-4 flex flex-row items-center justify-center md:pb-4">
|
<div className='lg:w-1/6 w-1/4 w-full mx-auto flex items-center justify-center min-w-[22rem] text-center rounded-md mt-4'>
|
||||||
<p className="flex w-max justify-center text-sm text-gray-400">{t('login.need-account')}</p>
|
<Button
|
||||||
<Link href="/signup">
|
colorSchema="primary"
|
||||||
|
variant="outline_bg"
|
||||||
|
onClick={async () => handleLogin()}
|
||||||
|
isFullWidth
|
||||||
|
isLoading={isLoading}
|
||||||
|
className="h-14"
|
||||||
|
>
|
||||||
|
{t('login.login')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className="text-bunker-400 text-xs flex flex-col items-center w-max mx-auto mt-4">
|
||||||
|
<span className='duration-200 max-w-sm text-center px-4'>
|
||||||
|
Infisical Master Password serves as a decryption mechanism so that even Google is not able to access your secrets.
|
||||||
|
</span>
|
||||||
|
<Link href="/verify-email">
|
||||||
|
<span className='hover:underline mt-2 hover:underline-offset-4 hover:decoration-primary-700 hover:text-bunker-200 duration-200 cursor-pointer'>{t('login.forgot-password')}</span>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-row items-center justify-center">
|
||||||
<button
|
<button
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
SecurityClient.setProviderAuthToken('');
|
||||||
|
setProviderAuthToken('');
|
||||||
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
className="ml-1.5 text-sm font-normal text-primary-700 underline-offset-4 duration-200 hover:text-primary"
|
className="text-bunker-400 text-xs hover:underline mt-2 hover:underline-offset-4 hover:decoration-primary-700 hover:text-bunker-200 duration-200 cursor-pointer"
|
||||||
>
|
>
|
||||||
{t('login.create-account')}
|
{t('login.other-option')}
|
||||||
</button>
|
</button>
|
||||||
</Link>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex flex-row items-center justify-center">
|
|
||||||
<button
|
|
||||||
onClick={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
SecurityClient.setProviderAuthToken('');
|
|
||||||
setProviderAuthToken('');
|
|
||||||
}}
|
|
||||||
type="button"
|
|
||||||
className="ml-1.5 text-sm font-normal text-primary-700 underline-offset-4 duration-200 hover:text-primary"
|
|
||||||
>
|
|
||||||
{t('login.other-option')}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ import { usePopUp } from '@app/hooks/usePopUp';
|
|||||||
import addUserToOrg from '@app/pages/api/organization/addUserToOrg';
|
import addUserToOrg from '@app/pages/api/organization/addUserToOrg';
|
||||||
import getWorkspaces from '@app/pages/api/workspace/getWorkspaces';
|
import getWorkspaces from '@app/pages/api/workspace/getWorkspaces';
|
||||||
|
|
||||||
import Button from '../basic/buttons/Button';
|
import { Button, EmailServiceSetupModal } from '../v2';
|
||||||
import { EmailServiceSetupModal } from '../v2';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the last step of the signup flow. People can optionally invite their teammates here.
|
* This is the last step of the signup flow. People can optionally invite their teammates here.
|
||||||
@@ -44,7 +43,7 @@ export default function TeamInviteStep(): JSX.Element {
|
|||||||
<p className="text-center flex justify-center text-bunker-400 md:mx-8 mb-6 mt-4">
|
<p className="text-center flex justify-center text-bunker-400 md:mx-8 mb-6 mt-4">
|
||||||
{t('signup.step5-subtitle')}
|
{t('signup.step5-subtitle')}
|
||||||
</p>
|
</p>
|
||||||
<div className="bg-mineshaft-800 border border-mineshaft-600 w-max mx-auto pt-6 pb-4 px-8 rounded-xl drop-shadow-xl mb-64 md:mb-32">
|
<div className="bg-mineshaft-800 border border-mineshaft-600 w-max mx-auto pt-6 pb-4 px-8 rounded-xl drop-shadow-xl mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="text-bunker-300 font-medium pl-1 pb-1 text-sm">
|
<div className="text-bunker-300 font-medium pl-1 pb-1 text-sm">
|
||||||
<span>Emails</span>
|
<span>Emails</span>
|
||||||
@@ -56,33 +55,37 @@ export default function TeamInviteStep(): JSX.Element {
|
|||||||
placeholder="[email protected], [email protected]..."
|
placeholder="[email protected], [email protected]..."
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row max-w-max min-w-28 items-center justify-center md:p-2 max-h-24 mx-auto text-lg px-4 mt-4 mb-2">
|
<div className="flex flex-row items-end justify-end mt-0 md:mt-4 md:mb-2 w-full md:min-w-[30rem] mt-2 md:max-w-md mx-auto text-sm">
|
||||||
<div
|
|
||||||
onKeyDown={() => null}
|
|
||||||
role="button"
|
|
||||||
tabIndex={0}
|
|
||||||
className="text-md md:text-sm mx-3 text-bunker-300 bg-mineshaft-700 py-3 md:py-3.5 px-5 rounded-md cursor-pointer hover:bg-mineshaft-500 duration-200"
|
|
||||||
onClick={redirectToHome}
|
|
||||||
>
|
|
||||||
{t('signup.step5-skip')}
|
|
||||||
</div>
|
|
||||||
<Button
|
<Button
|
||||||
text={t('signup.step5-send-invites') ?? ''}
|
onClick={() => {
|
||||||
onButtonPressed={() => {
|
|
||||||
if (serverDetails?.emailConfigured) {
|
if (serverDetails?.emailConfigured) {
|
||||||
inviteUsers({ emails })
|
inviteUsers({ emails })
|
||||||
} else {
|
} else {
|
||||||
handlePopUpOpen('setUpEmail');
|
handlePopUpOpen('setUpEmail');
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
size="lg"
|
size="sm"
|
||||||
/>
|
// isFullWidth
|
||||||
|
className='h-10'
|
||||||
|
colorSchema="primary"
|
||||||
|
variant="solid"
|
||||||
|
> {t('signup.step5-send-invites') ?? ''} </Button>
|
||||||
</div>
|
</div>
|
||||||
<EmailServiceSetupModal
|
<EmailServiceSetupModal
|
||||||
isOpen={popUp.setUpEmail?.isOpen}
|
isOpen={popUp.setUpEmail?.isOpen}
|
||||||
onOpenChange={(isOpen) => handlePopUpToggle('setUpEmail', isOpen)}
|
onOpenChange={(isOpen) => handlePopUpToggle('setUpEmail', isOpen)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex flex-row max-w-max min-w-28 items-center justify-center md:p-2 min-w-[20rem] max-h-24 mx-auto text-lg px-4 mt-4 mb-2">
|
||||||
|
<Button
|
||||||
|
onClick={redirectToHome}
|
||||||
|
size="sm"
|
||||||
|
isFullWidth
|
||||||
|
className='h-12'
|
||||||
|
colorSchema="secondary"
|
||||||
|
variant="outline"
|
||||||
|
> {t('signup.step5-skip') ?? 'Skip'} </Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const buttonVariants = cva(
|
|||||||
variants: {
|
variants: {
|
||||||
colorSchema: {
|
colorSchema: {
|
||||||
primary: ['bg-primary', 'text-black', 'border-primary bg-opacity-80 hover:bg-opacity-100'],
|
primary: ['bg-primary', 'text-black', 'border-primary bg-opacity-80 hover:bg-opacity-100'],
|
||||||
secondary: ['bg-mineshaft', 'text-gray-300', 'border-mineshaft hover:bg-opacity-80'],
|
secondary: ['bg-mineshaft', 'text-bunker-300', 'border-mineshaft hover:bg-opacity-80'],
|
||||||
danger: ['bg-red', 'text-white', 'border-red hover:bg-opacity-90'],
|
danger: ['bg-red', 'text-white', 'border-red hover:bg-opacity-90'],
|
||||||
gray: ['bg-bunker-500', 'text-bunker-200']
|
gray: ['bg-bunker-500', 'text-bunker-200']
|
||||||
},
|
},
|
||||||
@@ -96,7 +96,7 @@ const buttonVariants = cva(
|
|||||||
{
|
{
|
||||||
colorSchema: 'secondary',
|
colorSchema: 'secondary',
|
||||||
variant: 'outline',
|
variant: 'outline',
|
||||||
className: 'hover:bg-mineshaft'
|
className: 'border-mineshaft-700 hover:border-mineshaft-500'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
colorSchema: 'danger',
|
colorSchema: 'danger',
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export default function Login() {
|
|||||||
} = useProviderAuth();
|
} = useProviderAuth();
|
||||||
|
|
||||||
if (providerAuthToken && isProviderUserCompleted === false) {
|
if (providerAuthToken && isProviderUserCompleted === false) {
|
||||||
router.push('/signup');
|
// router.push('/signup');
|
||||||
}
|
}
|
||||||
|
|
||||||
const setLanguage = async (to: string) => {
|
const setLanguage = async (to: string) => {
|
||||||
@@ -99,7 +99,7 @@ export default function Login() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-gradient-to-tr from-bunker-600 to-bunker-800 h-screen flex flex-col justify-center pb-28 px-6 ">
|
<div className="bg-gradient-to-tr from-bunker-500 to-bunker-800 h-screen flex flex-col justify-center pb-28 px-6 ">
|
||||||
<Head>
|
<Head>
|
||||||
<title>{t('common.head-title', { title: t('login.title') })}</title>
|
<title>{t('common.head-title', { title: t('login.title') })}</title>
|
||||||
<link rel="icon" href="/infisical.ico" />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
|
|||||||
Reference in New Issue
Block a user