trends sidebar cleanup: minimal display + beige/navy palette
Per Ryan 2026-05-15: - Removed Vector pass footer (no audience value) - Removed PHASE 6b comment - Removed corner brackets + monitoring subtitle + rank prefix - Top 5 entities now show as Sony +12 / Riedel +8 — entity name serif + count mono, right-aligned - Background #F5EFEB (beige; #F5EFFEB had 7 hex chars, interpreted as #F5EFEB) via new --color-trends-bg token - Text #2F4F5B (navy) via new --color-trends-text token - Tokens added to redesign-tokens.css palette section Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -10,17 +10,6 @@ interface Article {
|
||||
published_at: string | null;
|
||||
}
|
||||
|
||||
function ago(iso: string | null): string {
|
||||
if (!iso) return "just now";
|
||||
const t = Date.now() - new Date(iso).getTime();
|
||||
const m = Math.floor(t / 60000);
|
||||
if (m < 60) return `${m}m ago`;
|
||||
return `${Math.floor(m / 60)}h ago`;
|
||||
}
|
||||
|
||||
// Tiny inline entity extractor: count tag occurrences in recent vs older
|
||||
// articles and surface the top 5 by lift. Not vector — just keyword
|
||||
// salience. Phase 6b will replace with pgvector semantic similarity.
|
||||
function detectTrends(recent: Article[], baseline: Article[]) {
|
||||
const recentCounts: Record<string, number> = {};
|
||||
for (const a of recent) for (const t of a.tags || []) {
|
||||
@@ -39,8 +28,11 @@ function detectTrends(recent: Article[], baseline: Article[]) {
|
||||
return { entity: k, lift, count: c };
|
||||
});
|
||||
scored.sort((a, b) => b.lift - a.lift);
|
||||
const top = scored.slice(0, 5);
|
||||
return top;
|
||||
return scored.slice(0, 5);
|
||||
}
|
||||
|
||||
function titleCase(s: string): string {
|
||||
return s.replace(/\b\w/g, (c) => c.toUpperCase());
|
||||
}
|
||||
|
||||
export default async function TrendsSidebar() {
|
||||
@@ -55,7 +47,7 @@ export default async function TrendsSidebar() {
|
||||
|
||||
const since7d = new Date(Date.now() - 7 * 86400000).toISOString();
|
||||
const since30d = new Date(Date.now() - 30 * 86400000).toISOString();
|
||||
const [recent, baseline, total] = await Promise.all([
|
||||
const [recent, baseline] = await Promise.all([
|
||||
sb
|
||||
.from("wp_imported_posts")
|
||||
.select("title, excerpt, tags, wp_published_at")
|
||||
@@ -71,7 +63,6 @@ export default async function TrendsSidebar() {
|
||||
.lt("wp_published_at", since7d)
|
||||
.order("wp_published_at", { ascending: false })
|
||||
.limit(800),
|
||||
sb.from("wp_imported_posts").select("wp_id", { count: "exact", head: true }).eq("status", "published"),
|
||||
]);
|
||||
|
||||
const recentArts: Article[] = (recent.data || []).map((r: any) => ({
|
||||
@@ -82,47 +73,37 @@ export default async function TrendsSidebar() {
|
||||
}));
|
||||
const trends = detectTrends(recentArts, baselineArts);
|
||||
|
||||
const nowIso = new Date().toISOString();
|
||||
|
||||
return (
|
||||
<aside
|
||||
className="rounded border border-[#252525] bg-[var(--color-background-secondary,#111)] p-4 relative"
|
||||
style={{ borderRadius: "var(--border-radius-md,6px)" }}
|
||||
className="rounded p-4"
|
||||
style={{
|
||||
background: "var(--color-trends-bg, #F5EFEB)",
|
||||
color: "var(--color-trends-text, #2F4F5B)",
|
||||
borderRadius: "var(--border-radius-md, 6px)",
|
||||
}}
|
||||
aria-label="BB AI detected trends"
|
||||
>
|
||||
<span aria-hidden className="absolute top-2 left-2 w-3 h-3 border-t border-l border-[var(--color-text-info,#60a5fa)]" />
|
||||
<span aria-hidden className="absolute bottom-2 right-2 w-3 h-3 border-b border-r border-[var(--color-text-info,#60a5fa)]" />
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<h2 className="font-serif text-base font-semibold">BB AI · detected trends</h2>
|
||||
<span className="inline-flex items-center gap-1.5 text-[10px] font-mono uppercase tracking-wider text-[var(--color-text-info,#60a5fa)]">
|
||||
<span className="bb-pulse-dot" />
|
||||
<span className="inline-flex items-center gap-1.5 text-[10px] font-mono uppercase tracking-wider opacity-70">
|
||||
<span className="bb-pulse-dot" style={{ background: "var(--color-trends-text, #2F4F5B)" }} />
|
||||
live
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-[10px] font-mono text-[#6b7280] mt-1">
|
||||
monitoring 47 sources · 24h
|
||||
</p>
|
||||
|
||||
<ol className="mt-4 space-y-2">
|
||||
<ul className="space-y-1.5">
|
||||
{trends.length === 0 && (
|
||||
<li className="text-xs text-[#6b7280]">No trend data yet.</li>
|
||||
<li className="text-xs opacity-60">No trend data yet.</li>
|
||||
)}
|
||||
{trends.map((t, i) => (
|
||||
<li key={t.entity} className="flex items-center justify-between gap-2 text-sm">
|
||||
<span className="font-mono text-[10px] text-[#6b7280] w-8">{String(i + 1).padStart(2, "0")}</span>
|
||||
<span className="flex-1 truncate text-[#e5e7eb]">{t.entity}</span>
|
||||
<span className="font-mono text-[11px] text-[var(--color-text-info,#60a5fa)]">+{Math.round((t.lift - 1) * 100) || t.count}</span>
|
||||
{trends.map((t) => (
|
||||
<li key={t.entity} className="flex items-center justify-between text-sm">
|
||||
<span className="truncate font-serif">{titleCase(t.entity)}</span>
|
||||
<span className="font-mono text-[12px] opacity-80">
|
||||
+{Math.round((t.lift - 1) * 100) || t.count}
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
|
||||
<div className="mt-4 pt-3 border-t border-[#252525] text-[10px] font-mono text-[#6b7280]">
|
||||
Vector pass {ago(nowIso)} · n={(total.count || 0).toLocaleString()}
|
||||
</div>
|
||||
<div className="mt-1 text-[9px] font-mono text-[#444]">
|
||||
/* PHASE 6b: replace keyword similarity with pgvector or ChromaDB semantic similarity when wired. */
|
||||
</div>
|
||||
</ul>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
--color-text-warning: #f59e0b;
|
||||
--color-text-danger: #ef4444;
|
||||
|
||||
/* Trends sidebar palette (Ryan, 2026-05-15) */
|
||||
--color-trends-bg: #F5EFEB;
|
||||
--color-trends-text: #2F4F5B;
|
||||
|
||||
/* Type families */
|
||||
--font-serif: Georgia, "Times New Roman", "Tinos", serif;
|
||||
--font-mono: "JetBrains Mono", "Fira Code", "Courier New", Courier, monospace;
|
||||
|
||||
Reference in New Issue
Block a user