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

[IndexTable] Fix UX / jank when resizing #4033

Merged
merged 10 commits into from
Mar 15, 2021

Conversation

lhoffbeck
Copy link
Contributor

WHY are these changes introduced?

Resolves #3991.

The IndexTable currently has some UX, jank, and performance issues when resizing. This PR aims to address a lot of these by making UX and performance fixes to make this resize buttery-smooth.

WHAT is this pull request doing?

1) Fixed sticky header alignment issues
All the sticky headers are sized on load and not resized when the window width changes.

👀 before (watch the Location column) 👀

2.mp4

👀 after (watch the Location column) 👀

6.mp4

2) Fixed first (non-sticky) column alignment issues when resizing browser
First column header doesn't resize when window does.

👀 before 👀

3.mp4

👀 after 👀

7.mp4

**3) Fixed first sticky header misalignment **
First column is out of place when you load the page and scroll down

👀 before (watch the Name column) 👀

1.mp4

👀 after 👀

8.mp4

**4) Fix flickering scrollbar **
Scrollbar flickers when resizing window large->small. The issue here was that the width of .ScrollBarContent was set by --p-scroll-bar-content-width, so when you resize smaller unless --p-scroll-bar-content-width is set on a bare-metal resize event (i.e. not by a throttled/debounced function), the scrollbar will be larger than the content when you size the window down and will flicker. Fixed this by setting this width to 0 when resizing and only actually setting --p-scroll-bar-content-width once resizing completes.

👀 before 👀

4.mp4

👀 after 👀

9.mp4

**5) Fix sticky header not resizing smoothly **
Watch the upper right corner of the sticky header. As you resize, the width of the header goes out of shape with the rest of the card, this happens because the debounce period is at a slower framerate than it should be. Fix was to update to 60FPS (and converted to use throttle instead of debounce with maxWait for clarity).

👀 before (watch upper right corner of sticky header) 👀

5.mp4

👀 after 👀

10.mp4

**6) Performance stuff **

  • converted the resize handler to use useCallback instead of useMemo, we really don't need to memoize anything for this
  • cache the column header / sticky column header DOM lookups instead of performing them on every resize event
  • increased the debounce period on the scrollbar resize event so it fires ~600% less frequently

How to 🎩

🖥 Local development instructions
🗒 General tophatting guidelines
📄 Changelog guidelines

Copy-paste this code in playground/Playground.tsx:

import React from 'react';

import {Card, IndexTable, Page, TextStyle, useIndexResourceState} from '../src';

export function Playground() {
  return (
    <Page title="Playground">
      {/* Add the code you want to test in here */}

      <div style={{ marginBottom: 1000 }}>
        <SimpleIndexTableExample />
      </div>
    </Page>
  );
}


function SimpleIndexTableExample() {
  const customers = [
    {
      id: '3411',
      url: 'customers/341',
      name: 'Mae Jemison',
      location: 'Decatur, USA',
      orders: 20,
      amountSpent: '$2,400',
    },
    {
      id: '2561',
      url: 'customers/256',
      name: 'Ellen Ochoa',
      location: 'Los Angeles, USA',
      orders: 30,
      amountSpent: '$140',
    },
  ];
  const resourceName = {
    singular: 'customer',
    plural: 'customers',
  };

  const {
    selectedResources,
    allResourcesSelected,
    handleSelectionChange,
  } = useIndexResourceState(customers);

  const rowMarkup = customers.map(
    ({id, name, location, orders, amountSpent}, index) => (
      <IndexTable.Row
        id={id}
        key={id}
        selected={selectedResources.includes(id)}
        position={index}
      >
        <IndexTable.Cell>
          <TextStyle variation="strong">{name}</TextStyle>
        </IndexTable.Cell>
        <IndexTable.Cell>{location}</IndexTable.Cell>
        <IndexTable.Cell>{orders}</IndexTable.Cell>
        <IndexTable.Cell>{amountSpent}</IndexTable.Cell>
      </IndexTable.Row>
    ),
  );

  return (
    <Card>
      <IndexTable
        resourceName={resourceName}
        itemCount={customers.length}
        selectedItemsCount={
          allResourcesSelected ? 'All' : selectedResources.length
        }
        onSelectionChange={handleSelectionChange}
        headings={[
          {title: 'Name'},
          {title: 'Location'},
          {title: 'Order count'},
          {title: 'Amount spent'},
        ]}
      >
        {rowMarkup}
      </IndexTable>
    </Card>
  );
}


