patternfly / pf-roadmap

This repo is used to track new feature requests for PatternFly as epics. It contains no code.
0 stars 0 forks source link

[ProgressStepper] - indicate progress between (long-running) steps #16

Closed garrett closed 1 year ago

garrett commented 2 years ago

Is this a new component or an extension of an existing one? Progress Stepper component

Describe the feature Display in-between progress for steps that take a while.

For the new Anaconda (OS installation for Fedora, RHEL, CentOS, Alma, Rocky, etc.) implementation using PatternFly, during a usability test, there wasn't enough granular feedback for the process. The stepper component was used, but each step could take some time between several seconds to several minutes.

Are there visuals for this feature? If applicable, please include examples for each state and for varying widths

Here's a quick idea that would blend the progress bar experience into the progress stepper, so the stepper works as it does currently, but in-between progress shows up as a progress-bar-like line. PatternFly 4 • Progress stepper

Source SVG: Progress stepper.svg

An additional idea is that we could even have a spinner on the current step. But that's probably overkill. :wink:

mcoker commented 2 years ago

cc @mcarrano @mmenestr

mcarrano commented 2 years ago

@garrett I can see the desire for this but is this a continuous process from start to end or does each step represent a stop along the way. i.e. to progress stop when I get to the end of a step and the user needs to intervene?

shirimordechay commented 2 years ago

You can use the current PF design with PF icons and combine the sub-steps for additional indications such as we use in OCM: image

garrett commented 2 years ago

Firstly, reminder: This mockup was made as a response to a user study. PatternFly currently does not solve the issue in the study, so the installer team will either have to do something custom or rely on PatternFly to address the need of having a widget that communicates a long running, multi-step progress.

@garrett I can see the desire for this but is this a continuous process from start to end or does each step represent a stop along the way. i.e. to progress stop when I get to the end of a step and the user needs to intervene?

It's for Anaconda. It installs Linux to a computer.

