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:
@@ -2186,6 +2186,29 @@ html[data-theme="dark"] .ai-reasoning-card {
|
||||
}
|
||||
.post-row:hover { border-color: var(--line-2); }
|
||||
.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 {
|
||||
display: grid;
|
||||
grid-template-columns: 36px 1fr auto;
|
||||
|
||||
@@ -119,7 +119,7 @@ const PostRow = memo(function PostRow({ post, selected, onClick }: PostRowProps)
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`post-row ${selected ? 'selected' : ''}`}
|
||||
className={`post-row ${selected ? 'selected' : ''} ${aiScored ? '' : 'noise'}`}
|
||||
onClick={handleClick}
|
||||
>
|
||||
{/* ── main row ── */}
|
||||
@@ -164,54 +164,45 @@ const PostRow = memo(function PostRow({ post, selected, onClick }: PostRowProps)
|
||||
: (post.text.slice(0, aiScored ? 180 : 90) + (post.text.length > (aiScored ? 180 : 90) ? '…' : ''))}
|
||||
</p>
|
||||
</div>
|
||||
<div className="post-aside">
|
||||
{aiScored ? (
|
||||
<>
|
||||
<SignalPill signal={post.signal} />
|
||||
{/* Target asset chip for actionable signals */}
|
||||
{post.target_asset && (post.signal === 'buy' || post.signal === 'short') && (
|
||||
<span style={{
|
||||
fontSize: 10, fontWeight: 700, fontFamily: 'var(--mono)',
|
||||
padding: '2px 6px', borderRadius: 4,
|
||||
background: post.signal === 'buy' ? 'rgba(34,197,94,0.12)' : 'rgba(239,68,68,0.12)',
|
||||
color: post.signal === 'buy' ? '#22c55e' : '#ef4444',
|
||||
letterSpacing: '0.04em',
|
||||
}}>
|
||||
{post.target_asset}
|
||||
{post.expected_move_pct ? ` +${post.expected_move_pct}%` : ''}
|
||||
</span>
|
||||
{/* 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">
|
||||
<SignalPill signal={post.signal} />
|
||||
{/* Target asset chip for actionable signals */}
|
||||
{post.target_asset && (post.signal === 'buy' || post.signal === 'short') && (
|
||||
<span style={{
|
||||
fontSize: 10, fontWeight: 700, fontFamily: 'var(--mono)',
|
||||
padding: '2px 6px', borderRadius: 4,
|
||||
background: post.signal === 'buy' ? 'rgba(34,197,94,0.12)' : 'rgba(239,68,68,0.12)',
|
||||
color: post.signal === 'buy' ? '#22c55e' : '#ef4444',
|
||||
letterSpacing: '0.04em',
|
||||
}}>
|
||||
{post.target_asset}
|
||||
{post.expected_move_pct ? ` +${post.expected_move_pct}%` : ''}
|
||||
</span>
|
||||
)}
|
||||
<div className="impact-mini">
|
||||
{impact ? (
|
||||
<>
|
||||
<span className="tf">1h peak</span>
|
||||
<span className={`delta ${impact.m1h == null ? '' : impact.m1h >= 0 ? 'up' : 'down'}`}>
|
||||
{impact.m1h == null ? '…' : fmtPct(impact.m1h)}
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<span className="tf">no data</span>
|
||||
)}
|
||||
<div className="impact-mini">
|
||||
{impact ? (
|
||||
<>
|
||||
<span className="tf">1h peak</span>
|
||||
<span className={`delta ${impact.m1h == null ? '' : impact.m1h >= 0 ? 'up' : 'down'}`}>
|
||||
{impact.m1h == null ? '…' : fmtPct(impact.m1h)}
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<span className="tf">no data</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="row gap-s" style={{ fontSize: 11, color: 'var(--ink-3)' }}>
|
||||
<span>AI</span>
|
||||
<span className="mono" style={{ color: 'var(--ink-2)', fontWeight: 500 }}>
|
||||
{post.ai_confidence}%
|
||||
</span>
|
||||
</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 className="row gap-s" style={{ fontSize: 11, color: 'var(--ink-3)' }}>
|
||||
<span>AI</span>
|
||||
<span className="mono" style={{ color: 'var(--ink-2)', fontWeight: 500 }}>
|
||||
{post.ai_confidence}%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* ── expanded detail ── */}
|
||||
|
||||
Reference in New Issue
Block a user