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

Update Popover with center alignments and Justify.Fit #295

Merged
merged 27 commits into from
Mar 26, 2020
Merged

Conversation

jetpacmonkey
Copy link
Collaborator

@jetpacmonkey jetpacmonkey commented Mar 3, 2020

✍️ Proposed changes

As part of the work for adding a <Select> component, Popover needed some additional functionality. This PR adds support for align={Align.CenterHorizontal}, align={Align.CenterVertical}, and justify={Justify.Fit}. I also removed the Justification enum, as it's become redundant with Align, and refactored a bunch of internals in positionUtils to derive values directly from Align and Justify, without using Justification as a go-between.

Some of the changes led to test failures in the positionUtils unit tests because of a change from 30 to '30px' (for example), so instead of changing them all over, I wrote a custom matcher that accepts either of the two formats. This feels like a better test (to me, at least) since it should generally avoid false positives on changes that don't actually impact behavior.

🎟 Jira ticket: PD-271

🛠 Types of changes

  • Tooling (updates to workspace config or internal tooling)
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

✅ Checklist

  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)
  • I have run yarn changeset and documented my changes
  • I have added my new package to the global tsconfig
  • I have added my new package to the Table of Contents on the global README

💬 Further comments

This is, unfortunately, a breaking change, since justification was being passed to the function-as-a-child pattern. I've also included a fix for Tooltip, which was relying on that behavior. I would assume that we probably don't have any external consumers relying on Popover, so that should be sufficient.

@jetpacmonkey
Copy link
Collaborator Author

Oh, I guess I should probably add testcases for the new enum values. Regardless, this is ready for review while I do that.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 4, 2020

Size Change: +1.31 kB (0%)

Total Size: 519 kB

Filename Size Change
packages/popover/dist/index.node.js 4.72 kB +595 B (12%) ⚠️
packages/popover/dist/index.web.js 4.72 kB +595 B (12%) ⚠️
packages/tooltip/dist/index.node.js 4.56 kB +60 B (1%)
packages/tooltip/dist/index.web.js 4.61 kB +57 B (1%)
ℹ️ View Unchanged
Filename Size Change
packages/badge/dist/index.node.js 1.92 kB 0 B
packages/badge/dist/index.web.js 1.92 kB 0 B
packages/box/dist/index.node.js 7.01 kB 0 B
packages/box/dist/index.web.js 7.05 kB 0 B
packages/button/dist/index.node.js 9.31 kB 0 B
packages/button/dist/index.web.js 9.35 kB 0 B
packages/card/dist/index.node.js 7.05 kB 0 B
packages/card/dist/index.web.js 7.08 kB 0 B
packages/checkbox/dist/index.node.js 74.1 kB 0 B
packages/checkbox/dist/index.web.js 74.1 kB 0 B
packages/code/dist/index.node.js 7.74 kB 0 B
packages/code/dist/index.web.js 7.79 kB 0 B
packages/emotion/dist/index.node.js 973 B 0 B
packages/emotion/dist/index.web.js 1.04 kB 0 B
packages/hooks/dist/index.node.js 2.72 kB 0 B
packages/hooks/dist/index.web.js 2.77 kB 0 B
packages/icon-button/dist/index.node.js 2.28 kB 0 B
packages/icon-button/dist/index.web.js 2.28 kB 0 B
packages/icon/dist/index.node.js 8.3 kB 0 B
packages/icon/dist/index.web.js 8.3 kB 0 B
packages/leafygreen-provider/dist/index.node.js 1.8 kB 0 B
packages/leafygreen-provider/dist/index.web.js 1.8 kB 0 B
packages/lib/dist/index.node.js 1.25 kB 0 B
packages/lib/dist/index.web.js 1.25 kB 0 B
packages/logo/dist/index.node.js 8.3 kB 0 B
packages/logo/dist/index.web.js 8.3 kB 0 B
packages/menu/dist/index.node.js 6.78 kB 0 B
packages/menu/dist/index.web.js 6.78 kB 0 B
packages/modal/dist/index.node.js 2.96 kB 0 B
packages/modal/dist/index.web.js 2.96 kB 0 B
packages/mongo-nav/dist/index.node.js 26.6 kB 0 B
packages/mongo-nav/dist/index.web.js 26.6 kB 0 B
packages/palette/dist/index.node.js 1.17 kB 0 B
packages/palette/dist/index.web.js 1.17 kB 0 B
packages/pipeline/dist/index.node.js 12.9 kB 0 B
packages/pipeline/dist/index.web.js 12.9 kB 0 B
packages/portal/dist/index.node.js 1.71 kB 0 B
packages/portal/dist/index.web.js 1.71 kB 0 B
packages/radio-box-group/dist/index.node.js 3.79 kB 0 B
packages/radio-box-group/dist/index.web.js 3.8 kB 0 B
packages/radio-group/dist/index.node.js 2.93 kB 0 B
packages/radio-group/dist/index.web.js 2.93 kB 0 B
packages/side-nav/dist/index.node.js 8.69 kB 0 B
packages/side-nav/dist/index.web.js 8.75 kB 0 B
packages/syntax/dist/index.node.js 24.1 kB 0 B
packages/syntax/dist/index.web.js 24.1 kB 0 B
packages/tabs/dist/index.node.js 9.51 kB 0 B
packages/tabs/dist/index.web.js 9.55 kB 0 B
packages/text-input/dist/index.node.js 3.19 kB 0 B
packages/text-input/dist/index.web.js 3.19 kB 0 B
packages/theme/dist/index.node.js 940 B 0 B
packages/theme/dist/index.web.js 940 B 0 B
packages/toggle/dist/index.node.js 4.29 kB 0 B
packages/toggle/dist/index.web.js 4.29 kB 0 B
packages/typography/dist/index.node.js 7.59 kB 0 B
packages/typography/dist/index.web.js 7.63 kB 0 B

