Skip to content

Instantly share code, notes, and snippets.

@urish
Created April 7, 2017 04:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save urish/5f5474ad721113f26388773115bf1bfc to your computer and use it in GitHub Desktop.
Save urish/5f5474ad721113f26388773115bf1bfc to your computer and use it in GitHub Desktop.
Star Rating Component - Accessible
.star {
display: inline-block;
margin-right: 2px;
}
.full-star {
fill: yellow;
}
<span (mouseleave)="reset()" tabindex="0"
(keydown)="onKeydown($event)" role="slider"
[attr.aria-label]="ariaLabel"
aria-valuemin="0"
[attr.aria-valuemax]="stars.length"
[attr.aria-valuenow]="value">
<i *ngFor="let s of stars; let i = index" class="star"
(mouseenter)="enter(i + 1)" (click)="rate(i + 1)">
<svg width="20" height="20">
<path d="m 15.81,20 -6.06,-3.42 -6.26,3.06 1.38,-6.83 -4.84,-5.01 6.92,-0.79 3.27,-6.15 2.89,6.33 6.86,1.21 -5.13,4.71 z"
fill="transparent" stroke="#f7993d" stroke-width="1"
[class.full-star]="i < value"/>
</svg>
</i>
</span>
import { Component, Output, EventEmitter } from '@angular/core';
const STAR_COUNT = 5;
@Component({
selector: 'app-star-rating',
templateUrl: './star-rating.component.html',
styleUrls: ['./star-rating.component.css']
})
export class StarRatingComponent {
@Output() rated = new EventEmitter<number>();
stars = new Array(STAR_COUNT);
value: number;
private lastValue: number;
rate(value: number) {
this.value = value;
this.lastValue = value;
this.rated.emit(value);
}
enter(value: number) {
this.value = value;
}
reset() {
this.value = this.lastValue;
}
onKeydown(evt: KeyboardEvent) {
const KEY_LEFT = 37;
const KEY_UP = 38;
const KEY_RIGHT = 39;
const KEY_DOWN = 40;
const keyCode = evt.which;
const validKeys = [KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT];
if (validKeys.indexOf(keyCode) >= 0) {
evt.preventDefault();
evt.stopPropagation();
const currentValue = this.value || 0;
switch (keyCode) {
case KEY_UP: case KEY_RIGHT:
this.rate(Math.min(currentValue + 1, STAR_COUNT));
break;
case KEY_DOWN: case KEY_LEFT:
this.rate(Math.max(1, currentValue - 1));
break;
}
}
}
get ariaLabel(): string {
if (this.value) {
return this.value === 1 ? '1 star' : `${this.value} stars`;
} else {
return 'No rating';
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment