Skip to content

Commit 9169666

Browse files
ktranDevtools-frontend LUCI CQ
authored andcommitted
[GM3Restyling] Update animations panel empty states
Before: https://imgur.com/a/A6eCZFD After: https://imgur.com/a/Fx2Ib6W Bug: 325443331 Change-Id: I990fd9d69399779d9ffc5a4a5a14c5d7a4b1d181 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6254938 Commit-Queue: Kim-Anh Tran <[email protected]> Reviewed-by: Kateryna Prokopenko <[email protected]>
1 parent 663a015 commit 9169666

File tree

3 files changed

+90
-20
lines changed

3 files changed

+90
-20
lines changed

front_end/panels/animation/AnimationTimeline.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,3 +676,55 @@ describeWithMockConnection('AnimationTimeline', () => {
676676
});
677677
});
678678
});
679+
680+
describeWithMockConnection('AnimationTimeline', () => {
681+
it('shows placeholder showing that the panel is waiting for animations', () => {
682+
const view = Animation.AnimationTimeline.AnimationTimeline.instance();
683+
const placeholder = view.contentElement.querySelector('.animation-timeline-buffer-hint');
684+
assert.exists(placeholder);
685+
686+
// Render into document in order to see the computed styles.
687+
view.markAsRoot();
688+
view.show(document.body);
689+
assert.deepEqual(window.getComputedStyle(placeholder).display, 'flex');
690+
691+
assert.deepEqual(placeholder.querySelector('.empty-state-header')?.textContent, 'Currently waiting for animations');
692+
assert.deepEqual(
693+
placeholder.querySelector('.empty-state-description span')?.textContent,
694+
'On this page you can inspect and modify animations.');
695+
696+
view.detach();
697+
});
698+
699+
it('shows placeholder if no animation has been selected', async () => {
700+
const target = createTarget();
701+
const model = target.model(SDK.AnimationModel.AnimationModel);
702+
assert.exists(model);
703+
704+
const dummyGroups = new Map<string, SDK.AnimationModel.AnimationGroup>();
705+
sinon.stub(model!, 'animationGroups').value(dummyGroups);
706+
dummyGroups.set('dummy', new SDK.AnimationModel.AnimationGroup(model, 'dummy', []));
707+
708+
// Render into document in order to update the shown empty state.
709+
const view = Animation.AnimationTimeline.AnimationTimeline.instance();
710+
view.markAsRoot();
711+
view.show(document.body);
712+
713+
const previewUpdatePromise = new ManualPromise();
714+
sinon.stub(view, 'previewsCreatedForTest').callsFake(() => {
715+
previewUpdatePromise.resolve();
716+
});
717+
718+
await previewUpdatePromise.wait();
719+
const placeholder = view.contentElement.querySelector('.animation-timeline-rows-hint');
720+
assert.exists(placeholder);
721+
722+
assert.deepEqual(window.getComputedStyle(placeholder).display, 'flex');
723+
assert.deepEqual(placeholder.querySelector('.empty-state-header')?.textContent, 'No animation effect selected');
724+
assert.deepEqual(
725+
placeholder.querySelector('.empty-state-description span')?.textContent,
726+
'Select an effect above to inspect and modify');
727+
728+
view.detach();
729+
});
730+
});

front_end/panels/animation/AnimationTimeline.ts

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,17 @@ import {AnimationUI} from './AnimationUI.js';
2020