compressed-size-action

@jetpacmonkey
Copy link
Collaborator Author

Alright, that should be full test coverage for the new values now

@jetpacmonkey
Copy link
Collaborator Author

Note: The Justify.Fit value impacts the width/height of the child, which can cause some wonkiness when changing from Fit to one of the other Justify values. For instance...

  1. align={Align.Top} justify={Justify.Fit}: left: 0, width: parent width
  2. justify={Justify.Middle}: Since child width and parent width are equal, centering means left: 0
  3. Browser re-renders, and now that we're not explicitly setting the child width it changes back to being based on its content, while being left-aligned on the parent.

The popover will then correct its position the next time the browser window is resized or if the mutation observer is triggered.

Changes to the justify prop seems like a pretty rare edge case to me, but thought it should be mentioned.

Copy link
Collaborator

@hswolff hswolff left a comment

Choose a reason for hiding this comment

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

I did not go too in depth on the logic changes, I skimmed them and they look mostly 'right'.

packages/tooltip/src/Tooltip.tsx Outdated Show resolved Hide resolved
packages/tooltip/src/tooltipUtils.tsx Outdated Show resolved Hide resolved
import diff from 'jest-diff';

expect.extend({
toBePx(received, expected) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I mean, I guess so? I'd just as much update the tests to have them match so we don't have to maintain this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

My first pass updated all the tests with a regex replace, but then it turned out that not all of the internal functions seemed to be consistent with whether it used a number or a string with px. I suppose a helper function in the test file might be easier to maintain, though.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I feel semi strongly to not take on this debt, but I'm curious about @DesignerDave's thoughts.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

function checkPixelValue(actual: string | number, expected: number) {
  if (typeof actual === 'string') {
    expect(actual).toBe(`${expected}px`);
  } else {
    expect(actual).toBe(expected);
  }
}

it's a pretty easy regex find/replace to just use this instead, so that's probably worth the small tradeoff in having very slightly worse diffs and error messages.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated with the helper function

@jetpacmonkey
Copy link
Collaborator Author

@hswolff addressed your comments

@jetpacmonkey
Copy link
Collaborator Author

@DesignerDave I just pushed up a commit that fixes the issue when changing to/from justify={Justify.Fit} that I described on Tuesday

break;
}
// Constructs the transform origin for any given pair of alignment / justification
function getTransformOrigin({ align, justify }: TransformOriginArgs): string {
Copy link
Collaborator

Choose a reason for hiding this comment

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

love this

}

switch (justification) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Thank you for removing these crazy switch statements

@jetpacmonkey
Copy link
Collaborator Author

Right, and that's still effectively the case if you do align=left and justify=middle or whatever, although since I removed the Justification enum the end user might have to do a bit of that logic for themselves in the function-as-a-child version. But if you want your primary alignment to be in the center, you need some way to distinguish which axis it is that you're centering on, and there's no way to infer that based off of just start, end, middle, or fit.

@DesignerDave
Copy link
Collaborator

Alright, I think I was misunderstanding.

With the latest I'm still finding issues when switching between alignments:

align: center-vertical with justify: middle:
Screen Shot 2020-03-09 at 3 55 14 PM

align: center-vertical with justify: fit:
Screen Shot 2020-03-09 at 3 57 07 PM

align: fit with justify: fit:
Screen Shot 2020-03-09 at 4 03 28 PM

All of these were triggered from switching to, and then from a center alignment. I'm having trouble reproducing the padding issue in particular, but I can pretty consistently reproduce the alignment issues.

@jetpacmonkey
Copy link
Collaborator Author

I switched the storybook popover to have overflow: hidden to more directly see it changing the widths/heights, so that's probably the padding issue. The alignment being off, though, is odd, and I'm not seeing the same behavior on my machine. Also what is align: fit?

@DesignerDave
Copy link
Collaborator

Whoops, copy + paste error. align: left I believe that was.

Try this:

  1. Refresh the page
  2. Open the popover
  3. Change align to center-vertical
  4. Change justify to fit
  5. Change align to left

That should get you to at least the last screenshot I sent.

Doing the following will also result in a strange alignment:

  1. Refresh the page
  2. Open the popover
  3. Change align to center-vertical
  4. Change justify to fit
  5. Change align to center-horizontal

@jetpacmonkey
Copy link
Collaborator Author

Oh, there it is! Just reproduced it.

@jetpacmonkey
Copy link
Collaborator Author

Alright, so I had it re-render when changing to or from fit, but it seems like I probably also should have it re-render when justify is fit and you're switching between one of the "column" direction alignments and one of the "row" direction alignments.

@jetpacmonkey
Copy link
Collaborator Author

Thanks for the thorough debugging @DesignerDave! Just pushed up an update that should cover those additional cases. I'm not sure if there's a good way to write an automated test for those types of cases without a browser environment, but I also doubt that there's a realistic usecase for switching between a vertically-oriented alignment and a horizontal one, so we should be fine I think.

@DesignerDave
Copy link
Collaborator

@jetpacmonkey Those fixes seem to be working well! Thanks for the update.

Little more QA on components currently using popover:

Tooltip – align: center-horizontal | center-vertical; justify: middle;
Screen Shot 2020-03-11 at 10 43 42 AM
The arrow is now positioned strangely likely due to the alignment not being handled (the top of the "I" is being cut off). I wouldn't be opposed to not supporting center-horizontal and center-vertical at all in tooltip, but if we do, we should at least hide the arrow. Ditto for disabling justify: fit for tooltips for the time being.

Everything else is looking good now it seems! Awesome stuff.

@jetpacmonkey
Copy link
Collaborator Author

I'm back from the worst-timed vacation in history! I don't think I realized that Tooltip was extending PopoverProps directly, I agree that the new alignments probably don't need to be supported at all. justify: fit is probably harmless to allow on its own, but I'll skip it if there seem to be issues.

@jetpacmonkey
Copy link
Collaborator Author

@DesignerDave I think that should be everything. I left justify: fit in there for Tooltip even though it's not a super likely usecase, because it seemed to work without any other modifications.

@DesignerDave
Copy link
Collaborator

Hey @jetpacmonkey, sorry for the delayed response.

I was testing out tooltip, and it looks like align left/right with justify fit doesn't work:
Screen Shot 2020-03-26 at 2 41 47 PM

Fit should work for those alignments, right? Otherwise this seems ready to go!

@jetpacmonkey
Copy link
Collaborator Author

Yeah, that's actually working the same as it does in Popover. If your popover/tooltip has a defined height (or width for top/bottom alignments) that's larger than the trigger, or enough content and padding to make the popover grow to be bigger without overflow: hidden, that overrides setting top/bottom. That's why I made the change to the Popover storybook to have a taller button and overflow: hidden on the popover.

Copy link
Collaborator

@DesignerDave DesignerDave left a comment

Choose a reason for hiding this comment

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

Sweet, that makes sense. LGTM!

@jetpacmonkey jetpacmonkey merged commit 8fe6529 into master Mar 26, 2020
@jetpacmonkey jetpacmonkey deleted the PD-271 branch March 26, 2020 19:26
jetpacmonkey added a commit that referenced this pull request Mar 26, 2020
@jetpacmonkey jetpacmonkey mentioned this pull request Mar 26, 2020
9 tasks
jetpacmonkey added a commit that referenced this pull request Mar 26, 2020
bruugey pushed a commit that referenced this pull request Aug 9, 2023
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.

4 participants