From e90363a2d450a568b3befdc5c8948a09fcd6f094 Mon Sep 17 00:00:00 2001 From: Olivier Tassinari Date: Sun, 12 Feb 2023 00:50:29 +0100 Subject: [PATCH] fix the fade transition at the same time --- .../data/base/components/modal/SpringModal.js | 36 ++++++--------- .../base/components/modal/SpringModal.tsx | 38 +++++++-------- .../base/components/modal/TransitionsModal.js | 34 ++++++-------- .../components/modal/TransitionsModal.tsx | 46 +++++++++---------- .../material/components/modal/SpringModal.js | 21 +++++---- .../material/components/modal/SpringModal.tsx | 25 +++++----- .../components/modal/TransitionsModal.js | 8 ++-- .../components/modal/TransitionsModal.tsx | 8 ++-- docs/pages/material-ui/api/backdrop.json | 1 + .../api-docs/backdrop/backdrop.json | 1 + .../mui-base/src/utils/isHostComponent.ts | 4 +- packages/mui-base/src/utils/mergeSlotProps.ts | 1 + packages/mui-base/src/utils/types.ts | 2 + .../mui-material/src/Backdrop/Backdrop.d.ts | 8 ++++ .../mui-material/src/Backdrop/Backdrop.js | 13 ++++-- 15 files changed, 126 insertions(+), 120 deletions(-) diff --git a/docs/data/base/components/modal/SpringModal.js b/docs/data/base/components/modal/SpringModal.js index db04fb2a101307..5875cd29461b14 100644 --- a/docs/data/base/components/modal/SpringModal.js +++ b/docs/data/base/components/modal/SpringModal.js @@ -1,27 +1,10 @@ import * as React from 'react'; import PropTypes from 'prop-types'; -import clsx from 'clsx'; import { Box, styled } from '@mui/system'; import ModalUnstyled from '@mui/base/ModalUnstyled'; import Button from '@mui/base/ButtonUnstyled'; import { useSpring, animated } from '@react-spring/web'; -const BackdropUnstyled = React.forwardRef((props, ref) => { - const { open, className, ...other } = props; - return ( -
- ); -}); - -BackdropUnstyled.propTypes = { - className: PropTypes.string.isRequired, - open: PropTypes.bool, -}; - const Modal = styled(ModalUnstyled)` position: fixed; z-index: 1300; @@ -34,6 +17,15 @@ const Modal = styled(ModalUnstyled)` justify-content: center; `; +const BackdropUnstyled = React.forwardRef((props, ref) => { + const { open, ...other } = props; + return ; +}); + +BackdropUnstyled.propTypes = { + open: PropTypes.bool.isRequired, +}; + const Backdrop = styled(BackdropUnstyled)` z-index: -1; position: fixed; @@ -52,12 +44,12 @@ const Fade = React.forwardRef(function Fade(props, ref) { to: { opacity: open ? 1 : 0 }, onStart: () => { if (open && onEnter) { - onEnter(); + onEnter(null, true); } }, onRest: () => { if (!open && onExited) { - onExited(); + onExited(null, true); } }, }); @@ -70,8 +62,8 @@ const Fade = React.forwardRef(function Fade(props, ref) { }); Fade.propTypes = { - children: PropTypes.element, - in: PropTypes.bool.isRequired, + children: PropTypes.element.isRequired, + in: PropTypes.bool, onEnter: PropTypes.func, onExited: PropTypes.func, }; @@ -107,7 +99,7 @@ export default function SpringModal() {

Text in a modal

- + Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
diff --git a/docs/data/base/components/modal/SpringModal.tsx b/docs/data/base/components/modal/SpringModal.tsx index a2be4d874fcc2a..ba77d97557b9ed 100644 --- a/docs/data/base/components/modal/SpringModal.tsx +++ b/docs/data/base/components/modal/SpringModal.tsx @@ -1,24 +1,9 @@ import * as React from 'react'; -import clsx from 'clsx'; import { Box, styled, Theme } from '@mui/system'; import ModalUnstyled from '@mui/base/ModalUnstyled'; import Button from '@mui/base/ButtonUnstyled'; import { useSpring, animated } from '@react-spring/web'; -const BackdropUnstyled = React.forwardRef< - HTMLDivElement, - { open?: boolean; className: string } ->((props, ref) => { - const { open, className, ...other } = props; - return ( -
- ); -}); - const Modal = styled(ModalUnstyled)` position: fixed; z-index: 1300; @@ -31,6 +16,14 @@ const Modal = styled(ModalUnstyled)` justify-content: center; `; +const BackdropUnstyled = React.forwardRef< + HTMLDivElement, + { children: React.ReactElement; open: boolean } +>((props, ref) => { + const { open, ...other } = props; + return ; +}); + const Backdrop = styled(BackdropUnstyled)` z-index: -1; position: fixed; @@ -43,10 +36,11 @@ const Backdrop = styled(BackdropUnstyled)` `; interface FadeProps { - children?: React.ReactElement; - in: boolean; - onEnter?: () => {}; - onExited?: () => {}; + children: React.ReactElement; + in?: boolean; + onClick?: any; + onEnter?: (node: HTMLElement, isAppearing: boolean) => void; + onExited?: (node: HTMLElement, isAppearing: boolean) => void; } const Fade = React.forwardRef(function Fade(props, ref) { @@ -56,12 +50,12 @@ const Fade = React.forwardRef(function Fade(props, re to: { opacity: open ? 1 : 0 }, onStart: () => { if (open && onEnter) { - onEnter(); + onEnter(null as any, true); } }, onRest: () => { if (!open && onExited) { - onExited(); + onExited(null as any, true); } }, }); @@ -104,7 +98,7 @@ export default function SpringModal() {

Text in a modal

- + Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
diff --git a/docs/data/base/components/modal/TransitionsModal.js b/docs/data/base/components/modal/TransitionsModal.js index 9d74b2561faf49..bf42b21bb29eac 100644 --- a/docs/data/base/components/modal/TransitionsModal.js +++ b/docs/data/base/components/modal/TransitionsModal.js @@ -1,48 +1,44 @@ import * as React from 'react'; import PropTypes from 'prop-types'; -import clsx from 'clsx'; import { Box, styled } from '@mui/system'; import ModalUnstyled from '@mui/base/ModalUnstyled'; import Fade from '@mui/material/Fade'; import Button from '@mui/base/ButtonUnstyled'; const BackdropUnstyled = React.forwardRef((props, ref) => { - const { open, className, ...other } = props; + const { open, ...other } = props; return ( -
+ +
+ ); }); BackdropUnstyled.propTypes = { - className: PropTypes.string.isRequired, open: PropTypes.bool, }; -const Modal = styled(ModalUnstyled)` +const Backdrop = styled(BackdropUnstyled)` + z-index: -1; position: fixed; - z-index: 1300; right: 0; bottom: 0; top: 0; left: 0; - display: flex; - align-items: center; - justify-content: center; + background-color: rgba(0, 0, 0, 0.5); + -webkit-tap-highlight-color: transparent; `; -const Backdrop = styled(BackdropUnstyled)` - z-index: -1; +const Modal = styled(ModalUnstyled)` position: fixed; + z-index: 1300; right: 0; bottom: 0; top: 0; left: 0; - background-color: rgba(0, 0, 0, 0.5); - -webkit-tap-highlight-color: transparent; + display: flex; + align-items: center; + justify-content: center; `; const style = (theme) => ({ @@ -73,10 +69,10 @@ export default function TransitionsModal() { closeAfterTransition slots={{ backdrop: Backdrop }} > - +

Text in a modal

- + Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
diff --git a/docs/data/base/components/modal/TransitionsModal.tsx b/docs/data/base/components/modal/TransitionsModal.tsx index b81cedbc068a54..d91a25e0eab3a2 100644 --- a/docs/data/base/components/modal/TransitionsModal.tsx +++ b/docs/data/base/components/modal/TransitionsModal.tsx @@ -1,45 +1,41 @@ import * as React from 'react'; -import clsx from 'clsx'; import { Box, styled, Theme } from '@mui/system'; import ModalUnstyled from '@mui/base/ModalUnstyled'; import Fade from '@mui/material/Fade'; import Button from '@mui/base/ButtonUnstyled'; -const BackdropUnstyled = React.forwardRef< - HTMLDivElement, - { open?: boolean; className: string } ->((props, ref) => { - const { open, className, ...other } = props; - return ( -
- ); -}); +const BackdropUnstyled = React.forwardRef( + (props, ref) => { + const { open, ...other } = props; + return ( + +
+ + ); + }, +); -const Modal = styled(ModalUnstyled)` +const Backdrop = styled(BackdropUnstyled)` + z-index: -1; position: fixed; - z-index: 1300; right: 0; bottom: 0; top: 0; left: 0; - display: flex; - align-items: center; - justify-content: center; + background-color: rgba(0, 0, 0, 0.5); + -webkit-tap-highlight-color: transparent; `; -const Backdrop = styled(BackdropUnstyled)` - z-index: -1; +const Modal = styled(ModalUnstyled)` position: fixed; + z-index: 1300; right: 0; bottom: 0; top: 0; left: 0; - background-color: rgba(0, 0, 0, 0.5); - -webkit-tap-highlight-color: transparent; + display: flex; + align-items: center; + justify-content: center; `; const style = (theme: Theme) => ({ @@ -70,10 +66,10 @@ export default function TransitionsModal() { closeAfterTransition slots={{ backdrop: Backdrop }} > - +

Text in a modal

- + Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
diff --git a/docs/data/material/components/modal/SpringModal.js b/docs/data/material/components/modal/SpringModal.js index 4853c4536a1b46..66984e497889c7 100644 --- a/docs/data/material/components/modal/SpringModal.js +++ b/docs/data/material/components/modal/SpringModal.js @@ -8,32 +8,33 @@ import Typography from '@mui/material/Typography'; import { useSpring, animated } from '@react-spring/web'; const Fade = React.forwardRef(function Fade(props, ref) { - const { in: open, children, onEnter, onExited, ...other } = props; + const { in: open, children, onEnter, onExited, onClick, ...other } = props; const style = useSpring({ from: { opacity: 0 }, to: { opacity: open ? 1 : 0 }, onStart: () => { if (open && onEnter) { - onEnter(); + onEnter(null, true); } }, onRest: () => { if (!open && onExited) { - onExited(); + onExited(null, true); } }, }); return ( - {children} + {React.cloneElement(children, { onClick })} ); }); Fade.propTypes = { - children: PropTypes.element, - in: PropTypes.bool.isRequired, + children: PropTypes.element.isRequired, + in: PropTypes.bool, + onClick: PropTypes.any, onEnter: PropTypes.func, onExited: PropTypes.func, }; @@ -64,9 +65,11 @@ export default function SpringModal() { open={open} onClose={handleClose} closeAfterTransition - BackdropComponent={Backdrop} - BackdropProps={{ - timeout: 500, + slots={{ backdrop: Backdrop }} + slotProps={{ + backdrop: { + TransitionComponent: Fade, + }, }} > diff --git a/docs/data/material/components/modal/SpringModal.tsx b/docs/data/material/components/modal/SpringModal.tsx index 1d9dab71c5d561..e83df6c6bcabc7 100644 --- a/docs/data/material/components/modal/SpringModal.tsx +++ b/docs/data/material/components/modal/SpringModal.tsx @@ -7,32 +7,33 @@ import Typography from '@mui/material/Typography'; import { useSpring, animated } from '@react-spring/web'; interface FadeProps { - children?: React.ReactElement; - in: boolean; - onEnter?: () => {}; - onExited?: () => {}; + children: React.ReactElement; + in?: boolean; + onClick?: any; + onEnter?: (node: HTMLElement, isAppearing: boolean) => void; + onExited?: (node: HTMLElement, isAppearing: boolean) => void; } const Fade = React.forwardRef(function Fade(props, ref) { - const { in: open, children, onEnter, onExited, ...other } = props; + const { in: open, children, onEnter, onExited, onClick, ...other } = props; const style = useSpring({ from: { opacity: 0 }, to: { opacity: open ? 1 : 0 }, onStart: () => { if (open && onEnter) { - onEnter(); + onEnter(null as any, true); } }, onRest: () => { if (!open && onExited) { - onExited(); + onExited(null as any, true); } }, }); return ( - {children} + {React.cloneElement(children, { onClick })} ); }); @@ -63,9 +64,11 @@ export default function SpringModal() { open={open} onClose={handleClose} closeAfterTransition - BackdropComponent={Backdrop} - BackdropProps={{ - timeout: 500, + slots={{ backdrop: Backdrop }} + slotProps={{ + backdrop: { + TransitionComponent: Fade, + }, }} > diff --git a/docs/data/material/components/modal/TransitionsModal.js b/docs/data/material/components/modal/TransitionsModal.js index 607f9e939450e5..8a2304e534bb0b 100644 --- a/docs/data/material/components/modal/TransitionsModal.js +++ b/docs/data/material/components/modal/TransitionsModal.js @@ -32,9 +32,11 @@ export default function TransitionsModal() { open={open} onClose={handleClose} closeAfterTransition - BackdropComponent={Backdrop} - BackdropProps={{ - timeout: 500, + slots={{ backdrop: Backdrop }} + slotProps={{ + backdrop: { + timeout: 500, + }, }} > diff --git a/docs/data/material/components/modal/TransitionsModal.tsx b/docs/data/material/components/modal/TransitionsModal.tsx index 8cd21903cc324e..b67e1b2ee08d5f 100644 --- a/docs/data/material/components/modal/TransitionsModal.tsx +++ b/docs/data/material/components/modal/TransitionsModal.tsx @@ -32,9 +32,11 @@ export default function TransitionsModal() { open={open} onClose={handleClose} closeAfterTransition - BackdropComponent={Backdrop} - BackdropProps={{ - timeout: 500, + slots={{ backdrop: Backdrop }} + slotProps={{ + backdrop: { + timeout: 500, + }, }} > diff --git a/docs/pages/material-ui/api/backdrop.json b/docs/pages/material-ui/api/backdrop.json index 61eb4c56ff41ed..b7a0b9a5c2e612 100644 --- a/docs/pages/material-ui/api/backdrop.json +++ b/docs/pages/material-ui/api/backdrop.json @@ -27,6 +27,7 @@ "description": "Array<func
| object
| bool>
| func
| object" } }, + "TransitionComponent": { "type": { "name": "elementType" }, "default": "Fade" }, "transitionDuration": { "type": { "name": "union", diff --git a/docs/translations/api-docs/backdrop/backdrop.json b/docs/translations/api-docs/backdrop/backdrop.json index 24d6eae24c1bbf..e9e00bc3a6b0a8 100644 --- a/docs/translations/api-docs/backdrop/backdrop.json +++ b/docs/translations/api-docs/backdrop/backdrop.json @@ -11,6 +11,7 @@ "slotProps": "The extra props for the slot components. You can override the existing props or add new ones.
This prop is an alias for the componentsProps prop, which will be deprecated in the future.", "slots": "The components used for each slot inside.
This prop is an alias for the components prop, which will be deprecated in the future.", "sx": "The system prop that allows defining system overrides as well as additional CSS styles. See the `sx` page for more details.", + "TransitionComponent": "The component used for the transition. Follow this guide to learn more about the requirements for this component.", "transitionDuration": "The duration for the transition, in milliseconds. You may specify a single timeout for all transitions, or individually with an object." }, "classDescriptions": { diff --git a/packages/mui-base/src/utils/isHostComponent.ts b/packages/mui-base/src/utils/isHostComponent.ts index f94464fe4e38a4..3b22328e9d8873 100644 --- a/packages/mui-base/src/utils/isHostComponent.ts +++ b/packages/mui-base/src/utils/isHostComponent.ts @@ -3,8 +3,6 @@ import * as React from 'react'; /** * Determines if a given element is a DOM element name (i.e. not a React component). */ -function isHostComponent(element: React.ElementType) { +export default function isHostComponent(element: React.ElementType) { return typeof element === 'string'; } - -export default isHostComponent; diff --git a/packages/mui-base/src/utils/mergeSlotProps.ts b/packages/mui-base/src/utils/mergeSlotProps.ts index c7e9ea0d3a1e87..90477e7c111572 100644 --- a/packages/mui-base/src/utils/mergeSlotProps.ts +++ b/packages/mui-base/src/utils/mergeSlotProps.ts @@ -1,3 +1,4 @@ +import * as React from 'react'; import clsx, { ClassValue } from 'clsx'; import { Simplify } from '@mui/types'; import { EventHandlers } from './types'; diff --git a/packages/mui-base/src/utils/types.ts b/packages/mui-base/src/utils/types.ts index b58f09b5332aa3..ead43556174e39 100644 --- a/packages/mui-base/src/utils/types.ts +++ b/packages/mui-base/src/utils/types.ts @@ -1,3 +1,5 @@ +import * as React from 'react'; + export type EventHandlers = Record>; export type WithOptionalOwnerState = Omit & diff --git a/packages/mui-material/src/Backdrop/Backdrop.d.ts b/packages/mui-material/src/Backdrop/Backdrop.d.ts index 83621c33e6fa9a..153cf2eee40563 100644 --- a/packages/mui-material/src/Backdrop/Backdrop.d.ts +++ b/packages/mui-material/src/Backdrop/Backdrop.d.ts @@ -83,6 +83,14 @@ export interface BackdropTypeMap

{ * You may specify a single timeout for all transitions, or individually with an object. */ transitionDuration?: TransitionProps['timeout']; + /** + * The component used for the transition. + * [Follow this guide](/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component. + * @default Fade + */ + TransitionComponent?: React.JSXElementConstructor< + TransitionProps & { children: React.ReactElement } + >; }; defaultComponent: D; } diff --git a/packages/mui-material/src/Backdrop/Backdrop.js b/packages/mui-material/src/Backdrop/Backdrop.js index 459ba3de68a561..888858f680c85f 100644 --- a/packages/mui-material/src/Backdrop/Backdrop.js +++ b/packages/mui-material/src/Backdrop/Backdrop.js @@ -45,17 +45,18 @@ const Backdrop = React.forwardRef(function Backdrop(inProps, ref) { const props = useThemeProps({ props: inProps, name: 'MuiBackdrop' }); const { children, + className, component = 'div', components = {}, componentsProps = {}, - className, invisible = false, open, + // eslint-disable-next-line react/prop-types + ownerState: ownerStateProp, slotProps = {}, slots = {}, - transitionDuration, - // eslint-disable-next-line react/prop-types TransitionComponent = Fade, + transitionDuration, ...other } = props; @@ -170,6 +171,12 @@ Backdrop.propTypes /* remove-proptypes */ = { PropTypes.func, PropTypes.object, ]), + /** + * The component used for the transition. + * [Follow this guide](/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component. + * @default Fade + */ + TransitionComponent: PropTypes.elementType, /** * The duration for the transition, in milliseconds. * You may specify a single timeout for all transitions, or individually with an object.