fix: make custom dropdowns and date pickers respect UI zoom setting
Teleported panels read zoom from #app and apply it to their own style, with position coordinates divided by the zoom factor so they align correctly with the zoomed trigger elements.
This commit is contained in:
@@ -122,24 +122,34 @@ const dayCells = computed<DayCell[]>(() => {
|
|||||||
const dayHeaders = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su']
|
const dayHeaders = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su']
|
||||||
|
|
||||||
// ── Positioning ─────────────────────────────────────────────────────
|
// ── Positioning ─────────────────────────────────────────────────────
|
||||||
|
function getZoomFactor(): number {
|
||||||
|
const app = document.getElementById('app')
|
||||||
|
if (!app) return 1
|
||||||
|
const zoom = (app.style as any).zoom
|
||||||
|
return zoom ? parseFloat(zoom) / 100 : 1
|
||||||
|
}
|
||||||
|
|
||||||
function updatePosition() {
|
function updatePosition() {
|
||||||
if (!triggerRef.value) return
|
if (!triggerRef.value) return
|
||||||
const rect = triggerRef.value.getBoundingClientRect()
|
const rect = triggerRef.value.getBoundingClientRect()
|
||||||
|
const zoom = getZoomFactor()
|
||||||
const panelWidth = 280
|
const panelWidth = 280
|
||||||
|
const renderedWidth = panelWidth * zoom
|
||||||
|
|
||||||
let left = rect.left
|
// Compute left in viewport space, then convert to panel's zoomed coordinate space
|
||||||
// Shift left if it would overflow the viewport right edge
|
let leftViewport = rect.left
|
||||||
if (left + panelWidth > window.innerWidth) {
|
if (leftViewport + renderedWidth > window.innerWidth) {
|
||||||
left = window.innerWidth - panelWidth - 8
|
leftViewport = window.innerWidth - renderedWidth - 8
|
||||||
}
|
}
|
||||||
if (left < 0) left = 0
|
if (leftViewport < 0) leftViewport = 0
|
||||||
|
|
||||||
panelStyle.value = {
|
panelStyle.value = {
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
top: `${rect.bottom + 4}px`,
|
top: `${(rect.bottom + 4) / zoom}px`,
|
||||||
left: `${left}px`,
|
left: `${leftViewport / zoom}px`,
|
||||||
width: `${panelWidth}px`,
|
width: `${panelWidth}px`,
|
||||||
zIndex: '9999',
|
zIndex: '9999',
|
||||||
|
zoom: `${zoom * 100}%`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,15 +64,24 @@ function isSelected(item: any): boolean {
|
|||||||
return val === props.modelValue
|
return val === props.modelValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getZoomFactor(): number {
|
||||||
|
const app = document.getElementById('app')
|
||||||
|
if (!app) return 1
|
||||||
|
const zoom = (app.style as any).zoom
|
||||||
|
return zoom ? parseFloat(zoom) / 100 : 1
|
||||||
|
}
|
||||||
|
|
||||||
function updatePosition() {
|
function updatePosition() {
|
||||||
if (!triggerRef.value) return
|
if (!triggerRef.value) return
|
||||||
const rect = triggerRef.value.getBoundingClientRect()
|
const rect = triggerRef.value.getBoundingClientRect()
|
||||||
|
const zoom = getZoomFactor()
|
||||||
panelStyle.value = {
|
panelStyle.value = {
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
top: `${rect.bottom + 4}px`,
|
top: `${(rect.bottom + 4) / zoom}px`,
|
||||||
left: `${rect.left}px`,
|
left: `${rect.left / zoom}px`,
|
||||||
width: `${rect.width}px`,
|
width: `${rect.width / zoom}px`,
|
||||||
zIndex: '9999',
|
zIndex: '9999',
|
||||||
|
zoom: `${zoom * 100}%`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user