npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@coderoycc/bottom-sheet-wrappers

v2.0.0

Published

A flexible Vue 3 bottom sheet component with touch gesture support

Readme

📱 Bottom Sheet Wrappers — v2

A flexible and powerful Vue 3 bottom sheet library designed specifically for mobile devices with native-like touch gesture support and two distinct display modes.

Version 2 introduces a simplified API with new component names (BsDynamic, BsSimple) and no plugin registration required — just import and use.

npm version License: MIT

📱 Mobile-First Design: Built from the ground up for mobile devices with smooth 60fps animations and native-like touch interactions. Full Documentation & Demo →

✨ Features

  • 🎯 Two Distinct Components: BsDynamic (resizable with snap points) and BsSimple (static height or auto-fit).
  • 👆 Native Touch Gestures: Smooth swipe, drag, and tap interactions optimized for mobile.
  • 🎨 Customizable Backdrop: Optional backdrop with configurable behavior.
  • 📱 Mobile-First & Responsive: Optimized for mobile devices, works great on desktop too.
  • 🔧 TypeScript Support: Full TypeScript definitions included.
  • 🪶 Lightweight: Minimal dependencies (only Vue 3).
  • Accessible: ARIA support and keyboard interaction ready.
  • Performant: 60fps animations with GPU acceleration.

📦 Installation

npm install @coderoycc/bottom-sheet-wrappers

Or with yarn:

yarn add @coderoycc/bottom-sheet-wrappers

Or with pnpm:

pnpm add @coderoycc/bottom-sheet-wrappers

🚀 Quick Start

1. Import the styles

Import the styles once in your entry file (main.ts) or at the top of the component where you need them. This must be done before using any component:

// main.ts
import "@coderoycc/bottom-sheet-wrappers/style.css";

2. Import and use the components directly

No plugin registration needed — simply import the component you want and use it:

<script setup>
import { ref } from "vue";
import { BsDynamic } from "@coderoycc/bottom-sheet-wrappers";

const isOpen = ref(false);
</script>

<template>
  <button @click="isOpen = true">Open Bottom Sheet</button>

  <BsDynamic v-model="isOpen" title="My Bottom Sheet">
    <p>Your content here</p>
  </BsDynamic>
</template>

💡 You can also import the styles directly in the component's <style> block or in a dedicated CSS entry file.

🎭 Display Modes

The library consists of two main components acting as distinct modes to perfectly match your use case:

1. Dynamic Bottom Sheet (BsDynamic)

This mode allows the user to resize the sheet by dragging up or down between three size states: collapsed, half, and full. It supports a mini-player pattern out of the box.

BsDynamic demo

<script setup>
import { ref } from 'vue';
import { BsDynamic } from '@coderoycc/bottom-sheet-wrappers';

const isDynamicOpen = ref(false);
</script>

<template>
  <BsDynamic
    v-model="isDynamicOpen"
    initial-size="half"
    half="45dvh"
    full="95dvh"
    @size-change="onSizeChange"
  >
    <p>Swipe up or down to resize content</p>

    <!-- Optional collapsed slot for a mini-player/bar view -->
    <template #collapsed-content>
      <div>Now Playing...</div>
    </template>
  </BsDynamic>
</template>

Behavior:

  • ✅ Swipe up/down to resize through specific snap points.
  • ✅ Handles its own internal sizes accurately mapping to your UI expectations (half, full).
  • ✅ Provides a seamless collapsed state for a "mini view" via #collapsed-content slot.
  • ✅ Smart expansion boundaries that block accidental full expansion when limits are hit.

2. Simple Bottom Sheet (BsSimple)

This mode maintains a fixed or auto-adjusted height (based on the content inside it) and cannot be resized, though the user can swipe down to close it. Perfectly covers both fixed-size and auto-fit use cases.

BsSimple demo

<script setup>
import { ref } from 'vue';
import { BsSimple } from '@coderoycc/bottom-sheet-wrappers';

const isSimpleOpen = ref(false);
</script>

