Skip to content
This repository was archived by the owner on Mar 27, 2025. It is now read-only.

Commit fdcb8cd

Browse files
authored
docs: update modal docs for useModal & useModalController (bootstrap-vue-next#1433)
docs: update modal docs for useModal & useModalController fix: some scoped slots fixes
1 parent 0de3e78 commit fdcb8cd

File tree

8 files changed

+206
-83
lines changed

8 files changed

+206
-83
lines changed

apps/docs/src/components/TableOfContentsNav.vue

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,12 @@ const componentsList: {name: string}[] = [
122122
{name: 'Toast'},
123123
]
124124
125-
const composablesList: {name: string}[] = [{name: 'useBreadcrumb'}, {name: 'useColorMode'}]
125+
const composablesList: {name: string}[] = [
126+
{name: 'useBreadcrumb'},
127+
{name: 'useColorMode'},
128+
{name: 'useModal'},
129+
{name: 'useModalController'},
130+
]
126131
127132
const directivesList: {name: string}[] = [
128133
{name: 'BColorMode'},

apps/docs/src/docs/components/modal.md

Lines changed: 4 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ const nestedModal3 = ref(false)
121121
</template>
122122
</HighlightCard>
123123

124+
## Programmatically Control
125+
126+
To programmatically control your modals with global state, refer to our documentation at [useModal](/docs/composables/useModal) and [useModalController](/docs/composables/useModalController)
127+
124128
<ComponentReference :data="data" />
125129

126130
<script setup lang="ts">
@@ -138,75 +142,3 @@ const nestedModal1 = ref(false)
138142
const nestedModal2 = ref(false)
139143
const nestedModal3 = ref(false)
140144
</script>
141-
142-
## Programmatically Control
143-
144-
### `useModal()`
145-
146-
You can use `useModal()` to get the closest modal in child component and hide it.
147-
148-
```vue
149-
<BModal>
150-
<MyComponent>
151-
</BModal>
152-
```
153-
154-
```vue
155-
<template>
156-
<BButton @click="hideSelf">Done</BButton>
157-
</template>
158-
159-
<script setup lang="ts">
160-
import {useModal} from 'bootstrap-vue-next'
161-
162-
const {hide} = useModal()
163-
164-
function hideSelf() {
165-
hide()
166-
}
167-
</script>
168-
```
169-
170-
You can also provide an id to get particular modal and show/hide it. Currently, we don't support using CSS selector to
171-
find modal since the `BModal` in lazy mode may not render at page initial.
172-
173-
```vue
174-
<template>
175-
<BModal v-if="someConditions" id="my-modal"> ...</BModal>
176-
</template>
177-
178-
<script setup lang="ts">
179-
import {useModal} from 'bootstrap-vue-next'
180-
import {ref} from 'vue'
181-
182-
const someConditions = ref(...)
183-
184-
const {show, hide, modal} = useModal('my-modal')
185-
186-
// modal variable is BModal component ref
187-
if (modal.value) {
188-
show()
189-
hide()
190-
191-
modal.value.show()
192-
modal.value.hide()
193-
} else {
194-
// If modal component not exists, you can still call show/hide methods but nothing happened
195-
show()
196-
hide()
197-
}
198-
</script>
199-
```
200-
201-
### `useModalController()`
202-
203-
`modalController` can hide modals everywhere.
204-
205-
```ts
206-
import {useModalController} from 'bootstrap-vue-next'
207-
208-
const modalController = useModalController()
209-
210-
modalController.hide() // Hide last modal
211-
modalController.hideAll() // Hide all modals at once
212-
```
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# useModal
2+
3+
<ClientOnly>
4+
<Teleport to=".bd-toc">
5+
6+
[[toc]]
7+
8+
</Teleport>
9+
</ClientOnly>
10+
11+
<div class="lead mb-5">
12+
13+
You can use `useModal` to get the closest modal in **child component** and hide it. It can also be supplied a target id to show or hide a specific modal
14+
15+
</div>
16+
17+
<HighlightCard>
18+
<template #html>
19+
20+
```vue
21+
<BModal>
22+
<MyComponent />
23+
</BModal>
24+
25+
<template>
26+
<BButton @click="hide">Done</BButton>
27+
</template>
28+
29+
<script setup lang="ts">
30+
const {hide} = useModal()
31+
</script>
32+
```
33+
34+
</template>
35+
</HighlightCard>
36+
37+
You can also provide an id to get particular modal and show/hide it. Currently, we do not support using CSS selector to
38+
find modal since the `BModal` in lazy mode may not render at page initial. If the modal component does not exist and you attempt to call any of the exposed methods the methods will safely ignore
39+
40+
<HighlightCard>
41+
<BButton @click="show">Click me</BButton>
42+
<BModal v-if="someConditions" v-model="programmaticModal" id="my-modal">
43+
<BButton @click="hide">Hide me</BButton>
44+
</BModal>
45+
<template #html>
46+
47+
```vue
48+
<template>
49+
<BButton @click="show">Click me</BButton>
50+
<BModal v-if="someConditions" v-model="programmaticModal" id="my-modal">
51+
<BButton @click="hide">Hide me</BButton>
52+
</BModal>
53+
</template>
54+
55+
<script setup lang="ts">
56+
const someConditions = ref(false)
57+
const programmaticModal = ref(false)
58+
59+
onMounted(() => {
60+
someConditions.value = true
61+
})
62+
63+
const {show, hide, modal} = useModal('my-modal')
64+
</script>
65+
```
66+
67+
</template>
68+
</HighlightCard>
69+
70+
<script setup lang="ts">
71+
import {BButton, BModal, useModal} from 'bootstrap-vue-next'
72+
import HighlightCard from '../../components/HighlightCard.vue'
73+
import {ref, onMounted} from 'vue'
74+
75+
const someConditions = ref(false)
76+
const programmaticModal = ref(false)
77+
78+
onMounted(() => {
79+
someConditions.value = true
80+
})
81+
82+
const {show, hide} = useModal('my-modal')
83+
</script>
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# useModalController
2+
3+
<ClientOnly>
4+
<Teleport to=".bd-toc">
5+
6+
[[toc]]
7+
8+
</Teleport>
9+
</ClientOnly>
10+
11+
<div class="lead mb-5">
12+
13+
`useModalController` can hide modals everywhere in the app
14+
15+
</div>
16+
17+
<HighlightCard>
18+
<BButton @click="nestedModal1 = !nestedModal1">Open First Modal</BButton>
19+
<BModal v-model="nestedModal1" title="First Modal" ok-only>
20+
<p class="my-2">First Modal</p>
21+
<BButtonGroup>
22+
<BButton @click="nestedModal2 = !nestedModal2">Open Second Modal</BButton>
23+
<BButton @click="hide">Hide Last</BButton>
24+
<BButton @click="hideAll">Hide All</BButton>
25+
</BButtonGroup>
26+
</BModal>
27+
<BModal v-model="nestedModal2" title="Second Modal" ok-only>
28+
<p class="my-2">Second Modal</p>
29+
<BButtonGroup>
30+
<BButton @click="nestedModal3 = !nestedModal3" size="sm">Open Third Modal</BButton>
31+
<BButton @click="hide">Hide Last</BButton>
32+
<BButton @click="hideAll">Hide All</BButton>
33+
</BButtonGroup>
34+
</BModal>
35+
<BModal v-model="nestedModal3" title="Third Modal" ok-only>
36+
<p class="my-1">Third Modal</p>
37+
<BButtonGroup>
38+
<BButton @click="hide">Hide Last</BButton>
39+
<BButton @click="hideAll">Hide All</BButton>
40+
</BButtonGroup>
41+
</BModal>
42+
<template #html>
43+
44+
```vue
45+
<template>
46+
<BButton @click="nestedModal1 = !nestedModal1">Open First Modal</BButton>
47+
<BModal v-model="nestedModal1" title="First Modal" ok-only>
48+
<p class="my-2">First Modal</p>
49+
<BButtonGroup>
50+
<BButton @click="nestedModal2 = !nestedModal2">Open Second Modal</BButton>
51+
<BButton @click="hide">Hide Last</BButton>
52+
<BButton @click="hideAll">Hide All</BButton>
53+
</BButtonGroup>
54+
</BModal>
55+
<BModal v-model="nestedModal2" title="Second Modal" ok-only>
56+
<p class="my-2">Second Modal</p>
57+
<BButtonGroup>
58+
<BButton @click="nestedModal3 = !nestedModal3" size="sm">Open Third Modal</BButton>
59+
<BButton @click="hide">Hide Last</BButton>
60+
<BButton @click="hideAll">Hide All</BButton>
61+
</BButtonGroup>
62+
</BModal>
63+
<BModal v-model="nestedModal3" title="Third Modal" ok-only>
64+
<p class="my-1">Third Modal</p>
65+
<BButtonGroup>
66+
<BButton @click="hide">Hide Last</BButton>
67+
<BButton @click="hideAll">Hide All</BButton>
68+
</BButtonGroup>
69+
</BModal>
70+
</template>
71+
72+
<script setup lang="ts">
73+
const nestedModal1 = ref(false)
74+
const nestedModal2 = ref(false)
75+
const nestedModal3 = ref(false)
76+
77+
const {hide, hideAll} = useModalController()
78+
</script>
79+
```
80+
81+
</template>
82+
</HighlightCard>
83+
84+
<script setup lang="ts">
85+
import {BButton, BModal, useModalController, BButtonGroup} from 'bootstrap-vue-next'
86+
import HighlightCard from '../../components/HighlightCard.vue'
87+
import {ref} from 'vue'
88+
89+
const nestedModal1 = ref(false)
90+
const nestedModal2 = ref(false)
91+
const nestedModal3 = ref(false)
92+
93+
const {hide, hideAll} = useModalController()
94+
</script>

packages/bootstrap-vue-next/src/components/BDropdown/BDropdown.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
:role="role"
5454
@click="onClickInside"
5555
>
56-
<slot />
56+
<slot :hide="close" :show="open" />
5757
</ul>
5858
</div>
5959
</template>
@@ -129,7 +129,7 @@ const emit = defineEmits<{
129129
130130
defineSlots<{
131131
// eslint-disable-next-line @typescript-eslint/no-explicit-any
132-
'default'?: (props: Record<string, never>) => any
132+
'default'?: (props: {hide: () => void; show: () => void}) => any
133133
// eslint-disable-next-line @typescript-eslint/no-explicit-any
134134
'button-content'?: (props: Record<string, never>) => any
135135
// eslint-disable-next-line @typescript-eslint/no-explicit-any

packages/bootstrap-vue-next/src/components/BNav/BNavItemDropdown.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
<slot name="toggle-text" />
2222
</template>
2323
<template #default>
24-
<slot />
24+
<slot :hide="close" :show="open" />
2525
</template>
2626
</BDropdown>
2727
</li>
@@ -84,7 +84,7 @@ const emit = defineEmits<{
8484
8585
defineSlots<{
8686
// eslint-disable-next-line @typescript-eslint/no-explicit-any
87-
'default'?: (props: Record<string, never>) => any
87+
'default'?: (props: {hide: () => void; show: () => void}) => any
8888
// eslint-disable-next-line @typescript-eslint/no-explicit-any
8989
'toggle-text'?: (props: Record<string, never>) => any
9090
// eslint-disable-next-line @typescript-eslint/no-explicit-any

packages/bootstrap-vue-next/src/components/BNavbar/BNavbarToggle.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ const emit = defineEmits<{
3838
}>()
3939
4040
defineSlots<{
41+
// TODO this scoped slot is {expanded: boolean}
4142
// eslint-disable-next-line @typescript-eslint/no-explicit-any
4243
default?: (props: Record<string, never>) => any
4344
}>()

packages/bootstrap-vue-next/src/components/BOffcanvas/BOffcanvas.vue

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
<div v-if="!noHeaderBoolean" class="offcanvas-header" :class="headerClass">
3030
<slot name="header" :visible="modelValueBoolean" :placement="placement" :hide="hide">
3131
<h5 :id="`${computedId}-offcanvas-label`" class="offcanvas-title">
32-
<slot name="title">
32+
<slot name="title" :visible="modelValueBoolean" :placement="placement" :hide="hide">
3333
{{ title }}
3434
</slot>
3535
</h5>
@@ -47,7 +47,7 @@
4747
</slot>
4848
</div>
4949
<div class="offcanvas-body" :class="bodyClass">
50-
<slot />
50+
<slot :visible="modelValueBoolean" :placement="placement" :hide="hide" />
5151
</div>
5252
<div v-if="hasFooterSlot" :class="footerClass">
5353
<slot name="footer" :visible="modelValueBoolean" :placement="placement" :hide="hide" />
@@ -158,10 +158,18 @@ const emit = defineEmits<{
158158
}>()
159159
160160
defineSlots<{
161-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
162-
'default'?: (props: Record<string, never>) => any
163-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
164-
'title'?: (props: Record<string, never>) => any
161+
'default'?: (props: {
162+
visible: boolean
163+
placement: 'top' | 'bottom' | 'start' | 'end'
164+
hide: (trigger?: string) => void
165+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
166+
}) => any
167+
'title'?: (props: {
168+
visible: boolean
169+
placement: 'top' | 'bottom' | 'start' | 'end'
170+
hide: (trigger?: string) => void
171+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
172+
}) => any
165173
'header'?: (props: {
166174
visible: boolean
167175
placement: 'top' | 'bottom' | 'start' | 'end'

0 commit comments

Comments
 (0)