Skip to content
This repository has been archived by the owner on Nov 9, 2022. It is now read-only.

Mega-menu Entity #449

Open
ebollens opened this issue Sep 17, 2013 · 7 comments
Open

Mega-menu Entity #449

ebollens opened this issue Sep 17, 2013 · 7 comments

Comments

@ebollens
Copy link
Contributor

This is an oft-requested feature that can be achieved already through the use of .row with panels (and for responsive behavior, additional nested rows plus some Javascript). However, we should provide a simple way to access this.

Open questions are:

  1. Markup prototype (@ebollens to provide subsequently)
  2. Class name (@loganfranken any ideas here?)
@loganfranken
Copy link
Contributor

As for class name, any issue with simply .mega or .megamenu or .mega-menu?

@ebollens
Copy link
Contributor Author

I think mega would be fine, except I'm a bit shaky on where this differs significantly from a navbar with a particular dropdown effect.

@ebollens
Copy link
Contributor Author

ebollens commented Nov 4, 2013

My proposed markup for the mega-menu:

<nav class="mega">
    <ul>
        <li>
            <a href="#">Direct Link</a>
        </li>
        <li>
            <h1><a href="#">Simple Sub-menu</a></h1>
            <ul>
                <li><a href="#">Link 1</a></li>
                <li><a href="#">Link 2</a></li>
                <li><a href="#">Link 3</a></li>
                <li><a href="#">Link 4</a></li>
                <li><a href="#">Link 5</a></li>
                <li><a href="#">Link 6</a></li>
                <li><a href="#">Link 7</a></li>
                <li><a href="#">Link 8</a></li>
            </ul>
        </li>
        <li>
            <h1><a href="#">Complex Sub-menu</a></h1>
            <ul>
                <li>
                    <h2>Sub-header 1</h2>
                    <ul>
                        <li><a href="#">Link 1</a></li>
                        <li><a href="#">Link 2</a></li>
                        <li><a href="#">Link 3</a></li>
                        <li><a href="#">Link 4</a></li>
                    </ul>
                </li>
                <li>
                    <h2>Sub-header 2</h2>
                    <ul>
                        <li><a href="#">Link 1</a></li>
                        <li><a href="#">Link 2</a></li>
                    </ul>
                </li>
                <li>
                    <h2>Sub-header 3</h2>
                    <ul>
                        <li><a href="#">Link 1</a></li>
                        <li><a href="#">Link 2</a></li>
                    </ul>
                </li>
                <li>
                    <h2>Sub-header 4</h2>
                    <ul>
                        <li><a href="#">Link 1</a></li>
                        <li><a href="#">Link 2</a></li>
                    </ul>
                </li>
                <li>
                    <h2>Sub-header 5</h2>
                    <ul>
                        <li><a href="#">Link 1</a></li>
                        <li><a href="#">Link 2</a></li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>
</nav>

Three primary types of support:

  1. Direct link from the mega menu is any link that does not have a sibling ul
  2. Top-level item that has a sibling ul containing list items with links
  3. Top-level item that has a sibling ul containing list items with sub-lists

The dropdown behavior:

  1. If a direct link, no dropdown - just goes to the other page.
  2. If has a sub-list, linking behavior on top item is overridden - instead causes the mega menu to drop down.

The gridding behavior:

  1. Above $breakpoint-medium, show four columns for the sub-list. If more than four columns, every set of four become a "row".
  2. Between $breakpoint-small and $breakpoint-medium, show two columns for the sub-lists. If more than two columns, every two columns become a "row".
  3. Below $breakpoint-small, each item is shown inline.

The dropdown behavior (2) occurs regardless of breakpoint - however, below $breakpoint-small, the dropdown happens directly under the item clicked on (causing the whole menu to expand), while above that breakpoint, the dropdown happens below the list of top-level items.

