Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add logic for new requireScroll prop for Snap Footer component #29863

Draft
wants to merge 44 commits into
base: main
Choose a base branch
from

Conversation

hmalik88
Copy link
Contributor

@hmalik88 hmalik88 commented Jan 22, 2025

Description

Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions:

  1. What is the reason for the change? A new prop was added: requireScroll.
  2. What is the improvement/solution? Snap devs can now optionally include the requireScroll prop in their footers. The prop ensures that the footer buttons are disabled until the snap ui content has been viewed. This prop also means that a scroll arrow is displayed based on the isScrolledToBottom prop.

Related issues

Fixes: MetaMask/snaps#3021

Manual testing steps

  1. Go to https://github.com/hmalik88/swiss-knife-snap and pull down the repo.
  2. Install the snap and click "Trigger long content"
  3. Observe that a scroll arrow appears and that the footer is disabled until content is scrolled.

Screenshots/Recordings

After

Screen.Recording.2025-02-05.at.12.46.34.PM.mov

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Copy link
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamaskbot metamaskbot added the team-snaps-platform Snaps Platform team label Jan 22, 2025
@metamaskbot
Copy link
Collaborator

Builds ready [fb1ef7c]
Page Load Metrics (1814 ± 116 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint27622621720409196
domContentLoaded136722351789242116
load143722621814242116
domInteractive246738126
backgroundConnect676242210
firstReactRender1579332210
getState4106192512
initialActions0492115
loadScripts9901733132520398
setupStore65819209
uiStartup163526862089308148
Bundle size diffs
  • background: 0 Bytes (0.00%)
  • ui: 999 Bytes (0.01%)
  • common: 0 Bytes (0.00%)

@metamaskbot
Copy link
Collaborator

Builds ready [22be388]
Page Load Metrics (1687 ± 87 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint29522931563455218
domContentLoaded14902226165917082
load15152298168718087
domInteractive23100382110
backgroundConnect988302713
firstReactRender1598382613
getState46316168
initialActions00000
loadScripts10641716121415273
setupStore691242412
uiStartup168126571954246118
Bundle size diffs
  • background: 0 Bytes (0.00%)
  • ui: 999 Bytes (0.01%)
  • common: 0 Bytes (0.00%)

}, [rawContent, scrollState, scrollArrow, requireScroll]);
};

