Stop preview loading progress from rerendering the preview - #3968

Closed
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/component-performance-optimization-70d2
Closed

Stop preview loading progress from rerendering the preview#3968
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/component-performance-optimization-70d2

Conversation

@cursor

@cursorcursorBot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

What Changed

  • Replaced the 120 ms React state loop used by the preview loading bar with a compositor-driven CSS transform animation.
  • Removed useLoadingProgress, so progress animation no longer rerenders PreviewView and its browser surface.
  • Moved the URL focus synchronization effect into the named useFocusPreviewUrlInput hook.
  • Added a reduced-motion fallback.

Why

React Doctor flagged the loading progress hook's synchronous effect update. A manual ownership trace found the hook running in PreviewView, which made the entire preview tree reconcile roughly eight times per second for a cosmetic animation.

With React Scan enabled, the before recording grows from 1 to 50 parent commits during the measured loading cycle and repeatedly highlights PreviewChromeRow. The after recording stays at 2 commits throughout active loading and reaches 3 only when loading stops, while the progress bar still advances smoothly.

UI Changes

There is no intentional visual change to the loading indicator. Before/after React Scan recordings are included with the automation handoff:

  • react_scan_preview_loading_before.mp4
  • react_scan_preview_loading_after.mp4

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after React Scan recordings for the interaction
  • I included a video for animation/interaction changes

Validation: vp check --fix, vp run typecheck, 1,280 web unit tests, and React Doctor changed-file scan (0 diagnostics).

Open in WebView Automation

Note

Stop preview loading progress from rerendering the preview

  • Replaces the numeric loadProgress-driven progress bar with a CSS-animated bar controlled by a boolean loading state in PreviewChromeRow.tsx.
  • Adds a PreviewLoadingProgress component that stays mounted and toggles active/idle CSS classes, animating scaleX between 0.04 and 0.9 via keyframes in index.css.
  • Removes the useLoadingProgress hook that simulated asymptotic progress (0→90%, snap to 100%), eliminating the frequent numeric state updates that caused rerenders.
  • Respects prefers-reduced-motion by disabling the animation and applying a static transform.
📊 Macroscope summarized 7893cc9. 3 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 14, 2026
opacity 150ms ease-out 220ms;
}

@media (prefers-reduced-motion: reduce) {

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.

🟢 Lowsrc/index.css:918

The prefers-reduced-motion override disables the active keyframe animation but leaves .preview-loading-progress-idle's 150 ms transform and opacity transitions untouched. When loading finishes, users with reduced motion enabled still see the bar animate from scaleX(0.9) to scaleX(1). Override the idle transition inside the media query as well.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/index.css around line 918:
The `prefers-reduced-motion` override disables the active keyframe animation but leaves `.preview-loading-progress-idle`'s 150 ms `transform` and `opacity` transitions untouched. When loading finishes, users with reduced motion enabled still see the bar animate from `scaleX(0.9)` to `scaleX(1)`. Override the idle transition inside the media query as well.

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing this PR after an automated pass over open pull requests. Abandoned bot draft is also replaced by the merged preview-rendering fix in #7561.

@t3dotggt3dotgg closed this Aug 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@t3dotgg@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Stop preview loading progress from rerendering the preview - #3968

Closed
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/component-performance-optimization-70d2
Closed

Stop preview loading progress from rerendering the preview#3968
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/component-performance-optimization-70d2

Conversation

@cursor

@cursorcursorBot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

What Changed

  • Replaced the 120 ms React state loop used by the preview loading bar with a compositor-driven CSS transform animation.
  • Removed useLoadingProgress, so progress animation no longer rerenders PreviewView and its browser surface.
  • Moved the URL focus synchronization effect into the named useFocusPreviewUrlInput hook.
  • Added a reduced-motion fallback.

Why

React Doctor flagged the loading progress hook's synchronous effect update. A manual ownership trace found the hook running in PreviewView, which made the entire preview tree reconcile roughly eight times per second for a cosmetic animation.

With React Scan enabled, the before recording grows from 1 to 50 parent commits during the measured loading cycle and repeatedly highlights PreviewChromeRow. The after recording stays at 2 commits throughout active loading and reaches 3 only when loading stops, while the progress bar still advances smoothly.

UI Changes

There is no intentional visual change to the loading indicator. Before/after React Scan recordings are included with the automation handoff:

  • react_scan_preview_loading_before.mp4
  • react_scan_preview_loading_after.mp4

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after React Scan recordings for the interaction
  • I included a video for animation/interaction changes

Validation: vp check --fix, vp run typecheck, 1,280 web unit tests, and React Doctor changed-file scan (0 diagnostics).

Open in WebView Automation

Note

Stop preview loading progress from rerendering the preview

  • Replaces the numeric loadProgress-driven progress bar with a CSS-animated bar controlled by a boolean loading state in PreviewChromeRow.tsx.
  • Adds a PreviewLoadingProgress component that stays mounted and toggles active/idle CSS classes, animating scaleX between 0.04 and 0.9 via keyframes in index.css.
  • Removes the useLoadingProgress hook that simulated asymptotic progress (0→90%, snap to 100%), eliminating the frequent numeric state updates that caused rerenders.
  • Respects prefers-reduced-motion by disabling the animation and applying a static transform.
📊 Macroscope summarized 7893cc9. 3 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 14, 2026
opacity 150ms ease-out 220ms;
}

@media (prefers-reduced-motion: reduce) {

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.

🟢 Lowsrc/index.css:918

The prefers-reduced-motion override disables the active keyframe animation but leaves .preview-loading-progress-idle's 150 ms transform and opacity transitions untouched. When loading finishes, users with reduced motion enabled still see the bar animate from scaleX(0.9) to scaleX(1). Override the idle transition inside the media query as well.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/index.css around line 918:
The `prefers-reduced-motion` override disables the active keyframe animation but leaves `.preview-loading-progress-idle`'s 150 ms `transform` and `opacity` transitions untouched. When loading finishes, users with reduced motion enabled still see the bar animate from `scaleX(0.9)` to `scaleX(1)`. Override the idle transition inside the media query as well.

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing this PR after an automated pass over open pull requests. Abandoned bot draft is also replaced by the merged preview-rendering fix in #7561.

@t3dotggt3dotgg closed this Aug 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@t3dotgg@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Stop preview loading progress from rerendering the preview - #3968

Closed
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/component-performance-optimization-70d2
Closed

Stop preview loading progress from rerendering the preview#3968
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/component-performance-optimization-70d2

Conversation

@cursor

@cursorcursorBot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

What Changed

  • Replaced the 120 ms React state loop used by the preview loading bar with a compositor-driven CSS transform animation.
  • Removed useLoadingProgress, so progress animation no longer rerenders PreviewView and its browser surface.
  • Moved the URL focus synchronization effect into the named useFocusPreviewUrlInput hook.
  • Added a reduced-motion fallback.

Why

React Doctor flagged the loading progress hook's synchronous effect update. A manual ownership trace found the hook running in PreviewView, which made the entire preview tree reconcile roughly eight times per second for a cosmetic animation.

With React Scan enabled, the before recording grows from 1 to 50 parent commits during the measured loading cycle and repeatedly highlights PreviewChromeRow. The after recording stays at 2 commits throughout active loading and reaches 3 only when loading stops, while the progress bar still advances smoothly.

UI Changes

There is no intentional visual change to the loading indicator. Before/after React Scan recordings are included with the automation handoff:

  • react_scan_preview_loading_before.mp4
  • react_scan_preview_loading_after.mp4

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after React Scan recordings for the interaction
  • I included a video for animation/interaction changes

Validation: vp check --fix, vp run typecheck, 1,280 web unit tests, and React Doctor changed-file scan (0 diagnostics).

Open in WebView Automation

Note

Stop preview loading progress from rerendering the preview

  • Replaces the numeric loadProgress-driven progress bar with a CSS-animated bar controlled by a boolean loading state in PreviewChromeRow.tsx.
  • Adds a PreviewLoadingProgress component that stays mounted and toggles active/idle CSS classes, animating scaleX between 0.04 and 0.9 via keyframes in index.css.
  • Removes the useLoadingProgress hook that simulated asymptotic progress (0→90%, snap to 100%), eliminating the frequent numeric state updates that caused rerenders.
  • Respects prefers-reduced-motion by disabling the animation and applying a static transform.
📊 Macroscope summarized 7893cc9. 3 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 14, 2026
opacity 150ms ease-out 220ms;
}

