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

Expand EuiFlyout usage to help EuiCollapsibleNav #4713

Merged
merged 41 commits into from
May 11, 2021

Conversation

cchaos
Copy link
Contributor

@cchaos cchaos commented Apr 14, 2021

This PR mainly pushes a bunch of custom props implemented for EuiCollapsibleNav back up to EuiFlyout so that EuiCollapsibleNav can just extend EuiFlyout and EuiFlyout gets more customization options.

👉 EuiFlyout new/adjusted props

as

/**
* Sets the HTML element for `EuiFlyout`
*/
as?: T = 'div';

This helps the EuiCollapsibleNav or any other consumption to pass nav as an element directly.

role

/**
* Defaults to `dialog` which is best for most cases of the flyout.
* Otherwise pass in your own, aria-role, or `none` to remove it and use the semantic `as` element instead
*/
role?: 'none' | HTMLAttributes['role'];

This also helps the EuiCollapsibleNav or any other consumption to change the aria-role type to fit their needs.

size now accepts any viable CSS width value

/**
* Defines the width of the panel.
* Pass a predefined size of `s | m | l`, or pass any number/string compatible with the CSS `width` attribute
*/
size?: _EuiFlyoutSize | CSSProperties['width'];

Allows for real customization of the actual rendered flyout width instead of relying on max-width or overrides.

Screen Shot 2021-04-19 at 16 00 12 PM

closeButtonProps

/**
* Extends EuiButtonIconProps onto the close button
*/
closeButtonProps?: EuiButtonIconProps;

Good for extending/changing things like data-test-subj or adding a className.

closeButtonPosition

/**
* Position of close button.
* `inside`: Floating to just inside the flyout, always top right;
* `outside`: Floating just outside the flyout near the top (side dependent on `side`). Helpful when the close button may cover other interactable content.
*/
closeButtonPosition?: 'inside' | 'outside';

This was added to push up EuiCollapsibleNav's custom implementation of a solid close button that floats outside of the flyout, instead of within. Purposefully, there was no documentation added around this as we want to try to stay consistent for default EuiFlyout types.

Screen Shot 2021-04-19 at 16 20 43 PM

outsideClickCloses

/**
* Forces this interaction on the mask overlay or body content.
* Defaults depend on `ownFocus` and `type` values
*/
outsideClickCloses?: boolean;

Also another request of the EuiCollapsibleNav is to allow a version where there's no overlay mask obscuring the content beneath, but we still want it to close automatically when starting to interact with the page content.

Video
Screen.Recording.2021-04-19.at.04.26.08.PM.mp4

side

/**
* Which side of the window to attach to.
* The `left` option should only be used for navigation.
*/
side?: 'left' | 'right';

This removed the duplication of the CSS styles via the euiFlyout() Sass mixin in EuiCollapsibleNav and just added a quick manipulation of the position CSS for the flyout itself. Again, purposefully left this prop out of the docs examples as we want the default to always be right.

type

/**
* How to display the the flyout in relation to the body content;
* `push` keeps it visible, pushing the `<body>` content via padding
*/
type?: 'overlay' | 'push';

This one might be controversial. But, we have custom implementations like this in Kibana that would be good to maintain at the EUI level. It helps EuiCollapsibleNav maintain the docked status and how the body accommodates for it with padding.

Screen Shot 2021-04-30 at 10 33 26 AM

pushMinBreakpoint

/**
* Named breakpoint or pixel value for customizing the minimum window width to enable the `push` type
*/
pushMinBreakpoint?: EuiBreakpointSize | number;

A pushed flyout still positions itself as fixed, but adds padding to the document's body element to accomodate for the flyout's width. Because this squishes the page content, the flyout changes back to overlay at smaller window widths. You can adjust this minimum breakpoint with pushMinBreakpoint.

Screen Shot 2021-04-19 at 16 36 35 PM

👉 EuiCollapsibleNav now extends EuiFlyout

The props list has been shortened and instead extends all the same props as EuiFlyout (with a few exceptions like type because it manages this with isDocked).

🔔 Breaking changes

EuiFlyout now defaults to ownFocus = true

This means that any default implementations of EuiFlyout with display the overlay mask. This is inherently good for accessibility and the proper way to display EuiFlyouts. The version without the overlay mask is the lesser common use or should be less common.

To compensate: If you need users to maintain the ability to interact with page contents while the flyout is open, set ownFocus={false}. Otherwise, the overlay mask is appropriate.

EuiFlyout gets wrapped in an EuiPortal when ownFocus = true

Because z-indexes are terrible and overlay masks are always in a portal, but the flyout itself was not, we were using z-indexes to position these layers. But this broke as soon as position: relative was added to any element wrapping the EuiFlyout. So now we just append the flyout to the document body within the overlay mask if the overlay mask exists (when ownFocus = true).

