fix: /trade Market slippage chips wrap so 0.5% sits above 1% / 5% #528
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#528
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
On
/tradeMarket, the 0.5% Slippage protection chip sits on the same row as the label while 1% and 5% wrap to the next row. The three presets look staggered instead of one aligned group.This is one product surface: retail slippage preset chips (
SLIPPAGE_TOLERANCE_PRESETS_PERCENT=[0.5, 1.0, 5.0]). Bundle Trade Market (the reported wrap) and the same three chips on Swap Settings so they cannot orphan the first preset. Do not split “Trade wrap” vs “Swap group” vs “shared helper” into separate issues.Related: #497 (default 5% + shared presets), #417 (
TRADE_SLIPPAGE_PRESET_CLASS~44px touch target), #412 (retail Slippage protection label), #488 (tab-glass*), #489 (copy), #527 (ticket footer must not cover these chips).Evidence
Phone-width
/tradeMarket ticket (Buy {base}, disconnected). Label Slippage protection: + 0.5% on the first line; 1% and 5% on the line below. Copy Taker swap at 5% slippage protection confirms the store default is still 5% — this is layout only.Current codebase
/tradeMarket tab rendersTradeMarketOrderPanel. The chip row is a singleflex flex-wrapwhose children are the label and the three preset buttons:Paneldrag),flex-wrapfits Slippage protection: + the first chip, then wraps 1% / 5%. The first chip is vertically aligned with the label row, not with its siblings.TRADE_SLIPPAGE_PRESET_CLASS=tab-glass min-h-11 px-3 py-2 text-sm(#417). Tall 44px chips + atext-[10px]label in one wrap list makes the orphan obvious. Default flexalign-items: stretchdoes not keep a shared baseline once wrap occurs.useDexStore.slippageTolerance←DEFAULT_SLIPPAGE_TOLERANCE_PERCENT(5). Click callssetSlippageTolerance(v)(clamped 0.01–50). Market submit mapsmax_spread = (slippageTolerance / 100).toString()(5 →"0.05"). Lead copy interpolates the same value:Taker swap at {slippageTolerance}% slippage protection.SwapPage.tsxalready puts the label on its own line (label-glass), thenflex flex-wrapof 0.5 / 1 / 5 + a flex-1 Custom input. Narrow widths can still wrap mid-preset (e.g. 0.5%+1% on row 1, 5%+Custom on row 2). Same three values; keep them one group if a helper is extracted.PoolPage.tsxuses a different set (0.5 / 1.0 / 2.0) and already stacks label aboveflex gap-2chips. Out of scope unless a shared helper is reused without changing those values.data-testid={trade-market-slippage-preset-${v}}exists.TradeMarketOrderPanel.submitSnapshot.test.tsxcovers submit/max_spreadsnapshots, not chip geometry or wrap. No Playwright assert that the three Market chips share a row / baseline.Playbook:
skills/AGENTS_FRONTEND_DEFAULT_SLIPPAGE.md. Spec:docs/frontend.md§ slippage protection. Tokens:docs/design-system.md(tab-glass*for slippage chips).Why this is needed
max_spread. A staggered hit area makes it easy to tap 0.5% when aiming for 1%, or to miss the group entirely. Wrong protection is a correctness / MEV-exposure issue, not only polish./tradephone stack, tablet chart|ticket, and a dragged-narrow desktop panel all hit the wrap. The screenshot is the default Market ticket, not an edge-case zoom.Constraints / guardrails
[0.5, 1.0, 5.0], default 5%,setSlippageToleranceclamp0.01–50, ormax_spread = percent / 100. Do not hard-code0.5as the product default (#497).HIGH_SLIPPAGE_PROTECTION_WARN_PERCENT = 5, warn only when strictly greater than 5%).TRADE_SLIPPAGE_PRESET_CLASS(min-h-11). Do not shrink to “fit the label row”.SLIPPAGE_PROTECTION_LABEL(#412). Do not put the label inside the wrap list with the buttons. Do not rename to “slippage tolerance” /max_spreadin retail UI (#489).role="group"row for the three buttons. If the ticket is too narrow for threemin-h-11chips, wrap as a group or use equalgrid-cols-3— never leave 0.5% on the label row.items-center(or a 3-column grid) on the chip group, notalign-items: stretchacross label + buttons.tab-glass/tab-glass-active/tab-glass-inactive. Tokens--ink,--ink-dim. No*-neoclasses (#488). Light + dark.trade-market-slippage-preset-0.5,trade-market-slippage-preset-1,trade-market-slippage-preset-5(note:1.0stringifies as1). Add a group testid (e.g.trade-market-slippage-presets) for geometry. Update every test if a testid changes.aria-label/aria-labelledbypointing at the visible label). Keyboard: Tab 0.5 → 1 → 5;:focus-visibleon.tab-glassunchanged (#144). Selected chip staystab-glass-activeand matchesuseDexStore.slippageTolerance.assertSubmitHybridAligned, pause / blacklist / gas gates, invert convert-on-submit (#524) stay as they are. Clicking a chip must still only update the store (and therefore the next quote /max_spread).elementFromPointon a chip must hit that chip).Taker swap at {n}% slippage protection. Best pool/book split by default.+ optional Docs. No new essay (#489).Relevant files
frontend-dapp/src/components/trade/TradeMarketOrderPanel.tsxflex-wrapfrontend-dapp/src/utils/tradeMoneyCta.tsTRADE_SLIPPAGE_PRESET_CLASSfrontend-dapp/src/utils/slippageProtectionCopy.tsfrontend-dapp/src/stores/dex.tsslippageTolerance/setSlippageTolerancefrontend-dapp/src/pages/SwapPage.tsxfrontend-dapp/src/index.css.tab-glass*frontend-dapp/src/components/trade/__tests__/TradeMarketOrderPanel.submitSnapshot.test.tsxmax_spread— extend for chip selection, not geometryfrontend-dapp/src/pages/SwapPage.test.tsxfrontend-dapp/e2e/trade-page-responsive.spec.tsskills/AGENTS_FRONTEND_DEFAULT_SLIPPAGE.mdRecommended direction
TradeMarketOrderPanel(label above, chips below). Put the three buttons inrole="group"withflex items-center gap-2orgrid grid-cols-3 gap-2so they share one row and one baseline.min-h-11chips cannot fit the ticket width, keep them equal-width in a 3-column grid (they shrink together) rather than wrapping the first chip onto the label line.SlippageProtectionPresets(Trade: three chips; Swap: three chips + Custom sibling outside the chip group). Do not invent a fourth Trade preset.data-testid="trade-market-slippage-presets"(and Swap equivalent if extracted) for bounding-box tests.tab-glass-activeon that chip only. Playwright:getBoundingClientRect— three chips samey(±2px) and 0.5%yis not the label’sywhen the label is on the previous line; chip rowtop≥ labelbottom.Acceptance criteria
/tradeMarket, 0.5%, 1%, and 5% share the same horizontal axis (top and bottom edges within 2px). 0.5% is not on the label’s line.:) sits above or beside the group, never as aflex-wrapsibling that can take the first chip with it.useDexStore.slippageToleranceto that number; only that chip istab-glass-active; lead copyTaker swap at {n}% slippage protectionmatches. Fresh session still defaults to 5% active.max_spreadas(percent/100)string. Snapshot tests that assert"0.05"at default still pass. Selecting 0.5% →"0.005"; 1% →"0.01".:focus-visiblering visible. Hit targets ≥ 44px on Trade (min-h-11).elementFromPointat each chip center hits that chip — not the money CTA, pair search, or a sibling chip.make verify-issue-<iid>exists.Test plan (all paths)
Unit / RTL (
make test-frontend/ scoped Vitest)trade-market-slippage-preset-*render when a pair is selected (connected and disconnected).tab-glass-active; 0.5% and 1% havetab-glass-inactive.0.5, only that chip active; click 1% →1; click 5% →5. Lead copy updates.max_spread: "0.05"; after clicking 0.5%, next submit / quote path uses"0.005"(extendTradeMarketOrderPanel.submitSnapshot.test.tsxor a focused chip test — do not weaken existing default-5% cases).[0.5, 1, 5]; Custom sanitizes non-numeric; values>50clamp to 50;<0.01shows range error and does not persist an out-of-range store write beyond existing behavior; warn copy only when store> 5.playButtonPresson click still called (do not drop).Playwright (
e2e/trade-page-responsive.spec.tsand/or a focused spec, Chromium)Use bounding boxes, not screenshots-only. Open
/trade, select Market, wait fortrade-market-slippage-preset-0.5.abs(y0.5 − y1) ≤ 2andabs(y1 − y5) ≤ 2. Labelbottom≤ chip rowtop+ 4px (label not sharing the chip baseline as a wrap sibling).xis not immediately after the label on a shorter row than 1%/5%.tab-glass-activefollows the click; no overlap of chip boxes (gap ≥ 0; centers distinct).elementFromPointat each chip center/Settings open, 390×844y(±2px). Custom input, if wrapped, is below the group, not between chips.Firefox/WebKit: if the suite runs them, P1 + P5 must pass (alignment must not be Chrome-only CSS).
Manual QA
make dev→/tradeMarket on a live pair. Confirm 0.5 / 1 / 5 sit on one row under (or clearly grouped with) Slippage protection.99(clamp/warn) and0(range error).Test plan — attack, hack, and abuse vectors
Layout chrome on a control that sets on-chain
max_spread. Treat mis-hit and value injection as integrity bugs.elementFromPointat each center hits that chip. A tap meant for 1% must not activate 0.5% because it sits on the label row.elementFromPointon a chip is the chip (#527, #181).max_spreadchangemax_spreadmatches the store at click time... NoinnerHTML. Values below 0.01 or above 50 do not reach the chain as raw user text. Reject1e9,0x1,1; DROP, unicode digits that parse as something else.max_spread/ hop min-returns match the store at confirm, not a stale chip. ExistingassertSubmitHybridAligned/ submit-aligned sim still gate the CTA.tabindex≥ 0 on the label. Disabled money CTA staysdisabledwhen chips change nothing about pause/blacklist. Esc/modals unchanged.tab-glass-activeonly.SLIPPAGE_PROTECTION_LABEL, not indexer/wallet text. Do not interpolate pair symbols into the chip row.Verification criteria
Issue is done when all of the following are true:
/tradeMarket at phone and desktop ticket widths: screenshot comparable to the report shows 0.5 / 1 / 5 on one aligned row, not 0.5% beside the label.max_spreadmapping still pass.AGENTS_FRONTEND_DEFAULT_SLIPPAGE.mdstates the chip-group invariant.make verify-issue-<iid>exists and is green locally (unit + testid/preset greps; E2E when LocalTerra is up — do not skip with a false “no LocalTerra” withoutmake has-localterra/make setup-cloud-localterra).Mode
max_spread)Severity
max_spread; visual defect on the default Market ticket)marked as related to #497
marked as related to #417
marked as related to #412
mentioned in commit
1f254d4ef6mentioned in issue #514
mentioned in merge request !1063
mentioned in merge request !1064
Merge sanity check for !1064 (before landing on main):
role="group"3-up grid; Swap Custom below; presets/default/max_spreadunchanged).elementFromPoint).528-fix-trade-market-slippage-chips-wrap-so-0-5-sits-above-1-5-is an empty placeholder atorigin/main(no unique commits). Safe to delete after !1064 lands.mentioned in issue #527
mentioned in commit
a879d25890mentioned in commit
9ee15f75ecmentioned in commit
9fd8b4eadfmentioned in issue #595
mentioned in issue #693