feat(onboarding): one-time 「那一刻的天空」 reveal after the first own chart (T6)

After saveOnboardingPlace succeeds (and the next step is already set), the
new useBirthSkyReveal hook fetches /api/birth-sky?subject=self and paints
the cover; if that finishes within 3 s the chart page's dialog fades in
(600 ms, none under reduced motion) with 「继续」. Timeout or failure is
silent, no retry; closing touches only the reveal's own state. Home() gains
no useState/useRef; page.tsx only wires. Family profiles and profile edits
never trigger it.

Also caps the dialog image by viewport height (the percentage max-height did
not resolve inside the flex/grid cell), and completes PROGRESS, DESIGN §17,
CHANGELOG and the real-device checklist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0199rbQDTsUbCVw84wc8BTFe
This commit is contained in:
Jesse_Chen
2026-09-28 20:47:35 +08:00
co-authored by Claude Opus 5.5
parent 028aef2737
commit 14ef18ac24
13 changed files with 369 additions and 9 deletions
@@ -0,0 +1,15 @@
"use client";
import dynamic from "next/dynamic";
import type { BirthSkyCover } from "@/lib/birth-sky/cover";
const BirthSkyDialog = dynamic(
() => import("./birth-sky-dialog").then((module) => module.BirthSkyDialog),
{ ssr: false },
);
/** First-chart reveal: the chart page's dialog, faded in once, with 「继续」. */
export function BirthSkyReveal({ cover, onClose }: { cover: BirthSkyCover | null; onClose: () => void }) {
return cover ? <BirthSkyDialog cover={cover} onClose={onClose} reveal /> : null;
}
@@ -15,9 +15,6 @@
color: var(--color-ink);
overflow: hidden;
}
@supports (height: 1dvh) {
.birth-sky-dialog { height: 100dvh; }
}
.birth-sky-dialog::backdrop { background: var(--color-scrim); }
.birth-sky-panel { display: flex; flex-direction: column; height: 100%; }
.birth-sky-header {
@@ -42,11 +39,16 @@
width: auto;
height: auto;
max-width: 100%;
max-height: 100%;
/* Header + footer ≈ 170px; a percentage would not resolve inside the flex/grid cell everywhere. */
max-height: calc(100vh - 170px);
aspect-ratio: 3 / 4;
border-radius: var(--radius-md);
-webkit-touch-callout: default;
}
@supports (height: 1dvh) {
.birth-sky-dialog { height: 100dvh; }
.birth-sky-image { max-height: calc(100dvh - 170px); }
}
.birth-sky-footer {
display: flex;
flex-wrap: wrap;