Remove the ScrollArea from the sidebar

This commit is contained in:
pa
2026-01-25 18:56:12 +09:00
parent 7e312a0e8c
commit 722cc615cb
3 changed files with 127 additions and 182 deletions
-5
View File
@@ -95,16 +95,12 @@
</template> </template>
<template #friends> <template #friends>
<div class="h-full overflow-hidden"> <div class="h-full overflow-hidden">
<ScrollArea class="h-full">
<FriendsSidebar /> <FriendsSidebar />
</ScrollArea>
</div> </div>
</template> </template>
<template #groups> <template #groups>
<div class="h-full overflow-hidden"> <div class="h-full overflow-hidden">
<ScrollArea class="h-full">
<GroupsSidebar /> <GroupsSidebar />
</ScrollArea>
</div> </div>
</template> </template>
</TabsUnderline> </TabsUnderline>
@@ -118,7 +114,6 @@
import { DataTableEmpty } from '@/components/ui/data-table'; import { DataTableEmpty } from '@/components/ui/data-table';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { RefreshCw } from 'lucide-vue-next'; import { RefreshCw } from 'lucide-vue-next';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Spinner } from '@/components/ui/spinner'; import { Spinner } from '@/components/ui/spinner';
import { TabsUnderline } from '@/components/ui/tabs'; import { TabsUnderline } from '@/components/ui/tabs';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
+15 -41
View File
@@ -1,21 +1,24 @@
<template> <template>
<div ref="listRootRef" class="x-friend-list" style="padding: 10px 5px"> <div ref="scrollRootRef" class="relative h-full">
<div v-if="virtualRows.length" class="friend-sidebar__virtual" :style="virtualContainerStyle"> <div ref="scrollViewportRef" class="h-full w-full overflow-auto">
<div class="x-friend-list px-1.5 py-2.5">
<div v-if="virtualRows.length" class="relative w-full box-border" :style="virtualContainerStyle">
<template v-for="item in virtualItems" :key="String(item.virtualItem.key)"> <template v-for="item in virtualItems" :key="String(item.virtualItem.key)">
<div <div
v-if="item.row" v-if="item.row"
class="friend-sidebar__virtual-row" class="absolute left-0 top-0 w-full box-border"
:class="`friend-sidebar__virtual-row--${item.row.type}`"
:data-index="item.virtualItem.index" :data-index="item.virtualItem.index"
:ref="virtualizer.measureElement" :ref="virtualizer.measureElement"
:style="rowStyle(item)"> :style="rowStyle(item)">
<template v-if="item.row.type === 'toggle-header'"> <template v-if="item.row.type === 'toggle-header'">
<div <div
class="x-friend-group cursor-pointer flex items-center" class="x-friend-group flex cursor-pointer items-center pt-4 pb-1.5 text-xs"
:style="item.row.headerPadding ? { padding: item.row.headerPadding } : undefined" :style="item.row.headerPadding ? { padding: item.row.headerPadding } : undefined"
@click="item.row.onClick && item.row.onClick()"> @click="item.row.onClick && item.row.onClick()">
<ChevronDown class="rotation-transition" :class="{ 'is-rotated': !item.row.expanded }" /> <ChevronDown
<span style="margin-left: 5px"> class="transition-transform duration-200 ease-in-out"
:class="{ '-rotate-90': !item.row.expanded }" />
<span class="ml-1.5">
{{ item.row.label }} {{ item.row.label }}
<template v-if="item.row.count !== null && item.row.count !== undefined"> <template v-if="item.row.count !== null && item.row.count !== undefined">
&horbar; {{ item.row.count }} &horbar; {{ item.row.count }}
@@ -59,14 +62,14 @@
<template v-else-if="item.row.type === 'vip-subheader'"> <template v-else-if="item.row.type === 'vip-subheader'">
<div> <div>
<span class="text-xs">{{ item.row.label }}</span> <span class="text-xs">{{ item.row.label }}</span>
<span class="text-xs" style="margin-left: 5px">{{ `(${item.row.count})` }}</span> <span class="text-xs ml-1.5">{{ `(${item.row.count})` }}</span>
</div> </div>
</template> </template>
<template v-else-if="item.row.type === 'instance-header'"> <template v-else-if="item.row.type === 'instance-header'">
<div class="mb-1 flex items-center"> <div class="mb-1 flex items-center">
<Location class="text-xs" :location="item.row.location" style="display: inline" /> <Location class="inline text-xs" :location="item.row.location" />
<span class="text-xs" style="margin-left: 5px">{{ `(${item.row.count})` }}</span> <span class="text-xs ml-1.5">{{ `(${item.row.count})` }}</span>
</div> </div>
</template> </template>
@@ -79,6 +82,8 @@
</div> </div>
</template> </template>
</div> </div>
</div>
</div>
<BackToTopVirtual :virtualizer="virtualizer" :target="scrollViewportRef" :teleport-to="scrollRootRef" /> <BackToTopVirtual :virtualizer="virtualizer" :target="scrollViewportRef" :teleport-to="scrollRootRef" />
</div> </div>
</template> </template>
@@ -127,7 +132,6 @@
const isActiveFriends = ref(true); const isActiveFriends = ref(true);
const isOfflineFriends = ref(true); const isOfflineFriends = ref(true);
const isSidebarGroupByInstanceCollapsed = ref(false); const isSidebarGroupByInstanceCollapsed = ref(false);
const listRootRef = ref(null);
const scrollViewportRef = ref(null); const scrollViewportRef = ref(null);
const scrollRootRef = ref(null); const scrollRootRef = ref(null);
@@ -476,8 +480,6 @@
} }
onMounted(() => { onMounted(() => {
scrollViewportRef.value = listRootRef.value?.closest('[data-slot="scroll-area-viewport"]') ?? null;
scrollRootRef.value = listRootRef.value?.closest('[data-slot="scroll-area"]') ?? null;
nextTick(() => { nextTick(() => {
virtualizer.value?.measure?.(); virtualizer.value?.measure?.();
}); });
@@ -490,31 +492,3 @@
}); });
}); });
</script> </script>
<style scoped>
.is-rotated {
transform: rotate(-90deg);
}
.rotation-transition {
transition: transform 0.2s ease-in-out;
}
.friend-sidebar__virtual {
width: 100%;
position: relative;
box-sizing: border-box;
}
.friend-sidebar__virtual-row {
width: 100%;
box-sizing: border-box;
position: absolute;
left: 0;
top: 0;
}
.friend-sidebar__virtual-row--toggle-header .x-friend-group {
padding: 16px 0 6px;
font-size: 12px;
}
</style>
+20 -44
View File
@@ -1,25 +1,30 @@
<template> <template>
<div ref="listRootRef" class="x-friend-list" style="padding: 10px 5px"> <div ref="scrollRootRef" class="relative h-full">
<div v-if="virtualRows.length" class="group-sidebar__virtual" :style="virtualContainerStyle"> <div ref="scrollViewportRef" class="h-full w-full overflow-auto">
<div class="x-friend-list px-1.5 py-2.5">
<div v-if="virtualRows.length" class="relative w-full box-border" :style="virtualContainerStyle">
<template v-for="item in virtualItems" :key="String(item.virtualItem.key)"> <template v-for="item in virtualItems" :key="String(item.virtualItem.key)">
<div <div
v-if="item.row" v-if="item.row"
class="group-sidebar__virtual-row" class="absolute left-0 top-0 w-full box-border"
:class="`group-sidebar__virtual-row--${item.row.type}`"
:data-index="item.virtualItem.index" :data-index="item.virtualItem.index"
:ref="virtualizer.measureElement" :ref="virtualizer.measureElement"
:style="rowStyle(item)"> :style="rowStyle(item)">
<template v-if="item.row.type === 'group-header'"> <template v-if="item.row.type === 'group-header'">
<div <div
class="x-friend-group cursor-pointer" class="x-friend-group cursor-pointer pt-4 pb-1.5 text-xs"
:style="item.row.headerPaddingTop ? { paddingTop: item.row.headerPaddingTop } : undefined"> :style="
item.row.headerPaddingTop
? { paddingTop: item.row.headerPaddingTop }
: undefined
">
<div <div
@click="toggleGroupSidebarCollapse(item.row.groupId)" @click="toggleGroupSidebarCollapse(item.row.groupId)"
style="display: flex; align-items: center"> class="flex items-center">
<ChevronDown <ChevronDown
class="rotation-transition" class="transition-transform duration-200 ease-in-out"
:class="{ 'is-rotated': item.row.isCollapsed }" /> :class="{ '-rotate-90': item.row.isCollapsed }" />
<span style="margin-left: 5px"> {{ item.row.label }} {{ item.row.count }} </span> <span class="ml-1.5"> {{ item.row.label }} {{ item.row.count }} </span>
</div> </div>
</div> </div>
</template> </template>
@@ -33,9 +38,9 @@
<div class="detail"> <div class="detail">
<span class="name"> <span class="name">
<span v-text="item.row.name"></span> <span v-text="item.row.name"></span>
<span style="font-weight: normal; margin-left: 5px" <span class="ml-1.5 font-normal">
>({{ item.row.userCount }}/{{ item.row.capacity }})</span ({{ item.row.userCount }}/{{ item.row.capacity }})
> </span>
</span> </span>
<Location class="text-xs" :location="item.row.location" :link="false" /> <Location class="text-xs" :location="item.row.location" :link="false" />
</div> </div>
@@ -45,6 +50,8 @@
</div> </div>
</template> </template>
</div> </div>
</div>
</div>
<BackToTopVirtual :virtualizer="virtualizer" :target="scrollViewportRef" :teleport-to="scrollRootRef" /> <BackToTopVirtual :virtualizer="virtualizer" :target="scrollViewportRef" :teleport-to="scrollRootRef" />
</div> </div>
</template> </template>
@@ -66,7 +73,6 @@
const { groupInstances } = storeToRefs(useGroupStore()); const { groupInstances } = storeToRefs(useGroupStore());
const groupInstancesCfg = ref({}); const groupInstancesCfg = ref({});
const listRootRef = ref(null);
const scrollViewportRef = ref(null); const scrollViewportRef = ref(null);
const scrollRootRef = ref(null); const scrollRootRef = ref(null);
@@ -177,8 +183,6 @@
} }
onMounted(() => { onMounted(() => {
scrollViewportRef.value = listRootRef.value?.closest('[data-slot="scroll-area-viewport"]') ?? null;
scrollRootRef.value = listRootRef.value?.closest('[data-slot="scroll-area"]') ?? null;
nextTick(() => { nextTick(() => {
virtualizer.value?.measure?.(); virtualizer.value?.measure?.();
}); });
@@ -190,31 +194,3 @@
}); });
}); });
</script> </script>
<style scoped>
.is-rotated {
transform: rotate(-90deg);
}
.rotation-transition {
transition: transform 0.2s ease-in-out;
}
.group-sidebar__virtual {
width: 100%;
position: relative;
box-sizing: border-box;
}
.group-sidebar__virtual-row {
width: 100%;
box-sizing: border-box;
position: absolute;
left: 0;
top: 0;
}
.group-sidebar__virtual-row--group-header .x-friend-group {
padding: 16px 0 5px;
font-size: 12px;
}
</style>