From 2eced1a48fe6ff71ffaa30bcebff4e60e34dbabc Mon Sep 17 00:00:00 2001 From: Andrey Medvedev Date: Fri, 11 Oct 2024 12:15:20 +0300 Subject: [PATCH] Use AppRootPortal directly in the ModalRoot/PopoutRoot/ActionSheet To avoid rendering modal/popout in SplitLayout during SSR and after hydration --- .../components/ActionSheet/ActionSheet.tsx | 23 ++-- packages/vkui/src/components/Alert/Alert.tsx | 117 ++++++++--------- .../src/components/ModalRoot/ModalRoot.tsx | 119 +++++++++--------- .../src/components/PopoutRoot/PopoutRoot.tsx | 5 +- .../ScreenSpinner/ScreenSpinner.tsx | 15 ++- 5 files changed, 146 insertions(+), 133 deletions(-) diff --git a/packages/vkui/src/components/ActionSheet/ActionSheet.tsx b/packages/vkui/src/components/ActionSheet/ActionSheet.tsx index 0f7c070a89d..5af1576a1b6 100644 --- a/packages/vkui/src/components/ActionSheet/ActionSheet.tsx +++ b/packages/vkui/src/components/ActionSheet/ActionSheet.tsx @@ -6,6 +6,7 @@ import { useAdaptivityWithJSMediaQueries } from '../../hooks/useAdaptivityWithJS import { useObjectMemo } from '../../hooks/useObjectMemo'; import { usePlatform } from '../../hooks/usePlatform'; import { useCSSKeyframesAnimationController } from '../../lib/animation'; +import { AppRootPortal } from '../AppRoot/AppRootPortal'; import { useScrollLock } from '../AppRoot/ScrollContext'; import { PopoutWrapper } from '../PopoutWrapper/PopoutWrapper'; import { Footnote } from '../Typography/Footnote/Footnote'; @@ -140,15 +141,17 @@ export const ActionSheet = ({ } return ( - - {actionSheet} - + + + {actionSheet} + + ); }; diff --git a/packages/vkui/src/components/Alert/Alert.tsx b/packages/vkui/src/components/Alert/Alert.tsx index 422618169a6..c4fc1af52c6 100644 --- a/packages/vkui/src/components/Alert/Alert.tsx +++ b/packages/vkui/src/components/Alert/Alert.tsx @@ -13,6 +13,7 @@ import type { HasDataAttribute, HasRootRef, } from '../../types'; +import { AppRootPortal } from '../AppRoot/AppRootPortal'; import { useScrollLock } from '../AppRoot/ScrollContext'; import type { ButtonProps } from '../Button/Button'; import { FocusTrap } from '../FocusTrap/FocusTrap'; @@ -134,67 +135,69 @@ export const Alert = ({ useScrollLock(); return ( - - + -
- {hasReactNode(header) && {header}} - {hasReactNode(text) && {text}} - {children} - {isDismissButtonVisible && dismissButtonMode === 'inside' && ( - - - +
+ {hasReactNode(header) && {header}} + {hasReactNode(text) && {text}} + {children} + {isDismissButtonVisible && dismissButtonMode === 'inside' && ( + + + + )} +
+ + {isDismissButtonVisible && dismissButtonMode === 'outside' && ( + + {dismissLabel} + )} -
- - {isDismissButtonVisible && dismissButtonMode === 'outside' && ( - - {dismissLabel} - - )} -
-
+ + + ); }; diff --git a/packages/vkui/src/components/ModalRoot/ModalRoot.tsx b/packages/vkui/src/components/ModalRoot/ModalRoot.tsx index dd7717f69ca..8eae410c35c 100644 --- a/packages/vkui/src/components/ModalRoot/ModalRoot.tsx +++ b/packages/vkui/src/components/ModalRoot/ModalRoot.tsx @@ -9,6 +9,7 @@ import { type DOMProps, withDOM } from '../../lib/dom'; import { getNavId } from '../../lib/getNavId'; import { rubber } from '../../lib/touch'; import { warnOnce } from '../../lib/warnOnce'; +import { AppRootPortal } from '../AppRoot/AppRootPortal'; import { ConfigProviderContext } from '../ConfigProvider/ConfigProviderContext'; import { FocusTrap } from '../FocusTrap/FocusTrap'; import { type CustomTouchEvent, Touch } from '../Touch/Touch'; @@ -544,63 +545,67 @@ class ModalRootTouchComponent extends React.Component< } return ( - - - -
-
- {this.getModals().map((Modal) => { - const modalId = getNavId(Modal.props, warn); - const _modalState = this.props.getModalState(modalId); - if ((modalId !== activeModal && modalId !== exitingModal) || !_modalState) { - return null; - } - const modalState = { ..._modalState }; - - const isPage = modalState.type === 'page'; - const key = `modal-${modalId}`; - - return ( - - {Modal} - - ); - })} -
- - - + + + + +
+
+ {this.getModals().map((Modal) => { + const modalId = getNavId(Modal.props, warn); + const _modalState = this.props.getModalState(modalId); + if ((modalId !== activeModal && modalId !== exitingModal) || !_modalState) { + return null; + } + const modalState = { ..._modalState }; + + const isPage = modalState.type === 'page'; + const key = `modal-${modalId}`; + + return ( + + {Modal} + + ); + })} +
+ + + + ); } } diff --git a/packages/vkui/src/components/PopoutRoot/PopoutRoot.tsx b/packages/vkui/src/components/PopoutRoot/PopoutRoot.tsx index 62b6d949585..9cfeaeee205 100644 --- a/packages/vkui/src/components/PopoutRoot/PopoutRoot.tsx +++ b/packages/vkui/src/components/PopoutRoot/PopoutRoot.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { classNames } from '@vkontakte/vkjs'; import type { HTMLAttributesWithRootRef } from '../../types'; -import { AppRootPortal } from '../AppRoot/AppRootPortal'; import { RootComponent } from '../RootComponent/RootComponent'; import styles from './PopoutRoot.module.css'; @@ -42,10 +41,10 @@ export const PopoutRoot = ({ return ( {children} - +
{!!popout && {popout}} {!!modal && {modal}} - +
); }; diff --git a/packages/vkui/src/components/ScreenSpinner/ScreenSpinner.tsx b/packages/vkui/src/components/ScreenSpinner/ScreenSpinner.tsx index 105ea91fb2d..b19fa5d9de5 100644 --- a/packages/vkui/src/components/ScreenSpinner/ScreenSpinner.tsx +++ b/packages/vkui/src/components/ScreenSpinner/ScreenSpinner.tsx @@ -1,6 +1,7 @@ 'use client'; import * as React from 'react'; +import { AppRootPortal } from '../AppRoot/AppRootPortal'; import { useScrollLock } from '../AppRoot/ScrollContext'; import { PopoutWrapper } from '../PopoutWrapper/PopoutWrapper'; import { ScreenSpinnerContainer } from './ScreenSpinnerContainer'; @@ -31,12 +32,14 @@ export const ScreenSpinner: React.FC & { useScrollLock(); return ( - - - - - - + + + + + + + + ); };