Add a permanent "Latest" lane beside "Highlights"
Restructure the nav around two permanent lanes, then the reader's chosen ones: "Highlights" (the curated daily brief — formerly "Today") and "Latest" (the freshest accepted stories, newest-first). Now that the gate is tight, a chronological "incoming" feed is safe to expose. * feed(): new sort="latest" (pure recency) alongside the default best-first rank; /api/feed exposes sort=ranked|latest (validated). Still accepted-only and boundary-respecting either way. * lanes.py: two pinned lanes (Highlights + Latest) instead of one. * Home: "Latest" view + "Load more" pagination for every feed view (offset- paged, de-duped). Mobile bottom bar gains a Latest tab. * LanePicker shows both pinned lanes; nav rail renders them first. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,14 +1,18 @@
|
||||
<script>
|
||||
// Mobile-only primary navigation. Today = the brief, Browse = mood/topic
|
||||
// discovery, You = account + personal controls (shows the user's avatar in).
|
||||
// Mobile-only primary navigation. Highlights = the brief, Latest = the
|
||||
// chronological feed, Browse = mood/topic discovery, You = account.
|
||||
import Avatar from './Avatar.svelte';
|
||||
let { active = 'today', onToday, onBrowse, onYou, user = null } = $props();
|
||||
let { active = 'today', onToday, onLatest, onBrowse, onYou, user = null } = $props();
|
||||
</script>
|
||||
|
||||
<nav class="bottomnav" aria-label="Primary">
|
||||
<button class:active={active === 'today'} onclick={onToday}>
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="4.2" fill="none" stroke="currentColor" stroke-width="1.8" /><path d="M12 3v2M12 19v2M3 12h2M19 12h2M5.6 5.6l1.4 1.4M17 17l1.4 1.4M18.4 5.6L17 7M7 17l-1.4 1.4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" /></svg>
|
||||
<span>Today</span>
|
||||
<span>Highlights</span>
|
||||
</button>
|
||||
<button class:active={active === 'latest'} onclick={onLatest}>
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 7h16M4 12h16M4 17h10" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" /></svg>
|
||||
<span>Latest</span>
|
||||
</button>
|
||||
<button class:active={active === 'browse'} onclick={onBrowse}>
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" stroke-width="1.8" /><path d="M15.5 8.5l-2 5-5 2 2-5 5-2z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" /></svg>
|
||||
|
||||
@@ -26,10 +26,12 @@
|
||||
|
||||
{#snippet body()}
|
||||
<h2>Your lanes</h2>
|
||||
<p class="sub">Pick the quick-access lanes above the feed. <strong>Today</strong> always stays — choose the rest. Changes apply right away.</p>
|
||||
<p class="sub"><strong>Highlights</strong> and <strong>Latest</strong> always stay — choose the rest. Changes apply right away.</p>
|
||||
|
||||
<div class="pinned-row">
|
||||
<span class="chip pinned" title="Always shown">Today <span class="lock">📌</span></span>
|
||||
{#each pool?.pinned ?? [] as p (p.key)}
|
||||
<span class="chip pinned" title="Always shown">{p.label} <span class="lock">📌</span></span>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
{#each pool?.groups ?? [] as g (g.name)}
|
||||
|
||||
Reference in New Issue
Block a user