fix(progress): add shared class

PiperOrigin-RevId: 549369009
This commit is contained in:
Elizabeth Mitchell 2023-07-19 11:09:27 -07:00 committed by Copybara-Service
parent 45f42f03ce
commit 75058ca2be
5 changed files with 99 additions and 107 deletions

View File

@ -67,13 +67,13 @@
content-visibility: auto; content-visibility: auto;
} }
.circular-progress { .progress {
flex: 1; flex: 1;
align-self: stretch; align-self: stretch;
margin: $container-padding; margin: $container-padding;
} }
.circular-progress, .progress,
.spinner, .spinner,
.left, .left,
.right, .right,
@ -110,7 +110,7 @@
stroke: transparent; stroke: transparent;
} }
.circular-progress.indeterminate { .progress.indeterminate {
will-change: transform; will-change: transform;
animation: linear infinite linear-rotate; animation: linear infinite linear-rotate;
animation-duration: $linear-rotate-duration; animation-duration: $linear-rotate-duration;

View File

@ -48,9 +48,9 @@ $_track-background: 0 / $_track-background-width 100%
// Generates a list of rtl selectors. This is done so rules can be generated // Generates a list of rtl selectors. This is done so rules can be generated
// separately so they don't get dropped where unsupported. // separately so they don't get dropped where unsupported.
$rtl-selectors: ( $rtl-selectors: (
':host-context([dir="rtl"]) .linear-progress', ':host-context([dir="rtl"]) .progress',
':host([dir="rtl"]) .linear-progress', ':host([dir="rtl"]) .progress',
'.linear-progress:dir(rtl)' '.progress:dir(rtl)'
); );
@mixin styles() { @mixin styles() {
@ -72,7 +72,7 @@ $rtl-selectors: (
contain: strict; contain: strict;
} }
.linear-progress, .progress,
.track, .track,
.buffer-bar, .buffer-bar,
.bar, .bar,
@ -80,7 +80,7 @@ $rtl-selectors: (
position: absolute; position: absolute;
} }
.linear-progress { .progress {
inset: 0; inset: 0;
outline: transparent solid 1px; outline: transparent solid 1px;
border-radius: var(--_track-shape); border-radius: var(--_track-shape);
@ -310,13 +310,13 @@ $rtl-selectors: (
} }
@media screen and (forced-colors: active) { @media screen and (forced-colors: active) {
.linear-progress { .progress {
--_active-indicator-color: canvastext; --_active-indicator-color: canvastext;
--_track-color: graytext; --_track-color: graytext;
border: 1px solid canvastext; border: 1px solid canvastext;
} }
.indeterminate.linear-progress { .indeterminate.progress {
--_track-color: canvas; --_track-color: canvas;
} }
} }

View File

@ -4,58 +4,20 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
import {html, LitElement, nothing} from 'lit'; import {html} from 'lit';
import {property} from 'lit/decorators.js';
import {classMap} from 'lit/directives/class-map.js';
import {ARIAMixinStrict} from '../../internal/aria/aria.js'; import {Progress} from './progress.js';
import {requestUpdateOnAriaChange} from '../../internal/aria/delegate.js';
/** /**
* A circular progress component. * A circular progress component.
*/ */
export class CircularProgress extends LitElement { export class CircularProgress extends Progress {
static { protected override renderIndicator() {
requestUpdateOnAriaChange(this); if (this.indeterminate) {
} return this.renderIndeterminateContainer();
}
/** return this.renderDeterminateContainer();
* Progress to display, a fraction between 0 and 1.
*/
@property({type: Number}) progress = 0;
/**
* Whether or not to display an animated spinner representing indeterminate
* progress.
*/
@property({type: Boolean}) indeterminate = false;
/**
* Whether or not to render indeterminate mode using 4 colors instead of one.
*/
@property({type: Boolean, attribute: 'four-color'}) fourColor = false;
protected override render() {
const classes = {
'indeterminate': this.indeterminate,
'four-color': this.fourColor
};
// Needed for closure conformance
const {ariaLabel} = this as ARIAMixinStrict;
return html`
<div
class="circular-progress ${classMap(classes)}"
role="progressbar"
aria-label="${ariaLabel || nothing}"
aria-valuemin="0"
aria-valuemax="1"
aria-valuenow="${this.indeterminate ? nothing : this.progress}">
${
this.indeterminate ? this.renderIndeterminateContainer() :
this.renderDeterminateContainer()}
</div>
`;
} }
// Determinate mode is rendered with an svg so the progress arc can be // Determinate mode is rendered with an svg so the progress arc can be

View File

@ -4,58 +4,37 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
import {html, LitElement, nothing} from 'lit'; import {html} from 'lit';
import {property, query, state} from 'lit/decorators.js'; import {property, query, state} from 'lit/decorators.js';
import {classMap} from 'lit/directives/class-map.js';
import {styleMap} from 'lit/directives/style-map.js'; import {styleMap} from 'lit/directives/style-map.js';
import {ARIAMixinStrict} from '../../internal/aria/aria.js'; import {Progress} from './progress.js';
import {requestUpdateOnAriaChange} from '../../internal/aria/delegate.js';
/** /**
* A linear progress component. * A linear progress component.
*/ */
export class LinearProgress extends LitElement { export class LinearProgress extends Progress {
static {
requestUpdateOnAriaChange(this);
}
/**
* Whether or not to render indeterminate progress in an animated state.
*/
@property({type: Boolean}) indeterminate = false;
/**
* Progress to display, a fraction between 0 and 1.
*/
@property({type: Number}) progress = 0;
/** /**
* Buffer amount to display, a fraction between 0 and 1. * Buffer amount to display, a fraction between 0 and 1.
*/ */
@property({type: Number}) buffer = 1; @property({type: Number}) buffer = 1;
/** @query('.progress') private readonly rootEl!: HTMLElement|null;
* Whether or not to render indeterminate mode using 4 colors instead of one.
*
*/
@property({type: Boolean, attribute: 'four-color'}) fourColor = false;
@query('.linear-progress') private readonly rootEl!: HTMLElement|null;
@state() private animationReady = true; @state() private animationReady = true;
private resizeObserver: ResizeObserver|null = null; private resizeObserver: ResizeObserver|null = null;
protected override getRenderClasses() {
return {
...super.getRenderClasses(),
'animation-ready': this.animationReady,
};
}
// Note, the indeterminate animation is rendered with transform %'s // Note, the indeterminate animation is rendered with transform %'s
// Previously, this was optimized to use px calculated with the resizeObserver // Previously, this was optimized to use px calculated with the resizeObserver
// due to a now fixed Chrome bug: crbug.com/389359. // due to a now fixed Chrome bug: crbug.com/389359.
protected override render() { protected override renderIndicator() {
const rootClasses = {
'indeterminate': this.indeterminate,
'animation-ready': this.animationReady,
'four-color': this.fourColor
};
const progressStyles = { const progressStyles = {
transform: `scaleX(${(this.indeterminate ? 1 : this.progress) * 100}%)` transform: `scaleX(${(this.indeterminate ? 1 : this.progress) * 100}%)`
}; };
@ -63,25 +42,16 @@ export class LinearProgress extends LitElement {
transform: `scaleX(${(this.indeterminate ? 1 : this.buffer) * 100}%)` transform: `scaleX(${(this.indeterminate ? 1 : this.buffer) * 100}%)`
}; };
// Needed for closure conformance
const {ariaLabel} = this as ARIAMixinStrict;
return html` return html`
<div <div class="track"></div>
role="progressbar" <div class="buffer-bar" style=${styleMap(bufferStyles)}></div>
class="linear-progress ${classMap(rootClasses)}" <div class="bar primary-bar" style=${styleMap(progressStyles)}>
aria-label="${ariaLabel || nothing}" <div class="bar-inner"></div>
aria-valuemin="0" </div>
aria-valuemax="1" <div class="bar secondary-bar">
aria-valuenow="${this.indeterminate ? nothing : this.progress}"> <div class="bar-inner"></div>
<div class="track"></div> </div>
<div class="buffer-bar" style=${styleMap(bufferStyles)}></div> `;
<div class="bar primary-bar" style=${styleMap(progressStyles)}>
<div class="bar-inner"></div>
</div>
<div class="bar secondary-bar">
<div class="bar-inner"></div>
</div>
</div>`;
} }
override async connectedCallback() { override async connectedCallback() {

60
progress/lib/progress.ts Normal file
View File

@ -0,0 +1,60 @@
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {html, LitElement, nothing, TemplateResult} from 'lit';
import {property} from 'lit/decorators.js';
import {classMap} from 'lit/directives/class-map.js';
import {ARIAMixinStrict} from '../../internal/aria/aria.js';
import {requestUpdateOnAriaChange} from '../../internal/aria/delegate.js';
/**
* A progress component.
*/
export abstract class Progress extends LitElement {
static {
requestUpdateOnAriaChange(this);
}
/**
* Progress to display, a fraction between 0 and 1.
*/
@property({type: Number}) progress = 0;
/**
* Whether or not to display indeterminate progress, which gives no indication
* to how long an activity will take.
*/
@property({type: Boolean}) indeterminate = false;
/**
* Whether or not to render indeterminate mode using 4 colors instead of one.
*/
@property({type: Boolean, attribute: 'four-color'}) fourColor = false;
protected override render() {
// Needed for closure conformance
const {ariaLabel} = this as ARIAMixinStrict;
return html`
<div class="progress ${classMap(this.getRenderClasses())}"
role="progressbar"
aria-label="${ariaLabel || nothing}"
aria-valuemin="0"
aria-valuemax="1"
aria-valuenow=${this.indeterminate ? nothing : this.progress}
>${this.renderIndicator()}</div>
`;
}
protected getRenderClasses() {
return {
'indeterminate': this.indeterminate,
'four-color': this.fourColor,
};
}
protected abstract renderIndicator(): TemplateResult;
}