Skip to content

Commit 488d569

Browse files
committed
fix: show ConfirmationModal animation in some places
1 parent a5b5162 commit 488d569

File tree

4 files changed

+59
-12
lines changed

4 files changed

+59
-12
lines changed

src/Shared/Components/ConfirmationModal/ConfirmationModal.tsx

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ import { ComponentSizeType } from '@Shared/constants'
2121
import { ConfirmationModalBodyProps, ConfirmationModalProps } from './types'
2222
import { getPrimaryButtonStyleFromVariant, getConfirmationLabel, getIconFromVariant } from './utils'
2323
import { Button, ButtonStyleType, ButtonVariantType } from '../Button'
24-
import './confirmationModal.scss'
2524
import { Backdrop } from '../Backdrop'
25+
import { useConfirmationModalContext } from './ConfirmationModalContext'
26+
import './confirmationModal.scss'
2627

2728
const ConfirmationModalBody = ({
2829
title,
@@ -156,14 +157,40 @@ const ConfirmationModalBody = ({
156157
)
157158
}
158159

159-
const ConfirmationModal = ({ showConfirmationModal, ...props }: ConfirmationModalProps) => (
160-
<AnimatePresence>{showConfirmationModal ? <ConfirmationModalBody {...props} /> : null}</AnimatePresence>
161-
)
160+
/**
161+
* NOTE: In some cases, we use a boolean useState to render Modals.
162+
* This approach can cause issues with the animation of ConfirmationModals,
163+
* as the animation requires the ConfirmationModal to remain mounted,
164+
* and only toggle the showConfirmationModal prop to true when it needs to be displayed.
165+
* This implementation serves as a workaround to allow modals to function as required.
166+
*
167+
* Please see NodeActionMenu.tsx as an example of why this is required
168+
*/
169+
export const BaseConfirmationModal = () => {
170+
const { props } = useConfirmationModalContext()
162171

163-
const WrapWithShortcutProvider = (props: ConfirmationModalProps) => (
164-
<UseRegisterShortcutProvider ignoreTags={['button']}>
165-
<ConfirmationModal {...props} />
166-
</UseRegisterShortcutProvider>
167-
)
172+
return (
173+
<UseRegisterShortcutProvider ignoreTags={['button']}>
174+
<AnimatePresence>{props && <ConfirmationModalBody {...props} />}</AnimatePresence>
175+
</UseRegisterShortcutProvider>
176+
)
177+
}
178+
179+
const ConfirmationModal = ({ showConfirmationModal, ...props }: ConfirmationModalProps) => {
180+
const { setProps } = useConfirmationModalContext()
181+
182+
useEffect(() => {
183+
setProps(showConfirmationModal ? props : null)
184+
}, [showConfirmationModal])
185+
186+
useEffect(
187+
() => () => {
188+
setProps(null)
189+
},
190+
[],
191+
)
192+
193+
return null
194+
}
168195

169-
export default WrapWithShortcutProvider
196+
export default ConfirmationModal
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { createContext, PropsWithChildren, useContext, useMemo, useState } from 'react'
2+
import { ConfirmationModalContextType } from './types'
3+
4+
export const ConfirmationModalContext = createContext<ConfirmationModalContextType>(null)
5+
6+
export const ConfirmationModalProvider = ({ children }: PropsWithChildren<{}>) => {
7+
const [props, setProps] = useState<ConfirmationModalContextType['props']>(null)
8+
9+
const value = useMemo(() => ({ props, setProps }), [props])
10+
11+
return <ConfirmationModalContext.Provider value={value}>{children}</ConfirmationModalContext.Provider>
12+
}
13+
14+
export const useConfirmationModalContext = () => useContext(ConfirmationModalContext)

src/Shared/Components/ConfirmationModal/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
* limitations under the License.
1515
*/
1616

17-
export { default as ConfirmationModal } from './ConfirmationModal'
17+
export { default as ConfirmationModal, BaseConfirmationModal } from './ConfirmationModal'
1818
export { DeleteConfirmationModal } from './DeleteConfirmationModal'
1919
export { ForceDeleteConfirmationModal } from './ForceDeleteConfirmationModal'
2020
export { CannotDeleteModal } from './CannotDeleteModal'
2121
export { ConfirmationModalVariantType, type ConfirmationModalProps } from './types'
22+
export { ConfirmationModalProvider } from './ConfirmationModalContext'

src/Shared/Components/ConfirmationModal/types.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { PropsWithChildren, ReactElement, ReactNode, SyntheticEvent } from 'react'
17+
import { Dispatch, PropsWithChildren, ReactElement, ReactNode, SetStateAction, SyntheticEvent } from 'react'
1818
import { ButtonProps } from '../Button'
1919

2020
export enum ConfirmationModalVariantType {
@@ -181,3 +181,8 @@ export interface ForceDeleteConfirmationProps
181181
Pick<DeleteConfirmationModalProps, 'onDelete' | 'showConfirmationModal' | 'closeConfirmationModal'>
182182
>,
183183
Partial<Pick<ConfirmationModalProps, 'title' | 'subtitle'>> {}
184+
185+
export interface ConfirmationModalContextType {
186+
props: Omit<ConfirmationModalProps, 'showConfirmationModal'> | null
187+
setProps: Dispatch<SetStateAction<ConfirmationModalContextType['props']>>
188+
}

0 commit comments

Comments
 (0)