style(feed): compact, recessed layout for off-topic posts

Off-topic posts are the bulk of the Trump feed but carry no signal. Before,
each rendered as a full-size card identical to real signals, making the feed
long and sparse and burying the ~15 actionable posts.

Now noise posts (.post-row.noise) render as a compact, recessed two-column
row: sunk background, 22px dimmed avatar, no aside column, tight padding,
smaller text. The lone floating 'SKIPPED' tag is gone (the meta-line
'off-topic · not crypto' chip already conveys it). Real signal cards are
unchanged — they now visually pop against the muted noise rows.

Verified in the browser: ~6 noise rows per screen (was ~3 cards), and the
'Hide off-topic' toggle collapses to a clean signal-only stream.

tsc clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
k
2026-05-30 03:32:24 +08:00
parent c8dd7176fa
commit 90cccd422b
2 changed files with 62 additions and 48 deletions
+23
View File
@@ -2186,6 +2186,29 @@ html[data-theme="dark"] .ai-reasoning-card {
} }
.post-row:hover { border-color: var(--line-2); } .post-row:hover { border-color: var(--line-2); }
.post-row.selected { border-color: var(--amber-ring); background: oklch(99% 0.02 85); } .post-row.selected { border-color: var(--amber-ring); background: oklch(99% 0.02 85); }
/* Off-topic / noise posts: compact, recessed, low-emphasis. They're the bulk
of the Trump feed but carry no signal — make them read as skippable filler
so the eye lands on the real signals. */
.post-row.noise {
background: var(--bg-sunk);
border-color: transparent;
}
.post-row.noise:hover { border-color: var(--line); }
.post-row.noise .post-row-main {
grid-template-columns: 22px 1fr; /* drop the aside column */
gap: 10px;
padding: 8px 14px;
align-items: center;
}
.post-row.noise .src-ico {
width: 22px; height: 22px;
font-size: 11px; border-radius: 6px;
opacity: 0.45;
align-self: center;
}
.post-row.noise .post-body .meta { margin-bottom: 2px; }
.post-row.noise .post-body .text { margin: 0; font-size: 13px; }
.post-row-main { .post-row-main {
display: grid; display: grid;
grid-template-columns: 36px 1fr auto; grid-template-columns: 36px 1fr auto;
+6 -15
View File
@@ -119,7 +119,7 @@ const PostRow = memo(function PostRow({ post, selected, onClick }: PostRowProps)
return ( return (
<div <div
className={`post-row ${selected ? 'selected' : ''}`} className={`post-row ${selected ? 'selected' : ''} ${aiScored ? '' : 'noise'}`}
onClick={handleClick} onClick={handleClick}
> >
{/* ── main row ── */} {/* ── main row ── */}
@@ -164,9 +164,11 @@ const PostRow = memo(function PostRow({ post, selected, onClick }: PostRowProps)
: (post.text.slice(0, aiScored ? 180 : 90) + (post.text.length > (aiScored ? 180 : 90) ? '…' : ''))} : (post.text.slice(0, aiScored ? 180 : 90) + (post.text.length > (aiScored ? 180 : 90) ? '…' : ''))}
</p> </p>
</div> </div>
{/* Aside (signal pill / target / impact / AI%) only for scored posts.
Noise posts render as a compact two-column row (no aside) — the
'off-topic · not crypto' tag in the meta line is enough. */}
{aiScored && (
<div className="post-aside"> <div className="post-aside">
{aiScored ? (
<>
<SignalPill signal={post.signal} /> <SignalPill signal={post.signal} />
{/* Target asset chip for actionable signals */} {/* Target asset chip for actionable signals */}
{post.target_asset && (post.signal === 'buy' || post.signal === 'short') && ( {post.target_asset && (post.signal === 'buy' || post.signal === 'short') && (
@@ -199,19 +201,8 @@ const PostRow = memo(function PostRow({ post, selected, onClick }: PostRowProps)
{post.ai_confidence}% {post.ai_confidence}%
</span> </span>
</div> </div>
</>
) : (
// Noise post: no signal, no AI score. Show a single muted SKIPPED
// tag instead of HOLD pill + empty AI metric, so the row reads as
// "ignore this" at a glance.
<span style={{
fontSize: 10, fontWeight: 700, letterSpacing: '0.06em',
color: 'var(--ink-4)', textTransform: 'uppercase',
}}>
skipped
</span>
)}
</div> </div>
)}
</div> </div>
{/* ── expanded detail ── */} {/* ── expanded detail ── */}