u
This commit is contained in:
107
src/components/AppDialog.jsx
Normal file
107
src/components/AppDialog.jsx
Normal 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;
|
||||
Reference in New Issue
Block a user