Improve school modal charts for mobile visualization
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 58s

- Make charts taller on mobile with better aspect ratios (0.9 for <480px, 1.1 for <768px)
- Shorten chart title and dataset labels on mobile
- Add responsive font sizes for legend, title, and axis ticks
- Add mobile-specific styling for chart container, stats grid, and modal
- Add extra-small screen breakpoint (480px) for very narrow devices

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Tudor
2026-01-14 19:09:07 +00:00
parent f2eec08bd4
commit 9b6c37cda3
2 changed files with 110 additions and 7 deletions

View File

@@ -160,7 +160,14 @@ const schoolMaps = new Map();
// Helper to get chart aspect ratio based on screen size // Helper to get chart aspect ratio based on screen size
function getChartAspectRatio() { function getChartAspectRatio() {
return window.innerWidth <= 768 ? 1.2 : 2; if (window.innerWidth <= 480) return 0.9; // Very small screens - taller chart
if (window.innerWidth <= 768) return 1.1; // Mobile - taller chart
return 2;
}
// Helper to check if we're on mobile
function isMobile() {
return window.innerWidth <= 768;
} }
// ============================================================================= // =============================================================================
@@ -1442,25 +1449,26 @@ async function openSchoolModal(urn) {
const years = validData.map((d) => d.year); const years = validData.map((d) => d.year);
const ctx = elements.schoolDetailChart.getContext("2d"); const ctx = elements.schoolDetailChart.getContext("2d");
const mobile = isMobile();
schoolDetailChart = new Chart(ctx, { schoolDetailChart = new Chart(ctx, {
type: "bar", type: "bar",
data: { data: {
labels: years, labels: years,
datasets: [ datasets: [
{ {
label: "Reading %", label: mobile ? "Reading" : "Reading %",
data: validData.map((d) => d.reading_expected_pct), data: validData.map((d) => d.reading_expected_pct),
backgroundColor: "#2d7d7d", backgroundColor: "#2d7d7d",
borderRadius: 4, borderRadius: 4,
}, },
{ {
label: "Writing %", label: mobile ? "Writing" : "Writing %",
data: validData.map((d) => d.writing_expected_pct), data: validData.map((d) => d.writing_expected_pct),
backgroundColor: "#c9a227", backgroundColor: "#c9a227",
borderRadius: 4, borderRadius: 4,
}, },
{ {
label: "Maths %", label: mobile ? "Maths" : "Maths %",
data: validData.map((d) => d.maths_expected_pct), data: validData.map((d) => d.maths_expected_pct),
backgroundColor: "#e07256", backgroundColor: "#e07256",
borderRadius: 4, borderRadius: 4,
@@ -1475,14 +1483,36 @@ async function openSchoolModal(urn) {
legend: { legend: {
position: "bottom", position: "bottom",
labels: { labels: {
font: { family: "'DM Sans', sans-serif" }, font: {
family: "'DM Sans', sans-serif",
size: mobile ? 11 : 12,
},
usePointStyle: true, usePointStyle: true,
pointStyle: "circle",
padding: mobile ? 12 : 16,
boxWidth: mobile ? 8 : 12,
}, },
}, },
title: { title: {
display: true, display: true,
text: "KS2 Attainment Over Time (% meeting expected standard)", text: mobile
font: { family: "'Playfair Display', serif", size: 16, weight: 600 }, ? "KS2 Attainment (% expected)"
: "KS2 Attainment Over Time (% meeting expected standard)",
font: {
family: "'Playfair Display', serif",
size: mobile ? 14 : 16,
weight: 600,
},
padding: {
bottom: mobile ? 12 : 16,
},
},
tooltip: {
callbacks: {
label: function(context) {
return `${context.dataset.label}: ${context.parsed.y}%`;
}
}
}, },
}, },
scales: { scales: {
@@ -1490,9 +1520,18 @@ async function openSchoolModal(urn) {
beginAtZero: true, beginAtZero: true,
max: 100, max: 100,
grid: { color: "#e5dfd5" }, grid: { color: "#e5dfd5" },
ticks: {
font: { size: mobile ? 10 : 12 },
callback: function(value) {
return value + "%";
},
},
}, },
x: { x: {
grid: { display: false }, grid: { display: false },
ticks: {
font: { size: mobile ? 10 : 12 },
},
}, },
}, },
}, },

View File

@@ -1420,12 +1420,76 @@ body {
width: 100%; width: 100%;
} }
.modal-body {
padding: 1rem;
}
.modal-chart-container {
margin-bottom: 1.5rem;
padding: 0.5rem;
background: var(--bg-secondary);
border-radius: var(--radius-md);
}
.modal-chart-container canvas {
max-height: 280px;
}
.modal-stats-grid {
grid-template-columns: repeat(2, 1fr);
gap: 0.5rem;
}
.modal-stat {
padding: 0.75rem 0.5rem;
}
.modal-stat-value {
font-size: 1.25rem;
}
.modal-stat-label {
font-size: 0.65rem;
}
.rankings-controls { .rankings-controls {
flex-direction: column; flex-direction: column;
align-items: stretch; align-items: stretch;
} }
} }
/* Extra small screens */
@media (max-width: 480px) {
.modal-content {
margin: 0.5rem;
max-height: calc(100vh - 1rem);
}
.modal-header {
padding: 1rem;
}
.modal-header h2 {
font-size: 1.25rem;
}
.modal-chart-container canvas {
max-height: 260px;
}
.modal-stats-grid {
grid-template-columns: repeat(2, 1fr);
}
.modal-stat-value {
font-size: 1.1rem;
}
.modal-map {
height: 160px;
}
}
/* ============================================================================= /* =============================================================================
TOOLTIP SYSTEM TOOLTIP SYSTEM
============================================================================= */ ============================================================================= */