From 180c0b90d919eae5312a85e3cbd77a6afb47c309 Mon Sep 17 00:00:00 2001 From: Mikhail Novikov <10743009+notiv-nt@users.noreply.github.com> Date: Wed, 27 Aug 2025 15:06:42 +0300 Subject: [PATCH 1/2] Add swipeCloseThreshold --- .../src/BottomSheet.vue | 26 +++++++++++++++---- packages/vue-spring-bottom-sheet/src/types.ts | 1 + 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/packages/vue-spring-bottom-sheet/src/BottomSheet.vue b/packages/vue-spring-bottom-sheet/src/BottomSheet.vue index 359349f..a112604 100644 --- a/packages/vue-spring-bottom-sheet/src/BottomSheet.vue +++ b/packages/vue-spring-bottom-sheet/src/BottomSheet.vue @@ -316,11 +316,27 @@ const handlePan = async (_: PointerEvent, info: PanInfo) => { } const handlePanEnd = () => { - translateY.value = props.canSwipeClose - ? [0, height.value].reduce((prev, curr) => - Math.abs(curr - translateY.value) < Math.abs(prev - translateY.value) ? curr : prev, - ) - : 0 + if (props.canSwipeClose) { + let threshold = height.value / 2 + + if (props.swipeCloseThreshold && typeof props.swipeCloseThreshold === 'number') { + threshold = props.swipeCloseThreshold + } + + if ( + props.swipeCloseThreshold && + typeof props.swipeCloseThreshold === 'string' && + props.swipeCloseThreshold.includes('%') + ) { + threshold = height.value * (Number(props.swipeCloseThreshold.replace('%', '')) / 100) + } + + if (translateY.value > threshold) { + translateY.value = height.value + } + } else { + translateY.value = 0 + } controls = animate(translateYValue, translateY.value, { duration: props.duration / 1000, diff --git a/packages/vue-spring-bottom-sheet/src/types.ts b/packages/vue-spring-bottom-sheet/src/types.ts index fd0c7ce..8f07e02 100644 --- a/packages/vue-spring-bottom-sheet/src/types.ts +++ b/packages/vue-spring-bottom-sheet/src/types.ts @@ -6,6 +6,7 @@ export interface BottomSheetProps { initialSnapPoint?: number blocking?: boolean canSwipeClose?: boolean + swipeCloseThreshold?: string | number canBackdropClose?: boolean expandOnContentDrag?: boolean modelValue?: boolean From c3c1a85a6cf9f1d84cbbd9a78dcabc2aeb567c02 Mon Sep 17 00:00:00 2001 From: Mikhail Novikov <10743009+notiv-nt@users.noreply.github.com> Date: Wed, 27 Aug 2025 15:11:58 +0300 Subject: [PATCH 2/2] Update README.md --- README.md | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index e38f2f6..69a6732 100644 --- a/README.md +++ b/README.md @@ -132,20 +132,21 @@ For Nuxt 3, just wrap component in `` ### Prop Definitions -| Prop | Type | Default | Description | -| ------------------- | ------------------------- | ---------------- | ---------------------------------------------- | -| duration | Number | 250 | Animation duration in milliseconds | -| snapPoints | Array | [instinctHeight] | Custom snapping positions | -| initialSnapPoint | Number | minHeight | Initial snap point index | -| blocking | Boolean | true | Block interactions with underlying content | -| canSwipeClose | Boolean | true | Enable swipe-to-close gesture | -| canBackdropClose | Boolean | true | Allow closing by tapping backdrop | -| expandOnContentDrag | Boolean | true | Enable expanding by dragging content | -| teleprtTo | String \| RendererElement | body | Teleport to a specific element | -| teleportDefer | Boolean | false | Defer teleporting until opened (Vue 3.5+ only) | -| headerClass | String | '' | Set header element class | -| contentClass | String | '' | Set content element class | -| footerClass | String | '' | Set footer element class | +| Prop | Type | Default | Description | +| ------------------- | ------------------------- | ---------------- | ------------------------------------------------------------------------- | +| duration | Number | 250 | Animation duration in milliseconds | +| snapPoints | Array | [instinctHeight] | Custom snapping positions | +| initialSnapPoint | Number | minHeight | Initial snap point index | +| blocking | Boolean | true | Block interactions with underlying content | +| canSwipeClose | Boolean | true | Enable swipe-to-close gesture | +| swipeCloseThreshold | Number\|String | "50%" | The amount of translation (in px or %) after which the element will close | +| canBackdropClose | Boolean | true | Allow closing by tapping backdrop | +| expandOnContentDrag | Boolean | true | Enable expanding by dragging content | +| teleportTo | String \| RendererElement | body | Teleport to a specific element | +| teleportDefer | Boolean | false | Defer teleporting until opened (Vue 3.5+ only) | +| headerClass | String | '' | Set header element class | +| contentClass | String | '' | Set content element class | +| footerClass | String | '' | Set footer element class | ## Exposed methods @@ -160,7 +161,7 @@ Assuming there is `const bottomSheet = ref()` ## Events | Event | Description | Payload | -| -------------- | -------------------------------------- | ----------------------- | +| --------------- | -------------------------------------- | ----------------------- | | opened | Emitted when sheet finishes opening | - | | opening-started | Emitted when sheet starts opening | - | | closed | Emitted when sheet finishes closing | - |