Skip to content

refactor: Fix ui flashes from on prop changes#1812

Open
mfortman11 wants to merge 3 commits into
mainfrom
no-adjust-state-on-prop
Open

refactor: Fix ui flashes from on prop changes#1812
mfortman11 wants to merge 3 commits into
mainfrom
no-adjust-state-on-prop

Conversation

@mfortman11

@mfortman11 mfortman11 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Eliminate stale UI flashes from state-on-prop-change effects

Fixes 10 instances of no-adjust-state-on-prop-change across 5 files. These useEffect calls synced state to prop changes, causing React to render once with stale values before the effect corrected them — users
briefly saw wrong data.

Changes:

  • file-list.tsx — Tab reset on retry tab disappearing moved to render-time check
  • use-task-dialog.ts — Selection clear on dialog close and status category fallback moved to prev-prop pattern
  • animated-provider-steps.tsx — Removed redundant startTime state (was just a copy of processingStartTime prop); elapsed time now captured during render on completion transition
  • onboarding-step.tsx — Split monolithic effect into render-time prop adjustments + a slimmer effect for the typewriter animation interval only
  • unified-cloud-picker.tsx — Replaced fake-async effect with render-time check (the "async" function was synchronous); removed dead isLoadingBaseUrl state and unreachable loading UI

Summary by CodeRabbit

  • Refactor
    • Internal optimization of component state management and initialization patterns across onboarding and dialog components for improved performance and maintainability.

@github-actions github-actions Bot added community frontend 🟨 Issues related to the UI/UX and removed community labels Jun 9, 2026
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 07df23c5-ddf7-4734-aecb-20f2093783d0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Five frontend components refactor state management from useEffect-based initialization and effects to render-time conditionals and local state tracking. AnimatedProviderSteps detects completion transitions to set elapsed time, OnboardingStep synchronizes text/visibility/completion state during render, UnifiedCloudPicker inlines OneDrive URL detection, and TaskDialogFileList and useTaskDialog hook consolidate state resets into conditional blocks instead of effect watchers.

Changes

Render-time state synchronization refactor

Layer / File(s) Summary
Completion-transition elapsed time detection
frontend/app/onboarding/_components/animated-provider-steps.tsx
AnimatedProviderSteps now detects the transition into completion via prevIsCompleted tracking and computes elapsedTime directly from processingStartTime at that moment, removing the prior startTime state and initialization effect.
Onboarding step input-change synchronization
frontend/app/onboarding/_components/onboarding-step.tsx
OnboardingStep tracks previous text, isVisible, and isCompleted values and synchronizes displayedText/showChildren during render when inputs change, moving reset logic from useEffect into a dedicated conditional block and removing the timing comment.
OneDrive base URL inline conditional detection
frontend/components/cloud-picker/unified-cloud-picker.tsx
UnifiedCloudPicker removes isLoadingBaseUrl state and its associated async effect, replacing with an inline render-time conditional that sets autoBaseUrl when provider is onedrive and required credentials exist, and removes the loading UI branch.
Task dialog and file list state synchronization
frontend/components/task-dialog/file-list.tsx, frontend/components/task-dialog/use-task-dialog.ts
TaskDialogFileList and useTaskDialog hook remove useEffect imports and replace effect-based logic: file-list moves tab-switch validation to render time, and the hook tracks previous open state to clear selectedPaths on close and resets statusCategory inline when category count is zero.

Possibly related PRs

  • langflow-ai/openrag#1739: The main PR's frontend/components/task-dialog/use-task-dialog.ts changes how the task dialog reacts to open/filter updates (local previous-open tracking and render-time state resets), which is directly tied to the retrieved PR's new task dialog open/close state added in frontend/contexts/task-context.tsx and used across the task dialog UI.

Suggested labels

refactor

