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

[WIP] Fix calculation for center aligned popover #2362

Closed
wants to merge 3 commits into from

Conversation

alex-page
Copy link
Member

@alex-page alex-page commented Oct 25, 2019

WHY are these changes introduced?

Re-re- fixes #1673
Fixes #2231 (comment)

WHAT is this pull request doing?

  • Remove horizontal margin on popover overlay.
  • Right aligned popovers positioned with left value
  • Simplify and update math.ts
  • Remove prefferedAlignment="right" on topbar

How to 🎩

🖥 Local development instructions
🗒 General tophatting guidelines
📄 Changelog guidelines

Copy-paste this code in playground/Playground.tsx:
import * as React from 'react';
import {ArrowLeftMinor} from '@shopify/polaris-icons';
import {string} from 'prop-types';
import {
  AppProvider,
  Frame,
  Page,
  Card,
  ActionList,
  TopBar,
  Button,
  Popover,
  PopoverProps,
} from '../src';

interface State {
  userMenuOpen: boolean;
  searchActive: boolean;
  searchText: string;
  popover1Active: boolean;
  popover2Active: boolean;
  popover3Active: boolean;
  popover1PositionBelow: boolean;
  popover2PositionBelow: boolean;
  popover3PositionBelow: boolean;
  showScrollingUserMenu: boolean;
}

export class Playground extends React.Component {
  state: State = {
    userMenuOpen: false,
    searchActive: false,
    searchText: '',
    popover1Active: false,
    popover2Active: false,
    popover3Active: false,
    popover1PositionBelow: true,
    popover2PositionBelow: true,
    popover3PositionBelow: true,
    showScrollingUserMenu: true,
  };

  render() {
    const {
      state,
      handleSearchChange,
      handleSearchResultsDismiss,
      toggleUserMenu,
    } = this;
    const {
      userMenuOpen,
      searchText,
      searchActive,
      showScrollingUserMenu,
    } = state;

    const theme = {
      colors: {
        topBar: {
          background: '#357997',
          backgroundLighter: '#6192a9',
          color: '#FFFFFF',
        },
      },
      logo: {
        width: 124,
        topBarSource:
          'https://cdn.shopify.com/s/files/1/0446/6937/files/jaded-pixel-logo-color.svg?6215648040070010999',
        url: 'http://jadedpixel.com',
        accessibilityLabel: 'Jaded Pixel',
      },
    };

    const actionsWithScroll = [
      {
        items: [{content: 'Back to Shopify', icon: ArrowLeftMinor}],
      },
      {
        items: [{content: 'Community forums'}],
      },
      {
        items: [{content: 'Community forums'}],
      },
      {
        items: [{content: 'Community forums'}],
      },
      {
        items: [{content: 'Community forums'}],
      },
      {
        items: [{content: 'Community forums'}],
      },
      {
        items: [{content: 'Community forums'}],
      },
    ];

    const actions = [
      {
        items: [{content: 'Back to Shopify', icon: ArrowLeftMinor}],
      },
      {
        items: [{content: 'Community forums'}],
      },
      {
        items: [{content: 'Community forums'}],
      },
      {
        items: [{content: 'Community forums'}],
      },
    ];

    const userMenuMarkup = (
      <TopBar.UserMenu
        actions={showScrollingUserMenu ? actionsWithScroll : actions}
        name="Dharma"
        detail="Jaded Pixel"
        initials="D"
        open={userMenuOpen}
        onToggle={toggleUserMenu}
      />
    );

    const searchResultsMarkup = (
      <Card>
        <ActionList
          items={[
            {content: 'Shopify help center'},
            {content: 'Community forums'},
          ]}
        />
      </Card>
    );

    const searchFieldMarkup = (
      <TopBar.SearchField
        onChange={handleSearchChange}
        value={searchText}
        placeholder="Search"
      />
    );

    const topBarMarkup = (
      <TopBar
        showNavigationToggle
        userMenu={userMenuMarkup}
        searchResultsVisible={searchActive}
        searchField={searchFieldMarkup}
        searchResults={searchResultsMarkup}
        onSearchResultsDismiss={handleSearchResultsDismiss}
      />
    );

    const activator1 = (
      <Button onClick={this.togglePopover('popover1', 'Active')}>
        Popover Left
      </Button>
    );

    const activator2 = (
      <Button onClick={this.togglePopover('popover2', 'Active')}>
        Popover Center
      </Button>
    );

    const activator3 = (
      <Button onClick={this.togglePopover('popover3', 'Active')}>
        Popover Right
      </Button>
    );

    return (
      <AppProvider i18n={{}} theme={theme}>
        <Frame topBar={topBarMarkup}>
          <Page
            title="Popover alignment/width bug"
            primaryAction={{
              content: `Render ${
                showScrollingUserMenu ? 'non-scrolling' : 'scrolling'
              } user menu`,
              onAction: this.toggleScrollingUserMenu,
            }}
          >
            <Card>
              <Card.Section
                actions={[
                  {
                    content: 'Toggle position',
                    onAction: this.togglePopover('popover1', 'PositionBelow'),
                  },
                ]}
              >
                <Popover
                  active={this.state.popover1Active}
                  activator={activator1}
                  onClose={this.togglePopover('popover1', 'Active')}
                  preferredAlignment="left"
                  preferredPosition={
                    this.state.popover1PositionBelow ? 'below' : 'above'
                  }
                >
                  <ActionList
                    items={[{content: 'Import'}, {content: 'Export'}]}
                  />
                </Popover>
              </Card.Section>
              <Card.Section
                actions={[
                  {
                    content: 'Toggle position',
                    onAction: this.togglePopover('popover2', 'PositionBelow'),
                  },
                ]}
              >
                <Popover
                  active={this.state.popover2Active}
                  activator={activator2}
                  onClose={this.togglePopover('popover2', 'Active')}
                  preferredAlignment="center"
                  preferredPosition={
                    this.state.popover2PositionBelow ? 'below' : 'above'
                  }
                >
                  <ActionList
                    items={[{content: 'Import'}, {content: 'Export'}]}
                  />
                </Popover>
              </Card.Section>
              <Card.Section
                actions={[
                  {
                    content: 'Toggle position',
                    onAction: this.togglePopover('popover3', 'PositionBelow'),
                  },
                ]}
              >
                <Popover
                  active={this.state.popover3Active}
                  activator={activator3}
                  onClose={this.togglePopover('popover3', 'Active')}
                  preferredAlignment="right"
                  preferredPosition={
                    this.state.popover3PositionBelow ? 'below' : 'above'
                  }
                >
                  <ActionList
                    items={[{content: 'Import'}, {content: 'Export'}]}
                  />
                </Popover>
              </Card.Section>
            </Card>
          </Page>
        </Frame>
      </AppProvider>
    );
  }

