Desirability:
I wonder if this is something I would use in my projects, because I think this will create a less than optimal user experience.
The regular pages probably show a nice header and title for context, while when navigating to child modules the user finds himself midway a page without header and context. I think this behaviour is not consistent and hence confusing. Besides, why using a modular page if you present the child pages as being separate content already?
I haven’t used modular pages in my themes (yet) and I think I would use them as follows:
- As the only page for a single page website:
The ‘onpage_menu: true’ would make it easy for users to jump to sections. It feels natural to the user. - For multi-page website:
I would switch off the ‘onpage_menu’ and show the page as a single regular page.
Solution using Quark theme:
Steps: (Skip to code below if not interested in process/explaination…)
- In ‘modular.md’ set ‘onpage_menu: false’
The modular page will now use ‘partials/navigation.html.twig’ to generate the menu containing ‘Home Page1 page2’. - Combine part of ‘modular.html.twig’ navigation with ‘partials/navigation.html.twig’ and use “page.tempate == ‘modular’” to discriminated between the page types.
- Construct the anchor urls for the modular children by combining the url of the modular page and the menu of the child module:
href="{{p.url}}/#{{ _self.pageLinkName(module.menu) }}"
- The menu will now show: ‘Home Module1 Module2 Page1 Page2’
- Unfortunately, the smooth scrolling and menu highlighting has disappeared from the modular page. This is because the required javascript is only run with ‘onpage_menu=true’.
- Fix:
- In ‘modular.html.twig’, remove the surrounding if-statements in
{% block javascripts %}
and{% block bottom %}
to add the required javascripts. - In ‘navigation.html.twig’ add class ‘navigation’ to the ‘<ul>’
- In ‘modular.html.twig’, remove the surrounding if-statements in
- But now, because of the enabled javascript, we cannot navigate to ‘Page1’ and ‘Page2’ anymore… Sigh…
- Fix:
- Add class ‘regular’ to all menu-items of regular pages in ‘navigation.html.twig’.
- Tell the javascript in ‘modular.html.twig’ to exclude the menuitems with class ‘regular’ by setting its filter to
filter: ':not(.external):not(.regular)'
It should work now…
Code:
‘modular.html.twig’:
{% extends 'partials/base.html.twig' %}
{% set show_onpage_menu = header.onpage_menu == true or header.onpage_menu is null %}
{% macro pageLinkName(text) %}{{ text|lower|replace({' ':'_'}) }}{% endmacro %}
{% block javascripts %}
{# {% if show_onpage_menu %} #} {# Comment out #}
{% do assets.add('theme://js/singlepagenav.min.js') %}
{# {% endif %} #} {# Comment out #}
{{ parent() }}
{% endblock %}
{% block bottom %}
{{ parent() }}
{# {% if show_onpage_menu %} #} {# Comment out #}
<script>
// singlePageNav initialization & configuration
$('ul.navigation').singlePageNav({
offset: $('#header').outerHeight(),
filter: ':not(.external):not(.regular)', // Add filter
updateHash: true,
currentClass: 'active'
});
</script>
{# {% endif %} #} {# Comment out #}
{% endblock %}
{% block header_navigation %}
{% if show_onpage_menu %}
<ul class="navigation">
{% for module in page.collection() %}
{% set current_module = (module.active or module.activeChild) ? 'active' : '' %}
<li><a class="{{ current_module }}" href="#{{ _self.pageLinkName(module.menu) }}">{{ module.menu }}</a></li>
{% endfor %}
{% for mitem in site.menu %}
<li>
<a {% if mitem.class %}class="{{ mitem.class }}"{% endif %} href="{{ mitem.url }}">
{% if mitem.icon %}<i class="fa fa-{{ mitem.icon }}"></i>{% endif %}
{{ mitem.text }}
</a>
</li>
{% endfor %}
</ul>
{% else %}
{{ parent() }}
{% endif %}
{% endblock %}
{% block hero %}
{% for module in page.collection() if module.template == 'modular/hero' %}
<div id="{{ _self.pageLinkName(module.menu) }}"></div>
{{ module.content }}
{% endfor %}
{% endblock %}
{% block body %}
{% for module in page.collection() if module.template != 'modular/hero' %}
<div id="{{ _self.pageLinkName(module.menu) }}"></div>
{{ module.content }}
{% endfor %}
{% endblock %}
‘/partials/navigation.html.twig’:
{% macro pageLinkName(text) %}{{ text|lower|replace({' ':'_'}) }}{% endmacro %}
{% macro nav_loop(page) %}
{% for p in page.children.visible %}
{% if p.template != 'modular' %} {# Add if #}
{% set active_page = (p.active or p.activeChild) ? 'active' : '' %}
{% if p.children.visible.count > 0 %}
<li>
<a href="{{ p.url }}" class="regular {{ active_page }}"> {# Add class 'regular' #}
{{ p.menu }}
</a>
<ul>
{{ _self.nav_loop(p) }}
</ul>
</li>
{% else %}
<li>
<a href="{{ p.url }}" class="regular {{ active_page }}"> {# Add class 'regular' #}
{{ p.menu }}
</a>
</li>
{% endif %}
{% else %} {# Add code to loop through modules #}
{% for module in p.collection() %}
{% set current_module = (module.active or module.activeChild) ? 'active' : '' %}
<li><a class="{{ current_module }}" href="{{p.url}}/#{{ _self.pageLinkName(module.menu) }}">{{ module.menu }}</a></li>
{% endfor %}
{% endif %}
{% endfor %}
{% endmacro %}
<ul {{ tree ? 'class="navigation tree"' : 'class="navigation"' }}> {# Add class 'navigation' required by javascript #}
{{ _self.nav_loop(pages) }}
</ul>