Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ux): Update 2fa signin screens/reset PW copy, create HeadingPrimary #17982

Merged
merged 1 commit into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions packages/functional-tests/pages/resetPassword.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ export class ResetPasswordPage extends BaseLayout {
}

async fillOutTotpForm(code: string) {
await this.page.getByLabel('Enter code').fill(code);
await this.page.getByLabel('Enter 6-digit code').fill(code);
return this.page.getByRole('button', { name: 'Confirm' }).click();
}

Expand All @@ -203,9 +203,7 @@ export class ResetPasswordPage extends BaseLayout {
}

async fillOurRecoveryCodeForm(code: string) {
await this.page
.getByLabel('Enter 10-digit backup authentication code')
.fill(code);
await this.page.getByLabel('Enter 10-character code').fill(code);
return this.page.getByRole('button', { name: 'Confirm' }).click();
}

Expand Down
2 changes: 1 addition & 1 deletion packages/functional-tests/pages/signinRecoveryCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class SigninRecoveryCodePage extends BaseTokenCodePage {
get codeInput() {
this.checkPath();
return this.page
.getByLabel('Enter 10-digit backup') // React
.getByLabel('Enter 10-character code') // React
.or(this.page.getByPlaceholder('Enter 10-digit backup')); //Backbone
}
}
2 changes: 1 addition & 1 deletion packages/functional-tests/pages/signinTotpCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class SigninTotpCodePage extends BaseTokenCodePage {
get codeInput() {
this.checkPath();
return this.page
.getByLabel('Enter code') // React
.getByLabel('Enter 6-digit code') // React
.or(this.page.getByPlaceholder('Enter 6-digit code')); //Backbone
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import React from 'react';
import { HeadingPrimary } from '.';
import { Meta } from '@storybook/react';

export default {
title: 'Components/HeadingPrimary',
component: HeadingPrimary,
} as Meta;

export const Default = <HeadingPrimary>Primary heading text</HeadingPrimary>;
13 changes: 13 additions & 0 deletions packages/fxa-settings/src/components/HeadingPrimary/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import React from 'react';

export const HeadingPrimary = ({
vpomerleau marked this conversation as resolved.
Show resolved Hide resolved
children,
marginClass = 'mb-5',
}: {
children: React.ReactNode;
marginClass?: string;
}) => <h1 className={`${marginClass} text-grey-400 text-base`}>{children}</h1>;
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { FtlMsg } from 'fxa-react/lib/utils';
import { CreateRecoveryKeyHandler } from '../../pages/InlineRecoveryKeySetup/interfaces';
import Banner from '../Banner';
import { useFtlMsgResolver } from '../../models';
import { HeadingPrimary } from '../HeadingPrimary';

export const InlineRecoveryKeySetupCreate = ({
createRecoveryKeyHandler,
Expand Down Expand Up @@ -50,11 +51,9 @@ export const InlineRecoveryKeySetupCreate = ({
content={{ localizedHeading: localizedErrorBannerMessage }}
/>
)}
<h1 className="text-grey-400 mb-3 mt-5">
<FtlMsg id="inline-recovery-key-setup-create-header">
Secure your account
</FtlMsg>
</h1>
<FtlMsg id="inline-recovery-key-setup-create-header">
<HeadingPrimary>Secure your account</HeadingPrimary>
</FtlMsg>

<RecoveryKeyImage className="my-6 mx-auto" />

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { InlineRecoveryKeySetupProps } from './interfaces';
import RecoveryKeySetupHint from '../../components/RecoveryKeySetupHint';
import Banner from '../../components/Banner';
import { useFtlMsgResolver } from '../../models';
import { HeadingPrimary } from '../../components/HeadingPrimary';

const viewName = 'inline-recovery-key-setup';

Expand Down Expand Up @@ -43,11 +44,9 @@ export const InlineRecoveryKeySetup = ({
case 3:
return (
<>
<h1 className="text-grey-400">
<FtlMsg id="inline-recovery-key-setup-hint-header">
Security recommendation
</FtlMsg>
</h1>
<FtlMsg id="inline-recovery-key-setup-hint-header">
<HeadingPrimary>Security recommendation</HeadingPrimary>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the heading be the same for all steps? Either "Security recommendation" or "Secure your account"?

Copy link
Contributor Author

@LZoog LZoog Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call out. I remember running this one by Eduardo before - the first step is a recommendation. If they're on step 2, they're in the process of doing the thing.

</FtlMsg>
<RecoveryKeySetupHint
{...{ viewName }}
navigateForward={() => {
Expand All @@ -69,11 +68,9 @@ export const InlineRecoveryKeySetup = ({
),
}}
/>
<h1 className="text-grey-400 mb-3 mt-5">
<FtlMsg id="inline-recovery-key-setup-download-header">
Secure your account
</FtlMsg>
</h1>
<FtlMsg id="inline-recovery-key-setup-download-header">
<HeadingPrimary>Secure your account</HeadingPrimary>
</FtlMsg>
<RecoveryKeyImage className="my-6 mx-auto" />

<h2 className="font-bold text-xl mb-5">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { getLocalizedErrorMessage } from '../../../lib/error-utils';
import { RecoveryKeyImage } from '../../../components/images';
import { Constants } from '../../../lib/constants';
import Banner from '../../../components/Banner';
import { HeadingPrimary } from '../../../components/HeadingPrimary';

// TODO in FXA-7894 use sensitive data client to pass sensitive data
// Depends on FXA-7400
Expand Down Expand Up @@ -138,23 +139,19 @@ const AccountRecoveryConfirmKey = ({
};

return (
<AppLayout>
<AppLayout cardClass="card-base">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self: remember to check for new mentions of "card-base" when finalizing FXA-10613

<FtlMsg id="password-reset-flow-heading">
<h1 className="text-start text-grey-400 text-sm">
Reset your password
</h1>
<HeadingPrimary>Reset your password</HeadingPrimary>
</FtlMsg>
{errorMessage && (
<Banner type="error" content={{ localizedHeading: errorMessage }} />
)}
<RecoveryKeyImage className="mx-auto my-2" />
<FtlMsg id="account-recovery-confirm-key-heading">
<h2 className="card-header text-start mb-2">
Enter your account recovery key
</h2>
<h2 className="card-header mb-2">Enter your account recovery key</h2>
</FtlMsg>
<FtlMsg id="account-recovery-confirm-key-instruction">
<p className="text-start text-sm">
<p className="text-sm">
This key recovers your encrypted browsing data, such as passwords and
bookmarks, from Firefox servers.
</p>
Expand Down Expand Up @@ -190,7 +187,7 @@ const AccountRecoveryConfirmKey = ({
</FtlMsg>

{recoveryKeyHint && (
<div className="bg-grey-50 p-4 text-start text-sm rounded-md">
<div className="bg-grey-50 p-4 text-sm rounded-md">
<FtlMsg id="account-recovery-confirm-key-hint">
<p className="text-grey-500">Your storage hint is:</p>
</FtlMsg>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { FtlMsg } from 'fxa-react/lib/utils';
import ResetPasswordWarning from '../../../components/ResetPasswordWarning';
import { Link, useLocation } from '@reach/router';
import Banner from '../../../components/Banner';
import { HeadingPrimary } from '../../../components/HeadingPrimary';

const CompleteResetPassword = ({
email,
Expand Down Expand Up @@ -63,11 +64,9 @@ const CompleteResetPassword = ({
};

return (
<AppLayout>
<AppLayout cardClass="card-base">
<FtlMsg id="password-reset-flow-heading">
<p className="text-start text-grey-400 text-sm mb-6">
Reset your password
</p>
<HeadingPrimary>Reset your password</HeadingPrimary>
</FtlMsg>

{/*
Expand All @@ -92,11 +91,9 @@ const CompleteResetPassword = ({
<input type="email" value={email} className="hidden" readOnly />

<FtlMsg id="complete-reset-pw-header-v2">
<h1 className="font-semibold text-xl text-start mt-6">
Create a new password
</h1>
<h1 className="font-semibold text-xl mt-6">Create a new password</h1>
</FtlMsg>
<section className="text-start mt-2">
<section className="mt-2">
<FormPasswordWithInlineCriteria
{...{
email,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { ResendStatus } from '../../../lib/types';
import { EmailCodeImage } from '../../../components/images';
import GleanMetrics from '../../../lib/glean';
import Banner, { ResendCodeSuccessBanner } from '../../../components/Banner';
import { HeadingPrimary } from '../../../components/HeadingPrimary';

const ConfirmResetPassword = ({
clearBanners,
Expand Down Expand Up @@ -43,9 +44,9 @@ const ConfirmResetPassword = ({
};

return (
<AppLayout>
<AppLayout cardClass="card-base">
<FtlMsg id="password-reset-flow-heading">
<p className="text-start text-grey-400 text-sm">Reset your password</p>
<HeadingPrimary marginClass="">Reset your password</HeadingPrimary>
</FtlMsg>
{resendStatus === ResendStatus.sent && !hasResendError && (
<ResendCodeSuccessBanner />
Expand All @@ -61,16 +62,14 @@ const ConfirmResetPassword = ({
)}
<EmailCodeImage className="mx-auto" />
<FtlMsg id="confirm-reset-password-with-code-heading">
<h2 className="card-header text-start my-4">Check your email</h2>
<h2 className="card-header my-4">Check your email</h2>
</FtlMsg>
<FtlMsg
id="confirm-reset-password-with-code-instruction"
vars={{ email }}
elems={{ span: spanElement }}
>
<p className="text-start">
We sent a confirmation code to {spanElement}.
</p>
<p>We sent a confirmation code to {spanElement}.</p>
</FtlMsg>
<FormVerifyTotp
codeLength={8}
Expand All @@ -91,7 +90,7 @@ const ConfirmResetPassword = ({
}}
/>
<LinkRememberPassword {...{ email }} clickHandler={signinClickHandler} />
<div className="flex justify-between mt-4 text-sm">
<div className="flex justify-between mt-5 text-sm">
<FtlMsg id="confirm-reset-password-otp-resend-code-button">
<button type="button" className="link-blue" onClick={resendCode}>
Resend code
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
## PasswordResetConfirmTotp Page

confirm-totp-reset-password-header = Reset your password
confirm-totp-reset-password-subheader = Enter your two-factor authentication security code (2FA)
confirm-totp-reset-password-instruction = Check your authenticator app to reset your password.
confirm-totp-reset-password-subheader-v2 = Enter two-step authentication code
confirm-totp-reset-password-instruction-v2 = Check your <strong>authenticator app</strong> to reset your password.
confirm-totp-reset-password-trouble-code = Trouble entering code?
confirm-totp-reset-password-confirm-button = Confirm
confirm-totp-reset-password-input-label = Enter code
confirm-totp-reset-password-use-different-account = Use a different account
confirm-totp-reset-password-input-label-v2 = Enter 6-digit code
confirm-totp-reset-password-use-different-account = Use a different account
confirm-recovery-code-reset-password-input-label = Enter 10-character code
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch that l10n was missing for these strings.

confirm-recovery-code-reset-password-trouble-code = Back
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ describe('ConfirmTotpResetPassword', () => {
).toBeVisible();

expect(screen.getByRole('heading', { level: 2 })).toHaveTextContent(
'Enter your two-factor authentication security code (2FA)'
'Enter two-step authentication code'
);

expect(screen.getByRole('textbox', { name: 'Enter code' })).toBeVisible();

expect(
screen.getByText('Check your authenticator app to reset your password.')
screen.getByRole('textbox', { name: 'Enter 6-digit code' })
).toBeVisible();

screen.getByText('authenticator app', { exact: false });
screen.getByText('to reset your password', { exact: false });
expect(screen.getByRole('button', { name: 'Confirm' })).toBeVisible();
expect(screen.getByText('Trouble entering code?')).toBeVisible();
});
Expand All @@ -47,7 +48,7 @@ describe('ConfirmTotpResetPassword', () => {
renderWithLocalizationProvider(<Subject verifyCode={mockVerifyCode} />);

await waitFor(() =>
screen.getByRole('textbox', { name: 'Enter code' }).click()
screen.getByRole('textbox', { name: 'Enter 6-digit code' }).click()
);
await waitFor(() => {
user.paste('123456');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import FormVerifyCode, {
commonBackupCodeFormAttributes,
FormAttributes,
} from '../../../components/FormVerifyCode';
import { HeadingPrimary } from '../../../components/HeadingPrimary';

export type ConfirmTotpResetPasswordProps = {
verifyCode: (code: string) => Promise<void>;
Expand All @@ -29,8 +30,8 @@ const ConfirmTotpResetPassword = ({
const [showRecoveryCode, setShowRecoveryCode] = useState<boolean>(false);

const totpFormAttributes: FormAttributes = {
inputFtlId: 'confirm-totp-reset-password-input-label',
inputLabelText: 'Enter code',
inputFtlId: 'confirm-totp-reset-password-input-label-v2',
inputLabelText: 'Enter 6-digit code',
pattern: '[0-9]{6}',
maxLength: 6,
submitButtonFtlId: 'confirm-totp-reset-password-confirm-button',
Expand All @@ -39,7 +40,7 @@ const ConfirmTotpResetPassword = ({

const recoveryCodeFormAttributes: FormAttributes = {
inputFtlId: 'confirm-recovery-code-reset-password-input-label',
inputLabelText: 'Enter 10-digit backup authentication code',
inputLabelText: 'Enter 10-character code',
submitButtonFtlId: 'confirm-totp-reset-password-confirm-button',
submitButtonText: 'Confirm',
...commonBackupCodeFormAttributes,
Expand All @@ -54,21 +55,19 @@ const ConfirmTotpResetPassword = ({
<>
{showRecoveryCode ? (
<AppLayout cardClass="card-base">
<h1 className="text-grey-400 mb-6 text-start">
<FtlMsg id="confirm-totp-reset-password-header">
Reset your password
</FtlMsg>
</h1>
<FtlMsg id="confirm-totp-reset-password-header">
<HeadingPrimary>Reset your password</HeadingPrimary>
</FtlMsg>

<h2 className="font-bold text-xl text-start">
<h2 className="font-bold text-xl">
<FtlMsg id="confirm-totp-reset-password-subheader">
Enter your backup recovery code
</FtlMsg>
</h2>

<div className="flex space-x-4">
<img src={protectionShieldIcon} alt="" />
<p className="my-5 text-md text-start">
<p className="my-5 text-md">
<FtlMsg id="confirm-totp-reset-password-instruction">
Check your download or saved backup recovery code.
</FtlMsg>
Expand Down Expand Up @@ -103,25 +102,24 @@ const ConfirmTotpResetPassword = ({
</AppLayout>
) : (
<AppLayout cardClass="card-base">
<h1 className="text-grey-400 mb-6 text-start">
<FtlMsg id="confirm-totp-reset-password-header">
Reset your password
</FtlMsg>
</h1>
<FtlMsg id="confirm-totp-reset-password-header">
<HeadingPrimary>Reset your password</HeadingPrimary>
</FtlMsg>

<h2 className="font-bold text-xl text-start">
<FtlMsg id="confirm-totp-reset-password-subheader">
Enter your two-factor authentication security code (2FA)
<h2 className="font-bold text-xl">
<FtlMsg id="confirm-totp-reset-password-subheader-v2">
Enter two-step authentication code
</FtlMsg>
</h2>

<div className="flex space-x-4">
<img src={protectionShieldIcon} alt="" />
<p className="my-5 text-md text-start">
<FtlMsg id="confirm-totp-reset-password-instruction">
Check your authenticator app to reset your password.
</FtlMsg>
</p>
<FtlMsg id="confirm-totp-reset-password-instruction-v2">
<p className="my-5 text-md">
Check your <strong>authenticator app</strong> to reset your
password.
</p>
</FtlMsg>
</div>

<FormVerifyCode
Expand Down
Loading