@media (prefers-reduced-motion: reduce) {

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.

🟢 Lowsrc/index.css:918

The prefers-reduced-motion override disables the active keyframe animation but leaves .preview-loading-progress-idle's 150 ms transform and opacity transitions untouched. When loading finishes, users with reduced motion enabled still see the bar animate from scaleX(0.9) to scaleX(1). Override the idle transition inside the media query as well.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/index.css around line 918:
The `prefers-reduced-motion` override disables the active keyframe animation but leaves `.preview-loading-progress-idle`'s 150 ms `transform` and `opacity` transitions untouched. When loading finishes, users with reduced motion enabled still see the bar animate from `scaleX(0.9)` to `scaleX(1)`. Override the idle transition inside the media query as well.

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing this PR after an automated pass over open pull requests. Abandoned bot draft is also replaced by the merged preview-rendering fix in #7561.

@t3dotggt3dotgg closed this Aug 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@t3dotgg@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Stop preview loading progress from rerendering the preview - #3968

Closed
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/component-performance-optimization-70d2
Closed

Stop preview loading progress from rerendering the preview#3968
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/component-performance-optimization-70d2

Conversation

@cursor

@cursorcursorBot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

What Changed

  • Replaced the 120 ms React state loop used by the preview loading bar with a compositor-driven CSS transform animation.
  • Removed useLoadingProgress, so progress animation no longer rerenders PreviewView and its browser surface.
  • Moved the URL focus synchronization effect into the named useFocusPreviewUrlInput hook.
  • Added a reduced-motion fallback.

Why

React Doctor flagged the loading progress hook's synchronous effect update. A manual ownership trace found the hook running in PreviewView, which made the entire preview tree reconcile roughly eight times per second for a cosmetic animation.

With React Scan enabled, the before recording grows from 1 to 50 parent commits during the measured loading cycle and repeatedly highlights PreviewChromeRow. The after recording stays at 2 commits throughout active loading and reaches 3 only when loading stops, while the progress bar still advances smoothly.

UI Changes

There is no intentional visual change to the loading indicator. Before/after React Scan recordings are included with the automation handoff:

  • react_scan_preview_loading_before.mp4
  • react_scan_preview_loading_after.mp4

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after React Scan recordings for the interaction
  • I included a video for animation/interaction changes

Validation: vp check --fix, vp run typecheck, 1,280 web unit tests, and React Doctor changed-file scan (0 diagnostics).

Open in WebView Automation

Note

Stop preview loading progress from rerendering the preview

  • Replaces the numeric loadProgress-driven progress bar with a CSS-animated bar controlled by a boolean loading state in PreviewChromeRow.tsx.
  • Adds a PreviewLoadingProgress component that stays mounted and toggles active/idle CSS classes, animating scaleX between 0.04 and 0.9 via keyframes in index.css.
  • Removes the useLoadingProgress hook that simulated asymptotic progress (0→90%, snap to 100%), eliminating the frequent numeric state updates that caused rerenders.
  • Respects prefers-reduced-motion by disabling the animation and applying a static transform.
📊 Macroscope summarized 7893cc9. 3 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 14, 2026
opacity 150ms ease-out 220ms;
}

