Breadcrumbs Best Practice - Scola FE v2¶
Overview¶
Breadcrumbs harus hanya ada di topbar, bukan di content area halaman. Ini adalah best practice UI/UX yang memastikan navigasi konsisten di seluruh aplikasi.
❌ Anti-Pattern (JANGAN LAKUKAN INI)¶
<!-- SALAH: Breadcrumbs di content area -->
<template>
<AppLayout>
<div class="px-4 py-5">
<!-- ❌ Breadcrumbs di sini SALAH -->
<AppBreadcrumbs
:items="[
{ label: 'Home', href: '/home' },
{ label: 'Current Page', active: true }
]"
class="mb-4"
/>
<h1>Page Title</h1>
<!-- content -->
</div>
</AppLayout>
</template>
Masalah: - Breadcrumbs muncul 2x (topbar + content) - Tidak konsisten dengan halaman lain - Membuang space vertikal - Sulit maintenance (harus update di banyak tempat)
✅ Best Practice (LAKUKAN INI)¶
1. Topbar Otomatis (Menu-Based)¶
Breadcrumbs otomatis di-generate dari menu registry. Tidak perlu kode tambahan di halaman.
<!-- BENAR: Tidak ada breadcrumbs di content -->
<template>
<AppLayout>
<div class="px-4 py-5">
<!-- Langsung ke header, no breadcrumbs -->
<h1>Page Title</h1>
<!-- content -->
</div>
</AppLayout>
</template>
Cara kerja:
1. Topbar.vue otomatis render breadcrumbs
2. getBreadcrumbs() dari useMenuV2 mencari route di menu registry
3. Generate breadcrumb trail dari menu hierarchy
4. Semua breadcrumb item dapat diklik (kecuali halaman aktif/saat ini)
5. Halaman saat ini selalu ditampilkan di breadcrumb trail
2. Konfigurasi Menu Registry¶
Untuk breadcrumbs otomatis bekerja, route harus terdaftar di menuRegistry.js:
// src/config/menuRegistry.js
{
id: "library.catalog.view",
label: "Perpustakaan",
route: "/library/home",
capabilityKey: "library.catalog.view",
icon: Library,
order: 1,
// ✅ PENTING: Tambahkan relatedRoutes untuk sub-pages
relatedRoutes: [
"/library/catalog",
"/library/reservations",
"/library/loans",
"/library/wishlist",
"/library/reading-log",
"/library/purchase-requests"
],
}
Hasil breadcrumbs:
- /library/home → Sekolah > Perpustakaan
- /library/catalog → Sekolah > Perpustakaan > Katalog ✅ (current page shown)
- /library/loans → Sekolah > Perpustakaan > Daftar Pinjaman ✅ (current page shown)
Navigasi:
- Sekolah → Clickable, navigasi ke home
- Perpustakaan → Clickable, navigasi ke /library/home
- Katalog → Not clickable (current page, shown in bold)
3. Custom Breadcrumbs (Untuk Halaman Detail)¶
Jika perlu custom breadcrumbs (misal: halaman detail dengan data dinamis):
<script setup>
import { useBreadcrumbs } from '@/composables/useBreadcrumbs';
import { onMounted, onUnmounted } from 'vue';
const { setBreadcrumbs, clearBreadcrumbs } = useBreadcrumbs();
onMounted(async () => {
// Fetch data dulu
const student = await fetchStudent(id);
// Set custom breadcrumbs
setBreadcrumbs([
{ label: 'Data Siswa', href: '/students' },
{ label: student.name, active: true }
]);
});
onUnmounted(() => {
clearBreadcrumbs(); // Optional, auto-clear saat route berubah
});
</script>
Implementasi Pattern¶
Step 1: Hapus Breadcrumbs dari Content¶
# Cari semua file dengan AppBreadcrumbs di content area
grep -r "AppBreadcrumbs" src/views/
Untuk setiap file:
1. Hapus <AppBreadcrumbs /> component dari template
2. Hapus import AppBreadcrumbs dari script
3. Hapus breadcrumb items array jika ada
Step 2: Update Menu Registry¶
Untuk setiap menu entry yang punya sub-pages:
{
id: "menu.parent",
label: "Parent Menu",
route: "/parent",
// Tambahkan relatedRoutes untuk semua sub-pages
relatedRoutes: [
"/parent/sub1",
"/parent/sub2",
"/parent/sub3"
],
}
Step 3: Verifikasi¶
- Buka halaman di browser
- Cek breadcrumbs di topbar (bukan di content)
- Navigasi ke sub-pages, breadcrumbs harus update otomatis
- Tidak ada breadcrumbs duplikat
Troubleshooting¶
Breadcrumbs tidak muncul di topbar¶
Penyebab: Route tidak terdaftar di menu registry
Solusi:
1. Cek menuRegistry.js untuk role yang sesuai
2. Pastikan route ada di menu entry atau relatedRoutes
3. Pastikan user punya capability yang sesuai
Breadcrumbs lompat-lompat / tidak runtut¶
Penyebab: relatedRoutes tidak lengkap atau salah
Solusi:
1. Tambahkan semua sub-routes ke relatedRoutes array
2. Pastikan path exact match (case-sensitive)
3. Gunakan absolute path, bukan relative
Breadcrumbs tidak update saat navigasi¶
Penyebab: Custom breadcrumbs tidak di-clear
Solusi:
// Pastikan clear di onUnmounted
onUnmounted(() => {
clearBreadcrumbs();
});
// Atau gunakan watcher di useBreadcrumbs (sudah otomatis)
Migration Checklist¶
Untuk migrate existing pages:
- [ ] Hapus
<AppBreadcrumbs />dari template - [ ] Hapus
import AppBreadcrumbsdari script - [ ] Hapus breadcrumb items array/data
- [ ] Update
menuRegistry.jsdenganrelatedRoutes - [ ] Test breadcrumbs di topbar
- [ ] Verify navigation flow
- [ ] Commit dengan message yang jelas
Contoh Implementasi¶
Before (❌ Anti-pattern)¶
<template>
<AppLayout>
<div class="px-4 py-5">
<AppBreadcrumbs
:items="[
{ label: 'Perpustakaan', href: '/library/home' },
{ label: 'Katalog', active: true }
]"
class="mb-4"
/>
<h1>Katalog Perpustakaan</h1>
</div>
</AppLayout>
</template>
<script setup>
import AppBreadcrumbs from '@/components/ui/AppBreadcrumbs.vue';
</script>
After (✅ Best practice)¶
<template>
<AppLayout>
<div class="px-4 py-5">
<!-- No breadcrumbs here! -->
<h1>Katalog Perpustakaan</h1>
</div>
</AppLayout>
</template>
<script setup>
// No AppBreadcrumbs import needed
</script>
// menuRegistry.js
{
id: "library.catalog.view",
label: "Perpustakaan",
route: "/library/home",
relatedRoutes: ["/library/catalog"], // ✅ Added
}
How Breadcrumbs Work as Navigation¶
Smart Breadcrumb Generation¶
getBreadcrumbs() in useMenuV2.js intelligently generates breadcrumb trails:
-
Exact Match: Route directly in menu → Simple trail
/library/home → Sekolah > Perpustakaan -
Related Route Match: Route in
relatedRoutes→ Enhanced trail/library/catalog → Sekolah > Perpustakaan > Katalog
Process:
- Match parent via relatedRoutes
- Check if child exists in menu
- If not, create breadcrumb from routeMap
- Add to trail: parent + current page
- Route Label Mapping: For routes not in menu structure
const routeMap = { '/library/catalog': 'Katalog', '/library/loans': 'Daftar Pinjaman', '/library/wishlist': 'Daftar Keinginan', // etc. };
Clickable Navigation¶
All breadcrumb items are clickable except the current page:
Home > Perpustakaan > Katalog
✓ ✓ ✗
click click (current)
AppBreadcrumbs.vue handles:
- Blue links for clickable items (href provided)
- Bold text for current page (active: true)
- Proper routing via router.push()
Key Properties¶
Breadcrumb items have:
- label: Display text
- href: Navigation target (null for current page)
- active: Boolean (true for current page)
Example:
[
{ label: 'Sekolah', href: '/faculty/home', active: false },
{ label: 'Perpustakaan', href: '/library/home', active: false },
{ label: 'Katalog', href: null, active: true }
]
Benefits¶
- Konsistensi: Breadcrumbs selalu di tempat yang sama (topbar)
- Maintainability: Single source of truth (menu registry)
- DRY: Tidak perlu duplicate breadcrumb logic di setiap halaman
- UX: Standard pattern yang familiar untuk users
- Performance: Tidak render breadcrumbs 2x
- Navigation: Breadcrumbs berfungsi sebagai alat navigasi yang sebenarnya
- Context: User selalu tahu posisi mereka di aplikasi
References¶
src/components/Topbar.vue- Topbar component dengan breadcrumbssrc/composables/useMenuV2.js- Menu system dengangetBreadcrumbs()src/composables/useBreadcrumbs.js- Custom breadcrumbs composablesrc/config/menuRegistry.js- Menu configurationsrc/components/ui/AppBreadcrumbs.vue- Breadcrumbs component
Last Updated: 2026-03-01
Author: Scola Development Team