Skip to content

[Popover] Refactor popover transition - separation of concerns#7720

Merged
oliviertassinari merged 17 commits into
mui:v1-betafrom
alienfast:refactor-popover-transition
Aug 10, 2017
Merged

[Popover] Refactor popover transition - separation of concerns#7720
oliviertassinari merged 17 commits into
mui:v1-betafrom
alienfast:refactor-popover-transition

Conversation

@rosskevin

@rosskevin rosskevin commented Aug 9, 2017

Copy link
Copy Markdown
Contributor

squash+merge

For simplification and external reuse of the Popover transition (now called Grow) with react-autosuggest, I have refactored Popover. Popover is currently used exclusively by Menu.

As it stands, here are the purposes:

  • internal/Popover = positioning + Modal + Grow + Paper (used by Menu)
  • transitions/Grow = only the effect exhibited by popovers - grow with a bit of fade in.

There are also various small fixes I encountered as I refactored.

I should also mention that this is possibly the lead-in to deleting the positioning code in Popover in lieu of using react-popper, but I'll wait to take that on after I've used it a bit with react-autosuggest.


@rosskevin

rosskevin commented Aug 9, 2017

Copy link
Copy Markdown
Contributor Author

NOTE: I have seen cross-contamination of tests when run sequentially. I could use some help with that.

Individually, tests are passing and the Grow.spec.js in fact never uses the value woof, so I suspect that the virtual DOM has something left over or there is some sort of race condition from a previous test.

I have changed all references to woof to isolate the cross-contamination:

  1101 passing (3s)
  3 failing

  1) <Grow /> event callbacks should fire event callbacks:
     Error: Warning: Material-UI: argument "duration" must be a number but found woofCollapse
      at Console.console.error (test/utils/consoleError.js:8:5)
      at warning (node_modules/warning/warning.js:51:17)
      at Object.create (src/styles/transitions.js:66:5)
      at Grow._this.handleEnter (src/transitions/Grow.js:92:19)
      at node_modules/enzyme/build/ShallowWrapper.js:844:23
      at ReactDefaultBatchingStrategyTransaction.perform (node_modules/react-test-renderer/lib/shallow/Transaction.js:143:20)
      at Object.batchedUpdates (node_modules/react-test-renderer/lib/shallow/ReactDefaultBatchingStrategy.js:62:26)
      at Object.batchedUpdates (node_modules/react-test-renderer/lib/shallow/ReactUpdates.js:97:27)
      at ReactShallowRenderer.unstable_batchedUpdates (node_modules/react-test-renderer/lib/shallow/ReactShallowRenderer.js:130:25)
      at performBatchedUpdates (node_modules/enzyme/build/ShallowWrapper.js:103:21)
      at node_modules/enzyme/build/ShallowWrapper.js:843:13
      at withSetStateAllowed (node_modules/enzyme/build/Utils.js:284:3)
      at ShallowWrapper.simulate (node_modules/enzyme/build/ShallowWrapper.js:840:42)
      at src/transitions/Grow.spec.js:29:17
      at Array.forEach (native)
      at Context.<anonymous> (src/transitions/Grow.spec.js:27:14)

  2) <Grow /> transition lifecycle handleEnter(element) "before all" hook:
     Error: Warning: Material-UI: argument "duration" must be a number but found woofCollapse
      at Console.console.error (test/utils/consoleError.js:8:5)
      at warning (node_modules/warning/warning.js:51:17)
      at Object.create (src/styles/transitions.js:66:5)
      at Grow._this.handleEnter (src/transitions/Grow.js:92:19)
      at Context.<anonymous> (src/transitions/Grow.spec.js:55:28)

  3) <Grow /> transition lifecycle handleExit(element) "before all" hook:
     Error: Warning: Material-UI: argument "duration" must be a number but found woofCollapse
      at Console.console.error (test/utils/consoleError.js:8:5)
      at warning (node_modules/warning/warning.js:51:17)
      at Object.create (src/styles/transitions.js:66:5)
      at Grow._this.handleExit (src/transitions/Grow.js:120:19)
      at Context.<anonymous> (src/transitions/Grow.spec.js:104:28)

@rosskevin

Copy link
Copy Markdown
Contributor Author

This appears to be stubbed and perhaps never unstubbed:

theme.transitions.getAutoHeightDuration = stub().returns('woofCollapse');

@rosskevin

rosskevin commented Aug 10, 2017

Copy link
Copy Markdown
Contributor Author

@oliviertassinari this recently changed from a styleManagerMock to an assignment on theme.
Was:

         styleManagerMock = wrapper.context('styleManager');
          styleManagerMock.theme.transitions.getAutoHeightDuration = stub().returns('woof');
          wrapper.setContext({ styleManager: styleManagerMock });
          wrapper.setProps({ transitionDuration: 'auto' });
          instance = wrapper.instance();

Now:

          theme = instance.props.theme;
          theme.transitions.getAutoHeightDuration = stub().returns('woofCollapseStub');
          wrapper.setProps({ transitionDuration: 'auto' });
          instance = wrapper.instance();

Either we need to regenerate theme so it is pristine on each shallow | mount, or this test needs to go back to using a mock. What are your thoughts?

@rosskevin

Copy link
Copy Markdown
Contributor Author

I added an explicit restore of the stubbed method.