@media (prefers-reduced-motion: reduce) {

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.

🟢 Lowsrc/index.css:918

The prefers-reduced-motion override disables the active keyframe animation but leaves .preview-loading-progress-idle's 150 ms transform and opacity transitions untouched. When loading finishes, users with reduced motion enabled still see the bar animate from scaleX(0.9) to scaleX(1). Override the idle transition inside the media query as well.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/index.css around line 918:
The `prefers-reduced-motion` override disables the active keyframe animation but leaves `.preview-loading-progress-idle`'s 150 ms `transform` and `opacity` transitions untouched. When loading finishes, users with reduced motion enabled still see the bar animate from `scaleX(0.9)` to `scaleX(1)`. Override the idle transition inside the media query as well.

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing this PR after an automated pass over open pull requests. Abandoned bot draft is also replaced by the merged preview-rendering fix in #7561.

@t3dotggt3dotgg closed this Aug 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@t3dotgg@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Stop preview loading progress from rerendering the preview - #3968

Closed
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/component-performance-optimization-70d2
Closed

Stop preview loading progress from rerendering the preview#3968
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/component-performance-optimization-70d2

Conversation

@cursor

@cursorcursorBot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

What Changed

  • Replaced the 120 ms React state loop used by the preview loading bar with a compositor-driven CSS transform animation.
  • Removed useLoadingProgress, so progress animation no longer rerenders PreviewView and its browser surface.
  • Moved the URL focus synchronization effect into the named useFocusPreviewUrlInput hook.
  • Added a reduced-motion fallback.

Why

React Doctor flagged the loading progress hook's synchronous effect update. A manual ownership trace found the hook running in PreviewView, which made the entire preview tree reconcile roughly eight times per second for a cosmetic animation.

With React Scan enabled, the before recording grows from 1 to 50 parent commits during the measured loading cycle and repeatedly highlights PreviewChromeRow. The after recording stays at 2 commits throughout active loading and reaches 3 only when loading stops, while the progress bar still advances smoothly.

UI Changes

There is no intentional visual change to the loading indicator. Before/after React Scan recordings are included with the automation handoff:

  • react_scan_preview_loading_before.mp4
  • react_scan_preview_loading_after.mp4

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after React Scan recordings for the interaction
  • I included a video for animation/interaction changes

Validation: vp check --fix, vp run typecheck, 1,280 web unit tests, and React Doctor changed-file scan (0 diagnostics).

Open in WebView Automation

Note

Stop preview loading progress from rerendering the preview

  • Replaces the numeric loadProgress-driven progress bar with a CSS-animated bar controlled by a boolean loading state in PreviewChromeRow.tsx.
  • Adds a PreviewLoadingProgress component that stays mounted and toggles active/idle CSS classes, animating scaleX between 0.04 and 0.9 via keyframes in index.css.
  • Removes the useLoadingProgress hook that simulated asymptotic progress (0→90%, snap to 100%), eliminating the frequent numeric state updates that caused rerenders.
  • Respects prefers-reduced-motion by disabling the animation and applying a static transform.
📊 Macroscope summarized 7893cc9. 3 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 14, 2026
opacity 150ms ease-out 220ms;
}

@media (prefers-reduced-motion: reduce) {

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.

🟢 Lowsrc/index.css:918

The prefers-reduced-motion override disables the active keyframe animation but leaves .preview-loading-progress-idle's 150 ms transform and opacity transitions untouched. When loading finishes, users with reduced motion enabled still see the bar animate from scaleX(0.9) to scaleX(1). Override the idle transition inside the media query as well.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/index.css around line 918:
The `prefers-reduced-motion` override disables the active keyframe animation but leaves `.preview-loading-progress-idle`'s 150 ms `transform` and `opacity` transitions untouched. When loading finishes, users with reduced motion enabled still see the bar animate from `scaleX(0.9)` to `scaleX(1)`. Override the idle transition inside the media query as well.

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing this PR after an automated pass over open pull requests. Abandoned bot draft is also replaced by the merged preview-rendering fix in #7561.

@t3dotggt3dotgg closed this Aug 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@t3dotgg@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Stop preview loading progress from rerendering the preview - #3968

Closed
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/component-performance-optimization-70d2
Closed

Stop preview loading progress from rerendering the preview#3968
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/component-performance-optimization-70d2

Conversation

@cursor

@cursorcursorBot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

What Changed

  • Replaced the 120 ms React state loop used by the preview loading bar with a compositor-driven CSS transform animation.
  • Removed useLoadingProgress, so progress animation no longer rerenders PreviewView and its browser surface.
  • Moved the URL focus synchronization effect into the named useFocusPreviewUrlInput hook.
  • Added a reduced-motion fallback.

Why

React Doctor flagged the loading progress hook's synchronous effect update. A manual ownership trace found the hook running in PreviewView, which made the entire preview tree reconcile roughly eight times per second for a cosmetic animation.

With React Scan enabled, the before recording grows from 1 to 50 parent commits during the measured loading cycle and repeatedly highlights PreviewChromeRow. The after recording stays at 2 commits throughout active loading and reaches 3 only when loading stops, while the progress bar still advances smoothly.

UI Changes

There is no intentional visual change to the loading indicator. Before/after React Scan recordings are included with the automation handoff:

  • react_scan_preview_loading_before.mp4
  • react_scan_preview_loading_after.mp4

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after React Scan recordings for the interaction
  • I included a video for animation/interaction changes

Validation: vp check --fix, vp run typecheck, 1,280 web unit tests, and React Doctor changed-file scan (0 diagnostics).

Open in WebView Automation

Note

Stop preview loading progress from rerendering the preview

  • Replaces the numeric loadProgress-driven progress bar with a CSS-animated bar controlled by a boolean loading state in PreviewChromeRow.tsx.
  • Adds a PreviewLoadingProgress component that stays mounted and toggles active/idle CSS classes, animating scaleX between 0.04 and 0.9 via keyframes in index.css.
  • Removes the useLoadingProgress hook that simulated asymptotic progress (0→90%, snap to 100%), eliminating the frequent numeric state updates that caused rerenders.
  • Respects prefers-reduced-motion by disabling the animation and applying a static transform.
📊 Macroscope summarized 7893cc9. 3 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 14, 2026
opacity 150ms ease-out 220ms;
}

