.NET Assemblies  

Building a Dynamic, Dataverse‑Driven Leadership Component in Power Pages

In many enterprise portals, the Leadership or Management Team section is among the most frequently visited sections. Yet organizations often struggle to maintain this content due to hardcoded HTML, scattered data sources, or a dependence on developers for even minor updates.

To address this, I recently built a fully dynamic Leadership component in Power Pages, backed entirely by Microsoft Dataverse — no hardcoding, no manual content updates, no duplication.

This approach combines the best of low-code configurability with professional-grade UI, making the component both robust and business-friendly.

🎯 Objective

Create a reusable, responsive, modern Leadership section that enables business teams to easily manage content while delivering a rich, tab-based presentation layer in Power Pages.

Designer (1)

✨ Key Features

1. Dataverse Powered (OOB FetchXML)

All leadership data (Board, Executive members, designations, images, descriptions) is stored in Dataverse tables.

Using server-side FetchXML, the component retrieves and loads content dynamically:

  • No need to modify HTML

  • Centralized data management

  • Fast and secure

2. Dynamic Rendering with Liquid Templates

Liquid templates make the UI completely dynamic.

Power Pages Liquid allows logic like:

  • Fetching leadership profiles

  • Filtering by category (Board/Executive)

  • Rendering content loops dynamically

This ensures the portal updates itself instantly whenever data changes.

3. Tab-Based Leadership Navigation

A sleek tabbed interface enables users to switch between:

  • Board Leadership

  • Executive Leadership

Smooth transitions are handled with minimal JavaScript while the content itself is generated server-side.

leadership

4. Premium Custom UI with CSS

To ensure a modern, enterprise-ready experience, custom CSS styling was applied:

  • Card‑based layouts

  • Circular profile images

  • Clean typography

  • Hover effects

  • Responsive grids

  • Mobile optimizations

The result is a visually polished, corporate-grade section that feels native to any modern website.

/* site.css — Blue & White theme, footer pinned, no HTML changes */

/* ===== Design tokens ===== */
:root{
  /* Brand blues */
  --brand-50:#f0f7ff;
  --brand-100:#e3f0ff;
  --brand-400:#4ea3ff;
  --brand-600:#0a66c2;       /* primary */
  --brand-700:#0a57a3;

  /* Neutral surfaces */
  --bg:#f6f8fb;              /* page background */
  --surface:#ffffff;         /* cards, header */
  --surface-2:#ffffff;       /* tables */
  --border:#e6e9ef;          /* subtle borders */

  /* Text colors */
  --text:#14213d;            /* primary text */
  --muted:#5e6b7e;           /* secondary text */

  /* States */
  --success:#14853f;
  --danger:#b42318;
  --focus:#22c1ff;

  --shadow: 0 10px 24px rgba(20, 33, 61, .08);
}

/* ===== Reset ===== */
*{box-sizing:border-box}
html,body{margin:0;padding:0}

