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

Postponing the loadingspinners and where to implement the design system #118

Open
erikarenhill opened this issue Jun 30, 2020 · 5 comments
Assignees

Comments

@erikarenhill
Copy link
Contributor

erikarenhill commented Jun 30, 2020

Me and @HendrikThePendric came into an issue while building on the WHO DQ Tool, where we begun to discuss how and where to implement postponing of displaying a loading spinner to avoid having flickering/blinking loadingspinners in our apps. I should also mention that this came up for the specific usage of app-service-datastore where we can pass in a custom loadingComponent to the provider as a prop (https://github.com/dhis2/app-service-datastore/blob/master/src/DataStoreProvider.tsx)

Then it took fire in a slack-thread in #ui channel: https://dhis2.slack.com/archives/CBM8LNEQM/p1593440347005200 so we're creating a note for it instead.

Talking to @cooper-joe we already have a guideline to only display a loader if something takes more than 700ms (https://github.com/dhis2/design-system/blob/master/atoms/loading.md#usage) but this is merely how it should behave against the user.

How long the delay should be, is left for another discussion, so lets instead discuss where and how to support this design guideline.

Basically we came to the conclusion that we have 5 options, where I think most of us are in favor for one of the last 2

  • Implement a timer/effect in the app where to use the loading
  • Implement an css animation on the loader in the app
  • Implement a timer/effect in the library app-service-datastore that takes care of this no matter which loadingComponent you pass in
  • Implement a timer/effect on the CircularLoader component in UI-library to enforce this guideline automatically across all apps using our components and no matter where.
  • Same as previous but using css-animations

I think(?) from the Slack-discussion that most of us were in favor of adding this to the UI- library, so either 4 or 5 would be the choice for us.

And lastly, should we implement it in the already existing CircularLoader or do we need yet another component such as a PageLoader?

@Mohammer5
Copy link
Contributor

I agree with putting the solution into the UI library. I think the right approach here is to add a component to widgets because this is dhis2 specific behavior while the loading spinner component itself it independent of that so it can be used in other contexts as well without having too many options, which would make the component more complicated

@HendrikThePendric
Copy link
Contributor

I agree with @Mohammer5 and also have some suggestions on the implementation:

  • Add one or multiple widgets (i.e. PageLoader and ComponentLoader)
  • Implement delay via CSS: use a keyframe animation to make it appear and use the animation-delay CSS property to delay the appearance.
  • Add props translucent (bool) to toggle the translucent background.
  • Add prop delay (number, default 700) to specify the delay in ms.

@Mohammer5
Copy link
Contributor

An alternative would be skeleton screen, like facebook does it in the messenger app or so. It's more work on the app side, but it looks neat and resembles what it'll look like later anyways

@HendrikThePendric
Copy link
Contributor

Oh that's a nice idea too. Perhaps that could be integrated to the layouts?

@HendrikThePendric
Copy link
Contributor

FYI, because I hadn't worked with styled-jsx and keyframes before, I was curious if my proposed solution would be possible. It turned out it was. The code below works fine:

const PageLoader = ({
    className,
    dataTest,
    delay,
    large,
    small,
    translucent,
}) => {
    const appearStyle = resolve`
        @keyframes appear {
            0% {
                opacity: 0;
            }
            100% {
                opacity: 1;
            }
        }
        div {
            animation-name: appear;
            animation-duration: 150ms;
            animation-fill-mode: forwards;
            animation-delay ${delay}ms;
            opacity: 0;
        }
    `
    return (
        <Layer
            className={cx(className, appearStyle.className)}
            dataTest={dataTest}
            level={layers.alert}
            translucent={translucent}
        >
            <CenteredContent>
                <CircularLoader large={large} small={small} />
            </CenteredContent>
            {appearStyle.styles}
        </Layer>
    )
}

I'd prefer this CSS based approach over a timeout.

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

No branches or pull requests

7 participants