Skip to content

Commit 7edaf0e

Browse files
committed
Updates to CSS and dropdowns are now includes. Please see README
1 parent 5d1a5a1 commit 7edaf0e

7 files changed

+162
-60
lines changed

README.md

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ A Drupal 8/9 compatible module to apply the Unity Design System header/footer.
77
* The site's "Main navigation" menu will be inserted into the header.
88
* This module was built for a site using a sub-theme of Bootstrap Barrio. ymmv
99

10-
Important: This can only handle one level of menu items at the moment. Dropdowns are NOT working.
10+
Important: Per Bootstrap and Web Standards 2.0 sites are only allowed 2 levels of links in the menu.
1111

1212
## Configuration
1313

@@ -17,6 +17,15 @@ Important: This can only handle one level of menu items at the moment. Dropdowns
1717
* Layout > Region > Top Header, Header, and Footer fifth regions should all have "no wrapper" checked and no class set (the default is row).
1818
* A custom page.html.twig file is included for comparison. Any template in the theme will override this module's templates.
1919

20+
## Menu configuration
21+
22+
Because of the 2-level limit and to get the desired layout, the module requires menu elements to be set up a certain way.
23+
* Menu items that are links can be regular links.
24+
* Menu items that are dropdown triggers must have `route:<button>` set as the link.
25+
* Menu items that are headers within dropdowns must have `<nolink>` set as the link.
26+
27+
Note: At this time, the modules supports only 1- or 2-column dropdowns.
28+
2029
## Block placement
2130

2231
ASU Global Menu block into the Top Header region.

asu_header.info.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: 'ASU Header and Footer'
22
type: module
33
description: 'Global header and footer for ASU web standards'
44
core_version_requirement: ^8.0 || ^9.0
5-
package: 'ASU'
5+
package: 'ASU Library'
66
dependencies:
77
- block
88
- twig_tweak

asu_header.module

+15-10
Original file line numberDiff line numberDiff line change
@@ -124,27 +124,32 @@ function asu_header_preprocess_block__system_menu_block__main(&$variables) {
124124

125125
/**
126126
* Implements hook_preprocess_*()
127-
* Pass is_front to menu template
127+
* TODO: Count the number of nolink headings in the menu
128+
* and pass that as a variable to the menu so we can alter
129+
* the HTML for >2 columns.
128130
*/
129131
function asu_header_preprocess_menu(&$variables) {
132+
/* Pass is_front variable to menu templates */
130133
try {
131134
$variables['is_front'] = \Drupal::service('path.matcher')->isFrontPage();
132135
}
133136
catch (Exception $e) {
134137
$variables['is_front'] = FALSE;
135138
}
136-
}
139+
$variables['#cache']['contexts'][] = 'url.path.is_front';
137140

138-
/**
139-
* Implements hook_preprocess_menu()
140-
* Set the username and not cache it
141-
*/
142-
function asu_header_preprocess_menu__asu_global(&$variables) {
143-
$currentAccount = \Drupal::currentUser();
144-
$variables['username'] = $currentAccount->getAccountName();
145-
$variables['#cache']['contexts'][] = 'user';
141+
/* Set is_active on item if the link matches current path */
142+
$current_path = \Drupal::request()->getRequestUri();
143+
foreach ($variables['items'] as &$item) {
144+
if ($item['in_active_trail']) {
145+
if ($item['url']->toString() == $current_path) {
146+
$item['is_active'] = TRUE;
147+
}
148+
}
149+
}
146150
}
147151

152+
148153
/**
149154
* Implements hook_preprocess_*()
150155
* Pass the module path as a variable

css/asu-header-footer.css

+56-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@
3939
width: 1px;
4040
}
4141

42+
/* Not sure what this style in global_header.scss is supposed
43+
to accomplish but all it does is make long pages not scroll
44+
and shoots all the content to the left.
45+
Overriding until/unless it's needed.
46+
*/
47+
body.dropdown-pinned {
48+
overflow: auto;
49+
position: initial;
50+
}
51+
4252
/*--------------------------------------------------------------
4353
# Global Header
4454
@@ -325,6 +335,34 @@
325335
/* Magic number, same thing */
326336
}
327337

338+
#header-main .svg-inline--fa.fa-w-14 {
339+
width: .875em;
340+
}
341+
342+
#header-main .svg-inline--fa {
343+
font-size: inherit;
344+
height: 1em;
345+
vertical-align: -.125em;
346+
}
347+
348+
#header-main .svg-inline--fa.fa-stack-2x {
349+
height: 2em;
350+
width: 2.5em;
351+
}
352+
353+
#header-main .svg-inline--fa.fa-stack-1x {
354+
height: 1em;
355+
width: 1.25em;
356+
}
357+
358+
#header-main .svg-inline--fa.fa-stack-1x,
359+
#header-main .svg-inline--fa.fa-stack-2x {
360+
bottom: 0;
361+
margin: auto;
362+
right: 0;
363+
top: 0;
364+
}
365+
328366
#header-main .navbar-toggler.collapsed .fa-stack {
329367
display: none;
330368
}
@@ -596,6 +634,23 @@
596634
margin: 0.5rem 0;
597635
}
598636

