Skip to content

Commit

Permalink
feat(profile): make easter egg accessible
Browse files Browse the repository at this point in the history
displays "huh" photo version when passing by the element again
says a message about passing by again instead
  • Loading branch information
davidlj95 committed Sep 22, 2023
1 parent 886bde7 commit f82c992
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 9 deletions.
10 changes: 8 additions & 2 deletions src/app/about/profile-picture/profile-picture.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@
height="128" ngSrc="assets/img/profile_huh.png" width="128">
<img alt="A portrait of {{ realName }}. Slightly smiling. Wears 80'ish glasses and a green and black plaid shirt"
class="main"
height="128" ngSrc="assets/img/profile.png" priority width="128">
height="128" ngSrc="assets/img/profile.png" priority width="128" [tabindex]="hasBeenFocused ? -1 : 0"
(focus)="onFocus()">
<div class="comment">
Hey! 👋 Did you <span class="touch">tap</span><span class="hover">hover</span> me?
<span aria-hidden="true">
Hey! 👋 Did you <span class="touch">tap</span><span class="hover">hover</span> me?
</span>
<span class="sr-only">
Hey! 👋 Nice to see you again
</span>
</div>
5 changes: 4 additions & 1 deletion src/app/about/profile-picture/profile-picture.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ $picture-size: 128px;
right: 0;
bottom: 0;
opacity: 0;
visibility: hidden;
}

.comment {
Expand Down Expand Up @@ -90,7 +91,7 @@ $picture-size: 128px;
}
}

&:hover {
&:hover, &[data-has-been-focused]:focus {
.comment {
visibility: visible;
opacity: 1;
Expand All @@ -105,10 +106,12 @@ $picture-size: 128px;

.main {
opacity: 0;
visibility: hidden;
}

.huh {
opacity: 1;
visibility: visible;
}
}
}
48 changes: 44 additions & 4 deletions src/app/about/profile-picture/profile-picture.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { DebugElement } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';

Expand All @@ -9,31 +10,70 @@ describe('ProfilePictureComponent', () => {

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ProfilePictureComponent]
declarations: [ProfilePictureComponent],
});
fixture = TestBed.createComponent(ProfilePictureComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
const PROFILE_PIC_MAIN_SELECTOR = By.css('img.main')
const PROFILE_PIC_HUH_SELECTOR = By.css('img.huh')

it('should create', () => {
expect(component).toBeTruthy();
});

it('should display profile picture', () => {
const profilePic = fixture.debugElement.query(By.css('img.main'));
const profilePic = fixture.debugElement.query(PROFILE_PIC_MAIN_SELECTOR);
expect(profilePic).toBeTruthy();
expect(profilePic.attributes['ngSrc']).toBeDefined();
expect(profilePic.attributes['ngSrc']).toContain('profile.png');
})

it('should display "huh" profile picture hidden', () => {
const huhProfilePic = fixture.debugElement.query(By.css('img.huh'));
it('should contain "huh" profile picture, despite hidden', () => {
const huhProfilePic = fixture.debugElement.query(PROFILE_PIC_HUH_SELECTOR);
expect(huhProfilePic).toBeTruthy();
expect(huhProfilePic.attributes['ngSrc']).toBeDefined();
expect(huhProfilePic.attributes['ngSrc']).toContain('profile_huh.png');
const styles = getComputedStyle(huhProfilePic.nativeElement);
expect(styles).toBeTruthy();
expect(styles.opacity).toEqual('0');
expect(styles.visibility).toEqual('hidden');
})

describe('accessible easter egg', () => {
describe('initially', () => {
it('component should not have has been focused attribute', () => {
expect(fixture.debugElement.attributes[ProfilePictureComponent.HAS_BEEN_FOCUSED_ATTR]).toBeUndefined()
})
// We don't receive focus events if including whole component in tab sequence
it('component as a whole should not be in tab sequence', () => {
expect(fixture.debugElement.attributes['tabindex']).toBe('-1')
})
// So we include profile picture instead
it('main profile pic should be in tab sequence', () => {
const profilePic = fixture.debugElement.query(PROFILE_PIC_MAIN_SELECTOR);
expect(profilePic.attributes['tabindex']).toBe('0')
})
})
describe('after profile picture has received focus at least one', () => {
let profilePicEl: DebugElement

beforeEach(() => {
profilePicEl = fixture.debugElement.query(PROFILE_PIC_MAIN_SELECTOR)
profilePicEl.triggerEventHandler('focus')
fixture.detectChanges()
})

it('component should have has been focused attribute', () => {
expect(fixture.debugElement.attributes[ProfilePictureComponent.HAS_BEEN_FOCUSED_ATTR]).toBe(true.toString())
})
it('component should be included in tab sequence', () => {
expect(fixture.debugElement.attributes['tabindex']).toBe('0')
})
it('profile pic should no longer be in tab sequence', () => {
expect(profilePicEl.attributes['tabindex']).toBe('-1')
})
})
})
});
21 changes: 19 additions & 2 deletions src/app/about/profile-picture/profile-picture.component.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,34 @@
import { Component, Inject } from '@angular/core';
import { Component, HostBinding, Inject } from '@angular/core';
import { METADATA } from '../../common/injection-tokens';
import { Metadata } from '../../metadata';

@Component({
selector: 'app-profile-picture',
templateUrl: './profile-picture.component.html',
styleUrls: ['./profile-picture.component.scss']
styleUrls: ['./profile-picture.component.scss'],
})
export class ProfilePictureComponent {
protected realName: string = this.metadata.realName;
protected _hasBeenFocused= false;

public static HAS_BEEN_FOCUSED_ATTR = 'data-has-been-focused'

@HostBinding(`attr.${ProfilePictureComponent.HAS_BEEN_FOCUSED_ATTR}`) public get hasBeenFocused() {
return this._hasBeenFocused ? true : undefined
}

@HostBinding('attr.tabindex') public get tabIndex() {
return this.hasBeenFocused ? 0 : -1
}

@HostBinding('attr.aria-label') public ariaLabel = 'Profile picture'

constructor(
@Inject(METADATA) private metadata: Metadata,
) {
}

onFocus() {
this._hasBeenFocused = true
}
}

0 comments on commit f82c992

Please sign in to comment.