-
Notifications
You must be signed in to change notification settings - Fork 861
Restore Flyout System feature in EUI #9202
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
This PR contains breaking changes. The opener of this pull request is asked to perform the following due diligence steps below, to assist EUI in our next Kibana upgrade:
|
Co-authored-by: Clint Andrew Hall <clint.hall@elastic.co> Co-authored-by: Weronika Olejniczak <32842468+weronikaolejniczak@users.noreply.github.com> Co-authored-by: Tomasz Kajtoch <tomasz.kajtoch@elastic.co> Co-authored-by: Arturo Castillo Delgado <arturo.castillo@elastic.co> Co-authored-by: Paulina Shakirova <paulina.shakirova@elastic.co>
41f8990 to
e2b53f0
Compare
|
When testing in Storybook the multi-session story I noticed this issue: Kapture.2025-11-28.at.13.34.00.mp4It has to do with our portal and a similar issue has been reported here: #9242. |
💚 Build SucceededHistory
|
This issue seems to be related to the same EuiPortal issue and isn't caused by any of the changes introduced here. I dug into it a little and have some ideas on why this might be happening, but nothing concrete yet. Let's fix it separately since changing EuiPortal would need lots of testing in EUI and Kibana. |
💚 Build Succeeded
History
|
tkajtoch
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reviewed and tested all changes included in this PR. LGTM
## Summary This EUI upgrade brings the new Flyout System. While all of the changes we made are opt-in, we did have to update the DOM nesting in `EuiFlyout` and `EuiFlyoutResizable`. This change includes making overlay masks a sibling of flyouts, rather than wrapping the flyouts as children, which required internal changes to the mask's z-index value. Following @tsullivan request, please run through your UIs and make sure the flyouts render as expected, especially in the areas where you override EuiFlyout styles. ## Dependency updates - `@elastic/eui`: `v110.0.0` ⏩ `v111.0.0` - `@elastic/eui-theme-borealis`: `v5.1.0` ⏩ `v5.2.0` --- ## Changes - Removed `z-index` overrides from various places across Kibana. The updated EuiFlyout logic calculates `z-index` values dynamically based on the order of opening flyouts, making the manual overrides unnecessary. - Updated types of refs passed to `EuiFlyout` and `EuiFlyoutResizable` ## Package updates ### `@elastic/eui` v111.0.0 - Added an opt-in EuiFlyout session management for creating flyout compositions and journeys effortlessly. Session management handles side-by-side flyout rendering based on parent-child grouping, simple flyout transitions with history, state sharing, and more. ([#9202](elastic/eui#9202)) - EuiFlyout session management is an optional feature that can be enabled by adding `session="start"` to EuiFlyout. Check out the [documentation](https://eui.elastic.co/docs/components/containers/flyout/session-management) to learn more. - Added a new `hasChildBackground` boolean prop (defaults to false) to `EuiFlyout` ([#9056](elastic/eui#9056)) - Updated `EuiFlyout` with new `onActive` callback and enable stack managed history controls. ([#9003](elastic/eui#9003)) - Updated `EuiFlyoutMenu` with new prop `historyItems` and refactored props for back button. ([#9003](elastic/eui#9003)) - Added a new optional `resizable` (boolean) prop to `EuiFlyout`. Resizability can now be controlled dynamically without the need to use `EuiFlyoutResizable`. ([#8999](elastic/eui#8999)) - Flyout system menu bar: require tile, support custom actions ([#8897](elastic/eui#8897)) - Added a new `EuiFlyoutMenu` component that provides a standardized top menu bar for flyouts. ([#8851](elastic/eui#8851)) **Breaking changes** - Changed the way EuiFlyout renders overlay masks to decouple the overlay mask from the flyout itself. Now, the overlay mask is a separate portalled element. ([#9202](elastic/eui#9202)) - This change does not modify the functionality or behavior of flyout overlays but might affect some custom usages when your application relies on the specific element nesting within EuiFlyout. ### `@elastic/eui-theme-borealis` v5.2.0 - Updated parameters used for `euiAnimSlightResistance` for a smoother animation ([#9202](elastic/eui#9202)) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
…3806) ~~Depends on elastic/eui#8982 ~~Depends on elastic/eui#9202 ~~Depends on #245515 This PR enhances the core UX offerings in Kibana with `core.overlays.openSystemFlyout`. ### `core.overlays.openSystemFlyout` Opens a system flyout that integrates with the EUI Flyout Manager. Using a mount point would break the context propogation of the EUI Flyout Manager, so this method accepts React elements directly rather than `toMountPoint`. ```typescript import React, { useRef } from 'react'; import { EuiFlyoutBody, EuiFlyoutFooter, EuiText, EuiButton, EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import type { OverlayRef } from '@kbn/core-mount-utils-browser'; // Create a component or function that opens the system flyout const openMySystemFlyout = (overlays) => { const flyoutRef = useRef<OverlayRef | null>(null); const handleClose = () => { if (flyoutRef.current) { flyoutRef.current.close(); } }; const FlyoutContent = () => ( <> <EuiFlyoutBody> <EuiText> <p>This is a system flyout that integrates with EUI Flyout Manager.</p> <p>The header is automatically created from the title option.</p> </EuiText> </EuiFlyoutBody> <EuiFlyoutFooter> <EuiFlexGroup justifyContent="spaceBetween"> <EuiFlexItem grow={false}> <EuiButtonEmpty onClick={handleClose}> Cancel </EuiButtonEmpty> </EuiFlexItem> <EuiFlexItem grow={false}> <EuiButton onClick={() => console.log('Save')} fill> Save </EuiButton> </EuiFlexItem> </EuiFlexGroup> </EuiFlyoutFooter> </> ); flyoutRef.current = overlays.openSystemFlyout(<FlyoutContent />, { title: 'My System Flyout', type: 'overlay', size: 'm', maxWidth: 600, ownFocus: false, onClose: () => { console.log('System flyout closed'); flyoutRef.current = null; }, onActive: () => { console.log('System flyout became active'); }, }); return flyoutRef.current; }; // Open the flyout const flyoutRef = openMySystemFlyout(overlays); // Close the flyout programmatically from outside flyoutRef.close(); ``` The developer README for the Flyout System is [here](https://github.com/elastic/eui/blob/feat/flyout-system/packages/eui/src/components/flyout/README.md). ### Example plugin Along with the new service and documentation changes, a new example plugin for developers is provided that shows different integration patterns for the EUI flyout system. **Screenshot of example plugin:** <img width="1327" height="836" alt="image" src="https://github.com/user-attachments/assets/9664f0cb-f793-4a8c-8a96-c46d069756dd" /> --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Ania Kowalska <ania.kowalska@elastic.co> Co-authored-by: Lene Gadewoll <lene.gadewoll@elastic.co> Co-authored-by: Weronika Olejniczak <weronika.olejniczak@elastic.co> Co-authored-by: Jorge Oliveira <jorge.oliveira@elastic.co> Co-authored-by: Tomasz Kajtoch <tomasz.kajtoch@elastic.co> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
…stic#233806) ~~Depends on elastic/eui#8982 ~~Depends on elastic/eui#9202 ~~Depends on elastic#245515 This PR enhances the core UX offerings in Kibana with `core.overlays.openSystemFlyout`. ### `core.overlays.openSystemFlyout` Opens a system flyout that integrates with the EUI Flyout Manager. Using a mount point would break the context propogation of the EUI Flyout Manager, so this method accepts React elements directly rather than `toMountPoint`. ```typescript import React, { useRef } from 'react'; import { EuiFlyoutBody, EuiFlyoutFooter, EuiText, EuiButton, EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import type { OverlayRef } from '@kbn/core-mount-utils-browser'; // Create a component or function that opens the system flyout const openMySystemFlyout = (overlays) => { const flyoutRef = useRef<OverlayRef | null>(null); const handleClose = () => { if (flyoutRef.current) { flyoutRef.current.close(); } }; const FlyoutContent = () => ( <> <EuiFlyoutBody> <EuiText> <p>This is a system flyout that integrates with EUI Flyout Manager.</p> <p>The header is automatically created from the title option.</p> </EuiText> </EuiFlyoutBody> <EuiFlyoutFooter> <EuiFlexGroup justifyContent="spaceBetween"> <EuiFlexItem grow={false}> <EuiButtonEmpty onClick={handleClose}> Cancel </EuiButtonEmpty> </EuiFlexItem> <EuiFlexItem grow={false}> <EuiButton onClick={() => console.log('Save')} fill> Save </EuiButton> </EuiFlexItem> </EuiFlexGroup> </EuiFlyoutFooter> </> ); flyoutRef.current = overlays.openSystemFlyout(<FlyoutContent />, { title: 'My System Flyout', type: 'overlay', size: 'm', maxWidth: 600, ownFocus: false, onClose: () => { console.log('System flyout closed'); flyoutRef.current = null; }, onActive: () => { console.log('System flyout became active'); }, }); return flyoutRef.current; }; // Open the flyout const flyoutRef = openMySystemFlyout(overlays); // Close the flyout programmatically from outside flyoutRef.close(); ``` The developer README for the Flyout System is [here](https://github.com/elastic/eui/blob/feat/flyout-system/packages/eui/src/components/flyout/README.md). ### Example plugin Along with the new service and documentation changes, a new example plugin for developers is provided that shows different integration patterns for the EUI flyout system. **Screenshot of example plugin:** <img width="1327" height="836" alt="image" src="https://github.com/user-attachments/assets/9664f0cb-f793-4a8c-8a96-c46d069756dd" /> --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Ania Kowalska <ania.kowalska@elastic.co> Co-authored-by: Lene Gadewoll <lene.gadewoll@elastic.co> Co-authored-by: Weronika Olejniczak <weronika.olejniczak@elastic.co> Co-authored-by: Jorge Oliveira <jorge.oliveira@elastic.co> Co-authored-by: Tomasz Kajtoch <tomasz.kajtoch@elastic.co> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
New Managed Flyout System
Re-open of #9068
This represents a significant evolution in the flyout system: a hook-based manager system with automatic context detection and support for complex flyout workflows.
Summary of API changes
session?('start' | 'never' | 'inherit', optional - defaults toinherit)Documentation: https://eui.elastic.co/pr_9202/docs/components/containers/flyout/#EuiFlyout-prop-session
onActive?(() => void, optional)Documentation: https://eui.elastic.co/pr_9202/docs/components/containers/flyout/#EuiFlyout-prop-onActive
resizable?(boolean, optional - defaults tofalse)resizableprop is dynamic which allows toggling between resizable state without whole-component rerendersThis makes the old EuiFlyoutResizable component obsolete (but it still works exactly like before). We may officially deprecate it in near future, but that's not the goal of this project. Read more
Documentation: https://eui.elastic.co/pr_9202/docs/components/containers/flyout/#resizable-flyout
onResize?minWidth?(number, optional)resizabe={true}to set a minimum width of the flyout.Documentation: https://eui.elastic.co/pr_9202/docs/components/containers/flyout/#resizable-flyout
flyoutMenuProps?(EuiFlyoutMenuProps, optional)Documentation: https://eui.elastic.co/pr_9202/docs/components/containers/flyout/#flyout-menu
hasChildBackground?refprop updateref?(React.Ref, optional)Legacy string refs are no longer supported with EuiFlyout. Use modern React refs like
useRefinstead. Read moreuseEuiFlyoutSession
EuiFlyoutSessionApi
EuiFlyoutSessionConfig
EuiFlyoutSessionRenderContext
ADDED - New Public-Facing Features
1. New Manager System
A comprehensive new "manager" system for centralized management of flyout sessions (
src/components/flyout/manager/):Core Component:
EuiFlyout: Same flyout component that developers are accustomed toSession Management Props:
sessionprop onEuiFlyoutwith three modes:'start'- Creates a new flyout session (for main flyouts)'inherit'- (default) Inherits existing session if active'never'- Opts out of session managementRequired EuiFlyoutMenu:
Managed flyouts require an
EuiFlyoutMenuat the top, which is automatically rendered when you provide the necessary props.flyoutMenuProps.title- (Required, or providearia-label) Prop that provides the title for the automatically renderedEuiFlyoutMenu. Additional properties inflyoutMenuPropsallow further customization of the menu (back button, history items, custom actions, etc.).Synchronizing local state with the visible flyout session:
Since flyout sessions can be programmatically activated, i.e the history navigation system can reactivate them, you may want to have a local state that is kept in sync with the active session. These callbacks can be used to update your local state variables:
onActivecallback - Fires when flyout becomes active/visible (new prop)onClosecallback - Fires when flyout is closed (not a new prop)The new manager system uses
use-sync-external-storeand a singleton store pattern for cross-React-root state sharing.2. New Flyout Menu Component
EuiFlyoutMenuandEuiFlyoutMenuProps: A new component for rendering a top menu bar in EuiFlyout.3.
resizableprop.EuiFlyoutResizablewas a complex wrapper that managed all resizing and state logic internally. The logic has been moved to an internal hook, which is now integrated directly into the main flyout component.EuiFlyoutnow supports aresizableboolean propEuiFlyoutResizableis still supported, but is just a wrapper forEuiFlyoutwithresizableset totrue.REMOVED - Earlier iteration of the Flyout System Feature
An earlier pre-release iteration of the Flyout System was in main but is now being removed.
1. Old Session System
The entire API of the earlier version is being removed:
EuiFlyoutSessionProvideruseEuiFlyoutSession()EuiFlyoutSessionApiEuiFlyoutSessionConfigEuiFlyoutSessionOpenChildOptionsEuiFlyoutSessionOpenMainOptionsEuiFlyoutSessionOpenGroupOptionsEuiFlyoutSessionProviderComponentPropsEuiFlyoutSessionRenderContext2. Old Child Flyout Implementation
Standalone(replaced with managed version)EuiFlyoutChildcomponentThe key difference from the old session system is that it used render props; the new manager system uses a centralized state store with hooks. The old system required explicit provider wrapping; the new system automatically detects when to use managed behavior.
Number of component usages in Kibana that will need to be updated: 0
Screenshots #
Impact to users #
BREAKING CHANGE - String Refs No Longer Supported
EuiFlyoutis aforwardRefcomponent that previously had loose typing allowing string refs. It now enforces strict typing that only accepts modern ref patterns. Specifically, this could impact you in two scenarios:EuiFlyout, you will need to pass an HTML element ref instead:styled-componentsto wrapEuiFlyout, your component implicitly becomes a string ref component. You will need to addref={null}to your component:Number of component usages in Kibana that will need to be updated: 1
fleet/sections/agent_policy/list_page/components/create_agent_policy.tsxFlyout overlay mask
z-indexvalue updateOverlay masks are now siblings of flyouts, which required a change to the mask's
z-indexvalue. Now, flyout overlay masks usez-indexvalue oflevels.flyout - 2making it more predictable. This stacking order allows child flyouts to have their ownz-indexlayer between the main flyout and the mask.QA
Remove or strikethrough items that do not apply to your PR.
PR Mergeability / Release readiness checklist
We must ensure this feature has everything it needs to be a publicly available feature in EUI before this branch is merged into
main. Please ensure the following are completed before merging this PR:General checklist
@defaultif default values are missing) and playground toggles[ ] Updated visual regression tests