Just like any other operating system installer (just like when installing Windows, macOS), it can take a very long time (such as half an hour; sometimes more, sometimes less) to install, depending on several different factors (especially disk speed; but sometimes network speed too, when it's downloading packages from a remote site).

Each step is along the way where the installer is doing something different. There's (usually) no user intervention in this long-running process, but each step can take different amounts of time to complete. (Some might take a minute or less, whereas others might be the bulk of the time, such as 10 - 30 minutes or even longer.) There is always user intervention at the end of the process, when the installation has either succeeded or failed (in which it still would show which step it has failed). There might need to be user intervention in a mid-step too (example: such as if the network went down while it was downloading packages during a network install; one could try again or the process could fail, depending). The final screen shows the status (success/fail), along with the step in the stepper, and that the user needs to reboot the system.

Knowing each step is important, as someone who has installed Linux before will know that some steps are longer (installing especially). The steps of the installer are, basically:

  1. Partitioning the disk and formatting filesystems in partitions
    • some partitioning schemes take a while longer to set up (such as RAID) and/or when network storage is used (such as iSCSI)
  2. Installing software packages to the disk
    • installing software usually takes the longest amount of time, especially when installing from the network or installing from a slow device (USB stick or DVD-ROM) and/or installing to a slow device (hard disk versus SSD or NVMe)
  3. Configuring the system
  4. Finalizing installation by making it able to boot
    • in this step, Anaconda is building a special booting filesystem (which can take a little while) called an initrd (initial ram disk) with initial hardware support so that it can load the rest from disk; this can be slow
    • it then sets up the computer to boot through that using either a legacy method or UEFI; this is usually very quick and included in the same step

These are done in order and one step has to wait on the next.

If someone walks away form an installation to get coffee and they return and it's still installing software packages, they'll know it'll take a while longer. If it's finalizing installation, it might just be a minute or two before they have to tell the computer to reboot. If it fails in a step, it's important to know which step failed, as the resolution might be different (try again vs. replacing faulty hardware).

Right now, using the PF stepper component, it can sit there with absolutely no user feedback of progress, so the system looks like it has hung. (An indeterminate spinner doesn't help, either; one was used in the current PF-based Anaconda during the user study.)

Basically: Someone installing an OS on a computer needs feedback that it's still happening and that there is forward progression. The PF progress bar does not have steps (or even tickmarks) and the stepper does not show progress, and every single person in the user study commented on this problem... so this is why I'm suggesting this hybrid to solve the issue.

The normal component could even have the progression indicated in the line and circle part, to reinforce progress, even if it doesn't have partial lines between the items. (Especially because it's a little confusing where you are in the screenshots that @shirimordechay posted. But I guess the context of actually doing the process might help there?)


You can use the current PF design with PF icons and combine the sub-steps for additional indications such as we use in OCM:

That's not the same thing at all. There's no progress between long-running steps in these screenshots, which is what this issue is about. I know the icons can be changed; the icons are basically placeholders in my mockup above... I didn't want to distract from the actual issue and solution, so I just used the default incomplete, current, & complete icons.

mcarrano commented 2 years ago

@garrett thanks for posting this detailed explanation. Having done many OS installs myself over the years, I get what the problem is, and think your proposed solution is a reasonable one. Before putting this on our feature roadmap, I think this would be a good topic to present in an upcoming design share meeting just to see if others have also encountered this and if there are other potential solutions we are not considering here. Those meetings are every third Wednesday at 11am EDT. Is it possible for you to be available to present this at that time? If not, I can present this on your behalf for feedback on your proposal. Let me know.

I am also going to move this issue over to Design for further consideration.

garrett commented 2 years ago

I've implemented the mockup in basically 5 lines of CSS (mainly to set colors and a width for percentage), where the percentage is exposed as a number (representing a percentage), which React can modify.

Demo: https://codesandbox.io/s/unruffled-benji-cx657r?file=/progress-demo.scss

Screenshot:

stepper progress


Most of the content below are pulled directly from PatternFly's basic demo for the stepper, in JSX. We'd probably want to set the progress colors to the same color, like a progress color variable (unless we want past, active, and future to be the same). In the mockup, I merged the colors of past and current and leave future the default color. In the demo, I used green and red for past and current, respectively. I do not suggest using green and red in the actual implementation; they're for demonstration purposes only.

When progress isn't set, the width between steps is 0%, so it works by default to indicate past and current step, but not current progress.

Additionally, the ::after could have a CSS transition set for width so for smooth animation can be handled by CSS (therefore GPU accelerated), so when something jumps from 25% to 63% (or whatever), it won't just jump, but smoothly move.

Current progress is relative to the step, not the overall progress.

SCSS:

// Example CSS
.pf-m-success {
  // Demo colors
  --pf-c-progress-stepper__step-icon--BorderColor: green;
  --pf-c-progress-stepper__step-connector--before--BorderBottomColor: green;
}

.pf-m-current {
  // Another demo color (could be the same as the success colors)
  --pf-c-progress-stepper__step-icon--BorderColor: red;
}

.pf-c-progress-stepper__step:not(:last-of-type) > .pf-c-progress-stepper__step-connector::after {
  // Unique to ::after
  --pf-c-progress-stepper__step-connector--before--BorderBottomColor: red;
  width: calc(var(--pf-c-progress-stepper__step-percent) * 1%);

  // /////////////////////////////////////////////////////////////
  // Shared in common with ::before (from PF)
  position: absolute;
  top: var(--pf-c-progress-stepper__step-connector--before--Top);
  left: var(--pf-c-progress-stepper__step-connector--before--Left);
  height: var(--pf-c-progress-stepper__step-connector--before--Height);
  content: "";
  border-right: var(--pf-c-progress-stepper__step-connector--before--BorderRightWidth) solid var(--pf-c-progress-stepper__step-connector--before--BorderRightColor);
  border-bottom: var(--pf-c-progress-stepper__step-connector--before--BorderBottomWidth) solid var(--pf-c-progress-stepper__step-connector--before--BorderBottomColor);
  transform: var(--pf-c-progress-stepper__step-connector--before--Transform);
}

JSX:

import ReactDOM from "react-dom";
import "@patternfly/react-core/dist/styles/base.css";
import "./fonts.css";
import "./progress-demo.scss";

import React from "react";
import { ProgressStepper, ProgressStep } from "@patternfly/react-core";

const Basic = () => (
  <ProgressStepper>
    <ProgressStep
      variant="success"
      id="basic-step1"
      titleId="basic-step1-title"
      aria-label="completed step, step with success"
    >
      First step
    </ProgressStep>
    <ProgressStep
      variant="info"
      isCurrent
      id="basic-step2"
      titleId="basic-step2-title"
      aria-label="step with info"
      // Implemented here as a style, so I didn't have to change any PF JS;
      // ideally, it would be exposed as a property
      style={{ "--pf-c-progress-stepper__step-percent": 50 }}
    >
      Second step
    </ProgressStep>
    <ProgressStep
      variant="pending"
      id="basic-step3"
      titleId="basic-step3-title"
      aria-label="pending step"
    >
      Third step
    </ProgressStep>
  </ProgressStepper>
);

const rootElement = document.getElementById("root");
ReactDOM.render(<Basic />, rootElement);
garrett commented 2 years ago

I've made a modified second demo which has closer-to-ready SCSS (tying it to the widget), adding it as a pf-m- variant, uses success and current colors, and adds a transition:

https://codesandbox.io/s/staging-dream-6wrzt8?file=/progress-demo.scss

It adds a className to the topmost widget and changes the SCSS to:

.pf-c-progress-stepper.pf-m-show-progress {
  --pf-c-progress--SuccessColor: green;
  --pf-c-progress--CurrentColor: red;

  .pf-c-progress-stepper__step {
    &.pf-m-success {
      // Demo colors
      --pf-c-progress-stepper__step-icon--BorderColor: var(--pf-c-progress--SuccessColor);
      --pf-c-progress-stepper__step-connector--before--BorderRightColor: var(--pf-c-progress--SuccessColor);
      --pf-c-progress-stepper__step-connector--before--BorderBottomColor: var(--pf-c-progress--SuccessColor);
    }

    &.pf-m-current {
      // Another demo color (could be the same as the success colors)
      --pf-c-progress-stepper__step-icon--BorderColor: var(--pf-c-progress--CurrentColor);
    }  
  }

  .pf-c-progress-stepper__step:not(:last-of-type) > .pf-c-progress-stepper__step-connector::after {
    // Unique to ::after
    --pf-c-progress-stepper__step-connector--before--BorderBottomColor: var(--pf-c-progress--CurrentColor);
    --pf-c-progress-stepper__step-connector--before--BorderRightColor: var(--pf-c-progress--CurrentColor);
    width: calc(var(--pf-c-progress-stepper__step-percent, 0) * 1%);
    transition: width 500ms ease-out;

    // /////////////////////////////////////////////////////////////
    // Shared in common with ::before (from PF); PF CSS should be modified to share this with ::before
    position: absolute;
    top: var(--pf-c-progress-stepper__step-connector--before--Top);
    left: var(--pf-c-progress-stepper__step-connector--before--Left);
    height: var(--pf-c-progress-stepper__step-connector--before--Height);
    content: "";
    border-right: var(--pf-c-progress-stepper__step-connector--before--BorderRightWidth) solid var(--pf-c-progress-stepper__step-connector--before--BorderRightColor);
    border-bottom: var(--pf-c-progress-stepper__step-connector--before--BorderBottomWidth) solid var(--pf-c-progress-stepper__step-connector--before--BorderBottomColor);
    transform: var(--pf-c-progress-stepper__step-connector--before--Transform);
  }
}
lclay2 commented 2 years ago

@garrett , thanks for your brainstorming around this! In your proposed design above (afaik) the bar is calculating progress between steps 1-2, 2-3, rather than overall progress. If so it requires the availability of realtime, detailed intra-step progress (%, or other calculations) between all of the steps. That might impose a functional limitation.

To make the design solution more feasible if that data were not available, wdyt of using an indeterminate progress bar between steps instead? I don’t believe that PF has one of these bar types, so I have to make one up for the mockup that I posted. 
If this worked we would obviously need help from a visual designer. ;) Note: I believe that that if a particular milestone step (dot) is in progress, then it’s the preceding segment of bar that would be highlighted.

