Skip to content

Conversation

chloerice
Copy link
Member

@chloerice chloerice commented May 24, 2019

WHY are these changes introduced?

This PR is one of two that will enable the improvement of transitions from skeleton loading states to empty states by adding support for use of the empty state component in a content context. For example, within a Card or ResourceList**.

WHAT is this pull request doing?

Adds content context consumer to EmptyState

Empty state in a card (small screen on right):

Screen Shot 2019-10-01 at 7 39 01 PM

**Note: I'm adding empty state handling to ResourceList in a separate PR.

How to 🎩

Click to view collapsed tophatting instructions

🖥 Local development instructions
🗒 General tophatting guidelines
📄 Changelog guidelines

View the "Empty state in content context" example in the Chroma deployment. The latest deployment can be found by clicking the "Details" link in the ci/chroma check line item of the PR checks below.

I recommend reviewing the code with whitespace changes removed from the diff so it's easier to see what actually changed (since I converted the component from a class to a function, most of the code in EmptyState.tsx shifted left one tab).

Screen Shot 2019-09-17 at 7 27 02 PM

or

Copy-paste this code in playground/Playground.tsx:
import React, {useState, useCallback} from 'react';
import {Page, Layout, EmptyState, Card} from '../src';

export function Playground() {
  const [contentContext, setContentContext] = useState(true);
  const toggleContentContext = useCallback(
    () => setContentContext((contentContext) => !contentContext),
    [],
  );

  const emptyStateMarkup = contentContext ? (
    <Card sectioned>
      <EmptyState
        heading="Upload a file to get started"
        action={{content: 'Upload files'}}
        image="https://user-images.githubusercontent.com/18447883/59945230-fa4be980-9434-11e9-9106-a373f0efbe08.png"
      >
        <p>
          You can use the Files section to upload images, videos, and other
          documents
        </p>
      </EmptyState>
    </Card>
  ) : (
    <EmptyState
      heading="Manage your inventory transfers"
      action={{content: 'Add transfer'}}
      secondaryAction={{content: 'Learn more', url: 'https://help.shopify.com'}}
      image="https://cdn.shopify.com/s/files/1/0757/9955/files/empty-state.svg"
    >
      <p>Track and receive your incoming inventory from suppliers.</p>
    </EmptyState>
  );

  const markup = contentContext ? (
    <Card>{emptyStateMarkup}</Card>
  ) : (
    emptyStateMarkup
  );

  const secondaryLayoutSection = contentContext ? (
    <Layout.Section secondary>{markup}</Layout.Section>
  ) : null;

  const title = contentContext
    ? 'Empty state content context'
    : 'Empty state standard';

  return (
    <Page
      title={title}
      primaryAction={{
        content: 'Toggle content context',
        onAction: toggleContentContext,
      }}
    >
      <Layout>
        <Layout.Section>{markup}</Layout.Section>
        {secondaryLayoutSection}
      </Layout>
    </Page>
  );
}

How to test your use case in a content context 👩‍🔬

Click to view collapsed instructions for testing your use case

Add a comment to this PR with an explanation of your use case with your empty state image attached/embedded in the comment.

For example, the image attached below is here so the playground code collapsed above will work for anyone locally. This is because the EmptyState image prop has the url of the attachment set as its string value.

You can copy the link to your image attachment by right clicking on the image and selecting "Copy image address" from the right click menu.

File-Upload-Spot


PR checklist

@Ipkhchan
Copy link
Contributor

Uploading image to test with our use case on POS Channel Staff!

spot-add-POS-staff

@Ipkhchan
Copy link
Contributor

Our use case is within a ResourceList that displays POS staff members. If a shop does not have POS staff members, we want to show an empty state within the resource list that prompts them to add staff rather than just the default resource list empty state that just indicates that the shop has no staff.
Our workaround right now is to conditionally render the empty state vs. the resource list based on if there are staff. It would be nice to pass in an empty state to the resource list instead. Great that know someone's working on this!

Below is the design for the empty state provided by @pauyeung.

Screen Shot 2019-07-17 at 10 37 32 AM

Below is the result of tossing our content (img and text) into the modified EmptyState implemented by this PR.

Screen Shot 2019-07-17 at 10 24 51 AM

The EmptyState currently requires there to be a button in the content, whereas our design does not have a button within the empty state because our pageAction in the top right provides the call-to-action.

@pauyeung perhaps you can comment on this and how this looks?

@pauyeung
Copy link

@Ipkhchan @chloerice - I modelled my design off of this example in the Vault update. If buttons are required, does that mean there should be double parked primary action in both the page actions and resource list (Ex. Customers, Products)? I think it could be heavy handed
f9706163a5

@chloerice
Copy link
Member Author

Thanks for sharing your use cases @Ipkhchan @pauyeung!

The EmptyState currently requires there to be a button in the content, whereas our design does not have a button within the empty state because our pageAction in the top right provides the call-to-action.

I modelled my design off of this example in the Vault update. If buttons are required, does that mean there should be double parked primary action in both the page actions and resource list (Ex. Customers, Products)? I think it could be heavy handed

Having an action in the EmptyState is no longer required 🎉. Your page level action is enough in this use case to give merchants a next step 👍.

@chloerice
Copy link
Member Author

Work on this functionality will be picked up again at the next Frideations.