const LoadingSpinner = memo(function LoadingSpinner() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this moved out?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For readability

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and memoizing because it's static no need to re-create on every render

@metamaskbot
Copy link
Collaborator

Builds ready [995774c]
Page Load Metrics (1716 ± 89 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint15302354171718689
domContentLoaded15172337168018086
load15292361171618689
domInteractive23101382311
backgroundConnect10143383215
firstReactRender15104442914
getState55617178
initialActions01000
loadScripts10791741122614972
setupStore77817199
uiStartup176126271991241116
Bundle size diffs
  • background: 0 Bytes (0.00%)
  • ui: 4.77 KiB (0.06%)
  • common: 0 Bytes (0.00%)

@metamaskbot
Copy link
Collaborator

Builds ready [f7bac01]
Page Load Metrics (1708 ± 47 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint1560199017099747
domContentLoaded1545193616829546
load1561198917089747
domInteractive25153483316
backgroundConnect95726168
firstReactRender1676372412
getState45214157
initialActions01000
loadScripts1059139212097938
setupStore765212110
uiStartup18042207195310048
Bundle size diffs
  • background: 0 Bytes (0.00%)
  • ui: 3.15 KiB (0.04%)
  • common: 0 Bytes (0.00%)

@metamaskbot
Copy link
Collaborator

Builds ready [1697674]
Page Load Metrics (1613 ± 66 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint21719531550328157
domContentLoaded13961929159012259
load14012023161313766
domInteractive248336189
backgroundConnect877252010
firstReactRender1469352311
getState48011168
initialActions0724168
loadScripts9631406113710852
setupStore763192110
uiStartup158127481883243117
Bundle size diffs
  • background: 0 Bytes (0.00%)
  • ui: 2.78 KiB (0.04%)
  • common: 0 Bytes (0.00%)

return;
}

const isActuallyAtBottom =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this different from useScrollRequired's hasScrolledToBottomState? Can we deduplicate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I don't think that hook should even export isScrolledToBottom or hasScrolledToBottomState tbh, that calculation should happen in the component itself because it sets state too early in the hook.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand. It seems like we're duplicating a lot of logic here, can we update the hook instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hook is used in a lot of places, it'll blow the scope of this PR up if I make a major change to the hook. I made as much changes as possible to it without possibly breaking anything elsewhere.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still trying to understand why we actually need all this code. The useScrollRequired hook has a property that indicates if the user has scrolled to the bottom already, which seems to work fine in existing implementations. Can you explain why all this code is necessary, and why we can't simply rely on useScrollRequired?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm so I was definitely experiencing flickering issues before, it was most likely something else that was causing it. I re-factored to just use the hook: 355fe1e. Updating the tests in another commit.

Comment on lines +165 to +169
// Prevent multiple clicks
if (isProgrammaticScrollRef.current) {
return;
}
isProgrammaticScrollRef.current = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this a ref? Is this necessary in the first place?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Glad you questioned this, made me refactor things a little. Removed the reducer state and simplified the scroll handler. The ref is needed for the scroll to bottom function, I don't want to use state to set a flag and cause an unnecessary re-render.

@metamaskbot
Copy link
Collaborator

Builds ready [3b460ca]
Page Load Metrics (1773 ± 94 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint14722132177619594
domContentLoaded14362111174819493
load14432144177319594
domInteractive248338147
backgroundConnect107031199
firstReactRender1481412412
getState45619199
initialActions00000
loadScripts10771589131115173
setupStore76514168
uiStartup166924302029228110
Bundle size diffs
  • background: 0 Bytes (0.00%)
  • ui: 2.16 KiB (0.03%)
  • common: 0 Bytes (0.00%)

@metamaskbot
Copy link
Collaborator

Builds ready [f6ba4c5]
Page Load Metrics (1656 ± 66 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint14742090165713665
domContentLoaded14582007162712962
load14722098165613766
domInteractive24127473014
backgroundConnect1190342210
firstReactRender146225168
getState55716178
initialActions01000
loadScripts10201472120710751
setupStore867192010
uiStartup17002455189416378
Bundle size diffs
  • background: 0 Bytes (0.00%)
  • ui: 2.1 KiB (0.03%)
  • common: 0 Bytes (0.00%)

@metamaskbot
Copy link
Collaborator

Builds ready [355fe1e]
Page Load Metrics (1995 ± 121 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint17662723198520498
domContentLoaded17402268189913263
load176929451995253121
domInteractive27107462612
backgroundConnect196419613264
firstReactRender16112383015
getState8209544924
initialActions01000
loadScripts1307164414489947
setupStore8112192411
uiStartup201354452460747359
Bundle size diffs
  • background: 0 Bytes (0.00%)
  • ui: 1.69 KiB (0.02%)
  • common: 0 Bytes (0.00%)

@hmalik88 hmalik88 requested a review from Mrtenz March 11, 2025 18:12
@metamaskbot
Copy link
Collaborator

Builds ready [8e0b3d7]
Page Load Metrics (2270 ± 165 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint34729822038610293
domContentLoaded18622506209919393
load187733392270344165
domInteractive257542126
backgroundConnect1185116918287
firstReactRender17138563416
getState7344697536
initialActions01000
loadScripts14241950159814570
setupStore9158313216
uiStartup2071638730391001481
Bundle size diffs
  • background: 0 Bytes (0.00%)
  • ui: 1.69 KiB (0.02%)
  • common: 0 Bytes (0.00%)

});

const shouldShowArrow = useMemo(() => {
if (!requireScroll || isScrolledToBottom || hasScrolledToBottom) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this first if if we return false at the end anyways ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah you're right that we don't need the first if, but not because there's a false return at the end, but because we're already using requireScroll as a condition in snap-ui-interface. If that requireScroll wasn't there then removing this would break things.

Comment on lines +288 to +307
{requireScroll && showArrow && (
<AvatarIcon
iconName={IconName.Arrow2Down}
data-testid="snap-ui-renderer__scroll-button"
backgroundColor={BackgroundColor.infoDefault}
color={IconColor.primaryInverse}
className="snap-ui-renderer__scroll-button"
onClick={scrollToBottom}
style={{
cursor: 'pointer',
position: 'absolute',
left: 0,
right: 0,
marginLeft: 'auto',
marginRight: 'auto',
zIndex: 'auto',
bottom: '84px',
}}
/>
)}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have to define this inside the context provider ? This seems not ideal

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is your suggestion?

@metamaskbot
Copy link
Collaborator

Builds ready [0191696]
Page Load Metrics (2675 ± 604 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint327676623611223587
domContentLoaded1597661121881072515
load1688693626751258604
domInteractive26241554823
backgroundConnect321552476459221
firstReactRender23226945326
getState2266421320699
initialActions01000
loadScripts117250371549820394
setupStore1041512011455
uiStartup205217248543139661904
Bundle size diffs
  • background: 0 Bytes (0.00%)
  • ui: 1.68 KiB (0.02%)
  • common: 0 Bytes (0.00%)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
team-snaps-platform Snaps Platform team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add prop & logic to disable footer actions until the entire content is viewed
7 participants