637+
#header-main .btn.nav-link {
638+
font-weight: normal;
639+
border-radius: 0;
640+
border: none;
641+
width: 100%;
642+
text-align: left;
643+
}
644+
645+
#header-main .btn.nav-link:hover,
646+
#header-main .btn.nav-link:focus {
647+
transform: none;
648+
}
649+
650+
#header-main .dropdown-toggle:after {
651+
border: none;
652+
}
653+
599654
#header-main .dropdown-menu div[class^='col-'] {
600655
margin-bottom: 3rem;
601656
padding: 0 2rem;
@@ -1264,4 +1319,4 @@ Footer - Table of Contents
12641319
#footer-colophon .nav-link:nth-child(n + 4) {
12651320
justify-self: end;
12661321
}
1267-
}
1322+
}

templates/block--system-menu-block--main.html.twig

+4-4
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,11 @@
5252
</a>
5353

5454
<button class="navbar-toggler collapsed" type="button" data-toggle="collapse" data-target="#menubar" aria-controls="menubar" aria-expanded="false" aria-label="Toggle navigation">
55-
<span title="Open mobile menu" class="fa fa-bars"></span>
55+
<svg title="Open mobile menu" class="svg-inline--fa fa-bars fa-w-14" aria-labelledby="svg-inline--fa-title-xjdaJbVF67zt" data-prefix="fa" data-icon="bars" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" data-fa-i2svg=""><title id="svg-inline--fa-title-xjdaJbVF67zt">Open mobile menu</title><path fill="currentColor" d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"></path></svg><!-- <span title="Open mobile menu" class="fa fa-bars"></span> -->
5656
<span title="Close mobile menu" class="fa-stack">
57-
<i class="fa fa-circle fa-stack-2x"></i>
58-
<i class="fa fa-times fa-stack-1x"></i>
59-
</span>
57+
<svg class="svg-inline--fa fa-circle fa-w-16 fa-stack-2x" aria-hidden="true" focusable="false" data-prefix="fa" data-icon="circle" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" data-fa-i2svg=""><path fill="currentColor" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"></path></svg><!-- <i class="fa fa-circle fa-stack-2x"></i> -->
58+
<svg class="svg-inline--fa fa-times fa-w-11 fa-stack-1x" aria-hidden="true" focusable="false" data-prefix="fa" data-icon="times" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 352 512" data-fa-i2svg=""><path fill="currentColor" d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"></path></svg><!-- <i class="fa fa-times fa-stack-1x"></i> -->
59+
</span>
6060
</button>
6161

6262
<div class="navbar-container">

