Skip to content

Commit 1838644

Browse files
style(Computer Avatar Selector): Improve selection flow (#2293)
Co-authored-by: Jonathan Lim-Breitbart <breity10@gmail.com>
1 parent 192c55c commit 1838644

5 files changed

Lines changed: 123 additions & 74 deletions

File tree

src/assets/wise5/vle/computer-avatar-selector/computer-avatar-selector.component.html

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,53 @@
44
<div class="mat-body-2" [innerHtml]="computerAvatarSettings.prompt"></div>
55
<mat-divider />
66
}
7-
@if (avatars.length === 1) {
8-
<div class="mat-subtitle-2 accent" i18n>Your {{ label }}:</div>
9-
} @else {
7+
@if (selectedAvatar == null) {
108
<div class="mat-subtitle-2 accent" i18n>Choose Your {{ label }}:</div>
9+
<div class="flex flex-wrap mt-2">
10+
@for (avatar of avatars; track avatar.id) {
11+
<button
12+
class="avatar-button"
13+
matButton
14+
[value]="avatar"
15+
(click)="selectedAvatar = avatar"
16+
aria-label="{{ avatar.name }}"
17+
>
18+
<img [src]="avatarsPath + avatar.image" alt="{{ avatar.name }}" class="avatar-image" />
19+
<div class="name">
20+
<b>{{ avatar.name }}</b>
21+
</div>
22+
</button>
23+
}
24+
</div>
25+
} @else {
26+
<div class="mat-subtitle-2 accent" i18n>Your {{ label }}:</div>
27+
<span class="flex flex-col items-center">
28+
<img
29+
[src]="avatarsPath + selectedAvatar.image"
30+
alt="{{ selectedAvatar.name }}"
31+
class="selected-avatar-image"
32+
/>
33+
<div class="selected-avatar-name">
34+
<b>{{ selectedAvatar.name }}</b>
35+
</div>
36+
</span>
1137
}
12-
<mat-button-toggle-group
13-
[(ngModel)]="selectedAvatar"
14-
[disabled]="avatars.length === 1"
15-
class="flex flex-wrap"
16-
aria-label="Selected avatar"
17-
i18n-aria-label
18-
>
19-
@for (avatar of avatars; track avatar.id) {
20-
<mat-button-toggle
21-
[value]="avatar"
22-
(click)="selectedAvatar = avatar"
23-
aria-label="{{ avatar.name }}"
24-
>
25-
<img [src]="avatarsPath + avatar.image" alt="{{ avatar.name }}" class="avatar-image" />
26-
<div class="name">
27-
<b>{{ avatar.name }}</b>
28-
</div>
29-
</mat-button-toggle>
30-
}
31-
</mat-button-toggle-group>
3238
</mat-card-content>
33-
<mat-card-actions align="end">
34-
<button
35-
mat-flat-button
36-
color="primary"
37-
[disabled]="selectedAvatar == null"
38-
(click)="chooseAvatarEvent.emit(this.selectedAvatar)"
39-
i18n
40-
>
41-
Continue
42-
</button>
43-
</mat-card-actions>
39+
@if (selectedAvatar != null) {
40+
<mat-card-actions class="flex justify-end">
41+
@if (avatars.length > 1) {
42+
<button mat-flat-button (click)="selectedAvatar = null" i18n>Back</button>
43+
<span class="flex-grow"></span>
44+
}
45+
<button
46+
mat-flat-button
47+
color="primary"
48+
class="motion-safe:animate-bounce"
49+
(click)="chooseAvatarEvent.emit(this.selectedAvatar)"
50+
i18n
51+
>
52+
Chat with {{ selectedAvatar.name }}
53+
</button>
54+
</mat-card-actions>
55+
}
4456
</mat-card>

src/assets/wise5/vle/computer-avatar-selector/computer-avatar-selector.component.scss

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,36 +11,45 @@
1111
}
1212
}
1313