Suggested reviewers

  • lucaseduoli
  • edwinjosechittilappilly

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'refactor: Fix ui flashes from on prop changes' directly addresses the main objective: eliminating UI flashes caused by state updates in useEffect hooks that synced state from props. This is the core issue resolved across all five files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch no-adjust-state-on-prop

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added refactor and removed refactor labels Jun 9, 2026

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/components/cloud-picker/unified-cloud-picker.tsx (1)

31-31: ⚠️ Potential issue | 🟠 Major

Fix stale effectiveBaseUrl caused by persisted autoBaseUrl when switching providers

unified-cloud-picker.tsx stores OneDrive’s fallback in component state (autoBaseUrl) and derives effectiveBaseUrl as baseUrl || autoBaseUrl. Since there’s no reset when provider changes away from "onedrive", createProviderHandler(provider, ..., effectiveBaseUrl) can receive the OneDrive picker URL for subsequent providers while baseUrl is still unset.

Suggested fix
-  const [autoBaseUrl, setAutoBaseUrl] = useState<string | undefined>(undefined);
-
-  const effectiveBaseUrl = baseUrl || autoBaseUrl;
-
-  if (provider === "onedrive" && !baseUrl && accessToken && !autoBaseUrl) {
-    setAutoBaseUrl("https://onedrive.live.com/picker");
-  }
+  const effectiveBaseUrl =
+    baseUrl ??
+    (provider === "onedrive" && accessToken
+      ? "https://onedrive.live.com/picker"
+      : undefined);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/components/cloud-picker/unified-cloud-picker.tsx` at line 31, The
stale OneDrive URL comes from storing OneDrive’s fallback in state (autoBaseUrl)
and using effectiveBaseUrl = baseUrl || autoBaseUrl even after provider changes;
update the component so autoBaseUrl is cleared or ignored when provider !==
"onedrive" — e.g., add a useEffect that watches provider and sets
setAutoBaseUrl(undefined) whenever provider changes away from "onedrive", or
only pass a OneDrive-specific effectiveBaseUrl into
createProviderHandler(provider, ..., effectiveBaseUrl) by computing
effectiveBaseUrl conditionally (use baseUrl || autoBaseUrl only if provider ===
"onedrive"); ensure references to autoBaseUrl, effectiveBaseUrl and
createProviderHandler are updated accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/app/onboarding/_components/animated-provider-steps.tsx`:
- Around line 30-38: The component seeds prevIsCompleted incorrectly and never
handles the true->false transition; change initialization of prevIsCompleted so
it does not start from the incoming isCompleted prop (initialize false) and
replace the inline if-block with a useEffect that watches isCompleted and
processingStartTime: when isCompleted becomes true && prevIsCompleted is false,
setElapsedTime(Date.now() - processingStartTime) (guarding for undefined
processingStartTime) and setPrevIsCompleted(true); when isCompleted becomes
false, setPrevIsCompleted(false) so subsequent completions recompute
elapsedTime; update references to setPrevIsCompleted and setElapsedTime inside
that effect.

In `@frontend/app/onboarding/_components/onboarding-step.tsx`:
- Around line 38-40: On mount OnboardingStep currently initializes displayedText
and showChildren to empty/false which causes blank render when isVisible &&
isCompleted && !isMarkdown; change the initial state setup so displayedText
initializes to text and showChildren to true when props.isVisible &&
props.isCompleted && !props.isMarkdown (keep prev as before), and ensure the
typing useEffect still early-returns for completed cases—this guarantees
immediate full text and children on first render for the non-markdown completed
case.

---

Outside diff comments:
In `@frontend/components/cloud-picker/unified-cloud-picker.tsx`:
- Line 31: The stale OneDrive URL comes from storing OneDrive’s fallback in
state (autoBaseUrl) and using effectiveBaseUrl = baseUrl || autoBaseUrl even
after provider changes; update the component so autoBaseUrl is cleared or
ignored when provider !== "onedrive" — e.g., add a useEffect that watches
provider and sets setAutoBaseUrl(undefined) whenever provider changes away from
"onedrive", or only pass a OneDrive-specific effectiveBaseUrl into
createProviderHandler(provider, ..., effectiveBaseUrl) by computing
effectiveBaseUrl conditionally (use baseUrl || autoBaseUrl only if provider ===
"onedrive"); ensure references to autoBaseUrl, effectiveBaseUrl and
createProviderHandler are updated accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dc95ce7a-6ed6-40c3-8cad-df6606d2a5ee

