From a2884da5f80cc865fdc5aeb298fb30fd90887f1f Mon Sep 17 00:00:00 2001 From: Zhong Date: Sat, 16 Aug 2025 01:18:31 +0800 Subject: [PATCH] fix(components): [splitter] collapse works with two-way size and min & max (#21738) * fix(components): [splitter] collapse works with two-way size and min * test: fix case * chore: rerun ci --- .../splitter/__tests__/splitter.test.tsx | 54 ++++++++++++++++++- .../components/splitter/src/split-panel.vue | 8 +-- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/packages/components/splitter/__tests__/splitter.test.tsx b/packages/components/splitter/__tests__/splitter.test.tsx index 87f24661e4..15b58d30cd 100644 --- a/packages/components/splitter/__tests__/splitter.test.tsx +++ b/packages/components/splitter/__tests__/splitter.test.tsx @@ -1,4 +1,4 @@ -import { nextTick } from 'vue' +import { nextTick, ref } from 'vue' import { mount } from '@vue/test-utils' import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' import { ElSplitter, ElSplitterPanel } from '../index' @@ -217,4 +217,56 @@ describe('Splitter', () => { await nextTick() expect(onCollapse).toHaveBeenCalledWith(0, 'end', [200, 200]) }) + + it('should collapse normally when size is two-way bound and min & max is set', async () => { + const size = ref(150) + const wrapper = mount(() => ( +
+ + + Left Panel + + Right Panel + +
+ )) + await nextTick() + + const panels = wrapper.findAll('.el-splitter-panel') + const startCollapseButton = wrapper.find( + '.el-splitter-bar__horizontal-collapse-icon-start' + ) + const endCollapseButton = wrapper.find( + '.el-splitter-bar__horizontal-collapse-icon-end' + ) + + // default size + expect(panels[0].attributes('style')).toContain('flex-basis: 150px;') + + // Click collapse button + await startCollapseButton.trigger('click') + await nextTick() + + // Panel should be collapsed (size = 0) + expect(panels[0].attributes('style')).toContain('flex-basis: 0px;') + + // Click collapse button to expand + await endCollapseButton.trigger('click') + await nextTick() + + // Panel should be restored to original size + expect(panels[0].attributes('style')).toContain('flex-basis: 150px;') + + // Click collapse button to expand + await endCollapseButton.trigger('click') + await nextTick() + + // Panel should be collapsed (size = 400) + expect(panels[0].attributes('style')).toContain('flex-basis: 400px;') + }) }) diff --git a/packages/components/splitter/src/split-panel.vue b/packages/components/splitter/src/split-panel.vue index 96a39334af..9d71c879f9 100644 --- a/packages/components/splitter/src/split-panel.vue +++ b/packages/components/splitter/src/split-panel.vue @@ -115,7 +115,7 @@ let isSizeUpdating = false watch( () => props.size, () => { - if (panel.value) { + if (!isSizeUpdating && panel.value) { const size = sizeToPx(props.size) const maxSize = sizeToPx(props.max) const minSize = sizeToPx(props.min) @@ -124,12 +124,10 @@ watch( const finalSize = Math.min(Math.max(size, minSize || 0), maxSize || size) if (finalSize !== size) { - isSizeUpdating = true emits('update:size', finalSize) } panel.value.size = finalSize - nextTick(() => (isSizeUpdating = false)) } } ) @@ -137,8 +135,10 @@ watch( watch( () => panel.value?.size, (val) => { - if (!isSizeUpdating && val !== props.size) { + if (val !== props.size) { + isSizeUpdating = true emits('update:size', val as number) + nextTick(() => (isSizeUpdating = false)) } } )