14-
/* TODO(mdc-migration): The following rule targets internal classes of button that may no longer apply for the MDC version. */
15-
.mat-button-toggle-group {
16-
border: 0 none;
17-
margin-top: 16px;
14+
.avatar-button{
15+
height: auto;
16+
text-transform: none;
1817
}
1918

20-
/* TODO(mdc-migration): The following rule targets internal classes of button that may no longer apply for the MDC version. */
21-
/* TODO(mdc-migration): The following rule targets internal classes of button that may no longer apply for the MDC version. */
22-
.mat-button-toggle-group-appearance-standard {
23-
/* TODO(mdc-migration): The following rule targets internal classes of button that may no longer apply for the MDC version. */
24-
.mat-button-toggle, .mat-button-toggle + .mat-button-toggle {
25-
border-left: 0 none;
26-
border-radius: variables.$card-border-radius;
27-
margin: 4px;
28-
}
19+
.avatar-image {
20+
width: 88px;
21+
height: auto;
22+
border-radius: 50%;
23+
padding: 8px 0;
2924
}
3025

31-
/* TODO(mdc-migration): The following rule targets internal classes of button that may no longer apply for the MDC version. */
32-
.mat-button-toggle-disabled.mat-button-toggle-checked {
33-
background-color: transparent;
26+
.name {
27+
line-height: 1;
28+
padding-bottom: 8px;
3429
}
3530

36-
.avatar-image {
37-
width: 88px;
31+
32+
.selected-avatar-image {
33+
width: 168px;
3834
height: auto;
3935
border-radius: 50%;
4036
padding: 8px 0;
4137
}
4238

43-
.name {
39+
.selected-avatar-name {
4440
line-height: 1;
4541
padding-bottom: 8px;
4642
}
43+
44+
@keyframes pulse {
45+
0%, 100% {
46+
transform: scale(1);
47+
}
48+
50% {
49+
transform: scale(1.06);
50+
}
51+
}
52+
53+
.pulse {
54+
animation: pulse 2s ease-in-out infinite;
55+
}

src/assets/wise5/vle/computer-avatar-selector/computer-avatar-selector.component.spec.ts

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,53 @@ describe('ComputerAvatarSelectorComponent', () => {
3333

3434
ngOnInit();
3535
selectAvatar();
36+
onlyOneAvatar();
3637
});
3738

39+
function onlyOneAvatar() {
40+
describe('only one avatar', () => {
41+
beforeEach(() => {
42+
component.computerAvatarSettings.ids = ['robot'];
43+
component.ngOnInit();
44+
fixture.detectChanges();
45+
});
46+
47+
it('should automatically select the avatar and only show the continue button', () => {
48+
expect(fixture.debugElement.queryAll(By.css('.avatar-button')).length).toEqual(0);
49+
expect(fixture.debugElement.query(By.css('.selected-avatar-image'))).toBeTruthy();
50+
expect(
51+
fixture.debugElement.query(By.css('.selected-avatar-name')).nativeElement.textContent.trim()
52+
).toEqual('Robot');
53+
54+
const backButton = fixture.debugElement
55+
.queryAll(By.css('button'))
56+
.find((btn) => btn.nativeElement.textContent.includes('Back'));
57+
58+
expect(getContinueButton()).toBeTruthy();
59+
expect(backButton).toBeUndefined();
60+
});
61+
62+
it('clicking continue should emit selected avatar', () => {
63+
const spy = spyOn(component.chooseAvatarEvent, 'emit');
64+
getContinueButton().nativeElement.click();
65+
fixture.detectChanges();
66+
expect(spy).toHaveBeenCalledWith(avatars[0]);
67+
});
68+
});
69+
}
70+
3871
function ngOnInit() {
3972
describe('ngOnInit()', () => {
40-
it('should show avatars and the continue button should be disabled', () => {
41-
expect(fixture.debugElement.queryAll(By.css('mat-button-toggle')).length).toEqual(2);
42-
expect(getContinueButton().nativeElement.disabled).toBeTrue();
73+
it('should show avatars', () => {
74+
expect(fixture.debugElement.queryAll(By.css('.avatar-button')).length).toEqual(2);
4375
});
4476
});
4577
}
4678

4779
function selectAvatar() {
4880
describe('select avatar', () => {
4981
beforeEach(() => {
50-
fixture.debugElement.queryAll(By.css('mat-button-toggle'))[0].nativeElement.click();
82+
fixture.debugElement.queryAll(By.css('.avatar-button'))[0].nativeElement.click();
5183
fixture.detectChanges();
5284
});
5385
it('should enable the continue button', () => {
@@ -72,5 +104,5 @@ function clickContinueButton_shouldEmitAvatar() {
72104
function getContinueButton() {
73105
return fixture.debugElement
74106
.queryAll(By.css('button'))
75-
.find((buttonDebugEl) => buttonDebugEl.nativeElement.textContent.includes('Continue'));
107+
.find((buttonDebugEl) => buttonDebugEl.nativeElement.textContent.includes('Chat with'));
76108
}

src/assets/wise5/vle/computer-avatar-selector/computer-avatar-selector.component.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
22
import { FormsModule } from '@angular/forms';
33
import { MatButtonModule } from '@angular/material/button';
44
import { MatCardModule } from '@angular/material/card';
5-
import { MatButtonToggleModule } from '@angular/material/button-toggle';
65
import { MatDividerModule } from '@angular/material/divider';
76
import { ComputerAvatar } from '../../common/computer-avatar/ComputerAvatar';
87
import { ComputerAvatarService } from '../../services/computerAvatarService';
98
import { ComputerAvatarSettings } from '../../common/computer-avatar/ComputerAvatarSettings';
109

1110
@Component({
12-
imports: [FormsModule, MatButtonModule, MatButtonToggleModule, MatCardModule, MatDividerModule],
11+
imports: [FormsModule, MatButtonModule, MatCardModule, MatDividerModule],
1312
selector: 'computer-avatar-selector',
1413
styleUrl: './computer-avatar-selector.component.scss',
1514
templateUrl: './computer-avatar-selector.component.html'

src/messages.xlf

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,6 +1551,10 @@ Click &quot;Cancel&quot; to keep the invalid JSON open so you can fix it.</sourc
15511551
<context context-type="sourcefile">src/assets/wise5/classroomMonitor/dataExport/export-student-work/export-student-work.component.html</context>
15521552
<context context-type="linenumber">7,10</context>
15531553
</context-group>
1554+
<context-group purpose="location">
1555+
<context context-type="sourcefile">src/assets/wise5/vle/computer-avatar-selector/computer-avatar-selector.component.html</context>
1556+
<context context-type="linenumber">42,46</context>
1557+
</context-group>
15541558
</trans-unit>
15551559
<trans-unit id="8132424293432274889" datatype="html">
15561560
<source> Back </source>
@@ -23294,32 +23298,25 @@ If this problem continues, let your teacher know and move on to the next activit
2329423298
<context context-type="linenumber">70,73</context>
2329523299
</context-group>
2329623300
</trans-unit>
23297-
<trans-unit id="5926207769041293626" datatype="html">
23298-
<source>Your <x id="INTERPOLATION" equiv-text="{{ label }}"/>:</source>
23299-
<context-group purpose="location">
23300-
<context context-type="sourcefile">src/assets/wise5/vle/computer-avatar-selector/computer-avatar-selector.component.html</context>
23301-
<context context-type="linenumber">8,9</context>
23302-
</context-group>
23303-
</trans-unit>
2330423301
<trans-unit id="2670863509967113900" datatype="html">
2330523302
<source>Choose Your <x id="INTERPOLATION" equiv-text="{{ label }}"/>:</source>
2330623303
<context-group purpose="location">
2330723304
<context context-type="sourcefile">src/assets/wise5/vle/computer-avatar-selector/computer-avatar-selector.component.html</context>
23308-
<context context-type="linenumber">10,12</context>
23305+
<context context-type="linenumber">8,9</context>
2330923306
</context-group>
2331023307
</trans-unit>
23311-
<trans-unit id="4626694020452925586" datatype="html">
23312-
<source>Selected avatar</source>
23308+
<trans-unit id="5926207769041293626" datatype="html">
23309+
<source>Your <x id="INTERPOLATION" equiv-text="{{ label }}"/>:</source>
2331323310
<context-group purpose="location">
2331423311
<context context-type="sourcefile">src/assets/wise5/vle/computer-avatar-selector/computer-avatar-selector.component.html</context>
23315-
<context context-type="linenumber">16,19</context>
23312+
<context context-type="linenumber">26,27</context>
2331623313
</context-group>
2331723314
</trans-unit>
23318-
<trans-unit id="2917314929120683887" datatype="html">
23319-
<source> Continue </source>
23315+
<trans-unit id="962551360143606449" datatype="html">
23316+
<source> Chat with <x id="INTERPOLATION" equiv-text="{{ selectedAvatar.name }}"/> </source>
2332023317
<context-group purpose="location">
2332123318
<context context-type="sourcefile">src/assets/wise5/vle/computer-avatar-selector/computer-avatar-selector.component.html</context>
23322-
<context context-type="linenumber">41,45</context>
23319+
<context context-type="linenumber">52,54</context>
2332323320
</context-group>
2332423321
</trans-unit>
2332523322
<trans-unit id="1098411996448900439" datatype="html">

0 commit comments

Comments
 (0)