templates/menu--asu-global.html.twig

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
{% import _self as menus %}
2222
{# TODO: Uncomment first/preferred name when that field is available. For now use account name #}
2323
{#{% set firstname = drupal_field('field_first_name', 'user', user.id, {label: 'hidden'}) %}#}
24-
{% set firstname = username %}
24+
{% set firstname = user.account.name %}
2525
{#
2626
We call a macro which calls itself to render the full tree.
2727
@see http://twig.sensiolabs.org/doc/tags/macro.html

templates/menu--main--mainnavigation.html.twig

+75-42
Original file line numberDiff line numberDiff line change
@@ -18,66 +18,99 @@
1818
* - in_active_trail: TRUE if the link is in the active trail.
1919
*/
2020
#}
21+
{#
22+
Bootstrap-based menus won't display menu levels greater than 2
23+
so to get multi-columns working with ASU theme, we make certain
24+
assumptions how the menu is built.
25+
Top-level menu items with submenus should have the route:<button>
26+
as their link. Column headings should use the <nolink> route.
27+
This menu assumes that each heading is its own column.
28+
Larger menus or ones with multiple headings in a column
29+
will need to adjust this or use another method.
30+
See: https://www.phase2technology.com/blog/creating-mega-menu-layout-builder
31+
#}
32+
{% set attributes = attributes.addClass('menu') %}
2133
{% import _self as menus %}
2234

2335
{#
2436
We call a macro which calls itself to render the full tree.
2537
@see http://twig.sensiolabs.org/doc/tags/macro.html
2638
#}
27-
{{ menus.menu_links(items, is_front, attributes, 0) }}
39+
{{ menus.menu_links(items, is_front, dropdown, attributes, 0) }}
2840

29-
{% macro menu_links(items, is_front, attributes, menu_level) %}
41+
{% macro menu_links(items, is_front, dropdown, attributes, menu_level) %}
42+
{% set primary_nav_level = 'menu--level-' ~ (menu_level + 1) %}
3043
{% import _self as menus %}
3144
{% if items %}
32-
{% if is_expanded %}
33-
<div class="nav-item dropdown">
34-
{% endif %}
45+
{% set attributes = attributes.removeClass(primary_nav_level) %}
3546
{% for item in items %}
36-
{%
37-
set classes = [
38-
menu_level ? 'dropdown-item' : 'nav-item',
39-
item.is_expanded ? 'menu-item--expanded',
40-
item.is_collapsed ? 'menu-item--collapsed',
41-
item.in_active_trail ? 'active',
42-
item.below ? 'dropdown',
47+
{% if item.url.isrouted and item.url.routeName == '<nolink>' %}
48+
{% set menu_item_type = 'nolink' %}
49+
{# If there's more than one column, end the current one and
50+
start a new one. #}
51+
{% if not loop.first %}
52+
</div>
53+
<div class="dropdown-col">
54+
{% endif %}
55+
{% elseif item.url.isrouted and item.url.routeName == '<button>' %}
56+
{% set menu_item_type = 'button' %}
57+
{% if item.below %}
58+
<div class="nav-item dropdown">
59+
{% endif %}
60+
{% else %}
61+
{% set menu_item_type = 'link' %}
62+
{% endif %}
63+
{% set link_classes = [
64+
'menu__link--level-' ~ (menu_level + 1),
65+
item.in_active_trail ? 'menu__link--active-trail',
66+
dropdown == 'yes' ? 'dropdown-item' : 'nav-link',
67+
item.is_active ? 'active',
4368
]
4469
%}
45-
46-
{%
47-
set link_classes = [
48-
not menu_level ? 'nav-link',
49-
item.in_active_trail ? 'active',
50-
item.below ? 'dropdown-toggle',
51-
item.url.getOption('attributes').class ? item.url.getOption('attributes').class | join(' '),
52-
'nav-link-' ~ item.url.toString() | clean_class,
53-
]
54-
%}
55-
{# Change out the home link for an icon #}
56-
{% if item.title == 'Home' %}
57-
{%
58-
set home_classes = [
70+
{#
71+
A unique ID should be used but not available through Twig so use the
72+
|clean_id filter
73+
#}
74+
{% set aria_id = (item.title ~ '-submenu-' ~ loop.index)|clean_id %}
75+
{% if menu_item_type == 'link' %}
76+
{# Change out any home link for an icon #}
77+
{% if ('Home' in item.title) or ('home' in item.title) %}
78+
{%
79+
set home_classes = [
5980
'nav-link-home',
6081
'nav-link',
82+
is_front ? 'active',
6183
]
62-
%}
63-
{% if is_front %}
64-
<a{{ item.attributes.addClass(home_classes).addClass('active') }} href="{{ item.url }}">
84+
%}
85+
<a{{ item.attributes.addClass(home_classes) }} href="{{ item.url }}" tabindex="0">
86+
<span class="d-xl-none">{{ item.title }}</span>
87+
<span title="{{ item.title }}" class="fas fa-fw fa-home"></span>
88+
</a>
6589
{% else %}
66-
<a{{ item.attributes.addClass(home_classes) }} href="{{ item.url }}">
90+
{{ link(item.title, item.url, { 'class': link_classes, 'id': aria_id, 'tabindex': '0'}) }}
91+
{% endif %}
92+
{% elseif menu_item_type == 'nolink' %}
93+
<h3>{{ item.title }}</h3>
94+
{% elseif menu_item_type == 'button' %}
95+
<button class="btn dropdown-toggle nav-link" id="{{ aria_id }}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
96+
{{ item.title }}
97+
<svg class="svg-inline--fa fa-chevron-down fa-w-14" aria-hidden="true" focusable="false" data-prefix="fa" data-icon="chevron-down" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" data-fa-i2svg=""><path fill="currentColor" d="M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z"></path></svg>
98+
<!--<span class="fa fa-chevron-down"></span>-->
99+
</button>
100+
{% set attributes = attributes.setAttributes('id', aria_id) %}
101+
{% if item.below %}
102+
{% set dropdown = 'yes' %}
103+
<div class="dropdown-menu dropdown-columns" aria-labelledby="{{ aria_id }}">
104+
{# Always at least one column in the dropdown #}
105+
<div class="dropdown-col">
106+
{{ menus.menu_links(item.below, is_front, dropdown, attributes, menu_level + 1) }}
107+
</div> {# End the last column in the dropdown #}
108+
</div>
67109
{% endif %}
68-
<span class="d-xl-none">Home</span>
69-
<span title="Home" class="fas fa-fw fa-home"></span>
70-
</a>
71-
{% elseif item.below %}
72-
{{ link(item.title, item.url, {'class': link_classes, 'data-toggle': 'dropdown', 'aria-expanded': 'false', 'aria-haspopup': 'true' }) }}
73-
{{ menus.menu_links(item.below, attributes, menu_level + 1) }}
74-
{% else %}
75-
{{ link(item.title, item.url, {'class': link_classes}) }}
76110
{% endif %}
77-
111+
{% if (item.below and item.url.routename == '<button>') %}
112+
</div>
113+
{% endif %}
78114
{% endfor %}
79-
{% if is_expanded %}
80-
</div>
81-
{% endif %}
82115
{% endif %}
83116
{% endmacro %}

0 commit comments

Comments
 (0)