Skip to content

[Flyout System] Shrink a resized main flyout to fit beside its child instead of stacking - #10250

Merged
tsullivan merged 12 commits into
elastic:mainfrom
tsullivan:flyout-system/avoid-unexpected-stack-mode
Oct 29, 2026
Merged

tsullivan merged 12 commits into
elastic:mainfrom
tsullivan:flyout-system/avoid-unexpected-stack-mode

Conversation

@tsullivan

@tsullivan tsullivan commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

Summary

Fixes #9683.

In the flyout system, if a user drags a resizable main flyout wide and then opens a child flyout, or the container narrows, the pair switches to stacked layout mode, which hides the main flyout behind the child. With this change, the main flyout shrinks to the largest width that fits beside the child, and the pair stays side-by-side. Once there is room again, such as when the child closes, the main flyout returns to the width the user dragged it to.

The resize clamp already limits a resizable main flyout and its child to 90% of the container in side-by-side mode, but layout mode decided from the main flyout's wider width first, and the clamp is off in stacked mode. Layout mode now decides from the width the clamp will apply, using the child's measured width. To know which main flyouts are clamped, the manager now stores whether each flyout is resizable. For a main flyout, the clamp starts from the user's dragged width for named sizes too (before, only numeric sizes did), so a named-size main flyout no longer keeps the clamped width. A child flyout keeps its clamped width, so a dragged main and a dragged child can't keep resizing each other. onResize is still only called for user resizes, so a saved width is never replaced by a clamped one.

API Changes

component / parent prop / child change description
getFlyoutManagerStore() setFlyoutResizable Added Updates whether a managed flyout is resizable. EuiManagedFlyout keeps it in sync, so consumers don't need to call it

Screenshots

Main flyout dragged to 1440px on a 1920px viewport, then "Open child panel" clicked:

Before After
Before: the child opens in stacked layout mode After: the main flyout shrinks to 1248px and the child opens side-by-side

Impact Assessment

Note: Most PRs should be tested in Kibana to help gauge their Impact before merging.

  • 🔴 Breaking changes — What will break? How many usages in Kibana/Cloud UI are impacted?
  • 💅 Visual changes — A resizable main flyout that the user dragged wide shrinks to the largest width that fits beside its child, where it used to switch to stacked layout mode.
  • 🧪 Test impact — May break functional or snapshot tests (e.g., HTML structure, class names, default values).
  • 🔧 Hard to integrate — If changes require substantial updates to Kibana, please stage the changes and link them here.

Impact level: 🟢 Low

Release Readiness

  • Documentation: Resizable flyout
  • Figma: {link to Figma or issue}
  • Migration guide: {steps or link, for breaking/visual changes or deprecations}
  • Adoption plan (new features): {link to issue/doc or outline who will integrate this and where}

QA instructions for reviewer

  • Open the Layout / EuiFlyout / Flyout Manager / Playground story (FlyoutChildDemo) with mainFlyoutResizable enabled, in a wide viewport (e.g. 1920px).
  • Drag the main flyout's resize handle until it covers about 75% of the viewport.
  • Click Open child panel.
  • Confirm that the main flyout shrinks only as much as needed (to about 65% at 1920px) and the child opens beside it ("Current layout mode: side-by-side").
  • Click Close child panel: confirm that the main flyout returns to the width you dragged it to.
  • Reload, drag the main flyout to about 55% of the viewport, and open the child: confirm that the main flyout keeps its dragged width beside the child.
  • With the child open, drag the main flyout as wide as it goes, then make the browser window narrower: confirm that the flyouts stay side-by-side.
  • With mainFlyoutResizable disabled, confirm that opening the child behaves as before.

Checklist before marking Ready for Review

Reviewer checklist

  • Approved Impact Assessment — Acceptable to merge given the consumer impact.
  • Approved Release Readiness — Docs, Figma, and migration info are sufficient to ship.

@tsullivan
tsullivan marked this pull request as ready for review October 27, 2026 22:07
Copilot AI balanced review requested due to automatic review settings October 27, 2026 22:07
@tsullivan
tsullivan requested a review from a team as a code owner October 27, 2026 22:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Flyout width calculations mishandle CSS sizes, clamped baselines, and child minimum widths, causing incorrect width resets, misleading onResize callbacks, and missed overflow handling.

