Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions _includes/platform-table.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

{% assign col_count = include.years | size | plus: 1 %}

<div class="platform-table-wrapper{% if include.compact %} platform-table-compact{% endif %}{% if include.scrollbar_top %} platform-table-scrollbar-top{% endif %}">
<div class="platform-table-wrapper{% if include.compact %} platform-table-compact{% else %} platform-table-sticky-col{% endif %}{% if include.scrollbar_top %} platform-table-scrollbar-top{% endif %}">
<div class="overflow-x-auto">
<table class="platform-table">
<thead>
Expand Down Expand Up @@ -35,8 +35,10 @@
{% for year in include.years %}<td></td>{% endfor %}
{% else %}
<td colspan="{{ col_count }}">
<span class="category-chevron">&#9662;</span>
{{ category.name }}
<span class="category-label">
<span class="category-chevron">&#9662;</span>
{{ category.name }}
</span>
</td>
{% endif %}
</tr>
Expand Down
86 changes: 84 additions & 2 deletions assets/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
@apply px-4 py-3 text-center;
border-bottom: 1px solid rgb(var(--color-border) / 0.5);
border-right: 1px solid rgb(var(--color-border));
transition: background-color 0.1s ease;
transition: background-color 0.15s ease;
}

.platform-table td:last-child {
Expand Down Expand Up @@ -176,6 +176,29 @@
position: relative;
}

/* Thin themed scrollbar on horizontally scrollable tables */
.platform-table-wrapper .overflow-x-auto {
scrollbar-width: thin;
scrollbar-color: rgb(var(--color-border-strong)) transparent;
}

.platform-table-wrapper .overflow-x-auto::-webkit-scrollbar {
height: 8px;
}

.platform-table-wrapper .overflow-x-auto::-webkit-scrollbar-track {
background-color: transparent;
}

.platform-table-wrapper .overflow-x-auto::-webkit-scrollbar-thumb {
background-color: rgb(var(--color-border-strong));
border-radius: 4px;
}

.platform-table-wrapper .overflow-x-auto::-webkit-scrollbar-thumb:hover {
background-color: rgb(var(--color-text-muted));
}

