App
The BApp component is the new recommended way to configure bootstrap-vue-next. It replaces the plugin-based approach and provides better defaults management, orchestrator integration, and improved type safety.
Overview
BApp serves as the root component for your bootstrap-vue-next application, providing:
- Global defaults management - Set and merge component defaults throughout your application
- Automatic orchestrator integration - Built-in Modal, Toast, and Popover orchestrators
- Plugin compatibility - Works alongside existing plugins for backward compatibility (see the Backward Compatibility section for details)
- Type safety - Full TypeScript support with proper type inference
- RTL support - Built-in right-to-left language support
- Flexible teleporting - Control where orchestrators are rendered in the DOM
Basic Usage
<template>
<BApp>
<!-- Your application content -->
<router-view />
</BApp>
</template>
<script setup lang="ts">
import {BApp} from 'bootstrap-vue-next'
</script>Configuration
Setting Component Defaults
You can provide global defaults for any bootstrap-vue-next component:
<template>
<BApp :defaults="appDefaults">
<!-- Your application content -->
<router-view />
</BApp>
</template>
<script setup lang="ts">
import {BApp} from 'bootstrap-vue-next'
const appDefaults = {
BButton: {
variant: 'info' as const,
size: 'lg' as const,
},
BModal: {
centered: true,
noCloseOnBackdrop: true,
},
BToast: {
variant: 'success' as const,
solid: true,
},
}
</script>Merging Defaults
By default, the defaults prop completely replaces any existing defaults. Use mergeDefaults to merge with parent or plugin defaults:
<template>
<BApp
:defaults="appDefaults"
:merge-defaults="true"
>
<!-- Your application content -->
</BApp>
</template>
<script setup lang="ts">
import {BApp} from 'bootstrap-vue-next'
const appDefaults = {
BButton: {
variant: 'primary' as const, // This will merge with existing BButton defaults
},
}
</script>Custom Merge Function
For advanced use cases, you can provide a custom merge function:
<template>
<BApp
:defaults="appDefaults"
:merge-defaults="customMerge"
>
<!-- Your application content -->
</BApp>
</template>
<script setup lang="ts">
import {BApp} from 'bootstrap-vue-next'
const appDefaults = {
BButton: {
variant: 'primary' as const,
},
}
const customMerge = (
oldDefaults: Record<string, unknown>,
newDefaults: Record<string, unknown>
): Record<string, unknown> => ({...oldDefaults, ...newDefaults})
</script>Orchestrator Configuration
Teleporting Orchestrators
By default, orchestrators render inline with your BApp component. Use teleportTo to render them elsewhere in the DOM:
<template>
<BApp teleport-to="body">
<!-- Orchestrators will render in document.body -->
<router-view />
</BApp>
</template>Disabling Orchestrators
If you don't need the built-in orchestrators (for example, if you're using custom implementations), you can disable them:
<template>
<BApp :no-orchestrator="true">
<!-- No automatic orchestrators will be created -->
<router-view />
</BApp>
</template>Toast Configuration
Control how toasts are added to the list:
<template>
<BApp :append-toast="true">
<!-- New toasts will be appended to the end of the list -->
<router-view />
</BApp>
</template>RTL Support
BApp provides built-in right-to-left language support:
<template>
<BApp :rtl="rtlConfig">
<!-- Your application content -->
<router-view />
</BApp>
</template>
<script setup lang="ts">
import {BApp} from 'bootstrap-vue-next'
const rtlConfig = {
rtlInitial: true,
localeInitial: 'ar',
}
</script>Migration from Plugins
Before (Plugin-based)
// main.ts
import {createApp} from 'vue'
import {createBootstrap} from 'bootstrap-vue-next'
import App from './App.vue'
const app = createApp(App)
app.use(
createBootstrap({
components: {
BButton: {
variant: 'primary',
},
},
})
)
app.mount('#app')After (BApp-based)
<!-- App.vue -->
<template>
<BApp :defaults="{BButton: {variant: 'primary'}}">
<router-view />
</BApp>
</template>
<script setup lang="ts">
import {BApp} from 'bootstrap-vue-next'
</script>// main.ts
import {createApp} from 'vue'
import App from './App.vue'
// Add the necessary CSS
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue-next/dist/bootstrap-vue-next.css'
const app = createApp(App)
app.mount('#app')Working with Composables
When using BApp, the following composables work without requiring plugin installation:
useToast()- Create and manage toasts programmaticallyuseModal()- Create and manage modals programmaticallyusePopover()- Create and manage popovers programmatically
Vue Provide/Inject Limitation
Due to how Vue's provide/inject system works, composables like useToast(), useModal(), and usePopover() cannot be called in the same component that declares <BApp>. They rely on values provided by BApp, and Vue's inject only works in child components — not in the component that calls provide itself.
To use these composables, place <BApp> at least one component level above where the composables are called:
<template>
<BApp>
<AppComposablesChild />
</BApp>
</template>
<script setup lang="ts">
import { BApp } from 'bootstrap-vue-next'
import AppComposablesChild from './AppComposablesChild.vue'
</script><template>
<BButton @click="showToast">Show Toast</BButton>
<BButton @click="showModal">Show Modal</BButton>
</template>
<script setup lang="ts">
import { BButton, useModal, useToast } from 'bootstrap-vue-next'
const toast = useToast()
const modal = useModal()
const showToast = () => {
toast
.create({
title: 'Hello',
body: 'This is a toast message!',
})
.show()
}
const showModal = () => {
modal
.create({
title: 'Confirm Action',
body: 'Are you sure you want to continue?',
})
.show()
}
</script>Backward Compatibility
The BApp component is fully backward compatible with existing plugin-based setups. You can gradually migrate by:
- Adding
BAppto your root component - Moving defaults from plugin configuration to
BAppprops - Removing plugin installations once migration is complete
Migration Note
Plugins will show deprecation warnings but continue to work until removed in a future version, with the following exceptions:
modalControllerPlugintoastControllerPluginpopoverControllerPlugin
These plugins have been removed as of version 0.40.0. Please replace references to these with a reference to orchestratorPlugin.
Testing Components
When testing components that use composables like useToast(), useModal(), or usePopover(), you need to install the createBootstrap plugin so that the required context is provided. Without it, these composables will throw an error because they rely on Vue's provide/inject system.
Per-Test Plugin Setup
Install the plugin directly on the component you are testing:
// MyComponent.spec.ts
import {mount} from '@vue/test-utils'
import {createBootstrap} from 'bootstrap-vue-next'
import MyComponent from './MyComponent.vue'
test('mounts a component that uses useToast()', () => {
const wrapper = mount(MyComponent, {
global: {
plugins: [createBootstrap()],
},
})
expect(wrapper.text()).toContain('Show Toast')
})Global Test Setup
To avoid repeating the plugin setup in every test, configure it globally in your test setup file:
// vitest.setup.ts (or in your test config)
import {config} from '@vue/test-utils'
import {createBootstrap} from 'bootstrap-vue-next'
config.global.plugins = [createBootstrap()]Then reference this file in your Vitest configuration:
// vitest.config.ts
import {defineConfig} from 'vitest/config'
export default defineConfig({
test: {
setupFiles: ['./vitest.setup.ts'],
},
})TIP
The createBootstrap() plugin registers the orchestrator, registry, and RTL services — the same services BApp provides. This is sufficient for mounting and rendering components that call useToast() and similar composables. You do not need to wrap your component in BApp during tests.
Mocking Composables
If you want to avoid executing real toast logic entirely, you can also mock the composable in your test:
import {vi} from 'vitest'
vi.mock('bootstrap-vue-next', async () => {
const actual = await vi.importActual('bootstrap-vue-next')
return {
...actual,
useToast: () => ({
create: vi.fn(),
show: vi.fn(),
}),
}
})Internal Features
The BApp component automatically provides several internal services:
- Show/Hide Registry - Global registry for show/hide components
- Modal Manager - Stack management for multiple modals
- Breadcrumb Service - Global breadcrumb item management
- RTL Service - Right-to-left text direction support
Notes
- Only one
BAppcomponent should be active at a time per application - The component uses Vue's provide/inject system for dependency injection
- All orchestrators are automatically teleported when
teleportTois specified - The component inherits all attributes and passes them to the default slot
Component Reference
<BApp>
| Prop | Type | Default | Description |
|---|---|---|---|
| append-toast | boolean | false | Appends toast notifications to the end of the list instead of beginning. |
| defaults | Partial<BvnComponentProps> | Ref<Partial<BvnComponentProps>> | undefined | Default props for components. Can be a plain object or a ref. |
| merge-defaults | boolean | ((oldDefaults: Partial<BvnComponentProps>, newDefaults: Partial<BvnComponentProps>) => Partial<BvnComponentProps>) | true | If `true`, performs a shallow merge with existing defaults (if `false`, replaces them). If a function, it receives (oldDefaults, newDefaults) and must return the merged defaults. |
| no-orchestrator | boolean | false | If `true`, disables the orchestration layer (Modal/Toast/Popover controllers) inside BApp. |
| rtl | boolean | { rtlInitial?: boolean; localeInitial?: string } | false | If `true`, enables RTL. If an object, you can set initial RTL state and locale. If `false`, disables RTL. |
| teleport-to | string | Element | null | undefined | null | Specifies the element to which the toasts, modals and popovers should be teleported. This is useful if you want to move them to a different part of the DOM. |
| Name | Scope | Description |
|---|---|---|
| default | App content. Attributes on <BApp> are forwarded to this slot. |