From d63821426ffeb2abb48eb93ae37e93de2495058f Mon Sep 17 00:00:00 2001 From: 0X-SquidSol Date: Wed, 6 May 2026 11:02:43 -0400 Subject: [PATCH 1/5] fix(trade): bump label / informational text contrast across trade UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The trade page was systematically using --text-dim (#2A2E3D) and --text-muted (#454B5F) for static labels and informational text on the dark surface. Both tokens render below comfortable readability for body content — they're intended for placeholder-style text and disabled states, not labels users need to scan. Promoting these to --text where they're labels and --text-secondary where they're inactive interactable elements. Input placeholders, no-data states ("Connect wallet to view NFT status", "Data will appear after cranks"), and decorative row indices keep their subdued tokens — those communicate "this is empty / disabled" by design. Files touched and rationale: TradeForm.tsx Labels (Order Type, Size, Order Leverage, Bal:, SOL/USD, SOL/USD unit suffixes, x suffix, Coin-margined market, inline Entry/Liq/Size/PnL/RiskLeverage labels) → --text. Inactive Long button when Short is selected, % presets, leverage presets → --text-secondary (still readable, but the active state still wins). Mainnet Phase 1 Guards bullets → --text (they're substantive policy info, not asides). Tx-signature link footer → --text-secondary. MarketStatsCard.tsx Stat labels (MARK / INDEX / SPREAD / OPEN INTEREST / VAULT / FUNDING/8H / TRADING FEE / INIT MARGIN / ACCOUNTS) → --text. "Funding History" toggle row → --text-secondary at rest, --text on hover (matches the chart toolbar contrast scheme). PositionNftPanel.tsx "Position NFT" / "Status" / "Mint" labels → --text. The "Connect wallet to view NFT status" no-data message stays --text-dim — bumping it would falsely advertise content. MarketBookCard.tsx "Order Book" header, Bid / Oracle / Ask column headers, Spread row label, LP table column headers → --text. Hide-book button (interactable) → --text-secondary at rest, --text on hover. "+N more" overflow row → --text-secondary. Spread % parenthetical bumped from --text-dim/60 (impossibly faint) to --text-secondary. Per-LP row indices and the conditional util-color-when-low stay --text-dim — they're decorative. FundingRateCard.tsx Funding Rate label (loading + loaded states), /8h suffix, Last N periods label, Est. 24h label → --text. "next {countdown}" parenthetical → --text-secondary. FundingRateChart.tsx "Funding Rate (24h)" header → --text. Hovered-point timestamp (a tooltip-like detail) → --text-secondary. "Data will appear after cranks" empty-state stays --text-dim. app/trade/[slab]/page.tsx — Tabs component Inactive tab text bumped from --text-muted to --text-secondary, with hover going from --text-secondary to --text. Matches the chart toolbar's two-tier rest+hover contrast pattern. Borders are intentionally untouched — modern dark UIs use low-alpha borders (5–15%) for subtle structure; bumping to white would create a wireframe / cage effect that fights with content. Tests: 2277 passing, no regressions. --- app/app/trade/[slab]/page.tsx | 2 +- app/components/trade/FundingRateCard.tsx | 12 +++---- app/components/trade/FundingRateChart.tsx | 4 +-- app/components/trade/MarketBookCard.tsx | 20 +++++------ app/components/trade/MarketStatsCard.tsx | 6 ++-- app/components/trade/PositionNftPanel.tsx | 6 ++-- app/components/trade/TradeForm.tsx | 42 +++++++++++------------ 7 files changed, 46 insertions(+), 46 deletions(-) diff --git a/app/app/trade/[slab]/page.tsx b/app/app/trade/[slab]/page.tsx index 81acdc30..4de60a7e 100644 --- a/app/app/trade/[slab]/page.tsx +++ b/app/app/trade/[slab]/page.tsx @@ -110,7 +110,7 @@ function Tabs({ tabs, children, defaultTab }: { tabs: string[]; children: React. className={`shrink-0 px-3 py-1.5 text-[10px] font-medium uppercase tracking-[0.15em] transition-colors border-b-2 ${ active === i ? "border-[var(--accent)] text-[var(--accent)]" - : "border-transparent text-[var(--text-muted)] hover:text-[var(--text-secondary)] hover:border-[var(--border)]" + : "border-transparent text-[var(--text-secondary)] hover:text-[var(--text)] hover:border-[var(--border)]" }`} > {label} diff --git a/app/components/trade/FundingRateCard.tsx b/app/components/trade/FundingRateCard.tsx index 3ca1fad5..4c54e988 100644 --- a/app/components/trade/FundingRateCard.tsx +++ b/app/components/trade/FundingRateCard.tsx @@ -239,7 +239,7 @@ export const FundingRateCard: FC<{ slabAddress: string }> = ({ slabAddress }) => return (
- Funding Rate + Funding Rate
@@ -266,7 +266,7 @@ export const FundingRateCard: FC<{ slabAddress: string }> = ({ slabAddress }) => {/* Header row: label + rate + APR */}
- + Funding Rate @@ -284,7 +284,7 @@ export const FundingRateCard: FC<{ slabAddress: string }> = ({ slabAddress }) => > {rateDisplay} - /8h + /8h
@@ -293,7 +293,7 @@ export const FundingRateCard: FC<{ slabAddress: string }> = ({ slabAddress }) =>
{directionText} {countdown > 0 && ( - · next {formatCountdown(countdown)} + · next {formatCountdown(countdown)} )}
@@ -304,7 +304,7 @@ export const FundingRateCard: FC<{ slabAddress: string }> = ({ slabAddress }) => {/* P3-4: Mini bar chart — last 4 periods */} {miniChartRates.length > 0 && (
- Last {miniChartRates.length} periods + Last {miniChartRates.length} periods
)} @@ -313,7 +313,7 @@ export const FundingRateCard: FC<{ slabAddress: string }> = ({ slabAddress }) => {positionDirection && estimatedFunding24h !== null && (
- + Est. 24h ({positionDirection}) diff --git a/app/components/trade/FundingRateChart.tsx b/app/components/trade/FundingRateChart.tsx index 2232509c..c8c058f7 100644 --- a/app/components/trade/FundingRateChart.tsx +++ b/app/components/trade/FundingRateChart.tsx @@ -250,7 +250,7 @@ export const FundingRateChart: FC<{ slabAddress: string }> = ({ slabAddress }) = return (
-

+

Funding Rate (24h)

@@ -258,7 +258,7 @@ export const FundingRateChart: FC<{ slabAddress: string }> = ({ slabAddress }) = {(hoveredPoint?.hourlyRatePercent ?? 0) >= 0 ? "+" : ""} {(hoveredPoint?.hourlyRatePercent ?? 0).toFixed(4)}%/h
-
+
{hoveredPoint ? new Date(hoveredPoint.timestamp).toLocaleString() : "\u00A0"}
diff --git a/app/components/trade/MarketBookCard.tsx b/app/components/trade/MarketBookCard.tsx index 375cce04..225eb53b 100644 --- a/app/components/trade/MarketBookCard.tsx +++ b/app/components/trade/MarketBookCard.tsx @@ -75,7 +75,7 @@ export const MarketBookCard: FC = () => { {/* Header with hide control — lets the user collapse the order book when they prefer a cleaner trade view. Persists via localStorage. */}
- + Order Book @@ -93,12 +93,12 @@ export const MarketBookCard: FC = () => {
{/* Bid */}
-

Bid

+

Bid

{formatUsdPriceE6(bestBidE6)}

{/* Oracle — subtle accent border + bg */}
-

Oracle

+

Oracle

{

{/* Ask */}
-

Ask

+

Ask

{formatUsdPriceE6(bestAskE6)}

@@ -116,10 +116,10 @@ export const MarketBookCard: FC = () => { {/* 2.2: Spread row */} {oraclePrice > 0n && (
- Spread - + Spread + ${spreadUsd.toFixed(spreadUsd < 0.001 ? 6 : 4)}{" "} - ({spreadPct.toFixed(3)}%) + ({spreadPct.toFixed(3)}%)
)} @@ -164,7 +164,7 @@ export const MarketBookCard: FC = () => { {lps.length > 0 && (
{/* Header */} -
+
# L.P. Capital @@ -204,7 +204,7 @@ export const MarketBookCard: FC = () => { {/* +N more row */} {hiddenLpCount > 0 && (
- +{hiddenLpCount} more + +{hiddenLpCount} more
)}
diff --git a/app/components/trade/MarketStatsCard.tsx b/app/components/trade/MarketStatsCard.tsx index f0918142..aec720fc 100644 --- a/app/components/trade/MarketStatsCard.tsx +++ b/app/components/trade/MarketStatsCard.tsx @@ -241,7 +241,7 @@ export const MarketStatsCard: FC = () => { className="min-w-0 overflow-hidden" >

@@ -271,10 +271,10 @@ export const MarketStatsCard: FC = () => {

{showFundingChart && (
diff --git a/app/components/trade/PositionNftPanel.tsx b/app/components/trade/PositionNftPanel.tsx index b1fd20d5..cad08f33 100644 --- a/app/components/trade/PositionNftPanel.tsx +++ b/app/components/trade/PositionNftPanel.tsx @@ -61,7 +61,7 @@ export const PositionNftPanel: FC<{ slabAddress: string }> = ({ slabAddress }) = return (
-

Position NFT

+

Position NFT

Connect wallet to view NFT status.

@@ -91,7 +91,7 @@ export const PositionNftPanel: FC<{ slabAddress: string }> = ({ slabAddress }) =
{/* Status row */}
- Status + Status = ({ slabAddress }) = {/* Mint address — shown when NFT exists */} {hasMintedNft && mintAddress && (
- Mint + Mint = ({ slabAddress }) => { {isOpenLong ? "LONG" : "SHORT"} - {symbol}/USD + {symbol}/USD = ({ slabAddress }) => { {/* Stats grid */}
- Entry + Entry {openEntryPriceE6 > 0n ? formatUsdPriceE6(openEntryPriceE6) : "—"}
- + Liq {openLiqDanger ? "⚠" : ""} @@ -573,13 +573,13 @@ export const TradeForm: FC<{ slabAddress: string }> = ({ slabAddress }) => {
- Size + Size {formatTokenAmount(abs(openPositionSize), decimals)} {symbol}
- PnL + PnL 0n ? "text-green-400" : openPnlTokens < 0n ? "text-red-400" : "text-[var(--text-muted)]"}`}> {openPnlTokens >= 0n ? "+" : ""}{formatTokenAmount(openPnlTokens, decimals)} ({openPnlPercent >= 0 ? "+" : ""}{openPnlPercent.toFixed(2)}%) @@ -587,7 +587,7 @@ export const TradeForm: FC<{ slabAddress: string }> = ({ slabAddress }) => {
{savedOpenLeverage != null && (
- {RISK_LEVERAGE_LABEL} + {RISK_LEVERAGE_LABEL} {formatLeverage(openAccountLeverage)} @@ -667,7 +667,7 @@ export const TradeForm: FC<{ slabAddress: string }> = ({ slabAddress }) => { {/* Order type indicator — market orders only */}
- Order Type + Order Type Market @@ -681,7 +681,7 @@ export const TradeForm: FC<{ slabAddress: string }> = ({ slabAddress }) => { className={`flex-1 rounded-none py-2.5 text-[11px] font-bold uppercase tracking-[0.1em] transition-all duration-150 ${ direction === "long" ? "bg-green-500 border border-green-500 text-black" - : "border border-[var(--border)] bg-[var(--bg-surface)] text-[var(--text-dim)]" + : "border border-[var(--border)] bg-[var(--bg-surface)] text-[var(--text-secondary)]" }`} > Long @@ -702,8 +702,8 @@ export const TradeForm: FC<{ slabAddress: string }> = ({ slabAddress }) => { {/* ── Dual size input (contracts ↔ USDC) ── */}
- - + + Bal: {userAccount ? formatPerc(capital, decimals) : (walletAtaBalance !== null ? formatPerc(walletAtaBalance, decimals) : "—")} {collateralSymbol}
@@ -725,7 +725,7 @@ export const TradeForm: FC<{ slabAddress: string }> = ({ slabAddress }) => { } ${exceedsMargin ? "border-[var(--short)]/50 bg-[var(--short)]/5" : ""}`} />
- {symbol} + {symbol}
{/* USDC input */}
@@ -744,7 +744,7 @@ export const TradeForm: FC<{ slabAddress: string }> = ({ slabAddress }) => { }`} />
- USD + USD
{exceedsMargin && ( @@ -760,7 +760,7 @@ export const TradeForm: FC<{ slabAddress: string }> = ({ slabAddress }) => { @@ -770,7 +770,7 @@ export const TradeForm: FC<{ slabAddress: string }> = ({ slabAddress }) => { {/* Leverage slider + presets */}
-
= ({ slabAddress }) => { className={`flex-1 basis-0 min-w-[32px] rounded-none py-1.5 min-h-[36px] text-[9px] font-medium transition-all duration-150 focus-visible:ring-1 focus-visible:ring-[var(--accent)]/30 touch-manipulation ${ leverage === l ? "bg-[var(--accent)] text-white" - : "border border-[var(--border)] text-[var(--text-muted)] hover:border-[var(--accent)]/50 hover:text-[var(--text-secondary)]" + : "border border-[var(--border)] text-[var(--text-secondary)] hover:border-[var(--accent)]/50 hover:text-[var(--text)]" }`} > {l}x @@ -833,9 +833,9 @@ export const TradeForm: FC<{ slabAddress: string }> = ({ slabAddress }) => { {getNetwork() === "mainnet" && (

⚡ Mainnet Phase 1 Guards Active

-

• $10K OI cap per market during beta

-

• {maxLeverage}x max leverage enforced on-chain

-

• Guards auto-lift when caps are raised by DAO

+

• $10K OI cap per market during beta

+

• {maxLeverage}x max leverage enforced on-chain

+

• Guards auto-lift when caps are raised by DAO

)} @@ -966,7 +966,7 @@ export const TradeForm: FC<{ slabAddress: string }> = ({ slabAddress }) => { )} {lastSig && ( -

+

Tx:{" "} = ({ slabAddress }) => {

{/* Close position modal */} From 36f2feef2c6bcfb2c3747db264dae39da7820739 Mon Sep 17 00:00:00 2001 From: 0X-SquidSol Date: Wed, 6 May 2026 11:20:14 -0400 Subject: [PATCH 2/5] fix(trade): bump positions panel + accounts card label contrast MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The positions panel (empty state, populated state, and Add Margin modal) and the accounts card (sub-tabs, column headers, empty states) were still using --text-dim / --text-muted for labels and informational text, on the same dark surface where the rest of the trade page just got bumped. This commit extends the same two-tier scheme: --text for labels and primary empty-state messages, --text-secondary for helper text, no-data hints, and inactive interactable controls. Files touched: PositionsTable.tsx Two empty-state primary messages ("No open positions") → --text; helper paragraphs ("Connect your wallet…", "Use the trade form…") → --text-secondary. Column headers (Market / Side / Size / Entry / Mark / Liq. Price / PnL / ROE% / Close) → --text. Symbol unit suffix in the Size cell → --text-secondary. The decorative svg icon, the "--" placeholder when mark is missing, and the conditional zero-value colors (PnL / ROE / Liq when out of range) intentionally stay dim — they communicate absence of data, which white text would falsely advertise. PositionPanel.tsx Populated-state labels (Size, Entry Price, Funding/8h, Market Price, Liq. Price, Margin Health, Risk Lev., Order Lev., Est. Funding (24h), Unrealized PnL) → --text. Empty-state primary message → --text; helper text → --text-secondary. Add Margin modal: Amount label → --text; close × button → --text-secondary at rest, --text on hover; description paragraph + Tx footer → --text-secondary. USD secondary value next to the contracts size, funding countdown parenthetical, and "Waiting for price data…" hint → --text-secondary. AccountsCard.tsx Sub-tabs (Open / Idle / Leaderboard) → --text-secondary at rest, --text on hover. "{N} total" right-aligned counter → --text-secondary. Empty-state line → --text. Column header row → --text. SortHeader hover changed from text-secondary to --accent: with the parent row now at --text, the previous hover would have dimmed the column on mouseover (brightness reversal). Switching hover to accent gives a color shift instead, with transition-colors added for smooth fade. Tests: 139 trade-component tests passing. The remaining dim/muted in these files are all conditional value colors for no-data states (loading, IDLE rows, decorative row indices, zero-PnL, absent mark price) — left intentionally subdued. --- app/components/trade/AccountsCard.tsx | 10 +++--- app/components/trade/PositionPanel.tsx | 42 ++++++++++++------------- app/components/trade/PositionsTable.tsx | 12 +++---- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/app/components/trade/AccountsCard.tsx b/app/components/trade/AccountsCard.tsx index 43c253ee..3a7c91d3 100644 --- a/app/components/trade/AccountsCard.tsx +++ b/app/components/trade/AccountsCard.tsx @@ -121,7 +121,7 @@ export const AccountsCard: FC = () => { const isOpenLike = tab === "open" || tab === "leaderboard"; const SortHeader: FC<{ label: string; sKey: SortKey; align?: "left" | "right"; className?: string }> = ({ label, sKey, align = "right", className = "" }) => ( - toggleSort(sKey)} className={`cursor-pointer select-none whitespace-nowrap px-2 py-1.5 font-medium ${align === "left" ? "text-left" : "text-right"} hover:text-[var(--text-secondary)] ${className}`}> + toggleSort(sKey)} className={`cursor-pointer select-none whitespace-nowrap px-2 py-1.5 font-medium transition-colors ${align === "left" ? "text-left" : "text-right"} hover:text-[var(--accent)] ${className}`}> {label} {sortKey === sKey ? {sortDir === "asc" ? "^" : "v"} : ""} @@ -139,23 +139,23 @@ export const AccountsCard: FC = () => { {tabs.map((t) => ( ))} - {accounts.length} total + {accounts.length} total
{sortedRows.length === 0 ? ( -

+

{tab === "open" ? "No open positions" : tab === "idle" ? "No idle accounts" : "No data"}

) : (
- + {isOpenLike && } diff --git a/app/components/trade/PositionPanel.tsx b/app/components/trade/PositionPanel.tsx index 341acc7b..a2b4bb4f 100644 --- a/app/components/trade/PositionPanel.tsx +++ b/app/components/trade/PositionPanel.tsx @@ -123,18 +123,18 @@ const AddMarginModal: FC = ({ slabAddress, userIdx, symbol, Add Margin -

+

Deposit additional collateral to increase your margin and reduce liquidation risk.

-
- + @@ -222,7 +222,7 @@ export const PositionsTable: FC<{ slabAddress: string }> = ({ slabAddress }) => {/* Size */} {/* Entry */} From ec854ba37f95f10a2945a0ddb4fe398a5e9c895c Mon Sep 17 00:00:00 2001 From: 0X-SquidSol Date: Wed, 6 May 2026 11:29:35 -0400 Subject: [PATCH 3/5] fix(markets): bump label and inactive-filter contrast on browse page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The /markets browse page was using --text-dim for table column headers, the row subtitle (mint/name line under each symbol), the "manual" oracle pill, and the end-of-list footer; --text-muted for the FILTER: label and every inactive filter / sort tab. On the dark surface those tokens render below comfortable readability for body content. Same two-tier scheme as the trade page now applies: labels and headers go to --text, inactive interactable controls go to --text-secondary at rest with hover brightening to --text. Specifics: Heading "All Markets" — the "All " span was --text/50 (50% opacity), making the word noticeably faded. Hierarchy is now carried by font-weight alone (normal vs medium) instead of brightness, so "All" sits at full text but reads lighter than the medium-weight "Markets". Filter row — "FILTER:" label → --text. All inactive filter pills (TOKENS/USD, ALL/5x+/10x+/20x+, ALL ORACLES/LIVE FEED/ MANUAL) and the four sort tabs (VOLUME/OI/HEALTH/RECENT) move from --text-muted/hover-text to --text-secondary/hover-text. Active states untouched (accent fill + accent text). Search clear (×) button — was --text-dim → hover:--text-secondary (very dim → medium, both subdued); now --text-secondary → hover:--text (medium → bright). Added transition-colors. Table column headers (token/price/OI/vol/insurance/max lev/ health) → --text. They're the same hierarchical level as the row data values; subdued labels misframed them as decorative. Row metadata — the per-row mint/name subtitle bumped to --text-secondary so the address shorten is readable without competing with the primary symbol/USD title above it. "manual" oracle pill — text bumped to --text-secondary while the border (/30 alpha) and background (/0.08 alpha) stay --text-dim. Preserves the "less authoritative oracle" subdued visual semantic while making the label readable; without this the pill was effectively invisible against the row. End-of-list footer "all N markets loaded" → --text-secondary. What stays subdued: - The search-bar magnifying-glass SVG (decorative inside input) - placeholder-[var(--text-dim)] on the search input itself (placeholder UX convention) - The mobile-only "·" filter-group separators (decorative) - "Loading more…" infinite-scroll indicator (transient state) Tests: full app suite 2277 passing, 0 failures. --- app/app/markets/page.tsx | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/app/app/markets/page.tsx b/app/app/markets/page.tsx index dadaf4ab..6f59550c 100644 --- a/app/app/markets/page.tsx +++ b/app/app/markets/page.tsx @@ -580,7 +580,7 @@ function MarketsPageInner() { // browse

- All Markets + All Markets

perpetual futures, pick your poison.

@@ -609,7 +609,7 @@ function MarketsPageInner() { {hasSearch && ( @@ -783,7 +783,7 @@ export const CreateMarketWizard: FC<{ initialMint?: string }> = ({ initialMint } {/* GH#1615: Use display step/total/label so Quick Launch shows "STEP 2 / 3 — Slab Tier" instead of the confusing "STEP 2 / 4 — Oracle ✓" while rendering slab content. */}
-

+

STEP {headerStepNum} / {headerStepTotal} — {headerStepLabel}

@@ -809,7 +809,7 @@ export const CreateMarketWizard: FC<{ initialMint?: string }> = ({ initialMint }

Choose your market size. Larger slabs support more concurrent traders but cost more SOL to deploy.

-
Market Side Size {formatTokenAmount(absPosition, decimals)} - {symbol} + {symbol}