Skip to content

Commit d4874de

Browse files
authored
fix: drag to resize slider is not correct with multiple columns #7754 (#8085)
fix: #7754 drag to resize slider is not correct with multiple columns
1 parent 8bcc60e commit d4874de

1 file changed

Lines changed: 34 additions & 14 deletions

File tree

‎apps/app-frontend/src/components/ui/world/RecentWorldsList.vue‎

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
useVIntl,
1010
} from '@modrinth/ui'
1111
import { useQueries, useQuery, useQueryClient } from '@tanstack/vue-query'
12+
import { useResizeObserver } from '@vueuse/core'
1213
import type { Dayjs } from 'dayjs'
1314
import dayjs from 'dayjs'
1415
import { computed, onUnmounted, ref, watch } from 'vue'
@@ -66,26 +67,36 @@ const gameVersions = computed(() => gameVersionsQuery.data.value ?? [])
6667
6768
const MAX_JUMP_BACK_IN = 5
6869
const MAX_NEW_INSTANCES = 3
69-
const ITEM_DRAG_DISTANCE = 92
70+
const ROW_DRAG_DISTANCE = 92
7071
const STORAGE_KEY = 'modrinth-jump-back-in-count'
7172
73+
const itemsGrid = ref<HTMLElement>()
74+
const columnCount = ref(1)
75+
useResizeObserver(itemsGrid, () => {
76+
if (!itemsGrid.value) return
77+
columnCount.value = getComputedStyle(itemsGrid.value).gridTemplateColumns.split(' ').length
78+
})
79+
7280
const storedVisibleCount = Number.parseInt(localStorage.getItem(STORAGE_KEY) ?? '', 10)
7381
const visibleItemLimit = ref(
7482
Number.isFinite(storedVisibleCount)
7583
? Math.max(1, Math.min(storedVisibleCount, MAX_JUMP_BACK_IN))
7684
: MAX_JUMP_BACK_IN,
7785
)
7886
const maxVisibleItems = computed(() => Math.min(jumpBackInItems.value.length, MAX_JUMP_BACK_IN))
79-
const visibleItemCount = computed(() => Math.min(visibleItemLimit.value, maxVisibleItems.value))
87+
const minVisibleItems = computed(() => Math.min(columnCount.value, maxVisibleItems.value))
88+
const visibleItemCount = computed(() =>
89+
Math.max(minVisibleItems.value, Math.min(visibleItemLimit.value, maxVisibleItems.value)),
90+
)
8091
const visibleJumpBackInItems = computed(() =>
8192
jumpBackInItems.value.slice(0, visibleItemCount.value),
8293
)
83-
const canResize = computed(() => maxVisibleItems.value > 1)
94+
const canResize = computed(() => maxVisibleItems.value > minVisibleItems.value)
8495
const resizing = ref(false)
8596
const showOverdrag = ref(false)
8697
8798
function setVisibleItemLimit(count: number) {
88-
const clamped = Math.max(1, Math.min(count, maxVisibleItems.value))
99+
const clamped = Math.max(minVisibleItems.value, Math.min(count, maxVisibleItems.value))
89100
if (clamped >= maxVisibleItems.value) {
90101
visibleItemLimit.value = MAX_JUMP_BACK_IN
91102
localStorage.removeItem(STORAGE_KEY)
@@ -95,9 +106,15 @@ function setVisibleItemLimit(count: number) {
95106
}
96107
}
97108
98-
function adjustVisibleItemLimit(delta: number) {
99-
const target = visibleItemCount.value + delta
100-
if (target < 1 || target > maxVisibleItems.value) {
109+
function getRowResizeTarget(count: number, rowDelta: number) {
110+
return rowDelta < 0
111+
? (Math.ceil(count / columnCount.value) + rowDelta) * columnCount.value
112+
: count + rowDelta * columnCount.value
113+
}
114+
115+
function adjustVisibleItemLimit(rowDelta: number) {
116+
const target = getRowResizeTarget(visibleItemCount.value, rowDelta)
117+
if (target < minVisibleItems.value || target > maxVisibleItems.value) {
101118
flashOverdrag()
102119
}
103120
setVisibleItemLimit(target)
@@ -140,8 +157,9 @@ function onResizePointerDown(event: PointerEvent) {
140157
141158
function onResizePointerMove(event: PointerEvent) {
142159
if (!resizing.value) return
143-
const target = dragStartCount + Math.round((event.clientY - dragStartY) / ITEM_DRAG_DISTANCE)
144-
const isOverdragging = target < 1 || target > maxVisibleItems.value
160+
const rowDelta = Math.round((event.clientY - dragStartY) / ROW_DRAG_DISTANCE)
161+
const target = getRowResizeTarget(dragStartCount, rowDelta)
162+
const isOverdragging = target < minVisibleItems.value || target > maxVisibleItems.value
145163
if (isOverdragging && !wasOverdragging) {
146164
flashOverdrag()
147165
}
@@ -180,8 +198,10 @@ type JumpBackInItem = InstanceJumpBackInItem | WorldJumpBackInItem
180198
181199
const showWorlds = computed(() => appSettings.showJumpIn)
182200
201+
const recentWorldsOptions = recentWorldsQueryOptions(MAX_JUMP_BACK_IN)
183202
const recentWorldsQuery = useQuery({
184-
...recentWorldsQueryOptions(MAX_JUMP_BACK_IN),
203+
...recentWorldsOptions,
204+
queryKey: [...recentWorldsOptions.queryKey] as const,
185205
enabled: showWorlds,
186206
})
187207
const loading = computed(() => showWorlds.value && recentWorldsQuery.isLoading.value)
@@ -423,7 +443,7 @@ onUnmounted(() => {
423443
<div v-if="loading" class="text-center py-4">
424444
<LoaderCircleIcon class="mx-auto size-8 animate-spin text-contrast" />
425445
</div>
426-
<div v-else class="grid-when-huge relative flex w-full flex-col gap-3">
446+
<div v-else ref="itemsGrid" class="grid-when-huge relative flex w-full flex-col gap-3">
427447
<TransitionGroup name="jump-back-in-item">
428448
<div
429449
v-for="item in visibleJumpBackInItems"
@@ -501,17 +521,17 @@ onUnmounted(() => {
501521
tabindex="0"
502522
aria-orientation="horizontal"
503523
:aria-label="formatMessage(messages.resize)"
504-
:aria-valuemin="1"
524+
:aria-valuemin="minVisibleItems"
505525
:aria-valuemax="maxVisibleItems"
506526
:aria-valuenow="visibleItemCount"
507-
class="group/resize relative inset-x-0 bottom-0 flex h-6 -mt-3 w-1/3 mx-auto cursor-ns-resize touch-none select-none items-center justify-center"
527+
class="group/resize relative col-span-full inset-x-0 bottom-0 flex h-6 -mt-3 w-1/3 mx-auto cursor-ns-resize touch-none select-none items-center justify-center"
508528
@pointerdown="onResizePointerDown"
509529
@pointermove="onResizePointerMove"
510530
@pointerup="endResize"
511531
@pointercancel="endResize"
512532
@keydown.up.prevent="adjustVisibleItemLimit(-1)"
513533
@keydown.down.prevent="adjustVisibleItemLimit(1)"
514-
@keydown.home.prevent="setVisibleItemLimit(1)"
534+
@keydown.home.prevent="setVisibleItemLimit(minVisibleItems)"
515535
@keydown.end.prevent="setVisibleItemLimit(maxVisibleItems)"
516536
>
517537
<div class="flex flex-col gap-0.5">

0 commit comments

Comments
 (0)