feat(trip): pill radius on panel toggles, slide animation, mobile close button
- Radius: trip-panel-toggle now uses --radius-full, consistent with filter pills - Animation: stats/cycling blocks use CSS grid-template-rows 0fr→1fr transition (inner trip-panel-inner div carries decoration so border/padding don't peek out when collapsed; display:none removed) - Close button: ↑ Close stats / ↑ Close cycling at bottom of each panel, hidden ≥769px, triggers the header toggle via data-toggle attribute Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vgmzx8VTTTmCskSpQtsLTr
This commit is contained in:
@@ -968,7 +968,7 @@ body::after {
|
|||||||
.trip-panel-toggle {
|
.trip-panel-toggle {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
border-radius: var(--radius-sm);
|
border-radius: var(--radius-full);
|
||||||
padding: var(--space-1) var(--space-3);
|
padding: var(--space-1) var(--space-3);
|
||||||
font-family: var(--font-ui);
|
font-family: var(--font-ui);
|
||||||
font-size: var(--text-sm);
|
font-size: var(--text-sm);
|
||||||
@@ -1149,12 +1149,54 @@ body::after {
|
|||||||
|
|
||||||
/* ── Trip page inline stats block ───────────────────────────────────────────── */
|
/* ── Trip page inline stats block ───────────────────────────────────────────── */
|
||||||
|
|
||||||
.trip-stats-block {
|
.trip-stats-block,
|
||||||
|
.trip-cycling-block {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: 0fr;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 0;
|
||||||
|
transition: grid-template-rows 0.35s ease, margin-bottom 0.35s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trip-stats-block.is-open,
|
||||||
|
.trip-cycling-block.is-open {
|
||||||
|
grid-template-rows: 1fr;
|
||||||
|
margin-bottom: var(--space-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.trip-panel-inner {
|
||||||
|
min-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
background: var(--color-canvas);
|
background: var(--color-canvas);
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
border-radius: var(--radius-md);
|
border-radius: var(--radius-md);
|
||||||
padding: var(--space-6);
|
padding: var(--space-6);
|
||||||
margin-bottom: var(--space-6);
|
}
|
||||||
|
|
||||||
|
.trip-panel-close {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: var(--space-6);
|
||||||
|
padding: var(--space-2) var(--space-4);
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: var(--radius-full);
|
||||||
|
font-family: var(--font-ui);
|
||||||
|
font-size: var(--text-sm);
|
||||||
|
color: var(--color-ink-muted);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color 0.15s, border-color 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trip-panel-close:hover {
|
||||||
|
color: var(--color-ink);
|
||||||
|
border-color: var(--color-ink-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 769px) {
|
||||||
|
.trip-panel-close { display: none; }
|
||||||
}
|
}
|
||||||
|
|
||||||
.trip-stats-grid {
|
.trip-stats-grid {
|
||||||
@@ -1181,13 +1223,6 @@ body::after {
|
|||||||
|
|
||||||
/* ── Trip page cycling panel ─────────────────────────────────────────────────── */
|
/* ── Trip page cycling panel ─────────────────────────────────────────────────── */
|
||||||
|
|
||||||
.trip-cycling-block {
|
|
||||||
background: var(--color-canvas);
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
border-radius: var(--radius-md);
|
|
||||||
padding: var(--space-6);
|
|
||||||
margin-bottom: var(--space-6);
|
|
||||||
}
|
|
||||||
|
|
||||||
.trip-cycling-header {
|
.trip-cycling-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -137,78 +137,84 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="trip-stats-block" class="trip-stats-block" style="display:none">
|
<div id="trip-stats-block" class="trip-stats-block">
|
||||||
<div class="trip-stats-grid">
|
<div class="trip-panel-inner">
|
||||||
<div class="stat-block">
|
<div class="trip-stats-grid">
|
||||||
<span class="stat-value">{{ days_on_road }}</span>
|
<div class="stat-block">
|
||||||
<span class="stat-label">{{ days_on_road == 1 ? 'day' : 'days' }} on the road</span>
|
<span class="stat-value">{{ days_on_road }}</span>
|
||||||
</div>
|
<span class="stat-label">{{ days_on_road == 1 ? 'day' : 'days' }} on the road</span>
|
||||||
<div class="stat-block">
|
</div>
|
||||||
<span class="stat-value">{{ journal_count }}</span>
|
<div class="stat-block">
|
||||||
<span class="stat-label">{{ journal_count == 1 ? 'entry' : 'entries' }} posted</span>
|
<span class="stat-value">{{ journal_count }}</span>
|
||||||
</div>
|
<span class="stat-label">{{ journal_count == 1 ? 'entry' : 'entries' }} posted</span>
|
||||||
<div class="stat-block">
|
</div>
|
||||||
<span class="stat-value">{{ country_display|length }}</span>
|
<div class="stat-block">
|
||||||
<span class="stat-label">{{ country_display|length == 1 ? 'country' : 'countries' }} visited</span>
|
<span class="stat-value">{{ country_display|length }}</span>
|
||||||
</div>
|
<span class="stat-label">{{ country_display|length == 1 ? 'country' : 'countries' }} visited</span>
|
||||||
<div class="stat-block">
|
</div>
|
||||||
<span class="stat-value">{{ city_display|length }}</span>
|
<div class="stat-block">
|
||||||
<span class="stat-label">{{ city_display|length == 1 ? 'city' : 'cities' }} visited</span>
|
<span class="stat-value">{{ city_display|length }}</span>
|
||||||
</div>
|
<span class="stat-label">{{ city_display|length == 1 ? 'city' : 'cities' }} visited</span>
|
||||||
<div class="stat-block">
|
</div>
|
||||||
<span class="stat-value" id="stat-distance">—</span>
|
<div class="stat-block">
|
||||||
<span class="stat-label">{{ has_gpx ? '🚴 km cycled' : '🧭 km roamed' }}</span>
|
<span class="stat-value" id="stat-distance">—</span>
|
||||||
</div>
|
<span class="stat-label">{{ has_gpx ? '🚴 km cycled' : '🧭 km roamed' }}</span>
|
||||||
<div class="stat-block">
|
</div>
|
||||||
{% if temp_min is not null %}
|
<div class="stat-block">
|
||||||
<span class="stat-value">{{ temp_min == temp_max ? temp_min : temp_min ~ ' → ' ~ temp_max }}</span>
|
{% if temp_min is not null %}
|
||||||
{% else %}
|
<span class="stat-value">{{ temp_min == temp_max ? temp_min : temp_min ~ ' → ' ~ temp_max }}</span>
|
||||||
<span class="stat-value">—</span>
|
{% else %}
|
||||||
{% endif %}
|
<span class="stat-value">—</span>
|
||||||
<span class="stat-label">°C range</span>
|
{% endif %}
|
||||||
|
<span class="stat-label">°C range</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% if country_display|length > 0 %}
|
||||||
|
<p class="trip-stats-countries">{{ country_display|join(' · ') }}</p>
|
||||||
|
{% endif %}
|
||||||
|
<p class="trip-stats-note">{{ has_gpx ? 'Distance based on GPS track data.' : 'Distance is approximate — straight lines between entry locations.' }}</p>
|
||||||
|
<button class="trip-panel-close" data-toggle="trip-stats-toggle">↑ Close stats</button>
|
||||||
</div>
|
</div>
|
||||||
{% if country_display|length > 0 %}
|
|
||||||
<p class="trip-stats-countries">{{ country_display|join(' · ') }}</p>
|
|
||||||
{% endif %}
|
|
||||||
<p class="trip-stats-note">{{ has_gpx ? 'Distance based on GPS track data.' : 'Distance is approximate — straight lines between entry locations.' }}</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if has_gpx %}
|
{% if has_gpx %}
|
||||||
<div id="trip-cycling-block" class="trip-cycling-block" style="display:none">
|
<div id="trip-cycling-block" class="trip-cycling-block">
|
||||||
<div class="trip-cycling-header">
|
<div class="trip-panel-inner">
|
||||||
<span class="trip-cycling-icon">🚴</span>
|
<div class="trip-cycling-header">
|
||||||
<span class="trip-cycling-title">Cycling Stats</span>
|
<span class="trip-cycling-icon">🚴</span>
|
||||||
</div>
|
<span class="trip-cycling-title">Cycling Stats</span>
|
||||||
<div class="trip-cycling-grid">
|
|
||||||
<div class="stat-block">
|
|
||||||
<span class="stat-value" id="cyc-distance">—</span>
|
|
||||||
<span class="stat-label">km distance</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="stat-block">
|
<div class="trip-cycling-grid">
|
||||||
<span class="stat-value" id="cyc-ele-gain">—</span>
|
<div class="stat-block">
|
||||||
<span class="stat-label">m ↑ gain</span>
|
<span class="stat-value" id="cyc-distance">—</span>
|
||||||
</div>
|
<span class="stat-label">km distance</span>
|
||||||
<div class="stat-block">
|
</div>
|
||||||
<span class="stat-value" id="cyc-ele-loss">—</span>
|
<div class="stat-block">
|
||||||
<span class="stat-label">m ↓ loss</span>
|
<span class="stat-value" id="cyc-ele-gain">—</span>
|
||||||
</div>
|
<span class="stat-label">m ↑ gain</span>
|
||||||
<div class="stat-block">
|
</div>
|
||||||
<span class="stat-value" id="cyc-highest">—</span>
|
<div class="stat-block">
|
||||||
<span class="stat-label">m highest</span>
|
<span class="stat-value" id="cyc-ele-loss">—</span>
|
||||||
</div>
|
<span class="stat-label">m ↓ loss</span>
|
||||||
<div class="stat-block">
|
</div>
|
||||||
<span class="stat-value" id="cyc-lowest">—</span>
|
<div class="stat-block">
|
||||||
<span class="stat-label">m lowest</span>
|
<span class="stat-value" id="cyc-highest">—</span>
|
||||||
</div>
|
<span class="stat-label">m highest</span>
|
||||||
<div class="stat-block">
|
</div>
|
||||||
<span class="stat-value" id="cyc-moving-time">—</span>
|
<div class="stat-block">
|
||||||
<span class="stat-label">moving time</span>
|
<span class="stat-value" id="cyc-lowest">—</span>
|
||||||
</div>
|
<span class="stat-label">m lowest</span>
|
||||||
<div class="stat-block">
|
</div>
|
||||||
<span class="stat-value" id="cyc-avg-speed">—</span>
|
<div class="stat-block">
|
||||||
<span class="stat-label">km/h avg speed</span>
|
<span class="stat-value" id="cyc-moving-time">—</span>
|
||||||
|
<span class="stat-label">moving time</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat-block">
|
||||||
|
<span class="stat-value" id="cyc-avg-speed">—</span>
|
||||||
|
<span class="stat-label">km/h avg speed</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<button class="trip-panel-close" data-toggle="trip-cycling-toggle">↑ Close cycling</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -478,29 +484,25 @@ function parseGpxFiles(urls, callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stats toggle
|
function makePanelToggle(toggleId, blockId) {
|
||||||
var statsToggle = document.getElementById('trip-stats-toggle');
|
var toggle = document.getElementById(toggleId);
|
||||||
var statsBlock = document.getElementById('trip-stats-block');
|
var block = document.getElementById(blockId);
|
||||||
if (statsToggle && statsBlock) {
|
if (!toggle || !block) return;
|
||||||
statsToggle.addEventListener('click', function() {
|
toggle.addEventListener('click', function() {
|
||||||
var isOpen = statsBlock.style.display !== 'none';
|
var isOpen = block.classList.contains('is-open');
|
||||||
statsBlock.style.display = isOpen ? 'none' : '';
|
block.classList.toggle('is-open', !isOpen);
|
||||||
statsToggle.classList.toggle('is-active', !isOpen);
|
toggle.classList.toggle('is-active', !isOpen);
|
||||||
statsToggle.setAttribute('aria-expanded', isOpen ? 'false' : 'true');
|
toggle.setAttribute('aria-expanded', isOpen ? 'false' : 'true');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
makePanelToggle('trip-stats-toggle', 'trip-stats-block');
|
||||||
|
makePanelToggle('trip-cycling-toggle', 'trip-cycling-block');
|
||||||
|
|
||||||
// Cycling toggle (only present when has_gpx)
|
// Close buttons inside panels (mobile only via CSS)
|
||||||
var cycToggle = document.getElementById('trip-cycling-toggle');
|
document.querySelectorAll('.trip-panel-close').forEach(function(btn) {
|
||||||
var cycBlock = document.getElementById('trip-cycling-block');
|
var toggleBtn = document.getElementById(btn.getAttribute('data-toggle'));
|
||||||
if (cycToggle && cycBlock) {
|
if (toggleBtn) btn.addEventListener('click', function() { toggleBtn.click(); });
|
||||||
cycToggle.addEventListener('click', function() {
|
});
|
||||||
var isOpen = cycBlock.style.display !== 'none';
|
|
||||||
cycBlock.style.display = isOpen ? 'none' : '';
|
|
||||||
cycToggle.classList.toggle('is-active', !isOpen);
|
|
||||||
cycToggle.setAttribute('aria-expanded', isOpen ? 'false' : 'true');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
/* ── Back to top ─────────────────────────────────────────── */
|
/* ── Back to top ─────────────────────────────────────────── */
|
||||||
|
|||||||
Reference in New Issue
Block a user