The solution that @shirimordechay is workable for sure. But 

I wanted to add this to the brainstorming effort, for ongoing design explorations.

indeterminate-step
lclay2 commented 2 years ago

cc @mkolman@redhat.com ^^

garrett commented 2 years ago

In your proposed design above (afaik) the bar is calculating progress between steps 1-2, 2-3, rather than overall progress.

No, I am actually talking about the current progress for the step, which is usually known during the install process (especially for the longer steps).

During the package installation step (the longest step in the overall installation), an example would be that the installer would know that it's on package 320 out of 2200 or something like that, so it could easily compute the progress of that specific step (in this example, 14.5%) during the package installation.

Some earlier or later steps, such as formatting partitions or setting up the bootloader, might be indeterminate, but finish within several seconds at the latest, whereas the longer steps might be up to several dozens of minutes (like somewhere between 5 to 45 minutes, depending on the speed of the installation media, the storage location, and network speed).

Having an indeterminate bar could be an enhancement after showing the general progress, although it might be misleading to label it blue in this case if it's not done (whereas, like a progress bar, the progress stepper indicating actual progress is using blue in the mockup above — and has green/red in the demo instead just for debugging purposes). But it's a good idea to add later, certainly! Thanks for suggesting it.

Please also note that I changed the outline of the circle around the icons too, to reinforce the progress.

lclay2 commented 2 years ago

@garrett - By "between" I meant Step x has been completed, now Step next is in progress. We might be talking about the same thing?

garrett commented 2 years ago

By "between" I meant Step x has been completed, now Step next is in progress. We might be talking about the same thing?

