Skip to content

Commit d87a513

Browse files
committed
chore(playground): fix splitter panel ordering and collapse after mobile transitions
- Keep SplitterPanel always mounted to preserve registration order with the SplitterRoot (unmount/remount via v-if inverts panel index, breaking drag direction and distribute calls) - Dynamic min-size (0 when closed or mobile, 30 when open on desktop) - Distribute [0, 100] on mobile to collapse the always-mounted panel - Watch left+isMobile with flush:post + nextTick to distribute after Splitter internals settle - Skip persisting collapsed distributions to preserve user's split
1 parent 6839c3a commit d87a513

File tree

2 files changed

+51
-21
lines changed

2 files changed

+51
-21
lines changed

apps/playground/src/components/playground/app/PlaygroundAppContent.vue

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,47 @@
11
<script setup lang="ts">
22
// Framework
3-
import { SplitterRoot, useStorage } from '@vuetify/v0'
3+
import { SplitterRoot, useBreakpoints, useStorage } from '@vuetify/v0'
4+
5+
// Components
6+
import { usePlayground } from './PlaygroundApp.vue'
47
58
// Utilities
6-
import { onMounted, useTemplateRef } from 'vue'
9+
import { nextTick, onMounted, useTemplateRef, watch } from 'vue'
710
11+
const playground = usePlayground()
12+
const { isMobile } = useBreakpoints()
813
const storage = useStorage()
914
const sizes = storage.get<number[]>('playground-h-sizes', [])
1015
1116
function onLayout (values: number[]) {
12-
sizes.value = values
17+
// Don't persist collapsed distributions — preserve the user's
18+
// preferred split so it can be restored when the panel reopens.
19+
if (values[0]! > 0) sizes.value = values
1320
}
1421
1522
const root = useTemplateRef<{ distribute: (sizes: number[]) => void }>('root')
1623
17-
onMounted(() => {
18-
if (sizes.value.length > 0) root.value?.distribute(sizes.value)
19-
})
24+
function distribute () {
25+
// On mobile or when left panel is closed, collapse to zero.
26+
// The SplitterPanel stays mounted to preserve registration order,
27+
// so its flex must be explicitly zeroed.
28+
if (isMobile.value || !playground.left.value) {
29+
root.value?.distribute([0, 100])
30+
} else if (sizes.value.length > 0) {
31+
root.value?.distribute(sizes.value)
32+
}
33+
}
34+
35+
onMounted(distribute)
36+
37+
// Re-distribute when left panel toggles or viewport changes.
38+
// flush: 'post' + nextTick ensures this runs after the Splitter's
39+
// own auto-redistribute watcher has settled.
40+
watch(
41+
() => [playground.left.value, isMobile.value] as const,
42+
() => nextTick(distribute),
43+
{ flush: 'post' },
44+
)
2045
</script>
2146

2247
<template>

apps/playground/src/components/playground/app/PlaygroundAppLeft.vue

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,27 @@
2525
</script>
2626

2727
<template>
28-
<!-- Desktop: only render SplitterPanel when open. When closed, the panel
29-
is removed entirely so PlaygroundAppRight takes full width naturally.
30-
No collapse timing issues — the Splitter never needs to redistribute. -->
31-
<template v-if="!isMobile && open">
32-
<SplitterPanel
33-
:default-size="30"
34-
:max-size="45"
35-
:min-size="30"
28+
<!-- Desktop: SplitterPanel is ALWAYS mounted to preserve registration order
29+
with the SplitterRoot. Unmounting on mobile would cause it to re-register
30+
at the end, inverting panel order and breaking drag direction. -->
31+
<SplitterPanel
32+
:default-size="30"
33+
:max-size="45"
34+
:min-size="open && !isMobile ? 30 : 0"
35+
>
36+
<div
37+
v-if="!isMobile && open"
38+
class="bg-surface h-full min-w-0 flex flex-col overflow-hidden"
3639
>
37-
<div class="bg-surface h-full min-w-0 flex flex-col overflow-hidden">
38-
<slot />
39-
</div>
40-
</SplitterPanel>
41-
42-
<PlaygroundSplitterHandle direction="horizontal" />
43-
</template>
40+
<slot />
41+
</div>
42+
</SplitterPanel>
43+
44+
<PlaygroundSplitterHandle
45+
v-if="!isMobile"
46+
direction="horizontal"
47+
:hidden="!open"
48+
/>
4449

4550
<!-- Mobile: fixed drawer -->
4651
<div

0 commit comments

Comments
 (0)