Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions docs/userGuide/syntax/navBars.mbdf
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,26 @@ Name | Description
</navbar>

</span>

****Page and site navigation menus****
Both [site navigation]({{ baseUrl }}/userGuide/usingComponents.html#site-navigation-menus) and [page navigation]({{ baseUrl }}/userGuide/usingComponents.html#page-navigation-menus) menus will be hidden on smaller screens.
To make these accessible on smaller screens, you can use the `<site-nav-button />` and `<page-nav-button />` components in the `lower-navbar` slot. By default, if the `lower-navbar` slot is not specified, both the site and
page navigation buttons will automatically be added if they exist.

```html{.no-line-numbers}
<navbar>
<!-- Any normal navbar items -->
<a slot="brand" href="/" title="Home" class="navbar-brand">MarkBind</a>
<li><a href="/userGuide/usingComponents.html#navbars" class="nav-link">Highlighted Link</a></li>
<!-- Use slot to wrap the buttons in the lower navbar -->
<div slot="lower-navbar" class="nav-menu-container">
<site-nav-button />
<page-nav-button />
</div>
</navbar>
```

Component | Description
--- | ---
`page-nav-button` | Pulls any element with an identifier, `id=page-nav` into the menu. If no such element exists, it pulls any [page navigation menu]({{ baseUrl }}/userGuide/usingComponents.html#page-navigation-menus) used in the layout.
`site-nav-button` | Pulls any element with an identifier, `id=site-nav` into the menu. If no such element exists, it pulls the first [site navigation menu]({{ baseUrl }}/userGuide/usingComponents.html#site-navigation-menus) used in the layout.
2 changes: 2 additions & 0 deletions docs/userGuide/syntax/pageNavigationMenus.mbdf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

3. **Position the page navigation menu** within your layout using the `{% raw %}{{ pageNav }}{% endraw %}` variable.

4. **(Optional) To make pageNav accessible on smaller screens, you can use the `<page-nav-button />` component in the [navbar]({{baseUrl}}/userGuide/usingComponents.html#navbars).**

<div id="short" class="indented">

{{ icon_example }}
Expand Down
1 change: 1 addition & 0 deletions docs/userGuide/syntax/siteNavigationMenus.mbdf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
Steps to add a siteNav:
1. Format your siteNav as an unordered Markdown list
2. Include it under a `<site-nav>` element.
3. (Optional) To make siteNav accessible on smaller screens, you can use the `<site-nav-button />` component in the [navbar]({{baseUrl}}/userGuide/usingComponents.html#navbars).

<div id="short">

Expand Down
34 changes: 34 additions & 0 deletions packages/core-web/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,40 @@ function detectAndApplyFixedHeaderStyles() {
margin-top: calc(-${headerHeight}px - ${bufferHeight}rem);
height: calc(${headerHeight}px + ${bufferHeight}rem);
}`);
insertCss(`.nav-menu-open { max-height: calc(100% - ${headerHeight}px); }`);

const addResizeHeaderListener = () => {
const resizeObserver = new ResizeObserver(() => {
const newHeaderHeight = headerSelector.height();
const sheets = document.styleSheets;
for (let i = 0; i < sheets.length; i += 1) {
const rules = sheets[i].cssRules;
// eslint-disable-next-line lodash/prefer-get
if (rules && rules[0] && rules[0].selectorText) {
switch (rules[0].selectorText) {
case '.fixed-header-padding':
sheets[i].deleteRule(0);
sheets[i].insertRule(`.fixed-header-padding { padding-top: ${newHeaderHeight}px !important }`);
break;
case 'span.anchor':
rules[0].style.top = `calc(-${newHeaderHeight}px - ${bufferHeight}rem)`;
break;
case 'span.card-container::before':
rules[0].style.marginTop = `calc(-${newHeaderHeight}px - ${bufferHeight}rem)`;
rules[0].style.height = `calc(${newHeaderHeight}px + ${bufferHeight}rem)`;
break;
case '.nav-menu-open':
rules[0].style.maxHeight = `calc(100% - ${newHeaderHeight}px + 50px)`;
break;
default:
break;
}
}
}
});
resizeObserver.observe(headerSelector[0]);
};
addResizeHeaderListener();
}

function updateSearchData(vm) {
Expand Down
2 changes: 1 addition & 1 deletion packages/core-web/src/styles/markbind.css
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ code.hljs.inline {
header[fixed] {
position: fixed;
width: 100%;
z-index: 1000;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more minor styling issue: (navbar example in ug)

Untitled

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Fixed :)

z-index: 1001;
}

/* #app is treated as the main container */
Expand Down
81 changes: 57 additions & 24 deletions packages/vue-components/src/Navbar.vue
Original file line number Diff line number Diff line change
@@ -1,31 +1,39 @@
<template>
<nav ref="navbar" :class="['navbar', 'navbar-expand-md', themeOptions, addClass, fixedOptions]">
<div class="container-fluid">
<div class="navbar-brand">
<slot name="brand"></slot>
</div>
<button
v-if="!slots.collapse"
class="navbar-toggler"
type="button"
aria-expanded="false"
aria-label="Toggle navigation"
@click="toggleCollapse"
>
<span class="navbar-toggler-icon"></span>
<slot name="collapse"></slot>
</button>
<div>
<nav ref="navbar" :class="['navbar', 'navbar-expand-md', themeOptions, addClass, fixedOptions]">
<div class="container-fluid">
<div class="navbar-brand">
<slot name="brand"></slot>
</div>
<button
v-if="!slots.collapse"
class="navbar-toggler"
type="button"
aria-expanded="false"
aria-label="Toggle navigation"
@click="toggleCollapse"
>
<span class="navbar-toggler-icon"></span>
<slot name="collapse"></slot>
</button>

<div :class="['navbar-collapse',{collapse:collapsed}]">
<ul class="navbar-nav mr-auto mt-2 mt-lg-0">
<slot></slot>
</ul>
<ul v-if="slots.right" class="navbar-nav navbar-right">
<slot name="right"></slot>
</ul>
<div :class="['navbar-collapse',{collapse:collapsed}]">
<ul class="navbar-nav mr-auto mt-2 mt-lg-0">
<slot></slot>
</ul>
<ul v-if="slots.right" class="navbar-nav navbar-right">
<slot name="right"></slot>
</ul>
</div>
</div>
</nav>
<div ref="lowerNavbar" v-show="isLowerNavbarShowing" class="lower-navbar-container">
<slot name="lower-navbar">
<site-nav-button />
<page-nav-button />
</slot>
</div>
</nav>
</div>
</template>

<script>
Expand All @@ -52,11 +60,17 @@ export default {
default: 'sibling-or-child',
},
},
provide() {
return {
toggleLowerNavbar: this.toggleLowerNavbar,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about just a prop? since they're in the same compilation scope

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm just to clarify, if this is passed to <page/site-nav-button> component through a prop, since lower-navbar is a slot, if a user defines new content in the layout file for this slot without specifying the prop, for example,

<div slot="lower-navbar">
  <site-nav-button />
</div>

then it won't be passed down to the component in this case?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

};
},
data() {
return {
id: 'bs-example-navbar-collapse-1',
collapsed: true,
styles: {},
isLowerNavbarShowing: false,
};
},
computed: {
Expand Down Expand Up @@ -198,6 +212,13 @@ export default {
}
}
},
toggleLowerNavbar() {
if (this.$refs.lowerNavbar.childElementCount > 0) {
this.isLowerNavbarShowing = true;
} else {
this.isLowerNavbarShowing = false;
}
},
},
created() {
this._navbar = true;
Expand Down Expand Up @@ -228,10 +249,14 @@ export default {

// highlight current nav link
this.highlightLink(window.location.href);

this.toggleLowerNavbar();
$(window).on('resize', this.toggleLowerNavbar);
},
beforeDestroy() {
$('.dropdown', this.$el).off('click').offBlur();
if (this.slots.collapse) $('[data-toggle="collapse"]', this.$el).off('click');
$(window).off('resize', this.toggleLowerNavbar);
},
};
</script>
Expand All @@ -255,4 +280,12 @@ export default {
color: #fff !important;
background: #007bff;
}

.lower-navbar-container {
background-color: #fff;
border-bottom: 1px solid #c1c1c1;
height: 50px;
width: 100%;
position: relative;
}
</style>
109 changes: 109 additions & 0 deletions packages/vue-components/src/Overlay.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<template>
<div>
<span

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: pull the icon upward using scoped slots, so the component specific styles can be moved up there

not sure if it would end up more verbose though 😐

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shifted this up. Doesn't look too verbose :)

:class="[{ 'nav-menu-close-icon': show }]"
@click="toggleNavMenu"
>
<slot name="navMenuIcon"></slot>
</span>
<div ref="navMenuContainer" :class="['nav-menu', { 'nav-menu-open': show }]">
<retriever
v-if="hasIdentifier"
:src="src"
:fragment="fragment"
@src-loaded="navMenuLoaded"
/>
<div v-else ref="navigationMenu"></div>
</div>
</div>
</template>

<script>
import retriever from './Retriever.vue';
import $ from './utils/NodeList';
import { publish, subscribe } from './utils/pubsub';

export default {
components: {
retriever,
},
props: {
type: {
type: String,
default: null,
},
src: {
type: String,
default: null,
},
fragment: {
type: String,
default: null,
},
hasIdentifier: {
type: Boolean,
default: false,
},
getNavMenuContent: {
type: Function,
default: () => {},
},
},
inject: ['toggleLowerNavbar'],
data() {
return {
show: false,
};
},
methods: {
toggleNavMenu() {
if (!this.show) { publish('closeOverlay'); }
this.show = !this.show;
},
navMenuLoaded() {
this.toggleLowerNavbar();
$(this.$refs.navMenuContainer).find('a').on('click', () => {
this.toggleNavMenu();
});
},
},
mounted() {
const navMenu = this.$refs.navigationMenu;
const buildNav = (navMenuItems) => {
if (!navMenuItems) { return; }
for (let i = 0; i < navMenuItems.childNodes.length; i += 1) {
navMenu.appendChild(navMenuItems.childNodes[i].cloneNode(true));
}
this.navMenuLoaded();
};

if (!this.hasIdentifier) {
buildNav(this.getNavMenuContent());
}

subscribe('closeOverlay', () => { this.show = false; });
},
};
</script>

<style scoped>
.nav-menu {
display: none;
padding: 50px 10px 20px;
position: fixed;
overflow-y: auto;
z-index: -1;
}

.nav-menu-close-icon > span::before {
content: "\e014" !important;
}

.nav-menu-open {
display: block !important;
width: 100% !important;
background: #fff;
height: 100%;
clear: both;
}
</style>
Loading