fix(ui): granular sleep sources, viewport-safe tour, one aligned settings language

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.
This commit is contained in:
Marc-André Bombeck committed 2026-06-10 21:19:05 +02:00
1 parent 9f2c403f84
commit 024da9fe96
67 files changed
+545 -344

No files matched your search

@@ -159,7 +159,7 @@ export function ApiTokenOverviewSection() {
return (
<div className="bg-card border-border overflow-hidden rounded-xl border p-4 sm:p-6">
<div className="flex items-center gap-2">
<Key className="text-primary h-5 w-5" />
<Key className="text-muted-foreground h-5 w-5" />
<div className="text-lg font-semibold">{t("admin.apiTokens")}</div>
</div>
@@ -116,7 +116,7 @@ export function AppLogPreviewSection() {
<div className="bg-card border-border space-y-4 rounded-xl border p-6">
<header className="flex items-start justify-between gap-3">
<div className="flex items-start gap-2">
<FileText className="text-primary mt-0.5 h-5 w-5" />
<FileText className="text-muted-foreground mt-0.5 h-5 w-5" />
<div>
<h2 className="text-lg font-semibold">
{t("admin.section.app-logs.title")}
+2 -2
View File
@@ -107,10 +107,10 @@ export function AssistantSection() {
return (
<div className="bg-card border-border space-y-6 rounded-xl border p-6">
<div className="flex items-center gap-2">
<Sparkles className="text-primary h-5 w-5" />
<Sparkles className="text-muted-foreground h-5 w-5" />
<div className="text-lg font-semibold">{t("admin.assistant.title")}</div>
</div>
<p className="text-muted-foreground text-sm">
<p className="text-muted-foreground pl-7 text-sm">
{t("admin.assistant.description")}
</p>
+1 -1
View File
@@ -349,7 +349,7 @@ export function BackupsSection() {
<div className="bg-card border-border rounded-xl border p-6">
<div className="flex items-center justify-between gap-2">
<div className="flex items-center gap-2">
<Database className="text-primary h-5 w-5" />
<Database className="text-muted-foreground h-5 w-5" />
<div className="text-lg font-semibold">
{t("admin.section.backups.title")}
</div>
+1 -1
View File
@@ -48,7 +48,7 @@ export function BugReportSection() {
<div className="bg-card border-border rounded-xl border p-6">
<div className="flex flex-wrap items-start justify-between gap-2">
<div className="flex items-center gap-2">
<Bug className="text-primary h-5 w-5" />
<Bug className="text-muted-foreground h-5 w-5" />
<h2 className="text-lg font-semibold">
{t("admin.bugReportGithub")}
</h2>
@@ -74,7 +74,7 @@ export function FeedbackInboxSection() {
`/admin/feedback`, so the page header already provides the
title + description — the card-level repetition was just
visual noise. The icon stays as a low-key card affordance. */}
<Inbox className="text-primary h-5 w-5" aria-hidden="true" />
<Inbox className="text-muted-foreground h-5 w-5" aria-hidden="true" />
<Tabs
value={activeStatus}
@@ -27,7 +27,7 @@ export function GeneralSettingsSection() {
return (
<div className="bg-card border-border rounded-xl border p-6">
<div className="flex items-center gap-2">
<Settings className="text-primary h-5 w-5" />
<Settings className="text-muted-foreground h-5 w-5" />
<div className="text-lg font-semibold">{t("admin.appSettings")}</div>
</div>
<div className="mt-4 space-y-4">
+1 -1
View File
@@ -75,7 +75,7 @@ export function GlitchtipSection() {
<div className="bg-card border-border rounded-xl border p-6">
<div className="flex flex-wrap items-start justify-between gap-2">
<div className="flex items-center gap-2">
<AlertTriangle className="text-primary h-5 w-5" />
<AlertTriangle className="text-muted-foreground h-5 w-5" />
<h2 className="text-lg font-semibold">{t("admin.glitchtipTitle")}</h2>
</div>
<div className="flex flex-wrap items-center gap-2">
@@ -314,15 +314,15 @@ export function InviteTokensSection() {
<div className="flex flex-col gap-4 p-4 sm:flex-row sm:items-start sm:justify-between sm:p-6">
<div className="min-w-0">
<div className="flex items-center gap-2">
<Ticket className="text-primary h-5 w-5" aria-hidden="true" />
<Ticket className="text-muted-foreground h-5 w-5" aria-hidden="true" />
<h2 id="admin-invites-title" className="text-lg font-semibold">
{t("admin.invites.title")}
</h2>
</div>
<p className="text-muted-foreground mt-1 text-sm">
<p className="text-muted-foreground mt-1 pl-7 text-sm">
{t("admin.invites.description")}
</p>
<p className="text-muted-foreground/80 mt-1 flex items-center gap-1.5 text-xs">
<p className="text-muted-foreground/80 mt-1 flex items-center gap-1.5 pl-7 text-xs">
<ShieldCheck className="size-3.5 shrink-0" aria-hidden="true" />
{t("admin.invites.adminOnlyHint")}
</p>
@@ -198,7 +198,7 @@ export function LoginOverviewSection() {
return (
<div className="bg-card border-border rounded-xl border p-6">
<div className="flex items-center gap-2">
<ScrollText className="text-primary h-5 w-5" />
<ScrollText className="text-muted-foreground h-5 w-5" />
<div className="text-lg font-semibold">{t("admin.loginOverview")}</div>
</div>
@@ -59,7 +59,7 @@ export function RecentAuditPreview() {
>
<div className="flex items-center justify-between gap-2">
<div className="flex items-center gap-2">
<ScrollText className="text-primary h-5 w-5" aria-hidden="true" />
<ScrollText className="text-muted-foreground h-5 w-5" aria-hidden="true" />
<h2
id="admin-overview-audit-heading"
className="text-lg font-semibold"
+2 -2
View File
@@ -111,12 +111,12 @@ export function RemindersSection() {
{/* 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. */}
<Bell className="text-primary h-5 w-5" />
<Bell className="text-muted-foreground h-5 w-5" />
<div className="text-lg font-semibold">
{t("admin.medicationReminders")}
</div>
</div>
<p className="text-muted-foreground mt-1 text-xs">
<p className="text-muted-foreground mt-1 pl-7 text-xs">
{t("admin.medicationRemindersDescription")}
</p>
+2 -2
View File
@@ -12,10 +12,10 @@ export function ServicesSection() {
return (
<div className="bg-card border-border rounded-xl border p-6">
<div className="flex items-center gap-2">
<Globe className="text-primary h-5 w-5" />
<Globe className="text-muted-foreground h-5 w-5" />
<div className="text-lg font-semibold">{t("admin.servicesGlobal")}</div>
</div>
<p className="text-muted-foreground mt-1 text-xs">
<p className="text-muted-foreground mt-1 pl-7 text-xs">
{t("admin.servicesGlobalDescription")}
</p>
<div className="mt-4 space-y-3">
@@ -53,7 +53,7 @@ export function SystemStatusSection() {
<HostMetricsChart />
<div className="bg-card border-border rounded-xl border p-6">
<div className="flex items-center gap-2">
<Server className="text-primary h-5 w-5" />
<Server className="text-muted-foreground h-5 w-5" />
<div className="text-lg font-semibold">{t("admin.systemStatus")}</div>
</div>
{status ? (
@@ -37,7 +37,7 @@ export function SystemStatusSummary() {
className="bg-card border-border rounded-xl border p-6"
>
<div className="flex items-center gap-2">
<Server className="text-primary h-5 w-5" aria-hidden="true" />
<Server className="text-muted-foreground h-5 w-5" aria-hidden="true" />
<h2
id="admin-overview-snapshot-heading"
className="text-lg font-semibold"
+1 -1
View File
@@ -78,7 +78,7 @@ export function UmamiSection() {
<div className="bg-card border-border rounded-xl border p-6">
<div className="flex flex-wrap items-start justify-between gap-2">
<div className="flex items-center gap-2">
<Activity className="text-primary h-5 w-5" />
<Activity className="text-muted-foreground h-5 w-5" />
<h2 className="text-lg font-semibold">{t("admin.umamiTitle")}</h2>
</div>
<div className="flex flex-wrap items-center gap-2">
@@ -243,7 +243,7 @@ export function UserManagementSection() {
floating into the title's gap. */}
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between sm:gap-2">
<div className="flex items-center gap-2">
<Users className="text-primary h-5 w-5" />
<Users className="text-muted-foreground h-5 w-5" />
<div className="text-lg font-semibold">
{t("admin.userManagement")}
</div>
@@ -77,7 +77,7 @@ export function VersionTileSection() {
className="bg-card border-border rounded-xl border p-6"
>
<div className="flex flex-wrap items-center gap-2">
<Tag className="text-primary h-5 w-5" aria-hidden="true" />
<Tag className="text-muted-foreground h-5 w-5" aria-hidden="true" />
<h2
id="admin-overview-version-heading"
className="text-lg font-semibold"
@@ -51,7 +51,7 @@ export function WebPushVapidSection() {
<div className="bg-card border-border rounded-xl border p-6">
<div className="flex flex-wrap items-start justify-between gap-2">
<div className="flex items-center gap-2">
<BellRing className="text-primary h-5 w-5" />
<BellRing className="text-muted-foreground h-5 w-5" />
<h2 className="text-lg font-semibold">
{t("admin.webPushVapidTitle")}
</h2>