fix(insights,settings): restore hero-strip column width, gate hero fieldset on hydration

This commit is contained in:
Marc-André Bombeck committed 2026-07-28 22:03:39 +02:00
1 parent 41a18813d1
commit 668e3ca6b6
3 files changed
+24 -1

No files matched your search

+1
View File
@@ -383,6 +383,7 @@ export function HeroStrip({
report={healthScore}
tension={tensionProp}
returnToBand={returnToBandProp}
className="w-full md:shrink-0 md:grow-0 md:basis-[22rem] xl:basis-[26rem]"
/>
)}
</div>
@@ -69,6 +69,16 @@ vi.mock("@/hooks/use-auth", () => ({
useAuth: () => ({ user: { modules: authState.modules } }),
}));
// The hero fieldset gates its presence via `useMounted()` (v1.34, hydration
// fix). Under SSR (`renderToStaticMarkup`) `useMounted()` returns `false`,
// which would hide the fieldset from every test below regardless of
// `layout`. Force it to the hydrated (`true`) snapshot so these tests
// exercise the real post-mount content — same convention as
// layout-section.test.tsx for the identical `LayoutModuleGate` pattern.
vi.mock("@/hooks/use-mounted", () => ({
useMounted: () => true,
}));
import { I18nProvider } from "@/lib/i18n/context";
import {
DashboardLayoutSection,
@@ -49,6 +49,7 @@ import {
type PriorityItemKind,
} from "@/lib/daily/priority-item";
import { apiDelete, apiGet, apiPut, ApiError } from "@/lib/api/api-fetch";
import { useMounted } from "@/hooks/use-mounted";
import { useAuth } from "@/hooks/use-auth";
import {
NATIVE_ONLY_WIDGET_LABEL_KEYS,
@@ -204,6 +205,17 @@ export function DashboardLayoutSection({ id }: { id: string }) {
const dragHintId = useId();
const heroDescriptionId = useId();
const heroNotificationNoteId = useId();
// v1.34 — the "Today highlights" fieldset below is gated on `layout`,
// which can be truthy on the very first client render whenever a
// returning visitor's browser already has a warm, offline-persisted
// `dashboardWidgets` cache (queryKeys.dashboardWidgets() sits in
// PERSIST_ALLOWLIST_HEADS). The static build has no session, so
// `layout` is always null in the server HTML — a warm cache then
// diverges the very first client paint from that HTML (React #418).
// `useMounted()` forces the fieldset's presence check to agree with
// the server on the hydrating render (both false), the same pattern
// `LayoutModuleGate` already uses for the same class of mismatch.
const hydrated = useMounted();
// v1.4.47 W4 — sensors: pointer for mouse/touch, keyboard for Tab + Space
// + arrow-key reordering. The KeyboardSensor still works for users who
@@ -452,7 +464,7 @@ export function DashboardLayoutSection({ id }: { id: string }) {
/>
}
/>
{layout && (
{hydrated && layout && (
<fieldset
aria-describedby={`${heroDescriptionId} ${heroNotificationNoteId}`}
data-slot="hero-content-settings"