Freshness first row; level clustering; verdict typography;
Deploy / lint (push) Successful in 6s
Deploy / test (push) Successful in 1m5s
Deploy / deploy (push) Successful in 34s

selectable targets drive the rail

- Data freshness is now the very first row of the ticker panel, above
  the symbol - data age is the first thing to check.
- Indicator cards: long price-level lists (pivot swing highs/lows,
  volume-profile HVN/LVN) no longer clip or overwhelm. Numeric lists
  are clustered into ranges (values within ~0.75% of price merge),
  sorted nearest-to-price first, capped at 4 chips with a "+n more"
  note; scalar values wrap instead of overflowing the card.
- Recommendation verdict: the action ("LONG (high confidence)") is set
  in the display face in accent cyan with the risk level beside it;
  the signal breakdown (technical/momentum/sentiment) drops to a small
  muted subtitle line.
- Target ladder is open by default and selectable: clicking a row
  previews that target on the price rail and updates the R:R and
  probability chips, the low-probability warning, and the prefilled
  target in Mark-as-taken (still overridable there). The scanner's
  primary stays the default; a non-primary choice is chipped as
  "custom target".

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-10 12:36:39 +02:00
co-authored by Claude Fable 5
parent 03bdcbd745
commit 9f56a25f2d
3 changed files with 182 additions and 63 deletions
+10 -11
View File
@@ -273,6 +273,15 @@ export default function TickerDetailPage() {
<div className="space-y-6 animate-slide-up">
{/* Drill-down header — identity + chips left, score fingerprint right */}
<section className="glass overflow-hidden">
{/* Data freshness — the very first row: how fresh is what I'm looking at */}
<div className="border-b border-white/[0.06] px-6 py-2.5 sm:px-7">
<DataFreshnessBar
items={dataStatus}
onRefresh={handleRefresh}
pendingLabel={refreshingLabel}
busy={ingestion.isPending}
/>
</div>
<div className="p-6 pb-5 sm:p-7 sm:pb-5">
<div className="flex flex-wrap items-start justify-between gap-x-8 gap-y-5">
<div className="min-w-0">
@@ -361,16 +370,6 @@ export default function TickerDetailPage() {
</div>
</div>
{/* Data freshness — up top: per-source age + refresh, always in view */}
<div className="border-t border-white/[0.06] px-6 py-2.5 sm:px-7">
<DataFreshnessBar
items={dataStatus}
onRefresh={handleRefresh}
pendingLabel={refreshingLabel}
busy={ingestion.isPending}
/>
</div>
{/* Tab row — inline, hairline, overlay pills ride along on Analysis */}
<div className="flex flex-wrap items-center gap-x-6 gap-y-1 border-b border-white/[0.06] px-6 sm:px-7" role="tablist" aria-label="Ticker sections">
{detailTabs.map((t) => (
@@ -510,7 +509,7 @@ export default function TickerDetailPage() {
{activeTab === 'Indicators' && (
<div className="hz-frameless animate-fade-in">
<IndicatorSelector symbol={symbol} />
<IndicatorSelector symbol={symbol} currentPrice={priceInfo?.price} />
</div>
)}