본문으로 건너뛰기

Data Visualization Example

This example demonstrates data visualization techniques in Remarp: KPI cards, charts, and dashboard layouts.

Design System Principles

Typography Hierarchy

ElementSizeWeightUse Case
Hero stat3.5rem+700Single dominant metric
KPI value2.4rem700Dashboard card values
Card title1.1rem600Section headers
Body text1rem400Descriptions
Label0.85rem500Axis labels, captions

Semantic Colors

PurposeVariableUsage
Positive--green (#00b894)Upward trends, success
Negative--red (#e17055)Downward trends, errors
Warning--yellow (#fdcb6e)Alerts, pending
Primary--accent (#6c5ce7)Key metrics

Complete Example: Metrics Dashboard

---
remarp: true
version: 1
title: "Data Visualization Demo"
author: "Cloud Skills Team"
date: 2026-03-22
lang: en

blocks:
- name: data-viz
title: "Data Visualization"
duration: 8

theme:
accent: "#6c5ce7"

transition:
default: fade
duration: 300
---

---
remarp: true
block: data-viz
---

# Metrics Dashboard
Data visualization patterns in Remarp

:::notes
{timing: 30s}
Overview of dashboard capabilities.
:::

---

## KPI Cards

:::html
<div class="kpi-grid">
<div class="kpi-card" data-fragment-index="1">
<div class="kpi-label">Monthly Active Users</div>
<div class="kpi-value">2.4M</div>
<div class="kpi-trend positive">+12.5%</div>
</div>
<div class="kpi-card" data-fragment-index="2">
<div class="kpi-label">API Requests/sec</div>
<div class="kpi-value">45.2K</div>
<div class="kpi-trend positive">+8.3%</div>
</div>
<div class="kpi-card" data-fragment-index="3">
<div class="kpi-label">P99 Latency</div>
<div class="kpi-value">142ms</div>
<div class="kpi-trend negative">+15ms</div>
</div>
<div class="kpi-card" data-fragment-index="4">
<div class="kpi-label">Error Rate</div>
<div class="kpi-value">0.02%</div>
<div class="kpi-trend positive">-0.01%</div>
</div>
</div>
:::

:::css
.kpi-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1.5rem;
padding: 2rem;
}
.kpi-card {
background: var(--surface);
border-radius: 12px;
padding: 1.5rem;
text-align: center;
border: 1px solid var(--border);
}
.kpi-label {
font-size: 0.85rem;
color: var(--text-secondary);
margin-bottom: 0.5rem;
}
.kpi-value {
font-size: 2.4rem;
font-weight: 700;
font-family: var(--font-mono);
color: var(--text-primary);
}
.kpi-trend {
font-size: 0.9rem;
font-weight: 600;
margin-top: 0.5rem;
}
.kpi-trend.positive { color: var(--green); }
.kpi-trend.negative { color: var(--red); }
:::

:::notes
{timing: 2min}
KPI cards with semantic color coding for trends.
:::

---

## Hero Metric

:::html
<div class="hero-metric">
<div class="hero-label">Total Revenue</div>
<div class="hero-value">$4.2M</div>
<div class="hero-subtitle">Q1 2026</div>
<div class="hero-comparison">
<span class="positive">+24%</span> vs Q4 2025
</div>
</div>
:::

:::css
.hero-metric {
text-align: center;
padding: 4rem 2rem;
}
.hero-label {
font-size: 1.2rem;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.1em;
}
.hero-value {
font-size: 5rem;
font-weight: 700;
color: var(--accent-light);
text-shadow: 0 0 30px var(--accent-glow);
font-family: var(--font-mono);
margin: 0.5rem 0;
}
.hero-subtitle {
font-size: 1.5rem;
color: var(--text-muted);
}
.hero-comparison {
margin-top: 1rem;
font-size: 1.1rem;
}
.hero-comparison .positive { color: var(--green); font-weight: 600; }
:::

:::notes
{timing: 1min}
Hero metrics for maximum visual impact.
:::

---

## Chart.js Bar Chart

:::html
<div class="chart-container">
<canvas id="revenue-chart"></canvas>
</div>
:::

:::css
.chart-container {
max-width: 800px;
margin: 0 auto;
padding: 2rem;
}
:::

:::script
const ctx = document.getElementById('revenue-chart').getContext('2d');
new Chart(ctx, {
type: 'bar',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
datasets: [{
label: 'Revenue ($K)',
data: [650, 720, 810, 780, 890, 950],
backgroundColor: 'rgba(108, 92, 231, 0.8)',
borderColor: 'rgba(108, 92, 231, 1)',
borderWidth: 1,
borderRadius: 4
}]
},
options: {
responsive: true,
plugins: {
legend: { display: false },
title: {
display: true,
text: 'Monthly Revenue 2026',
color: '#e0e0e0',
font: { size: 18, weight: '600' }
}
},
scales: {
y: {
beginAtZero: true,
grid: { color: 'rgba(255,255,255,0.1)' },
ticks: { color: '#a0a0a0' }
},
x: {
grid: { display: false },
ticks: { color: '#a0a0a0' }
}
}
}
});
:::

:::notes
{timing: 2min}
Chart.js integration for dynamic charts.
:::

---

## CSS-Only Progress Bars

:::html
<div class="progress-section">
<h3>Service Adoption</h3>

<div class="progress-item" data-fragment-index="1">
<div class="progress-label">
<span>Lambda</span>
<span>92%</span>
</div>
<div class="progress-bar">
<div class="progress-fill" style="--progress: 92%"></div>
</div>
</div>

<div class="progress-item" data-fragment-index="2">
<div class="progress-label">
<span>DynamoDB</span>
<span>78%</span>
</div>
<div class="progress-bar">
<div class="progress-fill" style="--progress: 78%"></div>
</div>
</div>

<div class="progress-item" data-fragment-index="3">
<div class="progress-label">
<span>EKS</span>
<span>65%</span>
</div>
<div class="progress-bar">
<div class="progress-fill" style="--progress: 65%"></div>
</div>
</div>

<div class="progress-item" data-fragment-index="4">
<div class="progress-label">
<span>Step Functions</span>
<span>41%</span>
</div>
<div class="progress-bar">
<div class="progress-fill" style="--progress: 41%"></div>
</div>
</div>
</div>
:::

:::css
.progress-section {
max-width: 600px;
margin: 0 auto;
padding: 2rem;
}
.progress-section h3 {
margin-bottom: 2rem;
text-align: center;
}
.progress-item {
margin-bottom: 1.5rem;
}
.progress-label {
display: flex;
justify-content: space-between;
margin-bottom: 0.5rem;
font-size: 0.95rem;
}
.progress-bar {
height: 12px;
background: var(--surface);
border-radius: 6px;
overflow: hidden;
}
.progress-fill {
height: 100%;
width: var(--progress);
background: linear-gradient(90deg, var(--accent), var(--accent-light));
border-radius: 6px;
transition: width 0.8s ease-out;
}
:::

:::notes
{timing: 1min}
CSS-only progress bars with custom properties.
:::

---

## Comparison Table

:::html
<div class="comparison-table">
<table>
<thead>
<tr>
<th>Metric</th>
<th>Q4 2025</th>
<th>Q1 2026</th>
<th>Change</th>
</tr>
</thead>
<tbody>
<tr data-fragment-index="1">
<td>Users</td>
<td>2.1M</td>
<td>2.4M</td>
<td class="positive">+14.3%</td>
</tr>
<tr data-fragment-index="2">
<td>Requests/day</td>
<td>3.2B</td>
<td>3.9B</td>
<td class="positive">+21.9%</td>
</tr>
<tr data-fragment-index="3">
<td>Avg Latency</td>
<td>95ms</td>
<td>82ms</td>
<td class="positive">-13.7%</td>
</tr>
<tr data-fragment-index="4">
<td>Cost/request</td>
<td>$0.0012</td>
<td>$0.0009</td>
<td class="positive">-25%</td>
</tr>
</tbody>
</table>
</div>
:::

:::css
.comparison-table {
max-width: 700px;
margin: 0 auto;
padding: 2rem;
}
.comparison-table table {
width: 100%;
border-collapse: collapse;
}
.comparison-table th,
.comparison-table td {
padding: 1rem;
text-align: left;
border-bottom: 1px solid var(--border);
}
.comparison-table th {
font-weight: 600;
color: var(--text-secondary);
font-size: 0.9rem;
text-transform: uppercase;
}
.comparison-table td.positive { color: var(--green); font-weight: 600; }
.comparison-table td.negative { color: var(--red); font-weight: 600; }
:::

:::notes
{timing: 1min}
Tabular data with semantic color coding.
:::

---

## Mini Sparklines (CSS-only)

:::html
<div class="sparkline-grid">
<div class="sparkline-card">
<div class="sparkline-header">
<span class="sparkline-label">CPU Usage</span>
<span class="sparkline-value">68%</span>
</div>
<div class="sparkline" style="--v1:40%; --v2:55%; --v3:62%; --v4:58%; --v5:72%; --v6:68%"></div>
</div>
<div class="sparkline-card">
<div class="sparkline-header">
<span class="sparkline-label">Memory</span>
<span class="sparkline-value">82%</span>
</div>
<div class="sparkline" style="--v1:75%; --v2:78%; --v3:80%; --v4:79%; --v5:81%; --v6:82%"></div>
</div>
<div class="sparkline-card">
<div class="sparkline-header">
<span class="sparkline-label">Network I/O</span>
<span class="sparkline-value">1.2GB/s</span>
</div>
<div class="sparkline" style="--v1:30%; --v2:45%; --v3:60%; --v4:55%; --v5:70%; --v6:65%"></div>
</div>
</div>
:::

:::css
.sparkline-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1.5rem;
padding: 2rem;
}
.sparkline-card {
background: var(--surface);
border-radius: 8px;
padding: 1rem;
}
.sparkline-header {
display: flex;
justify-content: space-between;
margin-bottom: 0.75rem;
}
.sparkline-label { font-size: 0.85rem; color: var(--text-secondary); }
.sparkline-value { font-weight: 600; font-family: var(--font-mono); }
.sparkline {
display: flex;
align-items: flex-end;
gap: 4px;
height: 40px;
}
.sparkline::before,
.sparkline::after,
.sparkline span { content: ''; }
.sparkline {
--bar-color: var(--accent);
}
.sparkline::before { flex: 1; height: var(--v1); background: var(--bar-color); border-radius: 2px; }
.sparkline::after { flex: 1; height: var(--v6); background: var(--bar-color); border-radius: 2px; }
/* Additional bars via pseudo-elements on wrapper */
:::

:::notes
{timing: 1min}
Lightweight CSS sparklines for quick metrics overview.
:::

KPI Card Patterns

Basic KPI Card

<div class="kpi-card">
<div class="kpi-label">Metric Name</div>
<div class="kpi-value">123.4K</div>
<div class="kpi-trend positive">+5.2%</div>
</div>
.kpi-card {
background: var(--surface);
border-radius: 12px;
padding: 1.5rem;
text-align: center;
}
.kpi-value {
font-size: 2.4rem;
font-weight: 700;
font-family: var(--font-mono);
}
.kpi-trend.positive { color: var(--green); }
.kpi-trend.negative { color: var(--red); }

KPI with Icon

<div class="kpi-card">
<div class="kpi-icon">
<img src="../common/aws-icons/services/Arch_AWS-Lambda_48.svg" alt="Lambda">
</div>
<div class="kpi-label">Lambda Invocations</div>
<div class="kpi-value">12.8M</div>
<div class="kpi-sublabel">/day</div>
</div>

KPI Grid Layout

.kpi-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
}