📥 Commits

Reviewing files that changed from the base of the PR and between cb3f5ed and 92d342a.

📒 Files selected for processing (5)
  • frontend/app/onboarding/_components/animated-provider-steps.tsx
  • frontend/app/onboarding/_components/onboarding-step.tsx
  • frontend/components/cloud-picker/unified-cloud-picker.tsx
  • frontend/components/task-dialog/file-list.tsx
  • frontend/components/task-dialog/use-task-dialog.ts

Comment on lines +30 to +38
const [prevIsCompleted, setPrevIsCompleted] = useState(isCompleted);
const [elapsedTime, setElapsedTime] = useState<number>(0);

// Initialize start time from prop
useEffect(() => {
if (isCompleted && !prevIsCompleted) {
setPrevIsCompleted(true);
if (processingStartTime) {
// Use the start time passed from parent (when user clicked Complete)
setStartTime(processingStartTime);
setElapsedTime(Date.now() - processingStartTime);
}
}, [processingStartTime]);
}

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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate and print the relevant portion of the file
FILE="frontend/app/onboarding/_components/animated-provider-steps.tsx"
echo "== File: $FILE =="
nl -ba "$FILE" | sed -n '1,200p'

# Focus on the specific lines mentioned (30-120 in case numbering differs)
echo
echo "== Focus: lines 20-90 =="
nl -ba "$FILE" | sed -n '20,90p'

# Extract any usage of isCompleted / processingStartTime within this component
echo
echo "== Search within file for isCompleted / processingStartTime =="
rg -n "isCompleted|processingStartTime|prevIsCompleted|elapsedTime|setElapsedTime" "$FILE" || true

Repository: langflow-ai/openrag

Length of output: 200


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="frontend/app/onboarding/_components/animated-provider-steps.tsx"

echo "== File exists? =="
if [[ -f "$FILE" ]]; then
  echo "yes: $FILE"
else
  echo "no: $FILE"
  exit 0
fi

echo
echo "== Focus: lines 1-200 (with line numbers via awk) =="
awk '{printf "%6d %s\n", NR, $0}' "$FILE" | sed -n '1,200p'

echo
echo "== Search within file for relevant identifiers =="
rg -n "isCompleted|processingStartTime|prevIsCompleted|elapsedTime|setPrevIsCompleted|setElapsedTime" "$FILE" || true

echo
echo "== Show around prevIsCompleted initialization and completion logic =="
rg -n "prevIsCompleted|setPrevIsCompleted|setElapsedTime|processingStartTime" "$FILE" | head -n 50

Repository: langflow-ai/openrag

Length of output: 10233


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "AnimatedProviderSteps" -S frontend || true

# If we found usages, show surrounding code for the first few matches
# (Limit output to avoid noise)
matches=$(rg -n "AnimatedProviderSteps" -S frontend || true)
echo
echo "== Matched lines =="
echo "$matches" | head -n 50

# For each match file, print a small window around it
echo
echo "== Context around matches (first 50 lines) =="
echo "$matches" | head -n 10 | while read -r line; do
  file=$(echo "$line" | cut -d: -f1)
  lineno=$(echo "$line" | cut -d: -f2)
  echo "-- $file:$lineno --"
  # print 40 lines around the match
  start=$((lineno-20)); end=$((lineno+20))
  awk -v s=$start -v e=$end 'NR>=s && NR<=e {print NR ":" $0}' "$file" | sed -n '1,80p'
done

Repository: langflow-ai/openrag

