Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/addons/Portal/Portal.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ export interface StrictPortalProps {
/** Event pool namespace that is used to handle component events. */
eventPool?: string

/** Hide the Popup when scrolling the window. */
hideOnScroll?: boolean

/** The node where the portal should mount. */
mountNode?: any

Expand Down
31 changes: 31 additions & 0 deletions src/addons/Portal/Portal.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ function Portal(props) {
openOnTriggerClick = true,
openOnTriggerFocus,
openOnTriggerMouseEnter,
hideOnScroll = false,
} = props

const [open, setOpen] = useAutoControlledValue({
Expand Down Expand Up @@ -146,6 +147,33 @@ function Portal(props) {
// Component Event Handlers
// ----------------------------------------

React.useEffect(() => {
if (!hideOnScroll) {
return
}
const abortController = new AbortController()

window.addEventListener(
'scroll',
(e) => {
debug('handleHideOnScroll()')

// Do not hide the popup when scroll comes from inside the popup
// https://github.com/Semantic-Org/Semantic-UI-React/issues/4305
if (_.isElement(e.target) && contentRef.current.contains(e.target)) {
return
}

closePortal(e)
},
{ signal: abortController.signal, passive: true },
)

return () => {
abortController.abort()
}
}, [closePortal, hideOnScroll])

const handlePortalMouseLeave = (e) => {
if (!closeOnPortalMouseLeave) {
return
Expand Down Expand Up @@ -318,6 +346,9 @@ Portal.propTypes = {
/** Event pool namespace that is used to handle component events */
eventPool: PropTypes.string,

/** Hide the Popup when scrolling the window. */
hideOnScroll: PropTypes.bool,

/** The node where the portal should mount. */
mountNode: PropTypes.any,

Expand Down
47 changes: 7 additions & 40 deletions src/modules/Popup/Popup.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import EventStack from '@semantic-ui-react/event-stack'
import cx from 'clsx'
import _ from 'lodash'
import PropTypes from 'prop-types'
Expand All @@ -14,9 +13,9 @@ import {
getUnhandledProps,
makeDebugger,
SUI,
useIsomorphicLayoutEffect,
useKeyOnly,
useKeyOrValueAndKey,
useIsomorphicLayoutEffect,
useMergedRefs,
usePrevious,
} from '../../lib'
Expand Down Expand Up @@ -72,11 +71,10 @@ function getPortalProps(props) {
* Splits props for Portal & Popup.
*
* @param {Object} unhandledProps
* @param {Boolean} closed
* @param {Boolean} disabled
*/
function partitionPortalProps(unhandledProps, closed, disabled) {
if (closed || disabled) {
function partitionPortalProps(unhandledProps, disabled) {
if (disabled) {
return {}
}

Expand Down Expand Up @@ -124,7 +122,7 @@ const Popup = React.forwardRef(function (props, ref) {
eventsEnabled = true,
flowing,
header,
hideOnScroll,
hideOnScroll = false,
inverted,
offset,
pinned = false,
Expand All @@ -139,18 +137,11 @@ const Popup = React.forwardRef(function (props, ref) {
wide,
} = props

const [closed, setClosed] = React.useState(false)

const unhandledProps = getUnhandledProps(Popup, props)
const { contentRestProps, portalRestProps } = partitionPortalProps(
unhandledProps,
closed,
disabled,
)
const { contentRestProps, portalRestProps } = partitionPortalProps(unhandledProps, disabled)

const elementRef = useMergedRefs(ref)
const positionUpdate = React.useRef()
const timeoutId = React.useRef()
const triggerRef = React.useRef()
const zIndexWasSynced = React.useRef(false)

Expand All @@ -160,12 +151,6 @@ const Popup = React.forwardRef(function (props, ref) {

usePositioningEffect(popperDependencies, positionUpdate)

React.useEffect(() => {
return () => {
clearTimeout(timeoutId.current)
}
}, [])

// ----------------------------------------
// Handlers
// ----------------------------------------
Expand All @@ -180,24 +165,6 @@ const Popup = React.forwardRef(function (props, ref) {
_.invoke(props, 'onOpen', e, { ...props, open: true })
}

const handleHideOnScroll = (e) => {
debug('handleHideOnScroll()')

// Do not hide the popup when scroll comes from inside the popup
// https://github.com/Semantic-Org/Semantic-UI-React/issues/4305
if (_.isElement(e.target) && elementRef.current.contains(e.target)) {
return
}

setClosed(true)

timeoutId.current = setTimeout(() => {
setClosed(false)
}, 50)

handleClose(e)
}

const handlePortalMount = (e) => {
debug('handlePortalMount()')
_.invoke(props, 'onMount', e, props)
Expand Down Expand Up @@ -254,7 +221,6 @@ const Popup = React.forwardRef(function (props, ref) {
) : (
children
)}
{hideOnScroll && <EventStack on={handleHideOnScroll} name='scroll' target='window' />}
</ElementType>
)

Expand All @@ -276,7 +242,7 @@ const Popup = React.forwardRef(function (props, ref) {
})
}

if (closed || disabled) {
if (disabled) {
return trigger
}

Expand Down Expand Up @@ -335,6 +301,7 @@ const Popup = React.forwardRef(function (props, ref) {
onUnmount={handlePortalUnmount}
trigger={trigger}
triggerRef={triggerRef}
hideOnScroll={hideOnScroll}
>
<Popper
modifiers={modifiers}
Expand Down
Loading