Line up the feed sidebar
Every row reserves the chevron slot, so artwork and titles share one column instead of stepping left when a feed has no children. Children keep a single icon size and read as nested from the indent alone. Labels stack on one line-height, and the unread count has a min-width so a three-digit feed doesn't shove its own title. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AdXho5tTkjFLeUXKbEjKBh
This commit is contained in:
14
PROGRESS.md
14
PROGRESS.md
@@ -56,6 +56,20 @@ and until now nothing set them.
|
||||
|
||||
---
|
||||
|
||||
## 2026-09-10 — Sidebar alignment
|
||||
|
||||
The feed list had four different left edges: a row with no children skipped the chevron entirely, so
|
||||
its artwork sat a chevron-width left of a folder's; children then used a different indent *and* a
|
||||
smaller icon. Nothing lined up with anything.
|
||||
|
||||
Every row now reserves the chevron slot whether or not it opens (an empty one is
|
||||
`pointer-events:none`, so the click falls through to the row), all artwork is one size, and nesting
|
||||
reads from the indent alone. Both label lines are `display:block` on a shared line-height instead of
|
||||
an inline baseline, and the unread count has a `min-width` so three-digit feeds don't shove the
|
||||
title. Rows came out shorter, so more feeds fit without scrolling.
|
||||
|
||||
---
|
||||
|
||||
## 2026-09-10 — An item's picture
|
||||
|
||||
An item's artwork now resolves in order of how deliberate the source is: `itunes:image`, then Media
|
||||
|
||||
@@ -174,7 +174,8 @@ test('an OPML subscription is a collapsible folder', async ({ page }) => {
|
||||
body: JSON.stringify({ feed: 'test-subscriptions', force: true }),
|
||||
}));
|
||||
|
||||
const chev = page.locator('.feed .chev');
|
||||
// Every row reserves the chevron slot for alignment; only a folder's is clickable.
|
||||
const chev = page.locator('.feed.group .chev');
|
||||
await expect(chev).toBeVisible({ timeout: 20_000 });
|
||||
|
||||
// Closed by default: the child is not listed until the folder is opened.
|
||||
|
||||
@@ -92,13 +92,13 @@ input:focus,select:focus{outline:0;border-color:var(--accent)}
|
||||
}
|
||||
.feed:hover{background:var(--panel2)}
|
||||
.feed.sel{background:var(--raise)}
|
||||
.feed.child{margin-left:14px}
|
||||
.feed.child .art{width:28px;height:28px;font-size:11px}
|
||||
.feed.child{margin-left:16px}
|
||||
.chev{
|
||||
flex:none;width:18px;height:18px;display:grid;place-items:center;border-radius:4px;
|
||||
color:var(--faint);font-size:11px;transition:transform .12s;
|
||||
}
|
||||
.chev:hover{background:var(--raise);color:var(--fg)}
|
||||
.chev:empty{pointer-events:none}
|
||||
.chev:not(:empty):hover{background:var(--raise);color:var(--fg)}
|
||||
.chev.open{transform:rotate(90deg)}
|
||||
.childlist{display:grid;gap:4px;margin-top:10px}
|
||||
.childrow{
|
||||
@@ -117,13 +117,13 @@ input:focus,select:focus{outline:0;border-color:var(--accent)}
|
||||
border-radius:7px;object-fit:cover;background:var(--raise);flex:none;
|
||||
display:grid;place-items:center;color:var(--faint);font-weight:700;overflow:hidden;
|
||||
}
|
||||
.feed .art{width:38px;height:38px;font-size:14px}
|
||||
.feed .art{width:34px;height:34px;font-size:13px}
|
||||
.feed .txt{min-width:0;flex:1}
|
||||
.feed .txt b{display:block;font-weight:600;font-size:13.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.feed .txt small{color:var(--faint);font-size:11.5px}
|
||||
.feed .txt b{display:block;font-weight:600;font-size:13.5px;line-height:1.35;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.feed .txt small{display:block;color:var(--faint);font-size:11.5px;line-height:1.35;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.badge{
|
||||
background:var(--accent);color:var(--ink);border-radius:20px;padding:1px 7px;
|
||||
font-size:11px;font-weight:700;flex:none;
|
||||
font-size:11px;font-weight:700;flex:none;min-width:26px;text-align:center;
|
||||
}
|
||||
.badge.zero{background:var(--raise);color:var(--faint)}
|
||||
|
||||
@@ -461,7 +461,7 @@ function renderFeeds(){
|
||||
el.className='feed'+(S.feed===f.id?' sel':'')+(depth?' child':'')+(kids?' group':'');
|
||||
const open = kids && (expanded.has(f.id) || q);
|
||||
el.innerHTML =
|
||||
(kids?`<span class="chev${open?' open':''}" title="Show or hide the feeds inside">▶</span>`:'')+
|
||||
`<span class="chev${open?' open':''}"${kids?' title="Show or hide the feeds inside"':''}>${kids?'▶':''}</span>`+
|
||||
artHTML(f.image,f.title||f.id)+
|
||||
`<div class="txt"><b>${esc(f.title||f.id)}</b><small>`+
|
||||
(kids?`${kids} feed${kids===1?'':'s'}${f.unread?` · ${f.unread} unread`:''}`
|
||||
@@ -470,8 +470,7 @@ function renderFeeds(){
|
||||
(f.orphaned?'<span class="tag" title="No longer listed in the OPML, kept because it has downloads">gone</span>':'')+
|
||||
`<span class="badge${f.unread?'':' zero'}">${f.unread}</span>`;
|
||||
el.onclick=()=>{ selectFeed(f.id); $('#sidebar').classList.remove('open'); };
|
||||
const chev=$('.chev',el);
|
||||
if(chev) chev.onclick=ev=>{ ev.stopPropagation(); toggleGroup(f.id); };
|
||||
if(kids) $('.chev',el).onclick=ev=>{ ev.stopPropagation(); toggleGroup(f.id); };
|
||||
list.appendChild(el);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user