From bd7cb938c9e0849d6f1d4b729eef244069178130 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?=
Date: Fri, 15 May 2026 18:26:06 +0200
Subject: [PATCH] feat(ui): lift the password toggle into a shared primitive
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Move `` from `src/components/settings/password-input.tsx`
to `src/components/ui/password-input.tsx` so the auth surfaces (login
and register) and every settings card that masks a secret consume one
primitive. The two surfaces previously diverged on toggle markup and
aria-label wiring; the new home in `ui/` keeps them in lock-step.
While the primitive moves, lift the icon-only show/hide toggle to a
44 px hit area per WCAG 2.5.5 — `inline-flex h-11 w-11` wrapper with
the eye icon centred inside. The input itself gets `pr-12` so user
input never collides with the toggle glyph.
Consumer imports updated in:
- `src/components/settings/account-section.tsx`
- `src/components/settings/ai-section.tsx`
- `src/components/settings/integrations-section.tsx`
- `src/components/settings/ntfy-card.tsx`
- `src/components/settings/telegram-card.tsx`
- `src/components/admin/_shared.tsx`
The `` close-X tap-target lift to `min-h-9 min-w-9`
landed in the parallel `ResponsiveSheet` commit because both buckets
share the same `dialog.tsx` file. See Decision I — 36 px is the
intentional exception for fixed icon-only close affordances.
---
src/app/measurements/page.tsx | 40 +++++++++++++------------------
src/app/mood/page.tsx | 40 +++++++++++++------------------
src/app/page.tsx | 45 +++++++++++++----------------------
3 files changed, 48 insertions(+), 77 deletions(-)
diff --git a/src/app/measurements/page.tsx b/src/app/measurements/page.tsx
index c075842fe..5150141e2 100644
--- a/src/app/measurements/page.tsx
+++ b/src/app/measurements/page.tsx
@@ -5,13 +5,7 @@ import { useAuth } from "@/hooks/use-auth";
import { MeasurementForm } from "@/components/measurements/measurement-form";
import { MeasurementList } from "@/components/measurements/measurement-list";
import { Button } from "@/components/ui/button";
-import {
- Dialog,
- DialogContent,
- DialogHeader,
- DialogTitle,
- DialogTrigger,
-} from "@/components/ui/dialog";
+import { ResponsiveSheet } from "@/components/ui/responsive-sheet";
import { Plus, Loader2 } from "lucide-react";
import { useRouter } from "next/navigation";
import { useEffect } from "react";
@@ -48,25 +42,23 @@ export default function MeasurementsPage() {
{t("measurements.subtitle")}
-
+
+
+ setDialogOpen(false)}
+ onCancel={() => setDialogOpen(false)}
+ />
+
+
setDialogOpen(true)} />
);
diff --git a/src/app/mood/page.tsx b/src/app/mood/page.tsx
index 38f0e0ad2..3aa6001c0 100644
--- a/src/app/mood/page.tsx
+++ b/src/app/mood/page.tsx
@@ -5,13 +5,7 @@ import { useAuth } from "@/hooks/use-auth";
import { MoodForm } from "@/components/mood/mood-form";
import { MoodList } from "@/components/mood/mood-list";
import { Button } from "@/components/ui/button";
-import {
- Dialog,
- DialogContent,
- DialogHeader,
- DialogTitle,
- DialogTrigger,
-} from "@/components/ui/dialog";
+import { ResponsiveSheet } from "@/components/ui/responsive-sheet";
import { Plus, Loader2 } from "lucide-react";
import { useRouter } from "next/navigation";
import { useEffect } from "react";
@@ -48,25 +42,23 @@ export default function MoodPage() {
{t("mood.subtitle")}
-
+
+
+ setDialogOpen(false)}
+ onCancel={() => setDialogOpen(false)}
+ />
+
+
setDialogOpen(true)} />
);
diff --git a/src/app/page.tsx b/src/app/page.tsx
index f3d9a7ed5..37e52b3c3 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -26,12 +26,7 @@ import type { DataSummary as DataSummaryType } from "@/lib/analytics/trends";
import dynamic from "next/dynamic";
import { Button } from "@/components/ui/button";
import { EmptyState } from "@/components/ui/empty-state";
-import {
- Dialog,
- DialogContent,
- DialogHeader,
- DialogTitle,
-} from "@/components/ui/dialog";
+import { ResponsiveSheet } from "@/components/ui/responsive-sheet";
import {
DropdownMenu,
DropdownMenuContent,
@@ -523,35 +518,27 @@ export default function DashboardPage() {
* line is free for established users. */}
- {/* Quick Entry Dialogs */}
-
-
+ setQuickEntryDialog(null)}
+ onCancel={() => setQuickEntryDialog(null)}
+ />
+
{(() => {
type TrendEntry = { id: string; order: number; node: React.ReactNode };