88 */
99
1010import React , {
11- useRef ,
1211 useMemo ,
13- useState ,
14- useLayoutEffect ,
1512 useCallback ,
1613 Fragment ,
1714 type ComponentProps ,
1815 type FC ,
1916 type ReactElement ,
2017} from 'react' ;
18+ import { Global } from '@emotion/react' ;
2119import {
2220 EuiButton ,
2321 EuiModal ,
@@ -77,38 +75,9 @@ const TabbedModalInner: FC<ITabbedModalInner> = ({
7775} ) => {
7876 const { tabs, state, dispatch } =
7977 useModalContext < Array < IModalTabDeclaration < Record < string , any > > > > ( ) ;
80- const { selectedTabId, defaultSelectedTabId } = state . meta ;
78+ const { selectedTabId } = state . meta ;
8179 const tabbedModalHTMLId = useGeneratedHtmlId ( { prefix : 'tabbedModal' } ) ;
82- const tabbedModalHeadingHTMLId = useGeneratedHtmlId ( { prefix : 'tabbedModal' } ) ;
83- const defaultTabCoordinates = useRef ( new Map < string , Pick < DOMRect , 'top' > > ( ) ) ;
84- const [ translateYValue , setTranslateYValue ] = useState ( 0 ) ;
85-
86- const onTabContentRender = useCallback ( ( ) => {
87- const tabbedModal = document . querySelector ( `[id="${ tabbedModalHTMLId } "]` ) as HTMLDivElement ;
88-
89- if ( ! defaultTabCoordinates . current . get ( defaultSelectedTabId ) ) {
90- // on initial render the modal animates into it's final position
91- // hence the need to wait till said animation has completed
92- tabbedModal . onanimationend = ( ) => {
93- const { top } = tabbedModal . getBoundingClientRect ( ) ;
94- defaultTabCoordinates . current . set ( defaultSelectedTabId , { top } ) ;
95- } ;
96- } else {
97- let translateYOverride = 0 ;
98-
99- if ( defaultSelectedTabId !== selectedTabId ) {
100- const defaultTabData = defaultTabCoordinates . current . get ( defaultSelectedTabId ) ;
101-
102- const rect = tabbedModal . getBoundingClientRect ( ) ;
103-
104- translateYOverride = translateYValue + ( defaultTabData ?. top ! - rect . top ) ;
105- }
106-
107- if ( translateYOverride !== translateYValue ) {
108- setTranslateYValue ( translateYOverride ) ;
109- }
110- }
111- } , [ tabbedModalHTMLId , defaultSelectedTabId , selectedTabId , translateYValue ] ) ;
80+ const tabbedModalHeadingHTMLId = useGeneratedHtmlId ( { prefix : 'tabbedModalHeading' } ) ;
11281
11382 const selectedTabState = useMemo (
11483 ( ) => ( selectedTabId ? state [ selectedTabId ] : { } ) ,
@@ -152,12 +121,6 @@ const TabbedModalInner: FC<ITabbedModalInner> = ({
152121 ) ;
153122 } , [ onSelectedTabChanged , selectedTabId , tabs ] ) ;
154123
155- const modalPositionOverrideStyles : React . CSSProperties = {
156- transform : `translateY(${ translateYValue } px)` ,
157- transformOrigin : 'top' ,
158- willChange : 'transform' ,
159- } ;
160-
161124 return (
162125 < EuiModal
163126 id = { tabbedModalHTMLId }
@@ -169,36 +132,32 @@ const TabbedModalInner: FC<ITabbedModalInner> = ({
169132 data-test-subj = { props [ 'data-test-subj' ] }
170133 css = { {
171134 ...( modalWidth ? { width : modalWidth } : { } ) ,
172- ...modalPositionOverrideStyles ,
173135 } }
174136 aria-labelledby = { tabbedModalHeadingHTMLId }
175137 >
138+ < Global
139+ styles = { {
140+ // overrides so modal retains a fixed position from top of viewport, despite having content of varying heights
141+ [ `.euiOverlayMask:has([id="${ tabbedModalHTMLId } "])` ] : {
142+ alignItems : 'flex-start' ,
143+ paddingBlockStart : '20vh' ,
144+ } ,
145+ } }
146+ />
176147 < EuiModalHeader >
177148 < EuiModalHeaderTitle id = { tabbedModalHeadingHTMLId } > { modalTitle } </ EuiModalHeaderTitle >
178149 </ EuiModalHeader >
179150 < EuiModalBody >
180- < Fragment >
181- < Fragment > { renderTabs ( ) } </ Fragment >
182- < EuiSpacer size = "m" />
183- { React . createElement ( function RenderSelectedTabContent ( ) {
184- useLayoutEffect ( ( ) => {
185- requestAnimationFrame ( onTabContentRender ) ;
186- } , [ ] ) ;
187- return (
188- < div
189- css = { { display : 'contents' } }
190- data-test-subj = { `tabbedModal-${ selectedTabId } -content` }
191- >
192- < SelectedTabContent
193- { ...{
194- state : selectedTabState ,
195- dispatch,
196- } }
197- />
198- </ div >
199- ) ;
200- } ) }
201- </ Fragment >
151+ < Fragment > { renderTabs ( ) } </ Fragment >
152+ < EuiSpacer size = "m" />
153+ < div css = { { display : 'contents' } } data-test-subj = { `tabbedModal-${ selectedTabId } -content` } >
154+ < SelectedTabContent
155+ { ...{
156+ state : selectedTabState ,
157+ dispatch,
158+ } }
159+ />
160+ </ div >
202161 </ EuiModalBody >
203162 { modalActionBtn ?. id !== undefined && selectedTabState && (
204163 < EuiModalFooter >
0 commit comments