@mikestools/usebootstrap
v0.0.5
Published
Vue 3 composables for Bootstrap 5 components - lightweight wrappers with full TypeScript support
Maintainers
Readme
@mikestools/usebootstrap
Vue 3 composables for Bootstrap 5 components - lightweight wrappers with full TypeScript support
Features
- 🎯 Composable-first: Wrap Bootstrap's JavaScript in Vue 3 composables, not components
- 📦 Lightweight: Minimal wrapper around Bootstrap's native functionality (~19kB minified)
- 🔒 Type-safe: Full TypeScript support with complete type definitions
- 🧩 Modular: Import only what you need - tree-shakeable exports
- 🎨 Theme support: Dark/light mode management with localStorage persistence
- 🧪 Well-tested: 390+ tests with comprehensive coverage
- ⚡ SSR-safe: All composables handle server-side rendering gracefully
Installation
npm install @mikestools/usebootstrap bootstrap vueRequirements
- Vue 3.3.0 or higher
- Bootstrap 5.3.0 or higher
Quick Start
Import Bootstrap's CSS in your main entry file:
import 'bootstrap/dist/css/bootstrap.min.css'Then use the composables in your Vue components:
<script setup lang="ts">
import { ref } from 'vue'
import { useBootstrapModal } from '@mikestools/usebootstrap'
const modalRef = ref<HTMLElement | null>(null)
const { show, hide, toggle } = useBootstrapModal(modalRef, {
backdrop: 'static',
onShown: () => console.log('Modal opened'),
onHidden: () => console.log('Modal closed')
})
</script>
<template>
<button @click="show" class="btn btn-primary">Open Modal</button>
<div ref="modalRef" class="modal fade" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modal Title</h5>
<button @click="hide" type="button" class="btn-close"></button>
</div>
<div class="modal-body">
<p>Modal content goes here</p>
</div>
</div>
</div>
</div>
</template>Available Composables
UI Components
| Composable | Description | Key Methods |
|------------|-------------|-------------|
| useBootstrapModal | Modal dialogs | show(), hide(), toggle(), handleUpdate() |
| useBootstrapTooltip | Tooltips | show(), hide(), toggle(), enable(), disable(), setContent() |
| useBootstrapPopover | Popovers | show(), hide(), toggle(), enable(), disable(), setContent() |
| useBootstrapDropdown | Dropdown menus | show(), hide(), toggle(), update() |
| useBootstrapToast | Toast notifications | show(), hide(), isShown() |
| useBootstrapCollapse | Collapsible content | show(), hide(), toggle(), isOpen |
| useBootstrapOffcanvas | Offcanvas sidebars | show(), hide(), toggle() |
| useBootstrapTab | Tab navigation | show() |
| useBootstrapCarousel | Image carousels | next(), prev(), to(), cycle(), pause() |
| useBootstrapAlert | Dismissible alerts | close() |
| useBootstrapScrollSpy | Scroll tracking | refresh() |
| useBootstrapButton | Toggle buttons | toggle() |
Utilities
| Composable | Description | Key Methods |
|------------|-------------|-------------|
| useBootstrapTheme | Theme management | toggleTheme(), setTheme(), theme, isDark |
API Examples
Modal with Events
import { ref } from 'vue'
import { useBootstrapModal } from '@mikestools/usebootstrap'
const modalRef = ref<HTMLElement | null>(null)
const { show, hide, toggle, handleUpdate } = useBootstrapModal(modalRef, {
backdrop: 'static',
keyboard: false,
onShow: (event) => console.log('Opening...'),
onShown: (event) => console.log('Fully open'),
onHide: (event) => {
// Can prevent close with event.preventDefault()
},
onHidden: (event) => console.log('Closed')
})Tooltip
import { ref } from 'vue'
import { useBootstrapTooltip } from '@mikestools/usebootstrap'
const buttonRef = ref<HTMLElement | null>(null)
const { show, hide, enable, disable, setContent } = useBootstrapTooltip(buttonRef, {
title: 'Tooltip text',
placement: 'top',
trigger: 'hover focus',
delay: { show: 100, hide: 200 }
})
// Update content dynamically
setContent({ '.tooltip-inner': 'New content!' })Toast
import { ref } from 'vue'
import { useBootstrapToast } from '@mikestools/usebootstrap'
const toastRef = ref<HTMLElement | null>(null)
const { show, hide, isShown } = useBootstrapToast(toastRef, {
autohide: true,
delay: 5000,
onShown: () => console.log('Toast visible'),
onHidden: () => console.log('Toast hidden')
})Theme
import { useBootstrapTheme } from '@mikestools/usebootstrap'
const { theme, isDark, toggleTheme, setTheme } = useBootstrapTheme()
// theme.value is 'light' or 'dark'
// isDark.value is true when in dark mode
// Automatically persists to localStorage
// Applies data-bs-theme attribute to <html>
setTheme('dark') // Set specific theme
toggleTheme() // Switch between light/darkCollapse with Accordion
import { ref } from 'vue'
import { useBootstrapCollapse } from '@mikestools/usebootstrap'
const collapseRef = ref<HTMLElement | null>(null)
const { show, hide, toggle, isOpen } = useBootstrapCollapse(collapseRef, {
parent: '#accordionId', // Makes it part of an accordion
onShow: () => console.log('Expanding'),
onHidden: () => console.log('Collapsed')
})Carousel with Indicators
import { ref } from 'vue'
import { useBootstrapCarousel } from '@mikestools/usebootstrap'
const carouselRef = ref<HTMLElement | null>(null)
const indicatorsRef = ref<HTMLElement | null>(null)
const { next, prev, to, cycle, pause, indicators } = useBootstrapCarousel(carouselRef, {
interval: 5000,
wrap: true,
indicators: {
carouselId: 'myCarousel',
slideCount: 3,
containerRef: indicatorsRef // Auto-applies data-bs-* attributes
},
onSlide: (e) => console.log('Sliding...'),
onSlid: (e) => console.log('Slid complete')
})Common Patterns
Event Callbacks
All composables support event callbacks that mirror Bootstrap's native events:
useBootstrapModal(ref, {
onShow: (event) => {}, // Before showing (cancellable)
onShown: (event) => {}, // After fully shown
onHide: (event) => {}, // Before hiding (cancellable)
onHidden: (event) => {} // After fully hidden
})Programmatic Control
All composables return methods for programmatic control:
const { show, hide, toggle, getInstance, cleanup } = useBootstrapModal(ref)
// Access the native Bootstrap instance if needed
const instance = getInstance()Conditional Rendering
When using v-if with composables, ensure the composable is created fresh when the element is re-added:
<template>
<div v-if="showModal" :key="modalKey">
<div ref="modalRef" class="modal">...</div>
</div>
</template>
<script setup>
// Increment modalKey when re-showing to reinitialize
</script>Development
# Install dependencies
npm install
# Run tests
npm test
# Type check
npm run check
# Build library
npm run build
# Dev server for showcase
npm run devPhilosophy
This library follows these principles:
- Composables over components: Bootstrap components work with standard HTML markup. We wrap the JavaScript behavior, not the markup.
- Minimal abstraction: Thin wrappers that expose Bootstrap's native API with Vue reactivity.
- Type safety: Full TypeScript support with strict typing - no
anytypes. - No extra dependencies: Only peer dependencies on Vue and Bootstrap.
- SSR-safe: All composables check for browser environment before initialization.
License
MIT
Contributing
Contributions are welcome! Please ensure:
- All tests pass (
npm test) - Type checking passes (
npm run check) - Code follows existing patterns and conventions
- New features include tests and documentation
