Skip to content

Commit 0279bc1

Browse files
feat: Add support for transitions (#12)
1 parent af6ae27 commit 0279bc1

File tree

4 files changed

+115
-2
lines changed

4 files changed

+115
-2
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<script lang="ts" setup>
2+
import { SplitPanel } from '@directus/vue-split-panel';
3+
</script>
4+
5+
<template>
6+
<SplitPanel
7+
class="w-full"
8+
collapsible
9+
size-unit="px"
10+
:min-size="250"
11+
:size="350"
12+
:max-size="500"
13+
:collapse-threshold="50"
14+
transition-duration="150ms"
15+
>
16+
<template #start>
17+
<div class="h-16 bg-orange-50 flex items-center justify-center">Panel A</div>
18+
</template>
19+
20+
<template #end>
21+
<div class="h-16 bg-blue-50 flex items-center justify-center">Panel B</div>
22+
</template>
23+
</SplitPanel>
24+
</template>

docs/content/1.getting-started/2.usage.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,21 @@ import { SplitPanel } from '@directus/vue-split-panel';
9696
::field{name="collapseThreshold" type="number"}
9797
How far to drag beyond the minSize to collapse/expand the primary panel.
9898
::
99+
100+
::field{name="transitionDuration" type="string"}
101+
Duration of the collapse/expand transition. Accepts a CSS duration value.
102+
Defaults to `"0"`
103+
::
104+
105+
::field{name="transitionTimingFunctionExpand" type="string"}
106+
CSS timing function for the expand transition.
107+
Defaults to `"cubic-bezier(0, 0, 0.2, 1)"`
108+
::
109+
110+
::field{name="transitionTimingFunctionCollapse" type="string"}
111+
CSS timing function for the collapse transition.
112+
Defaults to `"cubic-bezier(0.4, 0, 0.6, 1)"`
113+
::
99114
::
100115

101116
## Examples
@@ -376,6 +391,42 @@ import { SplitPanel } from '@directus/vue-split-panel';
376391
Resize your browser window to see primary in action.
377392
::
378393

394+
### Transitions
395+
396+
By setting the `transitionDuration` prop, you can control the duration of the transition. Use the `transitionTimingFunctionExpand` and `transitionTimingFunctionCollapse` properties to fine-tune the timing functions of the expand and collapse transition respectively.
397+
398+
::code-preview
399+
:example-transitions
400+
401+
#code
402+
```vue
403+
<script lang="ts" setup>
404+
import { SplitPanel } from '@directus/vue-split-panel';
405+
</script>
406+
407+
<template>
408+
<SplitPanel
409+
class="w-full"
410+
collapsible
411+
size-unit="px"
412+
:min-size="250"
413+
:size="350"
414+
:max-size="500"
415+
:collapse-threshold="50"
416+
transition-duration="150ms"
417+
>
418+
<template #start>
419+
<div class="h-16 bg-orange-50 flex items-center justify-center">Panel A</div>
420+
</template>
421+
422+
<template #end>
423+
<div class="h-16 bg-blue-50 flex items-center justify-center">Panel B</div>
424+
</template>
425+
</SplitPanel>
426+
</template>
427+
```
428+
::
429+
379430
## Accessibility
380431

381432
Uses the [Window Splitter WAI-ARIA pattern](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter).

docs/content/index.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,13 @@ A split panel component based on Reka-UI and Web Awesome Split Panel
6565
description: Create rich layouts by nesting split panel components
6666
---
6767
::::
68+
69+
::::u-page-feature
70+
---
71+
title: Transitions
72+
icon: lucide-send-to-back
73+
description: Support for transitions when collapsing/expanding the primary panel
74+
---
75+
::::
6876
:::
6977
::

packages/vue-split-panel/src/SplitPanel.vue

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,21 @@ export interface SplitPanelProps {
2929
3030
/** How far to drag beyond the minSize to collapse/expand the primary panel */
3131
collapseThreshold?: number;
32+
33+
/** How long should the collapse/expand state transition for in CSS value */
34+
transitionDuration?: string;
35+
36+
/** CSS transition timing function for the expand transition */
37+
transitionTimingFunctionExpand?: string;
38+
39+
/** CSS transition timing function for the collapse transition */
40+
transitionTimingFunctionCollapse?: string;
3241
}
3342
</script>
3443

3544
<script lang="ts" setup>
3645
import { clamp, useDraggable, useElementSize, useResizeObserver } from '@vueuse/core';
37-
import { computed, onMounted, useTemplateRef, watch } from 'vue';
46+
import { computed, onMounted, ref, useTemplateRef, watch } from 'vue';
3847
import { percentageToPixels } from './utils/percentage-to-pixels';
3948
import { pixelsToPercentage } from './utils/pixels-to-percentage';
4049
@@ -46,6 +55,9 @@ const props = withDefaults(defineProps<SplitPanelProps>(), {
4655
sizeUnit: '%',
4756
direction: 'ltr',
4857
collapsible: false,
58+
transitionDuration: '0',
59+
transitionTimingFunctionCollapse: 'cubic-bezier(0.4, 0, 0.6, 1)',
60+
transitionTimingFunctionExpand: 'cubic-bezier(0, 0, 0.2, 1)',
4961
});
5062
5163
const panelEl = useTemplateRef('split-panel');
@@ -116,13 +128,19 @@ let expandedSizePercentage = 0;
116128
/** Whether the primary column is collapsed or not */
117129
const collapsed = defineModel<boolean>('collapsed', { default: false });
118130
131+
const collapseTransitionState = ref<null | 'expanding' | 'collapsing'>(null);
132+
133+
const onTransitionEnd = () => collapseTransitionState.value = null;
134+
119135
watch(collapsed, (newCollapsed) => {
120136
if (newCollapsed === true) {
121137
expandedSizePercentage = sizePercentage.value;
122138
sizePercentage.value = 0;
139+
collapseTransitionState.value = 'collapsing';
123140
}
124141
else {
125142
sizePercentage.value = expandedSizePercentage;
143+
collapseTransitionState.value = 'expanding';
126144
}
127145
});
128146
@@ -260,7 +278,7 @@ defineExpose({ collapse, expand, toggle });
260278
</script>
261279

262280
<template>
263-
<div ref="split-panel" class="split-panel" :class="[orientation, { collapsed, dragging: isDragging }]">
281+
<div ref="split-panel" class="split-panel" :class="[orientation, collapseTransitionState, { collapsed, dragging: isDragging }]" @transitionend="onTransitionEnd">
264282
<div class="start">
265283
<slot name="start" />
266284
</div>
@@ -291,16 +309,28 @@ defineExpose({ collapse, expand, toggle });
291309
display: grid;
292310
293311
&.horizontal {
312+
transition-property: grid-template-columns;
294313
grid-template-columns: v-bind(gridTemplate);
295314
}
296315
297316
&.vertical {
298317
grid-template-rows: v-bind(gridTemplate);
318+
transition-property: grid-template-rows;
299319
}
300320
301321
&.dragging {
302322
user-select: none;
303323
}
324+
325+
&.collapsing {
326+
transition-duration: v-bind(transitionDuration);
327+
transition-timing-function: v-bind(transitionTimingFunctionCollapse);
328+
}
329+
330+
&.expanding {
331+
transition-duration: v-bind(transitionDuration);
332+
transition-timing-function: v-bind(transitionTimingFunctionExpand);
333+
}
304334
}
305335
306336
.start, .end {

0 commit comments

Comments
 (0)