korbit-ai[bot] commented on code in PR #34233:
URL: https://github.com/apache/superset/pull/34233#discussion_r2217265301


##########
superset-frontend/src/utils/downloadAsImage.ts:
##########
@@ -70,9 +70,41 @@ export default function downloadAsImage(
       return true;
     };
 
+    // Check if element is scrollable
+    const isScrollable = hasScrollableDescendant(elementToPrint as 
HTMLElement);

Review Comment:
   ### Missing Debug Logs for Export Logic Path <sub>![category 
Logging](https://img.shields.io/badge/Logging-4f46e5)</sub>
   
   <details>
     <summary>Tell me more</summary>
   
   ###### What is the issue?
   Missing debug logging for scrollable element detection, which is a key 
decision point in the export logic.
   
   
   ###### Why this matters
   When troubleshooting export issues, it would be helpful to know whether the 
scrollable content path was taken and what dimensions were detected.
   
   ###### Suggested change ∙ *Feature Preview*
   ```typescript
   const isScrollable = hasScrollableDescendant(elementToPrint as HTMLElement);
   console.debug(`Element ${selector} scrollable status: ${isScrollable}, 
dimensions: ${elementToPrint.scrollWidth}x${elementToPrint.scrollHeight}`);
   ```
   
   
   ###### Provide feedback to improve future suggestions
   [![Nice 
Catch](https://img.shields.io/badge/👍%20Nice%20Catch-71BC78)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/5f2953da-5540-4c17-b82c-88311ee2e05e/upvote)
 
[![Incorrect](https://img.shields.io/badge/👎%20Incorrect-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/5f2953da-5540-4c17-b82c-88311ee2e05e?what_not_true=true)
  [![Not in 
Scope](https://img.shields.io/badge/👎%20Out%20of%20PR%20scope-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/5f2953da-5540-4c17-b82c-88311ee2e05e?what_out_of_scope=true)
 [![Not in coding 
standard](https://img.shields.io/badge/👎%20Not%20in%20our%20standards-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/5f2953da-5540-4c17-b82c-88311ee2e05e?what_not_in_standard=true)
 
[![Other](https://img.shields.io/badge/👎%20Other-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/5f2953da-5540-4c17-b82c-88311ee2e05e)
   </details>
   
   <sub>
   
   💬 Looking for more details? Reply to this comment to chat with Korbit.
   </sub>
   
   <!--- korbi internal id:ae9964a3-5462-4a6f-9ff8-4da4d4fac175 -->
   
   
   [](ae9964a3-5462-4a6f-9ff8-4da4d4fac175)



##########
superset-frontend/src/utils/downloadAsImage.ts:
##########
@@ -70,9 +70,41 @@
       return true;
     };
 
+    // Check if element is scrollable
+    const isScrollable = hasScrollableDescendant(elementToPrint as 
HTMLElement);
+    let targetElement = elementToPrint as HTMLElement;
+    let cloned: HTMLElement | null = null;
+    const extraPadding = theme?.sizeUnit ? theme.sizeUnit * 2 : 16;

Review Comment:
   ### Unexplained Magic Number <sub>![category 
Readability](https://img.shields.io/badge/Readability-0284c7)</sub>
   
   <details>
     <summary>Tell me more</summary>
   
   ###### What is the issue?
   Magic number 16 is used without explanation of its significance.
   
   
   ###### Why this matters
   Future developers won't understand why 16 was chosen as the default padding 
value, making maintenance risky.
   
   ###### Suggested change ∙ *Feature Preview*
   ```typescript
   const DEFAULT_PADDING = 16; // Default padding in pixels when theme is not 
available
   const extraPadding = theme?.sizeUnit ? theme.sizeUnit * 2 : DEFAULT_PADDING;
   ```
   
   
   ###### Provide feedback to improve future suggestions
   [![Nice 
Catch](https://img.shields.io/badge/👍%20Nice%20Catch-71BC78)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/b27d8d76-218d-466b-9f16-74c4c3e81782/upvote)
 
[![Incorrect](https://img.shields.io/badge/👎%20Incorrect-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/b27d8d76-218d-466b-9f16-74c4c3e81782?what_not_true=true)
  [![Not in 
Scope](https://img.shields.io/badge/👎%20Out%20of%20PR%20scope-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/b27d8d76-218d-466b-9f16-74c4c3e81782?what_out_of_scope=true)
 [![Not in coding 
standard](https://img.shields.io/badge/👎%20Not%20in%20our%20standards-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/b27d8d76-218d-466b-9f16-74c4c3e81782?what_not_in_standard=true)
 
[![Other](https://img.shields.io/badge/👎%20Other-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/b27d8d76-218d-466b-9f16-74c4c3e81782)
   </details>
   
   <sub>
   
   💬 Looking for more details? Reply to this comment to chat with Korbit.
   </sub>
   
   <!--- korbi internal id:b9c62fe0-677f-4490-8110-268a8f5be129 -->
   
   
   [](b9c62fe0-677f-4490-8110-268a8f5be129)



##########
superset-frontend/src/utils/downloadAsImage.ts:
##########
@@ -83,6 +115,38 @@
       })
       .catch((e: Error) => {
         console.error('Creating image failed', e);
+      })
+      .finally(() => {
+        if (cloned) {
+          document.body.removeChild(cloned);
+        }
       });
   };
 }
+
+/**
+ * Check if an element or any of its child elements is scrollable
+ *
+ * @param el - The HTMLElement to check for scrollable descendants.
+ * @returns `true` if any descendant has scrollable overflow; otherwise 
`false`.
+ */
+function hasScrollableDescendant(el: HTMLElement): boolean {
+  const treeWalker = document.createTreeWalker(el, NodeFilter.SHOW_ELEMENT);

Review Comment:
   ### Multiple forced reflows <sub>![category 
Performance](https://img.shields.io/badge/Performance-4f46e5)</sub>
   
   <details>
     <summary>Tell me more</summary>
   
   ###### What is the issue?
   TreeWalker is being used to check every element's scroll dimensions, which 
requires accessing layout properties that force reflow on each iteration.
   
   
   ###### Why this matters
   Each scrollHeight and clientHeight access forces the browser to recalculate 
layout, potentially causing significant performance overhead when checking many 
elements.
   
   ###### Suggested change ∙ *Feature Preview*
   Cache scroll-related values and batch DOM reads to minimize reflows. 
Consider using IntersectionObserver or a more efficient way to detect 
scrollable content.
   
   
   ###### Provide feedback to improve future suggestions
   [![Nice 
Catch](https://img.shields.io/badge/👍%20Nice%20Catch-71BC78)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/25f24d65-ca5b-4155-843a-f7d50dcf5719/upvote)
 
[![Incorrect](https://img.shields.io/badge/👎%20Incorrect-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/25f24d65-ca5b-4155-843a-f7d50dcf5719?what_not_true=true)
  [![Not in 
Scope](https://img.shields.io/badge/👎%20Out%20of%20PR%20scope-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/25f24d65-ca5b-4155-843a-f7d50dcf5719?what_out_of_scope=true)
 [![Not in coding 
standard](https://img.shields.io/badge/👎%20Not%20in%20our%20standards-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/25f24d65-ca5b-4155-843a-f7d50dcf5719?what_not_in_standard=true)
 
[![Other](https://img.shields.io/badge/👎%20Other-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/25f24d65-ca5b-4155-843a-f7d50dcf5719)
   </details>
   
   <sub>
   
   💬 Looking for more details? Reply to this comment to chat with Korbit.
   </sub>
   
   <!--- korbi internal id:8b54c2cb-a50e-4e32-9d09-307643f448a9 -->
   
   
   [](8b54c2cb-a50e-4e32-9d09-307643f448a9)



##########
superset-frontend/src/utils/downloadAsImage.ts:
##########
@@ -70,9 +70,41 @@
       return true;
     };
 
+    // Check if element is scrollable
+    const isScrollable = hasScrollableDescendant(elementToPrint as 
HTMLElement);
+    let targetElement = elementToPrint as HTMLElement;
+    let cloned: HTMLElement | null = null;
+    const extraPadding = theme?.sizeUnit ? theme.sizeUnit * 2 : 16;
+    if (isScrollable) {
+      cloned = elementToPrint.cloneNode(true) as HTMLElement;
+      cloned.style.overflow = 'visible';
+      cloned.style.maxHeight = 'none';
+      cloned.style.height = 'auto';
+      cloned.style.width = `${elementToPrint.scrollWidth}px`;
+
+      cloned.querySelectorAll<HTMLElement>('*').forEach(el => {
+        // eslint-disable-next-line no-param-reassign
+        el.style.overflow = 'visible';
+        // eslint-disable-next-line no-param-reassign
+        el.style.maxHeight = 'none';
+        // eslint-disable-next-line no-param-reassign
+        el.style.height = 'auto';
+      });

Review Comment:
   ### Extract scrollable element styling logic <sub>![category 
Design](https://img.shields.io/badge/Design-0d9488)</sub>
   
   <details>
     <summary>Tell me more</summary>
   
   ###### What is the issue?
   The styling logic for scrollable elements is mixed within the main download 
function and contains repetitive style assignments.
   
   
   ###### Why this matters
   Violates the Single Responsibility Principle and DRY principle, making the 
code harder to maintain and modify.
   
   ###### Suggested change ∙ *Feature Preview*
   Extract the styling logic into a separate function:
   ```typescript
   function prepareScrollableElement(element: HTMLElement): HTMLElement {
     const cloned = element.cloneNode(true) as HTMLElement;
     const styleProps = { overflow: 'visible', maxHeight: 'none', height: 
'auto' };
     
     Object.assign(cloned.style, styleProps);
     cloned.style.width = `${element.scrollWidth}px`;
     
     cloned.querySelectorAll<HTMLElement>('*')
       .forEach(el => Object.assign(el.style, styleProps));
     
     return cloned;
   }
   ```
   
   
   ###### Provide feedback to improve future suggestions
   [![Nice 
Catch](https://img.shields.io/badge/👍%20Nice%20Catch-71BC78)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/fcc09318-7a7e-44ae-b41a-7951852bc5e9/upvote)
 
[![Incorrect](https://img.shields.io/badge/👎%20Incorrect-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/fcc09318-7a7e-44ae-b41a-7951852bc5e9?what_not_true=true)
  [![Not in 
Scope](https://img.shields.io/badge/👎%20Out%20of%20PR%20scope-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/fcc09318-7a7e-44ae-b41a-7951852bc5e9?what_out_of_scope=true)
 [![Not in coding 
standard](https://img.shields.io/badge/👎%20Not%20in%20our%20standards-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/fcc09318-7a7e-44ae-b41a-7951852bc5e9?what_not_in_standard=true)
 
[![Other](https://img.shields.io/badge/👎%20Other-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/fcc09318-7a7e-44ae-b41a-7951852bc5e9)
   </details>
   
   <sub>
   
   💬 Looking for more details? Reply to this comment to chat with Korbit.
   </sub>
   
   <!--- korbi internal id:f84faf23-deeb-4ba5-a9b6-be3c7f7d0fb1 -->
   
   
   [](f84faf23-deeb-4ba5-a9b6-be3c7f7d0fb1)



##########
superset-frontend/src/utils/downloadAsImage.ts:
##########
@@ -70,9 +70,41 @@
       return true;
     };
 
+    // Check if element is scrollable
+    const isScrollable = hasScrollableDescendant(elementToPrint as 
HTMLElement);
+    let targetElement = elementToPrint as HTMLElement;
+    let cloned: HTMLElement | null = null;
+    const extraPadding = theme?.sizeUnit ? theme.sizeUnit * 2 : 16;
+    if (isScrollable) {
+      cloned = elementToPrint.cloneNode(true) as HTMLElement;
+      cloned.style.overflow = 'visible';
+      cloned.style.maxHeight = 'none';
+      cloned.style.height = 'auto';
+      cloned.style.width = `${elementToPrint.scrollWidth}px`;
+
+      cloned.querySelectorAll<HTMLElement>('*').forEach(el => {

Review Comment:
   ### Inefficient DOM traversal <sub>![category 
Performance](https://img.shields.io/badge/Performance-4f46e5)</sub>
   
   <details>
     <summary>Tell me more</summary>
   
   ###### What is the issue?
   Using querySelectorAll('*') followed by forEach creates unnecessary 
iteration over every DOM element, including those that don't need style 
modifications.
   
   
   ###### Why this matters
   This operation has O(n) complexity where n is the total number of DOM 
elements, potentially causing performance issues with large DOM trees. Many 
elements processed may not even have overflow or height/maxHeight styles.
   
   ###### Suggested change ∙ *Feature Preview*
   Target only elements that could have scroll-related styles using a more 
specific selector like '[style*="overflow"], [style*="height"]' or create a 
list of specific element types/classes that need modification.
   
   
   ###### Provide feedback to improve future suggestions
   [![Nice 
Catch](https://img.shields.io/badge/👍%20Nice%20Catch-71BC78)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/6b90533e-1c77-4654-b4f1-9c4ed9dd3c88/upvote)
 
[![Incorrect](https://img.shields.io/badge/👎%20Incorrect-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/6b90533e-1c77-4654-b4f1-9c4ed9dd3c88?what_not_true=true)
  [![Not in 
Scope](https://img.shields.io/badge/👎%20Out%20of%20PR%20scope-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/6b90533e-1c77-4654-b4f1-9c4ed9dd3c88?what_out_of_scope=true)
 [![Not in coding 
standard](https://img.shields.io/badge/👎%20Not%20in%20our%20standards-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/6b90533e-1c77-4654-b4f1-9c4ed9dd3c88?what_not_in_standard=true)
 
[![Other](https://img.shields.io/badge/👎%20Other-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/6b90533e-1c77-4654-b4f1-9c4ed9dd3c88)
   </details>
   
   <sub>
   
   💬 Looking for more details? Reply to this comment to chat with Korbit.
   </sub>
   
   <!--- korbi internal id:88fc5161-9d6d-43cd-9d66-d5bbcb38269a -->
   
   
   [](88fc5161-9d6d-43cd-9d66-d5bbcb38269a)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to