Skip to content

Conversation

@Gianthard-cyh
Copy link

Description

Introduced a scrollable container to:

  • Limit the number of visible modules and links to MAX_LINKS at a time.

  • Still allow users to scroll through the full list of modules.

  • Dynamically render only the currently visible MAX_LINKS connections.

2025-12-08.16-00-10.mp4

Linked Issues

#142

Additional context

Copilot AI review requested due to automatic review settings December 8, 2025 08:05
@netlify
Copy link

netlify bot commented Dec 8, 2025

Deploy Preview for vite-devtools ready!

Name Link
🔨 Latest commit bc5a0b4
🔍 Latest deploy log https://app.netlify.com/projects/vite-devtools/deploys/693686c8b667820008f31872
😎 Deploy Preview https://deploy-preview-143--vite-devtools.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@Gianthard-cyh Gianthard-cyh changed the title [UI] Enhance interaction of Module Import Relationships enhancement New feature or request [UI] Enhance interaction of Module Import Relationships enhancement Dec 8, 2025
@Gianthard-cyh Gianthard-cyh marked this pull request as draft December 8, 2025 08:06
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR enhances the Module Import Relationships visualization by adding a scrollable container for the importers list on the left side. The enhancement limits visible modules to a maximum of 20 (MAX_LINKS) while allowing users to scroll through the complete list. As users scroll, the connecting links dynamically update their positions to maintain visual alignment with the visible modules.

Key changes:

  • Introduced scroll tracking for the importers container using @vueuse/core's useScroll composable
  • Implemented dynamic link position updates based on scroll offset
  • Added unique IDs to links for better tracking during scroll updates

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

width: `${SPACING.width}px`,
v-if="importers?.length" ref="importersContainer" py1 overflow-y-auto :style="{
width: `${SPACING.width + SPACING.marginX}px`,
maxHeight: `${SPACING.height * importersMaxLength + SPACING.padding * (importersMaxLength - 1)}px`,
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

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

The maxHeight calculation is incorrect. It should include the (importersMaxLength + 1) padding, not (importersMaxLength - 1), to match the nodesHeight calculation at line 52. This causes the scroll container to be too short and cut off content.

The calculation should be:

maxHeight: `${SPACING.height * importersMaxLength + SPACING.padding * (importersMaxLength + 1)}px`,

This aligns with how nodesHeight is calculated: SPACING.height * normalizedMaxLinks.value + SPACING.padding * (normalizedMaxLinks.value + 1) + SPACING.border * 2

Suggested change
maxHeight: `${SPACING.height * importersMaxLength + SPACING.padding * (importersMaxLength - 1)}px`,
maxHeight: `${SPACING.height * importersMaxLength + SPACING.padding * (importersMaxLength + 1)}px`,

Copilot uses AI. Check for mistakes.
Comment on lines +191 to 192
v-if="module.imports?.length" py1 :style="{
width: `${SPACING.width}px`,
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

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

The imports container on the right side is not scrollable like the importers container on the left. If there are more than MAX_LINKS imports, they won't be visible or scrollable. Consider applying the same scrollable behavior to this container for consistency:

<div
  v-if="module.imports?.length" ref="importsContainer" py1 overflow-y-auto :style="{
    width: `${SPACING.width + SPACING.marginX}px`,
    maxHeight: `${SPACING.height * importsMaxLength + SPACING.padding * (importsMaxLength + 1)}px`,
    marginTop: `${importsVerticalOffset}px`,
  }"
>

You would also need to track scroll position and update import link positions similarly to importers.

Suggested change
v-if="module.imports?.length" py1 :style="{
width: `${SPACING.width}px`,
v-if="module.imports?.length" ref="importsContainer" py1 overflow-y-auto :style="{
width: `${SPACING.width + SPACING.marginX}px`,
maxHeight: `${SPACING.height * importsMaxLength + SPACING.padding * (importsMaxLength - 1)}px`,

Copilot uses AI. Check for mistakes.
Comment on lines +148 to +153
watch(
() => importersScrollY.value,
() => {
updateLinksOffset()
},
)
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

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