Length of output: 8140


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show relevant portions of onboarding-card.tsx around the AnimatedProviderSteps usage
FILE1="frontend/app/onboarding/_components/onboarding-card.tsx"
echo "== onboarding-card: AnimatedProviderSteps call context =="
awk 'NR>=700 && NR<=820 {print NR ":" $0}' "$FILE1"

# Search within onboarding-card for isCompleted / processingStartTime declarations and update sites
echo
echo "== onboarding-card: search for isCompleted / processingStartTime =="
rg -n "processingStartTime|isCompleted" "$FILE1" || true

# Show around the first few matches for each
echo
echo "== onboarding-card: show processingStartTime related blocks (first 80 matches neighborhood) =="
rg -n "processingStartTime" "$FILE1" | head -n 20 | while read -r line; do
  lineno=$(echo "$line" | cut -d: -f1)
  start=$((lineno-25)); end=$((lineno+25))
  echo "-- $FILE1:$lineno --"
  awk -v s=$start -v e=$end 'NR>=s && NR<=e {print NR ":" $0}' "$FILE1" | sed -n '1,120p'
done

echo
echo "== onboarding-card: show isCompleted related blocks (first 20 matches neighborhood) =="
rg -n "isCompleted" "$FILE1" | head -n 20 | while read -r line; do
  lineno=$(echo "$line" | cut -d: -f1)
  start=$((lineno-25)); end=$((lineno+25))
  echo "-- $FILE1:$lineno --"
  awk -v s=$start -v e=$end 'NR>=s && NR<=e {print NR ":" $0}' "$FILE1" | sed -n '1,120p'
done

# Show relevant portions of onboarding-upload.tsx around the AnimatedProviderSteps usage
FILE2="frontend/app/onboarding/_components/onboarding-upload.tsx"
echo
echo "== onboarding-upload: AnimatedProviderSteps call context =="
awk 'NR>=250 && NR<=420 {print NR ":" $0}' "$FILE2"

# Search within onboarding-upload for isCompleted / processingStartTime
echo
echo "== onboarding-upload: search for isCompleted / processingStartTime =="
rg -n "processingStartTime|isCompleted" "$FILE2" || true

Repository: langflow-ai/openrag

Length of output: 24623


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE="frontend/app/onboarding/_components/onboarding-card.tsx"

echo "== Search for setProcessingStartTime =="
rg -n "setProcessingStartTime" "$FILE" || true

echo
echo "== Search for isCompleted state/derivation in this file =="
rg -n "isCompleted" "$FILE" | head -n 200

echo
echo "== Search for onComplete call sites in this file =="
rg -n "onComplete\(" "$FILE" || true

echo
echo "== Show around handleComplete definition area =="
# handleComplete likely contains setProcessingStartTime / onComplete.
handle_line=$(rg -n "const handleComplete" "$FILE" | head -n 1 | cut -d: -f1 || true)
if [[ -n "${handle_line:-}" ]]; then
  start=$((handle_line-80)); end=$((handle_line+160))
  awk -v s=$start -v e=$end 'NR>=s && NR<=e {print NR ":" $0}' "$FILE" | sed -n '1,200p'
else
  echo "No handleComplete found"
fi

Repository: langflow-ai/openrag

Length of output: 8353


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "OnboardingCard" frontend/app/onboarding -S || true
rg -n "<OnboardingCard|OnboardingCard\s" frontend -S || true

Repository: langflow-ai/openrag

Length of output: 1141


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE="frontend/app/onboarding/_components/onboarding-content.tsx"

echo "== File context (imports + around OnboardingCard usages) =="
awk 'NR>=180 && NR<=280 {print NR ":" $0}' "$FILE"

echo
echo "== Search within file for isCompleted props =="
rg -n "isCompleted" "$FILE" || true

echo
echo "== Search for key= on OnboardingCard elements =="
rg -n "<OnboardingCard[^>]*key=" "$FILE" || true

Repository: langflow-ai/openrag

Length of output: 4186


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE="frontend/app/onboarding/_components/onboarding-content.tsx"