@oliviertassinari oliviertassinari left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I like the idea of this PR. It's a quick review, I need to have a deeper look this evening :).

Comment thread src/internal/Popover.js Outdated
* @ignore - internal component.
*/
class Popover extends Component<DefaultProps, AllProps, void> {
class Popover extends PureComponent<DefaultProps, AllProps, void> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The component takes a children, let's keep Component.

Comment thread src/transitions/Grow.js Outdated
/**
* @ignore - internal component.
*/
class Grow extends PureComponent<DefaultProps, AllProps, void> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The component takes a children, PureComponent is harming the performance, let's use to Component.

@rosskevin

Copy link
Copy Markdown
Contributor Author

I've confirmed the Grow to work as expected when used externally.

@FezVrasta

Copy link
Copy Markdown

Feel free to ping me if you need help or more info about react-popper and Popper.js in general.

@rosskevin

Copy link
Copy Markdown
Contributor Author

Thanks @FezVrasta - hope you are well.

@oliviertassinari oliviertassinari left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I had a deep look into it. That looks great 😄 .

Comment thread src/internal/Popover.js
</Grow>
</Modal>
);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can remove all the occurrences of withTheme and theme in this file.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

still need it in #handleEnter for theme.transitions

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I can't find that.

@rosskevin rosskevin Aug 10, 2017

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sorry, I was looking at the wrong file, you are right.

Comment thread src/internal/Popover.js
...other
} = this.props;

// FIXME: props API consistency problem? - `...other` not spread over the root

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I agree, let's move the ...other to the root. What's preventing us from doing it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Nothing yet, just want to save that for the next wave of the refactor.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

OK

Comment thread src/transitions/Grow.js
}

type DefaultProps = {
theme: Object,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This property is injected by withTheme(), I don't think that we need it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

necessary for flow resolution. We could add it to AllProps instead, but that would differ from the pattern in other files.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Won't making the property required allow us to remove it here? It's the same for the classes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It has to be required somewhere, and it is not required outside this component. If it is not required outside the component, we cannot require it in export type Props, as it would prohibit using the type externally to compose components.

Comment thread src/transitions/Grow.js
/**
* @ignore
*/
theme?: Object,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think that it should be required.

@rosskevin rosskevin Aug 10, 2017

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It's not required externally (maybe type), but it is internally, that's why it's optional in Props and required in DefaultProps. The intersection of these mean internally the component can expect it to be non-null.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Isn't the same thing with the classes? I have put them required in the code, but in the documentation I have change them to be optional. Anyway here it's not documented.

@rosskevin rosskevin Aug 10, 2017

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Same as classes, see above for explanation. It's all about externalizing Props for reuse. If theme isn't allowed to be passed in (by the user), we should remove it from Props.

Comment thread src/transitions/Grow.js
import Transition from '../internal/Transition';
import type { TransitionCallback } from '../internal/Transition';

export function getScale(value: number) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe we should add // Only exported for the tests.

@oliviertassinari

Copy link
Copy Markdown
Member

I should also mention that this is possibly the lead-in to deleting the positioning code in Popover in lieu of using react-popper

I'm not that sure about it. The Popover has a getContentAnchorEl property to handle a specific positioning requirement of the material specification.
aout-10-2017 20-00-59

@rosskevin

Copy link
Copy Markdown
Contributor Author

I'm not that sure about it. The Popover has a getContentAnchorEl property to handle a specific positioning requirement of the material specification.

This can be done with popper, even the custom positioning with a modifier. I'm not too keen to take that on yet. I've got a lot on my plate, but it is certainly viable and I think it would cut code and rely on a good external project.

@oliviertassinari
oliviertassinari merged commit 640e56e into mui:v1-beta Aug 10, 2017
@oliviertassinari

Copy link
Copy Markdown
Member

@rosskevin Great, it's much better with the concerns separated :).

sebald pushed a commit to PTW-Freiburg/material-ui that referenced this pull request Aug 15, 2017
* upstream/v1-beta: (24 commits)
  v1.0.0-beta.5
  Update CHANGELOG.md
  [CHANGELOG] Prepare v1.0.0-beta.5
  chore(package): update size-limit to version 0.9.0 (mui#7757)
  [docs] Fix yarn docs:build script (mui#7745)
  [docs] Update the readme
  [Radio] Fix accessibility issue (mui#7742)
  [Tabs][BottomNavigation] Use value over index property (mui#7741)
  [core] Remove createStyleSheet (mui#7740)
  [core] Start simplifying styling API (mui#7730)
  [LinearProgress] Use transform instead width (mui#7732)
  Fix Typo (mui#7736)
  Documentation Fix - Fixing up the README documentation (mui#7733)
  [ButtonBase] Expose internal component (mui#7727)
  [Popover] Refactor popover transition - separation of concerns (mui#7720)
  Button documentation fix (mui#7726)
  Update supported-components.md (mui#7722)
  chore(package): update webpack to version 3.5.3 (mui#7723)
  [flow] flow type transitions Slide, Fade, Collapse (fixes)
  Create CODE_OF_CONDUCT.md
  ...
@rosskevin
rosskevin deleted the refactor-popover-transition branch August 16, 2017 21:05
@zannager zannager added the component: Popover The React component. label Mar 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: Popover The React component.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants