fix(dialoge): Dialoge an den body haengen, damit sie nicht in Karten haengen bleiben
Die Einblendanimationen laufen mit animation-fill-mode: both. Danach behaelt das Element den Wert des letzten Keyframes, bei transform also eine Einheitsmatrix statt "none". Das genuegt, um einen Bezugsrahmen fuer position: fixed zu erzeugen: Ein Dialog unterhalb einer solchen Karte hat sein Overlay nur noch ueber der Karte, deren overflow: hidden schneidet ihn ab. Sichtbar beim Bearbeiten eines Budgettopfs in der Projektansicht - das Fenster klebte an der Detailkarte und die Schaltflaechen waren abgeschnitten. Modal und ConfirmDialog rendern jetzt per createPortal in document.body. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ef7171496f
commit
133fca9ef6
@@ -1,6 +1,19 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { Icon } from './Icon';
|
||||
|
||||
/**
|
||||
* Dialoge haengen immer direkt am <body>.
|
||||
*
|
||||
* Grund: Die Einblendanimationen laufen mit "animation-fill-mode: both". Danach
|
||||
* behaelt das Element den Wert des letzten Keyframes - bei transform also eine
|
||||
* Einheitsmatrix statt "none". Das reicht, um einen Bezugsrahmen fuer
|
||||
* position: fixed zu erzeugen. Steht ein Dialog im Baum unter so einer Karte,
|
||||
* misst sein Overlay nur noch die Karte und deren overflow: hidden schneidet
|
||||
* ihn ab (z. B. Budgettopf bearbeiten in der Projektansicht).
|
||||
*/
|
||||
const toBody = (node: React.ReactElement) => (typeof document === 'undefined' ? node : createPortal(node, document.body));
|
||||
|
||||
interface ModalProps {
|
||||
title: string;
|
||||
subtitle?: React.ReactNode;
|
||||
@@ -54,7 +67,7 @@ function useDismiss(onClose: () => void) {
|
||||
*/
|
||||
export const Modal: React.FC<ModalProps> = ({ title, subtitle, onClose, children, footer, size = 'md' }) => {
|
||||
const dismiss = useDismiss(onClose);
|
||||
return (
|
||||
return toBody(
|
||||
<div
|
||||
{...dismiss}
|
||||
className="animate-fade fixed inset-0 z-[100] flex items-end justify-center bg-ink-950/50 backdrop-blur-sm sm:items-center sm:p-4"
|
||||
@@ -104,7 +117,7 @@ export const ConfirmDialog: React.FC<ConfirmProps> = ({
|
||||
onCancel,
|
||||
}) => {
|
||||
const dismiss = useDismiss(onCancel);
|
||||
return (
|
||||
return toBody(
|
||||
<div {...dismiss} className="animate-fade fixed inset-0 z-[130] flex items-center justify-center bg-ink-950/50 p-4 backdrop-blur-sm">
|
||||
<div className="animate-pop w-full max-w-sm rounded-2xl border border-ink-200 bg-surface p-7 text-center shadow-lift">
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user