2121
const UIStrings = {
2222
/**
23-
*@description Timeline hint text content in Animation Timeline of the Animation Inspector
23+
*@description Timeline hint text content in Animation Timeline of the Animation Inspector if no effect
24+
* is shown.
25+
* Animation effects are the visual effects of an animation on the page.
2426
*/
25-
selectAnEffectAboveToInspectAnd: 'Select an effect above to inspect and modify.',
27+
noEffectSelected: 'No animation effect selected',
28+
/**
29+
*@description Timeline hint text content in Animation Timeline of the Animation Inspector that instructs
30+
* users to select an effect.
31+
* Animation effects are the visual effects of an animation on the page.
32+
*/
33+
selectAnEffectAboveToInspectAnd: 'Select an effect above to inspect and modify',
2634
/**
2735
*@description Text to clear everything
2836
*/
@@ -54,9 +62,13 @@ const UIStrings = {
5462
*/
5563
animationPreviews: 'Animation previews',
5664
/**
57-
*@description Empty buffer hint text content in Animation Timeline of the Animation Inspector
65+
*@description Empty buffer hint text content in Animation Timeline of the Animation Inspector.
66+
*/
67+
waitingForAnimations: 'Currently waiting for animations',
68+
/**
69+
*@description Empty buffer hint text content in Animation Timeline of the Animation Inspector that explains the panel.
5870
*/
59-
waitingForAnimations: 'Waiting for animations...',
71+
animationDescription: 'On this page you can inspect and modify animations.',
6072
/**
6173
*@description Tooltip text that appears when hovering over largeicon replay animation button in Animation Timeline of the Animation Inspector
6274
*/
@@ -89,6 +101,9 @@ const MIN_TIMELINE_CONTROLS_WIDTH = 120;
89101
const DEFAULT_TIMELINE_CONTROLS_WIDTH = 150;
90102
const MAX_TIMELINE_CONTROLS_WIDTH = 720;
91103

104+
const ANIMATION_EXPLANATION_URL =
105+
'https://developer.chrome.com/docs/devtools/css/animations' as Platform.DevToolsPath.UrlString;
106+
92107
let animationTimelineInstance: AnimationTimeline;
93108

94109
export class AnimationTimeline extends UI.Widget.VBox implements
@@ -150,8 +165,16 @@ export class AnimationTimeline extends UI.Widget.VBox implements
150165
this.createHeader();
151166
this.#animationsContainer = this.contentElement.createChild('div', 'animation-timeline-rows');
152167
this.#animationsContainer.setAttribute('jslog', `${VisualLogging.section('animations')}`);
168+
const emptyBufferHint = this.contentElement.createChild('div', 'animation-timeline-buffer-hint');
169+
const noAnimationsPlaceholder = new UI.EmptyWidget.EmptyWidget(
170+
i18nString(UIStrings.waitingForAnimations), i18nString(UIStrings.animationDescription));
171+
noAnimationsPlaceholder.appendLink(ANIMATION_EXPLANATION_URL);
172+
noAnimationsPlaceholder.show(emptyBufferHint);
173+
153174
const timelineHint = this.contentElement.createChild('div', 'animation-timeline-rows-hint');
154-
timelineHint.textContent = i18nString(UIStrings.selectAnEffectAboveToInspectAnd);
175+
const noEffectSelectedPlaceholder = new UI.EmptyWidget.EmptyWidget(
176+
i18nString(UIStrings.noEffectSelected), i18nString(UIStrings.selectAnEffectAboveToInspectAnd));
177+
noEffectSelectedPlaceholder.show(timelineHint);
155178

156179
/** @const */ this.#defaultDuration = 100;
157180
this.#durationInternal = this.#defaultDuration;
@@ -351,8 +374,6 @@ export class AnimationTimeline extends UI.Widget.VBox implements
351374
this.#previewContainer.setAttribute('jslog', `${VisualLogging.section('film-strip')}`);
352375
UI.ARIAUtils.markAsListBox(this.#previewContainer);
353376
UI.ARIAUtils.setLabel(this.#previewContainer, i18nString(UIStrings.animationPreviews));
354-
const emptyBufferHint = this.contentElement.createChild('div', 'animation-timeline-buffer-hint');
355-
emptyBufferHint.textContent = i18nString(UIStrings.waitingForAnimations);
356377
const container = this.contentElement.createChild('div', 'animation-timeline-header');
357378
const controls = container.createChild('div', 'animation-controls');
358379
this.#currentTime = controls.createChild('div', 'animation-timeline-current-time monospace');

front_end/panels/animation/animationTimeline.css

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -144,28 +144,19 @@ circle.animation-keyframe-point:active {
144144
cursor: pointer;
145145
}
146146

147-
.animation-timeline-buffer,
148-
.animation-timeline-buffer-hint {
147+
.animation-timeline-buffer
148+
{
149149
height: 48px;
150150
flex: 0 0 auto;
151151
border-bottom: 1px solid var(--sys-color-divider);
152152
display: flex;
153153
padding: 0 2px;
154154
}
155155

156-
.animation-timeline-buffer:empty,
157156
.animation-timeline-buffer-hint {
158157
display: none;
159158
}
160159

161-
.animation-timeline-buffer:empty ~ .animation-timeline-buffer-hint {
162-
align-items: center;
163-
justify-content: center;
164-
font-size: 14px;
165-
z-index: 101;
166-
display: flex;
167-
}
168-
169160
.animation-time-overlay {
170161
background-color: var(--sys-color-on-surface);
171162
opacity: 5%;
@@ -352,7 +343,8 @@ text.animation-timeline-grid-label {
352343
}
353344

354345
.animation-timeline-rows,
355-
.animation-timeline-rows-hint {
346+
.animation-timeline-rows-hint,
347+
.animation-timeline-buffer-hint {
356348
flex-grow: 1;
357349
overflow: hidden auto;
358350
z-index: 1;
@@ -366,7 +358,12 @@ text.animation-timeline-grid-label {
366358
flex-grow: 0;
367359
}
368360

369-
.animation-timeline-buffer:not(:empty) ~ .animation-timeline-rows:empty ~ .animation-timeline-rows-hint {
361+
.animation-timeline-rows:empty {
362+
display: none;
363+
}
364+
365+
.animation-timeline-buffer:not(:empty) ~ .animation-timeline-rows:empty ~.animation-timeline-buffer-hint:not(:empty) ~ .animation-timeline-rows-hint,
366+
.animation-timeline-buffer:empty ~ .animation-timeline-buffer-hint {
370367
font-size: 14px;
371368
display: flex;
372369
align-items: center;

0 commit comments

Comments
 (0)