Yeah, in the demo I made, the current progress is in red. (I did use the green and red for demo purposes to show that they're not the same, but could be.) If we do know the progress and want to show that it's continuing, we could use animation like you're suggesting in the places where that's red.

I've revised the demo to make it use the same color for previous and current. I've also added an alternating line with a secondary color (which was initially transparent, but I made it use a similar color instead) and I've animated it. It's also using a pf-m-animated to opt-in to the animation (so the default non-animated version of the progress mockup would still work too).

https://codesandbox.io/s/modern-cdn-ebhubp?file=/progress-demo.scss

Screenshot:

image

(Visit the link above for the animation.)

lclay2 commented 2 years ago

Thanks @garrett , personal opinion, I really like the addition of the blue outline and coloring the completed segment. If coloring the step circle and segment line is already possible with the current component, maybe that's something to consider? Wdyt @mcarrano? I guess it would need a visual design/accessibility assessment. I'm not sure if the completed step-segments would be blue or green... Here's a quick mockup to illustrate a potential combo, minus the partially completed segment.

combo
garrett commented 2 years ago

If coloring the step circle and segment line is already possible with the current component, maybe that's something that might be feasible to consider in the short term?

It is! The demo I posted is some additional CSS that you can adapt to override the component a little if you'd like it without having to wait for an official implementation. (That's what the demo is doing, of course.)

Of course, an official implementation would be better. :wink:

I really like the addition of the blue outline and coloring the completed segment. My hesitation is the partial segments, at least for the installer use case that I'm working with.

Thanks!

The current segment also defaults to 0%, which means that a line isn't shown. The HTML+CSS is exactly the same. I left the green/red in the earlier demo (the most recent one that's not animated) to show that the finished and current colors can be separate too. (The animation has this in the CSS as well, but they're both set to a standard PF blue.)


By the way:

We do this kind of thing often enough with Cockpit, where we either find issues with PatternFly components or need to adjust them a little for ourselves. (Whenever possible, when we find actual bugs, we report them upstream and have a comment on our overrides. And then, when it's fixed in PatternFly and when we upgrade to the fixed version of PF, we drop our override. We do this for enhancements too, so we can use a custom version while we wait on a variant to be made.)

Our current list of overrides is @ https://github.com/cockpit-project/cockpit/blob/main/pkg/lib/patternfly/patternfly-4-overrides.scss (if you'd like to see it as an example). We even used to override PF3 to look like PF4 during our transition from PF3 to PF4 (hence this file specifically mentioning 4).

mcarrano commented 2 years ago

@garrett @lclay2 I like the addition of the blue outline and coloring of the completed segment, also, and would be in favor of making that enhancement. I'm not completely sold on the progress indicator, however. From the mockups you are showing, it's a bit unclear to me whether we have completed step 2 and are progressing to set three or if step 2 is still in progress. We don't currently have an indeterminate progress bar, and while we could add one, I wonder if it would make more sense to use the animated spinner to just indicate the step in progress.

garrett commented 2 years ago

From the mockups you are showing, it's a bit unclear to me whether we have completed step 2 and are progressing to set three or if step 2 is still in progress.

image

Step 2 is the current step, in progress. It's probably more obvious when using it interactively, as it would get to step 2; that would change, and then the progress would start crawling to the next step. Having different colors (the green/red above, but not green/red, but perhaps different shades of blue) could make this more obvious too, but I think the changing of the circle and the text is probably enough when this would be in action.

combo

Similarly, Title 2 is in the current step here. However, you don't know how far along you might be between Title 2 and Finalizing.

We don't currently have an indeterminate progress bar, and while we could add one, I wonder if it would make more sense to use the animated spinner to just indicate the step in progress.

Yeah, I didn't include an animated bar (it's determinate still, not indeterminate) earlier as I assumed there was already a spinner within Anaconda at the moment. It's redundant to have both. However, with a moving and animated progress bar, it could make sense to show that the computer hasn't frozen (which is really the point of all indeterminate progress indicators, including spinners) in the same place that indicates progress.

I know Mac OS X and macOS have famously had animated progress bars for this reason.

Indeterminate bar: image

Animated bar: image

Animated, in context: image

image

Windows has done this too over the years, for the same reason (to show that something's still happening even if the bar isn't currently moving forward at a detectable pace):

image

image

But Windows 10 and up sometimes gets a bit complex :wink::

image

image

Anyway, adding the ability to have an animated progress bar (instead of a spinner + progress bar) makes it super-simple to re-use the same animation (perhaps with color customization) for the indeterminate progress bar too. (It's just set to 100%, usually with different colors.)

mcarrano commented 1 year ago

Moving this here for further discussion: https://github.com/orgs/patternfly/discussions/categories/feature-requests