3 open issues
What changed in this PR

Addresses the child-opening scenario in #9683 by resetting an oversized, resizable main flyout to its configured size when the pair would otherwise exceed the available space. Container-resize behavior remains unchanged.

Changes:

  • Adds an opening-time width reset and synchronizes it with the flyout manager before paint.
  • Tests reset behavior and cases where dragged widths should be preserved.
  • Documents the reset and the expanded onResize callback behavior.
File Description
packages/​website/​docs/​components/​containers/​flyout/​_flyout_resizable.mdx Documents resets and persisted-width implications.
packages/​eui/​src/​components/​flyout/​use_flyout_resizable.ts Adds child-opening fit checks and width resets.
packages/​eui/​src/​components/​flyout/​use_flyout_resizable.test.ts Tests resets, callbacks, and width preservation.
packages/​eui/​src/​components/​flyout/​manager/​README.md Explains reset conditions and manager synchronization.
packages/​eui/​src/​components/​flyout/​flyout.component.tsx Supplies child context and publishes reset widths.
packages/​eui/​changelogs/​upcoming/​10250.md Records the behavior change.

Review effort: Balanced

@tsullivan
tsullivan marked this pull request as draft October 28, 2026 02:21
@tsullivan
tsullivan marked this pull request as ready for review October 28, 2026 19:28
@tsullivan tsullivan changed the title [Flyout System] avoid child opening in stacked layout [Flyout System] Shrink a resized main flyout to fit beside its child instead of stacking Oct 28, 2026
…hild can no longer feed each other in a loop

We strongly recommend setting reasonable numerical `minWidth` and `maxWidth` props based on the flyout content and page content that you _can_ predict.

In a flyout session, a resizable main flyout and its child flyout stay side by side whenever they can. If the user dragged the main flyout so wide that the child doesn't fit beside it, either when the child opens or when the available space narrows, the main flyout shrinks to the largest width that fits. When the child closes or the space widens again, the main flyout returns to the width the user dragged it to. With a named `size`, that width scales with the available space. A resizable child flyout keeps its shrunk width, so the main flyout gets the space back first. `onResize` is only called when the user resizes the flyout, so a width you save from it is never replaced by a shrunk one. The flyouts still stack when the available space is too narrow, or when the main flyout's `minWidth` leaves no room for the child.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: P3 (Low)

The new statement that a resizable child keeps its shrunk width only holds for string/named sizes. Numeric sizes are supported too, but that branch still re-clamps from requestedWidthRef, ignoring isChildFlyout, so a numeric-size child grows back when space becomes available. Qualify this statement (and the equivalent manager README text), or implement the same policy for numeric-size children, so consumers aren't promised main-flyout priority that isn't provided.

Generated by Libra. Specialist: docs-and-changelog. React with 👍 or 👎 to give feedback on this comment.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No change needed: a managed child flyout cannot have a numeric size. validateManagedFlyoutSize (manager/validation.ts) rejects any child size other than s, m, l or fill, and EuiManagedFlyout throws on that error in every environment (flyout_managed.tsx), so a child never reaches the numeric-size branch of the resize hook. The statement that a resizable child keeps its shrunk width therefore holds for every child the flyout system allows, and adding the child rule to the numeric branch would only add code that cannot run.

@infra-vault-gh-plugin-prod

Copy link
Copy Markdown

💚 Build Succeeded

History

@infra-vault-gh-plugin-prod

Copy link
Copy Markdown

💚 Build Succeeded

History

@Dosant Dosant left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! probably worth running kibana integration check if no tests break

@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Kibana Regression Integration Test

Status: 💚 Kibana CI passed
Branch: update-dependencies/pr-10250
Kibana PR: elastic/kibana#301643

@tsullivan
tsullivan merged commit 4542d6c into elastic:main Oct 29, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:regression-integration-test-kibana Run a Regression Integration Test in Kibana against this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Flyout System] Resizable Flyout Issues

3 participants