mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-13 17:10:06 +00:00
## Summary On mobile viewports, the minimap settings panel now opens above the minimap instead of to the left, preventing it from extending off-screen on narrow viewports. <img width="918" height="974" alt="image" src="https://github.com/user-attachments/assets/bd42fb38-207f-437e-86f3-65cd2eccc666" /> <img width="1074" height="970" alt="image" src="https://github.com/user-attachments/assets/3fdd2109-a492-4570-a8ee-e67de171126b" /> ## Changes - Add mobile breakpoint detection using `useBreakpoints` from VueUse - Use `flex-col-reverse` on mobile to position panel above the minimap - Change margin from `mr-2` (right) to `mb-2` (bottom) on mobile ## Testing - On desktop (≥768px width): Panel opens to the left of minimap (unchanged) - On mobile (<768px width): Panel opens above the minimap ## Related - Fixes [Bug: Mobile minimap settings popover opens left instead of up](https://www.notion.so/comfy-org/Bug-Mobile-minimap-settings-popover-opens-left-instead-of-up-2fc6d73d365081549a57c9132526edca) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Minimap now adapts layout between mobile and desktop for improved usability. * Panel spacing and alignment adjust automatically to better fit small screens, improving readability and control placement. * Responsive behavior provides a more consistent experience across device sizes, with smoother transitions between compact (mobile) and wide (desktop) layouts. <!-- end of auto-generated comment: release notes by coderabbit.ai --> ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8589-fix-open-minimap-settings-panel-above-on-mobile-2fc6d73d365081ed8125c16051865c2b) by [Unito](https://www.unito.io)
158 lines
3.6 KiB
Vue
158 lines
3.6 KiB
Vue
<template>
|
|
<div
|
|
v-if="visible && initialized"
|
|
ref="minimapRef"
|
|
:class="
|
|
cn(
|
|
'minimap-main-container absolute right-0 bottom-[54px] z-1000 flex',
|
|
isMobile ? 'flex-col' : 'flex-row'
|
|
)
|
|
"
|
|
>
|
|
<MiniMapPanel
|
|
v-if="showOptionsPanel"
|
|
:panel-styles="panelStyles"
|
|
:node-colors="nodeColors"
|
|
:show-links="showLinks"
|
|
:show-groups="showGroups"
|
|
:render-bypass="renderBypass"
|
|
:render-error="renderError"
|
|
:is-mobile="isMobile"
|
|
@update-option="updateOption"
|
|
/>
|
|
|
|
<div
|
|
ref="containerRef"
|
|
class="litegraph-minimap relative border border-interface-stroke bg-comfy-menu-bg shadow-interface"
|
|
:style="containerStyles"
|
|
>
|
|
<Button
|
|
class="absolute top-0 left-0 z-10"
|
|
size="icon"
|
|
variant="muted-textonly"
|
|
:aria-label="$t('g.settings')"
|
|
@click.stop="toggleOptionsPanel"
|
|
>
|
|
<i class="icon-[lucide--settings-2]" />
|
|
</Button>
|
|
<Button
|
|
class="absolute top-0 right-0 z-10"
|
|
size="icon"
|
|
variant="muted-textonly"
|
|
:aria-label="$t('g.close')"
|
|
data-testid="close-minmap-button"
|
|
@click.stop="() => commandStore.execute('Comfy.Canvas.ToggleMinimap')"
|
|
>
|
|
<i class="icon-[lucide--x]" />
|
|
</Button>
|
|
|
|
<hr
|
|
class="absolute top-6 h-px border-0 bg-node-component-border"
|
|
:style="{
|
|
width: containerStyles.width
|
|
}"
|
|
/>
|
|
|
|
<canvas
|
|
ref="canvasRef"
|
|
:width="width"
|
|
:height="height"
|
|
class="minimap-canvas"
|
|
/>
|
|
|
|
<div class="minimap-viewport" :style="viewportStyles" />
|
|
|
|
<div
|
|
class="absolute inset-0 touch-none"
|
|
@pointerdown="handlePointerDown"
|
|
@pointermove="handlePointerMove"
|
|
@pointerup="handlePointerUp"
|
|
@pointerleave="handlePointerUp"
|
|
@pointercancel="handlePointerCancel"
|
|
@wheel="handleWheel"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { breakpointsTailwind, useBreakpoints } from '@vueuse/core'
|
|
import { onMounted, onUnmounted, ref, useTemplateRef } from 'vue'
|
|
|
|
import Button from '@/components/ui/button/Button.vue'
|
|
import { useMinimap } from '@/renderer/extensions/minimap/composables/useMinimap'
|
|
import { useCommandStore } from '@/stores/commandStore'
|
|
import { cn } from '@/utils/tailwindUtil'
|
|
|
|
import MiniMapPanel from './MiniMapPanel.vue'
|
|
|
|
const isMobile = useBreakpoints(breakpointsTailwind).smaller('md')
|
|
|
|
const commandStore = useCommandStore()
|
|
const minimapRef = ref<HTMLDivElement>()
|
|
const containerRef = useTemplateRef<HTMLDivElement>('containerRef')
|
|
const canvasRef = useTemplateRef<HTMLCanvasElement>('canvasRef')
|
|
|
|
const {
|
|
initialized,
|
|
visible,
|
|
containerStyles,
|
|
viewportStyles,
|
|
width,
|
|
height,
|
|
panelStyles,
|
|
nodeColors,
|
|
showLinks,
|
|
showGroups,
|
|
renderBypass,
|
|
renderError,
|
|
updateOption,
|
|
destroy,
|
|
handlePointerDown,
|
|
handlePointerMove,
|
|
handlePointerUp,
|
|
handlePointerCancel,
|
|
handleWheel,
|
|
setMinimapRef
|
|
} = useMinimap({
|
|
containerRefMaybe: containerRef,
|
|
canvasRefMaybe: canvasRef
|
|
})
|
|
|
|
const showOptionsPanel = ref(false)
|
|
|
|
const toggleOptionsPanel = () => {
|
|
showOptionsPanel.value = !showOptionsPanel.value
|
|
}
|
|
|
|
onMounted(() => {
|
|
if (minimapRef.value) {
|
|
setMinimapRef(minimapRef.value)
|
|
}
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
destroy()
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.litegraph-minimap {
|
|
overflow: hidden;
|
|
}
|
|
|
|
.minimap-canvas {
|
|
display: block;
|
|
width: 100%;
|
|
height: 100%;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.minimap-viewport {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
pointer-events: none;
|
|
}
|
|
</style>
|