Files
Genarrative/src/components/platform-entry/PlatformEntryFlowShellImpl/PuzzleOnboardingView.tsx
T
kdletters ed2c386603 继续收口账号与运行态弹窗壳层
账号设置弹窗复用认证壳层并保留 direct mode 唯一 dialog 语义

拼图运行态新增本地弹窗壳层收口确认设置退出失败和通关结算

抓大鹅与跳一跳结算弹窗提取本地结算结构并补测试

拼图 onboarding 登录保存覆盖层迁入 UnifiedModal

更新 PlatformUiKit 收口文档和 Hermes 决策记录
2026-06-11 21:53:10 +08:00

180 lines
5.7 KiB
TypeScript

import { Loader2, Sparkles } from 'lucide-react';
import { PlatformActionButton } from '../../common/PlatformActionButton';
import { PlatformStatusMessage } from '../../common/PlatformStatusMessage';
import { PlatformTextField } from '../../common/PlatformTextField';
import { UnifiedModal } from '../../common/UnifiedModal';
export type PuzzleOnboardingPhase = 'input' | 'generating' | 'generated';
type PuzzleOnboardingViewProps = {
prompt: string;
phase: PuzzleOnboardingPhase;
error: string | null;
copy: string;
onPromptChange: (value: string) => void;
onSubmit: () => void;
onSkip: () => void;
};
export function PuzzleOnboardingView({
prompt,
phase,
error,
copy,
onPromptChange,
onSubmit,
onSkip,
}: PuzzleOnboardingViewProps) {
const isGenerating = phase === 'generating';
const isGenerated = phase === 'generated';
const canSubmit = Boolean(prompt.trim()) && !isGenerating && !isGenerated;
return (
<div className="relative flex min-h-screen items-center justify-center overflow-hidden bg-[radial-gradient(circle_at_30%_15%,rgba(251,191,36,0.22),transparent_30%),linear-gradient(135deg,#0f172a,#111827_46%,#1e1b4b)] px-4 py-8 text-white">
<div className="absolute inset-0 bg-[linear-gradient(rgba(255,255,255,0.045)_1px,transparent_1px),linear-gradient(90deg,rgba(255,255,255,0.04)_1px,transparent_1px)] bg-[length:38px_38px] opacity-30" />
<PlatformActionButton
type="button"
surface="editorDark"
tone="ghost"
size="sm"
shape="pill"
disabled={isGenerating}
onClick={onSkip}
className="absolute right-4 top-4 z-10 min-h-10 shadow-[0_12px_28px_rgba(0,0,0,0.22)] backdrop-blur sm:right-6 sm:top-6"
>
跳过
</PlatformActionButton>
<section className="relative flex w-full max-w-[34rem] flex-col items-center gap-5 text-center">
<div className="grid h-14 w-14 place-items-center rounded-[1.2rem] border border-amber-200/32 bg-amber-200/14 text-amber-100 shadow-[0_18px_48px_rgba(251,191,36,0.18)]">
{isGenerating ? (
<Loader2 className="h-6 w-6 animate-spin" />
) : (
<Sparkles className="h-6 w-6" />
)}
</div>
<h1 className="text-[2rem] font-black leading-tight sm:text-[2.85rem]">
{copy}
</h1>
<form
className="flex w-full flex-col gap-3"
onSubmit={(event) => {
event.preventDefault();
onSubmit();
}}
>
<PlatformTextField
variant="textarea"
surface="editorDark"
tone="warm"
density="roomy"
size="lg"
value={prompt}
disabled={isGenerating || isGenerated}
onChange={(event) => onPromptChange(event.target.value)}
placeholder="把你的梦讲给我听吧"
rows={4}
className="min-h-32 rounded-[1.25rem] border-white/14 bg-black/28 py-4 leading-7 shadow-[0_18px_50px_rgba(0,0,0,0.24)] backdrop-blur placeholder:text-white/42 focus:border-amber-200/70 focus:ring-2 focus:ring-amber-200/20 disabled:opacity-70"
/>
<PlatformActionButton
type="submit"
surface="editorDark"
tone="accent"
size="lg"
fullWidth
disabled={!canSubmit}
>
{isGenerating ? (
<>
<Loader2 className="h-4 w-4 animate-spin" />
生成
</>
) : (
'生成'
)}
</PlatformActionButton>
</form>
{error ? (
<PlatformStatusMessage
tone="error"
surface="editorDark"
size="md"
className="w-full font-semibold"
>
{error}
</PlatformStatusMessage>
) : null}
</section>
</div>
);
}
type PuzzleOnboardingLoginOverlayProps = {
isSaving: boolean;
error: string | null;
copy: string;
onLogin: () => void;
};
export function PuzzleOnboardingLoginOverlay({
isSaving,
error,
copy,
onLogin,
}: PuzzleOnboardingLoginOverlayProps) {
return (
<UnifiedModal
open
title={copy}
onClose={() => undefined}
portal={false}
showHeader={false}
showCloseButton={false}
closeOnBackdrop={false}
closeOnEscape={false}
size="sm"
zIndexClassName="z-[110]"
overlayClassName="!items-center bg-slate-950/72 !px-4 !py-6 text-white backdrop-blur-md"
panelClassName="!max-w-[24rem] !rounded-[1.35rem] border border-white/14 bg-slate-950/94 text-white shadow-[0_28px_90px_rgba(0,0,0,0.5)]"
bodyClassName="flex flex-col items-center gap-5 !px-5 !py-6 text-center"
>
<div className="grid h-12 w-12 place-items-center rounded-[1rem] bg-amber-200 text-slate-950">
{isSaving ? (
<Loader2 className="h-5 w-5 animate-spin" />
) : (
<Sparkles className="h-5 w-5" />
)}
</div>
<h2 className="text-2xl font-black leading-tight">{copy}</h2>
<PlatformActionButton
type="button"
surface="editorDark"
tone="accent"
size="lg"
fullWidth
disabled={isSaving}
onClick={onLogin}
>
{isSaving ? (
<>
<Loader2 className="h-4 w-4 animate-spin" />
注册账号 / 登录
</>
) : (
'注册账号 / 登录'
)}
</PlatformActionButton>
{error ? (
<PlatformStatusMessage
tone="error"
surface="editorDark"
size="md"
className="w-full font-semibold"
>
{error}
</PlatformStatusMessage>
) : null}
</UnifiedModal>
);
}