From 024da9fe96ca7a264af5541e7015ace86b33bf6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Wed, 10 Jun 2026 21:19:05 +0200 Subject: [PATCH] fix(ui): granular sleep sources, viewport-safe tour, one aligned settings language MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A night with coarse apple-health samples next to granular watch data showed only awake and asleep — the per-session source pick now prefers the source that knows its stages. Tour popovers clamp into the viewport, wrap their footer and fall back to a bottom sheet on narrow screens. Settings and admin sections share one alignment rule — icon column left, everything else flush on the content column — with neutral header icons, no duplicated section titles under the shell heading, and every select on the account-style idiom with a visible chevron. The dashboard's customize icon matches insights, the target-settings link leaves the home charts, and the mood heatmap adopts the damped fills the other mood charts already use. --- docs/ui-guidelines.md | 28 +++- messages/de.json | 4 +- messages/en.json | 4 +- messages/es.json | 4 +- messages/fr.json | 4 +- messages/it.json | 4 +- messages/pl.json | 4 +- src/app/globals.css | 7 + src/app/page.tsx | 8 +- .../admin/api-token-overview-section.tsx | 2 +- .../admin/app-log-preview-section.tsx | 2 +- src/components/admin/assistant-section.tsx | 4 +- src/components/admin/backups-section.tsx | 2 +- src/components/admin/bug-report-section.tsx | 2 +- .../admin/feedback-inbox-section.tsx | 2 +- .../admin/general-settings-section.tsx | 2 +- src/components/admin/glitchtip-section.tsx | 2 +- .../admin/invite-tokens-section.tsx | 6 +- .../admin/login-overview-section.tsx | 2 +- src/components/admin/recent-audit-preview.tsx | 2 +- src/components/admin/reminders-section.tsx | 4 +- src/components/admin/services-section.tsx | 4 +- .../admin/system-status-section.tsx | 2 +- .../admin/system-status-summary.tsx | 2 +- src/components/admin/umami-section.tsx | 2 +- .../admin/user-management-section.tsx | 2 +- src/components/admin/version-tile-section.tsx | 2 +- .../admin/web-push-vapid-section.tsx | 2 +- src/components/charts/mood-heatmap.tsx | 3 +- .../__tests__/layout-coach-fab.test.tsx | 127 ++++++-------- .../insights/coach-launch-button.tsx | 10 +- .../insights/insights-layout-shell.tsx | 7 +- src/components/insights/layout-coach-fab.tsx | 156 ++++++++++++------ src/components/onboarding/tour.tsx | 88 +++++++--- src/components/settings/_card-header.tsx | 6 +- src/components/settings/about-me-section.tsx | 8 +- src/components/settings/about-section.tsx | 22 +-- src/components/settings/account-section.tsx | 38 +++-- src/components/settings/advanced-section.tsx | 6 +- src/components/settings/ai-section.tsx | 115 +++++++------ src/components/settings/api-section.tsx | 4 +- src/components/settings/coach-nudge-card.tsx | 4 +- .../settings/cycle-tracking-card.tsx | 2 +- .../settings/dashboard-layout-section.tsx | 2 +- src/components/settings/dashboard-section.tsx | 2 +- src/components/settings/export-section.tsx | 4 +- .../settings/health-record-export-panel.tsx | 2 +- src/components/settings/import-panel.tsx | 2 +- .../settings/injection-sites-card.tsx | 2 +- src/components/settings/insights-section.tsx | 2 +- .../settings/integrations-section.tsx | 8 +- .../settings/mood-reminder-card.tsx | 13 +- .../settings/notification-status-card.tsx | 8 +- .../settings/notifications-section.tsx | 2 +- src/components/settings/ntfy-card.tsx | 2 +- .../settings/section-placeholder.tsx | 2 +- src/components/settings/sources-section.tsx | 6 +- src/components/settings/telegram-card.tsx | 2 +- .../settings/thresholds-editor-section.tsx | 2 +- .../settings/thresholds-section.tsx | 2 +- src/components/settings/web-push-card.tsx | 2 +- src/components/ui/native-select.tsx | 18 +- src/components/ui/select.tsx | 6 +- .../analytics/__tests__/sleep-night.test.ts | 41 +++++ src/lib/analytics/sleep-night.ts | 23 ++- .../__tests__/coach-cascade.test.tsx | 13 +- .../__tests__/coach-user-disable.test.tsx | 12 +- 67 files changed, 545 insertions(+), 344 deletions(-) diff --git a/docs/ui-guidelines.md b/docs/ui-guidelines.md index d58ef382d..fcb14b166 100644 --- a/docs/ui-guidelines.md +++ b/docs/ui-guidelines.md @@ -218,7 +218,31 @@ labelled ` handleHourChange(Number(e.target.value))} @@ -201,7 +202,7 @@ export function MoodReminderCard({ {`${h.toString().padStart(2, "0")}:00`} ))} - + )} {msg && ( @@ -210,8 +211,8 @@ export function MoodReminderCard({ aria-live="polite" className={ msgType === "error" - ? "text-destructive mt-3 text-sm" - : "text-muted-foreground mt-3 text-sm" + ? "text-destructive mt-3 pl-7 text-sm" + : "text-muted-foreground mt-3 pl-7 text-sm" } > {msg} diff --git a/src/components/settings/notification-status-card.tsx b/src/components/settings/notification-status-card.tsx index fe9b5c835..9b1c10fa4 100644 --- a/src/components/settings/notification-status-card.tsx +++ b/src/components/settings/notification-status-card.tsx @@ -136,12 +136,12 @@ export function NotificationStatusCard() { data-testid="notification-status-empty" >
- +

