1- import { forwardRef , useLayoutEffect , useRef , type ReactNode } from 'react' ;
2- import { createPortal } from 'react-dom' ;
1+ import { forwardRef , type ReactNode } from 'react' ;
32import { Button } from '@/components/ui/Button' ;
43import { LoadingSpinner } from '@/components/ui/LoadingSpinner' ;
54import { IconChevronLeft } from '@/components/ui/icons' ;
6- import { usePageTransitionLayer } from './PageTransitionLayer' ;
75import styles from './SecondaryScreenShell.module.scss' ;
86
97export type SecondaryScreenShellProps = {
@@ -12,9 +10,6 @@ export type SecondaryScreenShellProps = {
1210 backLabel ?: string ;
1311 backAriaLabel ?: string ;
1412 rightAction ?: ReactNode ;
15- hideTopBarBackButton ?: boolean ;
16- hideTopBarRightAction ?: boolean ;
17- floatingAction ?: ReactNode ;
1813 isLoading ?: boolean ;
1914 loadingLabel ?: ReactNode ;
2015 className ?: string ;
@@ -30,9 +25,6 @@ export const SecondaryScreenShell = forwardRef<HTMLDivElement, SecondaryScreenSh
3025 backLabel = 'Back' ,
3126 backAriaLabel,
3227 rightAction,
33- hideTopBarBackButton = false ,
34- hideTopBarRightAction = false ,
35- floatingAction,
3628 isLoading = false ,
3729 loadingLabel = 'Loading...' ,
3830 className = '' ,
@@ -42,94 +34,44 @@ export const SecondaryScreenShell = forwardRef<HTMLDivElement, SecondaryScreenSh
4234 ref
4335 ) {
4436 const containerClassName = [ styles . container , className ] . filter ( Boolean ) . join ( ' ' ) ;
45- const contentClasses = [
46- styles . content ,
47- floatingAction ? styles . contentWithFloatingAction : '' ,
48- contentClassName ,
49- ]
50- . filter ( Boolean )
51- . join ( ' ' ) ;
37+ const contentClasses = [ styles . content , contentClassName ] . filter ( Boolean ) . join ( ' ' ) ;
5238 const titleTooltip = typeof title === 'string' ? title : undefined ;
5339 const resolvedBackAriaLabel = backAriaLabel ?? backLabel ;
54- const pageTransitionLayer = usePageTransitionLayer ( ) ;
55- const isCurrentLayer = pageTransitionLayer ? pageTransitionLayer . isCurrentLayer : true ;
56- const shouldRenderFloatingAction = Boolean ( floatingAction ) && isCurrentLayer ;
57- const floatingActionRef = useRef < HTMLDivElement | null > ( null ) ;
58-
59- useLayoutEffect ( ( ) => {
60- if ( ! shouldRenderFloatingAction ) return ;
61-
62- const element = floatingActionRef . current ;
63- if ( ! element ) return ;
64-
65- const updateHeight = ( ) => {
66- const height = element . getBoundingClientRect ( ) . height ;
67- document . documentElement . style . setProperty (
68- '--secondary-shell-floating-action-height' ,
69- `${ height } px`
70- ) ;
71- } ;
72-
73- updateHeight ( ) ;
74- window . addEventListener ( 'resize' , updateHeight ) ;
75-
76- const resizeObserver =
77- typeof ResizeObserver === 'undefined' ? null : new ResizeObserver ( updateHeight ) ;
78- resizeObserver ?. observe ( element ) ;
79-
80- return ( ) => {
81- resizeObserver ?. disconnect ( ) ;
82- window . removeEventListener ( 'resize' , updateHeight ) ;
83- document . documentElement . style . removeProperty ( '--secondary-shell-floating-action-height' ) ;
84- } ;
85- } , [ shouldRenderFloatingAction ] ) ;
8640
8741 return (
88- < >
89- < div className = { containerClassName } ref = { ref } >
90- < div className = { styles . topBar } >
91- { onBack && ! hideTopBarBackButton ? (
92- < Button
93- variant = "ghost"
94- size = "sm"
95- onClick = { onBack }
96- className = { styles . backButton }
97- aria-label = { resolvedBackAriaLabel }
98- >
99- < span className = { styles . backIcon } >
100- < IconChevronLeft size = { 18 } />
101- </ span >
102- < span className = { styles . backText } > { backLabel } </ span >
103- </ Button >
104- ) : (
105- < div />
106- ) }
107- < div className = { styles . topBarTitle } title = { titleTooltip } >
108- { title }
109- </ div >
110- < div className = { styles . rightSlot } > { hideTopBarRightAction ? null : rightAction } </ div >
111- </ div >
112-
113- { isLoading ? (
114- < div className = { styles . loadingState } >
115- < LoadingSpinner size = { 16 } />
116- < span > { loadingLabel } </ span >
117- </ div >
42+ < div className = { containerClassName } ref = { ref } >
43+ < div className = { styles . topBar } >
44+ { onBack ? (
45+ < Button
46+ variant = "ghost"
47+ size = "sm"
48+ onClick = { onBack }
49+ className = { styles . backButton }
50+ aria-label = { resolvedBackAriaLabel }
51+ >
52+ < span className = { styles . backIcon } >
53+ < IconChevronLeft size = { 18 } />
54+ </ span >
55+ < span className = { styles . backText } > { backLabel } </ span >
56+ </ Button >
11857 ) : (
119- < div className = { contentClasses } > { children } </ div >
58+ < div / >
12059 ) }
60+ < div className = { styles . topBarTitle } title = { titleTooltip } >
61+ { title }
62+ </ div >
63+ < div className = { styles . rightSlot } > { rightAction } </ div >
12164 </ div >
122- { shouldRenderFloatingAction && typeof document !== 'undefined'
123- ? createPortal (
124- < div className = { styles . floatingActionContainer } >
125- < div className = { styles . floatingActionSurface } ref = { floatingActionRef } >
126- { floatingAction }
127- </ div >
128- </ div > ,
129- document . body
130- )
131- : null }
132- </ >
65+
66+ { isLoading ? (
67+ < div className = { styles . loadingState } >
68+ < LoadingSpinner size = { 16 } />
69+ < span > { loadingLabel } </ span >
70+ </ div >
71+ ) : (
72+ < div className = { contentClasses } > { children } </ div >
73+ ) }
74+ </ div >
13375 ) ;
13476 }
13577) ;
0 commit comments