  toggleUserMenu = () => {
    this.setState(({userMenuOpen}: State) => ({userMenuOpen: !userMenuOpen}));
  };

  toggleScrollingUserMenu = () => {
    this.setState(({showScrollingUserMenu, userMenuOpen}: State) => ({
      showScrollingUserMenu: !showScrollingUserMenu,
    }));
  };

  togglePopover = (popoverID: string, prop: string) => () => {
    this.setState((state: State) => {
      return {[`${popoverID}${prop}`]: !state[`${popoverID}${prop}`]};
    });
  };

  handleSearchResultsDismiss = () => {
    this.setState(() => {
      return {
        searchActive: false,
        searchText: '',
      };
    });
  };

  handleSearchChange = (value) => {
    this.setState({searchText: value});
    if (value.length > 0) {
      this.setState({searchActive: true});
    } else {
      this.setState({searchActive: false});
    }
  };
}

🎩 checklist

@alex-page alex-page self-assigned this Oct 25, 2019
@github-actions
Copy link
Contributor

github-actions bot commented Oct 25, 2019

💦 Potential splash zone of changes introduced to src/**/*.tsx in this pull request:

Files modified5
Files potentially affected29

Details

All files potentially affected (total: 29)
📄 UNRELEASED.md (total: 0)

Files potentially affected (total: 0)

🎨 src/components/Popover/Popover.scss (total: 25)

Files potentially affected (total: 25)

🧩 src/components/PositionedOverlay/PositionedOverlay.tsx (total: 28)

Files potentially affected (total: 28)

🧩 src/components/PositionedOverlay/utilities/math.ts (total: 29)

Files potentially affected (total: 29)

🧩 src/components/TopBar/components/UserMenu/UserMenu.tsx (total: 1)

Files potentially affected (total: 1)


This comment automatically updates as changes are made to this pull request.
Feedback, troubleshooting: open an issue or reach out on Slack in #polaris-tooling.

@alex-page
Copy link
Member Author

alex-page commented Oct 25, 2019

Tophatting this fix in web locally. It currently looks like this, if we want it aligned with the activator on the right we need to set prefferedAlignment="right" for that component in web:
Screen Shot 2019-10-25 at 11 32 01 AM
Screen Shot 2019-10-25 at 11 32 10 AM

I can't replicate the issue @AndrewMusgrave had here #2231 (comment)

margin: $visible-portion-of-arrow spacing(tight) spacing();
margin: $visible-portion-of-arrow 0 0;
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure why the popover needed margin on the horizontal axis as it is positioned absolutely.

right:
preferredAlignment === 'right' ? horizontalPosition : undefined,
left: preferredAlignment === 'right' ? 0 : horizontalPosition,
left: horizontalPosition,
Copy link
Member Author

@alex-page alex-page Oct 25, 2019

Choose a reason for hiding this comment

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

Remove the right value and only positioning the popover with the left value. This is how it previously worked.

This simplifies the math when the popover overlaps the page. It now doesn't have to calculate a three right values it can just switch to a previously defined left value.

@@ -55,7 +55,6 @@ export function UserMenu({

return (
<Menu
preferredAlignment="right"
Copy link
Member Author

Choose a reason for hiding this comment

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

This should work with default middle, left or right alignment.

If the popover overlaps the right hand side of the page it should use a different left value.

@alex-page alex-page changed the title Fix calculation for center aligned popover [WIP] Fix calculation for center aligned popover Oct 25, 2019
@tmlayton
Copy link
Contributor

tmlayton commented Oct 25, 2019

Can we add a regression test for the previous bug? Also, do we have good test cases for the different positions? I’m just weary of this much code changing without any tests changing/being added that, while we might fix #2231 (comment), we could inadvertently introduce a new positioning bug.

@alex-page
Copy link
Member Author

Closing as #2587 shipped. Thanks Tim.

@alex-page alex-page closed this Jan 13, 2020
@alex-page alex-page deleted the popover-pagescroll branch January 13, 2020 18:48
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.

PositionOverlay incorrectly calculating the left value for right aligned components with scroll bars
3 participants