# Show file header + where currentStep is initialized
echo "== onboarding-content: search for currentStep state initialization =="
rg -n "currentStep" "$FILE" || true

echo
echo "== onboarding-content: show around currentStep useState/initialization =="
rg -n "useState<.*currentStep|useState\(.*currentStep|const \[currentStep" "$FILE" -S || true

echo
# Show near where handleStepComplete is defined
echo "== onboarding-content: search for handleStepComplete =="
rg -n "handleStepComplete" "$FILE" -S || true

echo
echo "== onboarding-content: show around handleStepComplete definition =="
line=$(rg -n "const handleStepComplete|function handleStepComplete|handleStepComplete\s*=" "$FILE" -S | head -n 1 | cut -d: -f1 || true)
if [[ -n "${line}" ]]; then
  start=$((line-80)); end=$((line+140))
  awk -v s=$start -v e=$end 'NR>=s && NR<=e {print NR ":" $0}' "$FILE" | sed -n '1,220p'
else
  echo "No handleStepComplete definition found"
fi

echo
echo "== onboarding-content: show around any persistence/initial completion logic =="
# Look for localStorage/session or query params / hydration / initial state indicators
rg -n "localStorage|sessionStorage|searchParams|query|persist|initial|default.*currentStep|hydr" "$FILE" -S || true

Repository: langflow-ai/openrag

Length of output: 2059


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE="frontend/app/onboarding/_components/onboarding-content.tsx"

echo "== File length =="
wc -l "$FILE" || true

echo
echo "== onboarding-content: top 220 lines =="
awk 'NR>=1 && NR<=220 {print NR ":" $0}' "$FILE" | sed -n '1,220p'

echo
echo
echo "== Search for currentStep source (useState / params / context) =="
rg -n "useState\(|useSearchParams|searchParams|params|router|currentStep\s*[,=]" "$FILE" -S || true

echo
echo
echo "== Search for handleStepComplete definition (non-type) =="
rg -n "handleStepComplete" "$FILE" -S || true

Repository: langflow-ai/openrag

Length of output: 9000


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Inspect onboarding-card.tsx around where AnimatedProviderSteps is rendered and what condition/keys control it
FILE1="frontend/app/onboarding/_components/onboarding-card.tsx"
echo "== onboarding-card: show around AnimatedProviderSteps render and its surrounding ternary/AnimatePresence =="
rg -n "AnimatedProviderSteps" "$FILE1" | head -n 5 | while read -r line; do
  lineno=$(echo "$line" | cut -d: -f1)
  start=$((lineno-120)); end=$((lineno+120))
  echo
  echo "-- $FILE1:$start..$end --"
  awk -v s=$start -v e=$end 'NR>=s && NR<=e {print NR ":" $0}' "$FILE1" | sed -n '1,260p'
done

# 2) Locate OnboardingStep component and inspect whether it unmounts/mounts children based on isVisible/isCompleted
FILE2="frontend/app/onboarding/_components/onboarding-step.tsx"
echo
echo "== OnboardingStep file exists? =="
if [[ -f "$FILE2" ]]; then echo "yes: $FILE2"; else echo "no: $FILE2"; fi

# Search for actual definition if path differs
echo
echo "== Search for 'function OnboardingStep' or 'const OnboardingStep' =="
rg -n "OnboardingStep\s*=" frontend/app/onboarding/_components -S || true
rg -n "function\s+OnboardingStep|const\s+OnboardingStep" frontend/app/onboarding/_components -S || true

# If found, print around first match
match=$(rg -n "function\s+OnboardingStep|const\s+OnboardingStep" frontend/app/onboarding/_components -S | head -n 1 || true)
if [[ -n "$match" ]]; then
  file=$(echo "$match" | cut -d: -f1)
  lineno=$(echo "$match" | cut -d: -f2)
  echo
  echo "== OnboardingStep definition: $file:$lineno =="
  start=$((lineno-80)); end=$((lineno+160))
  awk -v s=$start -v e=$end 'NR>=s && NR<=e {print NR ":" $0}' "$file" | sed -n '1,260p'
fi

Repository: langflow-ai/openrag

Length of output: 16862


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find where OnboardingContent is used (likely defines currentStep + handlers)
rg -n "OnboardingContent" frontend/app/onboarding -S

# Find handleStepBack implementation by searching for the identifier in the onboarding flow
rg -n "handleStepBack" frontend/app/onboarding -S

# Also search globally for "currentStep" in onboarding context to locate the state owner
rg -n "const \[currentStep" frontend/app/onboarding -S || true
rg -n "currentStep\W*>\W*0" frontend/app/onboarding -S || true

Repository: langflow-ai/openrag

Length of output: 1091


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find where OnboardingContent is rendered (parent that owns currentStep)
rg -n "<OnboardingContent\b|OnboardingContent\s*\(" frontend/app/onboarding -S || true
rg -n "<OnboardingContent\b|OnboardingContent\s*\(" frontend/app -S || true

# Also look for handleStepBack definition (likely in same parent)
rg -n "handleStepBack\s*=\s*\(" frontend/app/onboarding -S || true
rg -n "handleStepBack\s*=\s*\(" frontend/app -S || true

# Search for currentStep state owner near that parent by looking for `const [currentStep` outside onboarding-content
rg -n "const \[currentStep" frontend/app -S || true

Repository: langflow-ai/openrag

Length of output: 516


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "OnboardingContent" frontend -S || true
rg -n "<OnboardingContent\b|OnboardingContent\s*\(" frontend -S || true

Repository: langflow-ai/openrag

Length of output: 543


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE="frontend/components/chat-renderer.tsx"

# Show around where OnboardingContent is rendered
echo "== Context around OnboardingContent usage =="
awk 'NR>=320 && NR<=430 {print NR ":" $0}' "$FILE" | sed -n '1,200p'

echo
echo "== Search within chat-renderer for currentStep state owner =="
rg -n "currentStep" "$FILE" || true

echo
echo "== Search within chat-renderer for handleStepComplete/Back =="
rg -n "handleStepComplete|handleStepBack" "$FILE" || true

Repository: langflow-ai/openrag

Length of output: 3616


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE="frontend/components/chat-renderer.tsx"

echo "== currentStep initialization and persistence in chat-renderer =="
awk 'NR>=1 && NR<=120 {print NR ":" $0}' "$FILE" | sed -n '1,140p'

echo
echo "== handleStepComplete logic =="
line=$(rg -n "const handleStepComplete" "$FILE" | head -n 1 | cut -d: -f1)
start=$((line-30)); end=$((line+140))
awk -v s=$start -v e=$end 'NR>=s && NR<=e {print NR ":" $0}' "$FILE" | sed -n '1,220p'

echo
echo "== handleStepBack logic =="
line2=$(rg -n "const handleStepBack" "$FILE" | head -n 1 | cut -d: -f1)
start2=$((line2-30)); end2=$((line2+160))
awk -v s=$start2 -v e=$end2 'NR>=s && NR<=e {print NR ":" $0}' "$FILE" | sed -n '1,260p'

echo
echo "== showLayout condition around OnboardingContent mount =="
awk 'NR>=300 && NR<=390 {print NR ":" $0}' "$FILE" | sed -n '1,140p'

Repository: langflow-ai/openrag

Length of output: 23618


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Look for isCompleted usage in effects in onboarding-card.tsx
rg -n "useEffect\\(|isCompleted" frontend/app/onboarding/_components/onboarding-card.tsx -S

# Specifically find effects that list isCompleted in deps
rg -n "useEffect\\([^\\)]*\\n[^\\)]*isCompleted|useEffect\\(.*isCompleted" frontend/app/onboarding/_components/onboarding-card.tsx -S || true

