vue3-bootstrap-components

Twitter Bootstrap Components for Vue 3
8,606
Install
npm install vue3-bootstrap-components
Latest Version:2.1.4
Vue:3
License:ISC
Last Updated:Oct 18, 2026
Links: GitHub  ·  npm
Maintainer: novinvision

vue3-bootstrap-components

Twitter Bootstrap 5 components for Vue 3, built as thin wrapper components around Bootstrap's markup and JS plugins (Collapse, Modal, Tab, Dropdown, Offcanvas). Designed to work well with Laravel + Inertia.js projects (it automatically closes open Modals/Offcanvas/Dropdowns on Inertia page visits).

This package has been developed and maintained by Novin Vision (شرکت نوین ویژن), a team specialized in طراحی سایت and web design.

  • Package name: vue3-bootstrap-components
  • Vue version: 3.x
  • Bootstrap version: 5.3.x
  • Written in: TypeScript / Vue SFCs, bundled with Vite

Table of Contents

  1. Requirements
  2. Installation
  3. Bootstrap CSS & JS setup
  4. Using the components
  5. Component Reference
  6. Inertia.js integration
  7. TypeScript support
  8. Known issues / limitations
  9. License

Requirements

This package does not bundle Bootstrap or Vue — they are peer dependencies, so you control their versions and configuration yourself:

Package Required version
vue ^3.0.0
bootstrap ^5.3.3

Some components (Dropdown) rely on Bootstrap's own JS plugins, which in turn depend on Popper. If you plan to use Dropdown, also install @popperjs/core as documented in Bootstrap's own Dropdown docs.

Installation

Install the package together with its peer dependencies:

npm install vue3-bootstrap-components bootstrap
# or
yarn add vue3-bootstrap-components bootstrap
# or
pnpm add vue3-bootstrap-components bootstrap

If you need the Dropdown component:

npm install @popperjs/core

Bootstrap CSS & JS setup

This library only ships Vue components that render Bootstrap's HTML markup and, where needed, import Bootstrap's individual JS plugin modules directly (e.g. bootstrap/js/src/collapse, bootstrap/js/dist/modal). It does not ship or override Bootstrap's CSS.

You are responsible for importing Bootstrap's CSS (and, if you want, its Sass so you can use Bootstrap's own customization variables) in your app's entry point:

// main.js / app.js
import 'bootstrap/dist/css/bootstrap.min.css'
// or, if you want to customize Bootstrap via Sass variables (colors, spacing, etc.),
// follow Bootstrap's own theming docs and import your custom .scss instead:
// https://getbootstrap.com/docs/5.3/customize/sass/

Because each interactive component (Collapse, Modal, Tab, Dropdown, OffCanvas) imports the specific Bootstrap JS module it needs internally, you generally do not need to import the full bootstrap.bundle.js yourself. Any Bootstrap-level configuration (animation duration, backdrop behavior, data attributes, RTL support, dark mode, etc.) is entirely governed by Bootstrap itself — refer to Bootstrap's own documentation for those options, since this package does not add a configuration layer on top of them:

Using the components

You can import components individually wherever you need them (recommended, enables tree-shaking):

<script setup>
import { Alert, Modal, ModalHeader, ModalBody, ModalFooter, ModalButton } from 'vue3-bootstrap-components'
</script>

<template>
  <Alert type="success">Saved successfully.</Alert>
</template>

Or register everything globally (not recommended for large apps, but convenient for quick prototyping):

// main.js
import { createApp } from 'vue'
import * as BootstrapComponents from 'vue3-bootstrap-components'
import App from './App.vue'

const app = createApp(App)

Object.entries(BootstrapComponents).forEach(([name, component]) => {
  app.component(name, component)
})

app.mount('#app')

Component Reference

Each entry below reflects exactly what the component's source code does (props, events, slots, exposed methods) rather than a generic description, so you know precisely what to expect.

Alert

Wraps Bootstrap's .alert markup.

Props

