Summary / Pitch
Target EUI release date(s) : TBD
Portalling in EUI—rendering overlay components like flyouts, modals, and popovers into document.body—is causing UI crashes, React compatibility issues, and conflicts with Kibana's new layout architecture. This initiative reduces or eliminates unnecessary portalling to improve stability and unblock key Kibana features.
Context
Portalling was originally added to solve z-index and overflow issues , but it has become a source of significant problems:
UI Crashes — Push flyouts throw NotFoundError during concurrent DOM operations when portal elements are removed mid-render ([EuiFlyout] type="push" throws NotFoundError on unmount during concurrent DOM operations #9389 ). This crashes the UI with no recovery path.
React Strict Mode Incompatibility — Portal divs are created twice and orphaned divs aren't cleaned up, causing DOM bloat that accumulates with user interactions ([Strict Mode] Redundant div is portalled and not cleaned up #8784 ). This affects every EUI consumer using React 18's Strict Mode.
Kibana Layout Blocked — The new Kibana Workspace Chrome grid layout requires flyouts and popovers to be scoped to application containers, not document.body. Current portalling behavior prevents this ([Meta][Kibana Workspace Chrome] Improvements for new Kibana layout #8820 ).
z-index Wars — Portalled elements frequently appear above or below other UI elements unexpectedly, requiring constant workarounds ([EuiPopover] Popover is placed above header (z-index) #4756 , [EuiComboBox] Combobox popover can be hidden behind EuiBottomBar #4872 , EuiGlobalToastList became hidden behind EuiFlyout with EUI 7.14.1 #5169 , [EuiFlyout] [EuiButtonGroup] Z-Index conflict when a Flyout occludes Toggle Buttons #4122 ).
SSR Incompatibility — Portal components fail during server-side rendering because document is not defined ([EuiBottomBar] document is not defined when using server rendering #5656 ).
This is not a new concern. Issue #9255 explicitly states: "Long term, consider what could be done about portaling generally in EUI, which is overused, unnecessary, and problematic."
Goals
Out of scope
Complete removal of all portalling (some edge cases may still require it)
Changing the public API signatures of affected components (deprecation path should be gradual)
Fixing third-party portal libraries (e.g., react-reverse-portal)
Scope of Work
12 components currently rely on portalling:
Component
Portal Method
Proposed Change
EuiPopover
EuiPortal (always)
Evaluate if portalling is necessary; add usePortal opt-out
EuiToolTip
EuiPortal (always)
Evaluate if portalling is necessary; add usePortal opt-out
EuiBottomBar
EuiPortal (default on)
Change default to usePortal={false}
EuiFlyout
EuiPortal + EuiOverlayMask
Support container-scoped flyouts; reduce portal usage for push type
EuiModal
EuiOverlayMask → EuiPortal
Evaluate container-scoped alternative
EuiDraggable
EuiPortal (opt-in)
No change needed (already opt-in)
EuiWrappingPopover
EuiPortal (always)
Evaluate if portalling is necessary
EuiImageFullScreenWrapper
EuiOverlayMask
May need to remain portalled
EuiCodeBlockFullScreen
EuiOverlayMask
May need to remain portalled
EuiDataGridCell
createPortal
Evaluate if portalling is necessary
_EuiPageBottomBar
createPortal
No change needed (portals to parent, not body)
DataGrid Draggable Columns
EuiPortal
No change needed (drag overlay only)
High-level approach for each component:
Audit current portal usage and determine if it's necessary
For components where portalling is unnecessary, remove it or change the default
For components where portalling is sometimes needed, add a usePortal prop (if not present)
For components where container-scoping is needed, add a container prop
Migrate EuiPortal from class to function component ([EuiPortal] Migrate from class to function component #9456 ) to fix Strict Mode issues
Definition of Ready for Dev
Definition of done
Related Issues
Notable Related Issue Details
#9255
"Long term, consider what could be done about portaling generally in EUI, which is overused, unnecessary, and problematic."
This spike is investigating:
How often users experience portal-related bugs in Kibana
Short-term solutions (e.g., updating Kibana usage to usePortal={false})
Long-term improvements to portaling strategy in EUI
#9456
EuiPortal is being migrated from a class component to a function component:
File: components/portal/portal.tsx
Used internally by every overlay component (popover, modal, flyout, tooltip)
Straightforward conversion: mount/unmount logic maps to useEffect cleanup pattern
#8784
When Strict Mode is enabled, portal divs are created twice and the empty one isn't cleaned up:
Impacts all end-users
No known workaround
EuiPortal is used in: EuiPopover (512 uses in Kibana), EuiToolTip (856), EuiFlyout (350), EuiOverlayMask (16)
#7778
Request to allow EuiPortal to use different portal targets via React Context, instead of always using document.body. This would enable:
Multi-window Electron apps
Child windows opened via window.open
Scoped flyouts/modals within specific containers
Open Issues (High Priority)
#
Title
Updated
#9456
[EuiPortal] Migrate from class to function component
Mar 12, 2026
#9255
[Spike] Investigate "[EuiBottomBar] Fixed position..."
Feb 17, 2026
#9242
[EuiBottomBar] Fixed position shouldn't mount into a portal by default
Dec 2, 2025
#8784
[Strict Mode] Redundant div is portalled and not cleaned up
Dec 10, 2025
#8520
[EuiDataGrid][A11y] Column selector dragging accessibility improvements
Nov 27, 2025
#7778
EuiPortal should be able to use different portal target than document.body
Sep 22, 2025
Search results uncovering 50+ related issues
Complete Issue List (50 issues returned)
#
Title
State
Updated
#9389
[EuiFlyout] type="push" throws NotFoundError on unmount during concurrent DOM operations
Closed
Mar 12, 2026
#9456
[EuiPortal] Migrate from class to function component
Open
Mar 12, 2026
#9255
[Spike] Investigate "[EuiBottomBar] Fixed position... #9242 "
Open
Feb 17, 2026
#8820
[Meta][Kibana Workspace Chrome] Improvements for new Kibana layout
Closed
Feb 5, 2026
#4157
[EuiDataGrid] Header Popover does not re-compute the position in scrollable container
Closed
Dec 15, 2025
#8784
[Strict Mode] Redundant div is portalled and not cleaned up
Open
Dec 10, 2025
#9242
[EuiBottomBar] Fixed position shouldn't mount into a portal by default
Open
Dec 2, 2025
#8520
[EuiDataGrid][A11y] Column selector dragging accessibility improvements
Open
Nov 27, 2025
#8984
[EuiPopover] Expose repositionOnScroll in componentDefaults
Closed
Nov 5, 2025
#8989
[Flyout System] Render EuiOverlayMask for EuiFlyout only when necessary
Closed
Oct 15, 2025
#7778
EuiPortal should be able to use different portal target than document.body based on provided Context
Open
Sep 22, 2025
#8578
Deprecate Support for React 16
Closed
Jul 21, 2025
#8269
Workaround for Chromium CSS mask-image bug breaks positioning for nested position:fixed content
Closed
Apr 3, 2025
#8190
[EUI+] Missing Utilities content
Closed
Mar 17, 2025
#8410
[EUI+] Fix typos
Closed
Feb 27, 2025
#8206
[Bug] Focusable Site Navigation in Flyouts After Recent Update
Closed
Dec 5, 2024
#6300
[META] Add Cypress cy.checkAxe() tests to components
Closed
Nov 19, 2024
#5685
[Meta][CSS-in-JS] Component conversions
Closed
Sep 23, 2024
#6596
Portal widget (EuiBottomBar, EuiPopover etc) does not work in Vite dev mode
Closed
Aug 26, 2024
#7879
[A11Y] Using nested EuiPopover in EuiModal: Pressing ESC in child component closes parent
Closed
Jun 24, 2024
#7219
Spike: Removing Data Grid from @elastic/eui
Closed
Jun 20, 2024
#5788
[EuiPopover] Background in dark mode isn't different from the main background
Closed
May 30, 2024
#4265
[EuiPopover] Should unmount immediately on parent unmount
Closed
May 23, 2024
#7280
Close modal on outside click
Closed
May 14, 2024
#6882
[EuiPortal] Shadow DOM Support for Portal-Based Components (e.g., Modal, Overlay Mask)
Closed
May 13, 2024
#6845
[EuiToolTip] Dom cannot be removed
Closed
May 13, 2024
#6732
Not working properly on react and react-dom v-18
Closed
Apr 17, 2024
#6592
[EuiPopover] Scrolling an open popover down stretches page height
Closed
Mar 21, 2024
#5330
Guidelines for bottom bars
Closed
Feb 12, 2024
#6338
EuiModal scrolls to bottom of page when modal is open
Closed
Jan 30, 2024
#6337
(duplicate of #6338 )
Closed
Jan 30, 2024
#6304
EuiModal scrolls to bottom of page when modal is open
Closed
Jan 30, 2024
#5370
[EuiMarkdown] Allow EuiFlyout instead of EuiModal
Closed
Dec 6, 2023
#6339
[EuiResizableContainer] Add support for onResizeStart and onResizeEnd callback props
Closed
Nov 14, 2023
#6225
[EuiPortal docs] Add a custom modal/flyout example that meets a11y requirements
Closed
Sep 27, 2023
#6241
[EuiResizableContainer] Resizable container misbehaves when using react-reverse-portal
Closed
Aug 31, 2023
#6199
[EuiResizableContainer] Resizable container misbehaves when using react-reverse-portal
Closed
Aug 31, 2023
#5859
Popover and ContextMenu do not support react 18
Closed
May 11, 2023
#5656
[EuiBottomBar] document is not defined when using server rendering
Closed
Apr 26, 2023
#1101
[EuiContextMenu] Tabbing regressions
Closed
Mar 23, 2023
#4364
[EuiDataGrid] Columns resize infinite loop
Closed
Jan 24, 2023
#4872
[EuiComboBox] Combobox popover can be hidden behind EuiBottomBar
Closed
Dec 19, 2021
#4756
[EuiPopover] Popover is placed above header (z-index)
Closed
Nov 29, 2021
#2903
Scrollspy feature requested
Closed
Sep 24, 2021
#5169
EuiGlobalToastList became hidden behind EuiFlyout with EUI 7.14.1
Closed
Sep 22, 2021
#1023
[EuiInputPopover] In fixed container (like flyout) has positioning issues
Closed
Sep 13, 2021
#4666
[Portals][Doc] Props table not available for Portals
Closed
Mar 29, 2021
#1381
[makeId] Makes it difficult for consumers to create Jest tests
Closed
Nov 11, 2020
#4122
[EuiFlyout] [EuiButtonGroup] Z-Index conflict when a Flyout occludes Toggle Buttons
Closed
Oct 8, 2020
#1877
EuiBottomBar needs a container prop similar to EuiPopover
Closed
Sep 20, 2020
Risks
Breaking changes — Changing portal defaults may affect existing Kibana usage; requires careful deprecation path
Edge cases — Some components may genuinely need portalling in certain contexts (e.g., deeply nested scroll containers)
Testing complexity — Portal behavior is difficult to test; changes require extensive manual QA in Kibana
Summary / Pitch
Target EUI release date(s): TBD
Portalling in EUI—rendering overlay components like flyouts, modals, and popovers into
document.body—is causing UI crashes, React compatibility issues, and conflicts with Kibana's new layout architecture. This initiative reduces or eliminates unnecessary portalling to improve stability and unblock key Kibana features.Context
Portalling was originally added to solve z-index and overflow issues, but it has become a source of significant problems:
UI Crashes — Push flyouts throw
NotFoundErrorduring concurrent DOM operations when portal elements are removed mid-render ([EuiFlyout] type="push" throws NotFoundError on unmount during concurrent DOM operations #9389). This crashes the UI with no recovery path.React Strict Mode Incompatibility — Portal divs are created twice and orphaned divs aren't cleaned up, causing DOM bloat that accumulates with user interactions ([Strict Mode] Redundant div is portalled and not cleaned up #8784). This affects every EUI consumer using React 18's Strict Mode.
Kibana Layout Blocked — The new Kibana Workspace Chrome grid layout requires flyouts and popovers to be scoped to application containers, not
document.body. Current portalling behavior prevents this ([Meta][Kibana Workspace Chrome] Improvements for new Kibana layout #8820).z-index Wars — Portalled elements frequently appear above or below other UI elements unexpectedly, requiring constant workarounds ([EuiPopover] Popover is placed above header (z-index) #4756, [EuiComboBox] Combobox popover can be hidden behind EuiBottomBar #4872, EuiGlobalToastList became hidden behind EuiFlyout with EUI 7.14.1 #5169, [EuiFlyout] [EuiButtonGroup] Z-Index conflict when a Flyout occludes Toggle Buttons #4122).
SSR Incompatibility — Portal components fail during server-side rendering because
documentis not defined ([EuiBottomBar] document is not defined when using server rendering #5656).This is not a new concern. Issue #9255 explicitly states: "Long term, consider what could be done about portaling generally in EUI, which is overused, unnecessary, and problematic."
Goals
position: fixed) sufficedocument.bodyOut of scope
react-reverse-portal)Scope of Work
12 components currently rely on portalling:
EuiPopoverEuiPortal(always)usePortalopt-outEuiToolTipEuiPortal(always)usePortalopt-outEuiBottomBarEuiPortal(default on)usePortal={false}EuiFlyoutEuiPortal+EuiOverlayMaskEuiModalEuiOverlayMask→EuiPortalEuiDraggableEuiPortal(opt-in)EuiWrappingPopoverEuiPortal(always)EuiImageFullScreenWrapperEuiOverlayMaskEuiCodeBlockFullScreenEuiOverlayMaskEuiDataGridCellcreatePortal_EuiPageBottomBarcreatePortalEuiPortalHigh-level approach for each component:
usePortalprop (if not present)containerpropEuiPortalfrom class to function component ([EuiPortal] Migrate from class to function component #9456) to fix Strict Mode issuesDefinition of Ready for Dev
Definition of done
Related Issues
Notable Related Issue Details
#9255
This spike is investigating:
usePortal={false})#9456
EuiPortalis being migrated from a class component to a function component:components/portal/portal.tsxuseEffectcleanup pattern#8784
When Strict Mode is enabled, portal divs are created twice and the empty one isn't cleaned up:
EuiPopover(512 uses in Kibana),EuiToolTip(856),EuiFlyout(350),EuiOverlayMask(16)#7778
Request to allow
EuiPortalto use different portal targets via React Context, instead of always usingdocument.body. This would enable:window.openOpen Issues (High Priority)
Search results uncovering 50+ related issues
Complete Issue List (50 issues returned)
repositionOnScrollincomponentDefaultsEuiOverlayMaskforEuiFlyoutonly when necessarycy.checkAxe()tests to componentsEuiPopoverinEuiModal: Pressing ESC in child component closes parentEuiFlyoutinstead ofEuiModalonResizeStartandonResizeEndcallback propscontainerprop similar to EuiPopoverRisks