/* Mobile scroll affordance — gradient fade on right edge hints at scrollable content */
@media (max-width: 767px) {
.platform-table-wrapper::after {
Expand All @@ -196,6 +219,39 @@
.platform-table .category-header td {
@apply py-3;
}

/* Sticky first column keeps component names visible while scrolling */
.platform-table-sticky-col .platform-table th:first-child,
.platform-table-sticky-col .platform-table tr:not(.category-header) td:first-child {
position: sticky;
left: 0;
z-index: 1;
box-shadow: 2px 0 4px rgb(0 0 0 / 0.04);
}

:is(.dark) .platform-table-sticky-col .platform-table th:first-child,
:is(.dark) .platform-table-sticky-col .platform-table tr:not(.category-header) td:first-child {
box-shadow: 2px 0 4px rgb(0 0 0 / 0.15);
}

.platform-table-sticky-col .platform-table th:first-child {
z-index: 2;
}

.platform-table-sticky-col .platform-table tr:not(.category-header) td:first-child {
background-color: rgb(var(--color-surface));
}

.platform-table-sticky-col .platform-table tr.row-alt td:first-child {
background-color: rgb(var(--color-surface-alt));
}

/* Category cells span the full table width, so pin their label instead */
.platform-table-sticky-col .category-label {
display: inline-block;
position: sticky;
left: 1rem;
}
}

/* Scrollbar at top variant (used on history page) */
Expand Down Expand Up @@ -359,6 +415,8 @@

.note-popover-arrow {
@apply absolute w-0 h-0;
/* JS sets `left` to the trigger center; anchor the triangle tip there */
transform: translateX(-50%);
}

.note-popover-arrow.arrow-top {
Expand Down Expand Up @@ -386,7 +444,10 @@

/* Note bottom sheet (mobile) */
.note-bottom-sheet {
@apply fixed bottom-0 left-0 right-0 z-50 rounded-t-2xl shadow-2xl p-5 pt-8 max-h-[70vh] overflow-y-auto;
@apply fixed bottom-0 left-0 right-0 z-50 rounded-t-2xl shadow-2xl p-5 pt-8 overflow-y-auto;
max-height: 70vh;
max-height: min(70dvh, calc(100dvh - 2rem));
padding-bottom: calc(1.25rem + env(safe-area-inset-bottom));
background-color: rgb(var(--color-surface));
transform: translateY(100%);
transition: transform 0.25s ease-out;
Expand Down Expand Up @@ -445,13 +506,34 @@
}
}

/* Styled select with custom chevron (compare page) */
.select-control {
@apply appearance-none rounded-lg px-4 py-2.5 pr-8 bg-no-repeat transition-colors;
background-color: rgb(var(--color-surface-raised));
border: 1px solid rgb(var(--color-border-strong));
color: rgb(var(--color-text-heading));
background-image: url('data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2020%2020%22%20fill%3D%22%236b7280%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20d%3D%22M5.23%207.21a.75.75%200%20011.06.02L10%2011.168l3.71-3.938a.75.75%200%20111.08%201.04l-4.25%204.5a.75.75%200%2001-1.08%200l-4.25-4.5a.75.75%200%2001.02-1.06z%22%20clip-rule%3D%22evenodd%22%2F%3E%3C%2Fsvg%3E');
background-size: 1.25rem 1.25rem;
background-position: right 0.5rem center;
}

/* Info box */
.info-box {
background-color: rgb(var(--color-primary-subtle) / 0.5);
border: 1px solid rgb(var(--color-primary-subtle));
@apply rounded-lg p-5;
}

/* Gentle fade when switching between table and card views */
.view-fade-in {
animation: view-fade-in 0.15s var(--ease-out-quart);
}

@keyframes view-fade-in {
from { opacity: 0; }
to { opacity: 1; }
}

/* View toggle buttons */
.view-toggle-btn {
@apply bg-transparent cursor-pointer transition-colors duration-150;
Expand Down
2 changes: 1 addition & 1 deletion assets/css/output.css

Large diffs are not rendered by default.

17 changes: 12 additions & 5 deletions assets/js/history-view-toggle.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,29 @@

if (!tableView || !cardView || !btnTable || !btnCards) return;

function setView(view) {
function setView(view, animate) {
var isTable = view === 'table';
tableView.classList.toggle('hidden', !isTable);
cardView.classList.toggle('hidden', isTable);
btnTable.classList.toggle('active', isTable);
btnCards.classList.toggle('active', !isTable);
btnTable.setAttribute('aria-pressed', isTable ? 'true' : 'false');
btnCards.setAttribute('aria-pressed', isTable ? 'false' : 'true');
if (animate) {
var shown = isTable ? tableView : cardView;
shown.classList.add('view-fade-in');
shown.addEventListener('animationend', function() {
shown.classList.remove('view-fade-in');
}, { once: true });
}
try { localStorage.setItem(STORAGE_KEY, view); } catch (e) {}
}

btnTable.addEventListener('click', function() { setView('table'); });
btnCards.addEventListener('click', function() { setView('cards'); });
btnTable.addEventListener('click', function() { setView('table', true); });
btnCards.addEventListener('click', function() { setView('cards', true); });

// Initialize from saved preference (default: table)
// Initialize from saved preference (default: table), without animation
var saved = 'table';
try { saved = localStorage.getItem(STORAGE_KEY) || 'table'; } catch (e) {}
setView(saved);
setView(saved, false);
})();
20 changes: 18 additions & 2 deletions assets/js/note-popover.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
(function () {
let activePopover = null;
let activeTrigger = null;

function closeActive() {
if (!activePopover) return;
activePopover.remove();
activePopover = null;
const backdrop = document.querySelector('.note-backdrop');
if (backdrop) backdrop.remove();
if (activeTrigger && activeTrigger.isConnected) {
activeTrigger.focus();
}
activeTrigger = null;
}

function isMobile() {
Expand All @@ -30,6 +35,8 @@

const sheet = document.createElement('div');
sheet.className = 'note-bottom-sheet';
sheet.setAttribute('role', 'dialog');
sheet.setAttribute('aria-label', 'Note');
sheet.appendChild(createCloseBtn());
sheet.appendChild(content);
document.body.appendChild(sheet);
Expand All @@ -45,6 +52,8 @@
function showPopover(content, trigger) {
const popover = document.createElement('div');
popover.className = 'note-popover';
popover.setAttribute('role', 'dialog');
popover.setAttribute('aria-label', 'Note');
popover.appendChild(createCloseBtn());
popover.appendChild(content);

Expand Down Expand Up @@ -81,9 +90,9 @@
popover.style.top = top + 'px';
popover.style.left = left + 'px';

// Position arrow to point at trigger center
// Position arrow tip at trigger center (CSS translateX(-50%) anchors the tip)
let arrowLeft = rect.left + scrollX + rect.width / 2 - left;
arrowLeft = Math.max(16, Math.min(arrowLeft, popRect.width - 16));
arrowLeft = Math.max(14, Math.min(arrowLeft, popRect.width - 14));
arrow.style.left = arrowLeft + 'px';
}

Expand All @@ -105,6 +114,9 @@
} else {
showPopover(wrapper, link);
}
activeTrigger = link;
const closeBtn = activePopover.querySelector('.note-close-btn');
if (closeBtn) closeBtn.focus({ preventScroll: true });
return;
}

Expand All @@ -117,4 +129,8 @@
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape') closeActive();
});

