diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 8d6e563f3..ffe60bdf2 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,4 +1,4 @@
{
- "packages/bootstrap-vue-next": "0.29.2",
- "packages/nuxt": "0.29.2"
+ "packages/bootstrap-vue-next": "0.29.3",
+ "packages/nuxt": "0.29.3"
}
diff --git a/apps/docs/.vitepress/theme/Layout.vue b/apps/docs/.vitepress/theme/Layout.vue
index f01b921c4..cb85cdad1 100644
--- a/apps/docs/.vitepress/theme/Layout.vue
+++ b/apps/docs/.vitepress/theme/Layout.vue
@@ -138,7 +138,7 @@
header-class="pb-0 d-flex offcanvas-hidden-width"
body-class="py-2"
>
-
+
@@ -193,6 +193,7 @@ import {VPNavBarSearch} from 'vitepress/theme'
import {appInfoKey} from './keys'
import {useMediaQuery} from '@vueuse/core'
import PageContents from '../../src/components/PageContents.vue'
+import {type ContentsItem, type HeaderItem} from '../../src/types'
// https://vitepress.dev/reference/runtime-api#usedata
const {page} = useData()
@@ -201,9 +202,11 @@ const route = useRoute()
const content = useTemplateRef>('_content')
const target = useTemplateRef>('_target')
-useScrollspy(content, target, {
- contentQuery: ':scope > div > [id], #component-reference',
+const {current: activeId, list: items} = useScrollspy(content, target, {
+ contentQuery: ':scope > div > [id], #component-reference, .component-reference h3',
targetQuery: ':scope [href]',
+ rootMargin: '0px 0px -25%',
+ manual: true,
})
const globalData = inject(appInfoKey, {
@@ -295,6 +298,49 @@ const set = (newValue: keyof typeof map) => {
colorMode.value = newValue
}
+const headers = computed(() =>
+ items.value.map((item) => {
+ const rawTag = item.el?.tagName?.toUpperCase() ?? ''
+ const isHeading = /^H[1-6]$/.test(rawTag)
+ const tag = isHeading ? rawTag : 'DIV'
+ const level = tag.startsWith('H') ? parseInt(tag.replace('H', '')) : 3
+ return {
+ ...item,
+ tag,
+ level,
+ } as HeaderItem
+ })
+)
+
+const contents = computed(() => {
+ const root: ContentsItem[] = []
+ const stack: ContentsItem[] = []
+
+ headers.value.forEach((header) => {
+ const item = {...header, children: [] as ContentsItem[]} as ContentsItem
+
+ while (stack.length && stack[stack.length - 1].level >= item.level) {
+ stack.pop()
+ }
+
+ if (stack.length === 0) {
+ root.push(item)
+ } else {
+ stack[stack.length - 1].children.push(item)
+ }
+
+ stack.push(item)
+ })
+
+ if (root.length !== 1) {
+ // Something isn't right if we have no root items or more than one root item
+ // eslint-disable-next-line no-console
+ console.warn('Unexpected header structure:', headers, 'Root items:', root)
+ }
+
+ return root.length > 0 ? root[0] : undefined
+})
+
watch(
() => route.path,
() => {
diff --git a/apps/docs/src/components/ComponentReference.vue b/apps/docs/src/components/ComponentReference.vue
index 27c7df633..2a919f8bc 100644
--- a/apps/docs/src/components/ComponentReference.vue
+++ b/apps/docs/src/components/ComponentReference.vue
@@ -10,7 +10,9 @@
- {{ `<` + component.component + `>` }}
+
+ {{ `<` + component.component + `>` }}
+
-
- Component Reference
+