@chloerice chloerice force-pushed the empty-state-content-context branch 2 times, most recently from 799cf7b to 9f7c1c4 Compare September 17, 2019 22:41
@chloerice chloerice changed the title [WIP][EmptyState] Add content context variant [EmptyState] Add content context variant Sep 17, 2019
@chloerice chloerice force-pushed the empty-state-content-context branch 4 times, most recently from cc7ed90 to 3b65fbc Compare September 18, 2019 14:57
@@ -0,0 +1 @@
export {default as FileUploadSpot} from './File-Upload-Spot.png';
Copy link
Contributor

Choose a reason for hiding this comment

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

🔥 ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for catching, meant to 🔥 this! That was left over from when I'd saved the empty state image locally before figuring out I could reference images attached to GitHub comments 👍.

<TextContainer>{footerContent}</TextContainer>
</div>
) : null;
const headingSize = withinContentContainer ? 'small' : 'medium';
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe moving the DisplayText Size type to src/types to use here, there and in tests would be better.

Copy link
Member Author

Choose a reason for hiding this comment

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

To clarify, you mean I should change DisplayText.size to use an enum instead of a union type so that I can use that there and here instead?

Copy link
Member Author

@chloerice chloerice Sep 18, 2019

Choose a reason for hiding this comment

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

^ Just pushed up that change, but it will be a breaking change, at least for anyone consuming @shopify/polaris in a TypeScript project (web etc). I'm not sure it's worth that, @dleroux @BPScott let me know what you think.

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess you are right, it's not worth the breaking change. Didn't realize it would be. We could just share the current type but not sure there's much value.

width: $detail-width;
.withinContentContainer {
.Section {
position: unset;
Copy link
Contributor

Choose a reason for hiding this comment

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

do you need unset?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, because the position is set to relative, when not in a content context, the position has to be unset or it still has a relative position which pushes it to the right a noticeable amount.

Copy link
Contributor

@dleroux dleroux left a comment

Choose a reason for hiding this comment

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

Looks good except for the image that is accidentally being committed and left a comment on the size type.

footerContent,
}: EmptyStateProps) {
return (
<WithinContentContext.Consumer>
Copy link
Member

Choose a reason for hiding this comment

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

As you're in a functional component you can use hooks instead of the render prop function

const withinContentContainer = useContext(WithinContentContext);

/* stuff using withinContentContainer */

instead of

return (
  <WithinContentContext.Consumer>
    {(withinContentContainer) => {
      /* stuff using withinContentContainer */
    }}
  </WithinContentContext.Consumer>
);

Copy link
Member Author

Choose a reason for hiding this comment

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

Gotcha, thanks!

@chloerice chloerice force-pushed the empty-state-content-context branch 2 times, most recently from f966084 to b63293f Compare September 18, 2019 21:32
@dleroux dleroux self-requested a review September 19, 2019 12:13
Copy link
Contributor

@sarahill sarahill left a comment

Choose a reason for hiding this comment

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

This is looking good! On some mobile devices, the horizontal spacing feels tight. Can we add some left/right padding?

Before After
Screen Shot 2019-09-19 at 9 55 06 AM Screen Shot 2019-09-19 at 9 55 27 AM

@chloerice
Copy link
Member Author

chloerice commented Sep 19, 2019

This is looking good! On some mobile devices, the horizontal spacing feels tight. Can we add some left/right padding?

Thanks @sarahill! I'm hesitant to add spacing around the EmptyState component directly, even just for the "in content context" variant. We generally handle the spacing of elements within the component, and leave it to the consumer to handle any spacing needed between and around components (by using structural Polaris components or custom styled elements as parent containers).

Nesting the EmptyState inside of a Card.Section takes care of the spacing in the case of a Card being the parent container. I'll update the example and playground code!

@chloerice chloerice dismissed dleroux’s stale review September 19, 2019 19:11

(Discussed and agreed that requested change would be breaking)

@chloerice chloerice force-pushed the empty-state-content-context branch 2 times, most recently from 0a8e15f to 332db66 Compare September 19, 2019 21:07
Copy link
Contributor

@sarahill sarahill left a comment

Choose a reason for hiding this comment

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

@chloerice chloerice force-pushed the empty-state-content-context branch from 332db66 to 3030987 Compare October 1, 2019 23:38
@github-actions
Copy link
Contributor

github-actions bot commented Oct 1, 2019

Results

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

Files modified5
Files potentially affected1

Details

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

Files potentially affected (total: 0)

🎨 src/components/EmptyState/EmptyState.scss (total: 1)

Files potentially affected (total: 1)

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

Files potentially affected (total: 0)

src/components/EmptyState/README.md (total: 0)

Files potentially affected (total: 0)

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

Files potentially affected (total: 0)


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.

let imgSrc =
'https://cdn.shopify.com/s/files/1/0757/9955/files/empty-state.svg';

describe('primaryAction', () => {
Copy link
Member Author

Choose a reason for hiding this comment

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

(There is no primaryAction prop, it's just action)

@chloerice chloerice force-pushed the empty-state-content-context branch 2 times, most recently from f8d7d7a to bda26c9 Compare October 1, 2019 23:47
@chloerice chloerice force-pushed the empty-state-content-context branch from bda26c9 to 9b0ad21 Compare November 26, 2019 20:17
@chloerice chloerice merged commit 9820e3a into master Nov 26, 2019
@dleroux dleroux temporarily deployed to production December 4, 2019 14:42 Inactive
@chloerice chloerice deleted the empty-state-content-context branch December 17, 2019 20:33
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.

6 participants