π’ Opening With a Question
Ever wondered how to build a sleek, accessible star rating component in Angular that users and screen readers will love?
Whether you're designing a review system or collecting user feedback, a star rating component is a UI staple. But creating one thatβs reusable, accessible, responsive, and powered by Angularβs latest features like Signals takes your development skills to the next level.
By the end of this tutorial, youβll learn:
- β How to create a reusable Angular component with Signals
- π·οΈ Best practices for accessibility (ARIA roles, keyboard navigation)
- π‘ Styling tips to make your rating UI shine
- π¦ How to use the component across apps and modules
π§ 1. Project Setup (Angular 18 + Signals)
Make sure you're on Angular 18+. If not, upgrade:
ng update @angular/cli @angular/core
Generate your component:
ng generate component shared/star-rating
We'll use @angular/core
βs new Signals API to handle the reactive logic cleanly and declaratively.
β 2. Component Structure
Here's what the star-rating component structure looks like:
@Component({
selector: 'app-star-rating',
templateUrl: './star-rating.component.html',
styleUrls: ['./star-rating.component.scss'],
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class StarRatingComponent {
readonly stars = 5;
readonly rating = signal(0);
readonly hovered = signal<number | null>(null);
setRating = (value: number) => this.rating.set(value);
setHover = (value: number | null) => this.hovered.set(value);
}
Use signals
for both rating state and hover effectsβclean and reactive with no RxJS needed.
π¨ 3. HTML Template with Accessibility (ARIA)
Hereβs the accessible and interactive template:
<div
role="radiogroup"
aria-label="Star rating"
class="star-rating"
>
<ng-container *ngFor="let star of [].constructor(stars); let i = index">
<span
role="radio"
tabindex="0"
[attr.aria-checked]="rating() === i + 1"
(click)="setRating(i + 1)"
(keydown.enter)="setRating(i + 1)"
(mouseenter)="setHover(i + 1)"
(mouseleave)="setHover(null)"
[class.filled]="i < (hovered() ?? rating())"
>
β
</span>
</ng-container>
</div>
π¬ Pro Tip: Always use role="radiogroup" for screen reader clarity and tabindex for keyboard focus.
π§ͺ 4. Styling (SCSS)
Give your stars a professional look:
.star-rating {
display: flex;
gap: 0.5rem;
span {
font-size: 2rem;
cursor: pointer;
color: #ccc;
transition: color 0.2s;
&.filled {
color: #f5b301;
}
&:focus {
outline: 2px solid #007acc;
outline-offset: 2px;
}
}
}
βΏ 5. Accessibility Checklist
- β
role="radiogroup"
on container - β
role="radio"
on stars - β
aria-checked
state - β Keyboard navigation (Enter key)
- β Focus outline for better visibility
π§© 6. Making It Reusable
Allow @Input()
s for max stars and readonly mode:
@Input({ required: true }) stars = 5;
@Input() readonly = false;
@Output() ratingChange = new EventEmitter<number>();
Update the template logic for readonly
:
(click)="!readonly && setRating(i + 1)"
π 7. Bonus: Add This to a Shared Library
If you're using Nx or a mono-repo setup, move this to a ui-components
library to share it across multiple Angular apps.
β What Youβve Learned
By now, youβve built a signal-powered, accessible, and reusable star rating component that is:
- π Reactive with Angular Signals
- βΏ Fully accessible with ARIA roles
- π Reusable across components/modules
- π± Stylish and responsive
π― Your Turn, Devs!
π Did this article spark new ideas or help solve a real problem?
π¬ I'd love to hear about it!
β Are you already using this technique in your Angular or frontend project?
π§ Got questions, doubts, or your own twist on the approach?
Drop them in the comments below β letβs learn together!
π Letβs Grow Together!
If this article added value to your dev journey:
π Share it with your team, tech friends, or community β you never know who might need it right now.
π Save it for later and revisit as a quick reference.
π Follow Me for More Angular & Frontend Goodness:
I regularly share hands-on tutorials, clean code tips, scalable frontend architecture, and real-world problem-solving guides.
- πΌ LinkedIn β Letβs connect professionally
- π₯ Threads β Short-form frontend insights
- π¦ X (Twitter) β Developer banter + code snippets
- π₯ BlueSky β Stay up to date on frontend trends
- π GitHub Projects β Explore code in action
- π Website β Everything in one place
- π Medium Blog β Long-form content and deep-dives
- π¬ Dev Blog β Free Long-form content and deep-dives
- βοΈ Substack β Weekly frontend stories & curated resources
- π§© Portfolio β Projects, talks, and recognitions
π If you found this article valuable:
- Leave a π Clap
- Drop a π¬ Comment
- Hit π Follow for more weekly frontend insights
Letβs build cleaner, faster, and smarter web apps β together.
Stay tuned for more Angular tips, patterns, and performance tricks! π§ͺπ§ π
** β¨ Share Your Thoughts To π£ Set Your Notification Preference **
Top comments (0)