feat(macro-vibes): rename BTC Signal → Macro Vibes; add MacroPanel UI
Module rename across page H1, navbar tab, URL (/en/btc → /en/macro), all metadata/JSON-LD, sitemap, llms.txt, opengraph image, and SystemControl copy. Old /btc route fully removed. New components/btc/MacroPanel.tsx polls /api/macro/snapshot and lays out the 8 indicators in four sections (Valuation / Bottom trigger reference / Market structure / Sentiment & flows / Positioning) with tone-coloured values, current-band threshold chips, and a single CoinGlass / source chart link per card. Composite -100..+100 needle pulses on score change. Also fixes the pinned bottom-reversal alert on the homepage, which still linked to the now-404 /en/btc — now routes to /en/macro. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
'use client'
|
||||
|
||||
/**
|
||||
* Inline "?"" hint icon with a hover tooltip.
|
||||
*
|
||||
* Use this for any UI element whose meaning isn't obvious from its label —
|
||||
* stat boxes, tab names, jargon-y settings. Goal is the same as the (i)
|
||||
* dots in Linear / Hyperliquid / Coinglass: small, ignorable, one hover
|
||||
* away from a one-line plain-English explanation.
|
||||
*
|
||||
* Design rules:
|
||||
* * `text` MUST be one short sentence — never paste long docs in here.
|
||||
* If you need a paragraph, you're explaining the wrong thing.
|
||||
* * The icon is intentionally subtle (12 px circle, ink-4 colour). It
|
||||
* should disappear visually until the user actively scans for help.
|
||||
* * The tooltip uses CSS hover only — no JS positioning, no portals.
|
||||
* Trade-off: it's clipped by the nearest `overflow:hidden` ancestor.
|
||||
* Pages that need tooltips inside a `<table>` cell should add
|
||||
* `overflow: visible` to that row/td.
|
||||
*
|
||||
* Usage:
|
||||
* <span>Latest cycle <InfoTip text="The single most recent funding payment, in %." /></span>
|
||||
*
|
||||
* <InfoTip
|
||||
* text="Last 24h of cycles, averaged. Smooths the noise of one print."
|
||||
* placement="bottom" // default 'top'
|
||||
* />
|
||||
*/
|
||||
|
||||
import type { CSSProperties } from 'react'
|
||||
|
||||
type Placement = 'top' | 'bottom' | 'left' | 'right'
|
||||
|
||||
interface Props {
|
||||
text: string
|
||||
placement?: Placement
|
||||
/** Tip max-width in px. Default 240 — fits ~2 short lines. */
|
||||
width?: number
|
||||
/** Tweak the icon's vertical alignment for fussy contexts. */
|
||||
iconStyle?: CSSProperties
|
||||
}
|
||||
|
||||
export default function InfoTip({
|
||||
text,
|
||||
placement = 'top',
|
||||
width = 240,
|
||||
iconStyle,
|
||||
}: Props) {
|
||||
return (
|
||||
<span
|
||||
className={`infotip infotip-${placement}`}
|
||||
// role=button is a slight overstatement but it lets screen-reader users
|
||||
// know there's a thing to tab to. The actual content is in data-tip and
|
||||
// also as a regular <span> child for non-CSS-tooltip fallback.
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
aria-label={text}
|
||||
style={{ ['--tip-w' as string]: `${width}px`, ...iconStyle }}
|
||||
>
|
||||
<span aria-hidden="true" className="infotip-icon">?</span>
|
||||
<span className="infotip-bubble" role="tooltip">{text}</span>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* One-line "what is this page" tagline that sits right under the page title.
|
||||
*
|
||||
* Replaces ad-hoc <p className="page-sub"> spots that ended up as ghost-gray
|
||||
* unreadable status lines ("Macro cycle bottom · 2 signals"). The new contract:
|
||||
*
|
||||
* * ALWAYS one short sentence — game-tutorial style. Tells the user the
|
||||
* "what" in plain English, not the "how" (the how lives in InfoTip's).
|
||||
* * Slightly bigger + higher contrast than page-sub. Meant to be read,
|
||||
* not glanced past.
|
||||
* * Optional `count` slot for the dim stat ("2 signals", "30 posts").
|
||||
* Renders muted after a separator so the tagline itself stays clean.
|
||||
*/
|
||||
export default function PageHint({
|
||||
children,
|
||||
count,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
count?: string
|
||||
}) {
|
||||
return (
|
||||
<p className="page-hint">
|
||||
{children}
|
||||
{count && (
|
||||
<span className="page-hint-count">{count}</span>
|
||||
)}
|
||||
</p>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user