Files
model-platform/frontend/app/components/common/AppFormDialog.tsx
T
2026-08-28 12:00:14 +08:00

92 lines
2.6 KiB
TypeScript

import type { ReactNode } from "react"
import {
Dialog,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
} from "~/components/ui/dialog"
import { cn } from "~/lib/utils"
import { primaryGradientButtonClass } from "./buttonClasses"
/** 与系统管理弹窗 footer 一致的次要按钮样式 */
export const dialogSecondaryButtonClass =
"h-[37px] gap-[7px] rounded-md border-[#d8e1e9] bg-white px-[15px] text-xs font-[650] text-[#56687c]"
/** 与系统管理弹窗 footer 一致的主按钮样式(STYLE_GUIDE §2.2 官方渐变) */
export const dialogPrimaryButtonClass = primaryGradientButtonClass
const EYEBROW_CLASS =
"text-[9px] font-extrabold tracking-[0.12em] text-[#2d82d4]"
const TITLE_CLASS = "mt-1 text-[19px] font-normal text-[#1c2d42]"
type AppFormDialogProps = {
open: boolean
onOpenChange: (open: boolean) => void
eyebrow?: string
title?: ReactNode
titleId?: string
children: ReactNode
footer?: ReactNode
contentClassName?: string
bodyClassName?: string
showCloseButton?: boolean
size?: "compact" | "panel"
}
function AppFormDialog({
open,
onOpenChange,
eyebrow,
title,
titleId,
children,
footer,
contentClassName,
bodyClassName,
showCloseButton = true,
size = "compact",
}: AppFormDialogProps) {
const maxWidth =
size === "panel"
? "sm:max-w-[min(520px,calc(100vw-40px))]"
: "sm:max-w-[min(480px,calc(100vw-40px))]"
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent
showCloseButton={showCloseButton}
className={cn(
"flex max-h-[80vh] flex-col gap-0 overflow-hidden rounded-[11px] border-[#dce4eb] bg-white p-0 text-[#1c2d42] shadow-xl ring-0",
maxWidth,
contentClassName,
)}
>
{eyebrow || title ? (
<DialogHeader className="shrink-0 space-y-0 border-b border-line px-[22px] pb-4 pt-5 text-left">
{eyebrow ? <span className={EYEBROW_CLASS}>{eyebrow}</span> : null}
{title ? (
<DialogTitle id={titleId} className={TITLE_CLASS}>
{title}
</DialogTitle>
) : null}
</DialogHeader>
) : null}
<div className={cn("min-h-0 flex-1 overflow-y-auto", bodyClassName)}>
{children}
</div>
{footer ? (
<DialogFooter className="mt-0 shrink-0 flex-row justify-end gap-2 border-t border-line bg-white px-[22px] py-3.5 sm:justify-end">
{footer}
</DialogFooter>
) : null}
</DialogContent>
</Dialog>
)
}
export { AppFormDialog }