Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

Components with open/close animations should have cancelable opening/closing start eventsΒ #4357

Closed
@jamesmfriedman

Description

This is more of a generalized issue and feedback regarding how MDC handles components that have an implied stateful lifecycle (opening, opened, closing, closed). Like most of my issues, this one is related to React, but is not React specific.

Because of the uni-directional data flow of React, interfacing with the components through RMWC is controlled via props. You don't execute an openMenu callback, you simply pass open=true. Again, following traditional React patterns, you would pass a callback to something like an onClose prop whenever the state is about to change to closed. This gives you the opportunity to respond to onClose and decided whether or not you want to close the component, or keep it opened. This a relatively standard pattern with what are called "controlled components".

A reductive example

class MyComponent extends React.Component {
  state = {
    open: false
  }

  render() {
    return (
      <Menu
        open={this.state.open}
        // maybe I want to stay open...
        onClose={() => this.setState({open: true})}
      />
    )
  }
}

The heart of where this becomes the problem is in the following code in the menu-surface foundation.

Basically, the MenuSurface has already started its un-cancellable close cycle before it notifies the consumers that it's going to close. This prevents consumers from doing something as simple as leaving the Menu open. The best I've been able to do in the upcoming RMWC release is to "re-open" the menu every time which gives you a nice little blip of the menu on the screen, as well as re-animate and re-call any logic when it opens (like focusing the first menu item).

This example is for the menu, but impacts anything that has similar opening / closing behavior (Menus, Dialogs, Drawers, and Snackbars at a quick glance).

Proposed Solution:

  • Implement a standard pattern for components with an open / close lifecycle
  • Keep an open: boolean flag in the foundation (Menu already has isOpen_)
  • Wait a frame when trying to execute the close cycle and cancel if the open flag has been set back to true
  • Dialog seems to be the closest fit to this pattern right now.

My ideal events

  • open: executed immediately when the open changes from false to true
  • opened: executed when all animations are finished and the component is resting. This may not execute if the component has been switched back to close.
  • close: executed immediately when open changes from true to false
  • closed: executed when all animations are finished and the component is resting. This may not be executed if the component has been switched back to open.

Sorry for the book. Thoughts?

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions