fix(fe): underline position on tab resize in Horizontal tabs
Replaces useElementSize with useResizeObserver to update the underline position and width when the active tab changes size, ensuring the underline stays correctly aligned even when tab content changes (e.g., badge count updates).
This commit is contained in:
@@ -98,7 +98,7 @@ import { isClient } from '@vueuse/core'
|
||||
import { ArrowLongRightIcon, ArrowLongLeftIcon } from '@heroicons/vue/24/outline'
|
||||
import type { Nullable } from '@speckle/shared'
|
||||
import { throttle } from '#lodash'
|
||||
import { useElementSize } from '@vueuse/core'
|
||||
import { useResizeObserver } from '@vueuse/core'
|
||||
import CommonBadge from '~~/src/components/common/Badge.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -113,7 +113,8 @@ const showLeftArrow = ref(false)
|
||||
const showRightArrow = ref(false)
|
||||
const isInitialSetup = ref(true)
|
||||
|
||||
const { width } = useElementSize(buttonContainer)
|
||||
const underlineLeft = ref('0px')
|
||||
const underlineWidth = ref('0px')
|
||||
|
||||
const buttonClass = computed(() => {
|
||||
return (item: LayoutPageTabItem) => {
|
||||
@@ -152,18 +153,18 @@ const activeItemRef = computed(() => {
|
||||
return btns.find((b) => b.dataset['tabId'] === id) || null
|
||||
})
|
||||
|
||||
const borderStyle = computed<CSSProperties>(() => {
|
||||
// Using width in calculation to force dependency
|
||||
return width.value
|
||||
? {
|
||||
left: `${activeItemRef.value?.offsetLeft || 0}px`,
|
||||
width: `${activeItemRef.value?.clientWidth || 0}px`
|
||||
}
|
||||
: {
|
||||
left: '0px',
|
||||
width: '0px'
|
||||
}
|
||||
})
|
||||
const borderStyle = computed<CSSProperties>(() => ({
|
||||
left: underlineLeft.value,
|
||||
width: underlineWidth.value
|
||||
}))
|
||||
|
||||
const updateUnderline = () => {
|
||||
const el = activeItemRef.value
|
||||
if (!el) return
|
||||
|
||||
underlineLeft.value = `${el.offsetLeft}px`
|
||||
underlineWidth.value = `${el.clientWidth}px`
|
||||
}
|
||||
|
||||
const setActiveItem = (item: LayoutPageTabItem) => {
|
||||
activeItem.value = item
|
||||
@@ -232,6 +233,19 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
// React to size changes of the active tab (e.g. when count badge disappears)
|
||||
watch(
|
||||
() => activeItemRef.value,
|
||||
(el, _prev, onCleanup) => {
|
||||
if (!el) return
|
||||
updateUnderline()
|
||||
|
||||
const { stop } = useResizeObserver(el, updateUnderline)
|
||||
onCleanup(stop)
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
handleScroll.cancel()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user