Implement custom scrollbar for DataTable component. Refactor structure to include a scrollable wrapper and synchronize scroll positions between the table and the custom scrollbar. Update styles for improved visibility and functionality of the scrollbar.

This commit is contained in:
burakovec
2025-12-18 12:36:51 +03:00
parent bf9c2b25f9
commit edb1d23d71
2 changed files with 144 additions and 4 deletions

View File

@ -1246,6 +1246,44 @@ section {
padding: 10px;
}
.list-wrapper-container {
width: 100%;
position: relative;
}
.list-wrapper-scrollbar-top {
width: 100%;
overflow-x: auto;
overflow-y: hidden;
height: 17px;
margin-bottom: 0;
display: none;
position: relative;
z-index: 10;
}
.list-wrapper-scrollbar-top .scrollbar-content {
height: 1px;
width: 0;
}
.list-wrapper-scrollbar-top::-webkit-scrollbar {
height: 17px;
}
.list-wrapper-scrollbar-top::-webkit-scrollbar-track {
background: transparent;
}
.list-wrapper-scrollbar-top::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, 0.2);
border-radius: 10px;
}
.list-wrapper-scrollbar-top::-webkit-scrollbar-thumb:hover {
background: rgba(0, 0, 0, 0.3);
}
.list-wrapper {
width: 100%;
position: relative;
@ -2374,6 +2412,14 @@ section {
width: 100% !important;
}
.list-wrapper-container {
overflow: visible;
}
.list-wrapper-scrollbar-top {
display: none !important;
}
.list-wrapper {
overflow: visible;
overflow-x: visible;

View File

@ -1,6 +1,10 @@
<template>
<div class="list-wrapper">
<table class="table-border table-colored table-list">
<div class="list-wrapper-container">
<div class="list-wrapper-scrollbar-top" ref="scrollbarTopRef">
<div class="scrollbar-content"></div>
</div>
<div class="list-wrapper" ref="listWrapperRef" @scroll="onScroll">
<table class="table-border table-colored table-list">
<thead>
<tr>
<th class="table-head-row-number" v-if="rowNumber">
@ -135,6 +139,7 @@
</template>
</tbody>
</table>
</div>
</div>
<data-table-pagination
v-if="pagination !== undefined && showPagination && !isPreview"
@ -142,7 +147,7 @@
:isUseRoute="isUseRoute" />
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch } from 'vue'
import { ref, reactive, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
import type { Ref } from 'vue'
import { useGlobalStore } from '@/stores/globalStore'
import icourl from '@/assets/images/icons.svg'
@ -172,7 +177,7 @@
}
export interface Props {
tableHeader: ITableHead[]
tableData: Record<string, any>
tableData: Record<string, any>[]
rowAction?: Function | string
pagination?: IPagination
sortData?: ISort
@ -285,6 +290,95 @@
},
{ deep: true }
)
watch(
() => props.tableData,
() => {
// Tablo verisi değiştiğinde scrollbar'ı güncelle
setTimeout(() => {
syncScrollbars()
}, 100)
},
{ deep: true }
)
const listWrapperRef = ref<HTMLElement | null>(null)
const scrollbarTopRef = ref<HTMLElement | null>(null)
const onScroll = (e: Event) => {
const target = e.target as HTMLElement
if (scrollbarTopRef.value) {
scrollbarTopRef.value.scrollLeft = target.scrollLeft
}
}
const syncScrollbars = () => {
if (listWrapperRef.value && scrollbarTopRef.value) {
const table = listWrapperRef.value.querySelector('table')
if (table) {
const tableWidth = table.scrollWidth
const wrapperWidth = listWrapperRef.value.clientWidth
if (tableWidth > wrapperWidth) {
scrollbarTopRef.value.style.display = 'block'
scrollbarTopRef.value.scrollLeft = listWrapperRef.value.scrollLeft
// Scrollbar wrapper'ın içeriğinin genişliğini tablo genişliğine eşitle
const scrollbarContent = scrollbarTopRef.value.querySelector('.scrollbar-content') as HTMLElement | null
if (scrollbarContent) {
scrollbarContent.style.width = tableWidth + 'px'
scrollbarContent.style.height = '1px'
}
} else {
scrollbarTopRef.value.style.display = 'none'
}
}
}
}
const onTopScroll = (e: Event) => {
const target = e.target as HTMLElement
if (listWrapperRef.value) {
listWrapperRef.value.scrollLeft = target.scrollLeft
}
}
onMounted(async () => {
await nextTick()
if (scrollbarTopRef.value) {
scrollbarTopRef.value.addEventListener('scroll', onTopScroll)
}
// İlk scrollbar senkronizasyonu
setTimeout(() => {
syncScrollbars()
}, 100)
const resizeObserver = new ResizeObserver(() => {
syncScrollbars()
})
if (listWrapperRef.value) {
resizeObserver.observe(listWrapperRef.value)
}
const tableObserver = new MutationObserver(() => {
syncScrollbars()
})
if (listWrapperRef.value) {
const table = listWrapperRef.value.querySelector('table')
if (table) {
tableObserver.observe(table, { childList: true, subtree: true, attributes: true })
}
}
})
onUnmounted(() => {
if (scrollbarTopRef.value) {
scrollbarTopRef.value.removeEventListener('scroll', onTopScroll)
}
})
</script>
<style scoped>
.action-fixed {