Scola-FE-V2 UI Design Pattern & Styles (SSOT)¶
This document establishes the official Single Source of Truth (SSOT) for UI design patterns in the Scola-FE-V2 repository. By following these guidelines, we ensure consistency, cross-mode visibility (Light/Dark Mode), and maintainability across all module boundaries.
1. Banner Systems & Gradient Layouts¶
Gradient banners give areas like Dashboards or Admission Landing a premium feel. However, embedding content inside them requires care for Light/Dark mode resilience.
a. Gradient Guidelines¶
- Primary Gradients: Use
bg-linear-to-rorbg-linear-to-br. Avoid generic solid colors. - Palette Matching:
- Educational/Core (Teachers/Students):
from-blue-600 to-indigo-600orfrom-sky-500 to-blue-600. - Homeroom/Class Specific:
from-indigo-500 to-purple-600. - Action/Highlights:
from-emerald-500 to-teal-600.
b. Translucency & Contrast Rules (The Visibility Bug Fix)¶
If a container inherits text colors (like text-white inside a banner), never use opaque backgrounds (e.g. bg-white) for nested container elements (like badges or icon wrappers). Doing so results in invisible white-on-white text in light mode.
- Use Translucent Backgrounds: Use
bg-white/20along withdark:bg-slate-800/20inside gradient banners. - Example Pattern:
<!-- Outer Banner --> <div class="bg-linear-to-r from-blue-600 to-indigo-600 p-6 text-white rounded-3xl"> <!-- Inner Item Wrapper --> <div class="w-14 h-14 rounded-2xl bg-white/20 dark:bg-slate-800/20 flex flex-center"> <GraduationCap class="w-7 h-7 text-white" /> </div> </div>
2. Layout Rules: Pages & Sections¶
- AppLayout: Always wrap main application routes within the
<AppLayout>component. - TopbarMobile: Always implement a topbar for mobile compatibility with
<template #topbar>. - Page Spacing: Utilize
px-4 py-5 md:px-6 md:py-7for standard container padding. - Headers & Titles: Standardize page headers with
flex items-center gap-3 mb-5. Give titles thetruncateclass to prevent flex-box overflow issues on narrow screens.
3. UI Cards & Content Organization¶
- Cards: Use
<AppCard>for standardization, otherwise follow this pattern:bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 p-4. - Lists: When displaying list items, structure rows with Flexbox (
flex items-start justify-between). Separate metadata into a column:<div class="flex items-start justify-between mb-2"> <div> <h4 class="font-medium text-slate-800 dark:text-slate-200 text-sm">Title</h4> <p class="text-xs text-slate-500 dark:text-slate-400">Subtitle</p> </div> <AppBadge color="sky" size="sm">Active</AppBadge> </div>
4. Status Badges & Motivations¶
- AppBadge: Use
<AppBadge>for statuses (color="sky" | "emerald" | "amber" | "rose"). - Custom Badges: If crafting a custom label format, adhere strictly to semantic light/dark states:
- Backgrounds:
bg-blue-50 dark:bg-blue-900/20. - Borders:
border border-blue-200 dark:border-blue-800/50. - Text:
text-blue-700 dark:text-blue-400.
5. UI States (Empty, Loading, Error)¶
Consistent communication of system states improves UX. All states should be centered.
a. Loading State¶
Always use the Loader2 from lucide-vue-next with the animate-spin class and a sky-blue hue.
<div class="flex items-center justify-center py-20 text-center">
<Loader2 :size="32" class="animate-spin text-sky-500 mx-auto mb-3" />
<p class="text-sm text-slate-500 dark:text-slate-400">Memuat data...</p>
</div>
b. Empty State¶
Use distinct visual elements (large tinted box) and descriptive guidance rather than a simple "Data empty":
<div class="text-center py-16">
<div class="w-20 h-20 rounded-full bg-slate-100 dark:bg-slate-700 flex flex-center mx-auto mb-4">
<FileX :size="40" class="text-slate-400 dark:text-slate-500" />
</div>
<h3 class="text-lg font-semibold text-slate-700 dark:text-slate-300 mb-2">Belum ada tugas</h3>
<p class="text-sm text-slate-500 dark:text-slate-400 max-w-sm mx-auto">
Tugas yang dikumpulkan akan muncul di sini.
</p>
</div>
c. Error State¶
Make errors visually distinct using red palettes. Provide actionable buttons to re-fetch if possible.
<div class="text-center py-12">
<div class="w-20 h-20 mx-auto mb-4 rounded-3xl bg-red-100 flex items-center justify-center">
<AlertCircle :size="36" class="text-red-600" />
</div>
<h3 class="text-lg font-bold text-slate-900 dark:text-slate-100 mb-2">Gagal Memuat</h3>
<p class="text-sm text-slate-500 dark:text-slate-400 mt-1">{{ error }}</p>
</div>
Quick Checklist for New Features¶
- [ ] Did you use
bg-white/20inside gradient containers? - [ ] Does the page display loading, empty, and proper error states?
- [ ] Are semantic colors (Amber = Warning/Pending, Emerald = Success, Rose = Danger) respected?
- [ ] Did you implement Dark Mode classes (e.g.
dark:bg-slate-800,dark:text-slate-300) on all typography?