Skip to content
This repository was archived by the owner on Jan 13, 2025. It is now read-only.

Commit 98b8434

Browse files
allan-chencopybara-github
authored andcommitted
refactor(linear-progress): Restructure buffer DOM to allow translucent buffer
BREAKING CHANGE: DOM for linear progress buffer changed. MDCLinearProgressAdapter method `getBuffer`, `getPrimaryBar`, `setStyle` removed. MDCLinearProgressAdapter method `setBufferBarStyle`, `setPrimaryBarStyle` added. PiperOrigin-RevId: 299133963
1 parent 3657f88 commit 98b8434

File tree

9 files changed

+117
-99
lines changed

9 files changed

+117
-99
lines changed

packages/mdc-linear-progress/README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@ npm install @material/linear-progress
4242

4343
```html
4444
<div role="progressbar" class="mdc-linear-progress" aria-label="Example Progress Bar" aria-valuemin="0" aria-valuemax="1" aria-valuenow="0">
45-
<div class="mdc-linear-progress__buffering-dots"></div>
46-
<div class="mdc-linear-progress__buffer"></div>
45+
<div class="mdc-linear-progress__buffer">
46+
<div class="mdc-linear-progress__buffer-bar"></div>
47+
<div class="mdc-linear-progress__buffer-dots"></div>
48+
</div>
4749
<div class="mdc-linear-progress__bar mdc-linear-progress__primary-bar">
4850
<span class="mdc-linear-progress__bar-inner"></span>
4951
</div>
@@ -111,10 +113,9 @@ The adapter for linear progress must provide the following functions, with corre
111113
| `removeClass(className: string) => void` | Removes a class from the root element. |
112114
| `hasClass(className: string) => boolean` | Returns boolean indicating whether the root element has a given class. |
113115
| `forceLayout() => void` | Force-trigger a layout on the root element. This is needed to restart animations correctly. |
114-
| `getPrimaryBar() => Element` | Returns the primary bar element. |
115-
| `getBuffer() => Element` | Returns the buffer element. |
116116
| `setAttribute(attributeName: string, value: string) => void` | Sets the specified attribute on the root element. |
117-
| `setStyle(el: Element, styleProperty: string, value: string) => void` | Sets the inline style on the given element. |
117+
| `setBufferBarStyle(styleProperty: string, value: string) => void` | Sets the inline style on the buffer bar. |
118+
| `setPrimaryBarStyle(styleProperty: string, value: string) => void` | Sets the inline style on the primary bar. |
118119

119120
### MDCLinearProgressFoundation API
120121

packages/mdc-linear-progress/_keyframes.scss

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,11 @@
112112

113113
@mixin buffering-keyframes_ {
114114
@keyframes mdc-linear-progress-buffering {
115-
to {
116-
transform: translateX(-10px);
115+
from {
116+
// Normally the buffer dots start from the left and overflow to the right.
117+
// We rotate by 180deg so that the buffer dots start on the right when
118+
// in non-reversed mode and overflow to the left.
119+
transform: rotate(180deg) translateX(-10px);
117120
}
118121
}
119122
}
@@ -165,8 +168,8 @@
165168

166169
@mixin buffering-reverse-keyframes_ {
167170
@keyframes mdc-linear-progress-buffering-reverse {
168-
to {
169-
transform: translateX(10px);
171+
from {
172+
transform: translateX(-10px);
170173
}
171174
}
172175
}

packages/mdc-linear-progress/_mixins.scss

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,30 +87,35 @@
8787
}
8888
}
8989

90-
&__buffering-dots {
90+
&__buffer {
9191
@include feature-targeting-mixins.targets($feat-structure) {
92+
display: flex;
9293
position: absolute;
9394
width: 100%;
9495
height: 100%;
96+
}
97+
}
98+
99+
&__buffer-dots {
100+
@include feature-targeting-mixins.targets($feat-structure) {
95101
background-repeat: repeat-x;
96102
background-size: 10px variables.$height;
103+
flex: auto;
104+
transform: rotate(180deg);
97105
}
98106

99107
@include feature-targeting-mixins.targets($feat-animation) {
100108
animation: mdc-linear-progress-buffering 250ms infinite linear;
101109
}
102110
}
103111

104-
&__buffer {
112+
&__buffer-bar {
105113
@include feature-targeting-mixins.targets($feat-structure) {
106-
position: absolute;
107-
width: 100%;
108-
height: 100%;
109-
transform-origin: top left;
114+
flex: 0 1 100%;
110115
}
111116

112117
@include feature-targeting-mixins.targets($feat-animation) {
113-
transition: animation-functions.exit-temporary(transform, 250ms);
118+
transition: animation-functions.exit-temporary(flex-basis, 250ms);
114119
}
115120
}
116121

@@ -180,15 +185,15 @@
180185
$color-value-for-svg: str-replace_(string.unquote("#{$color-value-for-css}"), "#", "%23");
181186
$feat-color: feature-targeting-functions.create-target($query, color);
182187

183-
.mdc-linear-progress__buffering-dots {
188+
.mdc-linear-progress__buffer-dots {
184189
@include feature-targeting-mixins.targets($feat-color) {
185190
// SVG is optimized for data URI (https://codepen.io/tigt/post/optimizing-svgs-in-data-uris)
186191
// stylelint-disable-next-line function-url-quotes
187192
background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' enable-background='new 0 0 5 2' xml:space='preserve' viewBox='0 0 5 2' preserveAspectRatio='none slice'%3E%3Ccircle cx='1' cy='1' r='1' fill='#{$color-value-for-svg}'/%3E%3C/svg%3E");
188193
}
189194
}
190195

191-
.mdc-linear-progress__buffer {
196+
.mdc-linear-progress__buffer-bar {
192197
@include feature-targeting-mixins.targets($feat-color) {
193198
background-color: $color-value-for-css;
194199
}
@@ -250,8 +255,7 @@
250255
$feat-animation: feature-targeting-functions.create-target($query, animation);
251256

252257
&--reversed {
253-
.mdc-linear-progress__bar,
254-
.mdc-linear-progress__buffer {
258+
.mdc-linear-progress__bar {
255259
@include feature-targeting-mixins.targets($feat-structure) {
256260
right: 0;
257261
transform-origin: center right;
@@ -270,10 +274,21 @@
270274
}
271275
}
272276

273-
.mdc-linear-progress__buffering-dots {
277+
.mdc-linear-progress__buffer-dots {
274278
@include feature-targeting-mixins.targets($feat-animation) {
275279
animation: mdc-linear-progress-buffering-reverse 250ms infinite linear;
276280
}
281+
282+
@include feature-targeting-mixins.targets($feat-structure) {
283+
order: 0;
284+
transform: rotate(0);
285+
}
286+
}
287+
288+
.mdc-linear-progress__buffer-bar {
289+
@include feature-targeting-mixins.targets($feat-structure) {
290+
order: 1;
291+
}
277292
}
278293
}
279294
}

packages/mdc-linear-progress/adapter.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,10 @@
3131
export interface MDCLinearProgressAdapter {
3232
addClass(className: string): void;
3333
forceLayout(): void;
34-
getBuffer(): HTMLElement | null;
35-
getPrimaryBar(): HTMLElement | null;
34+
setBufferBarStyle(styleProperty: string, value: string): void;
35+
setPrimaryBarStyle(styleProperty: string, value: string): void;
3636
hasClass(className: string): boolean;
3737
removeClass(className: string): void;
3838
removeAttribute(name: string): void;
3939
setAttribute(name: string, value: string): void;
40-
setStyle(el: HTMLElement, styleProperty: string, value: string): void;
4140
}

packages/mdc-linear-progress/component.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,27 @@ export class MDCLinearProgress extends
6262
const adapter: MDCLinearProgressAdapter = {
6363
addClass: (className: string) => this.root_.classList.add(className),
6464
forceLayout: () => (this.root_ as HTMLElement).offsetWidth,
65-
getBuffer: () => this.root_.querySelector(MDCLinearProgressFoundation.strings.BUFFER_SELECTOR),
66-
getPrimaryBar: () => this.root_.querySelector(MDCLinearProgressFoundation.strings.PRIMARY_BAR_SELECTOR),
65+
setBufferBarStyle: (styleProperty: string, value: string) => {
66+
(this.root_.querySelector(
67+
MDCLinearProgressFoundation.strings.BUFFER_BAR_SELECTOR) as
68+
HTMLElement)
69+
.style.setProperty(styleProperty, value);
70+
},
71+
setPrimaryBarStyle: (styleProperty: string, value: string) => {
72+
(this.root_.querySelector(
73+
MDCLinearProgressFoundation.strings.PRIMARY_BAR_SELECTOR) as
74+
HTMLElement)
75+
.style.setProperty(styleProperty, value);
76+
},
6777
hasClass: (className: string) => this.root_.classList.contains(className),
6878
removeAttribute: (attributeName: string) => {
6979
this.root_.removeAttribute(attributeName);
7080
},
71-
removeClass: (className: string) => this.root_.classList.remove(className),
81+
removeClass: (className: string) =>
82+
this.root_.classList.remove(className),
7283
setAttribute: (attributeName: string, value: string) => {
7384
this.root_.setAttribute(attributeName, value);
7485
},
75-
setStyle: (el: HTMLElement, styleProperty: string, value: string) => el.style.setProperty(styleProperty, value),
7686
};
7787
return new MDCLinearProgressFoundation(adapter);
7888
}

packages/mdc-linear-progress/constants.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export const cssClasses = {
2929

3030
export const strings = {
3131
ARIA_VALUENOW: 'aria-valuenow',
32-
BUFFER_SELECTOR: '.mdc-linear-progress__buffer',
32+
BUFFER_BAR_SELECTOR: '.mdc-linear-progress__buffer-bar',
33+
FLEX_BASIS: 'flex-basis',
3334
PRIMARY_BAR_SELECTOR: '.mdc-linear-progress__primary-bar',
3435
};

packages/mdc-linear-progress/foundation.ts

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,12 @@ export class MDCLinearProgressFoundation extends
4242
return {
4343
addClass: () => undefined,
4444
forceLayout: () => undefined,
45-
getBuffer: () => null,
46-
getPrimaryBar: () => null,
45+
setBufferBarStyle: () => null,
46+
setPrimaryBarStyle: () => null,
4747
hasClass: () => false,
4848
removeAttribute: () => undefined,
4949
removeClass: () => undefined,
5050
setAttribute: () => undefined,
51-
setStyle: () => undefined,
5251
};
5352
}
5453

@@ -74,39 +73,41 @@ export class MDCLinearProgressFoundation extends
7473
if (this.isDeterminate_) {
7574
this.adapter_.removeClass(cssClasses.INDETERMINATE_CLASS);
7675
this.adapter_.setAttribute(strings.ARIA_VALUENOW, this.progress_.toString());
77-
this.setScale_(this.adapter_.getPrimaryBar(), this.progress_);
78-
this.setScale_(this.adapter_.getBuffer(), this.buffer_);
79-
} else {
80-
if (this.isReversed_) {
81-
// Adding/removing REVERSED_CLASS starts a translate animation, while
82-
// adding INDETERMINATE_CLASS starts a scale animation. Here, we reset
83-
// the translate animation in order to keep it in sync with the new
84-
// scale animation that will start from adding INDETERMINATE_CLASS
85-
// below.
86-
this.adapter_.removeClass(cssClasses.REVERSED_CLASS);
87-
this.adapter_.forceLayout();
88-
this.adapter_.addClass(cssClasses.REVERSED_CLASS);
89-
}
76+
this.setPrimaryBarProgress_(this.progress_);
77+
this.setBufferBarProgress_(this.buffer_);
9078

91-
this.adapter_.addClass(cssClasses.INDETERMINATE_CLASS);
92-
this.adapter_.removeAttribute(strings.ARIA_VALUENOW);
93-
this.setScale_(this.adapter_.getPrimaryBar(), 1);
94-
this.setScale_(this.adapter_.getBuffer(), 1);
79+
return;
80+
}
81+
82+
if (this.isReversed_) {
83+
// Adding/removing REVERSED_CLASS starts a translate animation, while
84+
// adding INDETERMINATE_CLASS starts a scale animation. Here, we reset
85+
// the translate animation in order to keep it in sync with the new
86+
// scale animation that will start from adding INDETERMINATE_CLASS
87+
// below.
88+
this.adapter_.removeClass(cssClasses.REVERSED_CLASS);
89+
this.adapter_.forceLayout();
90+
this.adapter_.addClass(cssClasses.REVERSED_CLASS);
9591
}
92+
93+
this.adapter_.addClass(cssClasses.INDETERMINATE_CLASS);
94+
this.adapter_.removeAttribute(strings.ARIA_VALUENOW);
95+
this.setPrimaryBarProgress_(1);
96+
this.setBufferBarProgress_(1);
9697
}
9798

9899
setProgress(value: number) {
99100
this.progress_ = value;
100101
if (this.isDeterminate_) {
101-
this.setScale_(this.adapter_.getPrimaryBar(), value);
102+
this.setPrimaryBarProgress_(value);
102103
this.adapter_.setAttribute(strings.ARIA_VALUENOW, value.toString());
103104
}
104105
}
105106

106107
setBuffer(value: number) {
107108
this.buffer_ = value;
108109
if (this.isDeterminate_) {
109-
this.setScale_(this.adapter_.getBuffer(), value);
110+
this.setBufferBarProgress_(value);
110111
}
111112
}
112113

@@ -126,9 +127,10 @@ export class MDCLinearProgressFoundation extends
126127

127128
if (this.isReversed_) {
128129
this.adapter_.addClass(cssClasses.REVERSED_CLASS);
129-
} else {
130-
this.adapter_.removeClass(cssClasses.REVERSED_CLASS);
130+
return;
131131
}
132+
133+
this.adapter_.removeClass(cssClasses.REVERSED_CLASS);
132134
}
133135

134136
open() {
@@ -139,12 +141,15 @@ export class MDCLinearProgressFoundation extends
139141
this.adapter_.addClass(cssClasses.CLOSED_CLASS);
140142
}
141143

142-
private setScale_(el: HTMLElement | null, scaleValue: number) {
143-
if (!el) {
144-
return;
145-
}
146-
const value = `scaleX(${scaleValue})`;
147-
this.adapter_.setStyle(el, getCorrectPropertyName(window, 'transform'), value);
144+
private setPrimaryBarProgress_(progressValue: number) {
145+
const value = `scaleX(${progressValue})`;
146+
this.adapter_.setPrimaryBarStyle(
147+
getCorrectPropertyName(window, 'transform'), value);
148+
}
149+
150+
private setBufferBarProgress_(progressValue: number) {
151+
const value = `${progressValue * 100}%`;
152+
this.adapter_.setBufferBarStyle(strings.FLEX_BASIS, value);
148153
}
149154
}
150155

packages/mdc-linear-progress/test/component.test.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ function getFixture() {
2929
wrapper.innerHTML = `
3030
<div role="progressbar" class="mdc-linear-progress" aria-label="Unit Test Progress Bar" aria-valuemin="0"
3131
aria-valuemax="1" aria-valuenow="0">
32-
<div class="mdc-linear-progress__buffering-dots"></div>
33-
<div class="mdc-linear-progress__buffer"></div>
32+
<div class="mdc-linear-progress__buffer">
33+
<div class="mdc-linear-progress__buffer-bar"></div>
34+
<div class="mdc-linear-progress__buffer-dots"></div>
35+
</div>
3436
<div class="mdc-linear-progress__bar mdc-linear-progress__primary-bar">
3537
<span class="mdc-linear-progress__bar-inner"></span>
3638
</div>
@@ -89,11 +91,12 @@ describe('MDCLinearProgress', () => {
8991
component.buffer = 0.5;
9092
const buffer =
9193
root.querySelector(
92-
MDCLinearProgressFoundation.strings.BUFFER_SELECTOR) as HTMLElement;
94+
MDCLinearProgressFoundation.strings.BUFFER_BAR_SELECTOR) as
95+
HTMLElement;
9396
// External GitHub TS compiler insists that `buffer.style.transform` could
9497
// be null
9598
// tslint:disable-next-line:no-unnecessary-type-assertion
96-
expect('scaleX(0.5)').toEqual(buffer.style.transform as string);
99+
expect('50%').toEqual(buffer.style.flexBasis as string);
97100
});
98101

99102
it('set reverse', () => {

0 commit comments

Comments
 (0)