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

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

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

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

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

94 lines
2.1 KiB
TypeScript

import type {
ButtonHTMLAttributes,
MouseEvent,
ReactNode,
} from 'react';
type PuzzleRuntimeModalShellProps = {
titleId: string;
children: ReactNode;
overlayClassName?: string;
dialogClassName?: string;
onOverlayClick?: () => void;
};
type PuzzleRuntimeDialogFooterProps = {
children: ReactNode;
className: string;
framed?: boolean;
};
type PuzzleRuntimeDialogButtonProps =
ButtonHTMLAttributes<HTMLButtonElement> & {
tone: 'primary' | 'secondary';
};
const DEFAULT_OVERLAY_CLASS_NAME =
'puzzle-runtime-modal-overlay absolute inset-0 z-50 flex items-center justify-center p-4 backdrop-blur-sm';
const DEFAULT_DIALOG_CLASS_NAME =
'puzzle-runtime-dialog w-full max-w-[22rem] overflow-hidden rounded-[1.35rem] shadow-[0_24px_80px_rgba(0,0,0,0.24)]';
export function PuzzleRuntimeModalShell({
titleId,
children,
overlayClassName = DEFAULT_OVERLAY_CLASS_NAME,
dialogClassName = DEFAULT_DIALOG_CLASS_NAME,
onOverlayClick,
}: PuzzleRuntimeModalShellProps) {
const handleDialogClick = (event: MouseEvent<HTMLElement>) => {
event.stopPropagation();
};
return (
<div
className={overlayClassName}
onClick={onOverlayClick ? () => onOverlayClick() : undefined}
>
<section
role="dialog"
aria-modal="true"
aria-labelledby={titleId}
className={dialogClassName}
onClick={handleDialogClick}
>
{children}
</section>
</div>
);
}
export function PuzzleRuntimeDialogFooter({
children,
className,
framed = true,
}: PuzzleRuntimeDialogFooterProps) {
return (
<footer
className={`${framed ? 'puzzle-runtime-dialog__line border-t ' : ''}${className}`}
>
{children}
</footer>
);
}
export function PuzzleRuntimeDialogButton({
tone,
className = '',
type = 'button',
...buttonProps
}: PuzzleRuntimeDialogButtonProps) {
const toneClassName =
tone === 'primary'
? 'puzzle-runtime-primary-button'
: 'puzzle-runtime-secondary-button';
return (
<button
{...buttonProps}
type={type}
className={`${toneClassName} ${className}`}
/>
);
}