Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions docs/components/example/ExampleTransitions.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script lang="ts" setup>
import { SplitPanel } from '@directus/vue-split-panel';
</script>

<template>
<SplitPanel
class="w-full"
collapsible
size-unit="px"
:min-size="250"
:size="350"
:max-size="500"
:collapse-threshold="50"
transition-duration="150ms"
>
<template #start>
<div class="h-16 bg-orange-50 flex items-center justify-center">Panel A</div>
</template>

<template #end>
<div class="h-16 bg-blue-50 flex items-center justify-center">Panel B</div>
</template>
</SplitPanel>
</template>
51 changes: 51 additions & 0 deletions docs/content/1.getting-started/2.usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,21 @@ import { SplitPanel } from '@directus/vue-split-panel';
::field{name="collapseThreshold" type="number"}
How far to drag beyond the minSize to collapse/expand the primary panel.
::

::field{name="transitionDuration" type="string"}
Duration of the collapse/expand transition. Accepts a CSS duration value.
Defaults to `"0"`
::

::field{name="transitionTimingFunctionExpand" type="string"}
CSS timing function for the expand transition.
Defaults to `"cubic-bezier(0, 0, 0.2, 1)"`
::

::field{name="transitionTimingFunctionCollapse" type="string"}
CSS timing function for the collapse transition.
Defaults to `"cubic-bezier(0.4, 0, 0.6, 1)"`
::
::

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

### Transitions

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.

::code-preview
:example-transitions

#code
```vue
<script lang="ts" setup>
import { SplitPanel } from '@directus/vue-split-panel';
</script>

<template>
<SplitPanel
class="w-full"
collapsible
size-unit="px"
:min-size="250"
:size="350"
:max-size="500"
:collapse-threshold="50"
transition-duration="150ms"
>
<template #start>
<div class="h-16 bg-orange-50 flex items-center justify-center">Panel A</div>
</template>

<template #end>
<div class="h-16 bg-blue-50 flex items-center justify-center">Panel B</div>
</template>
</SplitPanel>
</template>
```
::

## Accessibility

Uses the [Window Splitter WAI-ARIA pattern](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter).
Expand Down
8 changes: 8 additions & 0 deletions docs/content/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,13 @@ A split panel component based on Reka-UI and Web Awesome Split Panel
description: Create rich layouts by nesting split panel components
---
::::

::::u-page-feature
---
title: Transitions
icon: lucide-send-to-back
description: Support for transitions when collapsing/expanding the primary panel
---
::::
:::
::
34 changes: 32 additions & 2 deletions packages/vue-split-panel/src/SplitPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,21 @@ export interface SplitPanelProps {

/** How far to drag beyond the minSize to collapse/expand the primary panel */
collapseThreshold?: number;

/** How long should the collapse/expand state transition for in CSS value */
transitionDuration?: string;

/** CSS transition timing function for the expand transition */
transitionTimingFunctionExpand?: string;

/** CSS transition timing function for the collapse transition */
transitionTimingFunctionCollapse?: string;
}
</script>

<script lang="ts" setup>
import { clamp, useDraggable, useElementSize, useResizeObserver } from '@vueuse/core';
import { computed, onMounted, useTemplateRef, watch } from 'vue';
import { computed, onMounted, ref, useTemplateRef, watch } from 'vue';
import { percentageToPixels } from './utils/percentage-to-pixels';
import { pixelsToPercentage } from './utils/pixels-to-percentage';

Expand All @@ -46,6 +55,9 @@ const props = withDefaults(defineProps<SplitPanelProps>(), {
sizeUnit: '%',
direction: 'ltr',
collapsible: false,
transitionDuration: '0',
transitionTimingFunctionCollapse: 'cubic-bezier(0.4, 0, 0.6, 1)',
transitionTimingFunctionExpand: 'cubic-bezier(0, 0, 0.2, 1)',
});

const panelEl = useTemplateRef('split-panel');
Expand Down Expand Up @@ -116,13 +128,19 @@ let expandedSizePercentage = 0;
/** Whether the primary column is collapsed or not */
const collapsed = defineModel<boolean>('collapsed', { default: false });

const collapseTransitionState = ref<null | 'expanding' | 'collapsing'>(null);

const onTransitionEnd = () => collapseTransitionState.value = null;

watch(collapsed, (newCollapsed) => {
if (newCollapsed === true) {
expandedSizePercentage = sizePercentage.value;
sizePercentage.value = 0;
collapseTransitionState.value = 'collapsing';
}
else {
sizePercentage.value = expandedSizePercentage;
collapseTransitionState.value = 'expanding';
}
});

Expand Down Expand Up @@ -260,7 +278,7 @@ defineExpose({ collapse, expand, toggle });
</script>

<template>
<div ref="split-panel" class="split-panel" :class="[orientation, { collapsed, dragging: isDragging }]">
<div ref="split-panel" class="split-panel" :class="[orientation, collapseTransitionState, { collapsed, dragging: isDragging }]" @transitionend="onTransitionEnd">
<div class="start">
<slot name="start" />
</div>
Expand Down Expand Up @@ -291,16 +309,28 @@ defineExpose({ collapse, expand, toggle });
display: grid;

&.horizontal {
transition-property: grid-template-columns;
grid-template-columns: v-bind(gridTemplate);
}

&.vertical {
grid-template-rows: v-bind(gridTemplate);
transition-property: grid-template-rows;
}

&.dragging {
user-select: none;
}

&.collapsing {
transition-duration: v-bind(transitionDuration);
transition-timing-function: v-bind(transitionTimingFunctionCollapse);
}

&.expanding {
transition-duration: v-bind(transitionDuration);
transition-timing-function: v-bind(transitionTimingFunctionExpand);
}
}

.start, .end {
Expand Down