@@ -2,13 +2,14 @@ import EventStack from '@semantic-ui-react/event-stack'
22import cx from 'clsx'
33import _ from 'lodash'
44import PropTypes from 'prop-types'
5- import React , { Component , createRef } from 'react'
5+ import React , { Component } from 'react'
66import { Popper } from 'react-popper'
77import shallowEqual from 'shallowequal'
88
99import {
1010 eventStack ,
1111 childrenUtils ,
12+ createHTMLDivision ,
1213 customPropTypes ,
1314 getElementType ,
1415 getUnhandledProps ,
@@ -32,7 +33,9 @@ export default class Popup extends Component {
3233 state = { }
3334
3435 open = false
35- triggerRef = createRef ( )
36+ zIndexWasSynced = false
37+
38+ triggerRef = React . createRef ( )
3639
3740 static getDerivedStateFromProps ( props , state ) {
3841 if ( state . closed || state . disabled ) return { }
@@ -145,6 +148,7 @@ export default class Popup extends Component {
145148 flowing,
146149 header,
147150 inverted,
151+ popper,
148152 size,
149153 style,
150154 wide,
@@ -174,25 +178,36 @@ export default class Popup extends Component {
174178 ...style ,
175179 }
176180
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 >
195193 )
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+ } )
196211 }
197212
198213 render ( ) {
@@ -202,6 +217,7 @@ export default class Popup extends Component {
202217 eventsEnabled,
203218 offset,
204219 pinned,
220+ popper,
205221 popperModifiers,
206222 position,
207223 positionFixed,
@@ -220,6 +236,37 @@ export default class Popup extends Component {
220236 { name : 'preventOverflow' , enabled : ! ! offset } ,
221237 { name : 'offset' , enabled : ! ! offset , options : { offset } } ,
222238 ...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+ } ,
223270 ]
224271 debug ( 'popper modifiers:' , modifiers )
225272
@@ -352,6 +399,9 @@ Popup.propTypes = {
352399 /** Tells `Popper.js` to use the `position: fixed` strategy to position the popover. */
353400 positionFixed : PropTypes . bool ,
354401
402+ /** A wrapping element for an actual content that will be used for positioning. */
403+ popper : customPropTypes . itemShorthand ,
404+
355405 /** An array containing custom settings for the Popper.js modifiers. */
356406 popperModifiers : PropTypes . array ,
357407
0 commit comments