Prop Type Default Notes
type String 'warning' Appended as alert-{type} (e.g. success, danger, info)
<Alert type="danger">Something went wrong.</Alert>

Card

A set of plain structural wrapper components — none of them take props.

Component Renders
Card <div class="card">
CardHeader <div class="card-header">
CardBody <div class="card-body">
CardFooter <div class="card-footer">
CardImgOverly <div class="card-img-overlay"> (note: named "Overly", not "Overlay", in the package's export)
<Card>
  <CardHeader>Title</CardHeader>
  <CardBody>Body content</CardBody>
  <CardFooter>Footer</CardFooter>
</Card>

Collapse

Wraps Bootstrap's Collapse plugin (bootstrap/js/src/collapse).

Collapse

Prop Type Default
name String 'collapseExample' — used to build the element's id as {name}Collapse
  • Emits: hide, hidden, show, shown (forwarded 1:1 from Bootstrap's hide.bs.collapse / hidden.bs.collapse / show.bs.collapse / shown.bs.collapse events)
  • Exposes (via template ref): show(), hide(), toggle()

CollapseButton

Prop Type Required
name String Yes — must match the target Collapse's name
<CollapseButton name="details">Toggle details</CollapseButton>
<Collapse name="details">
  Extra content that expands/collapses.
</Collapse>

You can also drive it programmatically:

<script setup>
import { ref } from 'vue'
const collapseRef = ref(null)
</script>

<Collapse name="details" ref="collapseRef" @shown="onShown">...</Collapse>
<button @click="collapseRef.show()">Open</button>

Accordion

Wraps Bootstrap's Accordion pattern (built on Collapse).

Component Props Notes
Accordion name (String, default 'accordionExample') Root .accordion wrapper. Emits hide/hidden/show/shown; exposes show()/hide()/toggle().
AccordionItem name (String, required) Wraps one accordion entry (.accordion-item).
AccordionButton name (String, optional) The clickable header; targets #accordion-collapse-{name}.
AccordionCollapse name (String, required) The collapsible panel content.
<Accordion name="faq">
  <AccordionItem name="q1">
    <AccordionButton>What is this?</AccordionButton>
    <AccordionCollapse name="q1">Answer goes here.</AccordionCollapse>
  </AccordionItem>
</Accordion>

⚠️ See Known issues — in the current published build, AccordionCollapse panels do not render their content, and Accordion's internal provide() call throws at runtime. Treat Accordion as not usable as-is until these are fixed upstream.

Dropdown

Wraps Bootstrap's Dropdown plugin (bootstrap/js/src/dropdown — requires Popper, see Requirements).

Component Notes
Dropdown .dropdown wrapper, no props.
DropdownToggle The trigger button (data-bs-toggle="dropdown"). Exposes show()/hide().
DropdownMenu .dropdown-menu wrapper, no props. Add your own <a class="dropdown-item"> links inside.
<Dropdown>
  <DropdownToggle>Options</DropdownToggle>
  <DropdownMenu>
    <a class="dropdown-item" href="#">Edit</a>
    <a class="dropdown-item" href="#">Delete</a>
  </DropdownMenu>
</Dropdown>

Modal

Wraps Bootstrap's Modal plugin (bootstrap/js/dist/modal).

Modal

Prop Type Default
name String required — used as the element id and as the target for ModalButton/ModalDismiss
effect String 'fade' — appended as a class alongside .modal
  • Emits: opened (on shown.bs.modal), closed (on hidden.bs.modal)
  • Exposes: show(), hide()

Structural sub-components (all no-prop wrappers unless noted): ModalDialog (.modal-dialog), ModalContent (.modal-content), ModalBody (.modal-body), ModalFooter (.modal-footer).

ModalHeader

Prop Type Default
showClose Boolean true — renders a built-in close button when true

ModalButton (opens a modal)

Prop Type Required
name String Yes — must match the Modal's name

ModalDismiss (closes the nearest modal) — see Known issues; not currently included in the published bundle.

<ModalButton name="confirmModal">Delete item</ModalButton>

<Modal name="confirmModal" @opened="onOpened">
  <ModalDialog>
    <ModalContent>
      <ModalHeader>Are you sure?</ModalHeader>
      <ModalBody>This action cannot be undone.</ModalBody>
      <ModalFooter>
        <button class="btn btn-danger">Confirm</button>
      </ModalFooter>
    </ModalContent>
  </ModalDialog>
</Modal>

OffCanvas

Wraps Bootstrap's Offcanvas plugin (bootstrap/js/dist/offcanvas).

OffCanvas

Prop Type Default
name String 'offcanvasExample' — used as the element id
  • Emits: hide, hidden, hidePrevented, show, shown
  • Exposes: show(), hide()

OffCanvasHeader / OffCanvasButton

Prop Type Default
name String 'offcanvas'

OffCanvasButton's name must match the target OffCanvas's name (it toggles #{name}). OffCanvasHeader builds its title id as {name}Label, so pass the same name there too — it does not automatically inherit it from the parent OffCanvas.

OffCanvasBody — structural wrapper (.offcanvas-body); its name prop exists but isn't currently used in the template.

<OffCanvasButton name="cartCanvas">Open cart</OffCanvasButton>

<OffCanvas name="cartCanvas">
  <OffCanvasHeader name="cartCanvas">Your Cart</OffCanvasHeader>
  <OffCanvasBody>
    ...cart items...
  </OffCanvasBody>
</OffCanvas>

Tab

Wraps Bootstrap's Tab plugin (bootstrap/js/src/tab).

Component Props Notes
Tab name (String, default 'tabExample') Root wrapper (.bs-tab-area).
TabButton name (String, required) The clickable tab trigger. Exposes show(). Emits hide/hidden/show/shown.
TabContent name (String, default 'myTab') Wraps all TabPanes (.tab-content).
TabPane name (String, default 'tab1'), animation An individual tab panel.
<Tab name="settingsTabs">
  <TabButton name="general">General</TabButton>
  <TabButton name="security">Security</TabButton>
</Tab>

<TabContent name="settingsTabs">
  <TabPane name="general">General settings...</TabPane>
  <TabPane name="security">Security settings...</TabPane>
</TabContent>

⚠️ See Known issues — Tab's internal provide() call has the same bug as Accordion's and will throw at runtime in the current published build.

Nav

Structural navigation wrappers.

Component Props Renders
Nav — <ul class="nav">
NavItem — <li class="nav-item">
NavLink active (Boolean, required), href (String, required) <a class="nav-link">
<Nav>
  <NavItem><NavLink :active="true" href="/">Home</NavLink></NavItem>
  <NavItem><NavLink :active="false" href="/about">About</NavLink></NavItem>
</Nav>

ListGroup

Component Renders
ListGroup <div class="list-group">
ListGroupItem <div class="list-group-item">

Form (InputGroup)

Component Renders
InputGroup <div class="input-group">
InputGroupText <div class="input-group-text">
<InputGroup>
  <InputGroupText>@</InputGroupText>
  <input type="text" class="form-control" placeholder="username">
</InputGroup>

The following components exist in the package's src/ folder but are not currently exported from the package's public entry point or included in the built dist/ bundle — importing them from vue3-bootstrap-components will not work today. They're listed here for completeness / awareness, in case you're building from source or these get published in a future version.

Button / ButtonGroup (not currently published)

Plain wrappers: Button → <button class="btn">, ButtonGroup → <div class="btn-group">.

Container (not currently published)

<div class="container"> wrapper, no props.

Pagination (not currently published)

A Laravel-pagination-shaped component (expects props like links, current_page, last_page, total, matching Laravel's default paginator JSON shape) that renders a Bootstrap .pagination nav. Emits a page event.

Placeholder (not currently published)

Wraps Bootstrap's placeholder loading UI. Props: type (String, default 'glow'), holderClass (String).

ProgressBar (not currently published)

Props: value (Number, required, default 0) — renders a striped/animated Bootstrap progress bar sized to value%.

Spinner (not currently published)

Props: type (String, default 'border'), size (String, default 'sm') — renders <i class="spinner-{type} spinner-{type}-{size}">.

SidebarOffCanvasButton (not currently published)

A custom sidebar-toggle button that expects an appSetOverly function to be provided by an ancestor and an element with id="appOverly" to exist in the DOM (for a click-outside-to-close overlay pattern). Props: name (String, required).


Inertia.js integration

All interactive components (Collapse, Accordion, Modal, Tab, Dropdown, OffCanvas) share a composable (useBootstrapInstance) that automatically listens for Inertia's inertia:start event. On a plain GET navigation, it calls .hide() on the active Bootstrap instance and removes any leftover .modal-backdrop elements — so open modals/offcanvas/collapses/tabs close cleanly instead of staying stuck open across an Inertia page visit. No extra setup is needed on your end for this to work; it's automatic as long as Inertia is present on the page and dispatches its normal events.

TypeScript support

Type declarations are published via dist/index.d.ts (referenced from package.json's types field), so autocompletion for component names works out of the box in TS/Vue projects. Note that the shipped .d.ts file lists a few components/props that don't match the actual current implementation 1:1 (e.g. it includes ModalDismiss, fullscreen/dialogClass props on Modal, and several TabNav*/Dropdown*Item names that don't exist in the current src/) — treat the component reference above, not the .d.ts file, as the source of truth for what's actually implemented today.

Known issues / limitations

These are things to be aware of if you run into unexpected behavior — several are real bugs in the current source, not intentional design:

  1. AccordionCollapse never renders its content. Its isActive computed property is hardcoded to always return false, and the panel's v-if="isActive" means the collapse body is never mounted regardless of open/closed state.
  2. Accordion throws at runtime. Its provide({ 'accordionName': props.value.name }) call accesses props.value.name, but props from defineProps() in <script setup> is not a ref — it should be props.name. This will throw as soon as the component mounts.
  3. Tab has the same bug as Accordion in its provide({ 'tabName': props.value.name }) call, and TabButton's computed tabBtnName/tabPaneName also read props.value.name instead of props.name.
  4. TabPane's aria-labelledby references an undefined variable (tabPaneNames, plural, a typo) instead of its own computed tabBtnName.
  5. TabPane's animation prop is typed Number but defaulted to the string 'fade' — a type/default mismatch.
  6. ModalDismiss is not included in the published dist/ bundle even though it's exported from src/Components/Modal/index.ts and listed in index.d.ts. Until this is fixed, use a plain Bootstrap close button instead: <button type="button" class="btn-close" data-bs-dismiss="modal"></button>.
  7. OffCanvasHeader/OffCanvasButton don't inherit name from a parent OffCanvas via provide/inject — unlike Modal, you must repeat the same name value on each of OffCanvas, OffCanvasHeader, and OffCanvasButton manually.
  8. Several components documented above under "not currently published" exist in src/ but aren't wired into the package's public exports or Vite build entry (src/index.ts) — they can't be imported from the published package as-is.

License

ISC (see package.json).

Related Packages

vue3-laravel-datatable

yajra datatables for laravel with novinvision/laravel-datatable package

0 0
inertia-bootstrap-forms

Create bootstrap forms with inertia and twitter bootstrap

16,229 0
laravel-precognition-vue-inertia

Laravel Precognition (Vue w/ Inertia).

342,609 175
momentum-layout

A Vue 3 compiler macro to define persistent layouts in Inertia.js apps

9,916 33
vue-inertia-composable

Inertia for Vue2 Composition API.

3,077 1

Version History

Version Released Vue License
2.1.4 ^3.0.0 ISC
2.1.3 ^3.0.0 ISC
2.1.2 ^3.0.0 ISC
2.1.1 ^3.0.0 ISC
2.0.21 ^3.0.0 ISC