-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
feat(ProgressIndicator): add animation #9340
feat(ProgressIndicator): add animation #9340
Conversation
✔️ Deploy Preview for carbon-react-next ready! 🔨 Explore the source changes: 483982a 🔍 Inspect the deploy log: https://app.netlify.com/sites/carbon-react-next/deploys/616f23ad155fd60008b1729a 😎 Browse the preview: https://deploy-preview-9340--carbon-react-next.netlify.app |
DCO Assistant Lite bot All contributors have signed the DCO. |
I have read the DCO document and I hereby sign the DCO. |
✔️ Deploy Preview for carbon-elements ready! 🔨 Explore the source changes: 483982a 🔍 Inspect the deploy log: https://app.netlify.com/sites/carbon-elements/deploys/616f23ad4c35f10007e3f330 😎 Browse the preview: https://deploy-preview-9340--carbon-elements.netlify.app |
✔️ Deploy Preview for carbon-components-react ready! 🔨 Explore the source changes: 483982a 🔍 Inspect the deploy log: https://app.netlify.com/sites/carbon-components-react/deploys/616f23add63e4800084102bf 😎 Browse the preview: https://deploy-preview-9340--carbon-components-react.netlify.app |
The motion looks great to me @kristastarr ! Do you think we should include what errors and disabled states would look like in this pattern as well? For instance, if the user cannot click ahead a few steps because prior steps determine what is displayed in subsequent steps. There was a great discussion with @lisajkaiser about this last week and I think it would be great to include these scenarios as well. |
@johnbister Yes, that makes sense! I'll work on adding the error and disabled states this week. |
…invalid icons and helper text
…invalid icons and helper text
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The animation looks slick! I think the only big note from the implementation is that it seems like the PR makes a change to ProgressIndicator
where it reverts it to a class component versus the function component that we refactored it to recently.
From a motion perspective, will we need to add in support for disabling this animation when the user has a no motion preference? 👀
@joshblack Absolutely, I added media queries to disable the animations for users who prefer reduced motion. |
@joshblack I made the following updates:
One thing to mention (which maybe I should have indicated elsewhere?) is that this will be a breaking change - the format of the props passed to |
export class ProgressStep extends React.PureComponent { | ||
constructor(props) { | ||
super(props); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still trying to figure out what the status of this PR is, but we're actually working on making our components functional components for v11. Devs agreed that it makes more sense esp since most devs these days work with the latest React. We don't want this to be a class component.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ref: #9712
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, sorry, it looked like I needed to re-write some of the tests to get them to pass and unfortunately I haven't done it yet. I understand what you're saying about functional components, but I could not find a way to apply the animations without making it into a class component. Do you want to close this PR for the moment? I still plan to fix the failing tests, and I will review and seek advice on the feasibility of accomplishing the animation on a functional component.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious what issues you were running into with the functional component, and also if there are other ways we might be able to implement this without breaking changes. Referring to the stepData
prop. Why is that needed instead of handling the props through ProgressStep
? It's not our typical API pattern for data of parent/child components like Tabs
, Accordion
, ContentSwitcher
. I think there's a bigger discussion to be had about the implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please bear with my long explanation here 😅 I'll try to explain how/why I ended up doing it the way I did, and maybe we can come to a better solution - any thoughts or suggestions are greatly appreciated! I definitely agree it would be preferable to not introduce any breaking changes.
The issue I was having was how to prevent a re-render of all the ProgressStep
components each time there was a change to the ProgressIndicator
's props. Once I added in the CSS keyframes animations, the animations were re-triggered every time each ProgressStep
was re-rendered, which caused a weird flashing effect (see below although please note that that is an earlier version that did not yet include the line animations, only the icon animations). The goal was for each ProgressStep
& its icon to re-render only when there was a change to its status.
progress-tracker2.mp4
In the current implementation of ProgressIndicator.js, renderSteps()
clones each child element each time there is a change to the ProgressIndicator
's currentIndex
, and so the cloneElement()
is what was triggering the re-render. Instead of cloning the element, I wanted the element to persist but just change it's props if necessary. I first thought to use React.memo()
but from my understanding, that is not something that can be used with React.Children. So that's how I ended up passing the StepData in to render the ProgressStep
s with the newly added isCurrent
and isComplete
props, rather than rendering them as cloned React.Children. The solution I found was to use React.PureComponent
to make use of its comparison of those props to only re-render a ProgressStep
if it changes, hence the Class component.
As a next step, I addressed the lint and format errors, and I will take a look at the typical pattern for for handling parent/child components in the components you mentioned. (The PublicAPI-test is still failing but since we may eliminate the changes causing that fail, I will address it later if need be.) @matthewgallo will take a look at this as well and we will hopefully find a solution that will work as a functional component and also one without any breaking changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @kristastarr sorry for the late reply. Thank you for that detailed explanation, it's very helpful. I'd really like to help get this into production since it's something our designers are interested in. I think going forward, we can do a few things:
- Make this an RFC or create a separate RFC to get more input from the rest of our dev team on the implementation.
- I am also planning on bringing this up in our next dev team meeting (this week), and hopefully get some thoughts on how we feel about the API changes. Maybe even think about alternate solutions.
- Based on feedback and input from the rest of the team, we can decide what to do, how to help, etc.
How does that sound?
…arr/carbon into progress-tracker-motion
Hey @kristastarr After talking to our dev team, we would prefer for the component to keep the existing API, where the steps are rendered as children and not a prop data array. We've just found that our components that follow the data prop pattern can be a pain both for users and maintainers. It can just limit people sometimes. So our requests would be to keep the functional component and API as is. It seems that this PR hasn't had some activity for quite some time, so I'm going to close this for now. Please feel free to open another PR with these changes once you're ready. 🙂 |
I am still planning to work on implementing the animation with a functional component. If yes, I will check in with y’all to see if I should do a new PR to Carbon, and if not we will plan to incorporate it into the Carbon for IBM products. |
Closes #9156
Progress Indicator Animations:
Changelog
New
Added keyframes and transitions to _progress-indicator.scss
Changed
Changed the ProgressIndicator component in the React package - this change would require a
StepData
object to be passed in as a prop to theProgressIndicator
component, in orderProgressIndicator
to render aProgressStep
. (Currently theProgressStep
s are being rendered asReact.Children
inProgressIndicator
).Rationale: Properties of
this.props.children
cannot be modified, so currently are being re-rendered usingReact.cloneElement
with the updated "current" or "completed" property each time the CurrentIndex changed. When I added the CSS for the animations, this caused all the icons to animate every single time there is a change to the status of any singleProgressStep
. RenderingProgressStep
components from inside theProgressIndicator
enabled me to modify the "current" and "completed" properties of eachProgressStep
to trigger a re-render of a step/icon only when there is a change to that specificProgressStep
.Testing / Reviewing
You can see the changes by running the Carbon React Storybook.
recheck