feat: harden shared platform contracts

This commit is contained in:
2026-07-30 14:26:36 +02:00
parent 6970bf7457
commit 9b88ae388b
24 changed files with 2034 additions and 57 deletions
+16 -3
View File
@@ -1,4 +1,5 @@
import { useEffect, useId, useRef, type ReactNode } from "react";
import { useEffect, useId, useRef, type CSSProperties, type ReactNode } from "react";
import { createPortal } from "react-dom";
import { translateReactNode, usePlatformLanguage } from "../i18n/LanguageContext";
import { shouldCloseDialogOnBackdrop } from "./dialogInteractions";
import {
@@ -26,6 +27,9 @@ export type DialogProps = {
titleClassName?: string;
bodyClassName?: string;
footerClassName?: string;
portal?: boolean;
panelStyle?: CSSProperties;
backdropStyle?: CSSProperties;
};
function joinClasses(...classes: Array<string | undefined | false>) {
@@ -49,7 +53,10 @@ export default function Dialog({
headerClassName = "",
titleClassName = "",
bodyClassName = "",
footerClassName = ""
footerClassName = "",
portal = false,
panelStyle,
backdropStyle
}: DialogProps) {
const titleId = useId();
const canClose = Boolean(onClose) && !closeDisabled;
@@ -107,9 +114,10 @@ export default function Dialog({
if (!open) return null;
return (
const dialog = (
<div
className={joinClasses("dialog-backdrop", backdropClassName)}
style={backdropStyle}
role="presentation"
onMouseDown={(event) => {
if (
@@ -122,6 +130,7 @@ export default function Dialog({
ref={panelRef}
tabIndex={-1}
className={joinClasses("dialog-panel", className)}
style={panelStyle}
role={role}
aria-modal="true"
data-dialog-stack-state="topmost"
@@ -147,4 +156,8 @@ export default function Dialog({
</section>
</div>
);
return portal && typeof document !== "undefined"
? createPortal(dialog, document.body)
: dialog;
}