Put the passkey and security-key add actions in the card's action row

Both cards now end in the one right-aligned action row with the add
action as the card's primary, like the authenticator card's set-up
button, and both show the same plain empty state. The error line moves
above the row so nothing follows it.
This commit is contained in:
Marc-André Bombeck committed 2026-10-08 20:35:55 +02:00
1 parent f363405df0
commit 161963c82b
2 files changed
+34 -31

No files matched your search

@@ -29,6 +29,8 @@ import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { SettingsCard } from "@/components/settings/settings-card";
import { SettingsCardHeader } from "@/components/settings/_card-header";
import { SettingsCardActions } from "@/components/settings/_card-actions";
import { EmptyState } from "@/components/ui/empty-state";
import { formatDate } from "@/lib/format";
import { useTranslations } from "@/lib/i18n/context";
import { queryKeys } from "@/lib/query-keys";
@@ -193,11 +195,13 @@ export function PasskeyListSection({
description={t("settings.passkeysDescription")}
/>
<div>
<div className="space-y-4">
{!passkeys || passkeys.length === 0 ? (
<p className="text-muted-foreground text-sm">
{t("settings.noPasskeys")}
</p>
<EmptyState
variant="plain"
size="compact"
title={t("settings.noPasskeys")}
/>
) : (
<ul className="space-y-2" data-testid="passkeys-list">
{passkeys.map((pk) => (
@@ -341,6 +345,16 @@ export function PasskeyListSection({
</ul>
)}
{msg && !reauthOpen && (
<div
role="alert"
className="text-destructive flex items-center gap-2 text-sm"
>
<AlertTriangle className="h-4 w-4 shrink-0" />
{msg}
</div>
)}
<AlertDialog
open={reauthOpen}
onOpenChange={(open) => {
@@ -349,11 +363,10 @@ export function PasskeyListSection({
if (open) setMsg(null);
}}
>
<div className="mt-4">
<SettingsCardActions>
<AlertDialogTrigger asChild>
<Button
type="button"
variant="outline"
className="min-h-11 sm:min-h-9"
disabled={add.isPending}
>
@@ -365,7 +378,7 @@ export function PasskeyListSection({
{t("settings.addPasskey")}
</Button>
</AlertDialogTrigger>
</div>
</SettingsCardActions>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>
@@ -475,16 +488,6 @@ export function PasskeyListSection({
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
{msg && !reauthOpen && (
<div
role="alert"
className="text-destructive mt-3 flex items-center gap-2 text-sm"
>
<AlertTriangle className="h-4 w-4 shrink-0" />
{msg}
</div>
)}
</div>
</SettingsCard>
);
@@ -28,6 +28,7 @@ import { Input } from "@/components/ui/input";
import { EmptyState } from "@/components/ui/empty-state";
import { SettingsCard } from "@/components/settings/settings-card";
import { SettingsCardHeader } from "@/components/settings/_card-header";
import { SettingsCardActions } from "@/components/settings/_card-actions";
import { useTranslations } from "@/lib/i18n/context";
import { queryKeys } from "@/lib/query-keys";
import { ApiError, apiDelete, apiPatch, apiPost } from "@/lib/api/api-fetch";
@@ -197,7 +198,7 @@ export function SecurityKeysCard({
description={t("settings.security.keys.description")}
/>
<div>
<div className="space-y-4">
{keys.length === 0 ? (
<EmptyState
variant="plain"
@@ -335,10 +336,19 @@ export function SecurityKeysCard({
</ul>
)}
<div className="mt-4">
{error && (
<div
role="alert"
className="text-destructive flex items-center gap-2 text-sm"
>
<AlertTriangle className="h-4 w-4 shrink-0" />
{error}
</div>
)}
<SettingsCardActions>
<Button
type="button"
variant="outline"
className="min-h-11 sm:min-h-9"
onClick={() => add.mutate(undefined)}
disabled={add.isPending}
@@ -350,7 +360,7 @@ export function SecurityKeysCard({
)}
{t("settings.security.keys.add")}
</Button>
</div>
</SettingsCardActions>
<ExistingFactorReauthDialog
open={reauthOpen}
onOpenChange={(open) => {
@@ -362,16 +372,6 @@ export function SecurityKeysCard({
error={reauthError}
onProof={(proof) => add.mutate(proof)}
/>
{error && (
<div
role="alert"
className="text-destructive mt-3 flex items-center gap-2 text-sm"
>
<AlertTriangle className="h-4 w-4 shrink-0" />
{error}
</div>
)}
</div>
</SettingsCard>
);