/* ===== Sticky footer layout ===== */
html, body { height: 100%; }
body{
  min-height:100%;
  display:flex;
  flex-direction:column;
  background:
    radial-gradient(1200px 600px at 0% 0%, #ffffff 0%, var(--bg) 65%),
    radial-gradient(900px 300px at 100% 0%, #ffffff 0%, var(--bg) 60%);
  color:var(--text);
  font-family: Inter, system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
  letter-spacing:.2px;
  line-height:1.55;
}
::selection{background:var(--brand-600);color:#fff}

/* ===== Containers ===== */
.container{max-width:1100px;margin:0 auto;padding:24px}
main.container{flex:1 0 auto}

/* ===== Header ===== */



.header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: linear-gradient(180deg, var(--brand-700), rgba(255,255,255,.92));
  border-bottom: 1px solid var(--border);
  box-shadow: 0 4px 14px rgba(10,38,97,.06);
  backdrop-filter: saturate(140%) blur(6px);
}



.header .nav{
  display:flex;
  gap: 6px;
  align-items:center;
  min-height: 64px;
}
.header .brand{
  font-weight: 900;
  color: #0a2e61;
  letter-spacing: .2px;
  padding: 10px 12px;
  border-radius: 10px;
}
.header .nav a{
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--muted);
  padding: 10px 12px;
  border-radius: 10px;
  font-weight: 600;
  letter-spacing: .1px;
  transition: color .2s ease, background .2s ease, box-shadow .2s ease;
}
.header .nav a:hover{
  color:#0a2e61;
  background: #ecf5ff;
}
.header .nav a::after{
  content:"";
  position:absolute; left: 10px; right: 10px; bottom: 6px;
  height: 3px; border-radius: 3px;
  background: linear-gradient(90deg, var(--brand-700), var(--brand-600));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .18s ease;
  opacity: .9;
}
.header .nav a:hover::after{ transform: scaleX(1); }
.header .nav a.active{
  color:#0a2e61;
  background:#eaf3ff;
  box-shadow: inset 0 0 0 1px #d7e7ff, 0 6px 12px rgba(10,90,180,.10);
}
.header .nav a.active::after{ transform: scaleX(1); }
.header .nav a:focus-visible{
  box-shadow: 0 0 0 3px rgba(34,193,255,.35);
}
.header .spacer{ flex: 1; }
.header .nav .btn.secondary{
  margin-left: 4px;
  background: #ffffff;
  color: #0a2e61;
  border-color: #d9e2ef;
  box-shadow: 0 3px 10px rgba(20,33,61,.08);
}
.header .nav .btn.secondary:hover{ background:#f5f9ff; }
.header::after{
  content:"";
  display:block;
  height: 1px;
  background: linear-gradient(90deg, transparent, #cfe2ff, transparent);
}
@media (max-width: 980px){
  .header .nav{ flex-wrap: wrap; row-gap: 8px; }
  .header .spacer{ display: none; }
}
@media (max-width: 540px){
  .header .nav a{ padding: 8px 10px; }
}

/* ===== Cards ===== */
.card{
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:16px;
  padding:18px;
  box-shadow:var(--shadow);
}
.card h1,.card h2,.card h3{margin:0 0 10px 0;color:#0a2e61}
.card p{color:#334155}
.card ul{margin:8px 0 0 18px}

/* ===== Grid ===== */
.grid{display:grid;gap:18px}
.grid.cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}
.grid.cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}
@media(max-width:900px){.grid.cols-3{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:640px){.grid.cols-2,.grid.cols-3{grid-template-columns:1fr}}

/* ===== Buttons ===== */
.btn{
  display:inline-flex; align-items:center; gap:8px;
  padding:10px 14px; border-radius:12px; font-weight:700;
  border:1px solid transparent; cursor:pointer;
  transition:transform .05s ease, box-shadow .2s ease, background .2s ease, color .2s;
}
.btn:active{transform:translateY(1px)}
.btn.primary{
  background:linear-gradient(135deg, var(--brand-700), var(--brand-600));
  color:#fff;
  box-shadow:0 10px 16px rgba(10,102,194,.20);
}
.btn.primary:hover{filter:brightness(1.06)}
.btn.secondary{
  background:#ffffff; border-color:#d9e2ef; color:#0a2e61;
  box-shadow:0 2px 8px rgba(20,33,61,.06)
}
.btn.secondary:hover{background:#f5f8fc}
.btn.link{background:transparent;color:var(--brand-700);padding:0;border:none}

/* ===== Tables ===== */
.table{
  width:100%; border-collapse:separate; border-spacing:0;
  background:var(--surface-2);
  border:1px solid var(--border); border-radius:14px; overflow:hidden;
  box-shadow:var(--shadow)
}
.table thead th{
  background:#f4f9ff; color:#0a2e61; text-transform:uppercase;
  font-size:12px; letter-spacing:.5px; padding:12px; border-bottom:1px solid var(--border)
}
.table tbody td{padding:12px;border-top:1px solid var(--border);color:#1f2937}
.table tbody tr:hover{background:#f9fbff}

/* ===== Badges ===== */
.badge{
  display:inline-block; padding:4px 10px; border-radius:999px;
  font-size:12px; font-weight:700;
  background:#eef6ff; color:#0a2e61; border:1px solid #dbe7ff;
}

/* ===== Forms ===== */
.label{font-size:13px;color:var(--muted);margin-bottom:6px;display:block}
.input,select,textarea{
  width:100%; padding:12px; border:1px solid var(--border); border-radius:12px;
  background:#ffffff; color:#0a2e61; outline:none; transition:border .2s, box-shadow .2s;
}
.input::placeholder,textarea::placeholder{color:#9aa3af}
.input:focus,select:focus,textarea:focus{
  border-color:var(--focus);
  box-shadow:0 0 0 3px rgba(34,193,255,.25);
}
[aria-invalid="true"]{
  border-color:var(--danger);
  box-shadow:0 0 0 3px rgba(180,35,24,.20);
}
.form-row{display:grid;grid-template-columns:1fr 1fr;gap:18px}
@media(max-width:640px){.form-row{grid-template-columns:1fr}}

/* ===== Alerts ===== */
.alert{
  padding:12px 14px; border-radius:12px;
  background:linear-gradient(180deg, #fff7ed, #fff4e6);
  border:1px solid #ffe0b3; color:#7a2e0e
}

/* ===== Footer ===== */
.footer{
  flex-shrink:0;
  color:var(--muted);
  font-size:13px;
  padding:28px 0;
  border-top:1px solid var(--border);
  background:transparent;
}

/* ===== Links ===== */
a{color:var(--brand-600);text-decoration:none}
a:hover{text-decoration:underline}

/* ===== Utilities ===== */
.text-right{text-align:right}
.mono{font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}

/* Page-specific polish */
.card .label{color:#475467}

 status badges */
.badge.status-planned{background:#eaf3ff;border-color:#d7e7ff;color:#0a2e61}
.badge.status-approval-pending{background:#fff5e6;border-color:#ffd9a8;color:#7a4c10}
.badge.status-completed{background:#eafaf1;border-color:#cdebd6;color:#0f5132}


/* ===== Status Badges ===== */
.badge.status-planned {
  background: #eaf3ff;
  border-color: #d7e7ff;
  color: #0a2e61;
}
.badge.status-approval-pending {
  background: #fff5e6;
  border-color: #ffd9a8;
  color: #7a4c10;
}
.badge.status-completed {
  background: #eafaf1;
  border-color: #cdebd6;
  color: #0f5132;
}

/* ===== Tier Distribution Bars ===== */
.dist-chart {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 12px;
}
.bar-row {
  display: grid;
  grid-template-columns: 40px 1fr 60px;
  align-items: center;
  gap: 8px;
}
.bar-track {
  background: #e9eef6;
  height: 8px;
  border-radius: 4px;
  overflow: hidden;
}
.bar-fill {
  background: #2a6ef2;
  height: 100%;
  display: block;
}

/* ===== Table Styling ===== */
.table {
  width: 100%;
  border-collapse: collapse;
}
.table th, .table td {
  padding: 8px 10px;
  font-size: 13px;
  border-bottom: 1px solid #e9eef6;
}
.table th {
  background: #f7f9fc;
  color: #1f2a44;
  font-weight: 600;
}
.table tr:hover {
  background: #f0f4fa;
}

/* ===== Metrics Grid ===== */
.metric-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
  gap: 10px;
  margin-bottom: 12px;
}
.metric-card {
  background: #f7f9fc;
  border-radius: 8px;
  padding: 8px;
  text-align: center;
}
.metric-label {
  font-size: 12px;
  color: #5e6b7e;
}
.metric-value {
  font-size: 16px;
  font-weight: 600;
  color: #1f2a44;
}

/* ===== Controls Row ===== */
.row.controls {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
}
.row.controls label {
  font-size: 13px;
  color: var(--muted);
}
.row.controls input[type="date"] {
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 13px;
}
.btn.secondary {
  background: #f0f4fa;
  border: 1px solid #d4dbe7;
  border-radius: 6px;
  padding: 6px 12px;
  font-size: 13px;
  cursor: pointer;
  transition: background .2s ease;
}
.btn.secondary:hover {
  background: #eaf3ff;
}

/* ===== Grid ===== */
.reports-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 20px;
  margin-top: 20px;
}

.card h3 {
  font-size: 18px;
  margin-bottom: 12px;
  color: #0a2e61;
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 18px;
  box-shadow: var(--shadow);
}

.header .nav a {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--muted);
  padding: 10px 12px;
  border-radius: 10px;
  font-weight: 600;
  letter-spacing: .1px;
  transition: color .2s ease, background .2s ease, box-shadow .2s ease;
}
.header .nav a:hover {
  color: #0a2e61;
  background: #ecf5ff;
}

.header .nav {
  display: flex;
  gap: 6px;
  align-items: center;
  min-height: 64px;
}
.header .brand {
  font-weight: 900;
  color: #0a2e61;
  letter-spacing: .2px;
  padding: 10px 12px;
  border-radius: 10px;
}

.container { max-width: 1100px; margin: 0 auto; padding: 24px; }

::selection { background: var(--brand-600); color: #fff; }

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

/* ===== Sticky Footer Layout ===== */
html, body { height: 100%; }
body {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  background:
    radial-gradient(1200px 600px at 0% 0%, #ffffff 0%, var(--bg) 65%),
    radial-gradient(900px 300px at 100% 0%, #ffffff 0%, var(--bg) 60%);
  color: var(--text);
  font-family: Inter, system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
  letter-spacing: .2px;
  line-height: 1.55;
}

5. Completely Responsive & Reusable

The component auto-adjusts to different screen sizes:

  • Desktop multi-column layout

  • Tablet two-column layout

  • Mobile stacked layout

Because the data lives in Dataverse and the UI is template-based, the entire component is reusable:

  • Across multiple sites

  • For different business units

  • With varied leadership categories

<div class="row sectionBlockLayout text-start" style="display: flex; flex-wrap: wrap; margin: 0px; min-height: auto; padding: 8px;">
    <!-- ===== Main content (updated) ===== -->
  <main class="container">
    <!-- Top row: your original cards -->
    <div class="grid cols-3">
      <div class="card">
        <h2>Quick Links</h2>
        <p>Start a new engagement, browse HCP directory, or check pending approvals.</p>
        <p>
          <a class="btn primary" href="engagement-new.html">New Engagement</a>
          <a class="btn secondary" href="events.html">View Events</a>
        </p>
      </div>

      <div class="card">
        <h2>Compliance Reminders</h2>
        <ul>
          <li>Pre-event approvals (Medical &amp; Finance) are mandatory.</li>
          <li>Patient data access via Patient Voice Team only.</li>
          <li>Contracts must be generated in COUPA.</li>
        </ul>
      </div>

      <div class="card">
        <h2>Stats (Demo)</h2>
        <div class="grid cols-2">
          <div>
            <div class="label">Planned Events</div>
            <div style="font-size:24px;font-weight:700">2</div>
          </div>
          <div>
            <div class="label">Completed</div>
            <div style="font-size:24px;font-weight:700;color:var(--success)">1</div>
          </div>
        </div>
      </div>
    </div>

    <!-- Row 2: Upcoming + Pending -->
    <div class="grid cols-2" style="margin-top:24px">
      <!-- Upcoming Events -->
      <section class="card">
        <h2 style="margin-bottom:6px;">Upcoming Events</h2>
        <p class="label" style="margin:0 0 12px 0">Next 5 events by date</p>
        <table class="table" id="homeUpcomingTable">
          <thead>
            <tr>
              <th>Event ID</th>
              <th>Name</th>
              <th>Date</th>
              <th>Status</th>
              <th style="text-align:right">Budget</th>
            </tr>
          </thead>
          <tbody></tbody>
        </table>
        <p style="margin-top:12px">
          <a class="btn link" href="events.html">View all events →</a>
        </p>
      </section>

      <!-- Pending Actions -->
      <section class="card">
        <h2 style="margin-bottom:6px;">Pending Actions</h2>
        <p class="label" style="margin:0 0 12px 0">Approvals &amp; follow‑ups</p>
        <ul class="list-plain" id="homePendingList">
          <!-- Filled by JS -->
        </ul>
        <p style="margin-top:12px">
          <a class="btn link" href="approvals.html">Go to Approvals →</a>
        </p>
      </section>
    </div>


  </main>
</div>
</div>

6. Business-Friendly Content Management

One of the biggest wins for business teams:

✔ Update leadership data directly in Dataverse
✔ Upload images using Dataverse file fields
✔ Change order or department
✔ Add or remove profiles instantly
✔ No dependency on IT or developers

This significantly reduces content turnaround time and improves governance.

LEADER

🔚 Final Thoughts

This Leadership component is a great example of how Power Pages + Dataverse + Liquid can work together to deliver enterprise-quality web experiences—without compromising on maintainability, performance, or user experience.

If you’re building portals that need dynamic content, especially data managed by business teams, this approach can become a powerful blueprint.