fix: proper 2-column layout with scroll, header above columns, side padding

This commit is contained in:
haerikimmm
2026-06-16 19:33:50 +09:00
parent d157055ab7
commit 6f41f6e53e

View File

@@ -65,54 +65,56 @@
/> />
</div> </div>
{:else} {:else}
<div class="two-col"> <div class="list-view">
<div class="left-col"> <div class="page-header">
<div class="page-header"> <h1 class="page-title">My Journey</h1>
<h1 class="page-title">My Journey</h1> <button class="new-btn" onclick={() => { view = 'new'; }}>
<button class="new-btn" onclick={() => { view = 'new'; }}> <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"> <path d="M12 5v14M5 12h14"/>
<path d="M12 5v14M5 12h14"/> </svg>
</svg> Add trip
Add trip </button>
</button>
</div>
<TimelineToolbar {sortKey} onSort={(k) => (sortKey = k)} />
{#if sortedEntries.length === 0}
<p class="empty">No journal entries yet.</p>
{:else}
<div class="sort-row">
<span class="sort-label">Sort by</span>
<select class="sort-select" onchange={(e) => (sortKey = e.currentTarget.value)}>
<option value="date-desc" selected={sortKey === 'date-desc'}>Newest first</option>
<option value="date-asc" selected={sortKey === 'date-asc'}>Oldest first</option>
<option value="country-asc" selected={sortKey === 'country-asc'}>Country A Z</option>
<option value="country-desc" selected={sortKey === 'country-desc'}>Country Z A</option>
</select>
</div>
<ol class="v-list">
{#each sortedEntries as entry, i (entry.id)}
{#if i === 0 || getYear(entry.date) !== getYear(sortedEntries[i - 1].date)}
<li class="year-marker" aria-hidden="true">
<span class="year-label">{getYear(entry.date)}</span>
</li>
{/if}
<TimelineCard {entry} onClick={() => { selectedId = entry.id; view = 'detail'; onDetailChange(true); }} />
{/each}
</ol>
{/if}
<footer class="page-footer">
{sortedEntries.length} {sortedEntries.length === 1 ? 'trip' : 'trips'}
</footer>
</div> </div>
{#if sortedEntries.length > 0} <div class="two-col">
<div class="right-col"> <div class="left-col">
<SharePreview entries={sortedEntries} onClick={() => (showShare = true)} /> <TimelineToolbar {sortKey} onSort={(k) => (sortKey = k)} />
{#if sortedEntries.length === 0}
<p class="empty">No journal entries yet.</p>
{:else}
<div class="sort-row">
<span class="sort-label">Sort by</span>
<select class="sort-select" onchange={(e) => (sortKey = e.currentTarget.value)}>
<option value="date-desc" selected={sortKey === 'date-desc'}>Newest first</option>
<option value="date-asc" selected={sortKey === 'date-asc'}>Oldest first</option>
<option value="country-asc" selected={sortKey === 'country-asc'}>Country A Z</option>
<option value="country-desc" selected={sortKey === 'country-desc'}>Country Z A</option>
</select>
</div>
<ol class="v-list">
{#each sortedEntries as entry, i (entry.id)}
{#if i === 0 || getYear(entry.date) !== getYear(sortedEntries[i - 1].date)}
<li class="year-marker" aria-hidden="true">
<span class="year-label">{getYear(entry.date)}</span>
</li>
{/if}
<TimelineCard {entry} onClick={() => { selectedId = entry.id; view = 'detail'; onDetailChange(true); }} />
{/each}
</ol>
{/if}
<footer class="page-footer">
{sortedEntries.length} {sortedEntries.length === 1 ? 'trip' : 'trips'}
</footer>
</div> </div>
{/if}
{#if sortedEntries.length > 0}
<div class="right-col">
<SharePreview entries={sortedEntries} onClick={() => (showShare = true)} />
</div>
{/if}
</div>
</div> </div>
{/if} {/if}
@@ -132,41 +134,42 @@
overflow: hidden; overflow: hidden;
} }
/* ── Two-column layout ── */ /* ── List view wrapper (scrollable) ── */
.two-col { .list-view {
flex: 1; flex: 1;
overflow-y: auto;
padding: 48px 48px 80px;
box-sizing: border-box;
min-width: 0;
}
/* ── Two-column below header ── */
.two-col {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
min-width: 0; gap: 32px;
height: 100%; align-items: flex-start;
overflow: hidden; margin-top: 24px;
} }
.left-col { .left-col {
flex: 1; flex: 1;
min-width: 0; min-width: 0;
overflow-y: auto;
padding: 48px 48px 80px;
box-sizing: border-box;
max-width: 680px;
} }
.right-col { .right-col {
width: 280px; width: 260px;
flex-shrink: 0; flex-shrink: 0;
overflow-y: auto; position: sticky;
padding: 48px 24px 80px; top: 0;
border-left: 1px solid var(--border);
box-sizing: border-box;
} }
@media (max-width: 900px) { @media (max-width: 900px) {
.right-col { display: none; } .right-col { display: none; }
.left-col { max-width: 100%; }
} }
@media (max-width: 760px) { @media (max-width: 760px) {
.left-col { padding: 32px 24px 60px; } .list-view { padding: 32px 24px 60px; }
} }
/* ── Detail view ── */ /* ── Detail view ── */