To compensate: There shouldn't need to be anything to do here unless there's a specific reason you need the flyout to exist in the nested dom exactly where it is placed in the code.

EuiCollapsibleNav now manages width via prop instead of CSS

Since the component extends EuiFlyout which accepts a number or string value via the size prop, the Sass variable $euiCollapsibleNavWidth has been removed in favor of this React prop. Though, the default width is still the same 320px.

To compensate: Delete any usages of $euiCollapsibleNavWidth and apply your custom width as the size prop.

EuiOverlayMask no longer uses z-index alone for determining position below header

The z-index now actually matches that of the EuiHeader, but since it's in a portal (appended to the dom) it will alway be "above" to ensure it sits above any non-fixed headers. So in order to make it appear below the header, it now uses the top value to offset it's position. This is added in the euiHeaderAffordForFixed() Sass mixin.

To compensate: As long as you are still using the euiHeaderAffordForFixed() Sass mixin for other offsets based on fixed headers, there's nothing to do. Otherwise, you will have to afford for this manually.

Other

Added a isWithinMinBreakpoint() breakpoint service to help find when the browser width is actually above the breakpoint passed.

Checklist

  • Check against all themes for compatibility in both light and dark modes
  • Checked in mobile
  • Checked in Chrome, Safari, Edge, and Firefox
  • Checked in Kibana
  • Props have proper autodocs and playground toggles
  • Added documentation
  • Checked Code Sandbox works for the any docs examples
  • Added or updated jest tests
  • Checked for breaking changes and labeled appropriately
  • Checked for accessibility including keyboard-only and screenreader modes
  • A changelog entry exists and is marked appropriately

@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_4713/

@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_4713/

@cchaos cchaos changed the title [WIP] Expand EuiFlyout usage with push type and side prop. [WIP] Expand EuiFlyout usage to help EuiCollapsibleNav Apr 19, 2021
@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_4713/

@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_4713/

@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_4713/

cchaos added 2 commits May 3, 2021 11:57
…e-nav

# Conflicts:
#	CHANGELOG.md
#	src/components/collapsible_nav/__snapshots__/collapsible_nav.test.tsx.snap
#	src/components/flyout/__snapshots__/flyout.test.tsx.snap
@cchaos
Copy link
Contributor Author

cchaos commented May 4, 2021

Jenkins, test this

@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_4713/

Copy link
Contributor

@myasonik myasonik left a comment

Choose a reason for hiding this comment

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

🚀

src-docs/src/views/flyout/flyout_example.js Show resolved Hide resolved
src-docs/src/views/flyout/flyout_example.js Show resolved Hide resolved
@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_4713/

@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_4713/

* Defaults to `dialog` which is best for most cases of the flyout.
* Otherwise pass in your own, aria-role, or `none` to remove it and use the semantic `as` element instead
*/
role?: 'none' | string;
Copy link
Contributor

Choose a reason for hiding this comment

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

What do you think about dropping none and relying on role={undefined} to unset instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah I had tried that before and was getting a11y errors, and I just tried again by just setting role?: string but passing role={undefined} seems to completely ignore the undefined and always keep the default 'dialog'. I did try with null, which works but that means just changing this to role?: null | string; but undefined still won't work.

Should I go with null?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ack, that's right, because the default value is applied when a value is undefined. I think null is a bit cleaner than 'none', but I'm good either way

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll update to null

Copy link
Contributor

@miukimiu miukimiu left a comment

Choose a reason for hiding this comment

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

Tested in Chrome, Firefox, Safari and Edge. LGTM! 🎉

I just have a few suggestions.

src-docs/src/views/flyout/flyout_example.js Outdated Show resolved Hide resolved
@@ -72,11 +65,14 @@ export const CollapsibleNavExample = {
props: { EuiCollapsibleNav },
demo: <CollapsibleNav />,
snippet: `<EuiCollapsibleNav
ownFocus={false}
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any reason we want the snippet to have ownFocus={false}?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah yeah, so in Kibana we're going to use this setting on the global nav and went back and forth whether our docs should have it off by default too, then I think I forgot to update the snippet. Good catch.

src-docs/src/views/flyout/flyout_example.js Outdated Show resolved Hide resolved
Copy link
Contributor

@chandlerprall chandlerprall left a comment

Choose a reason for hiding this comment

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

Changes LGTM! Lots of goods things here

Copy link
Contributor

@thompsongl thompsongl left a comment

Choose a reason for hiding this comment

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

I will likely not have time to review this today, but I'm good merging with the current approvals in place.

Copy link
Contributor

@chandlerprall chandlerprall left a comment

Choose a reason for hiding this comment

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

null role change LGTM

@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_4713/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants