Skip to content

feat: animate execution page#701

Draft
yolodevz wants to merge 1 commit into
feat-checkoutfrom
animate-execution-page
Draft

feat: animate execution page#701
yolodevz wants to merge 1 commit into
feat-checkoutfrom
animate-execution-page

Conversation

@yolodevz
Copy link
Copy Markdown

Which Linear task is linked to this PR?

Why was it implemented this way?

Explain the reasoning behind the implementation. Were there alternative approaches? Why was this solution chosen?

Visual showcase (Screenshots or Videos)

If applicable, attach screenshots, GIFs, or videos to showcase the functionality, UI changes, or bug fixes.

Checklist before requesting a review

  • I have performed a self-review and testing of my code.
  • This pull request is focused and addresses a single problem.
  • If this PR modifies the Widget API or adds new features that require documentation, I have updated the documentation in the public-docs repository.

@yolodevz yolodevz requested a review from effie-ms April 14, 2026 15:29
@yolodevz yolodevz changed the base branch from main to feat-checkout April 14, 2026 15:30
@github-actions
Copy link
Copy Markdown

Hey! This is your new endpoint: https://c075c283.widget-animateexe.pages.dev

@github-actions
Copy link
Copy Markdown

Hey! This is your new endpoint: https://92a25e64.widget-animateexe.pages.dev

@yolodevz yolodevz force-pushed the animate-execution-page branch from 77dcdad to 7c77db2 Compare April 14, 2026 16:02
@github-actions
Copy link
Copy Markdown

Hey! This is your new endpoint: https://d64097a4.widget-animateexe.pages.dev

@yolodevz yolodevz force-pushed the animate-execution-page branch from 7c77db2 to 2dd02d4 Compare April 14, 2026 16:10
@github-actions
Copy link
Copy Markdown

Hey! This is your new endpoint: https://c1f03285.widget-animateexe.pages.dev

@github-actions
Copy link
Copy Markdown

Hey! This is your new endpoint: https://a40669b3.widget-animateexe.pages.dev

