+
{/* Tone */}
-
+
{t("insights.coach.settingsExcludeHint")}
{t("insights.coach.settingsContextLabel")}
-
+
{t("insights.coach.settingsContextHint")}
diff --git a/src/components/settings/coach-reminders-section.tsx b/src/components/settings/coach-reminders-section.tsx
index 914a39abb..f00e2a5da 100644
--- a/src/components/settings/coach-reminders-section.tsx
+++ b/src/components/settings/coach-reminders-section.tsx
@@ -21,6 +21,7 @@ import { useMemo } from "react";
import { BellRing, Check, Loader2, Trash2, X } from "lucide-react";
import { Button } from "@/components/ui/button";
+import { EmptyState } from "@/components/ui/empty-state";
import { formatDateOrRelative } from "@/lib/format";
import { SettingsCard } from "@/components/settings/settings-card";
import { SettingsCardHeader } from "@/components/settings/_card-header";
@@ -177,14 +178,14 @@ export function CoachRemindersSection({
)}
{!query.isError && reminders.length === 0 ? (
-
- {t("settings.ai.coachReminders.empty")}
-
+ variant="plain"
+ size="compact"
+ title={t("settings.ai.coachReminders.empty")}
+ />
) : (
-
+
{due.length > 0 && (
diff --git a/src/components/settings/dashboard-layout-section.tsx b/src/components/settings/dashboard-layout-section.tsx
index 3ee72adf8..20a4bb507 100644
--- a/src/components/settings/dashboard-layout-section.tsx
+++ b/src/components/settings/dashboard-layout-section.tsx
@@ -716,7 +716,7 @@ export function DashboardLayoutSection({ id }: { id: string }) {
{/* v1.4.47 W4 — column header spacer additionally reserves the
width of the new drag-handle icon (w-7) so Tile / Chart
alignment with the row switches below stays pixel-perfect. */}
-
+
diff --git a/src/components/settings/export-section.tsx b/src/components/settings/export-section.tsx
index 4140f0dca..c04266b19 100644
--- a/src/components/settings/export-section.tsx
+++ b/src/components/settings/export-section.tsx
@@ -147,7 +147,7 @@ function ExportCardShell({
title={title}
description={description}
status={
-
+
{format}
}
diff --git a/src/components/settings/insights-pill-order-section.tsx b/src/components/settings/insights-pill-order-section.tsx
index 0e6e82d3d..ad64c66e8 100644
--- a/src/components/settings/insights-pill-order-section.tsx
+++ b/src/components/settings/insights-pill-order-section.tsx
@@ -43,6 +43,7 @@ import {
} from "@/lib/insights/sub-page-metric";
import { SUB_PAGE_TABS } from "@/components/insights/insights-tab-strip";
import { apiPut } from "@/lib/api/api-fetch";
+import { EmptyState } from "@/components/ui/empty-state";
import { SettingsCard } from "@/components/settings/settings-card";
import { SettingsCardHeader } from "@/components/settings/_card-header";
@@ -240,12 +241,12 @@ export function InsightsPillOrderSection({ id }: { id?: string }) {
) : tilesByGroup.length === 0 ? (
-
- {t("insights.pillOrder.empty")}
-
+ title={t("insights.pillOrder.empty")}
+ />
) : (
{tilesByGroup.map(({ group, rows }) => (
@@ -254,7 +255,7 @@ export function InsightsPillOrderSection({ id }: { id?: string }) {
data-slot="insights-pill-order-group"
data-group={group}
>
-
+
{t(MANAGER_GROUP_HEADER_KEYS[group])}
-
+
{t("settings.tokenTablePermissions")}:
{" "}
{conn.scope}
-
+
{t("settings.mcp.connectionLastUsed")}:
{" "}
@@ -353,7 +353,7 @@ function McpTokensCard() {
aria-label={t("settings.mcp.writeScopeToggleLabel")}
/>
-
+
{t("settings.mcp.writeScopeNote")}
@@ -447,19 +447,19 @@ function McpTokensCard() {
)}
-
+
{t("settings.tokenTablePermissions")}:
{" "}
{tok.permissions.join(", ")}
-
+
{t("settings.tokenTableCreated")}:
{" "}
{formatDate(tok.createdAt)}
-
+
{t("settings.tokenTableLastUsed")}:
{" "}
diff --git a/src/components/settings/nutrient-intake-card.tsx b/src/components/settings/nutrient-intake-card.tsx
index 621c12fee..3ea7d1544 100644
--- a/src/components/settings/nutrient-intake-card.tsx
+++ b/src/components/settings/nutrient-intake-card.tsx
@@ -21,6 +21,7 @@ import { Leaf } from "lucide-react";
import { SettingsCard } from "@/components/settings/settings-card";
import { SettingsCardHeader } from "@/components/settings/_card-header";
+import { EmptyState } from "@/components/ui/empty-state";
import { Skeleton } from "@/components/ui/skeleton";
import { useAuth } from "@/hooks/use-auth";
import { useTranslations } from "@/lib/i18n/context";
@@ -85,9 +86,11 @@ export function NutrientIntakeCard() {
) : rows.length === 0 ? (
-
- {t("settings.sections.sources.nutrients.empty")}
-
+
) : (
{rows.map((row) => (
diff --git a/src/components/settings/security-activity-card.tsx b/src/components/settings/security-activity-card.tsx
index 6b5959325..bcd10943b 100644
--- a/src/components/settings/security-activity-card.tsx
+++ b/src/components/settings/security-activity-card.tsx
@@ -13,6 +13,7 @@ import { useQuery } from "@tanstack/react-query";
import { ChevronDown, Loader2, ShieldCheck } from "lucide-react";
import { SettingsCard } from "@/components/settings/settings-card";
+import { EmptyState } from "@/components/ui/empty-state";
import { useTranslations, useFormatters } from "@/lib/i18n/context";
import { queryKeys } from "@/lib/query-keys";
import { apiGet } from "@/lib/api/api-fetch";
@@ -112,9 +113,11 @@ export function SecurityActivityCard({
)}
{!isLoading && !isError && events.length === 0 && (
-
- {t("settings.security.activityEmpty")}
-
+
)}
{events.length > 0 && (
diff --git a/src/components/settings/security-section/security-keys-card.tsx b/src/components/settings/security-section/security-keys-card.tsx
index 4a1a5353f..1616e48de 100644
--- a/src/components/settings/security-section/security-keys-card.tsx
+++ b/src/components/settings/security-section/security-keys-card.tsx
@@ -25,6 +25,7 @@ import {
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
+import { EmptyState } from "@/components/ui/empty-state";
import { SettingsCard } from "@/components/settings/settings-card";
import { SettingsCardHeader } from "@/components/settings/_card-header";
import { useTranslations } from "@/lib/i18n/context";
@@ -138,9 +139,11 @@ export function SecurityKeysCard({ keys }: { keys: WebauthnKeyInfo[] }) {
{keys.length === 0 ? (
-
- {t("settings.security.keys.empty")}
-
+
) : (
{keys.map((key) => (
diff --git a/src/components/settings/security-sessions-card.tsx b/src/components/settings/security-sessions-card.tsx
index d02b41f81..da33aaa07 100644
--- a/src/components/settings/security-sessions-card.tsx
+++ b/src/components/settings/security-sessions-card.tsx
@@ -15,6 +15,7 @@ import { ChevronDown, Loader2, MonitorSmartphone } from "lucide-react";
import { Button } from "@/components/ui/button";
import { SettingsCard } from "@/components/settings/settings-card";
+import { EmptyState } from "@/components/ui/empty-state";
import { useTranslations, useFormatters } from "@/lib/i18n/context";
import { queryKeys } from "@/lib/query-keys";
import { apiGet, apiDelete } from "@/lib/api/api-fetch";
@@ -126,9 +127,11 @@ export function SecuritySessionsCard({
)}
{!isLoading && !isError && sessions.length === 0 && (
-
- {t("settings.security.sessionsEmpty")}
-
+
)}
{sessions.length > 0 && (
diff --git a/src/components/settings/share-link-create-form.tsx b/src/components/settings/share-link-create-form.tsx
index 299bd663a..c9eb5b6e2 100644
--- a/src/components/settings/share-link-create-form.tsx
+++ b/src/components/settings/share-link-create-form.tsx
@@ -320,7 +320,7 @@ export function ShareLinkCreateForm({
setRangeDays(Math.max(1, Number(e.target.value) || 1))
}
/>
-
+
{t("settings.sharing.rangeHint")}
@@ -338,7 +338,7 @@ export function ShareLinkCreateForm({
}
aria-invalid={expiryDays < 1 || expiryDays > MAX_DAYS}
/>
-
+
{t("settings.sharing.expiryHint", { max: MAX_DAYS })}
@@ -353,7 +353,7 @@ export function ShareLinkCreateForm({
-
+
{t("settings.sharing.fhirApiHint")}
@@ -396,7 +396,7 @@ export function ShareLinkCreateForm({
-
+
{t("settings.sharing.attachCount", {
count: selectedDocs.length,
max: MAX_DOCUMENTS,
@@ -445,11 +445,11 @@ export function ShareLinkCreateForm({
) : null}
-
+
{t("settings.sharing.attachFrozen")}
{selectedDocs.length > 0 ? (
-
+
{t("settings.sharing.exifNote")}
) : null}
@@ -499,7 +499,7 @@ export function ShareLinkCreateForm({
})}
)}
-
+
{t("settings.sharing.shownOnce")}
@@ -537,7 +537,7 @@ export function ShareLinkCreateForm({
{/* The link (no passphrase). On its own it cannot open the record. */}
-
+
{t("settings.sharing.linkLabel")}
@@ -556,7 +556,7 @@ export function ShareLinkCreateForm({
{copied === "link" && (
-
+
{t("settings.sharing.copied")}
)}
@@ -565,7 +565,7 @@ export function ShareLinkCreateForm({
{/* The passphrase — the second factor. Shown once; only its hash is
stored, so it cannot be recovered. */}
-
+
{t("settings.sharing.passphraseLabel")}
@@ -587,11 +587,11 @@ export function ShareLinkCreateForm({
{copied === "passphrase" && (
-
+
{t("settings.sharing.copied")}
)}
-
+
{t("settings.sharing.passphraseHint")}
diff --git a/src/components/settings/sharing-section.tsx b/src/components/settings/sharing-section.tsx
index 354599ee1..549d217d1 100644
--- a/src/components/settings/sharing-section.tsx
+++ b/src/components/settings/sharing-section.tsx
@@ -38,6 +38,7 @@ import {
} from "@/components/ui/alert-dialog";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
+import { EmptyState } from "@/components/ui/empty-state";
import { SettingsCard } from "@/components/settings/settings-card";
import { SettingsCardHeader } from "@/components/settings/_card-header";
import {
@@ -107,12 +108,11 @@ function ShareLinksCard() {
{t("settings.sharing.activeTitle")}
{activeLinks.length === 0 ? (
-
- {t("settings.sharing.noActive")}
-
+ title={t("settings.sharing.noActive")}
+ />
) : (
{activeLinks.map((link) => (
@@ -158,19 +158,19 @@ function ShareLinksCard() {
)}