Skip to content
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

[EuiFlyoutResizable] Add resizable flyout #7439

Merged
merged 7 commits into from
Jan 8, 2024

Conversation

cee-chen
Copy link
Contributor

@cee-chen cee-chen commented Dec 28, 2023

Summary

closes #287

Areas I'm looking for feedback on:

  • API - does adding a new <EuiFlyoutResizable /> component (as opposed to, e.g. <EuiFlyout resizable={true} />) make sense? I leaned this way because it felt the cleanest in terms of implementation (as opposed to adding Yet More Code to the existing logic-heavy flyout file), but definitely would like to hear feedback on this.

  • UI/UX - do we need more visual indicators or UI hints that the edge is resizable? Or does the existing appearance feel sufficient?

  • Documentation - especially with our new focus on patterns, I would really like feedback on the copy I wrote. I cribbed text from the above issue on why using resizable flyouts might be a good idea, but I think we should also consider adding some copy on when not to use resizable flyouts.

QA

General checklist

  • Browser QA
    • Checked in both light and dark modes
    • Checked in mobile
    • Checked in Chrome, Safari, Edge, and Firefox
    • Checked for accessibility including keyboard-only and screenreader modes
  • Docs site QA
  • Code quality checklist
    • Added or updated jest and cypress tests
      • Jest tests skipped as this functionality requires a lot more mocking in jsdom (widths etc), and is significantly less painful in Cypress/E2E. Code coverage is at 100% with Cypress tests
  • Release checklist
    • A changelog entry exists and is marked appropriately.
      - [ ] If applicable, added the breaking change issue label (and filled out the breaking change checklist)
  • Designer checklist
    • Updated the Figma library counterpart
      • Not sure if this should be added. Will check at the next Figma meeting

