menu https://publish.mediacurrent.com/ en Simplify Menu and Twig Macros https://publish.mediacurrent.com/blog/simplify-menu-and-twig-macros <span class="field field--name-title field--type-string field--label-hidden">Simplify Menu and Twig Macros</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>It is true that many Frontend Developers loathe the chore of creating a site’s menu, but I personally enjoy building them. I always thought of a website’s menu system as the perfect example of “the evolution of code”.</p> <p>Most menus start with a simple nested list of menu links; at most, all you need is the text and URL for the menu item. But over time, as the complexities of the menu and site evolve, you begin to watch as a complete custom menu system develops by adding parameters and logic. It’s a beautiful thing to observe.</p> <p>The same holds true with a menu module. Take the <a href="https://www.drupal.org/project/simplify_menu">Drupal 8 Simplify Menu module</a> as an example.</p> <p>Implemented as a TwigExtension to gain access to Drupal’s menu system, the array structure returned from `simplify_menu(menu_machine_name)` includes what is needed to have a simple menu.<br />  </p> <pre> <code class="language-twig">"menu_tree": [ { "text": "Section Menu text", "url": "#", "submenu": [] } ]</code></pre><p><em>Note that within the `"submenu":` array, the structure within the `{}` can repeat infinitely.</em></p> <p> </p> <h2>Creating a menu macro</h2> <p>With the understanding of the returned array structure, Twig macros can be leveraged to create a recursive menu. Here is an example of a rudimentary menu macro using the structure from the `simplify_menu(menu_machine_name)` function.<br />  </p> <pre> <code class="language-twig">{% macro menuMacro(menu) -%} &lt;ul&gt; {% for menu_item in menu %} &lt;li&gt; &lt;a href="{{ menu_item.url }}"&gt;{{ menu_item.text }}&lt;/a&gt; {% if menu_item.submenu %} {# Since this menu item has a submenu, recall function. #} {{ _self.menuMacro(menu_item.submenu) }} {% endif %} &lt;/li&gt; {% endfor %} &lt;/ul&gt; {%- endmacro %}</code></pre><p><em>An array of menu items, `menu`, is passed into macro containing `text`, `url`, and `submenu` in each row.</em></p> <p> </p> <h2>Active Trails</h2> <p>Active &amp; active-trail support is not supported in Simplify Menu module at the time of this writing. However, <a href="https://www.drupal.org/node/2882867">a patch exists on Drupal.org</a> that adds this functionality to the array structure from the Simplify Menu module.</p> <p>Big shoutout to <a href="https://www.drupal.org/u/smurrayatwork" style="background-color: whitesmoke;">smurrayatwork</a> for implementing the active trails!</p> <p>After the successful application of the active trails patch, the array structure returned from `simplify_menu()` includes 2 additional keys per row.<br />  </p> <pre> <code class="language-twig">"menu_tree": [ { "text": "Section Menu text", "url": "#", "active": true|false, "active-trail": true|false, "submenu": [] } ]</code></pre><p>And with the new keys in the array structure, we can then add some classes to our menu structure.<br />  </p> <pre> <code class="language-twig">{% macro menuMacro(menu) -%} &lt;ul&gt; {% for menu_item in menu %} {# Check if this is the active item. #} {% set active = (menu_item.active) ? ' is-active' : '' %} {# Check if this item is in the active trail. #} {% set active = active ~ ((menu_item.active_trail) ? ' is-active-trail' : '') %} &lt;li class=”menu__item{{ active }}”&gt; &lt;a href="{{ menu_item.url }}" class=”menu__link{{ active }}”&gt;{{ menu_item.text }}&lt;/a&gt; {% if menu_item.submenu %} {# Since this menu item has a submenu, recall function. #} {{ _self.menuMacro(menu_item.submenu) }} {% endif %} &lt;/li&gt; {% endfor %} &lt;/ul&gt; {%- endmacro %}</code></pre><p><em>Example uses string concatenation to build string of classes. Optionally, an array could be used with `|join()` in Twig.</em></p> <p> </p> <h2>Menu level classes?</h2> <p>An available class that identifies what level you are in a menu can make many tasks easier. About the easiest way to accomplish this with a Twig macro is to use simple integers. Setting a variable with a default of `1`, the menu would have the ability to know where it is in the loop.<br />  </p> <pre> <code class="language-twig">{% macro menuMacro(menu, level) -%} {# Set our default level as an integer. #} {% set default_level = 1 %} &lt;ul class=”menu-level--{{ level|default(default_level) }}”&gt; {% for menu_item in menu %} {# Check if this is the active item. #} {% set active = (menu_item.active) ? ' is-active' : '' %} {# Check if this item is in the active trail. #} {% set active = active ~ ((menu_item.active_trail) ? ' is-active-trail' : '') %} &lt;li class=”menu__item{{ active }}”&gt; &lt;a href="{{ menu_item.url }}" class=”menu__link{{ active }}”&gt;{{ menu_item.text }}&lt;/a&gt; {% if menu_item.submenu %} {# Since this menu item has a submenu, recall function and increment counter. #} {{ _self.menuMacro(menu_item.submenu, level|default(default_level) + 1) }} {% endif %} &lt;/li&gt; {% endfor %} &lt;/ul&gt; {%- endmacro %}</code></pre><p><em>Parameter `level` is now passed into function, in addition to a new variable added for default value. `level` is then added as part of a class, ensuring that the default value is provided. `level` is then incremented when called recursively.</em></p> <p> </p> <h2>Be careful of over-engineering</h2> <p>While this solution can be used to create a recursive menu, if a recursive menu is not needed, implementing one can be more work than it is worth. If all you are looking in your menu is a few levels at max, it may just be easier to code in the levels in the template, versus creating an intricate recursive structure.</p> <p>Use the right tool for the job!<br />  </p> <h2>Conclusion</h2> <p>At the end of the day, it all comes down to an understanding of recursive functions. A function calling itself recursively will allow an entire array tree to be traversed. Get what you need into that array, or available in another context in the template, and you will be able to act on all levels of the menu structure.</p> </div> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/about/our-team/mediacurrent-team" lang="" about="/about/our-team/mediacurrent-team" typeof="schema:Person" property="schema:name" datatype="" class="username">Mediacurrent Team</a></span> <span class="field field--name-created field--type-created field--label-hidden">Wed, 06/28/2017 - 09:05</span> <div class="field field--name-field-image-ref field--type-entity-reference field--label-above"> <div class="field__label">Main Image</div> <div class="field__item"><a href="/media/2987" hreflang="en">twig_0.jpg</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tags</div> <div class="field__items"> <div class="field__item"><a href="/tags/twig" hreflang="en">twig</a></div> <div class="field__item"><a href="/tags/menu" hreflang="en">menu</a></div> <div class="field__item"><a href="/tags/drupal-8" hreflang="en">Drupal 8</a></div> <div class="field__item"><a href="/tags/front-end-developer" hreflang="en">Front-End Developer</a></div> </div> </div> <div class="gatsby-iframe-container"><iframe class="gatsby-iframe" src="https://preview-misriptide.gtsb.io/blog/simplify-menu-and-twig-macros"></iframe></div> Wed, 28 Jun 2017 13:05:34 +0000 Mediacurrent Team 2985 at https://publish.mediacurrent.com More Mobile Menu Options https://publish.mediacurrent.com/blog/more-mobile-menu-options <span class="field field--name-title field--type-string field--label-hidden">More Mobile Menu Options</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>There are a lot of ways to handle navigation in general, because “best practices” for mobile are still being sorted out. There isn’t a one-size-fits-all solution because everyone has different needs for their site, and their menus are organized differently.</p> <p dir="ltr">I recently had the opportunity to participate in a <a href="http://drupaleasy.com/">DrupalEasy</a> podcast this week about designing and implementing <a href="http://drupaleasy.com/podcast/2012/12/drupaleasy-podcast-94-michigan-minecraft-montoya-mobile-menus">mobile-friendly navigation</a>. We discussed a handful of the options I outlined in my previous <a href="http://www.mediacurrent.com/blog/responsive-design-mobile-menu-options">mobile menu blog post</a>, but a few other strategies surfaced that I wanted to share.</p> <ul> <li dir="ltr"><a href="http://drupal.org/project/dhtml_menu">The DHTML module.</a> Be sure that if you are using this module that you’ve really thought through the options on what to do with parent links. You can find the options at /admin/config/user-interface/dhtml_menu which cover a variety of ways to handle those links. As far as UX goes, the "None"option is probably best. Meaning that pages that contain child links are not actually pages, rather they are just "containers" for the child links, or a means to organize and sort your menu tree of options. This is not ideal for everyone, but if you find yourself struggling to fill those parent pages with content and you wind up just describing the child pages -- this can be a great option.<br /><img style="margin-top: 10px;" src="/sites/default/files/dhtml-module-options.png" alt="" width="350" height="285" /></li> <li dir="ltr">If the parent pages on your site do hold real content, you could create a hybrid version of the accordion menu <a href="http://ivanchaquea.com/creating-responsive-menu-omega-subthemes.html">that allows users to both hit parent</a> pages and reveal child links. <a href="http://ivanchaquea.com/creating-responsive-menu-omega-subthemes.html">This method is outlined nicely here</a> - however I encourage lots of testing with this method since it appears that the JS loading the expand link was a bit slow on my phone.</li> <li dir="ltr">Print the menu twice, create a anchor link at the top that jumps users to the bottom where the menu is. With this method, you can use <a href="http://drupal.org/project/menu_block">menu blocks</a> set to show children menu items when a user is on the parent page. This can mean less scrolling past dozens of children menu options, but it also means that users have to click on a parent page to see the other child links for that page.<br /><img style="margin-top: 10px;" src="/sites/default/files/parent-child-menu-items.png" alt="" width="275" height="315" /></li> <li dir="ltr">Transform a list of links into a select menu for small screens. This avoids the problems the <a href="http://bradfrostweb.com/blog/web/responsive-nav-patterns/#top">top nav approach</a> presents and is a clever way to save real estate. There is a Drupal module called <a href="http://drupal.org/project/tinynav">tinynav.js</a> that does this. Note that if you have a huge menu tree, this can create an overwhelming sea of links for users. This method also makes it harder to see the hierarchy of the links.</li> </ul> <p>Above all else, remember not to treat your mobile users like they are less deserving of your content than the desktop users. Don't hide content or make menus difficult to use, and be sure to test any solution on a myriad of actual mobile devices.</p> <p><strong>Additional Resources</strong></p> <p><a href="http://www.mediacurrent.com/blog/responsive-design-mobile-menu-options">Responsive Design: Mobile Menu Options</a></p> <p>[video] <a href="http://www.mediacurrent.com/resources/videos/josh-clark-seven-deadly-mobile-myths">7 Deadly Myths of Mobile</a></p> <p>Free Drupal Whitepaper | <a href="http://www.mediacurrent.com/resources/white-papers/-papers/mobile-web-drupal">The Mobile Web and Drupal</a><strong><br /></strong></p> </div> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/about/our-team/mediacurrent-team" lang="" about="/about/our-team/mediacurrent-team" typeof="schema:Person" property="schema:name" datatype="" class="username">Mediacurrent Team</a></span> <span class="field field--name-created field--type-created field--label-hidden">Fri, 12/07/2012 - 13:59</span> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tags</div> <div class="field__items"> <div class="field__item"><a href="/tags/theming" hreflang="en">Theming</a></div> <div class="field__item"><a href="/tags/drupal" hreflang="en">Drupal</a></div> <div class="field__item"><a href="/tags/menu" hreflang="en">menu</a></div> <div class="field__item"><a href="/tags/mobile" hreflang="en">Mobile</a></div> <div class="field__item"><a href="/tags/navigation" hreflang="en">navigation</a></div> <div class="field__item"><a href="/tags/responsive" hreflang="en">responsive</a></div> </div> </div> <div class="gatsby-iframe-container"><iframe class="gatsby-iframe" src="https://preview-misriptide.gtsb.io/blog/more-mobile-menu-options"></iframe></div> Fri, 07 Dec 2012 18:59:45 +0000 Mediacurrent Team 722 at https://publish.mediacurrent.com Responsive Design: Mobile Menu Options https://publish.mediacurrent.com/blog/responsive-design-mobile-menu-options <span class="field field--name-title field--type-string field--label-hidden">Responsive Design: Mobile Menu Options</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>At various <a href="http://www.mediacurrent.com/drupal-give">Omega presentations</a> I've given at Drupalcamps and in <a href="http://www.mediacurrent.com/blog/all/19">blog posts I've written</a>, people have asked me about responsive menu options. Brad Frost has <a href="http://bradfrostweb.com/blog/web/responsive-nav-patterns/">outlined some great options</a> for <a href="http://bradfrostweb.com/blog/web/complex-navigation-patterns-for-responsive-design/">responsive menus</a>, and I'd encourage you to do your research since it's a always a good idea to review what your options are before deciding on a particular path. I will say that using browscap to hide/show your menu(s) is not recommended or necessary since browser sniffing is not very reliable, hence the whole movement toward responsive design.</p> <p>Since I'm now theming primarily with <a href="http://drupal.org/project/omega">Omega</a>, I typically style the menu links to be finger-friendly for mobile, and then I'll add styles to that same menu to put it back into a normal menu bar shape for desktop. Then I'll add a "menu link" block that displays only for mobile users (the default.css Omega stylesheet has this block set to display:none;). This link uses a bit of jQuery to hide and show the menu items (to save on space).</p> <p style="clear: left;"><a href="http://bit.ly/dca-2012">Check out this year's Drupalcamp Atlanta site to see the jquery mobile menu in action</a>.</p> <p>Since I've used this method 2 or 3 times now for different sites, my co-worker <a href="http://drupal.org/user/336254">Kevin</a> turned it into a module, and the sandbox version is on Drupal.org. So check out the <a href="http://bit.ly/mobile-menu-toggle">Mobile Menu Toggle module</a>, maybe it will save you a bit of time. Please provide feedback (or report issues if there are any)!</p> <p>If you are using <a href="http://drupal.org/project/om_maximenu">OM Maximenu</a>, those can be a bit unruly so you could use a separate menu for mobile. Or you can use <a href="http://drupal.org/project/menu_block">Menu Blocks</a> to help you build both the mobile menu and the MaxiMenu off of the same menu tree like Primary Links, which would be ideal. Thanks to <a href="https://twitter.com/thememaster">Danté</a> for that tip!</p> <p>Just create your Primary Menu structure first, and then create separate menu blocks for use in the maximenu structure. You can import the primary menu links using the import tab on the MaxiMenu admin page. Then save yourself time by adding all the children via menu blocks. You'd likely set these menu blocks to only begin displaying at the secondary menu level and show all the children. Then create another menu block just for mobile users, which only displays the children menu items when you are on their parent page, <a href="http://university.asco.org">like this</a>. Note, that example just uses anchors to jump to the menu at the bottom instead of hiding it. </p> <p>Hope some of this has been helpful, and thanks to <a href="http://bradfrostweb.com">Brad Frost</a> for his thorough coverage on all the different options out there! It's really a case-by-case issue, where you must determine which solution works best for your website needs.</p> <p><strong>Additional Resources</strong></p> <div><a href="http://bit.ly/KK8aY1">Going Mobile with Drupal</a> | Mediacurrent Blog Post</div> <div> <a href="http://bit.ly/KTgAv0">Responsive Design + Drupal</a> | Mediacurrent Blog Post<br />  </div> </div> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/about/our-team/mediacurrent-team" lang="" about="/about/our-team/mediacurrent-team" typeof="schema:Person" property="schema:name" datatype="" class="username">Mediacurrent Team</a></span> <span class="field field--name-created field--type-created field--label-hidden">Wed, 10/03/2012 - 11:47</span> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tags</div> <div class="field__items"> <div class="field__item"><a href="/tags/theming" hreflang="en">Theming</a></div> <div class="field__item"><a href="/tags/drupal" hreflang="en">Drupal</a></div> <div class="field__item"><a href="/tags/megamenu" hreflang="en">megamenu</a></div> <div class="field__item"><a href="/tags/menu" hreflang="en">menu</a></div> <div class="field__item"><a href="/tags/mobile" hreflang="en">Mobile</a></div> <div class="field__item"><a href="/tags/mobile-menu" hreflang="en">mobile menu</a></div> <div class="field__item"><a href="/tags/omega" hreflang="en">Omega</a></div> <div class="field__item"><a href="/tags/responsive" hreflang="en">responsive</a></div> <div class="field__item"><a href="/tags/responsive-menus" hreflang="en">responsive menus</a></div> <div class="field__item"><a href="/tags/rwd" hreflang="en">RWD</a></div> <div class="field__item"><a href="/tags/theme" hreflang="en">Theme</a></div> <div class="field__item"><a href="/tags/web" hreflang="en">web</a></div> <div class="field__item"><a href="/tags/website" hreflang="en">Website</a></div> </div> </div> <div class="gatsby-iframe-container"><iframe class="gatsby-iframe" src="https://preview-misriptide.gtsb.io/blog/responsive-design-mobile-menu-options"></iframe></div> Wed, 03 Oct 2012 15:47:11 +0000 Mediacurrent Team 684 at https://publish.mediacurrent.com