Chart.js Integration

Setup

Include Chart.js in your presentation's :::script block:

:::script
// Chart.js is auto-loaded by the reactive-presentation framework
:::

Bar Chart

new Chart(ctx, {
type: 'bar',
data: {
labels: ['Jan', 'Feb', 'Mar'],
datasets: [{
label: 'Revenue',
data: [650, 720, 810],
backgroundColor: 'rgba(108, 92, 231, 0.8)',
borderRadius: 4
}]
},
options: {
responsive: true,
scales: {
y: { beginAtZero: true }
}
}
});

Line Chart

new Chart(ctx, {
type: 'line',
data: {
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
datasets: [{
label: 'Requests',
data: [1200, 1900, 1500, 2100, 1800],
borderColor: 'rgba(108, 92, 231, 1)',
tension: 0.3,
fill: true,
backgroundColor: 'rgba(108, 92, 231, 0.1)'
}]
}
});

Doughnut Chart

new Chart(ctx, {
type: 'doughnut',
data: {
labels: ['Lambda', 'EC2', 'EKS', 'Fargate'],
datasets: [{
data: [45, 25, 20, 10],
backgroundColor: [
'#6c5ce7', '#FF9900', '#00b894', '#e17055'
]
}]
},
options: {
cutout: '60%'
}
});

