@@ -25,6 +25,7 @@ interface CheckoutModalContextValue {
2525 closeModal : ( ) => void
2626 openCloseConfirmation : ( ) => void
2727 panelEl : HTMLDivElement | null
28+ inline : boolean
2829}
2930
3031export const CheckoutModalContext : React . Context < CheckoutModalContextValue | null > =
@@ -39,7 +40,7 @@ export type { CheckoutModalRef }
3940export const CheckoutModal : ForwardRefExoticComponent <
4041 PropsWithChildren < CheckoutModalProps > & RefAttributes < CheckoutModalRef >
4142> = forwardRef < CheckoutModalRef , PropsWithChildren < CheckoutModalProps > > (
42- ( { elementRef, open, onClose, children } , ref ) => {
43+ ( { elementRef, open, onClose, inline , children } , ref ) => {
4344 const openRef = useRef ( Boolean ( open ) )
4445 const [ visible , setVisible ] = useState ( Boolean ( open ) )
4546 const [ confirmOpen , setConfirmOpen ] = useState ( false )
@@ -98,68 +99,103 @@ export const CheckoutModal: ForwardRefExoticComponent<
9899
99100 const modalContext : CheckoutModalContextValue = useMemo (
100101 ( ) => ( {
101- closeModal : closePanel ,
102- openCloseConfirmation : ( ) => setConfirmOpen ( true ) ,
102+ closeModal : inline ? ( ) => { } : closePanel ,
103+ openCloseConfirmation : inline ? ( ) => { } : ( ) => setConfirmOpen ( true ) ,
103104 panelEl,
105+ inline : Boolean ( inline ) ,
104106 } ) ,
105- [ closePanel , panelEl ]
107+ [ inline , closePanel , panelEl ]
106108 )
107109
108- return (
109- < CheckoutModalContext . Provider value = { modalContext } >
110- < Modal
111- open = { visible }
112- onClose = { handleModalClose }
113- keepMounted = { false }
114- slotProps = {
115- {
116- backdrop : {
117- sx : ( theme : Theme ) => ( {
118- backgroundColor : `rgba(${ theme . vars . palette . common . onBackgroundChannel } / 0.48)` ,
119- } ) ,
120- } ,
121- transition : {
122- timeout : { appear : 0 , enter : 160 , exit : 80 } ,
123- } ,
124- } as Parameters < typeof Modal > [ 0 ] [ 'slotProps' ]
110+ const panel = (
111+ < Box
112+ ref = { ( el : HTMLDivElement | null ) => {
113+ setPanelEl ( el )
114+ if ( elementRef ) {
115+ elementRef . current = el
125116 }
126- >
127- < Box
128- ref = { ( el : HTMLDivElement | null ) => {
129- setPanelEl ( el )
130- if ( elementRef ) {
131- elementRef . current = el
117+ } }
118+ tabIndex = { - 1 }
119+ role = "dialog"
120+ aria-modal = { inline ? undefined : 'true' }
121+ aria-label = "Checkout"
122+ sx = { ( theme ) =>
123+ inline
124+ ? {
125+ position : 'relative' ,
126+ display : 'flex' ,
127+ flexDirection : 'column' ,
128+ minHeight : 0 ,
129+ outline : 'none' ,
130+ width : `min(100%, ${ theme . breakpoints . values . sm } px)` ,
131+ maxHeight : 'min(90dvh, 640px)' ,
132+ overflow : 'hidden' ,
133+ // Inherit only the host widget theme's card *appearance*
134+ // (radius, shadow/border) so the inline panel matches the
135+ // standard widget — never its layout props (display/height),
136+ // which would break the panel's internal scroll.
137+ background :
138+ theme . container ?. background ??
139+ theme . vars . palette . background . default ,
140+ borderRadius :
141+ theme . container ?. borderRadius ??
142+ theme . vars . shape . borderRadiusTertiary ,
143+ border : theme . container ?. border ,
144+ boxShadow : theme . container ?. boxShadow ,
145+ filter : theme . container ?. filter ,
132146 }
133- } }
134- tabIndex = { - 1 }
135- role = "dialog"
136- aria-modal = "true"
137- aria-label = "Checkout"
138- sx = { ( theme ) => ( {
139- position : 'absolute' ,
140- top : '50%' ,
141- left : '50%' ,
142- transform : 'translate(-50%, -50%)' ,
143- width : `min(calc(100vw - 32px), ${ theme . breakpoints . values . sm } px)` ,
144- maxHeight : '90dvh' ,
145- display : 'flex' ,
146- flexDirection : 'column' ,
147- outline : 'none' ,
148- borderRadius : theme . vars . shape . borderRadiusTertiary ,
149- boxShadow : theme . shadows [ 24 ] ,
150- bgcolor : 'background.default' ,
151- overflow : 'hidden' ,
152- } ) }
147+ : {
148+ position : 'absolute' ,
149+ top : '50%' ,
150+ left : '50%' ,
151+ transform : 'translate(-50%, -50%)' ,
152+ width : `min(calc(100vw - 32px), ${ theme . breakpoints . values . sm } px)` ,
153+ maxHeight : '90dvh' ,
154+ display : 'flex' ,
155+ flexDirection : 'column' ,
156+ outline : 'none' ,
157+ borderRadius : theme . vars . shape . borderRadiusTertiary ,
158+ boxShadow : theme . shadows [ 24 ] ,
159+ bgcolor : 'background.default' ,
160+ overflow : 'hidden' ,
161+ }
162+ }
163+ >
164+ { children }
165+ < CloseConfirmationDialog
166+ open = { confirmOpen }
167+ onCancel = { handleCancelConfirm }
168+ onConfirm = { handleConfirmConfirm }
169+ container = { panelEl }
170+ />
171+ </ Box >
172+ )
173+
174+ return (
175+ < CheckoutModalContext . Provider value = { modalContext } >
176+ { inline ? (
177+ panel
178+ ) : (
179+ < Modal
180+ open = { visible }
181+ onClose = { handleModalClose }
182+ keepMounted = { false }
183+ slotProps = {
184+ {
185+ backdrop : {
186+ sx : ( theme : Theme ) => ( {
187+ backgroundColor : `rgba(${ theme . vars . palette . common . onBackgroundChannel } / 0.48)` ,
188+ } ) ,
189+ } ,
190+ transition : {
191+ timeout : { appear : 0 , enter : 160 , exit : 80 } ,
192+ } ,
193+ } as Parameters < typeof Modal > [ 0 ] [ 'slotProps' ]
194+ }
153195 >
154- { children }
155- < CloseConfirmationDialog
156- open = { confirmOpen }
157- onCancel = { handleCancelConfirm }
158- onConfirm = { handleConfirmConfirm }
159- container = { panelEl }
160- />
161- </ Box >
162- </ Modal >
196+ { panel }
197+ </ Modal >
198+ ) }
163199 </ CheckoutModalContext . Provider >
164200 )
165201 }
0 commit comments