29 KiB
Vera Design System Guidelines
Master Order Dashboard Design Reference
Version: 1.0
Last Updated: January 2026
Reference Implementation: Bill Tracking Dashboard
This document captures all design patterns, colors, typography, and component styles used in the Bill Tracking Dashboard. Use this as a reference when building new dashboards to maintain consistency.
Table of Contents
- Theme System
- Color Palette
- Typography
- Spacing System
- Border & Shadows
- Odoo Navigation Bar
- Dashboard Header Bar
- Component Library
- Layout Patterns
- Responsive Design
- Icons
- Interactive States
- Code Snippets
1. Theme System
1.1 CSS Variables
All theme colors are defined as CSS variables in master_order_theme_variables.scss:
:root {
// Primary Colors (change per theme)
--mo-theme-primary: #4682B4;
--mo-theme-primary-dark: #3A6D99;
--mo-theme-primary-light: #5B9BD5;
--mo-theme-primary-pale: #E8F4FC;
// Background Colors
--mo-theme-background: #F9FAFB;
--mo-theme-card-bg: #FFFFFF;
--mo-theme-border: #D9D9D9;
// Text Colors
--mo-theme-text: #1d1d1f;
--mo-theme-text-muted: #86868b;
}
1.2 Available Themes
| Theme Name | Primary | Background | Use Case |
|---|---|---|---|
| Vera Blue Eye | #4682B4 |
#F9FAFB |
Default, eye-friendly |
| Vera Excel | #23764A |
#FFFFFF |
Excel-like, pure white |
| Ocean Teal | #017e84 |
#F8F9FA |
Odoo Enterprise style |
1.3 Theme Switcher Component
<!-- Theme Switcher Dots -->
<div class="btd-theme-switcher">
<button class="btd-theme-dot btd-theme-blue-eye"
title="Vera Blue Eye"
t-on-click="() => this.setTheme('vera_blue_eye')"/>
<button class="btd-theme-dot btd-theme-excel"
title="Vera Excel"
t-on-click="() => this.setTheme('vera_excel')"/>
<button class="btd-theme-dot btd-theme-teal"
title="Ocean Teal"
t-on-click="() => this.setTheme('ocean_teal')"/>
</div>
1.4 Using Theme Variables
Always use CSS variables instead of hardcoded colors:
// ✅ GOOD - Theme aware
.my-element {
color: var(--mo-theme-primary);
background: var(--mo-theme-background);
border: 1px solid var(--mo-theme-border);
}
// ❌ BAD - Hardcoded
.my-element {
color: #4682B4;
background: #F9FAFB;
}
2. Color Palette
2.1 Primary Theme Colors
| Variable | Vera Blue Eye | Vera Excel | Ocean Teal |
|---|---|---|---|
--mo-theme-primary |
#4682B4 |
#23764A |
#017e84 |
--mo-theme-primary-dark |
#3A6D99 |
#1A5A38 |
#015d62 |
--mo-theme-primary-light |
#5B9BD5 |
#2D8F5E |
#02a5ad |
--mo-theme-primary-pale |
#E8F4FC |
#E8F5ED |
#E8F8F9 |
2.2 Status Colors
| Status | Dot Color | Badge Background | Text Color |
|---|---|---|---|
| Paid | #34c759 |
#d4edda |
#155724 |
| Partial | var(--mo-theme-primary) |
--mo-theme-primary-pale |
--mo-theme-primary |
| Not Paid | #ff3b30 |
#f8d7da |
#721c24 |
| Pending | #ff9500 |
#fff3cd |
#856404 |
2.3 Background Colors
| Element | Color | Usage |
|---|---|---|
| Page Background | var(--mo-theme-background) |
Main dashboard background |
| Card Background | var(--mo-theme-card-bg) / #FFFFFF |
All cards |
| Hover Background | rgba(0,0,0,0.02) |
Row hover states |
| Input Background | #f5f5f7 |
Form inputs, badges |
2.4 Semantic Colors
// Success (Green)
$color-success: #34c759;
$color-success-bg: #d4edda;
$color-success-text: #155724;
// Warning (Yellow/Orange)
$color-warning: #ff9500;
$color-warning-bg: #fff3cd;
$color-warning-text: #856404;
// Danger (Red)
$color-danger: #ff3b30;
$color-danger-bg: #f8d7da;
$color-danger-text: #721c24;
// Muted (Gray)
$color-muted: #86868b;
$color-muted-bg: #f5f5f7;
3. Typography
3.1 Font Stack
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, sans-serif;
3.2 Font Sizes
| Element | Size | Weight | Line Height |
|---|---|---|---|
| Page Title | 28px |
600 | 1.2 |
| Subtitle | 13px |
400 | 1.4 |
| Card Value (Large) | 24px |
600 | 1.2 |
| Card Label | 12px |
500 | 1.4 |
| Card Sub-text | 11px |
400 | 1.4 |
| Customer Name | 16px |
600 | 1.3 |
| Bill Number | 13px |
600 | 1.4 |
| Badge Text | 11px |
500 | 1 |
| Small Text | 10px |
400 | 1.4 |
3.3 Text Colors
| Type | Color | Usage |
|---|---|---|
| Primary Text | #1d1d1f |
Headlines, important values |
| Secondary Text | #86868b |
Labels, descriptions |
| Muted Text | #6c757d |
Hints, timestamps |
| Link Text | var(--mo-theme-primary) |
Clickable elements |
| Danger Text | #ff3b30 |
Negative values, warnings |
| Success Text | #34c759 |
Positive values |
4. Spacing System
4.1 Base Units
Use multiples of 4px for consistency:
| Name | Size | Usage |
|---|---|---|
xs |
4px |
Icon margins, tight gaps |
sm |
8px |
Badge padding, small gaps |
md |
12px |
Component gaps |
lg |
16px |
Section gaps |
xl |
24px |
Card padding, grid gaps |
2xl |
32px |
Section margins |
3xl |
48px |
Major section breaks |
4.2 Page Layout
.dashboard {
padding: 32px 40px 240px 40px; // Top Right Bottom Left
// Note: 240px bottom for generous scroll space
}
4.3 Card Spacing
.summary-card {
padding: 20px;
gap: 24px; // Grid gap between cards
margin-bottom: 48px; // Before divider
}
.customer-card {
padding: 20px;
gap: 16px; // Between elements inside
}
5. Border & Shadows
5.1 Border Radius
| Element | Radius |
|---|---|
| Cards (Summary/Customer) | 16px |
| Buttons | 8px |
| Badges | 6px |
| Progress Bars | 4px |
| Small Elements | 4px |
5.2 Border Color
border: 1px solid var(--mo-theme-border, #D9D9D9);
5.3 Shadows
| State | Shadow |
|---|---|
| Default Card | 0 2px 12px rgba(0, 0, 0, 0.03) |
| Hover Card | 0 8px 24px rgba(70, 130, 180, 0.15) |
| Elevated | 0 4px 20px rgba(0, 0, 0, 0.04) |
5.4 Dividers
// Section Divider
&::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 1px;
background: var(--mo-theme-border, #D9D9D9);
}
6. Odoo Navigation Bar
The main Odoo navigation bar (top menu) follows the theme colors for a cohesive branded experience.
6.1 Navigation Bar Structure
┌─────────────────────────────────────────────────────────────────────────────┐
│ [App Icon] Master Orders │ Dashboard │ Bill Tracking │ ... │ + │ 🔔 │ User │
└─────────────────────────────────────────────────────────────────────────────┘
6.2 Navigation Bar Colors
| Element | Color |
|---|---|
| Background | var(--mo-theme-primary-dark) |
| Text | rgba(255, 255, 255, 0.85) |
| Hover Background | var(--mo-theme-primary) |
| Active Menu Item | var(--mo-theme-primary) |
6.3 Navigation Bar SCSS Override
// Override Odoo's default navbar to follow Master Order theme
.o_main_navbar {
background-color: var(--mo-theme-primary-dark) !important;
border-bottom: 1px solid var(--mo-theme-primary-dark) !important;
// App name/brand
.o_menu_brand {
color: white !important;
&:hover {
background-color: var(--mo-theme-primary) !important;
}
}
// Menu items
.o_menu_sections .o_nav_entry {
color: rgba(255, 255, 255, 0.85) !important;
&:hover, &:focus, &.active {
background-color: var(--mo-theme-primary) !important;
color: white !important;
}
}
// Dropdown menus
.dropdown-menu {
background-color: var(--mo-theme-primary-dark) !important;
border: 1px solid var(--mo-theme-primary) !important;
.dropdown-item {
color: rgba(255, 255, 255, 0.85) !important;
&:hover {
background-color: var(--mo-theme-primary) !important;
color: white !important;
}
}
}
// Right side icons (systray)
.o_menu_systray .o_nav_entry {
color: rgba(255, 255, 255, 0.85) !important;
&:hover {
background-color: var(--mo-theme-primary) !important;
}
}
}
6.4 Theme Color on Navigation
| Theme | Nav Background | Nav Hover |
|---|---|---|
| Vera Blue Eye | #3A6D99 |
#4682B4 |
| Vera Excel | #1A5A38 |
#23764A |
| Ocean Teal | #015d62 |
#017e84 |
6.5 Important Note
The navigation bar uses !important to override Odoo's default styles. This ensures our theme colors take precedence.
7. Dashboard Header Bar
The header bar is a consistent element across all dashboards. It should always follow the theme colors.
6.1 Header Bar Structure
<div class="dashboard-header">
<div class="header-left">
<h2 class="title">
<i class="fa fa-icon"/> Page Title
</h2>
<span class="subtitle">Description text</span>
</div>
<div class="header-right">
<!-- Filters -->
<div class="filters">
<label class="filter-toggle">
<input type="checkbox"/> Filter Label
</label>
</div>
<!-- Theme Switcher -->
<div class="theme-switcher">...</div>
<!-- Refresh Button -->
<button class="refresh-btn">
<i class="fa fa-refresh"/> Refresh
</button>
<!-- View Toggle -->
<div class="view-toggle">
<button class="btn-grid"><i class="fa fa-th-large"/></button>
<button class="btn-list"><i class="fa fa-list"/></button>
</div>
</div>
</div>
6.2 Header Bar Styling
.dashboard-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 32px;
padding: 16px 20px;
background: var(--mo-theme-card-bg, white);
border: 1px solid var(--mo-theme-border, #D9D9D9);
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}
6.3 Title with Icon Box
.title {
font-size: 24px;
font-weight: 600;
color: var(--mo-theme-text, #1d1d1f);
display: flex;
align-items: center;
i {
color: var(--mo-theme-primary);
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
background: var(--mo-theme-primary-pale);
border-radius: 10px;
margin-right: 12px;
font-size: 22px;
}
}
.subtitle {
font-size: 13px;
color: var(--mo-theme-text-muted, #86868b);
margin-top: 4px;
margin-left: 52px; // Align with title text (after icon)
}
6.4 Filter Toggle
.filter-toggle {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
font-size: 12px;
color: var(--mo-theme-text-muted);
padding: 6px 12px;
background: var(--mo-theme-primary-pale);
border-radius: 6px;
border: 1px solid var(--mo-theme-border, #D9D9D9);
&:hover {
border-color: var(--mo-theme-primary);
}
input[type="checkbox"] {
width: 16px;
height: 16px;
accent-color: var(--mo-theme-primary);
}
}
6.5 Refresh Button
.refresh-btn {
border-radius: 6px;
padding: 6px 12px;
font-size: 12px;
border: 1px solid var(--mo-theme-primary);
color: var(--mo-theme-primary);
background: transparent;
&:hover {
background: var(--mo-theme-primary);
color: white;
}
i {
margin-right: 4px;
}
}
6.6 View Toggle
.view-toggle {
display: flex;
gap: 2px;
background: var(--mo-theme-primary-pale);
padding: 3px;
border-radius: 8px;
border: 1px solid var(--mo-theme-border, #D9D9D9);
.btn {
padding: 6px 12px;
border-radius: 6px;
border: none;
font-size: 12px;
// Inactive state
&.btn-outline-secondary {
background: transparent;
color: var(--mo-theme-text-muted);
&:hover {
background: rgba(255,255,255,0.7);
color: var(--mo-theme-primary);
}
}
// Active state
&.btn-primary {
background: linear-gradient(135deg,
var(--mo-theme-primary) 0%,
var(--mo-theme-primary-light) 100%);
color: white;
box-shadow: 0 2px 8px rgba(70, 130, 180, 0.25);
}
}
}
6.7 Theme Switcher Dots
.theme-switcher {
display: flex;
align-items: center;
gap: 6px;
padding: 4px 8px;
background: rgba(0, 0, 0, 0.04);
border-radius: 20px;
.theme-dot {
width: 18px;
height: 18px;
border-radius: 50%;
cursor: pointer;
transition: transform 0.2s ease, box-shadow 0.2s ease;
padding: 0;
&:hover {
transform: scale(1.2);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
// Each theme has gradient showing primary + background
&.theme-blue-eye {
background: linear-gradient(135deg, #4682B4 60%, #F9FAFB 100%);
border: 1px solid #4682B4;
}
&.theme-excel {
background: linear-gradient(135deg, #23764A 60%, #FFFFFF 100%);
border: 1px solid #23764A;
}
&.theme-teal {
background: linear-gradient(135deg, #017e84 60%, #F8F9FA 100%);
border: 1px solid #017e84;
}
}
}
8. Component Library
6.1 Summary Cards
.summary-card {
display: flex;
flex-direction: column;
align-items: flex-start;
padding: 20px;
background: var(--mo-theme-card-bg, white);
border-radius: 16px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.04);
border: 1px solid var(--mo-theme-border, #D9D9D9);
}
.summary-card-icon {
width: 44px;
height: 44px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, var(--mo-theme-primary-pale) 0%, white 100%);
color: var(--mo-theme-primary);
font-size: 18px;
}
.summary-card-value {
font-size: 24px;
font-weight: 600;
color: #1d1d1f;
}
.summary-card-label {
font-size: 12px;
font-weight: 500;
color: #86868b;
}
.summary-card-sub {
font-size: 11px;
color: #86868b;
}
6.2 Customer/Entity Cards
.entity-card {
background: var(--mo-theme-card-bg, white);
border-radius: 16px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.03);
border: 1px solid var(--mo-theme-border, #D9D9D9);
padding: 20px;
cursor: pointer;
transition: all 0.3s ease;
&:hover {
box-shadow: 0 8px 24px rgba(70, 130, 180, 0.15);
border-color: var(--mo-theme-primary);
}
}
6.3 Status Badges (Dot Style)
.status-badge {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 11px;
font-weight: 500;
white-space: nowrap;
&::before {
content: "●";
font-size: 8px;
}
// Paid - Green
&.badge-paid {
color: #34c759;
&::before { color: #34c759; }
}
// Partial - Theme Primary
&.badge-partial {
color: var(--mo-theme-primary);
&::before { color: var(--mo-theme-primary); }
}
// Not Paid - Red
&.badge-not_paid {
color: #ff3b30;
&::before { color: #ff3b30; }
}
// Pending - Orange
&.badge-pending {
color: #ff9500;
&::before { color: #ff9500; }
}
}
6.4 Logistics Badges (Pill Style)
.logistics-badge {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 3px 10px;
border-radius: 6px;
font-size: 11px;
font-weight: 500;
white-space: nowrap;
// Default (CTN count)
background: #f5f5f7;
color: #6c757d;
// Sent - Green
&.badge-sent {
background: #d4edda;
color: #155724;
}
// Remain - Yellow (if has value)
&.badge-remain.has-value {
background: #fff3cd;
color: #856404;
}
// Remain - Gray (if zero)
&.badge-remain {
background: #f5f5f7;
color: #6c757d;
}
}
6.5 Progress Bars
.progress-bar-container {
height: 4px;
background: #f2f2f7;
border-radius: 4px;
overflow: hidden;
}
.progress-bar-fill {
height: 100%;
border-radius: 4px;
transition: width 0.3s ease;
// Default - Theme Primary
background: linear-gradient(90deg,
var(--mo-theme-primary) 0%,
var(--mo-theme-primary-light) 100%);
// 100% - Green
&.complete {
background: linear-gradient(90deg, #34c759 0%, #30d158 100%);
}
}
.progress-label {
font-size: 10px;
color: var(--mo-theme-primary);
margin-top: 4px;
}
6.6 Buttons
// Primary Action Button
.btn-primary-action {
background: linear-gradient(135deg,
var(--mo-theme-primary) 0%,
var(--mo-theme-primary-light) 100%);
color: white;
border: none;
border-radius: 8px;
padding: 8px 16px;
font-size: 12px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
&:hover {
background: linear-gradient(135deg,
var(--mo-theme-primary-dark) 0%,
var(--mo-theme-primary) 100%);
box-shadow: 0 4px 12px rgba(70, 130, 180, 0.3);
}
}
// Icon Button
.btn-icon {
width: 28px;
height: 28px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
background: transparent;
border: 1px solid #e5e5ea;
color: #86868b;
cursor: pointer;
transition: all 0.2s ease;
&:hover {
background: #f5f5f7;
color: var(--mo-theme-primary);
}
}
7. Layout Patterns
7.1 Dashboard Structure
<div class="dashboard">
<!-- Header -->
<div class="dashboard-header">
<div class="header-left">
<h2 class="title"><i class="fa fa-icon"/> Title</h2>
<span class="subtitle">Description text</span>
</div>
<div class="header-right">
<!-- Filters, Theme Switcher, View Toggle -->
</div>
</div>
<!-- Summary Cards -->
<div class="summary-cards-grid">
<!-- 5-6 summary cards -->
</div>
<!-- Divider (CSS ::after) -->
<!-- Main Content -->
<div class="content-grid">
<!-- Entity cards or list view -->
</div>
</div>
7.2 Grid Layouts
// Summary Cards Grid
.summary-cards-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 24px;
}
// Entity Cards Grid
.entity-cards-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 16px;
}
7.3 Card Internal Layout
// Two-row layout for bill items
.bill-row {
display: flex;
flex-direction: column;
gap: 8px;
padding: 12px;
.bill-top {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.bill-bottom {
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
flex-wrap: wrap;
}
}
8. Responsive Design
8.1 Breakpoints
| Name | Width | Target |
|---|---|---|
| Desktop | > 1024px |
Full layout |
| Tablet | 768px - 1024px |
Reduced columns |
| Mobile | 480px - 768px |
Stacked layout |
| Small Mobile | < 480px |
Minimal layout |
8.2 Responsive SCSS
// Tablet
@media (max-width: 1024px) {
.dashboard {
padding: 24px 24px 200px 24px;
}
.summary-cards-grid {
grid-template-columns: repeat(3, 1fr);
}
}
// Mobile
@media (max-width: 768px) {
.dashboard {
padding: 16px 16px 180px 16px;
}
.summary-cards-grid {
grid-template-columns: repeat(2, 1fr);
gap: 12px;
}
.entity-cards-grid {
grid-template-columns: 1fr;
}
}
// Small Mobile
@media (max-width: 480px) {
.summary-cards-grid {
grid-template-columns: 1fr;
}
.card-value {
font-size: 20px;
}
}
8.3 Scrolling Setup
// Override Odoo container restrictions
.o_action_manager,
.o_action_manager > .o_action,
.o_view_manager_content,
.o_content {
overflow-y: auto !important;
overflow-x: hidden !important;
height: auto !important;
max-height: none !important;
}
// Dashboard wrapper
.dashboard {
min-height: 100vh;
height: auto !important;
overflow: visible !important; // Let parent scroll
}
9. Icons
9.1 Icon Library
Using Font Awesome 4.x (available in Odoo).
9.2 Common Icons
| Use Case | Icon | Class |
|---|---|---|
| Money/Amount | 💰 | fa-money |
| Paid/Success | ✓ | fa-check-circle |
| Outstanding | ⊘ | fa-exclamation-circle |
| Delayed/Time | ⏱ | fa-clock-o |
| Shipping/CTN | 📦 | fa-cubes |
| Truck/Sent | 🚚 | fa-truck |
| CBM/Volume | ⬛ | fa-cube |
| Remain/Inbox | 📥 | fa-inbox |
| Bill/Document | 📄 | fa-file-text-o |
| User/Customer | 👤 | fa-user |
| Vendor | 🏢 | fa-building |
| Payment | 💳 | fa-credit-card |
| View/Eye | 👁 | fa-eye |
| Refresh | 🔄 | fa-refresh |
| Expand/Collapse | ▼▲ | fa-chevron-down / fa-chevron-up |
| Grid View | ⊞ | fa-th-large |
| List View | ☰ | fa-list |
9.3 Icon Styling
.icon {
font-size: 18px;
color: var(--mo-theme-primary);
// In badges
&.badge-icon {
font-size: 10px;
margin-right: 4px;
}
// In card headers
&.card-icon {
width: 44px;
height: 44px;
display: flex;
align-items: center;
justify-content: center;
background: var(--mo-theme-primary-pale);
border-radius: 12px;
}
}
10. Interactive States
10.1 Hover States
// Card Hover
.card:hover {
box-shadow: 0 8px 24px rgba(70, 130, 180, 0.15);
border-color: var(--mo-theme-primary);
}
// Row Hover
.row:hover {
background: rgba(0, 0, 0, 0.02);
}
// Button Hover
.btn:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
// Link Hover
a:hover {
color: var(--mo-theme-primary-dark);
text-decoration: underline;
}
10.2 Transitions
// Standard transition
transition: all 0.3s ease;
// Smooth cubic bezier
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
// Quick transition (buttons)
transition: all 0.2s ease;
10.3 Focus States
// Accessible focus
:focus {
outline: 2px solid var(--mo-theme-primary);
outline-offset: 2px;
}
// Focus within cards
.card:focus-within {
border-color: var(--mo-theme-primary);
}
11. Code Snippets
11.1 Complete Summary Card
<div class="btd-card btd-card-blue">
<div class="btd-card-icon">
<i class="fa fa-money"></i>
</div>
<div class="btd-card-content">
<span class="btd-card-value">
<t t-esc="formatCurrency(state.summary.totalAmount)"/>
</span>
<span class="btd-card-label">Total Amount</span>
<span class="btd-card-sub">
<t t-esc="state.summary.count"/> items
</span>
</div>
</div>
11.2 Complete Entity Card
<div class="btd-vendor-card" t-on-click="() => this.toggleEntity(entity.id)">
<!-- Header -->
<div class="btd-card-header">
<div class="btd-vendor-info">
<i class="fa fa-user"></i>
<span class="btd-vendor-name"><t t-esc="entity.name"/></span>
</div>
<span t-attf-class="btd-status-badge btd-badge-#{entity.status}">
<t t-esc="getStatusLabel(entity.status)"/>
</span>
</div>
<!-- Financial Section -->
<div class="btd-financial-section">
<div class="btd-financial-value text-danger">
<t t-esc="formatCurrency(entity.outstanding)"/>
</div>
<div class="btd-financial-label">Outstanding</div>
<!-- Progress Bar -->
<div class="btd-progress-simple">
<div class="progress">
<div class="progress-bar" t-attf-style="width: #{entity.paidPct}%"/>
</div>
<span class="btd-progress-label">
<t t-esc="entity.paidPct"/>% paid
</span>
</div>
</div>
<!-- Logistics Section -->
<div class="btd-logistics-summary">
<div class="btd-logistics-item">
<i class="fa fa-truck"/>
<strong><t t-esc="entity.sentCtn"/></strong> / <t t-esc="entity.totalCtn"/> CTN
</div>
</div>
<!-- Expand Icon -->
<div class="btd-card-expand">
<i t-attf-class="fa #{isExpanded(entity.id) ? 'fa-chevron-up' : 'fa-chevron-down'}"/>
</div>
</div>
11.3 Complete Bill Row
<div class="btd-bill-row">
<!-- Top: Bill Info + Amount -->
<div class="btd-bill-top">
<div class="btd-bill-info">
<a class="btd-bill-name" t-on-click.stop="() => this.openBill(bill.id)">
<t t-esc="bill.name"/>
</a>
<span class="btd-bill-ref"><t t-esc="bill.reference"/></span>
<span class="btd-bill-date"><t t-esc="formatDate(bill.date)"/></span>
</div>
<div class="btd-bill-financial">
<span class="btd-bill-total"><t t-esc="formatCurrency(bill.total)"/></span>
<span class="btd-bill-outstanding text-danger">
<t t-esc="formatCurrency(bill.outstanding)"/> owed
</span>
</div>
</div>
<!-- Bottom: Status + Logistics + Actions -->
<div class="btd-bill-bottom">
<div class="btd-bill-status">
<span t-attf-class="btd-bill-badge badge-#{bill.status}">
<t t-esc="getStatusLabel(bill.status)"/>
</span>
</div>
<div class="btd-bill-logistics">
<span class="btd-logistics-stat">
<i class="fa fa-cubes"/> <t t-esc="bill.ctn"/> CTN
</span>
<span class="btd-logistics-stat btd-sent">
<i class="fa fa-truck"/> Sent: <t t-esc="bill.sent"/>
</span>
<span t-attf-class="btd-logistics-stat btd-remain #{bill.remain > 0 ? 'has-remain' : ''}">
<i class="fa fa-inbox"/> Remain: <t t-esc="bill.remain"/>
</span>
</div>
<div class="btd-bill-actions">
<button class="btn btd-pay-btn" title="Pay">
<i class="fa fa-credit-card"/>
</button>
<button class="btn btn-outline-secondary" title="View">
<i class="fa fa-eye"/>
</button>
</div>
</div>
</div>
11.4 Theme Setter JavaScript
async setTheme(themeName) {
// Apply immediately
document.documentElement.setAttribute('data-mo-theme', themeName);
document.body?.setAttribute('data-mo-theme', themeName);
localStorage.setItem('mo_theme', themeName);
// Save to backend
if (window.moTheme) {
await window.moTheme.setTheme(themeName);
}
}
Quick Reference Card
Colors to Remember
| Purpose | Color |
|---|---|
| Border | #D9D9D9 |
| Background (Eye-friendly) | #F9FAFB |
| Card Background | #FFFFFF |
| Muted Text | #86868b |
| Primary Text | #1d1d1f |
| Success Green | #34c759 |
| Warning Yellow | #ff9500 |
| Danger Red | #ff3b30 |
Sizes to Remember
| Element | Size |
|---|---|
| Card Border Radius | 16px |
| Button Border Radius | 8px |
| Badge Border Radius | 6px |
| Card Padding | 20px |
| Grid Gap | 16px - 24px |
| Page Bottom Padding | 240px |
Files to Update
| Component | File |
|---|---|
| Theme Variables | static/src/scss/master_order_theme_variables.scss |
| Dashboard Styles | static/src/scss/[dashboard_name]_dashboard.scss |
| Templates | static/src/xml/[dashboard_name]_templates.xml |
| JavaScript | static/src/js/[dashboard_name]_dashboard.js |
| Python Model | models/res_users.py (for theme field) |
This design system ensures visual consistency across all Master Order dashboards.