// Stale positioning after resize/rotation; closing also handles the
// popover/bottom-sheet mode flip across the 768px breakpoint
window.addEventListener('resize', closeActive);
})();
4 changes: 2 additions & 2 deletions compare.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ <h1 class="text-4xl md:text-5xl font-bold tracking-tight mb-4">
<div class="flex flex-col sm:flex-row sm:items-end gap-3 sm:gap-4 mb-8">
<div class="flex-1 sm:flex-none">
<label for="year1-select" class="block text-sm font-medium mb-1">First Year</label>
<select id="year1-select" class="w-full sm:w-auto appearance-none bg-white rounded-lg border border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100 px-4 py-2.5 pr-8 bg-[url('data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2020%2020%22%20fill%3D%22%236b7280%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20d%3D%22M5.23%207.21a.75.75%200%20011.06.02L10%2011.168l3.71-3.938a.75.75%200%20111.08%201.04l-4.25%204.5a.75.75%200%2001-1.08%200l-4.25-4.5a.75.75%200%2001.02-1.06z%22%20clip-rule%3D%22evenodd%22%2F%3E%3C%2Fsvg%3E')] bg-[length:1.25rem_1.25rem] bg-[right_0.5rem_center] bg-no-repeat transition-colors">
<select id="year1-select" class="select-control w-full sm:w-auto">
</select>
</div>

Expand All @@ -35,7 +35,7 @@ <h1 class="text-4xl md:text-5xl font-bold tracking-tight mb-4">

<div class="flex-1 sm:flex-none">
<label for="year2-select" class="block text-sm font-medium mb-1">Second Year</label>
<select id="year2-select" class="w-full sm:w-auto appearance-none bg-white rounded-lg border border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100 px-4 py-2.5 pr-8 bg-[url('data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2020%2020%22%20fill%3D%22%236b7280%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20d%3D%22M5.23%207.21a.75.75%200%20011.06.02L10%2011.168l3.71-3.938a.75.75%200%20111.08%201.04l-4.25%204.5a.75.75%200%2001-1.08%200l-4.25-4.5a.75.75%200%2001.02-1.06z%22%20clip-rule%3D%22evenodd%22%2F%3E%3C%2Fsvg%3E')] bg-[length:1.25rem_1.25rem] bg-[right_0.5rem_center] bg-no-repeat transition-colors">
<select id="year2-select" class="select-control w-full sm:w-auto">
</select>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion platform_history.html
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ <h2 class="text-2xl font-semibold whitespace-nowrap">All Platforms</h2>
<h2>Previous Status Updates</h2>
</div>

{% include status-updates.html offset=5 style="cards" show_latest=false %}
{% include status-updates.html offset=4 style="cards" show_latest=false %}
</section>

{% include note-popover-content.html %}
Expand Down