This commit is contained in:
seb
2026-10-05 14:54:43 +02:00
parent 358d34ecab
commit 26bee398a6
26 changed files with 209 additions and 75 deletions

View File

@@ -0,0 +1,107 @@
import { Component } from 'react';
import Dialog from '@mui/material/Dialog';
import { DIALOG_FOG } from '../colors';
/**
* Shared dialog shell — drop-in replacement for MUI `Dialog`.
*
* Guarantees across the whole app:
* - instant open/close (no Fade/scale animation): `transitionDuration={0}`
* - darker, bluish fog: backdrop `backgroundColor` = `DIALOG_FOG`
* - scrollbar-gutter matches the fog: toggles `df-dialog-open` on
* `<html>` while any `AppDialog` is open (see `src/index.css`).
*
* Class component on purpose (PureComponent-free: open state is driven
* by props, state lives in the wrapped content).
*
* Usage:
* import AppDialog from '../AppDialog';
* <AppDialog open={open} onClose={onClose} maxWidth="xs" fullWidth>
*/
class AppDialog extends Component {
static openCount = 0;
static updateFogClass() {
if (typeof document === 'undefined') return;
const html = document.documentElement;
if (!html) return;
if (AppDialog.openCount > 0) {
html.classList.add('df-dialog-open');
} else {
html.classList.remove('df-dialog-open');
}
}
static enter() {
AppDialog.openCount += 1;
AppDialog.updateFogClass();
}
static exit() {
AppDialog.openCount = Math.max(0, AppDialog.openCount - 1);
AppDialog.updateFogClass();
}
componentDidMount() {
if (this.props.open) AppDialog.enter();
}
componentDidUpdate(prevProps) {
if (this.props.open && !prevProps.open) AppDialog.enter();
else if (!this.props.open && prevProps.open) AppDialog.exit();
}
componentWillUnmount() {
if (this.props.open) AppDialog.exit();
}
render() {
const {
transitionDuration: _transitionDuration,
TransitionProps: _transitionProps,
TransitionComponent: _transitionComponent,
slotProps: userSlotProps,
slots: userSlots,
...rest
} = this.props;
void _transitionDuration;
void _transitionProps;
void _transitionComponent;
const userBackdrop = userSlotProps?.backdrop ?? {};
const { sx: userBackdropSx, ...restBackdrop } = userBackdrop;
const userTransition = userSlotProps?.transition ?? {};
const { transition: _userTransitionSlot, ...restSlots } = userSlots ?? {};
void _userTransitionSlot;
const slotProps = {
...userSlotProps,
backdrop: {
...restBackdrop,
sx: [
{ backgroundColor: DIALOG_FOG },
...(Array.isArray(userBackdropSx)
? userBackdropSx
: userBackdropSx
? [userBackdropSx]
: []),
],
},
transition: {
...userTransition,
timeout: 0,
},
};
return (
<Dialog
{...rest}
slots={restSlots}
slotProps={slotProps}
transitionDuration={0}
/>
);
}
}
export default AppDialog;