<template>
  <!-- Provide a specific height -->
  <BsSimple v-model="isSimpleOpen" title="Fixed Sheet" height="50dvh">
    <p>Fixed at 50% screen height</p>
  </BsSimple>

  <!-- Or let it auto-adjust (auto-fit behavior) by omitting height -->
  <BsSimple v-model="isSimpleOpen" title="Auto Sheet">
    <p>My height adjusts automatically to fit this content!</p>
  </BsSimple>
</template>

Behavior:

  • ✅ Fixed height or Auto-Height fallback depending on the provided height prop.
  • ✅ Swipe down on the handle to close directly.
  • ✅ No internal resizing gestures enabled, maintaining focused view boundaries.
  • ✅ Optional persistent mode to prevent closing via gestures.

📚 API Reference

BsDynamic

Props

| Prop | Type | Default | Description | | ---- | ---- | ------- | ----------- | | modelValue | boolean | false | Controls visibility (v-model). | | title | string | '' | Header title string. | | initialSize | 'collapsed' \| 'half' \| 'full' | 'half' | Starting size when the sheet opens. | | half | string | '45dvh' | Height when mapped to the half size. | | full | string | '95dvh' | Height when mapped to the full size. | | hideCloseButton | boolean | false | Hide the close icon button in the top right. | | showBackdrop | boolean | false | Render a dark visual backdrop behind the sheet. | | hideDragHandle | boolean | false | Hide the drag handle indicator. | | zIndex | number | 1 | Added over a base 9000 context z-index layer. |

Events

| Event | Payload | Description | | ----- | ------- | ----------- | | update:modelValue | boolean | Emitted when visibility changes. | | opened | — | Emitted when sheet is fully open and mounted. | | closed | — | Emitted when fully unloaded/closed. | | close | — | Triggered right before closing starts. | | size-change | 'collapsed' \| 'half' \| 'full' | Emitted when the sheet switches to a new size mode. |

Methods & Slots

Methods (via Template Ref): open(), close(), animateToSize(size)
Slots: #default, #header, #collapsed-content


BsSimple

Props

| Prop | Type | Default | Description | | ---- | ---- | ------- | ----------- | | modelValue | boolean | false | Controls visibility (v-model). | | title | string | '' | Header title string. | | height | string \| number | undefined | Forced static height. Omitting this makes it auto-fit the content inside. | | showBackdrop | boolean | false | Render a dark visual backdrop. | | hideCloseButton | boolean | false | Hide the close icon button. | | hideDragHandle | boolean | false | Hide the drag handle indicator. | | closeOnBackdrop | boolean | false | Close the sheet when clicking the backdrop. | | persistent | boolean | false | Prevent closing via gestures and hides the close button. | | zIndex | number | 0 | Added over a base 9000 context z-index layer. |

Events

| Event | Payload | Description | | ----- | ------- | ----------- | | update:modelValue | boolean | Emitted when visibility changes. | | opened | — | Emitted when sheet is fully created & mounted in active state. | | closed | — | Emitted when fully unloaded/closed. | | before-close | — | Emitted when the closing sequence begins. |

Methods & Slots

Slots: #default, #header

🎨 Styling

You can override the default styles using CSS variables or by targeting the component classes directly.

/* Custom backdrop opacity */
.bsw-bottom-sheet-backdrop--visible {
  background: rgba(0, 0, 0, 0.75) !important;
}

/* Custom handle color */
.bsw-bottom-sheet-handle {
  background: #007bff !important;
}

Dark Mode Support

The components naturally embrace CSS scopes for overrides, simply wrap components or nest logic within your specific theme identifiers:

<BsDynamic v-model="isOpen" class="my-dark-theme">
  <p>Content</p>
</BsDynamic>

<style>
.my-dark-theme .bsw-bottom-sheet-panel {
  background: #1a1a1a;
  color: #ffffff;
}
</style>

🏗️ Architecture

The library is built with clean code principles using Vue 3's Composition API structure:

  • BsDynamic & BsSimple logic separated for specialized behavior.
  • Use of internal composables (e.g., useDynamicGestures, useSimpleGestures, useAutoHeight) to decouple gesture tracking and size orchestration.

📖 Documentation

Full interactive documentation and live examples are available at:
https://coderoycc.github.io/bsw-demo/

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

MIT License - see LICENSE file for details

👤 Author

coderoycc


Made with ❤️ by coderoycc