🎩 checklist

  • Tested on mobile
  • Tested on multiple browsers
  • Tested for accessibility
  • Updated the component's README.md with documentation changes
  • Tophatted documentation changes in the style guide
  • For visual design changes, pinged one of @ HYPD, @ mirualves, @ sarahill, or @ ry5n to update the Polaris UI kit

@lhoffbeck
Copy link
Contributor Author

NOTE that I didn't add any test cases for this--this behavior hinges on being able to grab dimensions from the dom, which isn't possible with our test setup (afaik).

@lhoffbeck lhoffbeck requested review from a team, maxariss and ChrisMLee and removed request for ChrisMLee March 4, 2021 15:49
@github-actions
Copy link
Contributor

github-actions bot commented Mar 4, 2021

🔴 This pull request modifies 7 files and might impact 78 other files. Because this is a larger than average splash zone for a change, remember to tophat areas that could be affected.

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

Files potentially affected (total: 0)

🧩 src/components/IndexTable/IndexTable.tsx (total: 0)

Files potentially affected (total: 0)

🧩 src/components/IndexTable/tests/IndexTable.test.tsx (total: 0)

Files potentially affected (total: 0)

🧩 src/components/IndexTable/utilities/index.ts (total: 1)

Files potentially affected (total: 1)

🧩 src/components/IndexTable/utilities/tests/utilities.test.ts (total: 0)

Files potentially affected (total: 0)

🧩 src/components/IndexTable/utilities/utilities.ts (total: 2)

Files potentially affected (total: 2)

🧩 src/utilities/sticky-manager/sticky-manager.ts (total: 77)

Files potentially affected (total: 77)

src/components/IndexTable/IndexTable.tsx Outdated Show resolved Hide resolved
src/components/IndexTable/IndexTable.tsx Outdated Show resolved Hide resolved
src/components/IndexTable/IndexTable.tsx Outdated Show resolved Hide resolved
@alex-page alex-page requested a review from AndrewMusgrave March 9, 2021 15:31
Copy link
Member

@AndrewMusgrave AndrewMusgrave left a comment

Choose a reason for hiding this comment

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

Love how smooth this is looking 😍

UNRELEASED.md Outdated Show resolved Hide resolved
src/utilities/sticky-manager/sticky-manager.ts Outdated Show resolved Hide resolved
src/components/IndexTable/IndexTable.tsx Outdated Show resolved Hide resolved
src/components/IndexTable/IndexTable.tsx Show resolved Hide resolved
src/components/IndexTable/IndexTable.tsx Outdated Show resolved Hide resolved
src/components/IndexTable/IndexTable.tsx Outdated Show resolved Hide resolved
src/components/IndexTable/IndexTable.tsx Outdated Show resolved Hide resolved
Copy link
Member

@AndrewMusgrave AndrewMusgrave left a comment

Choose a reason for hiding this comment

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

LGTM! ✅

@@ -16,6 +18,11 @@ import {ScrollContainer} from '../components';
import {SelectionType} from '../../../utilities/index-provider';
import {AfterInitialMount} from '../../AfterInitialMount';

jest.mock('../utilities', () => ({
...(jest.requireActual('../utilities') as any),
Copy link
Member

Choose a reason for hiding this comment

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

Why was casting needed here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

bad copy paste 🙈

@AndrewMusgrave AndrewMusgrave requested a review from kmdavis March 15, 2021 15:30
@lhoffbeck lhoffbeck merged commit 58a8a32 into main Mar 15, 2021
@lhoffbeck lhoffbeck deleted the lh/index-table-sticky-header-alignment-and-jank branch March 15, 2021 16:40
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.

[IndexTable] Sticky column headers are misaligned
3 participants