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

Sidebar lags when you open it on mobile. Why? Seems to happen on calculator/exchange-info pages. #6

Open
mcscrad opened this issue Feb 14, 2021 · 0 comments
Labels
bug Something isn't working

Comments

@mcscrad
Copy link
Collaborator

mcscrad commented Feb 14, 2021

chrome on android has a weird delay when opening the navigation menu by clicking the hamburger. It also lags when I click the checkbox too. THis does not happen on firefox windows 10 or iphone chrome browser. if I comment out the textfield inside the FormLayout, the lag goes away when clicking checkbox OR the navigation menu hamburger.

reproducible on codepen with a nexus 5x emulator using chrome with the following code:

https://codesandbox.io/s/polaris-lag-bug-nbxre

app.js

import React, { useCallback, useRef, useState } from "react";
import {
  AppProvider,
  Avatar,
  ActionList,
  Card,
  Checkbox,
  ResourceList,
  TextField,
  TextContainer,
  ContextualSaveBar,
  FormLayout,
  Modal,
  Frame,
  Layout,
  Loading,
  Navigation,
  Page,
  ResourceItem,
  SkeletonBodyText,
  SkeletonDisplayText,
  SkeletonPage,
  Toast,
  TopBar
} from "@shopify/polaris";
import {
  ArrowLeftMinor,
  ConversationMinor,
  HomeMajor,
  OrdersMajor
} from "@shopify/polaris-icons";