Of course, all of this is useless without a prototype (which can be found under ucla/WebBlocks-kit and ucla/WebBlocks-kit-core...

Here's the behavior above medium breakpoint:

screen shot 2013-11-03 at 9 31 10 pm

And between the small and medium breakpoints:

screen shot 2013-11-03 at 9 32 44 pm

And below the small breakpoint:

screen shot 2013-11-03 at 9 33 29 pm

The blue hue in the background is being absorbed from a primary across the containing element at a higher level, namely the markup from the above example here:

        <header class="site primary inverted gradient clearfix">
            <div class="container">
                <hgroup>
                    <h1><a href="http://ucla.edu" class="ir logo">UCLA</a></h1>
                    <h2><a href="/">Department Name</a></h2>
                </hgroup>
                <nav class="search">
                    <form class="form">
                        <label for="search-input" class="hide-accessible">Site Search</label>
                        <input type="search" name="search" id="search-input">
                        <input type="submit">
                    </form>
                </nav>
                <nav class="mega">
                    <ul>
                        <li>
                            <a href="#">Direct Link</a>
                        </li>
                        <li>
                            <h1><a href="#">Simple Sub-menu</a></h1>
                            <ul>
                                <li><a href="#">Link 1</a></li>
                                <li><a href="#">Link 2</a></li>
                                <li><a href="#">Link 3</a></li>
                                <li><a href="#">Link 4</a></li>
                                <li><a href="#">Link 5</a></li>
                                <li><a href="#">Link 6</a></li>
                                <li><a href="#">Link 7</a></li>
                                <li><a href="#">Link 8</a></li>
                            </ul>
                        </li>
                        <li>
                            <h1><a href="#">Complex Sub-menu</a></h1>
                            <ul>
                                <li>
                                    <h2>Sub-header 1</h2>
                                    <ul>
                                        <li><a href="#">Link 1</a></li>
                                        <li><a href="#">Link 2</a></li>
                                        <li><a href="#">Link 3</a></li>
                                        <li><a href="#">Link 4</a></li>
                                    </ul>
                                </li>
                                <li>
                                    <h2>Sub-header 2</h2>
                                    <ul>
                                        <li><a href="#">Link 1</a></li>
                                        <li><a href="#">Link 2</a></li>
                                    </ul>
                                </li>
                                <li>
                                    <h2>Sub-header 3</h2>
                                    <ul>
                                        <li><a href="#">Link 1</a></li>
                                        <li><a href="#">Link 2</a></li>
                                    </ul>
                                </li>
                                <li>
                                    <h2>Sub-header 4</h2>
                                    <ul>
                                        <li><a href="#">Link 1</a></li>
                                        <li><a href="#">Link 2</a></li>
                                    </ul>
                                </li>
                                <li>
                                    <h2>Sub-header 5</h2>
                                    <ul>
                                        <li><a href="#">Link 1</a></li>
                                        <li><a href="#">Link 2</a></li>
                                    </ul>
                                </li>
                            </ul>
                        </li>
                    </ul>
                </nav>
            </div>
        </header>

The SASS that powers this (https://github.com/ucla/WebBlocks-kit-core/blob/master/extension/blocks/nav/_mega.scss):

nav.mega {

    clear: both;

    > ul {

        list-style: none;
        margin: 10px 0 0 0;
        padding: 0;

        > li {

            > h1 {

                font-size: inherit;
                line-height: inherit;
                margin-bottom: 0;

            }

            > a {
                font-weight: bold;
            }

            &:not(.active) {
                > ul {
                    @include -base-visibility-hide-accessible;
                }
            }

            ul {
                margin: 0;
                padding: 0;
            }

            > ul {

                padding: 10px 20px 0;
                margin-bottom: 10px;

                h2 {
                    font-size: inherit;
                }

                li {
                    list-style: none;
                    margin: 0;
                    padding: 0;
                }

                > li {
                    padding-bottom: 0.6*$type-line-spacing; /* same spacing as below an h2 */
                }
            }
        }
    }
}

@media (max-width:$breakpoint-small){
    nav.mega > ul > li:not(.active) {
        > h1, > a {
            display: block;
            padding-bottom: 0.6*$type-line-spacing; /* same spacing as below an h2 */
        }
    }
}

@media (min-width:$breakpoint-small+1){

    nav.mega > ul {

        height: 1.4em;
        float: right;

        > li {

            float: left;

            &.active {
                > h1, > a {
                    background-color: $color-body-background;
                }
                > h1 > a , > a {
                    color: $color-body-link-text !important;
                    &:hover {
                        color: $color-body-link-hover-text !important;
                    }
                }
            }

            &:not(:first-child) {

                padding-left: 20px;

                &:before {
                    content: "|";
                    float: left;
                    margin-left: -10px;
                }

            }

            > ul {

                position: absolute;
                left: 0;
                right: 0;
                z-index: 1000;
                background-color: $color-body-background;
                color: $color-body-background-text;

                a {
                    color: $color-body-link-text !important;
                    &:hover {
                        color: $color-body-link-hover-text !important;
                    }
                }

                > li {
                    padding-bottom: 0.6*$type-line-spacing; /* same spacing as below an h2 */
                }

            }
        }
    }
}

@media (min-width:$breakpoint-small+1) and (max-width:$breakpoint-medium) {
    nav.mega > ul > li > ul > li {
        float: left;
        width: 50%;
        &:nth-child(2n+1){
            clear: both;
        }
    }
}

@media (min-width:$breakpoint-medium+1){
    nav.mega > ul > li > ul > li {
        float: left;
        width: 25%;
        &:nth-child(4n+1){
            clear: both;
        }
    }
}

And the Javascript involved (https://github.com/ucla/WebBlocks-kit-core/blob/master/extension/blocks/nav/mega.js):

/**
 * NAVIGATION SUB-MENU TOGGLE
 * 
 * When a link in the navigation is clicked, it should cause the associated
 * sub-menu to be toggled.
 */
$(document).ready(function(){

    $('nav.mega > ul > li :not(ul) a').click(function(e){
        var liEle = $(this).closest('li'),
            dropdownEle = liEle.children('ul'),
            show = !liEle.hasClass('active');

        if(!dropdownEle.length) // if no sub-menu, exit early to allow click
            return;

        e.preventDefault();

        // hide any open submenus
        $('nav.mega > ul > li').removeClass('active')

        // if sub-menu was not already showing, show it
        if(show)
            liEle.addClass('active')

        // recompute dropdown spacer if need be
        setDropdownSpacer($(liEle).closest('nav.mega'));
    });

    /**
     * This function sets the height of #site-header-navigation to the height 
     * of the menu items plus the height of the dropdown. This is required 
     * because dropdown list items are floated and thus do not affect the 
     * height of #site-header-navigation.
     * 
     * @todo compute height rather than assume 26px (known from CSS)
     * @returns null
     */
    var setDropdownSpacer = function(navEle){

        // Don't do anything if dropdown is not floated, as height already
        // considers dropdown list items
        if(!isFloated(navEle))
            return;

        // Selects the currently open sub-menu
        var active = navEle.find('.active'),
            visible = active.find('ul:visible'),
            base = navEle.children('ul');

        if(visible.length) // if open sub-menu, set height as sum of sub-menu and top-level menu
            $(navEle).css('height', (visible.outerHeight()+base.outerHeight()+10)+'px')
        else // if no sub-menu open, set height to height of top-level menu
            $(navEle).css('height', base.outerHeight()+'px')

    }

    /**
     * This fuction returns true if navigation items are floated. A true value 
     * implies that sub-menu list items do not affect the height of 
     * #site-header-navigation and thus setDropdownSpacer() should be called to 
     * define an explicit height for #site-header-navigation.
     * 
     * @returns bool
     */
    var isFloated = function(navEle){
        var floatVal = navEle.children('ul').children('li').first().css('float')
        return floatVal == 'left' || floatVal == 'right';
    }

    /**
     * This function sets an explicit height if the dropdown sub-menu is
     * floated, or else the height is part of auto computation, so it sets
     * height to auto.
     * 
     * @todo compute height rather than assume 26px (known from CSS)
     * @returns null
     */
    var handleDropdownSpacing = function(navEle){
        $(navEle).css('height','auto');
        setDropdownSpacer($(navEle));
    }

    $(window).resize(function(){
        $('nav.mega').each(function(){
            handleDropdownSpacing(this);
        });
    });

});

There's of course polish needed, but I think this provides some motivation to start with.

@ebollens
Copy link
Contributor Author

ebollens commented Nov 4, 2013

@loganfranken suggests that we use h1 as title of mega-menu, h2 as title of menu sections and h3 sub-menu headers.

@loganfranken
Copy link
Contributor

An example of this from the W3C wiki:
http://www.w3.org/wiki/HTML/Elements/nav

@loganfranken
Copy link
Contributor

"Sectioning content" reference:
http://www.w3.org/html/wg/drafts/html/master/dom.html#sectioning-content

@ebollens
Copy link
Contributor Author

While I'm happy with the markup, the presentation is too UCLA-specific. I tried to come up with a better looking design, but so far I'm not happy with it. Rather than end up with another element like the navbar that lacks design flares, I'm going to open this issue up and ask if anyone can provide a nice design for implementation.

This was referenced Dec 27, 2013
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants