Skip to content

Dashboard Layout Pattern

The MetrePay portal dashboard uses a fixed sidebar + main content layout. It is the primary interface for merchants managing their payment operations.


Structure

┌──────────────────────────────────────────────────┐
│  ┌──────────┐  ┌────────────────────────────┐    │
│  │          │  │  Top bar                   │    │
│  │ Sidebar  │  ├────────────────────────────┤    │
│  │ (230px)  │  │  Stats row (4 cols)        │    │
│  │          │  ├────────────────────────────┤    │
│  │ Logo     │  │  Main content area         │    │
│  │ Nav      │  │  (tables, cards, etc.)     │    │
│  │ items    │  │                            │    │
│  │          │  │                            │    │
│  └──────────┘  └────────────────────────────┘    │
└──────────────────────────────────────────────────┘

CSS Implementation

/* =============================================
   DASHBOARD LAYOUT
   ============================================= */

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  font-family: 'Cabin', sans-serif;
  background: #F1F1F1;
  min-height: 100vh;
}

/* Sidebar */
.sidebar {
  width: 230px;
  height: 100vh;
  position: fixed;
  top: 0;
  left: 0;
  background: #FFFFFF;
  border-right: 1px solid #E5ECFB;
  display: flex;
  flex-direction: column;
  z-index: 100;
  transition: transform 0.3s ease-in-out;
}

.sidebar__logo {
  padding: 20px 24px;
  border-bottom: 1px solid #E5ECFB;
}

.sidebar__logo img {
  height: 32px;
}

.sidebar__nav {
  flex: 1;
  padding: 16px 0;
  overflow-y: auto;
}

.sidebar__nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 24px;
  font-size: 14px;
  font-weight: 500;
  color: #666666;
  text-decoration: none;
  transition: all 0.2s ease;
  border-left: 3px solid transparent;
}

.sidebar__nav-item:hover {
  background: #EBF0FF;
  color: #6E96FF;
}

.sidebar__nav-item--active {
  background: #EBF0FF;
  color: #6E96FF;
  font-weight: 600;
  border-left-color: #6E96FF;
}

.sidebar__nav-section {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #999999;
  padding: 16px 24px 8px;
}

/* Main content */
.main-content {
  margin-left: 230px;
  min-height: 100vh;
}

/* Top bar */
.topbar {
  background: #FFFFFF;
  border-bottom: 1px solid #E5ECFB;
  padding: 0 32px;
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: sticky;
  top: 0;
  z-index: 50;
}

.topbar__title {
  font-size: 18px;
  font-weight: 700;
  color: #333333;
}

.topbar__actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* Page content */
.page-content {
  padding: 32px;
}

/* Stats row */
.stats-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  margin-bottom: 32px;
}

/* Content card */
.content-card {
  background: #FFFFFF;
  border-radius: 10px;
  box-shadow: 0px 0px 6px 3px rgba(127, 146, 189, 0.1);
  overflow: hidden;
}

.content-card__header {
  padding: 16px 24px;
  border-bottom: 1px solid #E5ECFB;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.content-card__title {
  font-size: 16px;
  font-weight: 600;
  color: #333333;
}

.content-card__body {
  padding: 0;
}

/* Table */
.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

.data-table th {
  padding: 12px 24px;
  text-align: left;
  font-size: 12px;
  font-weight: 600;
  color: #999999;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-bottom: 1px solid #E5ECFB;
  background: #FAFAFA;
}

.data-table td {
  padding: 14px 24px;
  color: #555555;
  border-bottom: 1px solid #E5ECFB;
}

.data-table tr:last-child td {
  border-bottom: none;
}

.data-table tr:hover td {
  background: #FAFAFA;
}

/* Mobile: sidebar slides in */
@media (max-width: 768px) {
  .sidebar {
    transform: translateX(-230px);
  }

  .sidebar--open {
    transform: translateX(0);
    box-shadow: 4px 0 20px rgba(0,0,0,0.1);
  }

  .main-content {
    margin-left: 0;
  }

  .page-content {
    padding: 20px;
  }

  .stats-row {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 480px) {
  .stats-row {
    grid-template-columns: 1fr;
  }
}

<nav class="sidebar__nav">
  <span class="sidebar__nav-section">Overview</span>
  <a href="#" class="sidebar__nav-item sidebar__nav-item--active">
    📊 Dashboard
  </a>
  <a href="#" class="sidebar__nav-item">
    💳 Payments
  </a>
  <a href="#" class="sidebar__nav-item">
    🔄 Subscriptions
  </a>

  <span class="sidebar__nav-section">Catalog</span>
  <a href="#" class="sidebar__nav-item">
    📦 Products
  </a>
  <a href="#" class="sidebar__nav-item">
    🔗 Payment Links
  </a>

  <span class="sidebar__nav-section">Settings</span>
  <a href="#" class="sidebar__nav-item">
    ⚙️ Configuration
  </a>
  <a href="#" class="sidebar__nav-item">
    👤 Account
  </a>
</nav>

Rules

Dashboard rules

  • Sidebar width: always 230px on desktop
  • Sidebar background: white with right border #E5ECFB
  • Active nav item: blue left border + blue text + blue light background
  • Top bar: white, sticky, 60px height
  • Page content padding: 32px on desktop, 20px on mobile
  • Stats row: 4 columns on desktop, 2 on tablet, 1 on mobile
  • Data tables: always inside a white content card with shadow
  • Table header: #FAFAFA background, uppercase, muted text