- significantly easier to write in Cypress/E2E than in jsdom - much less width mocking (although there's still some with mouse/touch events)

- add fix for initial size going outside specified allowed min/maxes (yay TDD)
+ convert body padding inline styles to logical properties
@cee-chen cee-chen marked this pull request as ready for review December 28, 2023 22:01
@cee-chen cee-chen requested a review from a team as a code owner December 28, 2023 22:01
@cee-chen cee-chen changed the title [EuiFlyoutResizable] [EuiFlyoutResizable] Add resizable flyout Dec 28, 2023
Copy link
Member

@tkajtoch tkajtoch left a comment

Choose a reason for hiding this comment

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

I love how straightforward this solution is!

I was afraid adding 4 event listeners to window on mouse down and removing on mouse up might cause a small performance hit, but it seems everything's just fine 💯

@andreadelrio
Copy link
Contributor

Areas I'm looking for feedback on:

  • UI/UX - do we need more visual indicators or UI hints that the edge is resizable? Or does the existing appearance feel sufficient?

I think the visual indicators you currently have are adequate. To add more context, what we've been doing lately in Discover is manually hiding the icons in EuiResizableContainer (menuDown, menuLeft, menuRight, menuUp). The reasoning behind that is that we've found that those icons then to be overkill and can crowd the UI a bit. If you look at references such as Figma, Slack and Github they follow the pattern you're following here: they change the cursor and make the line a bit thicker and/or show it in blue.

@JasonStoltz
Copy link
Member

Just curious. For the API, how did you decide to go with a new component variant as opposed to a resizable prop?

@cee-chen
Copy link
Contributor Author

cee-chen commented Jan 5, 2024

@JasonStoltz that's mentioned in the PR description! It's actually an area I was looking for feedback on:

API - does adding a new <EuiFlyoutResizable /> component (as opposed to, e.g. <EuiFlyout resizable={true} />) make sense? I leaned this way because it felt the cleanest in terms of implementation (as opposed to adding Yet More Code to the existing logic-heavy flyout file), but definitely would like to hear feedback on this.

After having some time to sit on it, I'm like a 7.5/10 sold on the API choice - I think the code cleanliness outweighs the benefits, and having it as a separate component also I think adds a small extra friction that makes it so consumers won't reach for resizable flyouts without thinking at least a little more on it first (which I think we do want).

WDYT? Am I way off on that?

@JasonStoltz
Copy link
Member

@cee-chen Ugh, I am so sorry for not reading that PR description 🤦.

If we set the underlying implementation aside, the "resizable" prop feels like the right interface.

Is it possible to keep the logic for this cleanly separated like you have it, but maintain a prop-based API?

Something like:

export const EUIFlyout = ({ resizable }) => {
  if (resizable) {
    return EUIFlyoutResizable;
  }
  
  return EUIFlyoutBase;
}

@JasonStoltz
Copy link
Member

@kyrspl @boriskirov @mdefazio @cee-chen Is there any additional guidance you think we should add that goes along with this new option? Are there any considerations or recommendations we can make around when to make a flyout resizable or not?

If you'll recall, we had a lengthy conversation here, I'm hoping to try to gather some of that into our docs.

Here is the copy currently in this PR:

You can use EuiFlyoutResizable to render a flyout that users can drag with their mouse or use arrow keys to resize. This may be useful for scenarios where the space the user needs can be unpredictable, if content is dynamic. Resizable flyouts allow users to adjust content to better fit their individual screens and workflows.

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

Things we discussed in that thread that I'm wondering about:

  • Push flyouts vs non-push flyouts -- is this optimal for one or the other?
  • Responsiveness - do we need to encourage folks using this option to test their layouts with resizing at various resolutions to ensure their layouts continue to work?
  • Cee: You mentioned a number of technical considerations here, should folks using this be aware of any performance impllications
  • If a user needs more space, should they simply set a larger flyout width, or make it resizable? Do we have a preference as a UX team which they use?

@cee-chen
Copy link
Contributor Author

cee-chen commented Jan 5, 2024

Is it possible to keep the logic for this cleanly separated like you have it, but maintain a prop-based API?

Personally, I don't think so. Adding another EuiFlyoutBase component would create a decent amount of shenanigans primarily around refs and types (due to the as prop which lets consumers render a custom DOM element rendered, which then affects ref typing). I could also see it leading to an annoying amount of Enzyme snapshot churn due to the added wrapper. I just personally don't see the benefit worth time spent, I guess?

Cee: You mentioned a number of technical considerations #7290 (comment), should folks using this be aware of any performance impllications

Ha, past me was so smart, good thing I totally forgot everything I wrote there! Most of the bullet points are addressed but I totally forgot the perf/debouncer bit. That would be good to add pre-emptively to be honest. After some spiking, it's actually a bit of a pain 🥲 I'd be tempted to hang tight on this to see what performance is like before adding any performance optimizations.

One other option we can do here is to flag the component as a Beta one (probably should have done that anyway) and continue to build up the docs and perf behavior in the interim, if Kibana needs the component sooner rather than later. IMO, beta functionality is a fairly solid reason to make this a separate component as well.

@elasticmachine
Copy link
Collaborator

elasticmachine commented Jan 5, 2024

💚 Build Succeeded

History

@kibanamachine
Copy link

Preview staging links for this PR:

@cee-chen
Copy link
Contributor Author

cee-chen commented Jan 8, 2024

Hey y'all! Since this is a feature requested in Kibana, I'm going to go ahead and merge this in as a beta component so it gets into today's EUI release. That being said, I would still really love some answers (especially around documentation and recommendations) - any other comments that get added to this thread I'll be sure to address in a follow-up PR.

@cee-chen cee-chen merged commit 38853f5 into elastic:main Jan 8, 2024
7 checks passed
@cee-chen cee-chen deleted the flyout/resizable branch January 8, 2024 17:30
@kyrspl
Copy link
Contributor

kyrspl commented Jan 10, 2024

Thanks for working on this @cee-chen

Guidelines
Guidelines will be discussed in the Patterns group as we're ramping up a conversation on modality.

Edge case
While playing with the component, I noticed a scenario where the resizable flyout can be added in addition to an existing pushed flyout (see vid). What should be the expected behavior here?

Screen.Recording.2024-01-10.at.11.00.01.mov

Visual indicators
I'm torn regarding the visual indicators on resizing possibilities.

On one hand I do understand the argument of UI clutter. Conversely, removing affordances increases the mental effort to (1) know this option exists in the first place, and (2) move the cursor in the right spot to make it work
I'm also thinking here in terms of accessibility.

Here's a relevant article that describes the problem in more detail.

cee-chen added a commit to elastic/kibana that referenced this pull request Jan 10, 2024
`v91.3.1`⏩`v92.0.0-backport.0`

---

##
[`v92.0.0-backport.0`](https://github.com/elastic/eui/releases/v92.0.0-backport.0)

**This is a backport release only intended for use by Kibana.**

**Bug fixes**

- Fixed an `EuiTreeView` JSX Typescript error
([#7452](elastic/eui#7452))
- Fixed a color console warning being generated by disabled `EuiStep`s
([#7454](elastic/eui#7454))


## [`v92.0.0`](https://github.com/elastic/eui/releases/v92.0.0)

- Updated generic types of `EuiBasicTable`, `EuiInMemoryTable` and
`EuiSearchBar.Query.execute` to add `extends object` constraint
([#7340](elastic/eui#7340))
- This change should have no impact on your applications since the
updated types only affect properties that exclusively accept object
values.
- Added a new `EuiFlyoutResizable` component
([#7439](elastic/eui#7439))
- Updated `EuiTextArea` to accept `isClearable` and `icon` as props
([#7449](elastic/eui#7449))

**Bug fixes**

- `EuiRange`/`EuiDualRange`'s track ticks & highlights now update their
positions on resize ([#7442](elastic/eui#7442))

**Deprecations**

- Updated `EuiFilterButton` to remove the second
`.euiFilterButton__textShift` span wrapper. Target
`.euiFilterButton__text` instead
([#7444](elastic/eui#7444))

**Breaking changes**

- Removed deprecated `EuiNotificationEvent`. We recommend copying the
component to your application if necessary
([#7434](elastic/eui#7434))
- Removed deprecated `EuiControlBar`. We recommend using `EuiBottomBar`
instead ([#7435](elastic/eui#7435))
delanni pushed a commit to delanni/kibana that referenced this pull request Jan 11, 2024
`v91.3.1`⏩`v92.0.0-backport.0`

---

##
[`v92.0.0-backport.0`](https://github.com/elastic/eui/releases/v92.0.0-backport.0)

**This is a backport release only intended for use by Kibana.**

**Bug fixes**

- Fixed an `EuiTreeView` JSX Typescript error
([elastic#7452](elastic/eui#7452))
- Fixed a color console warning being generated by disabled `EuiStep`s
([elastic#7454](elastic/eui#7454))


## [`v92.0.0`](https://github.com/elastic/eui/releases/v92.0.0)

- Updated generic types of `EuiBasicTable`, `EuiInMemoryTable` and
`EuiSearchBar.Query.execute` to add `extends object` constraint
([elastic#7340](elastic/eui#7340))
- This change should have no impact on your applications since the
updated types only affect properties that exclusively accept object
values.
- Added a new `EuiFlyoutResizable` component
([elastic#7439](elastic/eui#7439))
- Updated `EuiTextArea` to accept `isClearable` and `icon` as props
([elastic#7449](elastic/eui#7449))

**Bug fixes**

- `EuiRange`/`EuiDualRange`'s track ticks & highlights now update their
positions on resize ([elastic#7442](elastic/eui#7442))

**Deprecations**

- Updated `EuiFilterButton` to remove the second
`.euiFilterButton__textShift` span wrapper. Target
`.euiFilterButton__text` instead
([elastic#7444](elastic/eui#7444))

**Breaking changes**

- Removed deprecated `EuiNotificationEvent`. We recommend copying the
component to your application if necessary
([elastic#7434](elastic/eui#7434))
- Removed deprecated `EuiControlBar`. We recommend using `EuiBottomBar`
instead ([elastic#7435](elastic/eui#7435))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[EuiFlyout] Allow resizing
7 participants