You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(history): long token names widen the popup; asset detail hidden behind transaction sheet - #3035
A long token name made the popup wider. If an account's history included a token with a long symbol, such as a Soroswap LP token (native-USDC-SOROSWAP-LP), opening History made the popup about 500px wide instead of 360px. Chrome sizes the popup to the narrowest width its content fits in. The amount on each history row stays on one line, and the 45% width cap on it doesn't count when Chrome measures the content, so the full symbol set the popup's width. Each row now takes its width from the page instead (CSS contain: inline-size), so the amount is cut off with an ellipsis, as it already was in the sidebar and fullscreen. A symbol with no hyphens or spaces now wraps inside the label instead of running off the row and hiding the amount.
Transaction details opened from an asset's page had a solid black background. Opening a transaction from Asset Details replaced the whole page with the details panel, so the see-through background behind the panel had nothing to show. Asset Details now stays on screen behind the panel, as it does on the History screen, and the background also dims the Send/Swap buttons.
The amount column is white-space: nowrap with max-width: 45% (#L44-L45). When Chrome measures the content's minimum width, a percentage max-width has nothing to resolve against and is ignored. So the row's minimum width was the full amount string.
Chromium sizes extension popups from the document's min-content width. With AutoSizeUsesScrollWidthForOverflow off, it uses LayoutView::ComputeMinimumWidth(). With it on, it expands the initial containing block to min-content while auto-sizing.
Measured with one native-USDC-SOROSWAP-LP row: the document's min-content width was 500.5px. Hiding the amount brought it to 360px. Adding min-width: 0 to the flex rows changed nothing. With containment the row's own min-content width no longer depends on its text, and at a fixed width the layout is identical.
Symbols with no break opportunity. Adds min-width: 0 to .HistoryItem__row and .HistoryItem__description, and overflow-wrap: anywhere to the description: HistoryItem/styles.scss#L10-L30
Containment keeps the popup at 360px, but the flex items inside the row still defaulted to min-width: auto. A symbol like SUPERLONGMEMECOINNAMEFORTESTING couldn't shrink below its own width, so the label ran 57px past the row and the amount column (whose minimum is 0 because of overflow: hidden) was squeezed to 0px.
With the change, the label wraps and the amount keeps its 140px. A hyphenated symbol still wraps at its hyphens, as before.
Before, the component returned only the SlideupModal whenever activeAssetId was set. That unmounted the view inside the account Sheet and left only its opaque gray-01 background.
The transaction SlideupModal is now always mounted inside the View, next to the existing balance-info sheet. This matches how AccountHistory renders it.
It passes hasBackdrop, so the backdrop is the fixed full-screen variant (z-index: 29). Otherwise the sticky Send/Swap bar (z-index: 10) would sit above the default backdrop (z-index: 1) while the sheet animates in and out.
Closing the sheet now returns to the same Asset Details instance instead of remounting it.
The popup width check fails before the containment fix (500.5px with the hyphenated row alone) and passes after (360px).
The per-row check (no overflow, amount wider than 0) fails with containment alone (the unbroken row overflows by 57px) and passes with the min-width/overflow-wrap change.
It measures the document's min-content width rather than the popup window. Headless Chromium doesn't re-auto-size an action popup on in-app navigation, so the window itself can't be asserted on there.
Chrome sizes the extension popup from the document's min-content width.
A history row's amount is nowrap, and its percentage max-width doesn't
cap its min-content contribution, so a long token symbol such as
"native-USDC-SOROSWAP-LP" pushed the history page to ~500px. Size each
row from its container with `contain: inline-size`; layout at a fixed
width (sidebar, fullscreen) is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…on sheet
Opening a transaction from an asset's detail returned only the slide-up
sheet, unmounting the detail view, so the translucent backdrop showed an
empty background. Keep the view mounted and render the sheet alongside
it, as the History screen does. The sheet uses the full-screen backdrop
so it also dims the sticky Send/Swap bar.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reason will be displayed to describe this comment to others. Learn more.
Long token symbols without hyphens still overflow the row
TL;DR: The popup now keeps its width, but the row's content can't shrink to fit inside it. A token symbol with no spaces or hyphens runs off the right edge, and the amount column is squeezed to zero width. SEP-41 puts no length limit on symbol(), so any custom Soroban token can do this. The new e2e test doesn't catch it because its symbol is hyphenated, so it wraps at the hyphens. The test still passes with a 31-character unbroken symbol.
Steps to reproduce:
In the new e2e test "A long token code does not widen the popup", change LONG_CODE to "SUPERLONGMEMECOINNAMEFORTESTING".
Run it. It still passes.
Look at the History screen: the label runs off the screen and the amount isn't visible.
Detailed explanation (for agents)
Root cause:contain: inline-size fixes the popup width, but the flex items inside the row still use the default min-width: auto, so they can't shrink below their content.
The icon+label .HistoryItem__row and .HistoryItem__description both have min-width: auto. With an unbreakable label, that minimum is the full label width.
.HistoryItem__amount has overflow: hidden, so its automatic minimum is 0. When there isn't enough space, it is the column that shrinks, all the way to nothing.
The label comes straight from the token contract: rowText: code where code = isNative ? "XLM" : symbol.
With this change the unbroken-symbol case measures row scrollWidth 312, amount width 140px, and label right edge 190 (wrapped). The hyphenated case is unchanged.
Test: in the e2e test, use an unbroken LONG_CODE, or add a second case with one. Also assert that history-item-amount-component has a non-zero width. The current assertion only checks the popup width, so it can't catch the amount being squeezed to zero.
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 7719168 with your suggestion: min-width: 0 on .HistoryItem__row and .HistoryItem__description, plus overflow-wrap: anywhere on the description.
The e2e test now stubs two rows, native-USDC-SOROSWAP-LP and SUPERLONGMEMECOINNAMEFORTESTING. Besides the popup width, it checks each row for no overflow and an amount wider than 0. It fails with containment alone (the unbroken row overflows by 57px) and passes with the CSS change. My measurements match yours: the row stays at 312px, the amount at 140px, and the label wraps.
The reason will be displayed to describe this comment to others. Learn more.
Tapping another transaction while the sheet is closing does nothing
Low severity: the tap is silently lost, but tapping the same row again opens it.
TL;DR: Now that the transaction list stays visible behind the sheet, a user can close one transaction and tap another within a fraction of a second. If the second tap lands during the sheet's 200ms closing animation, it is swallowed and no sheet opens. Before this PR this couldn't happen, because the list wasn't on screen while a transaction was selected.
Steps to reproduce:
Open an asset's detail page that has at least two history rows.
Tap row A to open its transaction sheet.
Tap the dimmed backdrop to close it, then tap row B within about 200ms.
No sheet opens for B. A second tap on B opens it normally.
Detailed explanation (for agents)
Root cause: the backdrop click closes the sheet in two steps. It sets the modal's internal isOpen to false right away, and only clears activeAssetId 200ms later in a setTimeout:
Deterministic repro: a throwaway Playwright spec using the data from "Orders failed transactions by date alongside successful ones", run at ae141d16f with real mouse clicks:
Click row 0 and wait for .SlideupModal to have the open class.
page.mouse.click on the backdrop, wait N ms, then page.mouse.click on the center of row 1.
Wait 1s and read the sheet's class.
gap between backdrop click and row click
sheet class 1s later
400ms
SlideupModal open
50ms
SlideupModal closed
(then a second tap on row 1)
SlideupModal open
Fix direction (not tested): selecting a row during the close needs to both cancel the pending clear of activeAssetId and open the sheet again. Today the delayed close callback clears whatever id is active by then. Making it clear only the id it was closing would stop it dropping B, but on its own the sheet still wouldn't reopen, because isModalOpen never went false.
The reason will be displayed to describe this comment to others. Learn more.
Not reachable with a real tap, so I'd leave this out of this PR. The race is real in the code. A programmatic .click() on row B 50ms after closing reproduces it exactly as you describe. But a pointer tap can't land in that window. The full-screen backdrop stays on top of the rows for about 370ms after the backdrop tap, and the pending clear fires at 200ms. So in the 50ms repro, the second tap goes to the fading backdrop and the row's click handler never runs.
Measurements
Built extension at ae141d1, 360×600, three USDC rows in Asset Details. I recorded the click target with a capture-phase listener on document. Each run: open row A, tap the backdrop with a real mouse click, wait the given gap, then tap row B's center.
gap after backdrop tap
click target
sheet 1s later
50ms
LoadingBackground
closed
200ms
LoadingBackground
closed
300ms
LoadingBackground
closed
350ms
LoadingBackground
closed
400ms
history-item
open
450ms
history-item
open
600ms
history-item
open
.LoadingBackground has transition: all (0.3s ease-out after a 0.1s delay), so its z-index animates from 29 down to -1 instead of dropping at once. Sampled under row B's center: 29 until about 110ms, 0 at about 370ms, and -1 from about 395ms, which is when the row becomes the hit target. History rows have no tabIndex or role, so there's no keyboard path either. The History screen uses the same SlideupModal close sequence.
If we want this not to depend on the transition timing, the fix belongs in SlideupModal, since History shares it. It would keep the pending close timeout in a ref and cancel it when the modal is reopened. That fits better as a follow-up than in this PR.
A symbol like "SUPERLONGMEMECOINNAMEFORTESTING" couldn't shrink below
its own width, so it ran past the row and squeezed the amount to zero
width. Let the label column shrink and break the symbol anywhere. The
e2e test now covers an unbroken symbol and checks each row for
overflow and a visible amount.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This only proves that the transaction detail is mounted in the DOM; SlideupModal always renders its children even when closed, so it would also pass if the click failed to open the sheet. Since this change adds both hasBackdrop and the layering needed to cover the sticky action bar, assert that the transaction modal has the open class and that an active full-screen backdrop is present (and ideally that the backdrop closes back to AssetDetail).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TL;DR
Two transaction history display fixes.
native-USDC-SOROSWAP-LP), opening History made the popup about 500px wide instead of 360px. Chrome sizes the popup to the narrowest width its content fits in. The amount on each history row stays on one line, and the 45% width cap on it doesn't count when Chrome measures the content, so the full symbol set the popup's width. Each row now takes its width from the page instead (CSScontain: inline-size), so the amount is cut off with an ellipsis, as it already was in the sidebar and fullscreen. A symbol with no hyphens or spaces now wraps inside the label instead of running off the row and hiding the amount.Before:
history-bugs-720p.mov
After:
history-bugs-fixed.mov
Implementation details (for agents)
What changed
contain: inline-sizeto.HistoryItem: HistoryItem/styles.scss#L5-L8white-space: nowrapwithmax-width: 45%(#L44-L45). When Chrome measures the content's minimum width, a percentagemax-widthhas nothing to resolve against and is ignored. So the row's minimum width was the full amount string.AutoSizeUsesScrollWidthForOverflowoff, it usesLayoutView::ComputeMinimumWidth(). With it on, it expands the initial containing block to min-content while auto-sizing.native-USDC-SOROSWAP-LProw: the document's min-content width was 500.5px. Hiding the amount brought it to 360px. Addingmin-width: 0to the flex rows changed nothing. With containment the row's own min-content width no longer depends on its text, and at a fixed width the layout is identical.min-width: 0to.HistoryItem__rowand.HistoryItem__description, andoverflow-wrap: anywhereto the description: HistoryItem/styles.scss#L10-L30min-width: auto. A symbol likeSUPERLONGMEMECOINNAMEFORTESTINGcouldn't shrink below its own width, so the label ran 57px past the row and the amount column (whose minimum is 0 because ofoverflow: hidden) was squeezed to 0px.SlideupModalwheneveractiveAssetIdwas set. That unmounted the view inside the account Sheet and left only its opaquegray-01background.SlideupModalis now always mounted inside theView, next to the existing balance-info sheet. This matches howAccountHistoryrenders it.hasBackdrop, so the backdrop is the fixed full-screen variant (z-index: 29). Otherwise the sticky Send/Swap bar (z-index: 10) would sit above the default backdrop (z-index: 1) while the sheet animates in and out.Verification
Long token codes fit in the popup, with a hyphenated symbol and one with no break opportunity:min-width/overflow-wrapchange.keeps the asset detail behind an opened transaction: fails before the fix becauseAssetDetailis unmounted, passes after.elementFromPointover Send and Swap hits the sheet.z-index: 29.yarn test:ci: 1945 passed.accountHistory,sendPayment,reviewTxFees,loadAccount: all pass. The only skips are the existingtest.skip/test.fixme.🤖 Generated with Claude Code