diff --git a/src/components/admin/feedback-inbox-section.tsx b/src/components/admin/feedback-inbox-section.tsx index 76852cff5..d42fe14ee 100644 --- a/src/components/admin/feedback-inbox-section.tsx +++ b/src/components/admin/feedback-inbox-section.tsx @@ -25,13 +25,7 @@ import { import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { EmptyState } from "@/components/ui/empty-state"; -import { - Dialog, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle, -} from "@/components/ui/dialog"; +import { ResponsiveSheet } from "@/components/ui/responsive-sheet"; import { Label } from "@/components/ui/label"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { formatDateTime } from "@/lib/format"; @@ -329,38 +323,110 @@ function FeedbackDetailDialog({ typeof meta.appVersion === "string" ? meta.appVersion : null; return ( - - - - - - {item.subject} - - - - - - {t("admin.feedback.submittedBy")}:{" "} - {item.user?.username ?? t("admin.feedback.anonymous")} - - · - {formatDateTime(item.createdAt)} - {issueUrl && ( - + + {item.subject} + + } + description={ + + + + {t("admin.feedback.submittedBy")}:{" "} + {item.user?.username ?? t("admin.feedback.anonymous")} + + · + {formatDateTime(item.createdAt)} + {issueUrl && ( + + + {t("admin.feedback.viewIssue")} + + + )} + + } + className="sm:max-w-2xl" + footer={ +
+ + + + + + + + + + {t("admin.feedback.archiveConfirm")} + + + + {t("common.cancel")} + archive.mutate()} + className="bg-destructive text-destructive-foreground hover:bg-destructive/90" > - - {t("admin.feedback.viewIssue")} - - + {t("admin.feedback.actionArchive")} + + + + + {githubConfigured && !issueUrl && ( + + )} + {issueUrl && ( + + {t("admin.feedback.publishedToGithub")} + + )} +
+ } + >
{item.description} @@ -450,76 +516,7 @@ function FeedbackDetailDialog({
-
- - - - - - - - - - {t("admin.feedback.archiveConfirm")} - - - - {t("common.cancel")} - archive.mutate()} - className="bg-destructive text-destructive-foreground hover:bg-destructive/90" - > - {t("admin.feedback.actionArchive")} - - - - - {githubConfigured && !issueUrl && ( - - )} - {issueUrl && ( - - {t("admin.feedback.publishedToGithub")} - - )} -
-
-
+ ); } diff --git a/src/components/charts/mood-chart.tsx b/src/components/charts/mood-chart.tsx index 527c134bc..8a17fb6b5 100644 --- a/src/components/charts/mood-chart.tsx +++ b/src/components/charts/mood-chart.tsx @@ -738,7 +738,7 @@ export function MoodChart({ tickLine={false} axisLine={false} width={65} - tickMargin={6} + tickMargin={10} tickFormatter={formatMoodTick} /> - + {latest !== null ? renderPair(latest, secondary?.latest) : "—"} diff --git a/src/components/medications/ResearchModeAcknowledgmentDialog.tsx b/src/components/medications/ResearchModeAcknowledgmentDialog.tsx index e1ad4cca8..659a5cb29 100644 --- a/src/components/medications/ResearchModeAcknowledgmentDialog.tsx +++ b/src/components/medications/ResearchModeAcknowledgmentDialog.tsx @@ -42,14 +42,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; import { AlertTriangle, BookOpenCheck, Loader2 } from "lucide-react"; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from "@/components/ui/dialog"; +import { ResponsiveSheet } from "@/components/ui/responsive-sheet"; import { Button } from "@/components/ui/button"; import { useTranslations } from "@/lib/i18n/context"; @@ -131,27 +124,44 @@ export function ResearchModeAcknowledgmentDialog({ } return ( - - - - - - {t("medications.researchMode.dialog.title")} - - - {t("medications.researchMode.dialog.intro")} - - - - {/* Only the body scrolls; header + footer stay pinned so the - Acknowledge / Cancel CTAs are always reachable without - scrolling on small viewports (the previous markup scrolled - the entire DialogContent, pushing the footer below the - fold on iPhone-class heights). */} -
+ + + {t("medications.researchMode.dialog.title")} + + } + description={t("medications.researchMode.dialog.intro")} + className="sm:max-w-xl" + footer={ +
+ + +
+ } + > +
)}
- - - - - - -
+ ); } diff --git a/src/components/medications/__tests__/ResearchModeAcknowledgmentDialog.test.tsx b/src/components/medications/__tests__/ResearchModeAcknowledgmentDialog.test.tsx index 95a447375..eaaa9440d 100644 --- a/src/components/medications/__tests__/ResearchModeAcknowledgmentDialog.test.tsx +++ b/src/components/medications/__tests__/ResearchModeAcknowledgmentDialog.test.tsx @@ -60,37 +60,38 @@ vi.mock("sonner", () => ({ }, })); -// Radix Dialog uses Portals which `renderToStaticMarkup` does not -// realise. We collapse the primitives to plain wrappers so the body of -// the dialog is reachable in the static markup. -vi.mock("@/components/ui/dialog", () => ({ - Dialog: ({ +// v1.4.27 R4 RC2 — the dialog now mounts . Its +// internals (Sheet on ` ({ + ResponsiveSheet: ({ open, + title, + description, + footer, children, }: { open: boolean; + title: React.ReactNode; + description?: React.ReactNode; + footer?: React.ReactNode; children: React.ReactNode; - }) => (open ?
{children}
: null), - DialogContent: ({ - children, - ...rest - }: React.ComponentProps<"div"> & { children: React.ReactNode }) => ( -
- {children} -
- ), - DialogHeader: ({ children }: { children: React.ReactNode }) => ( -
{children}
- ), - DialogTitle: ({ children }: { children: React.ReactNode }) => ( -

{children}

- ), - DialogDescription: ({ children }: { children: React.ReactNode }) => ( -

{children}

- ), - DialogFooter: ({ children }: { children: React.ReactNode }) => ( -
{children}
- ), + }) => + open ? ( +
+
+

{title}

+ {description ? ( +

{description}

+ ) : null} +
+
{children}
+ {footer ? ( +
{footer}
+ ) : null} +
+ ) : null, })); import { ResearchModeAcknowledgmentDialog } from "../ResearchModeAcknowledgmentDialog"; diff --git a/src/components/medications/phase-config-dialog.tsx b/src/components/medications/phase-config-dialog.tsx index e4de97eba..541d5073f 100644 --- a/src/components/medications/phase-config-dialog.tsx +++ b/src/components/medications/phase-config-dialog.tsx @@ -2,14 +2,7 @@ import { useState } from "react"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; -import { - Dialog, - DialogContent, - DialogHeader, - DialogTitle, - DialogDescription, - DialogFooter, -} from "@/components/ui/dialog"; +import { ResponsiveSheet } from "@/components/ui/responsive-sheet"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Loader2, RotateCcw } from "lucide-react"; @@ -160,15 +153,46 @@ export function PhaseConfigDialog({ }; return ( - - - - {t("medications.phaseConfig")} - - {t("medications.phaseConfigDescription")} - - - + + +
+ + +
+ + } + > {isLoading ? (
@@ -238,39 +262,6 @@ export function PhaseConfigDialog({ {statusMessage}
)} - - - -
- - -
-
-
-
+
); } diff --git a/src/components/settings/account-section.tsx b/src/components/settings/account-section.tsx index 3cded990b..5f9898597 100644 --- a/src/components/settings/account-section.tsx +++ b/src/components/settings/account-section.tsx @@ -610,7 +610,7 @@ export function AccountSection() { -
+