export default function FrameExample() {
  const defaultState = useRef({
    emailFieldValue: "[email protected]",
    nameFieldValue: "Jaded Pixel"
  });
  const skipToContentRef = useRef(null);

  const [toastActive, setToastActive] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const [isDirty, setIsDirty] = useState(false);
  const [searchActive, setSearchActive] = useState(false);
  const [searchValue, setSearchValue] = useState("");
  const [userMenuActive, setUserMenuActive] = useState(false);
  const [mobileNavigationActive, setMobileNavigationActive] = useState(false);
  const [modalActive, setModalActive] = useState(false);
  const [nameFieldValue, setNameFieldValue] = useState(
    defaultState.current.nameFieldValue
  );
  const [emailFieldValue, setEmailFieldValue] = useState(
    defaultState.current.emailFieldValue
  );
  const [storeName, setStoreName] = useState(
    defaultState.current.nameFieldValue
  );
  const [supportSubject, setSupportSubject] = useState("");
  const [supportMessage, setSupportMessage] = useState("");

  const handleSubjectChange = useCallback(
    (value) => setSupportSubject(value),
    []
  );
  const handleMessageChange = useCallback(
    (value) => setSupportMessage(value),
    []
  );
  const handleDiscard = useCallback(() => {
    setEmailFieldValue(defaultState.current.emailFieldValue);
    setNameFieldValue(defaultState.current.nameFieldValue);
    setIsDirty(false);
  }, []);
  const handleSave = useCallback(() => {
    defaultState.current.nameFieldValue = nameFieldValue;
    defaultState.current.emailFieldValue = emailFieldValue;

    setIsDirty(false);
    setToastActive(true);
    setStoreName(defaultState.current.nameFieldValue);
  }, [emailFieldValue, nameFieldValue]);
  const handleNameFieldChange = useCallback((value) => {
    setNameFieldValue(value);
    value && setIsDirty(true);
  }, []);
  const handleEmailFieldChange = useCallback((value) => {
    setEmailFieldValue(value);
    value && setIsDirty(true);
  }, []);
  const handleSearchResultsDismiss = useCallback(() => {
    setSearchActive(false);
    setSearchValue("");
  }, []);
  const handleSearchFieldChange = useCallback((value) => {
    setSearchValue(value);
    setSearchActive(value.length > 0);
  }, []);
  const toggleToastActive = useCallback(
    () => setToastActive((toastActive) => !toastActive),
    []
  );
  const toggleUserMenuActive = useCallback(
    () => setUserMenuActive((userMenuActive) => !userMenuActive),
    []
  );
  const toggleMobileNavigationActive = useCallback(
    () =>
      setMobileNavigationActive(
        (mobileNavigationActive) => !mobileNavigationActive
      ),
    []
  );
  const toggleIsLoading = useCallback(
    () => setIsLoading((isLoading) => !isLoading),
    []
  );
  const toggleModalActive = useCallback(
    () => setModalActive((modalActive) => !modalActive),
    []
  );

  const toastMarkup = toastActive ? (
    <Toast onDismiss={toggleToastActive} content="Changes saved" />
  ) : null;

  const userMenuActions = [
    {
      items: [{ content: "Community forums" }]
    }
  ];

  const contextualSaveBarMarkup = isDirty ? (
    <ContextualSaveBar
      message="Unsaved changes"
      saveAction={{
        onAction: handleSave
      }}
      discardAction={{
        onAction: handleDiscard
      }}
    />
  ) : null;

  const userMenuMarkup = (
    <TopBar.UserMenu
      actions={userMenuActions}
      name="Dharma"
      detail={storeName}
      initials="D"
      open={userMenuActive}
      onToggle={toggleUserMenuActive}
    />
  );

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

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

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

  const navigationMarkup = (
    <Navigation location="/">
      <Navigation.Section
        items={[
          {
            label: "Back to Shopify",
            icon: ArrowLeftMinor
          }
        ]}
      />
      <Navigation.Section
        separator
        title="Jaded Pixel App"
        items={[
          {
            label: "Dashboard",
            icon: HomeMajor,
            onClick: toggleIsLoading
          },
          {
            label: "Jaded Pixel Orders",
            icon: OrdersMajor,
            onClick: toggleIsLoading
          }
        ]}
        action={{
          icon: ConversationMinor,
          accessibilityLabel: "Contact support",
          onClick: toggleModalActive
        }}
      />
    </Navigation>
  );

  const loadingMarkup = isLoading ? <Loading /> : null;

  const skipToContentTarget = (
    <a id="SkipToContentTarget" ref={skipToContentRef} tabIndex={-1} />
  );

  const now = new Date();
  const [checked, setChecked] = useState(true);
  const [amountInput, setAmountInput] = useState("1000");
  const handleAmountChange = useCallback(
    (newAmount) => setAmountInput(newAmount),
    []
  );
  const [cryptocurrency, setCryptocurrency] = useState("");
  const [methodType, setMethodType] = useState("");
  const amount = parseInt(amountInput);
  const methodLabel = checked ? "Deposit" : "Withdrawal";

  let items = [];

  const actualPageMarkup = (
    <Page
      primaryAction={
        <Checkbox
          label="Sell / Buy"
          checked={checked}
          onChange={() => setChecked(!checked)}
        />
      }
    >
      <FormLayout>
        <FormLayout.Group>
          <TextField
            type="number"
            label="Amount to buy/sell"
            value={amountInput}
            onChange={handleAmountChange}
            min="10"
            step="10"
          />
        </FormLayout.Group>
      </FormLayout>
      <Layout sectioned>
        <Layout.AnnotatedSection title="" description="">
          <Card>
            <ResourceList
              resourceName={{ singular: "exchange", plural: "exchanges" }}
              items={items}
              renderItem={(item) => {
                const { fee, method, name, url } = item;
                // const { id, url, name, location, latestOrderUrl } = item;
                // const media = <Avatar customer size="medium" name={name} />;
                // const shortcutActions = latestOrderUrl
                //   ? [
                //       {
                //         content: "View latest order",
                //         accessibilityLabel: `View ${name}’s latest order`,
                //         url: latestOrderUrl,
                //       },
                //     ]
                //   : null;
                // const name = exchangeInfo.name;

                return (
                  <ResourceItem
                    id={name}
                    url={url}
                    // media={media}
                    // accessibilityLabel={`View details for ${name}`}
                    // shortcutActions={shortcutActions}
                    // persistActions
                  >
                    <div style={{ display: "flex", textAlign: "center" }}>
                      <h3
                        style={{ flex: "0 1 33%", textTransform: "capitalize" }}
                      >
                        <TextStyle variation="strong">{name}</TextStyle>
                      </h3>
                      <div style={{ flex: "0 1 33%" }}>{method}</div>
                      <div style={{ flex: "0 1 33%" }}>${fee}</div>
                    </div>
                  </ResourceItem>
                );
              }}
            />
          </Card>
        </Layout.AnnotatedSection>
      </Layout>
    </Page>
  );

  const loadingPageMarkup = (
    <SkeletonPage>
      <Layout>
        <Layout.Section>
          <Card sectioned>
            <TextContainer>
              <SkeletonDisplayText size="small" />
              <SkeletonBodyText lines={9} />
            </TextContainer>
          </Card>
        </Layout.Section>
      </Layout>
    </SkeletonPage>
  );

  const pageMarkup = isLoading ? loadingPageMarkup : actualPageMarkup;

  const modalMarkup = (
    <Modal
      open={modalActive}
      onClose={toggleModalActive}
      title="Contact support"
      primaryAction={{
        content: "Send",
        onAction: toggleModalActive
      }}
    >
      <Modal.Section>
        <FormLayout>
          <TextField
            label="Subject"
            value={supportSubject}
            onChange={handleSubjectChange}
          />
          <TextField
            label="Message"
            value={supportMessage}
            onChange={handleMessageChange}
            multiline
          />
        </FormLayout>
      </Modal.Section>
    </Modal>
  );

  const theme = {
    logo: {
      width: 124,
      topBarSource:
        "https://cdn.shopify.com/s/files/1/0446/6937/files/jaded-pixel-logo-color.svg?6215648040070010999",
      contextualSaveBarSource:
        "https://cdn.shopify.com/s/files/1/0446/6937/files/jaded-pixel-logo-gray.svg?6215648040070010999",
      url: "http://jadedpixel.com",
      accessibilityLabel: "Jaded Pixel"
    }
  };

  return (
    <div style={{ height: "500px" }}>
      <AppProvider
        theme={theme}
        i18n={{
          Polaris: {
            Avatar: {
              label: "Avatar",
              labelWithInitials: "Avatar with initials {initials}"
            },
            ContextualSaveBar: {
              save: "Save",
              discard: "Discard"
            },
            TextField: {
              characterCount: "{count} characters"
            },
            TopBar: {
              toggleMenuLabel: "Toggle menu",

              SearchField: {
                clearButtonLabel: "Clear",
                search: "Search"
              }
            },
            Modal: {
              iFrameTitle: "body markup"
            },
            Frame: {
              skipToContent: "Skip to content",
              Navigation: {
                closeMobileNavigationLabel: "Close navigation"
              }
            }
          }
        }}
      >
        <Frame
          topBar={topBarMarkup}
          navigation={navigationMarkup}
          showMobileNavigation={mobileNavigationActive}
          onNavigationDismiss={toggleMobileNavigationActive}
          skipToContentTarget={skipToContentRef.current}
        >
          {pageMarkup}
        </Frame>
      </AppProvider>
    </div>
  );
}

index.html

<div id="root"></div>

index.js

import React from "react";
import ReactDOM from "react-dom";


import App from "./App";
import "@shopify/polaris/dist/styles.css";

ReactDOM.render(<App />, document.getElementById("root"));

package.json

{
  "dependencies": {
    "react-dom": "latest",
    "react": "latest",
    "@shopify/polaris-icons": "latest",
    "@shopify/polaris": "latest"
  }
}
@mcscrad mcscrad added the bug Something isn't working label Feb 14, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant