Skip to content

Getting Started

Basic Usage

BottomSheet is a touch-driven bottom sheet component with built-in inertia scrolling and spring snap animations. Just place your content inside the default slot.

vue
<script setup>
import { BottomSheet } from '@wyatex/bottom-sheet'
import '@wyatex/bottom-sheet/dist/style.css'
</script>

<template>
  <div class="app">
    <!-- Background content -->
    <div class="map">
      ...
    </div>

    <!-- Bottom sheet -->
    <BottomSheet>
      <div v-for="n in 20" :key="n" class="item">
        Item {{ n }}
      </div>
    </BottomSheet>
  </div>
</template>

BottomSheet is positioned with position: absolute, so make sure its parent has a positioning context (e.g. position: relative or fixed).

Infinite Scroll

Listen to the load-more event to implement scroll-to-load:

vue
<script setup>
import { BottomSheet } from '@wyatex/bottom-sheet'
import { ref } from 'vue'
import '@wyatex/bottom-sheet/dist/style.css'

const items = ref([])
const loading = ref(false)

function loadMore() {
  if (loading.value)
    return
  loading.value = true

  setTimeout(() => {
    for (let i = 0; i < 20; i++) {
      items.value.push({ id: items.value.length, text: `Item ${items.value.length + 1}` })
    }
    loading.value = false
  }, 500)
}
</script>

<template>
  <BottomSheet @load-more="loadMore">
    <div v-for="item in items" :key="item.id" class="item">
      {{ item.text }}
    </div>
    <div v-if="loading" class="loading">
      Loading...
    </div>
  </BottomSheet>
</template>

The load-more event fires when the inner list scrolls to within 50px of the bottom.

Custom Snap Points

The three default snap points are calculated as a percentage of screen height:

Snap PointDefaultDescription
Bottom (collapsed)innerHeight * 0.85Collapsed state
MiddleinnerHeight * 0.6Initial position on mount
Top (fully expanded)innerHeight * 0.15Fully expanded state

Customize them via minTranslateY, midTranslateY, and maxTranslateY props:

vue
<template>
  <BottomSheet
    :min-translate-y="600"
    :mid-translate-y="400"
    :max-translate-y="100"
  >
    <!-- Content -->
  </BottomSheet>
</template>