ux: /trade ticket defaults to Market; flatten nested chrome; token-logo heading wash #693
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:implement
agent:implement
agent:open_issues
agent:ready
agent:research
agent:security_audit
agent:verify
architecture
backend
blocker:hybrid
blocker:launch
blocker:limit-orders
blocker:v2
block:log_only
block:security
bug
ci
contracts
correctness
deploy
dev
devops
docs
documentation
duplicate
e2e
enhancement
epic
feature
frontend
functional-completion
gas
good first issue
governance
help wanted
high-risk
hooks
hybrid
indexer
infra
infrastructure
integrators
invalid
launch-blocker
limit-orders
localnet
localterra
low priority
missing-implementation
needs-design
ops
performance
priority
high
priority
medium
product
qa
QA
question
ready
ready
research
scripts
security
security-hardening
smartcontracts
tech-debt
testing
ux
UX
v2
verification
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-dex-terraclassic#693
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
The
/tradeorder ticket is Limit-first, uses full-widthtab-glasspills, and stacks nested cards (Side panel + Top buy/Top sell + Market/LimitTicketSection+ a second “Market” heading + quotecard-glass). The Buy {base} header has no token logo and a hard-coded orange wash that ignores the asset. Flatten the ticket: default Market, compact underline Market/Limit text, logo + logo-derived heading wash, Buy/Sell directly in the parent (no Side chrome, no Top buy/Top sell), one Market Docs / Limit Docs line (not a card, not a second title), and move Slippage protection plus other non-blocking amount chrome into Advanced.Styling / IA only. Do not change escrow mapping, quote payloads, hybrid always-on, footer CTA dock, or on-chain
side.Related (do not re-open): #152 Market tab, #153 radiogroup, #155 side amount, #489 copy density, #497 / #528 slippage, #524 invert, #527 footer dock, #563 heading + green/red Buy/Sell (T563-6 tab-glass rule is amended here), #653 one chrome layer, #378 logo allowlist, #596 hybrid always on, #501 GET
/route/solve.Current codebase
Default tab is Limit
TradeOrderTicket.tsxinitializesorderTabto'limit'. Fresh/trade/:pairtherefore shows the resting-book form (price, expiry, pre-submit) and the footer Place limit CTA. Market (taker swap + hybrid quote) is a second click. Book Edit already forcessetOrderTab('limit')— keep that.Tests assume Limit-first:
TradePage.test.tsxfindstrade-limit-submit/trade-limit-pre-submit-summarywithout clicking the Limit tab; Market footer tests clicktrade-order-tab-marketfirst.Market / Limit are nested full-width pills
When
pairAddristerra1…, a 2-columngridwithrounded-2xl border+tab-glass/tab-glass-activehosts Limit then Market (role="tablist",trade-order-tab-*).docs/frontend.mdT563-6 and the Bid/Ask side table say Limit/Market tabs staytab-glass*. That uses a full ticket-width row for two words.Heading: text only + hard-coded orange wash
data-testid="trade-ticket-header"setsradial-gradient(… rgba(251, 146, 60, 0.18) …)— orange, not the displayed base.
h3.trade-ticket-headingis{verb} {displayBase}orSelect a pair(T563-1). NoTokenLogo/TokenDisplay. Invert stays in the row (T563-4). Logo allowlist + blockie fallback already exist (#378,useTokenDisplayInfo).Side panel + Top buy / Top sell
TicketSection title="Side"wrapsLimitOrderBidAskSideSelector(idPrefix="trade-ticket", compact) and twoTicketStattiles: Top buy / Top sell (bestBidLabel/bestAskLabel).TicketSectionis a secondrounded-2xl border+ wash inside the ticketcard-glass. Book head already lives on the sibling order-book panel.Market / Limit cards duplicate the mode word
Market:
TicketSection title="Market" tone="action"plusTradeMarketOrderPanel.tsx<h3>Market</h3>and a “Taker swap at {n}% slippage protection… Docs” paragraph.Limit:
TicketSection title="Limit" tone="action"around price / pay / receive / expiry / advanced /LimitOrderPreSubmitSummary(anothercard-glass, its own Docs).Mode name appears twice; Docs is buried in lecture copy or the pre-submit card.
Slippage and amount chrome sit on the default Market path
Always visible on Market (above Advanced):
SlippageProtectionPresets(trade-market-slippage-presets, 0.5 / 1 / 5 — #528)LimitOrderEscrowAmountField: Pay ({symbol}), USD notional, balance + 25/50/75/100%card-glass(trade-market-quote): expected receive, min after slippage, disclosure, hop spread, RouteSwapPreSubmitSummaryAdvanced today is only hybrid book-leg override + max makers (#501 / #596).
Limit default path still shows expiry, % deviation chips, ref/%/USD context, side-flip, receive USD, and the pre-submit fee card.
LimitOrderAdvancedLimitSettingsalready holds placement gas + rawexpires_at.Why the new implementation is needed
/tradeis the execution page; Market (immediate taker) is the common path. Limit-first trains users into resting-book fields and a Place limit CTA they did not ask for.card-glass→ Side section → stat tiles → Market/Limit action card → quote/pre-submitcard-glassis a card-of-cards. That fights #653 / #489 and wastes the narrow ticket column.Constraints / guardrails
/tradeticket. Do not restyle/limitsplace card except where a shared primitive must change;/limitsstays Limit-only. Do not change Swap Settings slippage placement.limitBookDraftKey) stillsetOrderTab('limit')and prefills (L561-11, #178). Place another after a successful limit stays on Limit and still focuses the price field (#161). Pair remount (keyed Outlet) → Market again.onSideChange('bid'). Quotes stay GET/route/solve(Advanced typed book → POST). Hybrid stays always on — no opt-out (#596).max_spread = slippage/100; default 5%; presets[0.5, 1, 5](#497 / #528).role="tablist"/tab/tabpanel(or an equivalent labelled switch). Buy/Sell stay the #153 radiogroup (aria-checked, Arrow/Home/End). New text tabs need:focus-visible(#144). Selected mode = underline +aria-selected(not color-only).side-control*(T563-5). Do not paint them with the token wash. Do not paint footer Market buy/sell / Place limit green/red. Do not restyle book Bid/Ask columns.{verb} {displayBase}plus a siblingTokenLogo(nodangerouslySetInnerHTML). T563-1 wrap still applies; logo isshrink-0. Invert stays tappable. Logo via allowlistedTokenLogoonly (#378); blockie when no safe URI. Wash from the displayed base after invert (#524).--inkon dark and light. Fallback: deterministic hue from token id / blockie, never the current orangergba(251, 146, 60, 0.18). No CSS/url()injection from metadata. Canvas extract only from allowlistedhttpsimages; tainted/CORS failure → fallback. Do not fetch arbitrarylogo_urlhosts.TicketSection/TicketStaton this ticket (or stop using them). No Market/Limit wrapper card. Quote / pre-submit must not be a secondcard-glasson the default path — typography or Advanced. Ticket shellcard-glass/ sibling Trade panels stay (L561). Do not wrapPriceChart. Updatescripts/chrome_nesting_allowlist.txt/check_chrome_nesting.pyif the flatten adds or removes a same-file nest.TicketSectiontitle and an inner<h3>Market</h3>and a lecture sentence. Docs is optional depth (#489); it must not replace pause / blacklist / code-id-frozen / tax extra-debit / hop-spread blocking errors.trade-market-slippage-*testids and #528grid-cols-3when open; still in ticket body, not footer), hybrid book leg + max makers, min-after-slippage / disclosure / hop spread / Route extras / pre-submit fee grid / taker lecture (or delete the lecture).LimitOrderExpiryFieldduplicate), placement gas, % chips + ref/USD context if they crowd the price row, pre-submit fee card. Side-flip may stay compact between Pay/Receive.VITE_INDEXER_URL(#164).TradeOrderTicketmount. Hidden desktop ticket staysinert+interactive={false}(L561-6). Flattened DOM must not create a second submit or a focusable control insideinert.tab-glasstabs: T563-6,docs/frontend.mdBid/Ask “Limit vs Market tabs staytab-glass*”,AGENTS_FRONTEND_TRADE_TICKET_HEADING.md. Playbook +make verify-issue-*for this issue.Relevant files
frontend-dapp/src/components/trade/TradeOrderTicket.tsxTicketSection/TicketStat, tablist, Side wrapperfrontend-dapp/src/components/trade/TradeMarketOrderPanel.tsxfrontend-dapp/src/components/trade/LimitOrderBidAskSideSelector.tsxfrontend-dapp/src/components/trade/LimitOrderEscrowAmountField.tsxfrontend-dapp/src/components/trade/LimitOrderPriceField.tsxfrontend-dapp/src/components/trade/LimitOrderExpiryField.tsx/tradefrontend-dapp/src/components/trade/LimitOrderAdvancedLimitSettings.tsxfrontend-dapp/src/components/trade/LimitOrderPreSubmitSummary.tsxcard-glass+ Docsfrontend-dapp/src/components/swap/SwapPreSubmitSummary.tsxfrontend-dapp/src/components/common/SlippageProtectionPresets.tsxfrontend-dapp/src/components/ui/TokenLogo.tsx/TokenDisplay.tsxfrontend-dapp/src/hooks/useTokenDisplayInfo.tsfrontend-dapp/src/utils/tokenLogoAllowlist.tsfrontend-dapp/src/index.css.trade-ticket-heading, new text-tab + wash primitivesfrontend-dapp/src/theme-dark.css/theme-light.cssfrontend-dapp/src/pages/TradePage.test.tsxfrontend-dapp/src/components/trade/__tests__/TradeMarketOrderPanel.slippagePresets.test.tsxfrontend-dapp/e2e/trade-page-responsive.spec.tsdocs/frontend.md§ ticket heading + market contextdocs/design-system.mdskills/AGENTS_FRONTEND_TRADE_TICKET_HEADING.mdskills/AGENTS_FRONTEND_TRADE_PAGE_LAYOUT.mdskills/AGENTS_FRONTEND_CHROME_NESTING.mdskills/AGENTS_FRONTEND_SLIPPAGE_PRESET_ALIGN.mdQA_TEMPLATE.mdRecommended direction
useState('market'). Update tests that assumed Limit-first: clicktrade-order-tab-limitwhere the case is Limit-only; asserttrade-order-tab-marketaria-selected="true"on fresh mount. Keep book-Edit → Limit.tab-glassrow with a compact inline text pair: small type, selected = underline +aria-selected, idle = muted, intrinsic width (notw-full). Keep testidstrade-order-tab-limit/trade-order-tab-market.TokenLogo(displayed base) + existingh3text + invert. Drive headerbackgroundfrom a clamped accent (logo sample or id-hash). Delete the orange radial.Select a pair= no logo, neutral wash.LimitOrderBidAskSideSelectoras a direct child oftrade-order-ticket-scroll. Delete Top buy / Top sell andTicketStatif unused.TicketSection. One line: Market + Docs or Limit + Docs. Remove the inner<h3>Market</h3>and the always-on taker paragraph.SlippageProtectionPresetsintotrade-market-advanced(open section). Keep #528 geometry when expanded. Same for quote extras /SwapPreSubmitSummary. Leave a single expected-receive line on the default path (not a nested card)./trade: move expiry + pre-submit card + crowding price context into Advanced; keep price + Pay + Receive on the default path.make verify-issue-<id>(Vitest + targeted e2e).Acceptance criteria
/trade/:pair(validterra1) hastrade-order-tab-marketaria-selected="true"; Market pay field + footer Market CTA; no limit price input until Limit is selected.tab-glasspills; not a full-width 2-col bordered toolbar). Less horizontal space than today’sgrid-cols-2pills. Keyboard +aria-*remain.trade-ticket-headingrow shows allowlistedTokenLogo(or blockie) for the displayed base beside Buy {base} / Sell {base}. Invert updates logo + verb/base together.Select a pairhas no logo.trade-ticket-headerhas norgba(251, 146, 60/ warm orange radial. Wash tracks displayed-base identity across pair switch and invert. Heading contrast holds on dark and light. Fallback never returns to the orange constant.TicketSection.TicketSectionMarket/Limit card. Visible mode title appears once with a single Docs link (Market + Docs or Limit + Docs). No second<h3>Market</h3>.trade-market-slippage-presets. Opening Advanced shows the same 0.5/1/5 group (#528). Changing a chip still writesuseDexStore.slippageToleranceand the next quote/submitmax_spread. Default remains 5% when Advanced stays closed.card-glassaround the amount input.docs/frontend.md+ design-system + skills + QA updated; T563-6 amended;make verify-issue-<id>exists.Test plan — all paths
/trade/:pair. Market selected; Market pay + Market footer CTA; nolimit-order-price-input; no Side / Top buy / Top sell; no MarketTicketSectioncard; heading has logo + non-orange wash.trade-sub-lg-workspace) and desktop (lg). Tabs stay compact; heading wraps (T563-1); logo does not cover invert or Sell./limits. Unchanged place-card IA (unless a shared component forced a surgical prop).make test-frontend(TradePage, TradeMarketOrderPanel slippage + submit snapshot, LimitOrderBidAskSideSelector, TokenLogo allowlist),make verify-issue-563(amended tab rule),make verify-issue-528(chips when Advanced open),make verify-issue-561,make verify-issue-653,python3 scripts/check_design_tokens.py,python3 scripts/check_chrome_nesting.py.Test plan — attack, hack, and abuse
max_spread/ min receive. Do not silently submitmax_spread=0or 50%. Quote vs execute snapshot tests stay.dangerouslySetInnerHTML.logo_urlonly via allowlist (https+TOKEN_LOGO_ALLOWED_HOSTS). Rejectjavascript:,data:, http, and off-allowlist hosts. Color path must not inject raw metadata intostyleexcept numericrgba(...)the app computed. Canvas from tainted image → fallback, no exception leak.alert-errorstay readable. Token wash must not recolor Buy/Sell or the money CTA (direction spoof).inert) must not focus tabs, Advanced, or submit.pairAddr+ displayed base id).<img>./limitsregression. Shared selector/amount changes must not alter/limitsescrow or add Market default there.Verification criteria
make lint-frontendand scopedmake test-frontendgreen (Trade ticket / Market panel / TokenLogo / heading tests).make verify-issue-<id>covers T1–T11 (unit + targeted Playwright if layout needs geometry).make verify-issue-563(updated),make verify-issue-528,make verify-issue-561,make verify-issue-653green.python3 scripts/check_design_tokens.pyandpython3 scripts/check_chrome_nesting.pygreen./trade— Market default, compact tabs, logo+wash, no Side/Top buy, no mode card, slippage only in Advanced, footer docked.rgba(251, 146, 60gone from the ticket header).mentioned in merge request !1194
mentioned in issue #701
Heads-up: !1195 (#692
/poolVol USD) merged tomain(f4fa6788). !1194 is still open and was left alone.Overlaps with that merge:
Makefile,AGENTS.md,docs/frontend.md(verify-target / docs lists). Rebasefeat/693-trade-ticket-flattenonto currentmainbefore merging !1194. Ticket flatten itself does not overlap the Vol USD UI.Merge review (!1194)
Rebased onto current
main(includes !1195). Makefile help conflict resolved by keepingverify-issue-692on the Cloud Agent line andverify-issue-693on the Frontend line.Local AC:
make verify-issue-6939/9 PASS. Relatedmake verify-issue-56313/13 andmake verify-issue-65314/14 PASS. T1–T11 / A1–A11 look met in source (Market default, compact text tabs, logo+wash, flatten Side/mode, slippage/expiry under Advanced,/limitsunchanged).Follow-up in-branch:
e2e/trade-page-responsive.spec.tsnow opens Limit Advanced before measuring#trade-ticket-expiry-dt(expiry moved off the default path per T9).Not merge-blocking: Playwright
/tradegeometry (375 / 1280) and manual dark+light QA 10.2.19 were not run here. Track those on a leftover after merge. Do not reopen this issue for ops/QA.mentioned in commit
e6ddbf1d4cmentioned in issue #702
marked as related to #702
Merged
!1194 is on
main(e6ddbf1d). Localmake verify-issue-693was 9/9. Ops leftovers (Coolify frontend rebuild,/trade10.2.19 visual QA) tracked on #702. Do not reopen this issue for ops/QA.mentioned in issue #713