@media (prefers-reduced-motion: reduce) {

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.

🟢 Lowsrc/index.css:918

The prefers-reduced-motion override disables the active keyframe animation but leaves .preview-loading-progress-idle's 150 ms transform and opacity transitions untouched. When loading finishes, users with reduced motion enabled still see the bar animate from scaleX(0.9) to scaleX(1). Override the idle transition inside the media query as well.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/index.css around line 918:
The `prefers-reduced-motion` override disables the active keyframe animation but leaves `.preview-loading-progress-idle`'s 150 ms `transform` and `opacity` transitions untouched. When loading finishes, users with reduced motion enabled still see the bar animate from `scaleX(0.9)` to `scaleX(1)`. Override the idle transition inside the media query as well.

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing this PR after an automated pass over open pull requests. Abandoned bot draft is also replaced by the merged preview-rendering fix in #7561.

@t3dotggt3dotgg closed this Aug 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@t3dotgg@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Stop preview loading progress from rerendering the preview - #3968

Closed
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/component-performance-optimization-70d2
Closed

Stop preview loading progress from rerendering the preview#3968
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/component-performance-optimization-70d2

Conversation

@cursor

@cursorcursorBot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

What Changed

  • Replaced the 120 ms React state loop used by the preview loading bar with a compositor-driven CSS transform animation.
  • Removed useLoadingProgress, so progress animation no longer rerenders PreviewView and its browser surface.
  • Moved the URL focus synchronization effect into the named useFocusPreviewUrlInput hook.
  • Added a reduced-motion fallback.

Why

React Doctor flagged the loading progress hook's synchronous effect update. A manual ownership trace found the hook running in PreviewView, which made the entire preview tree reconcile roughly eight times per second for a cosmetic animation.

With React Scan enabled, the before recording grows from 1 to 50 parent commits during the measured loading cycle and repeatedly highlights PreviewChromeRow. The after recording stays at 2 commits throughout active loading and reaches 3 only when loading stops, while the progress bar still advances smoothly.

UI Changes

There is no intentional visual change to the loading indicator. Before/after React Scan recordings are included with the automation handoff:

  • react_scan_preview_loading_before.mp4
  • react_scan_preview_loading_after.mp4

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after React Scan recordings for the interaction
  • I included a video for animation/interaction changes

Validation: vp check --fix, vp run typecheck, 1,280 web unit tests, and React Doctor changed-file scan (0 diagnostics).

Open in WebView Automation

Note

Stop preview loading progress from rerendering the preview

  • Replaces the numeric loadProgress-driven progress bar with a CSS-animated bar controlled by a boolean loading state in PreviewChromeRow.tsx.
  • Adds a PreviewLoadingProgress component that stays mounted and toggles active/idle CSS classes, animating scaleX between 0.04 and 0.9 via keyframes in index.css.
  • Removes the useLoadingProgress hook that simulated asymptotic progress (0→90%, snap to 100%), eliminating the frequent numeric state updates that caused rerenders.
  • Respects prefers-reduced-motion by disabling the animation and applying a static transform.
📊 Macroscope summarized 7893cc9. 3 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 14, 2026
opacity 150ms ease-out 220ms;
}

