Episode ini membahas accessibility dan UX: atribut ARIA dan navigasi keyboard, markup semantik dan form yang aksesibel, responsive layout dan dukungan mobile, serta internationalization dan localization.

Aplikasi yang baik bisa dipakai oleh semua orang — termasuk pengguna screen reader, pengguna keyboard, dan perangkat dengan layar kecil. Accessibility bukan fitur opsional; ia standar kualitas.
Episode 17 membahas atribut ARIA dan navigasi keyboard, markup semantik dan form yang aksesibel, responsive layout dan dukungan mobile, serta internationalization dan localization. Aksesibilitas yang baik hampir selalu meningkatkan UX untuk semua orang.
ARIA (Accessible Rich Internet Applications) memberi informasi tambahan ke assistive technology. Angular Material dan CDK sudah memakai ARIA secara internal; komponen custom perlu menyetelnya sendiri:
<button
(click)="bukaMenu()"
aria-haspopup="true"
[attr.aria-expanded]="menuTerbuka">
Menu
</button>aria-haspopup memberi tahu screen reader bahwa tombol membuka menu, sementara [attr.aria-expanded] menyatakan status buka-tutup yang mengikuti state menuTerbuka. Angular mengikat atribut ARIA lewat [attr.*].
Aplikasi harus bisa dioperasikan sepenuhnya dengan keyboard: Tab berpindah fokus, Enter atau Space mengaktifkan, dan Escape menutup. CDK a11y menyediakan FocusTrap, FocusMonitor, dan LiveAnnouncer:
import { Component, inject } from '@angular/core';
import { LiveAnnouncer } from '@angular/cdk/a11y';
@Component({ selector: 'app-notif', standalone: true, template: `` })
export class NotifComponent {
private readonly announcer = inject(LiveAnnouncer);
kirimPesan(pesan: string): void {
this.announcer.announce(pesan, 'polite');
}
}LiveAnnouncer.announce membacakan pesan secara lisan untuk pengguna screen reader tanpa mengganggu alur fokus. Pola ini penting saat konten berubah secara dinamis — misalnya status "Data berhasil disimpan".
Screen reader menavigasi berdasarkan struktur. Gunakan elemen semantik: header, nav, main, h1 sampai h6, button, a, dan label — bukan div dengan role manual. Judul harus membentuk hierarki yang logis.
Setiap input harus punya label yang terasosiasi. Tanpa label, pengguna screen reader tidak tahu apa yang harus diisi:
<div>
<label for="email">Alamat email</label>
<input id="email" type="email" [attr.aria-invalid]="email.invalid && email.touched" />
</div>label[for] dan input[id] menghubungkan keduanya. aria-invalid memberi tahu assistive technology bahwa input bermasalah. Hindari placeholder sebagai satu-satunya label — placeholder menghilang saat mengetik dan kontrasnya sering rendah.
Hubungkan pesan error dengan input memakai aria-describedby:
<input id="email" aria-describedby="errEmail" />
<small id="errEmail" role="alert">Format email tidak valid</small>aria-describedby="errEmail" membuat screen reader membacakan pesan error tersebut ketika input difokus. Ini membuat validasi tidak hanya terlihat, tetapi juga terdengar.
Mulai dari ukuran layar kecil, lalu tingkatkan untuk layar besar. CSS grid dan flexbox dengan unit relatif seperti rem dan % membuat layout mengikuti ukuran viewport:
.kartu-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 16px;
}repeat(auto-fit, minmax(240px, 1fr)) membuat grid otomatis menyesuaikan jumlah kolom dengan lebar layar — satu kolom di ponsel, beberapa kolom di desktop, tanpa media query untuk setiap breakpoint.
Perhatikan ukuran target sentuh minimal 44 piksel, hindari hover sebagai satu-satunya cara mengakses fungsi, dan uji di browser mobile yang nyata. Gunakan Angular CDK BreakpointObserver untuk logika layout yang perlu tahu ukuran layar:
import { Component, inject, signal } from '@angular/core';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
@Component({ selector: 'app-layout', standalone: true, template: `` })
export class LayoutComponent {
private readonly observer = inject(BreakpointObserver);
readonly isMobile = signal(false);
constructor() {
this.observer.observe([Breakpoints.Handset]).subscribe((state) => {
this.isMobile.set(state.matches);
});
}
}Breakpoints.Handset bernilai true saat viewport berupa ponsel. Hasilnya bisa mengubah menu, jumlah kolom, atau tata letak panel secara reaktif.
Angular i18n memakai paket @angular/localize. Tambahkan ke project:
ng add @angular/localizeSetelah itu, tandai teks yang perlu diterjemahkan dengan atribut i18n:
<h1 i18n>Selamat datang di toko online</h1>
<p i18n>Belanja mudah dan aman</p>i18n menandai teks agar bisa diekstrak ke file terjemahan. Jalankan perintah extract untuk menghasilkan file sumber terjemahan:
ng extract-i18n --output-path src/localePerintah ini menghasilkan messages.xlf yang dikirim ke penerjemah. Setelah terjemahan tersedia, aplikasi di-build per bahasa dengan --localize.
Bangun aplikasi untuk beberapa bahasa sekaligus:
ng build --localizeHasilnya folder terpisah per bahasa di dist. Angular juga menyediakan pipe DatePipe dan CurrencyPipe yang menyesuaikan format dengan locale aktif — jadi angka dan tanggal tampil sesuai kebiasaan setempat.
Inti yang harus dibawa pulang:
aria-describedby dan role="alert" menyampaikan error ke screen reader.auto-fit dan BreakpointObserver menghadirkan layout responsif.ng add @angular/localize mengaktifkan dukungan i18n.ng build --localize menghasilkan build terpisah per bahasa.Di episode 18 selanjutnya kita akan membahas architecture dan patterns — feature modules dan modular architecture, shared, core, dan lazy modules, domain-driven design dengan struktur folder yang scalable, serta clean architecture dan separation of concerns.