From f29db76ee424858146a4fba05149dbb3289a176f Mon Sep 17 00:00:00 2001 From: dcccrypto Date: Wed, 15 Jul 2026 11:27:44 +0100 Subject: [PATCH] fix(trade): lock the whole order ticket until a funded account exists With no wallet, no account, or an unfunded account, the direction toggle, size input, leverage slider, and receipt could all be interacted with even though the only real action is the CTA at the bottom (Connect / Start Trading / Deposit to Trade). Wrap the interactive stack in a disabled fieldset (native input+button+keyboard disabling) dimmed to 40% opacity so the ticket reads as locked until the account is ready. Co-Authored-By: Claude Fable 5 --- app/components/trade/OrderTicket.tsx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/app/components/trade/OrderTicket.tsx b/app/components/trade/OrderTicket.tsx index 2eaa1afd..c0b304c4 100644 --- a/app/components/trade/OrderTicket.tsx +++ b/app/components/trade/OrderTicket.tsx @@ -587,6 +587,12 @@ const OrderTicketInner: FC<{ slabAddress: string }> = ({ slabAddress }) => { const needsWallet = !connected; const needsAccount = connected && !userAccount; const needsDeposit = connected && userAccount && capital === 0n; + // With no wallet, no account, or an unfunded account, every control below + // can only compose an order that cannot be submitted — the CTA at the + // bottom (Connect / Start Trading / Deposit to Trade) is the only real + // action. Lock the whole ticket so the controls read as "not yet", instead + // of inviting input that dead-ends. + const ticketLocked = needsWallet || needsAccount || !!needsDeposit; async function handleTrade( snapshotSize?: bigint, @@ -698,6 +704,17 @@ setEngineLockError(null); + {/* Locked shell — a disabled fieldset natively disables every input and + button inside (including keyboard focus), and the opacity drop makes + the "not yet" state legible at a glance. min-w-0 counters fieldset's + default min-inline-size: min-content, which would otherwise stop the + ticket from shrinking in narrow layouts. */} +
+ {/* Long / Short segmented — semantic long/short tokens only, symmetric unselected states (both read as neutral until chosen — previously Short's idle state was tinted red even when not selected, which @@ -986,6 +1003,8 @@ setEngineLockError(null); ); })()} +
+ {/* Single validation banner (highest-priority issue only) */} {blockingIssue && (