Comment thread .claude/launch.json Outdated
@@ -0,0 +1,11 @@
{
"version": "0.0.1",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we need to merge this config for Claude?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ideally we don't need it

@@ -1,10 +1,10 @@
import type { RouteExtended } from '@lifi/sdk'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same file as on Transaction details? Could we make it reusable, if so?

Comment thread knip.json Outdated
"ignoreDependencies": ["@mui/system", "csstype"],
"workspaces": {
"packages/widget": {
"ignore": ["src/components/TransactionStatusCard/index.ts"]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we drop this index file, from this config and in the directory?

Comment thread package.json
route: RouteExtended,
toAddress?: string
): ExecutionRow[] {
const { getTransactionLink } = useExplorer()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you check how stable this dependency is? Otherwise there is no use from this memoization :)

@github-actions
Copy link
Copy Markdown

Hey! This is your new endpoint: https://fac35a66.widget-animateexe.pages.dev

@github-actions
Copy link
Copy Markdown

Hey! This is your new endpoint: https://9251e4a1.widget-animateexe.pages.dev

@vinzenzLIFI
Copy link
Copy Markdown
Contributor

🤖 The following is an extract from the QA Agent Analysis of this PR. Sharing these findings early so they can be addressed before QA execution begins.


Code Inspection Findings

🔴 Must address before merge

staggerQueue singleton breaks multi-widget isolation (staggerQueue.ts:2-4)
let pending, let lastFlushAt, and let timer are module-level globals — a single shared queue across all widget instances on a page. When two LiFiWidget instances execute routes concurrently, Widget B's enqueueStaggered call overwrites Widget A's pending callback. Widget A's route update is silently dropped. Needs either per-instance queue isolation or an explicit decision to drop multi-widget support with documentation.

WidgetEvent.RouteExecutionUpdated is now a breaking change for integrators
emitter.emit(RouteExecutionUpdated …) is now called inside enqueueStaggered, so intermediate events fired within the 1200 ms window are silently dropped. Pre-PR: one event per SDK callback. Post-PR: at most one event per 1200 ms, with intermediate ones lost. Integrators tracking per-step progress via this event will silently stop receiving updates — they won't notice until production. Needs a CHANGELOG entry or migration note before merge.

.claude/launch.json accidentally committed
VS Code debug config was included in the diff. Reviewer already flagged it with no response yet — worth resolving before further review rounds.


🟡 Should fix

getTransactionLink missing useCallback defeats memoization (useExplorer.ts:60, StepActionRow.tsx)
getTransactionLink is defined inline without useCallback, producing a new function reference on every render. useMemo in useExecutionRows lists it as a dependency, so the memo recomputes on every render. On the transaction page with active timer re-renders this means continuous row re-derivation. Flagged in an open review thread — hasn't been resolved yet.


🔵 Worth noting

visibility: hidden in StaggeredRevealTypography has no timeout fallback (StaggeredRevealTypography.tsx:36)
Text is invisible until document.fonts.ready resolves. The promise does resolve on font failure in all modern browsers, so this is safe in practice — but a code comment explaining the assumption would help future readers.

Index-based AnimatePresence keys on route restart (ChecklistSection.tsx:59)
key={\row-${index}`}` is stable for append-only growth but on a route restart, FAILED rows are removed and then re-added at the same indices — producing spurious enter animations. Low visual impact, easy to fix with stable IDs derived from action type or txHash.


Full test plan including 19 test cases, automation guide, and exit criteria available on request.

@github-actions
Copy link
Copy Markdown

Hey! This is your new endpoint: https://d29bc025.widget-animateexe.pages.dev

@github-actions
Copy link
Copy Markdown

Hey! This is your new endpoint: https://c4db33d0.widget-animateexe.pages.dev

@github-actions
Copy link
Copy Markdown

Hey! This is your new endpoint: https://29965eff.widget-animateexe.pages.dev

@yolodevz yolodevz force-pushed the animate-execution-page branch from 10f6162 to 2aa86a0 Compare May 28, 2026 20:31
@github-actions
Copy link
Copy Markdown

Hey! This is your new endpoint: https://fd5b14b8.widget-animateexe.pages.dev

if (!routeExecution) {
const enqueueStaggered = (task: () => void): void => {
const q = staggerRef.current
q.next = task
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you confirm we are not losing any events when pacing updates on UI?

return
}
q.scheduled = true
setTimeout(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cleanup for this timeout would be nice :)

staggerRef.current.lastAt = Date.now()
run()
},
q.lastAt + STAGGER_INTERVAL - Date.now()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

With zero q.lastAt, it will be negative - maybe Math.max(0, ...) would make it a bit cleaner.

const queryClient = useQueryClient()
const { account } = useAccount()
const resumedAfterMount = useRef(false)
const staggerRef = useRef({
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it would be nice if we could fully decouple staggering from the logic of receiving execution data from SDK - it's already pretty complicated.

step.execution.status = 'PENDING'
for (const action of step.execution.actions ?? []) {
if (action.status === 'FAILED') {
action.status = 'PENDING'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not sure if we should updateRoute(reset) here - let's see if he could omit it when decoupling the animation.

@@ -0,0 +1,12 @@
import type { StorybookConfig } from '@storybook/react-vite'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If we are not going to support a storybook for the repo - I would be nice to drop it.

@@ -0,0 +1,17 @@
import type { ReactNode } from 'react'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you move this type inline? We don't really follow the convention of creating separate types.tsx files for components. Just for consistency.

@@ -0,0 +1,2 @@
export { ExecutionStatusCard } from './ExecutionStatusCard.js'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The components can be exported right from the files, without this barrel file.

deleteRoute: () => void
}

/** Action buttons shown when route execution fails: retry, delete, and optional contact support. */
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Subjective: I think it's nice to have comments around complex logic, trade-offs, etc. Not sure they are necessary when the code is rather self-documenting. Personally, I would clean them up and left only the necessary ones (e.g. for animations, etc.) Otherwise it ends up being too many comments to read (and support) 😅

return (
<Box
sx={{
position: 'relative',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Until we moved away from MUI, these 3+ property styles could be moved to a style file (StatusIcon.style.tsx). Just a suggestion to keep in mind.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants