Skip to content

Commit

Permalink
fix: UI issue and improved a11y
Browse files Browse the repository at this point in the history
  • Loading branch information
berry-13 committed Feb 12, 2025
1 parent d8b6869 commit ba46e7c
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 33 deletions.
5 changes: 1 addition & 4 deletions client/src/components/Auth/TwoFactorScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,7 @@ const TwoFactorScreen: React.FC = React.memo(() => {
data-testid="login-button"
type="submit"
disabled={isLoading}
className="
w-full rounded-2xl bg-green-600 px-4 py-3 text-sm font-medium text-white
transition-colors hover:bg-green-700 dark:bg-green-600 dark:hover:bg-green-700
"
className="w-full rounded-2xl bg-green-600 px-4 py-3 text-sm font-medium text-white transition-colors hover:bg-green-700 dark:bg-green-600 dark:hover:bg-green-700"
>
{isLoading ? 'Verifying...' : 'Verify'}
</button>
Expand Down
21 changes: 15 additions & 6 deletions client/src/components/Nav/SettingsTabs/Account/Account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import DeleteAccount from './DeleteAccount';
import Avatar from './Avatar';
import EnableTwoFactorItem from './TwoFactorAuthentication';
import BackupCodesItem from './BackupCodesItem';
import { useAuthContext } from '~/hooks';

function Account() {
const user = useAuthContext();

return (
<div className="flex flex-col gap-3 p-1 text-sm text-text-primary">
<div className="pb-3">
Expand All @@ -14,12 +17,18 @@ function Account() {
<div className="pb-3">
<Avatar />
</div>
<div className="pb-3">
<EnableTwoFactorItem />
</div>
<div className="pb-3">
<BackupCodesItem />
</div>
{user?.user?.provider === 'local' && (
<>
<div className="pb-3">
<EnableTwoFactorItem />
</div>
{user?.user?.totpEnabled && (
<div className="pb-3">
<BackupCodesItem />
</div>
)}
</>
)}
<div className="pb-3">
<DeleteAccount />
</div>
Expand Down
57 changes: 39 additions & 18 deletions client/src/components/Nav/SettingsTabs/Account/BackupCodesItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
Button,
Label,
Spinner,
TooltipAnchor,
} from '~/components';
import { useAuthContext, useLocalize } from '~/hooks';
import { useToastContext } from '~/Providers';
Expand Down Expand Up @@ -71,7 +72,9 @@ const BackupCodesItem: React.FC = () => {
<Label className="font-light">{localize('com_ui_backup_codes')}</Label>
</div>
<OGDialogTrigger asChild>
<Button variant="outline">{localize('com_endpoint_show')}</Button>
<Button aria-label="Show Backup Codes" variant="outline">
{localize('com_endpoint_show')}
</Button>
</OGDialogTrigger>
</div>

Expand All @@ -92,38 +95,56 @@ const BackupCodesItem: React.FC = () => {
<div className="grid grid-cols-2 gap-4">
{user.backupCodes.map((code, index) => {
const isUsed = code.used;
const description = `Backup code number ${index + 1}, ${
isUsed
? `used on ${code.usedAt ? new Date(code.usedAt).toLocaleDateString() : 'an unknown date'}`
: 'not used yet'
}`;

return (
<motion.div
key={code.codeHash}
role="listitem"
tabIndex={0}
aria-label={description}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.1 }}
// className="rounded-lg bg-surface-tertiary p-3"
className={`flex flex-col rounded-xl border p-4 backdrop-blur-sm transition-colors ${
onFocus={() => {
const announcement = new CustomEvent('announce', {
detail: { message: description },
});
document.dispatchEvent(announcement);
}}
className={`flex flex-col rounded-xl border p-4 backdrop-blur-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary ${
isUsed
? 'border-red-200 bg-red-50/80 dark:border-red-800 dark:bg-red-900/20'
: 'border-green-200 bg-green-50/80 dark:border-green-800 dark:bg-green-900/20'
} `}
>
<div className="flex items-center justify-between">
<div className="flex items-center justify-between" aria-hidden="true">
<span className="text-sm font-medium text-text-secondary">
#{index + 1}
</span>
<span
className={`rounded-full px-3 py-1 text-sm font-medium ${
isUsed
? 'bg-red-100 text-red-700 dark:bg-red-900/40 dark:text-red-300'
: 'bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-300'
}`}
>
{isUsed ? localize('com_ui_used') : localize('com_ui_not_used')}
</span>
<TooltipAnchor
description={
code.usedAt ? new Date(code.usedAt).toLocaleDateString() : ''
}
disabled={!isUsed}
focusable={false}
render={
<span
className={`rounded-full px-3 py-1 text-sm font-medium ${
isUsed
? 'bg-red-100 text-red-700 dark:bg-red-900/40 dark:text-red-300'
: 'bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-300'
}`}
>
{isUsed ? localize('com_ui_used') : localize('com_ui_not_used')}
</span>
}
/>
</div>
{isUsed && code.usedAt && (
<span className="mt-2 text-xs text-gray-500">
{new Date(code.usedAt).toLocaleDateString()}
</span>
)}
</motion.div>
);
})}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import React, { useState } from 'react';
import { motion } from 'framer-motion';
import { REGEXP_ONLY_DIGITS, REGEXP_ONLY_DIGITS_AND_CHARS } from 'input-otp';
import { Button, InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } from '~/components';
import {
Button,
InputOTP,
InputOTPGroup,
InputOTPSlot,
InputOTPSeparator,
Spinner,
} from '~/components';
import { useLocalize } from '~/hooks';

const fadeAnimation = {
Expand Down Expand Up @@ -35,9 +42,14 @@ export const DisablePhase: React.FC<DisablePhaseProps> = ({ onDisable, isDisabli
>
{useBackup ? (
<InputOTPGroup>
{Array.from({ length: 8 }).map((_, i) => (
<InputOTPSlot key={i} index={i} />
))}
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
<InputOTPSlot index={2} />
<InputOTPSlot index={3} />
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
<InputOTPSlot index={6} />
<InputOTPSlot index={7} />
</InputOTPGroup>
) : (
<>
Expand All @@ -62,7 +74,8 @@ export const DisablePhase: React.FC<DisablePhaseProps> = ({ onDisable, isDisabli
disabled={isDisabling || token.length !== (useBackup ? 8 : 6)}
className="w-full rounded-xl px-6 py-3 transition-all disabled:opacity-50"
>
{localize('com_ui_2fa_disable')}
{isDisabling === true && <Spinner className="mr-2" />}
{isDisabling ? localize('com_ui_disabling') : localize('com_ui_2fa_disable')}
</Button>
<button
onClick={() => setUseBackup(!useBackup)}
Expand Down
3 changes: 3 additions & 0 deletions client/src/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -873,9 +873,12 @@
"com_ui_enter_2fa_code": "Enter the 2FA code from your app",
"com_ui_2fa_code_placeholder": "Enter your 2FA code here",
"com_ui_2fa_invalid": "Invalid two-factor authentication code",
"com_auth_verify_your_identity": "Verify Your Identity",
"com_auth_two_factor": "Check your preferred one-time password application for a code",
"com_ui_2fa_setup": "Setup 2FA",
"com_ui_2fa_enable": "Enable 2FA",
"com_ui_2fa_disable": "Disable 2FA",
"com_ui_disabling": "Disabling...",
"com_ui_2fa_enabled": "2FA has been enabled",
"com_ui_2fa_disabled": "2FA has been disabled",
"com_ui_download_backup": "Download Backup Codes",
Expand Down

0 comments on commit ba46e7c

Please sign in to comment.