{t("settings.notificationStatus.title")}

-

+

{t("settings.notificationStatus.emptyDescription")}

@@ -152,12 +152,12 @@ export function NotificationStatusCard() {
- +

{t("settings.notificationStatus.title")}

-

+

{t("settings.notificationStatus.description")}

diff --git a/src/components/settings/notifications-section.tsx b/src/components/settings/notifications-section.tsx index c03e123b0..f4bf8b6a5 100644 --- a/src/components/settings/notifications-section.tsx +++ b/src/components/settings/notifications-section.tsx @@ -77,7 +77,7 @@ export function NotificationsSection() {

{t("settings.sections.notifications.title")}

diff --git a/src/components/settings/ntfy-card.tsx b/src/components/settings/ntfy-card.tsx index dc0007425..8d6319dc6 100644 --- a/src/components/settings/ntfy-card.tsx +++ b/src/components/settings/ntfy-card.tsx @@ -91,7 +91,7 @@ export function NtfyCard({ isAuthenticated }: { isAuthenticated: boolean }) { description={t("settings.ntfyDescription")} /> -
+

{sectionTitle}

diff --git a/src/components/settings/sources-section.tsx b/src/components/settings/sources-section.tsx index 23c4b7e48..2799e30c5 100644 --- a/src/components/settings/sources-section.tsx +++ b/src/components/settings/sources-section.tsx @@ -301,7 +301,7 @@ export function SourcesSection() {

{t("settings.sections.sources.title")}

@@ -325,7 +325,7 @@ export function SourcesSection() {
- +

{t("settings.sections.sources.cardTitle")}

@@ -342,7 +342,7 @@ export function SourcesSection() {
-

+

{t("settings.sections.sources.help")}

diff --git a/src/components/settings/telegram-card.tsx b/src/components/settings/telegram-card.tsx index e886663ae..0af940ef7 100644 --- a/src/components/settings/telegram-card.tsx +++ b/src/components/settings/telegram-card.tsx @@ -96,7 +96,7 @@ export function TelegramCard({ description={t("settings.telegramDescription")} /> -
+
diff --git a/src/components/settings/thresholds-editor-section.tsx b/src/components/settings/thresholds-editor-section.tsx index 4ac8bf765..6736bacbc 100644 --- a/src/components/settings/thresholds-editor-section.tsx +++ b/src/components/settings/thresholds-editor-section.tsx @@ -128,7 +128,7 @@ export function ThresholdsEditorSection({ id }: { id: string }) { control affordance. */}