The scroll watcher triggers updateLinksOffset() on every scroll event, which can cause performance issues during rapid scrolling. Consider debouncing or throttling this watcher to reduce the number of updates:

watch(
  () => importersScrollY.value,
  useDebounceFn(() => {
    updateLinksOffset()
  }, 16), // ~60fps
)

Alternatively, use watchThrottled from @vueuse/core for better performance.

Copilot uses AI. Check for mistakes.
Comment on lines +132 to +140
function updateLinksOffset() {
for (const [idx, link] of links.value.entries()) {
if (idx >= (importersMaxLength.value)) {
continue
}
link.source.y = calculateLinkY('importer-start', idx)
}
triggerRef(links)
}
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

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

The updateLinksOffset() function only updates importer links but doesn't handle the case where there are no importers and only imports. When importersMaxLength.value is 0, all links could be import links, but they would still be checked and potentially modified incorrectly.

Consider adding a guard to ensure we're only updating importer links:

function updateLinksOffset() {
  if (!importers.value?.length) return
  
  for (const [idx, link] of links.value.entries()) {
    if (idx >= importersMaxLength.value) {
      continue
    }
    link.source.y = calculateLinkY('importer-start', idx)
  }
  triggerRef(links)
}

Copilot uses AI. Check for mistakes.
switch (type) {
case 'importer-start':
return ((SPACING.height + SPACING.padding) * i!) + (SPACING.height / 2 + SPACING.padding) + importersVerticalOffset.value
return ((SPACING.height + SPACING.padding) * i!) + (SPACING.height / 2 + SPACING.padding) + importersVerticalOffset.value - importersScrollY.value % (SPACING.height + SPACING.padding)
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

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

The scroll offset calculation uses modulo operation importersScrollY.value % (SPACING.height + SPACING.padding) which creates a visual "snapping" effect. However, this doesn't account for when there are fewer items than MAX_LINKS.

The modulo should only apply when scrolling is actually possible (i.e., when importers.value?.length > importersMaxLength). Otherwise, importersScrollY.value will always be 0 and the modulo operation is unnecessary.

Consider:

return ((SPACING.height + SPACING.padding) * i!) + (SPACING.height / 2 + SPACING.padding) + importersVerticalOffset.value - (importers.value?.length > importersMaxLength.value ? importersScrollY.value % (SPACING.height + SPACING.padding) : 0)
Suggested change
return ((SPACING.height + SPACING.padding) * i!) + (SPACING.height / 2 + SPACING.padding) + importersVerticalOffset.value - importersScrollY.value % (SPACING.height + SPACING.padding)
return ((SPACING.height + SPACING.padding) * i!) + (SPACING.height / 2 + SPACING.padding) + importersVerticalOffset.value - (importers.value?.length > importersMaxLength.value ? importersScrollY.value % (SPACING.height + SPACING.padding) : 0)

Copilot uses AI. Check for mistakes.
Comment on lines +163 to 167
v-if="importers?.length" ref="importersContainer" py1 overflow-y-auto :style="{
width: `${SPACING.width + SPACING.marginX}px`,
maxHeight: `${SPACING.height * importersMaxLength + SPACING.padding * (importersMaxLength - 1)}px`,
marginTop: `${importersVerticalOffset}px`,
}"
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

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

Multiple attributes on the same line reduce readability. While the formatting is syntactically correct, it would be more maintainable to keep each attribute on its own line or group related attributes together, especially for a div with 5+ attributes. Consider:

<div
  v-if="importers?.length"
  ref="importersContainer"
  py1
  overflow-y-auto
  :style="{
    width: `${SPACING.width + SPACING.marginX}px`,
    maxHeight: `${SPACING.height * importersMaxLength + SPACING.padding * (importersMaxLength + 1)}px`,
    marginTop: `${importersVerticalOffset}px`,
  }"
>

Copilot uses AI. Check for mistakes.
Comment on lines +150 to +152
() => {
updateLinksOffset()
},
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

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

The watch callback for importersScrollY can be simplified by passing the function reference directly instead of using an arrow function wrapper:

watch(
  () => importersScrollY.value,
  updateLinksOffset,
)
Suggested change
() => {
updateLinksOffset()
},
updateLinksOffset,

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant