Fractal Starter
Project version : 0.1.2

Navigation

<!--
 * The primary subnav can have two different states:
 *
 * 1) By default, the subnav appear on hover from the trigger link.
 *
 * 2) With the 'js-dropdown--onclick' on the ul.primary-nav,
 *		the subnav appear on click from the trigger link.
 *
-->

<nav class="main-nav">
    <ul class="nav-primary" data-ui-component="primary-main">
        <li>
            <a href="#">Home</a>
        </li>
        <li>
            <a href="https://google.com" class="js-dropdown-link">About</a>

            <ul class="nav-primary__sub-nav js-dropdown-menu">
                <li><a href="#">Products</a></li>
                <li><a href="#">Company</a></li>
            </ul>
        </li>
        <li>
            <a href="#">Contact</a>
        </li>
        <li>
            <a href="#" class="js-dropdown-link">Services</a>

            <ul class="nav-primary__sub-nav js-dropdown-menu">
                <li><a href="#">Web</a></li>
                <li><a href="#">Data</a></li>
            </ul>
        </li>
    </ul>
</nav>
<!--
 * The primary subnav can have two different states:
 *
 * 1) By default, the subnav appear on hover from the trigger link.
 *
 * 2) With the 'js-dropdown--onclick' on the ul.primary-nav,
 *		the subnav appear on click from the trigger link.
 *
-->

<nav class="main-nav">
	<ul class="nav-primary" data-ui-component="primary-main">
		<li>
			<a href="#">Home</a>
		</li>
		<li>
			<a href="https://google.com" class="js-dropdown-link">About</a>

			<ul class="nav-primary__sub-nav js-dropdown-menu">
				<li><a href="#">Products</a></li>
				<li><a href="#">Company</a></li>
			</ul>
		</li>
		<li>
			<a href="#">Contact</a>
		</li>
		<li>
			<a href="#" class="js-dropdown-link">Services</a>

			<ul class="nav-primary__sub-nav js-dropdown-menu">
				<li><a href="#">Web</a></li>
				<li><a href="#">Data</a></li>
			</ul>
		</li>
	</ul>
</nav>
/* No context defined for this component. */
  • Content:
    /*------------------------------------*\
      Primary Nav
    \*------------------------------------*/
    
    nav {
    	ul, ul ul {
    		list-style-type: none;
    		margin:  0;
    		padding: 0;
    	}
    
    	ul ul {
    		padding-left: $margin-l;
    
    		@include mediaWQuery($media-query-l) {
    			padding-left: 0;
    		}
    	}
    
    	&.main-nav {
    		@include mediaWQuery($media-query-l) {
    			display: block!important;
    		}
    	}
    }
    	
    .nav-primary {
    	text-align: right;
    	border-bottom: 1px solid $c-gold;
    
    	@include mediaWQuery($media-query-l) {
    		text-align: left;
    		border: none;
    	}		
    
    	& > li {
    		position: relative;
    		vertical-align: middle;
    		
    		// Dropdown arrow
    		& > a.js-dropdown-link {
    			position: relative;
    			align-items: center;
    
    			&::after {
    				content: '';
    				display: inline-block;
    				width: 15px;
    				height: 15px;
    				margin-left: $margin-s;
    				margin-right: $margin-s;
    				background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='chevron-down' class='svg-inline--fa fa-chevron-down fa-w-14' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E %3Cdefs%3E %3ClinearGradient id='FirstGradient' %3E %3Cstop offset='0%25'/%3E %3C/linearGradient%3E %3C/defs%3E %3Cpath fill='%23E3CB78' 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'%3E%3C/path%3E %3C/svg%3E");
    				background-repeat: no-repeat;
    				background-size: auto 100%;
    			}
    
    			@include mediaWQuery($media-query-l) {
    				flex-direction: row;
    
    				&::after {
    					margin-right: 0;
    				}
    			}
    		}
    
    		& + li {
    			margin-top: $margin-s;
    			@include mediaWQuery($media-query-l) {
    				margin-top: 0;
    			}
    		}
    
    		&:last-child {
    			padding-right: 0!important;
    		}
    
    		@include mediaWQuery($media-query-l) {
    			display: inline-block;
    			padding: 0 1.5rem;
    		}
    	}
    
    	&__sub-nav {
    		display: none;
    		margin-top: $margin-s; 
    		padding-left: $margin-m;
    		@include mediaWQuery($media-query-l) {
    			background: $c-white;
    			box-shadow: $box-shadow-xs;
    			border-radius: $border-radius-xs;
    			padding: $margin-s;
    			display: none;
    			left: 0;
    			min-width: 150px;
    			opacity: 0;
    			position: absolute;
    			top: calc(100% + 10px);
    			margin-top: 0;
    			transform: translateY(15px);
    			transition: .2s ease;
    			z-index: 20;
    
    			> li {
    				& > a {
    					display: inline-block;
    					border-radius: $border-radius-s;
    					padding: $margin-xs $margin-s;
    					@include transition();
    
    					&:hover, &:focus {
    						background: $c-link-dropdown-hover;
    					}
    				}
    			}
    
    			&::after {
    				content: '';
    				@include absPosition($top: -8px, $right: false, $bottom: false, $left: 50%);
    				margin-left: -13px;
    				width: 0;
    				height: 0;
    				border-style: solid;
    				border-width: 0 13px 8px 13px;
    				border-color: transparent transparent $c-white; 
    			}
    		}
    
    		li + li { margin-top: $margin-xs }
    	}
    		
    	& > li > a,
    	&__sub-nav > li > a {
    		color: $c-font-color;
    		display: block;
    		font-family: $font-primary;
    		text-transform: uppercase;
    		-webkit-font-smoothing : antialiased;
    		margin:  0;
    		padding: .5rem;
    		text-decoration: none;
    
    		@include mediaWQuery($media-query-m) {
    			font-size: 21px!important;
    		}
    
    		&:hover,
    		&:focus,
    		&:active {
    			background-color: $c-gray-20;
    			border-radius: 4px;
    
    			@include mediaWQuery($media-query-l) {
    				background-color: transparent;
    				border-radius: 0;
    			}
    		}
    	}
    
    	& > li > a {
    		padding: 0 .5rem;
    	}
    
    	&__sub-nav > li > a {
    		padding-right: 2rem;
    	}
    }
  • URL: /components/raw/nav/_nav.scss
  • Filesystem Path: components/06-components/01-navs/01-nav/_nav.scss
  • Size: 3.6 KB
  • Content:
    const primaryNav = document.querySelector(".nav-primary");
    
    /**
     * Display the subnav
     * @param {node} element to show
     */
    const showSubNav = (el) => {
       el.classList.add("dropdown--active");
       el.style.display = "block";
       setTimeout(() => {
          el.style.transform = "translateY(0)";
          el.style.opacity = "1";
       }, 50);
    };
    
    /**
     * Hide the subnav
     * @param {node} element to hide
     */
    const hideSubNav = (el) => {
       el.style.transform = "translateY(15px)";
       el.style.opacity = "0";
       setTimeout(() => {
          el.style.display = "none";
          el.classList.remove("dropdown--active");
       }, 300);
    };
    
    /**
     * Detect if clik is outside element and close it.
     * @param {class|ID} class or ID of element to hide
     */
    const hideElOnOutsideClick = (elReference) => {
       document.addEventListener(
          "click",
          (event) => {
             let displayedEl = document.querySelector(elReference);
    
             if (displayedEl) {
                var clickedEl = event.target;
    
                if (
                   !clickedEl.closest(elReference) &&
                   !clickedEl.classList.contains("js-dropdown-link")
                ) {
                   hideSubNav(displayedEl);
                }
             }
          },
          false
       );
    };
    
    // close subNav on click outside
    hideElOnOutsideClick(".dropdown--active");
    
    /*------------------------------------*\
      Nav Main
    \*------------------------------------*/
    
    [].map.call(document.getElementsByClassName("js-dropdown-link"), (trigger) => {
       if (primaryNav.classList.contains("js-subNavOnClick")) {
          // If there is the specific 'onclick' class, show subnav on click.
          trigger.addEventListener("click", (event) => {
             let subNav = trigger.nextElementSibling;
             if (
                window.getComputedStyle(subNav, null).getPropertyValue("display") ==
                "none"
             ) {
                event.preventDefault();
                let activeSubNav = document.querySelector(".dropdown--active");
                if (activeSubNav) hideSubNav(activeSubNav);
    
                showSubNav(subNav);
    
                event.stopPropagation();
             }
          });
       } else {
          if (window.innerWidth >= 980) {
             // If there is no closs, show subnav on hover.
             trigger.addEventListener("mouseover", () => {
                let subNav = trigger.nextElementSibling;
                if (!subNav.classList.contains("dropdown--active")) {
                   let activeSubNav = document.querySelector(".dropdown--active");
                   if (activeSubNav) hideSubNav(activeSubNav);
    
                   showSubNav(subNav);
                }
             });
          } else {
             // And ontouchstart for smartphone
             trigger.addEventListener("click", (event) => {
                let subNav = trigger.nextElementSibling;
                if (
                   window
                      .getComputedStyle(subNav, null)
                      .getPropertyValue("display") == "none"
                ) {
                   event.preventDefault();
                   let activeSubNav = document.querySelector(".dropdown--active");
                   if (activeSubNav) hideSubNav(activeSubNav);
    
                   showSubNav(subNav);
                }
             });
          }
       }
    
       // Show subnav on focus
       if (window.innerWidth >= 980) {
          trigger.addEventListener("focus", (event) => {
             let subNav = trigger.nextElementSibling;
             if (!subNav.classList.contains("dropdown--active")) {
                event.preventDefault();
                let activeSubNav = document.querySelector(".dropdown--active");
                if (activeSubNav) hideSubNav(activeSubNav);
    
                showSubNav(subNav);
             }
          });
       }
    });
    
  • URL: /components/raw/nav/nav.js
  • Filesystem Path: components/06-components/01-navs/01-nav/nav.js
  • Size: 3.6 KB

There are no notes for this item.