CSS-Only Charts

Progress Bar

<div class="progress-bar">
<div class="progress-fill" style="--progress: 75%"></div>
</div>
.progress-bar {
height: 12px;
background: var(--surface);
border-radius: 6px;
}
.progress-fill {
height: 100%;
width: var(--progress);
background: linear-gradient(90deg, var(--accent), var(--accent-light));
transition: width 0.8s ease-out;
}

Horizontal Bar Chart (CSS Grid)

<div class="bar-chart">
<div class="bar-row">
<span class="bar-label">Lambda</span>
<div class="bar" style="--width: 92%">92%</div>
</div>
<div class="bar-row">
<span class="bar-label">EKS</span>
<div class="bar" style="--width: 65%">65%</div>
</div>
</div>
.bar-chart { display: flex; flex-direction: column; gap: 1rem; }
.bar-row { display: grid; grid-template-columns: 100px 1fr; align-items: center; gap: 1rem; }
.bar {
height: 24px;
width: var(--width);
background: var(--accent);
border-radius: 4px;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 0.5rem;
font-size: 0.8rem;
}

Best Practices

  1. Use semantic colors - Green for positive, red for negative, consistently
  2. Limit data density - Maximum 4-6 KPI cards per slide
  3. Add context - Show trends, comparisons, or time periods
  4. Responsive grids - Use auto-fit and minmax() for flexible layouts
  5. Progressive reveal - Use data-fragment-index to build up dashboards
  6. Consistent typography - Follow the hierarchy table for font sizes
  7. Dark theme friendly - Use CSS variables for colors, not hardcoded values