From 86d80d2c041b19022ccc0657383a46b0dbdd52d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Wed, 1 Jul 2026 23:44:55 +0200 Subject: [PATCH] refactor(admin): migrate section cards onto the shared card primitives The admin tree hand-rolled its card surfaces and stepped padding at sm: instead of md:, so it read denser than every other route on a tablet. Move the sections onto SettingsCard/SettingsCardHeader and the mini-rows onto ListRow; no behaviour, data, or copy changes. --- .../api-token-overview-responsive.test.tsx | 9 +- .../user-management-responsive.test.tsx | 4 +- src/components/admin/ai-quality-section.tsx | 5 +- .../admin/ai-server-key-section.tsx | 8 +- .../admin/api-token-overview-section.tsx | 85 ++++++++++-------- .../admin/app-log-preview-section.tsx | 5 +- src/components/admin/assistant-section.tsx | 5 +- src/components/admin/backups-section.tsx | 89 ++++++++++--------- .../admin/coach-feedback-section.tsx | 5 +- .../admin/general-settings-section.tsx | 5 +- src/components/admin/glitchtip-section.tsx | 5 +- src/components/admin/host-metrics-chart.tsx | 29 ++---- .../admin/login-overview-section.tsx | 5 +- .../admin/module-availability-section.tsx | 5 +- src/components/admin/recent-audit-preview.tsx | 8 +- src/components/admin/reminders-section.tsx | 9 +- src/components/admin/services-section.tsx | 5 +- .../admin/system-status-section.tsx | 9 +- .../admin/system-status-summary.tsx | 7 +- src/components/admin/umami-section.tsx | 5 +- .../admin/user-management-section.tsx | 63 +++++++------ src/components/admin/version-tile-section.tsx | 8 +- .../admin/web-push-vapid-section.tsx | 5 +- 23 files changed, 200 insertions(+), 183 deletions(-) diff --git a/src/components/admin/__tests__/api-token-overview-responsive.test.tsx b/src/components/admin/__tests__/api-token-overview-responsive.test.tsx index 4ab40afa5..16a1eeff5 100644 --- a/src/components/admin/__tests__/api-token-overview-responsive.test.tsx +++ b/src/components/admin/__tests__/api-token-overview-responsive.test.tsx @@ -115,11 +115,12 @@ describe("ApiTokenOverviewSection — responsive", () => { expect(html).toContain("All"); }); - it("uses a smaller card padding on mobile (p-4 sm:p-6)", () => { + it("uses a smaller card padding on mobile (p-4 md:p-6)", () => { const html = render(); - // The card root carries the responsive padding to leave more room - // for content within a 393 CSS-px viewport. - expect(html).toMatch(/class="[^"]*\bp-4\b[^"]*sm:p-6/); + // The card root carries the shared SettingsCard padding contract + // (`p-4 md:p-6`) to leave more room for content within a 393 CSS-px + // viewport while stepping up only from `md`, not `sm`. + expect(html).toMatch(/class="[^"]*\bp-4\b[^"]*md:p-6/); }); it("desktop date cells drop whitespace-nowrap (v1.4.22 C2 5th-attempt fix)", () => { diff --git a/src/components/admin/__tests__/user-management-responsive.test.tsx b/src/components/admin/__tests__/user-management-responsive.test.tsx index 3dc75b13d..60c5dedb9 100644 --- a/src/components/admin/__tests__/user-management-responsive.test.tsx +++ b/src/components/admin/__tests__/user-management-responsive.test.tsx @@ -115,9 +115,9 @@ describe("UserManagementSection — mobile responsive", () => { expect(mobileSlice).toContain("Force logout"); }); - it("uses smaller card padding on mobile (p-4 sm:p-6)", () => { + it("uses smaller card padding on mobile (p-4 md:p-6)", () => { const html = render(); - expect(html).toMatch(/class="[^"]*\bp-4\b[^"]*sm:p-6/); + expect(html).toMatch(/class="[^"]*\bp-4\b[^"]*md:p-6/); }); it("wraps the filter pills below the title on narrow viewports", () => { diff --git a/src/components/admin/ai-quality-section.tsx b/src/components/admin/ai-quality-section.tsx index c43f24e3f..3b0e75ab0 100644 --- a/src/components/admin/ai-quality-section.tsx +++ b/src/components/admin/ai-quality-section.tsx @@ -21,6 +21,7 @@ import { useQuery } from "@tanstack/react-query"; import { Sparkles, Loader2 } from "lucide-react"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { useTranslations, useFormatters } from "@/lib/i18n/context"; import { queryKeys } from "@/lib/query-keys"; @@ -75,7 +76,7 @@ export function AiQualitySection() { // resolves. Mirrors (header outside the // fetch-state branch). return ( -
+
)} - + ); } diff --git a/src/components/admin/ai-server-key-section.tsx b/src/components/admin/ai-server-key-section.tsx index 5057b824d..16767c2a3 100644 --- a/src/components/admin/ai-server-key-section.tsx +++ b/src/components/admin/ai-server-key-section.tsx @@ -9,6 +9,7 @@ import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { useTranslations } from "@/lib/i18n/context"; import { queryKeys } from "@/lib/query-keys"; @@ -92,10 +93,7 @@ export function AiServerKeySection() { } return ( -
+
- + ); } diff --git a/src/components/admin/api-token-overview-section.tsx b/src/components/admin/api-token-overview-section.tsx index 114c2917f..aa3af44c2 100644 --- a/src/components/admin/api-token-overview-section.tsx +++ b/src/components/admin/api-token-overview-section.tsx @@ -11,7 +11,9 @@ import { TooltipTrigger, } from "@/components/ui/tooltip"; import { formatDate, formatDateTime } from "@/lib/format"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; +import { ListRow } from "@/components/ui/list-row"; import { useTranslations } from "@/lib/i18n/context"; import { queryKeys } from "@/lib/query-keys"; import { type ApiTokenInfo } from "./_shared"; @@ -157,7 +159,7 @@ export function ApiTokenOverviewSection() { }); return ( -
+ {tokens.map((token) => { return ( -
  • -
    -
    -
    +
  • +
    +
    +
    + + +
    -
    -
    -
  • -
    - {token.permissions.map((p) => ( - - {p === "*" ? t("admin.tokenPermissionAll") : p} - - ))} -
    -

    - {t("admin.tokenLastUsed")}:{" "} - {token.lastUsedAt - ? formatDateTime(token.lastUsedAt) - : t("admin.tokenNeverUsed")} -

    -

    - {t("admin.tokenCreated")}: {formatDate(token.createdAt)} -

    - +
    + {token.permissions.map((p) => ( + + {p === "*" ? t("admin.tokenPermissionAll") : p} + + ))} +
    +

    + {t("admin.tokenLastUsed")}:{" "} + {token.lastUsedAt + ? formatDateTime(token.lastUsedAt) + : t("admin.tokenNeverUsed")} +

    +

    + {t("admin.tokenCreated")}: {formatDate(token.createdAt)} +

    + + ); })} )} - + ); } diff --git a/src/components/admin/app-log-preview-section.tsx b/src/components/admin/app-log-preview-section.tsx index 61a46d8a0..995619b62 100644 --- a/src/components/admin/app-log-preview-section.tsx +++ b/src/components/admin/app-log-preview-section.tsx @@ -46,6 +46,7 @@ import { DialogTitle, } from "@/components/ui/dialog"; import { formatDateTime } from "@/lib/format"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { useTranslations } from "@/lib/i18n/context"; import { queryKeys } from "@/lib/query-keys"; @@ -115,7 +116,7 @@ export function AppLogPreviewSection() { const events = data?.events ?? []; return ( -
    + -
    + ); } diff --git a/src/components/admin/assistant-section.tsx b/src/components/admin/assistant-section.tsx index 8b49aaee4..a54adbe21 100644 --- a/src/components/admin/assistant-section.tsx +++ b/src/components/admin/assistant-section.tsx @@ -4,6 +4,7 @@ import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { Sparkles } from "lucide-react"; import { toast } from "sonner"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { useTranslations } from "@/lib/i18n/context"; import { queryKeys } from "@/lib/query-keys"; @@ -99,7 +100,7 @@ export function AssistantSection() { const disabledSubs = !masterOn || mutation.isPending; return ( -
    +
    - + ); } diff --git a/src/components/admin/backups-section.tsx b/src/components/admin/backups-section.tsx index f63244557..bc01e77e5 100644 --- a/src/components/admin/backups-section.tsx +++ b/src/components/admin/backups-section.tsx @@ -39,7 +39,9 @@ import { Button } from "@/components/ui/button"; import { EmptyState } from "@/components/ui/empty-state"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; +import { ListRow } from "@/components/ui/list-row"; import { useFormatters, useTranslations } from "@/lib/i18n/context"; import { queryKeys } from "@/lib/query-keys"; import type { BackupRow, BackupsList } from "@/types/backups"; @@ -332,7 +334,7 @@ export function BackupsSection() { } return ( -
    + {/* v1.18.1 E3 — the snapshot count leads (numbers first), the "Run now" button follows, and the explainer + docs link move into the header's description slot. Previously the description @@ -550,48 +552,51 @@ export function BackupsSection() { data-testid="admin-backups-mobile-list" > {rows.map((row) => ( -
  • -
    - {row.username} - - {formatBackupType(row.type, t)} - -
    -

    - {t("admin.section.backups.colSize")}:{" "} - {formatBytes(row.sizeBytes, fmt)} ·{" "} - {fmt.dateTime(row.createdAt)} -

    -
    - - restore.mutate(row)} - /> -
    -
  • +
  • +
    + {row.username} + + {formatBackupType(row.type, t)} + +
    +

    + {t("admin.section.backups.colSize")}:{" "} + {formatBytes(row.sizeBytes, fmt)} ·{" "} + {fmt.dateTime(row.createdAt)} +

    +
    + + restore.mutate(row)} + /> +
    +
  • + ))} @@ -602,6 +607,6 @@ export function BackupsSection() {

    )} - + ); } diff --git a/src/components/admin/coach-feedback-section.tsx b/src/components/admin/coach-feedback-section.tsx index c78619301..0308625c4 100644 --- a/src/components/admin/coach-feedback-section.tsx +++ b/src/components/admin/coach-feedback-section.tsx @@ -21,6 +21,7 @@ import { useQuery } from "@tanstack/react-query"; import { Loader2, Sparkles } from "lucide-react"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { useTranslations, useFormatters } from "@/lib/i18n/context"; import { queryKeys } from "@/lib/query-keys"; @@ -70,7 +71,7 @@ export function CoachFeedbackSection() { // /admin/coach-feedback. Mirrors the canonical structure used by // (header outside the fetch-state branch). return ( -
    +
    )} - + ); } diff --git a/src/components/admin/general-settings-section.tsx b/src/components/admin/general-settings-section.tsx index 62cb0d438..008edf4fb 100644 --- a/src/components/admin/general-settings-section.tsx +++ b/src/components/admin/general-settings-section.tsx @@ -2,6 +2,7 @@ import { useMemo } from "react"; import { Settings } from "lucide-react"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { useTranslations } from "@/lib/i18n/context"; import { NativeSelect } from "@/components/ui/native-select"; @@ -26,7 +27,7 @@ export function GeneralSettingsSection() { const currentDefaultTz = settings?.defaultUserTimezone ?? ""; return ( -
    +
    - + ); } diff --git a/src/components/admin/glitchtip-section.tsx b/src/components/admin/glitchtip-section.tsx index c14a18cc8..a608f876c 100644 --- a/src/components/admin/glitchtip-section.tsx +++ b/src/components/admin/glitchtip-section.tsx @@ -4,6 +4,7 @@ import { useState } from "react"; import { useMutation } from "@tanstack/react-query"; import { AlertTriangle, Loader2 } from "lucide-react"; import { toast } from "sonner"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; @@ -69,7 +70,7 @@ export function GlitchtipSection() { } return ( -
    +
    - + ); } diff --git a/src/components/admin/host-metrics-chart.tsx b/src/components/admin/host-metrics-chart.tsx index 7188f90f3..0ef11da16 100644 --- a/src/components/admin/host-metrics-chart.tsx +++ b/src/components/admin/host-metrics-chart.tsx @@ -39,6 +39,7 @@ import { useMemo } from "react"; import { useFormatters, useTranslations } from "@/lib/i18n/context"; import { queryKeys } from "@/lib/query-keys"; import { Skeleton } from "@/components/ui/skeleton"; +import { SettingsCard } from "@/components/settings/settings-card"; import { apiGet } from "@/lib/api/api-fetch"; interface HostMetricsApiSample { @@ -156,10 +157,7 @@ export function HostMetricsChart() { // jump when data lands. Animated only when motion isn't reduced. if (isLoading) { return ( -
    +

    {t("admin.hostMetrics.title")} @@ -169,16 +167,13 @@ export function HostMetricsChart() {

    -
    + ); } if (isError) { return ( -
    +

    {t("admin.hostMetrics.title")}

    @@ -188,7 +183,7 @@ export function HostMetricsChart() { > {t("admin.hostMetrics.loadError")}

    -
    + ); } @@ -197,10 +192,7 @@ export function HostMetricsChart() { // instead of an empty plot. if (rows.length === 0) { return ( -
    +

    {t("admin.hostMetrics.title")} @@ -212,15 +204,12 @@ export function HostMetricsChart() {

    {t("admin.hostMetrics.empty")}

    -

    + ); } return ( -
    +

    {t("admin.hostMetrics.title")} @@ -354,6 +343,6 @@ export function HostMetricsChart() {

    -
    + ); } diff --git a/src/components/admin/login-overview-section.tsx b/src/components/admin/login-overview-section.tsx index 54a6059fc..601a67d80 100644 --- a/src/components/admin/login-overview-section.tsx +++ b/src/components/admin/login-overview-section.tsx @@ -25,6 +25,7 @@ import { SelectValue, } from "@/components/ui/select"; import { formatDateTime } from "@/lib/format"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { useTranslations } from "@/lib/i18n/context"; import { queryKeys } from "@/lib/query-keys"; @@ -219,7 +220,7 @@ export function LoginOverviewSection() { } return ( -
    + )}
    - + ); } diff --git a/src/components/admin/module-availability-section.tsx b/src/components/admin/module-availability-section.tsx index c552c0245..e578d451f 100644 --- a/src/components/admin/module-availability-section.tsx +++ b/src/components/admin/module-availability-section.tsx @@ -4,6 +4,7 @@ import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { ToggleLeft } from "lucide-react"; import { toast } from "sonner"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { useTranslations } from "@/lib/i18n/context"; import { queryKeys } from "@/lib/query-keys"; @@ -87,7 +88,7 @@ export function ModuleAvailabilitySection() { const availability = data?.availability; return ( -
    + -
    + ); } diff --git a/src/components/admin/recent-audit-preview.tsx b/src/components/admin/recent-audit-preview.tsx index 486afb127..6f112b24c 100644 --- a/src/components/admin/recent-audit-preview.tsx +++ b/src/components/admin/recent-audit-preview.tsx @@ -20,6 +20,7 @@ import { } from "lucide-react"; import { EmptyState } from "@/components/ui/empty-state"; import { formatDateTime } from "@/lib/format"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { useTranslations } from "@/lib/i18n/context"; import { queryKeys } from "@/lib/query-keys"; @@ -53,10 +54,7 @@ export function RecentAuditPreview() { const entries = data?.entries ?? []; return ( -
    + )} -
    + ); } diff --git a/src/components/admin/reminders-section.tsx b/src/components/admin/reminders-section.tsx index 18dae6626..3c8b39f0b 100644 --- a/src/components/admin/reminders-section.tsx +++ b/src/components/admin/reminders-section.tsx @@ -15,6 +15,7 @@ import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { useTranslations } from "@/lib/i18n/context"; import { queryKeys } from "@/lib/query-keys"; @@ -53,7 +54,7 @@ function NotificationHealthPanel() { }); return ( -
    + )}
    - + ); } @@ -194,7 +195,7 @@ export function RemindersSection() { return ( <> -
    + {/* v1.4.22 D / F-58 — icon swap so the section header matches the admin-shell nav tile (Bell). Clock now lives on the timing chips inline instead of competing as the page icon. */} @@ -404,7 +405,7 @@ export function RemindersSection() {
    )} - + ); diff --git a/src/components/admin/services-section.tsx b/src/components/admin/services-section.tsx index 17a3bd784..27ff8e02b 100644 --- a/src/components/admin/services-section.tsx +++ b/src/components/admin/services-section.tsx @@ -1,6 +1,7 @@ "use client"; import { Bell, Globe, Key, MessageCircle, Smile } from "lucide-react"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { useTranslations } from "@/lib/i18n/context"; import { SettingsToggle, useAdminSettings, useUpdateSettings } from "./_shared"; @@ -11,7 +12,7 @@ export function ServicesSection() { const updateSettings = useUpdateSettings(); return ( -
    +
    - + ); } diff --git a/src/components/admin/system-status-section.tsx b/src/components/admin/system-status-section.tsx index e14543a84..244087d7c 100644 --- a/src/components/admin/system-status-section.tsx +++ b/src/components/admin/system-status-section.tsx @@ -13,13 +13,14 @@ import { Key, Loader2, Map, - RotateCw, + RefreshCw, Server, Users, } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Skeleton } from "@/components/ui/skeleton"; import { formatDateTime } from "@/lib/format"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { useFormatters, useTranslations } from "@/lib/i18n/context"; import { StatusItem, usePublicVersion, useSystemStatus } from "./_shared"; @@ -51,7 +52,7 @@ export function SystemStatusSection() { return (
    -
    + ) : ( - + )} {t("admin.systemStatusRetry")} @@ -218,7 +219,7 @@ export function SystemStatusSection() {
    )} -
    + ); } diff --git a/src/components/admin/system-status-summary.tsx b/src/components/admin/system-status-summary.tsx index 72583f105..c21a0ed3e 100644 --- a/src/components/admin/system-status-summary.tsx +++ b/src/components/admin/system-status-summary.tsx @@ -23,6 +23,7 @@ import { Tag, } from "lucide-react"; import { formatDateTime } from "@/lib/format"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { useTranslations } from "@/lib/i18n/context"; import { StatusItem, usePublicVersion, useSystemStatus } from "./_shared"; @@ -33,9 +34,9 @@ export function SystemStatusSummary() { const { data: version } = usePublicVersion(); return ( -
    )} -
    + ); } diff --git a/src/components/admin/umami-section.tsx b/src/components/admin/umami-section.tsx index 6a92dd0a8..b19d6327a 100644 --- a/src/components/admin/umami-section.tsx +++ b/src/components/admin/umami-section.tsx @@ -4,6 +4,7 @@ import { useState } from "react"; import { useMutation } from "@tanstack/react-query"; import { Activity, Loader2 } from "lucide-react"; import { toast } from "sonner"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; @@ -72,7 +73,7 @@ export function UmamiSection() { } return ( -
    +
    - + ); } diff --git a/src/components/admin/user-management-section.tsx b/src/components/admin/user-management-section.tsx index 320618621..f9412c43b 100644 --- a/src/components/admin/user-management-section.tsx +++ b/src/components/admin/user-management-section.tsx @@ -30,7 +30,9 @@ import { } from "@/components/ui/alert-dialog"; import { useAuth } from "@/hooks/use-auth"; import { formatDate } from "@/lib/format"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; +import { ListRow } from "@/components/ui/list-row"; import { useTranslations } from "@/lib/i18n/context"; import { queryKeys } from "@/lib/query-keys"; import { type AdminUser, PasswordInput } from "./_shared"; @@ -253,7 +255,7 @@ export function UserManagementSection() { ); return ( -
    + {filteredUsers.map((u) => ( -
  • -
    -
    -
    - - {u.username} - - - {u.role} - +
  • +
    +
    +
    + + {u.username} + + + {u.role} + +
    +

    + {u.email || "—"} +

    +

    + {t("admin.userPasskeys")}: {u.passkeyCount} ·{" "} + {formatDate(u.createdAt)} +

    -

    - {u.email || "—"} -

    -

    - {t("admin.userPasskeys")}: {u.passkeyCount} ·{" "} - {formatDate(u.createdAt)} -

    -
  • -
    - {renderUserActions(u)} -
    - +
    + {renderUserActions(u)} +
    + + ))} @@ -594,6 +601,6 @@ export function UserManagementSection() { - + ); } diff --git a/src/components/admin/version-tile-section.tsx b/src/components/admin/version-tile-section.tsx index fd7e0eda3..7389d6c0b 100644 --- a/src/components/admin/version-tile-section.tsx +++ b/src/components/admin/version-tile-section.tsx @@ -25,6 +25,7 @@ import { } from "lucide-react"; import { useQuery } from "@tanstack/react-query"; import { formatDateTime } from "@/lib/format"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { useTranslations } from "@/lib/i18n/context"; import { queryKeys } from "@/lib/query-keys"; @@ -82,10 +83,7 @@ export function VersionTileSection() { const sha = shortSha(version?.buildSha ?? null); return ( -
    + -
    + ); } diff --git a/src/components/admin/web-push-vapid-section.tsx b/src/components/admin/web-push-vapid-section.tsx index 16092aa65..c3acb4213 100644 --- a/src/components/admin/web-push-vapid-section.tsx +++ b/src/components/admin/web-push-vapid-section.tsx @@ -4,6 +4,7 @@ import { useState } from "react"; import { useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; import { BellRing, KeyRound, Loader2 } from "lucide-react"; +import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { Button } from "@/components/ui/button"; import { @@ -119,7 +120,7 @@ export function WebPushVapidSection() { } return ( -
    + -
    + ); }