-
Notifications
You must be signed in to change notification settings - Fork 12
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
va-button: add loading variation #1446
Conversation
{buttonText} | ||
{_continue && !back && <va-icon icon="navigate_far_next" />} | ||
</button> | ||
{/* This span must always be present for changes to be announced for the loading prop. It will not show visually or be read without content*/} |
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 don't love the idea of this span being rendered for all buttons. I have tested it and it does not announce anything when there is not content, but it would be nice to figure out a way to only render it if the button will be used for loading. Hoping someone has an idea for how to do that.
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 don't think it's a big deal to have a span always in the markup but was there some limitation with just doing conditional JSX? Something like:
{this.loading && (
<span class="loading-message" role="status">....</span>
)}
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.
Design looks good. That animation is 🔥!
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.
Nothing blocking that I could see but I had just a few questions and comments. The animation sure is slick. 😎
@@ -50,6 +53,22 @@ export class VaButton { | |||
*/ | |||
@Prop({ reflect: true }) disabled?: boolean = false; | |||
|
|||
/** | |||
* If `true`, the click event will not fire. |
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.
Is this description accurate for the loading prop?
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.
Yes, this is handled the same way as the disabled prop by preventDefault()
and preventPropogation()
on line 168.
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.
oh ok yes that makes sense. I was expecting it to mention that it will display the loading indicator too.
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.
oh, I should add that! Thanks!
animation: none; | ||
} | ||
|
||
@media (prefers-reduced-motion) { |
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.
This is a cool media feature. TIL!
{buttonText} | ||
{_continue && !back && <va-icon icon="navigate_far_next" />} | ||
</button> | ||
{/* This span must always be present for changes to be announced for the loading prop. It will not show visually or be read without content*/} |
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 don't think it's a big deal to have a span always in the markup but was there some limitation with just doing conditional JSX? Something like:
{this.loading && (
<span class="loading-message" role="status">....</span>
)}
@Watch('loading') | ||
announceLoadingChange(newValue: boolean, oldValue: boolean) { | ||
if (oldValue && !newValue) { | ||
var me = this; |
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.
Should this variable assignment be let
?
this.showCompletedMessage = true; | ||
setTimeout(() => { | ||
me.showCompletedMessage = false; | ||
}, 3000); |
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 not sure I understand the need for a timeout and why this specific time is used. Do you mind clarifying?
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 <span role="status">
will only be read by the screen reader if there are changes to the content of the span. This is the reasoning for the span always being rendered, even if the loading prop is false, because if we render it when the prop changes the reader will not count that as a change and "Loading" will never be read.
The same applies to this timeout. If there is not any time between when the completion message is set and when it is set to null, the reader won't detect the change and the message won't be read. Its an arbitrary number to guarantee the "Loading complete" is read.
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.
That makes sense. Thanks for the explanation!
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.
This looked good in my testing, screen readers announced the loading state/complete as expected. Thanks!
aria-disabled={ariaDisabled} | ||
aria-busy={loading ? 'true' : undefined} | ||
aria-label={label} | ||
aria-live={loading ? 'polite' : 'off'} |
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 don't believe we'll need this aria-live
on the button itself, as the span
will handle the live region. Leaving it in doesn't seem to cause any negative effects, but could lead to repetitive announcements. I tested this code without it and it announced as expected.
Chromatic
https://3460-button-loading--65a6e2ed2314f7b8f98609d8.chromatic.com
Description
Add loading variation for button.
The button should:
text
prop is not setloading
prop is true and "Loading complete" when it is set to falseCloses 3460
QA Checklist
Screenshots
Acceptance criteria
Definition of done