diff --git a/.changeset/chubby-donkeys-write.md b/.changeset/chubby-donkeys-write.md new file mode 100644 index 00000000000..a845151cc84 --- /dev/null +++ b/.changeset/chubby-donkeys-write.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/packages/mosaic/src/features/reverification/reverification.messages.ts b/packages/mosaic/src/features/reverification/reverification.messages.ts index 4c6213dde2f..1df87ac6755 100644 --- a/packages/mosaic/src/features/reverification/reverification.messages.ts +++ b/packages/mosaic/src/features/reverification/reverification.messages.ts @@ -27,7 +27,9 @@ export const reverificationMessages = { emailCode: { description: 'Enter the code sent to your email to continue', formTitle: 'Verification code', - resendButton: 'Didn’t receive a code? Resend', + resendButton: 'Resend', + resendCountdown: 'Resend ({seconds})', + resendText: 'Didn’t receive a code?', title: 'Verification required', }, passkey: { @@ -44,13 +46,17 @@ export const reverificationMessages = { phoneCode: { description: 'Enter the code sent to your phone to continue', formTitle: 'Verification code', - resendButton: 'Didn’t receive a code? Resend', + resendButton: 'Resend', + resendCountdown: 'Resend ({seconds})', + resendText: 'Didn’t receive a code?', title: 'Verification required', }, phoneCodeMfa: { description: 'Enter the code sent to your phone to continue', formTitle: 'Verification code', - resendButton: 'Didn’t receive a code? Resend', + resendButton: 'Resend', + resendCountdown: 'Resend ({seconds})', + resendText: 'Didn’t receive a code?', title: 'Verification required', }, error: { diff --git a/packages/mosaic/src/features/reverification/reverification.view.tsx b/packages/mosaic/src/features/reverification/reverification.view.tsx index 823052e6f59..863a17448b6 100644 --- a/packages/mosaic/src/features/reverification/reverification.view.tsx +++ b/packages/mosaic/src/features/reverification/reverification.view.tsx @@ -1,3 +1,4 @@ +import * as stylex from '@stylexjs/stylex'; import type { Ref } from 'react'; import { Button } from '../../components/button'; @@ -10,7 +11,8 @@ import { SecurityLockSquare } from '../../icons/glyphs/security-lock-square'; import { SecurityPasskey } from '../../icons/glyphs/security-passkey'; import { SecurityPhone } from '../../icons/glyphs/security-phone'; import type { MosaicMessages } from '../../localization'; -import { fill, useMessages } from '../../localization'; +import { fill, rich, useMessages } from '../../localization'; +import { tabularNumbersStyle } from '../../styles/typography.styles'; import { styles } from './reverification.styles'; import type { ReverificationErrorReason, @@ -150,11 +152,22 @@ export function ReverificationView({ pendingLabel: m.verifying, }; const hasAlternatives = methods.length > 0; - const resendLabel = otpChannel === 'phone' ? m.phoneCode.resendButton : m.emailCode.resendButton; + const resendCopy = otpChannel === 'phone' ? m.phoneCode : m.emailCode; const resend = otpChannel === 'email' || otpChannel === 'phone' ? { - label: resendRemainingSeconds ? `${resendLabel} (${resendRemainingSeconds})` : resendLabel, + text: resendCopy.resendText, + label: resendRemainingSeconds ? ( + + {rich(resendCopy.resendCountdown, { + values: { + seconds: {resendRemainingSeconds}, + }, + })} + + ) : ( + resendCopy.resendButton + ), disabled: !canResend || isPending, onClick: onResend, } diff --git a/packages/mosaic/src/features/reverification/steps/reverification-method-picker.tsx b/packages/mosaic/src/features/reverification/steps/reverification-method-picker.tsx index a4ff345ebc4..e8625e5446e 100644 --- a/packages/mosaic/src/features/reverification/steps/reverification-method-picker.tsx +++ b/packages/mosaic/src/features/reverification/steps/reverification-method-picker.tsx @@ -100,18 +100,17 @@ export function ReverificationMethodPicker({ ); })} + {onBack ? ( + + ) : null} - {onBack ? ( - - ) : null} void; } @@ -93,15 +94,18 @@ export function ReverificationOTP({ {errorMessage} {resend ? ( - + + {resend.text}{' '} + + ) : null} diff --git a/packages/mosaic/src/features/user-profile/user-profile-email-section/__tests__/user-profile-add-email.dialog.test.tsx b/packages/mosaic/src/features/user-profile/user-profile-email-section/__tests__/user-profile-add-email.dialog.test.tsx index d7ab0aff862..32e7e381e30 100644 --- a/packages/mosaic/src/features/user-profile/user-profile-email-section/__tests__/user-profile-add-email.dialog.test.tsx +++ b/packages/mosaic/src/features/user-profile/user-profile-email-section/__tests__/user-profile-add-email.dialog.test.tsx @@ -147,7 +147,7 @@ describe('UserProfileAddEmailDialog', () => { const verify = screen.getByRole('button', { name: 'Verify', exact: true }); expect(verify).toHaveAttribute('aria-busy', 'true'); await user.click(verify); - await user.click(screen.getByRole('button', { name: 'Didn’t receive a code? Resend' })); + await user.click(screen.getByRole('button', { name: 'Resend' })); expect(props.onSubmit).not.toHaveBeenCalled(); expect(props.onResend).not.toHaveBeenCalled(); @@ -159,13 +159,15 @@ describe('UserProfileAddEmailDialog', () => { const field = screen.getByRole('textbox', { name: step === 'email' ? 'Email' : 'Verification code' }); expect(field).toHaveAttribute('aria-invalid', 'true'); const describedControl = step === 'verify' ? screen.getByRole('group', { name: 'Verification code' }) : field; - expect(describedControl).toHaveAccessibleDescription('Please try again.'); + expect(describedControl).toHaveAccessibleDescription( + step === 'verify' ? 'Please try again. Didn’t receive a code? Resend' : 'Please try again.', + ); }); it('allows resending only after the countdown and the current request finish', async () => { const user = userEvent.setup(); const { props, rerender } = renderView({ step: 'verify', resendSeconds: 12 }); - await user.click(screen.getByRole('button', { name: 'Didn’t receive a code? Resend (12)' })); + await user.click(screen.getByRole('button', { name: 'Resend (12)' })); expect(props.onResend).not.toHaveBeenCalled(); rerender( @@ -176,7 +178,7 @@ describe('UserProfileAddEmailDialog', () => { /> , ); - await user.click(screen.getByRole('button', { name: 'Didn’t receive a code? Resend' })); + await user.click(screen.getByRole('button', { name: 'Resend' })); expect(props.onResend).toHaveBeenCalledOnce(); rerender( diff --git a/packages/mosaic/src/features/user-profile/user-profile-email-section/user-profile-add-email.dialog.tsx b/packages/mosaic/src/features/user-profile/user-profile-email-section/user-profile-add-email.dialog.tsx index 718e6cd987c..095c9e72684 100644 --- a/packages/mosaic/src/features/user-profile/user-profile-email-section/user-profile-add-email.dialog.tsx +++ b/packages/mosaic/src/features/user-profile/user-profile-email-section/user-profile-add-email.dialog.tsx @@ -16,9 +16,9 @@ import { Otp } from '../../../components/otp'; import { Text } from '../../../components/text'; import { ArrowUpRight } from '../../../icons/glyphs/arrow-up-right'; import { fill, rich, useMessages } from '../../../localization'; +import { tabularNumbersStyle } from '../../../styles/typography.styles'; import type { ReverificationController } from '../../reverification'; import { Reverification } from '../../reverification'; -import { styles as panelStyles } from '../user-profile-profile-panel.styles'; const styles = stylex.create({ ssoConnection: { @@ -253,13 +253,16 @@ function VerifyEmailStep(props: VerifyEmailStepProps) { {props.errorMessage} - + + {m.verify.resendText}{' '} + + @@ -435,7 +438,7 @@ function ResendButton(props: ResendButtonProps) { ) : resendSeconds > 0 ? ( {rich(props.labels.resendCountdown, { - values: { seconds: {resendSeconds} }, + values: { seconds: {resendSeconds} }, })} ) : ( diff --git a/packages/mosaic/src/features/user-profile/user-profile-email-section/user-profile-add-email.messages.ts b/packages/mosaic/src/features/user-profile/user-profile-email-section/user-profile-add-email.messages.ts index 7cd6329823a..ac0bcf3bd32 100644 --- a/packages/mosaic/src/features/user-profile/user-profile-email-section/user-profile-add-email.messages.ts +++ b/packages/mosaic/src/features/user-profile/user-profile-email-section/user-profile-add-email.messages.ts @@ -13,9 +13,10 @@ export const userProfileAddEmailMessages = { submit: 'Verify', pending: 'Verifying', cancel: 'Cancel', - resend: 'Didn’t receive a code? Resend', + resend: 'Resend', + resendText: 'Didn’t receive a code?', resending: 'Sending code…', - resendCountdown: 'Didn’t receive a code? Resend ({seconds})', + resendCountdown: 'Resend ({seconds})', }, link: { title: 'Verify your email', diff --git a/packages/mosaic/src/features/user-profile/user-profile-mfa-section/__tests__/user-profile-mfa.feature.test.tsx b/packages/mosaic/src/features/user-profile/user-profile-mfa-section/__tests__/user-profile-mfa.feature.test.tsx index 44f54d227b6..d7504997b29 100644 --- a/packages/mosaic/src/features/user-profile/user-profile-mfa-section/__tests__/user-profile-mfa.feature.test.tsx +++ b/packages/mosaic/src/features/user-profile/user-profile-mfa-section/__tests__/user-profile-mfa.feature.test.tsx @@ -141,7 +141,7 @@ describe('User profile MFA', () => { expect(screen.getByText('You cannot set your last identification as second factor.')).toBeVisible(), ); expect(screen.getByRole('combobox', { name: /Phone number/ })).toHaveAccessibleDescription( - 'You cannot set your last identification as second factor.', + 'Add a new phone number You cannot set your last identification as second factor.', ); expect(fapi.mfa.phoneUpdates).toHaveLength(0); expect(screen.getByRole('button', { name: 'Back' })).toBeVisible(); diff --git a/packages/mosaic/src/features/user-profile/user-profile-mfa-section/user-profile-add-sms.view.tsx b/packages/mosaic/src/features/user-profile/user-profile-mfa-section/user-profile-add-sms.view.tsx index d3653871c4b..8380cc82e8d 100644 --- a/packages/mosaic/src/features/user-profile/user-profile-mfa-section/user-profile-add-sms.view.tsx +++ b/packages/mosaic/src/features/user-profile/user-profile-mfa-section/user-profile-add-sms.view.tsx @@ -141,17 +141,19 @@ function SelectPhoneStep(props: UserProfileAddSmsViewProps & { inputRef?: Ref {props.errorMessage} + + + - + + {m.verify.resendText}{' '} + + diff --git a/packages/mosaic/src/features/user-profile/user-profile-profile-panel.styles.ts b/packages/mosaic/src/features/user-profile/user-profile-profile-panel.styles.ts index 9de819edbf7..1fcba8de2c0 100644 --- a/packages/mosaic/src/features/user-profile/user-profile-profile-panel.styles.ts +++ b/packages/mosaic/src/features/user-profile/user-profile-profile-panel.styles.ts @@ -3,9 +3,6 @@ import * as stylex from '@stylexjs/stylex'; import { space } from '../../tokens.stylex'; export const styles = stylex.create({ - countdown: { - fontVariantNumeric: 'tabular-nums', - }, contactValue: { gap: space['2'], alignItems: 'center', diff --git a/packages/swingset/src/stories/reverification.stories.tsx b/packages/swingset/src/stories/reverification.stories.tsx index d33912d229d..98558a9f838 100644 --- a/packages/swingset/src/stories/reverification.stories.tsx +++ b/packages/swingset/src/stories/reverification.stories.tsx @@ -417,7 +417,8 @@ function OTPPanel({ resend={ renderResend ? { - label: isResending ? 'Sending a new code…' : 'Didn’t receive a code? Resend', + text: 'Didn’t receive a code?', + label: isResending ? 'Sending a new code…' : 'Resend', disabled: isResending, onClick: () => setValue(''), }