-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: add quick links to docs pages for small screens and add section…
… table of contents indexes (#4145)
- Loading branch information
1 parent
d6d00ca
commit 22268aa
Showing
19 changed files
with
366 additions
and
82 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<template> | ||
<nav aria-label="Breadcrumbs"> | ||
<b-breadcrumb :items="items" class="d-inline-flex bg-transparent px-2 py-1 my-0"> | ||
</b-breadcrumb> | ||
</nav> | ||
</template> | ||
|
||
<style scoped> | ||
.breadcrumb /deep/ .breadcrumb-item { | ||
font-size: 0.875rem; | ||
line-height: 1.5; | ||
margin-bottom: 0; | ||
} | ||
</style> | ||
|
||
<script> | ||
import { nav } from '~/content' | ||
const navLookup = nav.reduce((obj, section) => { | ||
obj[section.base.replace('/', '')] = section | ||
return obj | ||
}, {}) | ||
export default { | ||
name: 'BDVBreadcrumbs', | ||
computed: { | ||
items() { | ||
const items = [{ text: 'Home', to: '/' }, { text: 'Docs', to: '/docs' }] | ||
const section = this.$route.name.split('-')[1] || '' | ||
const slug = this.$route.params.slug || '' | ||
if (section) { | ||
const sectionMeta = navLookup[section] || {} | ||
items.push({ | ||
text: sectionMeta.title || section, | ||
to: ['/docs', section].join('/') | ||
}) | ||
if (slug) { | ||
const pagesMeta = sectionMeta.pages || {} | ||
items.push({ | ||
text: (pagesMeta[slug] || {}).title || slug, | ||
to: ['/docs', section, slug].join('/') | ||
}) | ||
} | ||
} | ||
return items | ||
} | ||
} | ||
} | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
<template> | ||
<nav | ||
:class="['bd-quick-links', 'mb-3', { 'd-none': !quickLinksVisible || !hasContent }]" | ||
:aria-hidden="hasContent ? null : 'true'" | ||
> | ||
<header v-if="hasContent"> | ||
<b-button | ||
v-b-toggle.bd-quick-links-collapse | ||
class="font-weight-bold" | ||
variant="outline-secondary" | ||
size="sm" | ||
block | ||
> | ||
<span v-if="quickLinksExpanded">Hide</span> | ||
<span v-else>Show</span> | ||
page table of contents | ||
</b-button> | ||
</header> | ||
<b-collapse v-if="hasContent" id="bd-quick-links-collapse" v-model="quickLinksExpanded" tag="ul"> | ||
<li v-for="h2 in toc.toc" :key="h2.href"> | ||
<b-link :href="h2.href" @click="scrollIntoView($event, h2.href)"> | ||
<span v-html="h2.label"></span> | ||
</b-link> | ||
<ul v-if="h2.toc && h2.toc.length > 0" :key="`sub-${h2.href}`"> | ||
<li v-for="h3 in h2.toc" :key="h3.href"> | ||
<b-link :href="h3.href" @click="scrollIntoView($event, h3.href)"> | ||
<span v-html="h3.label"></span> | ||
</b-link> | ||
</li> | ||
</ul> | ||
</li> | ||
</b-collapse> | ||
</nav> | ||
</template> | ||
|
||
<style scoped lang="scss"> | ||
#bd-quick-links-collapse { | ||
list-style-type: square; | ||
border-left: 5px solid #ccc; | ||
padding-left: 2.5rem; | ||
margin-top: 1rem; | ||
ul { | ||
list-style-type: circle; | ||
padding-left: 1.25rem; | ||
margin-bottom: 0.25rem; | ||
} | ||
} | ||
</style> | ||
|
||
<script> | ||
import { offsetTop, scrollTo } from '~/utils' | ||
export default { | ||
name: 'BDVQuickToc', | ||
data() { | ||
return { | ||
toc: {}, | ||
offset: 0, | ||
quickLinksExpanded: false, | ||
quickLinksVisible: false | ||
} | ||
}, | ||
computed: { | ||
hasContent() { | ||
return !!this.toc.toc | ||
} | ||
}, | ||
created() { | ||
this.$root.$on('docs-set-toc', toc => { | ||
// Reset visible/expanded states | ||
this.quickLinksVisible = false | ||
this.quickLinksExpanded = false | ||
// Update the TOC content | ||
this.toc = toc | ||
// Re-position the quick links | ||
this.positionQuickLinks() | ||
}) | ||
}, | ||
mounted() { | ||
// Set the correct offset based on the header height | ||
const $header = document.body.querySelector('header.navbar') | ||
if ($header) { | ||
this.offset = $header.offsetHeight + 6 | ||
} | ||
// Re-position the quick links | ||
this.positionQuickLinks() | ||
}, | ||
methods: { | ||
scrollIntoView(evt, href) { | ||
evt.preventDefault() | ||
evt.stopPropagation() | ||
// We use an attribute `querySelector()` rather than `getElementByID()`, | ||
// as some auto-generated ID's are invalid or not unique | ||
const id = (href || '').replace(/#/g, '') | ||
const $el = document.body.querySelector(`[id="${id}"]`) | ||
if ($el) { | ||
// Get the document scrolling element | ||
const scroller = document.scrollingElement || document.documentElement || document.body | ||
// Scroll heading into view (minus offset to account for nav top height | ||
scrollTo(scroller, offsetTop($el) - 70, 100, () => { | ||
// Set a tab index so we can focus header for a11y support | ||
$el.tabIndex = -1 | ||
// Focus the heading | ||
$el.focus() | ||
}) | ||
} | ||
}, | ||
positionQuickLinks() { | ||
if (typeof document === 'undefined') { | ||
return | ||
} | ||
// Move the quick links to the correct position, if possible | ||
const $body = document.body | ||
const $referenceNode = $body.querySelector('.bd-lead') || $body.querySelector('h1') | ||
if ($referenceNode) { | ||
// IE 11 doesn't support the `node.after()` method, and appears | ||
// that the polyfill doesn't polyfill this method | ||
$referenceNode.insertAdjacentElement('afterend', this.$el) | ||
} | ||
// Make the quick links visible | ||
// We hide them initially to make the position change not that distracting | ||
this.quickLinksVisible = true | ||
} | ||
} | ||
} | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
<template> | ||
<Main> | ||
<Section> | ||
<h1 :id="id" tabindex="-1"> | ||
<span class="bd-content-title"> | ||
{{ groupTitle }} <span class="small text-muted">- table of contents</span> | ||
</span> | ||
</h1> | ||
<p v-if="groupDescription" class="bd-lead">{{ groupDescription }}</p> | ||
<b-list-group tag="nav" :aria-label="`${groupTitle} section navigation`" class="mb-5"> | ||
<b-list-group-item | ||
v-for="page in pages" | ||
:key="page.slug" | ||
:to="`/docs/${slug}/${page.slug}`" | ||
active-class="" | ||
> | ||
<strong class="text-primary">{{ page.title }}</strong> — | ||
<span class="text-muted">{{ page.description }}</span> | ||
</b-list-group-item> | ||
</b-list-group> | ||
</Section> | ||
</Main> | ||
</template> | ||
|
||
<style scoped> | ||
.list-group .list-group-item:hover strong { | ||
text-decoration: underline; | ||
} | ||
</style> | ||
|
||
<script> | ||
import Main from '~/components/main' | ||
import Section from '~/components/section' | ||
import { nav } from '~/content' | ||
// Normalize nav into a lookup object | ||
const groups = nav.reduce((obj, g) => { | ||
const groupSlug = g.base.replace(/\/$/, '') | ||
obj[groupSlug] = g | ||
return obj | ||
}, {}) | ||
export default { | ||
layout: 'docs', | ||
components: { | ||
Main, | ||
Section | ||
}, | ||
computed: { | ||
slug() { | ||
return this.$route.path.replace(/^\//, '').split('/')[1] || '' | ||
}, | ||
id() { | ||
return `bd-section-toc-${this.slug}` | ||
}, | ||
group() { | ||
return groups[this.slug] || {} | ||
}, | ||
groupDescription() { | ||
return this.group.description | ||
}, | ||
groupTitle() { | ||
const title = this.group.title || '' | ||
return title === 'Components' | ||
? 'Component groups' | ||
: title === 'Misc' | ||
? 'Miscellaneous' | ||
: title || '' | ||
}, | ||
pages() { | ||
return this.group.pages || [] | ||
} | ||
} | ||
} | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.