# Find whether onboarding-card uses a key on AnimatedProviderSteps or remount boundary tied to isCompleted/currentStep
rg -n "key=\"provider-steps\"|key=\\\"provider-|key=\\\"" frontend/app/onboarding/_components/onboarding-card.tsx -S

# Check onboarding-step: children mount/unmount logic based on isCompleted
rg -n "showChildren|isCompleted" frontend/app/onboarding/_components/onboarding-step.tsx -S

Repository: langflow-ai/openrag

Length of output: 792


Fix elapsed-time transition handling in AnimatedProviderSteps

In frontend/app/onboarding/_components/animated-provider-steps.tsx (lines 30-38), seeding prevIsCompleted from the isCompleted prop suppresses the isCompleted && !prevIsCompleted block on an initial mount where the wizard is restored to a completed step (ChatRenderer initializes currentStep from backend settings?.onboarding?.current_step, and OnboardingContent passes isCompleted={currentStep > 0}), so the UI shows Initialized in 0.0 seconds.

Also, prevIsCompleted is never updated on the true -> false edge, so if the component instance remains mounted across subsequent completions, elapsedTime won’t be recomputed.

Suggested fix
-  const [prevIsCompleted, setPrevIsCompleted] = useState(isCompleted);
-  const [elapsedTime, setElapsedTime] = useState<number>(0);
+  const [prevIsCompleted, setPrevIsCompleted] = useState(false);
+  const [elapsedTime, setElapsedTime] = useState<number>(() =>
+    isCompleted && processingStartTime != null
+      ? Date.now() - processingStartTime
+      : 0,
+  );

-  if (isCompleted && !prevIsCompleted) {
-    setPrevIsCompleted(true);
-    if (processingStartTime) {
-      setElapsedTime(Date.now() - processingStartTime);
-    }
-  }
+  if (isCompleted !== prevIsCompleted) {
+    setPrevIsCompleted(isCompleted);
+    setElapsedTime(
+      isCompleted && processingStartTime != null
+        ? Date.now() - processingStartTime
+        : 0,
+    );
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const [prevIsCompleted, setPrevIsCompleted] = useState(isCompleted);
const [elapsedTime, setElapsedTime] = useState<number>(0);
// Initialize start time from prop
useEffect(() => {
if (isCompleted && !prevIsCompleted) {
setPrevIsCompleted(true);
if (processingStartTime) {
// Use the start time passed from parent (when user clicked Complete)
setStartTime(processingStartTime);
setElapsedTime(Date.now() - processingStartTime);
}
}, [processingStartTime]);
}
const [prevIsCompleted, setPrevIsCompleted] = useState(false);
const [elapsedTime, setElapsedTime] = useState<number>(() =>
isCompleted && processingStartTime != null
? Date.now() - processingStartTime
: 0,
);
if (isCompleted !== prevIsCompleted) {
setPrevIsCompleted(isCompleted);
setElapsedTime(
isCompleted && processingStartTime != null
? Date.now() - processingStartTime
: 0,
);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/app/onboarding/_components/animated-provider-steps.tsx` around lines
30 - 38, The component seeds prevIsCompleted incorrectly and never handles the
true->false transition; change initialization of prevIsCompleted so it does not
start from the incoming isCompleted prop (initialize false) and replace the
inline if-block with a useEffect that watches isCompleted and
processingStartTime: when isCompleted becomes true && prevIsCompleted is false,
setElapsedTime(Date.now() - processingStartTime) (guarding for undefined
processingStartTime) and setPrevIsCompleted(true); when isCompleted becomes
false, setPrevIsCompleted(false) so subsequent completions recompute
elapsedTime; update references to setPrevIsCompleted and setElapsedTime inside
that effect.

Comment thread frontend/app/onboarding/_components/onboarding-step.tsx Outdated
@github-actions github-actions Bot added refactor and removed refactor labels Jun 9, 2026
@github-actions github-actions Bot added refactor and removed refactor labels Jun 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

frontend 🟨 Issues related to the UI/UX refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant