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 && (