@@ -2,13 +2,14 @@ import EventStack from '@semantic-ui-react/event-stack'
2
2
import cx from 'clsx'
3
3
import _ from 'lodash'
4
4
import PropTypes from 'prop-types'
5
- import React , { Component , createRef } from 'react'
5
+ import React , { Component } from 'react'
6
6
import { Popper } from 'react-popper'
7
7
import shallowEqual from 'shallowequal'
8
8
9
9
import {
10
10
eventStack ,
11
11
childrenUtils ,
12
+ createHTMLDivision ,
12
13
customPropTypes ,
13
14
getElementType ,
14
15
getUnhandledProps ,
@@ -32,7 +33,9 @@ export default class Popup extends Component {
32
33
state = { }
33
34
34
35
open = false
35
- triggerRef = createRef ( )
36
+ zIndexWasSynced = false
37
+
38
+ triggerRef = React . createRef ( )
36
39
37
40
static getDerivedStateFromProps ( props , state ) {
38
41
if ( state . closed || state . disabled ) return { }
@@ -145,6 +148,7 @@ export default class Popup extends Component {
145
148
flowing,
146
149
header,
147
150
inverted,
151
+ popper,
148
152
size,
149
153
style,
150
154
wide,
@@ -174,25 +178,36 @@ export default class Popup extends Component {
174
178
...style ,
175
179
}
176
180
177
- return (
178
- // https://github.com/popperjs/popper-core/blob/f1f9d1ab75b6b0e962f90a5b2a50f6cfd307d794/src/createPopper.js#L136-L137
179
- // Heads up!
180
- // A wrapping `div` there is a pure magic, it's required as Popper warns on margins that are
181
- // defined by SUI CSS. It also means that this `div` will be positioned instead of `content`.
182
- < div ref = { popperRef } style = { popperStyle } >
183
- < ElementType { ...contentRestProps } className = { classes } style = { styles } >
184
- { childrenUtils . isNil ( children ) ? (
185
- < >
186
- { PopupHeader . create ( header , { autoGenerateKey : false } ) }
187
- { PopupContent . create ( content , { autoGenerateKey : false } ) }
188
- </ >
189
- ) : (
190
- children
191
- ) }
192
- { hideOnScroll && < EventStack on = { this . hideOnScroll } name = 'scroll' target = 'window' /> }
193
- </ ElementType >
194
- </ div >
181
+ const innerElement = (
182
+ < ElementType { ...contentRestProps } className = { classes } style = { styles } >
183
+ { childrenUtils . isNil ( children ) ? (
184
+ < >
185
+ { PopupHeader . create ( header , { autoGenerateKey : false } ) }
186
+ { PopupContent . create ( content , { autoGenerateKey : false } ) }
187
+ </ >
188
+ ) : (
189
+ children
190
+ ) }
191
+ { hideOnScroll && < EventStack on = { this . hideOnScroll } name = 'scroll' target = 'window' /> }
192
+ </ ElementType >
195
193
)
194
+
195
+ // https://github.com/popperjs/popper-core/blob/f1f9d1ab75b6b0e962f90a5b2a50f6cfd307d794/src/createPopper.js#L136-L137
196
+ // Heads up!
197
+ // A wrapping `div` there is a pure magic, it's required as Popper warns on margins that are
198
+ // defined by SUI CSS. It also means that this `div` will be positioned instead of `content`.
199
+ return createHTMLDivision ( popper || { } , {
200
+ overrideProps : {
201
+ children : innerElement ,
202
+ ref : popperRef ,
203
+ style : {
204
+ // Fixes layout for floated elements
205
+ // https://github.com/Semantic-Org/Semantic-UI-React/issues/4092
206
+ display : 'flex' ,
207
+ ...popperStyle ,
208
+ } ,
209
+ } ,
210
+ } )
196
211
}
197
212
198
213
render ( ) {
@@ -202,6 +217,7 @@ export default class Popup extends Component {
202
217
eventsEnabled,
203
218
offset,
204
219
pinned,
220
+ popper,
205
221
popperModifiers,
206
222
position,
207
223
positionFixed,
@@ -220,6 +236,37 @@ export default class Popup extends Component {
220
236
{ name : 'preventOverflow' , enabled : ! ! offset } ,
221
237
{ name : 'offset' , enabled : ! ! offset , options : { offset } } ,
222
238
...popperModifiers ,
239
+
240
+ // We are syncing zIndex from `.ui.popup.content` to avoid layering issues as in SUIR we are using an additional
241
+ // `div` for Popper.js
242
+ // https://github.com/Semantic-Org/Semantic-UI-React/issues/4083
243
+ {
244
+ name : 'syncZIndex' ,
245
+ enabled : true ,
246
+ phase : 'beforeRead' ,
247
+ fn : ( { state } ) => {
248
+ if ( this . zIndexWasSynced ) {
249
+ return
250
+ }
251
+
252
+ // if zIndex defined in <Popup popper={{ style: {} }} /> there is no sense to override it
253
+ const definedZIndex = popper ?. style ?. zIndex
254
+
255
+ if ( _ . isUndefined ( definedZIndex ) ) {
256
+ // eslint-disable-next-line no-param-reassign
257
+ state . elements . popper . style . zIndex = window . getComputedStyle (
258
+ state . elements . popper . firstChild ,
259
+ ) . zIndex
260
+ }
261
+
262
+ this . zIndexWasSynced = true
263
+ } ,
264
+ effect : ( ) => {
265
+ return ( ) => {
266
+ this . zIndexWasSynced = false
267
+ }
268
+ } ,
269
+ } ,
223
270
]
224
271
debug ( 'popper modifiers:' , modifiers )
225
272
@@ -352,6 +399,9 @@ Popup.propTypes = {
352
399
/** Tells `Popper.js` to use the `position: fixed` strategy to position the popover. */
353
400
positionFixed : PropTypes . bool ,
354
401
402
+ /** A wrapping element for an actual content that will be used for positioning. */
403
+ popper : customPropTypes . itemShorthand ,
404
+
355
405
/** An array containing custom settings for the Popper.js modifiers. */
356
406
popperModifiers : PropTypes . array ,
357
407
0 commit comments