@media (prefers-reduced-motion: reduce) {

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.

🟢 Lowsrc/index.css:918

The prefers-reduced-motion override disables the active keyframe animation but leaves .preview-loading-progress-idle's 150 ms transform and opacity transitions untouched. When loading finishes, users with reduced motion enabled still see the bar animate from scaleX(0.9) to scaleX(1). Override the idle transition inside the media query as well.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/index.css around line 918:
The `prefers-reduced-motion` override disables the active keyframe animation but leaves `.preview-loading-progress-idle`'s 150 ms `transform` and `opacity` transitions untouched. When loading finishes, users with reduced motion enabled still see the bar animate from `scaleX(0.9)` to `scaleX(1)`. Override the idle transition inside the media query as well.

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing this PR after an automated pass over open pull requests. Abandoned bot draft is also replaced by the merged preview-rendering fix in #7561.

@t3dotggt3dotgg closed this Aug 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@t3dotgg@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Stop preview loading progress from rerendering the preview - #3968

Closed
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/component-performance-optimization-70d2
Closed

Stop preview loading progress from rerendering the preview#3968
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/component-performance-optimization-70d2

Conversation

@cursor

@cursorcursorBot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

What Changed

  • Replaced the 120 ms React state loop used by the preview loading bar with a compositor-driven CSS transform animation.
  • Removed useLoadingProgress, so progress animation no longer rerenders PreviewView and its browser surface.
  • Moved the URL focus synchronization effect into the named useFocusPreviewUrlInput hook.
  • Added a reduced-motion fallback.

Why

React Doctor flagged the loading progress hook's synchronous effect update. A manual ownership trace found the hook running in PreviewView, which made the entire preview tree reconcile roughly eight times per second for a cosmetic animation.

With React Scan enabled, the before recording grows from 1 to 50 parent commits during the measured loading cycle and repeatedly highlights PreviewChromeRow. The after recording stays at 2 commits throughout active loading and reaches 3 only when loading stops, while the progress bar still advances smoothly.

UI Changes

There is no intentional visual change to the loading indicator. Before/after React Scan recordings are included with the automation handoff:

  • react_scan_preview_loading_before.mp4
  • react_scan_preview_loading_after.mp4

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after React Scan recordings for the interaction
  • I included a video for animation/interaction changes

Validation: vp check --fix, vp run typecheck, 1,280 web unit tests, and React Doctor changed-file scan (0 diagnostics).

Open in WebView Automation

Note

Stop preview loading progress from rerendering the preview

  • Replaces the numeric loadProgress-driven progress bar with a CSS-animated bar controlled by a boolean loading state in PreviewChromeRow.tsx.
  • Adds a PreviewLoadingProgress component that stays mounted and toggles active/idle CSS classes, animating scaleX between 0.04 and 0.9 via keyframes in index.css.
  • Removes the useLoadingProgress hook that simulated asymptotic progress (0→90%, snap to 100%), eliminating the frequent numeric state updates that caused rerenders.
  • Respects prefers-reduced-motion by disabling the animation and applying a static transform.
📊 Macroscope summarized 7893cc9. 3 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 14, 2026
opacity 150ms ease-out 220ms;
}

@media (prefers-reduced-motion: reduce) {

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.

🟢 Lowsrc/index.css:918

The prefers-reduced-motion override disables the active keyframe animation but leaves .preview-loading-progress-idle's 150 ms transform and opacity transitions untouched. When loading finishes, users with reduced motion enabled still see the bar animate from scaleX(0.9) to scaleX(1). Override the idle transition inside the media query as well.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/index.css around line 918:
The `prefers-reduced-motion` override disables the active keyframe animation but leaves `.preview-loading-progress-idle`'s 150 ms `transform` and `opacity` transitions untouched. When loading finishes, users with reduced motion enabled still see the bar animate from `scaleX(0.9)` to `scaleX(1)`. Override the idle transition inside the media query as well.

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing this PR after an automated pass over open pull requests. Abandoned bot draft is also replaced by the merged preview-rendering fix in #7561.

@t3dotggt3dotgg closed this Aug 23, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@t3dotgg@cursoragent