Copy environment

Navigation

<nav class="navigation navigation--idle js-navigation">
    <ul class="navigation__list navigation__list--parents">
        <li class="navigation__item   ">
            <svg class="icon  navigation__arrow-icon">
                <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#arrow-right-long-54"></use>
            </svg>
            <a href="#" class="navigation__link">
                Home
            </a>
            <span class="navigation__description">Home is the place to be #staythefuckhome</span>
        </li>
        <li class="navigation__item has-children is-current  ">
            <svg class="icon  navigation__arrow-icon">
                <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#arrow-right-long-54"></use>
            </svg>
            <a href="#" class="navigation__link">
                Services
                <svg class="icon  navigation__chevron">
                    <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#chevron-bottom-24"></use>
                </svg>
            </a>
            <span class="navigation__description">Everything digital under one roof.</span>
            <ul class="navigation__list navigation__list--children">
                <li class="navigation__item  ">
                    <a href="#" class="navigation__link">
                        Business transformation
                    </a>

                    <svg class="icon  navigation__arrow-icon">
                        <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#tiny-arrow-right-long-24"></use>
                    </svg>
                </li>
                <li class="navigation__item  ">
                    <a href="#" class="navigation__link">
                        Design &amp; Innovation
                    </a>

                    <svg class="icon  navigation__arrow-icon">
                        <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#tiny-arrow-right-long-24"></use>
                    </svg>
                </li>
                <li class="navigation__item  ">
                    <a href="#" class="navigation__link">
                        Development
                    </a>

                    <svg class="icon  navigation__arrow-icon">
                        <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#tiny-arrow-right-long-24"></use>
                    </svg>
                </li>
                <li class="navigation__item  ">
                    <a href="#" class="navigation__link">
                        Maintenance
                    </a>

                    <svg class="icon  navigation__arrow-icon">
                        <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#tiny-arrow-right-long-24"></use>
                    </svg>
                </li>
            </ul>
        </li>
        <li class="navigation__item has-children  ">
            <svg class="icon  navigation__arrow-icon">
                <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#arrow-right-long-54"></use>
            </svg>
            <a href="#" class="navigation__link">
                Work
                <svg class="icon  navigation__chevron">
                    <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#chevron-bottom-24"></use>
                </svg>
            </a>
            <span class="navigation__description">Home is the place to be #staythefuckhome</span>
            <ul class="navigation__list navigation__list--children">
                <li class="navigation__item  ">
                    <a href="#" class="navigation__link">
                        Business transformation
                    </a>

                    <svg class="icon  navigation__arrow-icon">
                        <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#tiny-arrow-right-long-24"></use>
                    </svg>
                </li>
                <li class="navigation__item  ">
                    <a href="#" class="navigation__link">
                        Design &amp; Innovation
                    </a>

                    <svg class="icon  navigation__arrow-icon">
                        <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#tiny-arrow-right-long-24"></use>
                    </svg>
                </li>
                <li class="navigation__item  ">
                    <a href="#" class="navigation__link">
                        Development
                    </a>

                    <svg class="icon  navigation__arrow-icon">
                        <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#tiny-arrow-right-long-24"></use>
                    </svg>
                </li>
            </ul>
        </li>
        <li class="navigation__item   ">
            <svg class="icon  navigation__arrow-icon">
                <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#arrow-right-long-54"></use>
            </svg>
            <a href="#" class="navigation__link">
                About
            </a>
            <span class="navigation__description">Home is the place to be #staythefuckhome</span>
        </li>
        <li class="navigation__item   ">
            <svg class="icon  navigation__arrow-icon">
                <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#arrow-right-long-54"></use>
            </svg>
            <a href="#" class="navigation__link">
                Contact
            </a>
            <span class="navigation__description">Got a project you dream of realizing? Get in touch!</span>
        </li>
    </ul>
</nav>
{% macro navItemLink(item, icon) %}
    {% set attributes %}
        {% if item.target %} target="{{ item.target }}"{% endif %}
        {%- if item.attr_title %} title="{{ item.attr_title }}"{% endif %}
        {%- if item._menu_item_xfn and item.link %} rel="{{ item._menu_item_xfn }}"{% endif %}
    {% endset %}
    {% set element = item.link ? 'a' : 'p' %}
    <{{element}} {% if item.link %}href="{{ item.link }}"{% endif %} class="navigation__link" {{ attributes|trim }}>
        {{ item.title }}
        {% if icon %} {{ icon }} {% endif %}
    </{{element}}>
{% endmacro %}

{% import _self as navigation %}

<nav class="navigation {{ modifier }} {{ class }}">
    {% if data.items %}
        <ul class="navigation__list navigation__list--parents">
            {% for item in data.items %}
                <li class="navigation__item {% if item.children %}has-children{% endif %}{% if item.current or item.current_item_ancestor %} is-current{% endif %} {% if 'navigation--footer' in modifier %}navigation__item--divisible-by-{{ loop.length }}{% endif %} {{ item.classes|join(' ') }}">
                    {% include '@icon' with { name: 'arrow-right-long-54', class: 'navigation__arrow-icon', modifier: '' } %}
                    {% if item.children and 'navigation--footer' not in modifier %}
                        {% set icon %}
                            {% include '@icon' with { name: 'chevron-bottom-24', class: 'navigation__chevron', modifier: '' } %}
                        {% endset %}
                    {% else %}
                        {% set icon = false %}
                    {% endif %}
                    {{ navigation.navItemLink(item, icon)|trim }}
                    {% if item.description %}
                        <span class="navigation__description">{{ item.description }}</span>
                    {% endif %}
                    {% if item.children %}
                        <ul class="navigation__list navigation__list--children">
                            {% for child in item.children %}
                                <li class="navigation__item {% if child.current %}is-current{% endif %} {{ child.classes|join(' ') }}">
                                    {{ navigation.navItemLink(child) }}
                                    {% include '@icon' with { name: 'tiny-arrow-right-long-24', class: 'navigation__arrow-icon', modifier: '' } %}
                                </li>
                            {% endfor %}
                            {% if 'footer__navigation' in class and loop.index == 1 %}
                                <li class="navigation__item {% if child.current %}is-current{% endif %}">
                                    {% include '@icon' with { name: 'tiny-arrow-right-long-24', class: 'navigation__arrow-icon', modifier: '' } %}
                                    <a class="navigation__link" data-cc="show-preferencesModal">Cookie preferences</a>
                                </li>
                            {% endif %}
                        </ul>
                    {% endif %}
                </li>
            {% endfor %}
        </ul>
    {% endif %}
</nav>
{
  "language": "en-US",
  "modifier": "navigation--idle",
  "class": "js-navigation",
  "data": {
    "items": [
      {
        "link": "#",
        "title": "Home",
        "description": "Home is the place to be #staythefuckhome"
      },
      {
        "link": "#",
        "title": "Services",
        "description": "Everything digital under one roof.",
        "current": "true",
        "children": [
          {
            "link": "#",
            "title": "Business transformation"
          },
          {
            "link": "#",
            "title": "Design &amp; Innovation"
          },
          {
            "link": "#",
            "title": "Development"
          },
          {
            "link": "#",
            "title": "Maintenance"
          }
        ]
      },
      {
        "link": "#",
        "title": "Work",
        "description": "Home is the place to be #staythefuckhome",
        "children": [
          {
            "link": "#",
            "title": "Business transformation"
          },
          {
            "link": "#",
            "title": "Design &amp; Innovation"
          },
          {
            "link": "#",
            "title": "Development"
          }
        ]
      },
      {
        "link": "#",
        "title": "About",
        "description": "Home is the place to be #staythefuckhome"
      },
      {
        "link": "#",
        "title": "Contact",
        "description": "Got a project you dream of realizing? Get in touch!"
      }
    ]
  }
}
  • Content:
    .navigation {
        color: $color-text-03;
    
        @include bp(md-min) {
            display: flex;
            justify-content: flex-end;
        }
    }
    
    .navigation--idle {
        @include bp(md-min) {
            justify-content: space-evenly;
        }
    }
    
    .navigation--footer {
        display: block;
    }
    
    .navigation__list--parents {
        display: block;
    
        @media only screen and (min-width: #{$bp-sm-min}) and (orientation: portrait) {
            display: flex;
            flex-direction: column;
            align-items: flex-end;
        }
    
        @include bp(md-min) {
            display: flex;
            flex-direction: column;
            align-items: flex-end;
        }
    
        &:after {
            .navigation--idle & {
                @include bp(md-min) {
                    content: '';
                    height: 1px;
                    background-color: $color-text-03;
                    position: absolute;
                    bottom: 1px;
                    left: 15px;
                    right: 15px;
                    width: 0;
                    transition-property: width;
                    transition-duration: $transition-duration*1.5;
                    transition-timing-function: $transition-easing-in;
                    transition-delay: $transition-duration;
                }
            }
    
            .navigation--idle.is-finished-animating & {
                visibility: hidden;
            }
    
            body.core-has-loaded &
            .navigation--idle.is-ready & {
                @include bp(md-min) {
                    width: calc(100% - 30px); /* stylelint-disable-line plugin/no-unsupported-browser-features */
                }
            }
        }
    
        .navigation--idle & {
            @include bp(md-min) {
                display: flex;
                margin: 0 -15px;
                flex-direction: row;
                align-items: flex-start;
                width: 100%;
            }
        }
    
        .navigation--footer & {
            display: flex;
            flex-direction: column;
            align-items: stretch;
    
            @include bp(md-min) {
                flex-direction: row;
                justify-content: flex-end;
                margin: 0 -28px;
            }
        }
    }
    
    .navigation__list--children {
        padding-top: 4px;
        padding-bottom: 4px;
        margin: 0;
        position: absolute;
        bottom: 0;
        left: 0;
        z-index: map-get($zindex, 'default');
        display: block;
        pointer-events: none;
    
        @include bp(sm-min) {
            right: 0;
            left: auto;
            display: flex;
            min-width: max-content; /* stylelint-disable-line plugin/no-unsupported-browser-features */
            flex-direction: column;
            align-items: flex-end;
        }
    
        .navigation--idle & {
            @include bp(md-min) {
                width: 100%;
                left: 50%;
                right: auto;
                transform: translateX(-50%);
                padding-top: 16px;
                padding-bottom: 16px;
                display: block;
                min-width: 0;
            }
        }
    
        .navigation--footer & {
            position: relative;
            bottom: auto;
            left: auto;
            right: auto;
            pointer-events: all;
            display: block;
            padding: 0;
            margin-top: 8px;
            min-width: 0;
    
            @include bp(md-min) {
                margin-top: 72px;
            }
        }
    
        .navigation__item.is-active & {
            pointer-events: all;
        }
    }
    
    .navigation__item {
        position: relative;
        opacity: 0;
        transition-property: opacity;
        transition-timing-function: $transition-easing-in;
        transition-duration: $transition-duration;
    
        .navigation--idle & {
            @include bp(md-min) {
                display: inline-block;
            }
        }
    
        .navigation--footer & {
            opacity: 1;
        }
    
        .navigation__list--parents > & {
            transition-property: opacity;
            padding: 16px 0;
    
            @media only screen and (min-width: #{$bp-sm-min}) and (orientation: portrait) {
                text-align: right;
            }
    
            @include bp(md-min) {
                text-align: right;
            }
    
            .navigation--idle & {
                @include bp(md-min) {
                    text-align: left;
                    padding: 0 0 1px;
                    flex-basis: 100%;
                }
            }
    
            .navigation--footer & {
                text-align: left;
                display: block;
                padding: 0;
    
                @include bp(md-min) {
                    display: inline-block;
                    padding: 0 28px;
                }
            }
    
            &:not(:first-child) {
                .navigation--footer & {
                    margin-top: 24px;
    
                    @include bp(md-min) {
                        margin-top: 0;
                    }
                }
            }
        }
    
        &.navigation__item--divisible-by-2 {
            .navigation__list--parents & {
                .navigation--footer & {
                    @include bp(md-min) {
                        flex: 1 1 calc(100%/2); /* stylelint-disable-line plugin/no-unsupported-browser-features */
                        max-width: calc(100%/2); /* stylelint-disable-line plugin/no-unsupported-browser-features */
                    }
                }
            }
        }
    
        &.navigation__item--divisible-by-3 {
            .navigation__list--parents & {
                .navigation--footer & {
                    @include bp(md-min) {
                        flex: 1 1 calc(100%/3); /* stylelint-disable-line plugin/no-unsupported-browser-features */
                        max-width: calc(100%/3); /* stylelint-disable-line plugin/no-unsupported-browser-features */
                    }
                }
            }
        }
    
        &.navigation__item--divisible-by-4 {
            .navigation__list--parents & {
                .navigation--footer & {
                    @include bp(md-min) {
                        flex: 1 1 calc(100%/4); /* stylelint-disable-line plugin/no-unsupported-browser-features */
                        max-width: calc(100%/4); /* stylelint-disable-line plugin/no-unsupported-browser-features */
                    }
                }
            }
        }
    
        .navigation__list--children & {
            display: block;
            position: relative;
            padding: 8px 0;
    
            .navigation--idle & {
                @include bp(md-min) {
                    padding: 0;
                }
            }
    
            .navigation--footer & {
                padding: 0;
            }
        }
    
        &.has-children {
            position: relative;
        }
    
        &:nth-child(1) {
            .navigation__item.is-active & {
                animation: setVisible $transition-duration $transition-easing 0s both;
            }
    
            body.core-has-loaded .navigation__list--parents > &,
            .header--no-description .navigation__list--parents > &,
            .navigation.is-ready .navigation__list--parents > & {
                animation: setVisible $transition-duration $transition-easing $transition-duration both;
    
                @include bp(md-min) {
                    animation: setVisible $transition-duration $transition-easing 0ms both;
                }
            }
        }
    
        &:nth-child(2) {
            .navigation__item.is-active & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*.1 both;
            }
    
            body.core-has-loaded .navigation__list--parents > &,
            .header--no-description .navigation__list--parents > &,
            .navigation.is-ready .navigation__list--parents > & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*1.2 both;
    
                @include bp(md-min) {
                    animation: setVisible $transition-duration $transition-easing $transition-duration*.1 both;
                }
            }
        }
    
        &:nth-child(3) {
            .navigation__item.is-active & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*.4 both;
            }
    
            body.core-has-loaded .navigation__list--parents > &,
            .header--no-description .navigation__list--parents > &,
            .navigation.is-ready .navigation__list--parents > & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*1.4 both;
    
                @include bp(md-min) {
                    animation: setVisible $transition-duration $transition-easing $transition-duration*.4 both;
                }
            }
        }
    
        &:nth-child(4) {
            .navigation__item.is-active & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*.7 both;
            }
    
            body.core-has-loaded .navigation__list--parents > &,
            .header--no-description .navigation__list--parents > &,
            .navigation.is-ready .navigation__list--parents > & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*1.6 both;
    
                @include bp(md-min) {
                    animation: setVisible $transition-duration $transition-easing $transition-duration*.7 both;
                }
            }
        }
    
        &:nth-child(5) {
            .navigation__item.is-active & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*1 both;
            }
    
            body.core-has-loaded .navigation__list--parents > &,
            .header--no-description .navigation__list--parents > &,
            .navigation.is-ready .navigation__list--parents > & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*1.8 both;
    
                @include bp(md-min) {
                    animation: setVisible $transition-duration $transition-easing $transition-duration*1 both;
                }
            }
        }
    
        &:nth-child(6) {
            .navigation__item.is-active & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*1.2 both;
            }
    
            body.core-has-loaded .navigation__list--parents > &,
            .header--no-description .navigation__list--parents > &,
            .navigation.is-ready .navigation__list--parents > & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*2 both;
    
                @include bp(md-min) {
                    animation: setVisible $transition-duration $transition-easing $transition-duration*1.2 both;
                }
            }
        }
    
        &:nth-child(7) {
            .navigation__item.is-active & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*1.8 both;
            }
    
            body.core-has-loaded .navigation__list--parents > &,
            .header--no-description .navigation__list--parents > &,
            .navigation.is-ready .navigation__list--parents > & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*2.2 both;
    
                @include bp(md-min) {
                    animation: setVisible $transition-duration $transition-easing $transition-duration*1.8 both;
                }
            }
        }
    
        &:nth-child(8) {
            .navigation__item.is-active & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*2.1 both;
            }
    
            body.core-has-loaded .navigation__list--parents > &,
            .header--no-description .navigation__list--parents > &,
            .navigation.is-ready .navigation__list--parents > & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*2.4 both;
    
                @include bp(md-min) {
                    animation: setVisible $transition-duration $transition-easing $transition-duration*2.1 both;
                }
            }
        }
    }
    
    .navigation__link {
        position: relative;
        display: block;
        color: inherit;
        text-decoration: none;
        font-size: $font-size-h2-xs;
        line-height: $line-height-h3-xs;
        font-weight: $font-weight-medium;
    
        @include bp(sm-min) {
            transition-property: opacity;
            transition-timing-function: $transition-easing-in;
            transition-duration: $transition-duration;
        }
    
        @media only screen and (min-width: #{$bp-sm-min}) and (orientation: portrait) {
            font-size: $font-size-h2-lg;
            line-height: $line-height-h2-lg;
        }
    
        @include bp(md-min) {
            font-size: $font-size-h2-lg;
            line-height: $line-height-h2-lg;
        }
    
        .navigation--idle & {
            @include bp(md-min) {
                font-size: $font-size-tiny;
                line-height: $line-height-tiny;
                padding: 0 15px;
                display: flex;
                align-items: center;
            }
        }
    
        .navigation--footer & {
            font-size: $font-size-h3-xs;
            line-height: $line-height-h3-xs;
    
            @include bp(md-min) {
                font-size: $font-size-h3-lg;
                line-height: $line-height-h3-lg;
            }
        }
    
        .navigation__list--parents > .navigation__item > & {
            .navigation--idle & {
                @include bp(md-min) {
                    padding-bottom: 35px;
                }
            }
        }
    
        .navigation__list--children & {
            font-size: $font-size-tiny;
            line-height: $line-height-tiny;
            padding: 4px 0;
    
            @include bp(sm-min) {
                opacity: .6;
            }
    
            .navigation--footer & {
                opacity: 1;
                font-size: $font-size-small;
                line-height: $line-height-small;
                font-weight: $font-weight-regular;
                padding: 8px 0;
            }
    
            .navigation--idle & {
                @include bp(md-min) {
                    padding: 8px 15px;
                }
            }
        }
    
        &:before {
            .navigation__list--parents > .navigation__item > & {
                .navigation--idle & {
                    @include bp(md-min) {
                        content: '';
                        height: 1px;
                        background-color: $color-text-03;
                        position: absolute;
                        bottom: 0;
                        left: 0;
                        right: 0;
                        opacity: 0;
                        transition-duration: 0ms;
                        transition-property: opacity;
                        transition-delay: $transition-duration*2.6;
                    }
                }
    
                body.core-has-loaded &,
                .navigation--idle.is-ready & {
                    opacity: 1;
                }
            }
    
            .navigation__item:first-child & {
                .navigation__list--parents & {
                    left: 15px;
                }
            }
    
            .navigation__item:last-child & {
                .navigation__list--parents & {
                    right: 15px;
                }
            }
        }
    
        &:after {
            .navigation__list--parents > .navigation__item > & {
                .navigation--idle & {
                    @include bp(md-min) {
                        content: '';
                        height: 3px;
                        background-color: $color-text-03;
                        position: absolute;
                        bottom: -1px;
                        left: auto;
                        right: 15px;
                        width: 0;
                        transition-property: width, opacity;
                        transition-timing-function: $transition-easing-in;
                        transition-duration: $transition-duration;
                    }
                }
            }
    
            .navigation__item.is-current > & {
                .navigation__list--parents > & {
                    body.core-has-loaded &,
                    .navigation--idle.is-ready & {
                        @include bp(md-min) {
                            opacity: 1;
                            transition-delay: $transition-duration*1.75;
                            width: calc(100% - 30px); /* stylelint-disable-line plugin/no-unsupported-browser-features */
                            left: 15px;
                            right: auto;
                        }
                    }
                }
            }
    
            .navigation__item:hover > & {
                .navigation__list--parents > & {
                    .navigation--idle & {
                        @include bp(md-min) {
                            width: calc(100% - 30px); /* stylelint-disable-line plugin/no-unsupported-browser-features */
                            left: 15px;
                            right: auto;
                        }
                    }
                }
            }
        }
    
        .navigation__item:not(:hover) > & {
            .navigation__list--parents:hover > & {
                .navigation:not(.navigation--idle):not(.navigation--footer) & {
                    @include bp(md-min) {
                        @media (hover: hover) {
                            opacity: .6;
                            transition-timing-function: $transition-easing-out;
                        }
                    }
                }
            }
    
            .navigation__list--children:hover > & {
                .navigation--footer & {
                    @include bp(sm-min) {
                        opacity: .6;
                        transition-timing-function: $transition-easing-out;
                    }
                }
            }
        }
    
        &:hover {
            .navigation__list--children & {
                opacity: 1;
                transition-timing-function: $transition-easing-out;
            }
        }
    
        &:focus {
            html[data-whatintent='keyboard'] & {
                opacity: 1;
                transition-timing-function: $transition-easing-out;
            }
        }
    }
    
    .navigation__description {
        display: none;
        position: absolute;
        top: 60px;
        left: 0;
        pointer-events: none;
    
        .navigation--idle & {
            @include bp(md-min) {
                font-size: 14px;
                color: inherit;
                padding: 16px 15px 48px;
                opacity: 0;
                visibility: hidden;
                transition-property: visibility, opacity;
                transition-timing-function: $transition-easing-in;
                transition-duration: $transition-duration;
            }
    
            @include bp(lg-min) {
                display: block;
            }
        }
    
        .navigation__item:nth-child(1) & {
            transition-delay: $transition-duration;
        }
    
        .navigation__item:nth-child(2) & {
            transition-delay: $transition-duration*1.2;
        }
    
        .navigation__item:nth-child(3) & {
            transition-delay: $transition-duration*1.4;
        }
    
        .navigation__item:nth-child(4) & {
            transition-delay: $transition-duration*1.6;
        }
    
        .navigation__item:nth-child(5) & {
            transition-delay: $transition-duration*1.8;
        }
    
        .navigation__item:nth-child(6) & {
            transition-delay: $transition-duration*2;
        }
    
        .navigation__item:nth-child(7) & {
            transition-delay: $transition-duration*2.2;
        }
    
        .navigation__item:nth-child(8) & {
            transition-delay: $transition-duration*2.4;
        }
    
        body.core-has-loaded &,
        .navigation--idle.is-ready & {
            @include bp(md-min) {
                opacity: 1;
                visibility: visible;
                transition-timing-function: $transition-easing-out;
            }
    
            body.is-hovering-nav & {
                @include bp(md-min) {
                    opacity: 0;
                    visibility: hidden;
                    transition-timing-function: $transition-easing-out;
                    transition-delay: 0ms;
                }
            }
        }
    }
    
    .navigation__arrow-icon {
        transition-property: opacity;
        transition-timing-function: $transition-easing-in;
        transition-duration: $transition-duration;
        pointer-events: none;
        display: none;
    
        .navigation__item.is-current > & {
            .navigation__list--parents > & {
                @media only screen and (min-width: #{$bp-sm-min}) and (orientation: portrait) {
                    font-size: 54px;
                    position: absolute;
                    left: -70px;
                    top: 23px;
                    bottom: 0;
                    display: inline-block;
                }
    
                @include bp(md-min) {
                    font-size: 54px;
                    position: absolute;
                    left: -70px;
                    top: 23px;
                    bottom: 0;
                    display: inline-block;
                }
    
                .navigation--footer &,
                .navigation--idle & {
                    @include bp(md-min) {
                        display: none;
                    }
                }
            }
        }
    
        .navigation__list--children & {
            position: absolute;
            left: -25px;
            top: 12px;
            bottom: 0;
            font-size: 24px;
            opacity: 0;
            transform: translateX(-25px);
            transition-property: visibility, opacity, transform;
            transition-timing-function: $transition-easing-in;
            transition-duration: $transition-duration;
    
            @include bp(sm-min) {
                left: -32px;
                display: inline-block;
            }
    
            .navigation--idle & {
                @include bp(md-min) {
                    left: -25px;
                }
    
                @include bp(md-min) {
                    top: 8px;
                }
            }
    
            .navigation--footer & {
                display: none;
                left: -40px;
                top: 10px;
    
                @include bp(lg-min) {
                    display: inline-block;
                }
            }
        }
    
        .navigation__item:not(:hover) > & {
            .navigation__list--parents:hover > & {
                .navigation:not(.navigation--idle) & {
                    @include bp(md-min) {
                        opacity: .6;
                        transition-timing-function: $transition-easing-out;
                    }
                }
            }
        }
    
        .navigation__item:hover > & {
            .navigation__list--children & {
                transform: translateX(0);
                opacity: 1;
            }
        }
    
        .navigation__link:focus + & {
            .navigation__list--children & {
                html[data-whatintent='keyboard'] & {
                    transform: translateX(0);
                    opacity: 1;
                }
            }
        }
    }
    
    .navigation__chevron {
        display: none;
        font-size: 17px;
        margin-left: 2px;
    
        .navigation--idle & {
            @include bp(md-min) {
                display: block;
            }
        }
    }
    
    @keyframes setVisible {
        0% {
            transform: translateY(-10%);
            opacity: 0;
        }
    
        100% {
            transform: translateY(0);
            opacity: 1;
        }
    }
    
  • URL: /components/raw/navigation/navigation.scss
  • Filesystem Path: src/patterns/components/navigation/navigation.scss
  • Size: 21.8 KB
  • Content:
    import Component from '../component/component';
    import Helpers from '../helpers/helpers';
    
    import './navigation.scss';
    
    interface INavigationSettings {
        activeClass: string;
        animationSpeed: number;
        finishedClass: string;
        idleModifier: string;
        itemLinkClass: string;
        navHiddenClass: string;
        navHoverClass: string;
        readyClass: string;
    }
    
    export default class Navigation extends Component {
        static initSelector: string = '.js-navigation';
    
        public dropdownItems: JQuery;
        public dropdownLinks: JQuery;
        public initHeight: number;
        public continue: boolean;
        public body: JQuery;
        public animationDuration: number;
        public isOpen: boolean = false;
    
        settings: INavigationSettings;
    
        constructor(target: HTMLElement) {
            super(target);
    
            this.body = $('body');
    
            this.dropdownItems = this.element.find('.navigation__item.has-children');
            this.dropdownLinks = this.element.find('.navigation__list--children .navigation__link');
            this.initHeight = this.element.find('.navigation__item').first().outerHeight();
            this.continue = false;
    
            this.documentClickHandler = this.documentClickHandler.bind(this);
            this.openDropdown = this.openDropdown.bind(this);
            this.closeDropdown = this.closeDropdown.bind(this);
            this.toggleHandler = this.toggleHandler.bind(this);
    
            this.settings = {
                activeClass: 'is-active',
                animationSpeed: 250,
                finishedClass: 'is-finished-animating',
                idleModifier: 'navigation--idle',
                itemLinkClass: 'navigation__link',
                navHiddenClass: 'is-navigation-hidden',
                navHoverClass: 'is-hovering-nav',
                readyClass: 'is-ready',
            };
    
            this.init();
        }
    
        init(): void {
            setTimeout(() => {
                this.element.addClass(this.settings.readyClass);
            }, 250);
    
            setTimeout(() => {
                this.element.addClass(this.settings.finishedClass);
            }, 950);
    
            this.setAnimationSpeed();
    
            this.element.on('keyup.navigation', this.keyboardHandler.bind(this));
    
            this.addTriggerListeners();
            this.addFocusListener();
    
            $(window).on('resize', this.resizeHandler.bind(this));
    
            $(window).off('scroll', this.scrollHandler.bind(this));
            $(window).on('scroll', this.scrollHandler.bind(this));
        }
    
        setAnimationSpeed(): void {
            if ($(window).innerWidth() < Helpers.bp.md || this.body.hasClass(this.settings.navHiddenClass)) {
                this.animationDuration = this.settings.animationSpeed;
            } else {
                this.animationDuration = 5;
            }
        }
    
        scrollHandler(): void {
            setTimeout(() => {
                this.setAnimationSpeed();
            }, 100);
            this.addFocusListener();
        }
    
        resizeHandler(): void {
            this.closeDropdown();
            this.setIniHeights();
            this.setAnimationSpeed();
        }
    
        addFocusListener(): void {
            this.dropdownLinks.off('focus', this.sublinkFocusHandler.bind(this));
            this.dropdownLinks.off('blur', this.sublinkBlurHandler.bind(this));
    
            this.dropdownLinks.on('focus', this.sublinkFocusHandler.bind(this));
            this.dropdownLinks.on('blur', this.sublinkBlurHandler.bind(this));
        }
    
        addMouseListeners(): void {
            this.dropdownItems.on('mouseenter', this.openDropdown);
            this.dropdownItems.on('mouseleave', this.closeDropdown);
        }
    
        removeMouseListeners(): void {
            this.dropdownItems.off('mouseenter', this.openDropdown);
            this.dropdownItems.off('mouseleave', this.closeDropdown);
        }
    
        addClickListeners(): void {
            this.dropdownItems.children('.' + this.settings.itemLinkClass).on('click', this.toggleHandler);
        }
    
        removeClickListeners(): void {
            this.dropdownItems.children('.' + this.settings.itemLinkClass).off('click', this.toggleHandler);
        }
    
        toggleHandler(): void {
            event.preventDefault();
            this.toggleDropdown(event);
        }
    
        addEventListeners(): void {
            $(document).on('click.navigation', this.documentClickHandler);
        }
    
        addTriggerListeners(): void {
            if ($(window).width() < Helpers.bp.lg && Helpers.isMobileDevice || $(window).width() <= Helpers.bp.sm) {
                this.removeMouseListeners();
                this.addClickListeners();
            } else {
                this.addMouseListeners();
                this.removeClickListeners();
            }
        }
    
        sublinkFocusHandler(event: JQuery.TriggeredEvent): void {
            const targetElement: JQuery = $(event.currentTarget);
            const parentElement: JQuery = $(targetElement.closest('.navigation__item.has-children'));
            const inputDevice: string = $('html').attr('data-whatintent');
    
            if (inputDevice === 'keyboard' && !parentElement.hasClass(this.settings.activeClass)) {
                this.openDropdown();
            }
        }
    
        sublinkBlurHandler(): void {
            setTimeout(() => {
                const isSublinkFocused: JQuery = $('.navigation__list--children .navigation__link:focus');
    
                // avoid closing the dropdown if focus moved to another sublink
                if (!isSublinkFocused.length) {
                    this.closeDropdown();
                }
            }, 1);
        }
    
        documentClickHandler(event: JQuery.TriggeredEvent): void {
            if ($(event.target).closest(this.element.find('.navigation__list')).length === 0) {
                this.closeDropdown();
            }
        }
    
        setIniHeights(): void {
            this.dropdownItems.removeAttr('style');
            this.dropdownItems.each((index: number, element: HTMLElement) => {
                $(element).css({
                    height: $(element).outerHeight(),
                });
            });
        }
    
        toggleDropdown(event: Event): void {
            const previousOpen: JQuery = this.dropdownItems.filter('.' + this.settings.activeClass);
            const parentElement: JQuery = $(event.currentTarget).closest('.navigation__item') as JQuery;
    
            if (parentElement.hasClass(this.settings.activeClass)) {
                this.animateClose(parentElement);
                this.continue = true;
            }
    
            // Continue if there is nothing to close
            if (this.continue) {
                if (!parentElement.hasClass(this.settings.activeClass)) {
                    this.animateOpen(parentElement);
                    this.continue = false;
                } else {
                    this.animateClose(previousOpen);
                    this.continue = true;
                }
            } else {
                this.animateClose(previousOpen);
            }
        }
    
        open(menuItem: JQuery): void {
            menuItem.addClass(this.settings.activeClass);
            menuItem.children('.' + this.settings.itemLinkClass).attr('aria-expanded', 'true');
    
            this.addEventListeners();
        }
    
        animateOpen(parentElement: JQuery): void {
            const parentHeight: number = parentElement.outerHeight();
            const dropdownHeight: number = parentElement.find('.navigation__list').outerHeight();
    
            const calculatedHeight: number = parentHeight + dropdownHeight;
    
            if (parentElement.is(':animated')) {
                return;
            }
    
            this.body.addClass(this.settings.navHoverClass);
    
            this.initHeight = parentElement.outerHeight();
    
            parentElement.stop().animate({
                height: calculatedHeight,
            }, this.animationDuration, (): void => {
                this.open(parentElement);
            }).css('overflow', 'visible');
        }
    
        openDropdown(): void {
            if (!this.isOpen) {
                const parentElement: JQuery = $(event.currentTarget).closest('.navigation__item.has-children') as JQuery;
    
                this.animateOpen(parentElement);
                this.isOpen = true;
            }
        }
    
        closeDropdown(): void {
            if (this.isOpen) {
                this.animateClose($('.navigation__item.is-active') as JQuery);
    
                this.isOpen = false;
            }
        }
    
        close(): void {
            const currentActiveItem: JQuery = this.dropdownItems.filter('.' + this.settings.activeClass);
    
            currentActiveItem.removeClass(this.settings.activeClass);
            currentActiveItem.children('.' + this.settings.itemLinkClass).attr('aria-expanded', 'false');
            this.continue = true;
    
            this.destroy();
        }
    
        animateClose(current: JQuery): void {
            const currentActiveItem: JQuery = current;
    
            this.body.removeClass(this.settings.navHoverClass);
    
            if (currentActiveItem) {
                this.close();
    
                currentActiveItem.stop().animate({
                    height: this.initHeight,
                }, this.animationDuration).css('overflow', 'visible');
            }
        }
    
        keyboardHandler(event: KeyboardEvent): void {
            if (event.key === 'Escape') {
                this.close();
            }
        }
    
        destroy(): void {
            $(document).off('click.navigation', this.documentClickHandler);
        }
    }
    
    
  • URL: /components/raw/navigation/navigation.ts
  • Filesystem Path: src/patterns/components/navigation/navigation.ts
  • Size: 8.9 KB

Desktop Drawer

<nav class="navigation  js-navigation">
    <ul class="navigation__list navigation__list--parents">
        <li class="navigation__item   ">
            <svg class="icon  navigation__arrow-icon">
                <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#arrow-right-long-54"></use>
            </svg>
            <a href="#" class="navigation__link">
                Home
            </a>
            <span class="navigation__description">Home is the place to be #staythefuckhome</span>
        </li>
        <li class="navigation__item has-children is-current  ">
            <svg class="icon  navigation__arrow-icon">
                <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#arrow-right-long-54"></use>
            </svg>
            <a href="#" class="navigation__link">
                Services
                <svg class="icon  navigation__chevron">
                    <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#chevron-bottom-24"></use>
                </svg>
            </a>
            <span class="navigation__description">Everything digital under one roof.</span>
            <ul class="navigation__list navigation__list--children">
                <li class="navigation__item  ">
                    <a href="#" class="navigation__link">
                        Business transformation
                    </a>

                    <svg class="icon  navigation__arrow-icon">
                        <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#tiny-arrow-right-long-24"></use>
                    </svg>
                </li>
                <li class="navigation__item  ">
                    <a href="#" class="navigation__link">
                        Design &amp; Innovation
                    </a>

                    <svg class="icon  navigation__arrow-icon">
                        <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#tiny-arrow-right-long-24"></use>
                    </svg>
                </li>
                <li class="navigation__item  ">
                    <a href="#" class="navigation__link">
                        Development
                    </a>

                    <svg class="icon  navigation__arrow-icon">
                        <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#tiny-arrow-right-long-24"></use>
                    </svg>
                </li>
                <li class="navigation__item  ">
                    <a href="#" class="navigation__link">
                        Maintenance
                    </a>

                    <svg class="icon  navigation__arrow-icon">
                        <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#tiny-arrow-right-long-24"></use>
                    </svg>
                </li>
            </ul>
        </li>
        <li class="navigation__item has-children  ">
            <svg class="icon  navigation__arrow-icon">
                <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#arrow-right-long-54"></use>
            </svg>
            <a href="#" class="navigation__link">
                Work
                <svg class="icon  navigation__chevron">
                    <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#chevron-bottom-24"></use>
                </svg>
            </a>
            <span class="navigation__description">Home is the place to be #staythefuckhome</span>
            <ul class="navigation__list navigation__list--children">
                <li class="navigation__item  ">
                    <a href="#" class="navigation__link">
                        Business transformation
                    </a>

                    <svg class="icon  navigation__arrow-icon">
                        <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#tiny-arrow-right-long-24"></use>
                    </svg>
                </li>
                <li class="navigation__item  ">
                    <a href="#" class="navigation__link">
                        Design &amp; Innovation
                    </a>

                    <svg class="icon  navigation__arrow-icon">
                        <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#tiny-arrow-right-long-24"></use>
                    </svg>
                </li>
                <li class="navigation__item  ">
                    <a href="#" class="navigation__link">
                        Development
                    </a>

                    <svg class="icon  navigation__arrow-icon">
                        <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#tiny-arrow-right-long-24"></use>
                    </svg>
                </li>
            </ul>
        </li>
        <li class="navigation__item   ">
            <svg class="icon  navigation__arrow-icon">
                <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#arrow-right-long-54"></use>
            </svg>
            <a href="#" class="navigation__link">
                About
            </a>
            <span class="navigation__description">Home is the place to be #staythefuckhome</span>
        </li>
        <li class="navigation__item   ">
            <svg class="icon  navigation__arrow-icon">
                <use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#arrow-right-long-54"></use>
            </svg>
            <a href="#" class="navigation__link">
                Contact
            </a>
            <span class="navigation__description">Got a project you dream of realizing? Get in touch!</span>
        </li>
    </ul>
</nav>
{% macro navItemLink(item, icon) %}
    {% set attributes %}
        {% if item.target %} target="{{ item.target }}"{% endif %}
        {%- if item.attr_title %} title="{{ item.attr_title }}"{% endif %}
        {%- if item._menu_item_xfn and item.link %} rel="{{ item._menu_item_xfn }}"{% endif %}
    {% endset %}
    {% set element = item.link ? 'a' : 'p' %}
    <{{element}} {% if item.link %}href="{{ item.link }}"{% endif %} class="navigation__link" {{ attributes|trim }}>
        {{ item.title }}
        {% if icon %} {{ icon }} {% endif %}
    </{{element}}>
{% endmacro %}

{% import _self as navigation %}

<nav class="navigation {{ modifier }} {{ class }}">
    {% if data.items %}
        <ul class="navigation__list navigation__list--parents">
            {% for item in data.items %}
                <li class="navigation__item {% if item.children %}has-children{% endif %}{% if item.current or item.current_item_ancestor %} is-current{% endif %} {% if 'navigation--footer' in modifier %}navigation__item--divisible-by-{{ loop.length }}{% endif %} {{ item.classes|join(' ') }}">
                    {% include '@icon' with { name: 'arrow-right-long-54', class: 'navigation__arrow-icon', modifier: '' } %}
                    {% if item.children and 'navigation--footer' not in modifier %}
                        {% set icon %}
                            {% include '@icon' with { name: 'chevron-bottom-24', class: 'navigation__chevron', modifier: '' } %}
                        {% endset %}
                    {% else %}
                        {% set icon = false %}
                    {% endif %}
                    {{ navigation.navItemLink(item, icon)|trim }}
                    {% if item.description %}
                        <span class="navigation__description">{{ item.description }}</span>
                    {% endif %}
                    {% if item.children %}
                        <ul class="navigation__list navigation__list--children">
                            {% for child in item.children %}
                                <li class="navigation__item {% if child.current %}is-current{% endif %} {{ child.classes|join(' ') }}">
                                    {{ navigation.navItemLink(child) }}
                                    {% include '@icon' with { name: 'tiny-arrow-right-long-24', class: 'navigation__arrow-icon', modifier: '' } %}
                                </li>
                            {% endfor %}
                            {% if 'footer__navigation' in class and loop.index == 1 %}
                                <li class="navigation__item {% if child.current %}is-current{% endif %}">
                                    {% include '@icon' with { name: 'tiny-arrow-right-long-24', class: 'navigation__arrow-icon', modifier: '' } %}
                                    <a class="navigation__link" data-cc="show-preferencesModal">Cookie preferences</a>
                                </li>
                            {% endif %}
                        </ul>
                    {% endif %}
                </li>
            {% endfor %}
        </ul>
    {% endif %}
</nav>
{
  "language": "en-US",
  "modifier": "",
  "class": "js-navigation",
  "data": {
    "items": [
      {
        "link": "#",
        "title": "Home",
        "description": "Home is the place to be #staythefuckhome"
      },
      {
        "link": "#",
        "title": "Services",
        "description": "Everything digital under one roof.",
        "current": "true",
        "children": [
          {
            "link": "#",
            "title": "Business transformation"
          },
          {
            "link": "#",
            "title": "Design &amp; Innovation"
          },
          {
            "link": "#",
            "title": "Development"
          },
          {
            "link": "#",
            "title": "Maintenance"
          }
        ]
      },
      {
        "link": "#",
        "title": "Work",
        "description": "Home is the place to be #staythefuckhome",
        "children": [
          {
            "link": "#",
            "title": "Business transformation"
          },
          {
            "link": "#",
            "title": "Design &amp; Innovation"
          },
          {
            "link": "#",
            "title": "Development"
          }
        ]
      },
      {
        "link": "#",
        "title": "About",
        "description": "Home is the place to be #staythefuckhome"
      },
      {
        "link": "#",
        "title": "Contact",
        "description": "Got a project you dream of realizing? Get in touch!"
      }
    ]
  }
}
  • Content:
    .navigation {
        color: $color-text-03;
    
        @include bp(md-min) {
            display: flex;
            justify-content: flex-end;
        }
    }
    
    .navigation--idle {
        @include bp(md-min) {
            justify-content: space-evenly;
        }
    }
    
    .navigation--footer {
        display: block;
    }
    
    .navigation__list--parents {
        display: block;
    
        @media only screen and (min-width: #{$bp-sm-min}) and (orientation: portrait) {
            display: flex;
            flex-direction: column;
            align-items: flex-end;
        }
    
        @include bp(md-min) {
            display: flex;
            flex-direction: column;
            align-items: flex-end;
        }
    
        &:after {
            .navigation--idle & {
                @include bp(md-min) {
                    content: '';
                    height: 1px;
                    background-color: $color-text-03;
                    position: absolute;
                    bottom: 1px;
                    left: 15px;
                    right: 15px;
                    width: 0;
                    transition-property: width;
                    transition-duration: $transition-duration*1.5;
                    transition-timing-function: $transition-easing-in;
                    transition-delay: $transition-duration;
                }
            }
    
            .navigation--idle.is-finished-animating & {
                visibility: hidden;
            }
    
            body.core-has-loaded &
            .navigation--idle.is-ready & {
                @include bp(md-min) {
                    width: calc(100% - 30px); /* stylelint-disable-line plugin/no-unsupported-browser-features */
                }
            }
        }
    
        .navigation--idle & {
            @include bp(md-min) {
                display: flex;
                margin: 0 -15px;
                flex-direction: row;
                align-items: flex-start;
                width: 100%;
            }
        }
    
        .navigation--footer & {
            display: flex;
            flex-direction: column;
            align-items: stretch;
    
            @include bp(md-min) {
                flex-direction: row;
                justify-content: flex-end;
                margin: 0 -28px;
            }
        }
    }
    
    .navigation__list--children {
        padding-top: 4px;
        padding-bottom: 4px;
        margin: 0;
        position: absolute;
        bottom: 0;
        left: 0;
        z-index: map-get($zindex, 'default');
        display: block;
        pointer-events: none;
    
        @include bp(sm-min) {
            right: 0;
            left: auto;
            display: flex;
            min-width: max-content; /* stylelint-disable-line plugin/no-unsupported-browser-features */
            flex-direction: column;
            align-items: flex-end;
        }
    
        .navigation--idle & {
            @include bp(md-min) {
                width: 100%;
                left: 50%;
                right: auto;
                transform: translateX(-50%);
                padding-top: 16px;
                padding-bottom: 16px;
                display: block;
                min-width: 0;
            }
        }
    
        .navigation--footer & {
            position: relative;
            bottom: auto;
            left: auto;
            right: auto;
            pointer-events: all;
            display: block;
            padding: 0;
            margin-top: 8px;
            min-width: 0;
    
            @include bp(md-min) {
                margin-top: 72px;
            }
        }
    
        .navigation__item.is-active & {
            pointer-events: all;
        }
    }
    
    .navigation__item {
        position: relative;
        opacity: 0;
        transition-property: opacity;
        transition-timing-function: $transition-easing-in;
        transition-duration: $transition-duration;
    
        .navigation--idle & {
            @include bp(md-min) {
                display: inline-block;
            }
        }
    
        .navigation--footer & {
            opacity: 1;
        }
    
        .navigation__list--parents > & {
            transition-property: opacity;
            padding: 16px 0;
    
            @media only screen and (min-width: #{$bp-sm-min}) and (orientation: portrait) {
                text-align: right;
            }
    
            @include bp(md-min) {
                text-align: right;
            }
    
            .navigation--idle & {
                @include bp(md-min) {
                    text-align: left;
                    padding: 0 0 1px;
                    flex-basis: 100%;
                }
            }
    
            .navigation--footer & {
                text-align: left;
                display: block;
                padding: 0;
    
                @include bp(md-min) {
                    display: inline-block;
                    padding: 0 28px;
                }
            }
    
            &:not(:first-child) {
                .navigation--footer & {
                    margin-top: 24px;
    
                    @include bp(md-min) {
                        margin-top: 0;
                    }
                }
            }
        }
    
        &.navigation__item--divisible-by-2 {
            .navigation__list--parents & {
                .navigation--footer & {
                    @include bp(md-min) {
                        flex: 1 1 calc(100%/2); /* stylelint-disable-line plugin/no-unsupported-browser-features */
                        max-width: calc(100%/2); /* stylelint-disable-line plugin/no-unsupported-browser-features */
                    }
                }
            }
        }
    
        &.navigation__item--divisible-by-3 {
            .navigation__list--parents & {
                .navigation--footer & {
                    @include bp(md-min) {
                        flex: 1 1 calc(100%/3); /* stylelint-disable-line plugin/no-unsupported-browser-features */
                        max-width: calc(100%/3); /* stylelint-disable-line plugin/no-unsupported-browser-features */
                    }
                }
            }
        }
    
        &.navigation__item--divisible-by-4 {
            .navigation__list--parents & {
                .navigation--footer & {
                    @include bp(md-min) {
                        flex: 1 1 calc(100%/4); /* stylelint-disable-line plugin/no-unsupported-browser-features */
                        max-width: calc(100%/4); /* stylelint-disable-line plugin/no-unsupported-browser-features */
                    }
                }
            }
        }
    
        .navigation__list--children & {
            display: block;
            position: relative;
            padding: 8px 0;
    
            .navigation--idle & {
                @include bp(md-min) {
                    padding: 0;
                }
            }
    
            .navigation--footer & {
                padding: 0;
            }
        }
    
        &.has-children {
            position: relative;
        }
    
        &:nth-child(1) {
            .navigation__item.is-active & {
                animation: setVisible $transition-duration $transition-easing 0s both;
            }
    
            body.core-has-loaded .navigation__list--parents > &,
            .header--no-description .navigation__list--parents > &,
            .navigation.is-ready .navigation__list--parents > & {
                animation: setVisible $transition-duration $transition-easing $transition-duration both;
    
                @include bp(md-min) {
                    animation: setVisible $transition-duration $transition-easing 0ms both;
                }
            }
        }
    
        &:nth-child(2) {
            .navigation__item.is-active & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*.1 both;
            }
    
            body.core-has-loaded .navigation__list--parents > &,
            .header--no-description .navigation__list--parents > &,
            .navigation.is-ready .navigation__list--parents > & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*1.2 both;
    
                @include bp(md-min) {
                    animation: setVisible $transition-duration $transition-easing $transition-duration*.1 both;
                }
            }
        }
    
        &:nth-child(3) {
            .navigation__item.is-active & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*.4 both;
            }
    
            body.core-has-loaded .navigation__list--parents > &,
            .header--no-description .navigation__list--parents > &,
            .navigation.is-ready .navigation__list--parents > & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*1.4 both;
    
                @include bp(md-min) {
                    animation: setVisible $transition-duration $transition-easing $transition-duration*.4 both;
                }
            }
        }
    
        &:nth-child(4) {
            .navigation__item.is-active & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*.7 both;
            }
    
            body.core-has-loaded .navigation__list--parents > &,
            .header--no-description .navigation__list--parents > &,
            .navigation.is-ready .navigation__list--parents > & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*1.6 both;
    
                @include bp(md-min) {
                    animation: setVisible $transition-duration $transition-easing $transition-duration*.7 both;
                }
            }
        }
    
        &:nth-child(5) {
            .navigation__item.is-active & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*1 both;
            }
    
            body.core-has-loaded .navigation__list--parents > &,
            .header--no-description .navigation__list--parents > &,
            .navigation.is-ready .navigation__list--parents > & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*1.8 both;
    
                @include bp(md-min) {
                    animation: setVisible $transition-duration $transition-easing $transition-duration*1 both;
                }
            }
        }
    
        &:nth-child(6) {
            .navigation__item.is-active & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*1.2 both;
            }
    
            body.core-has-loaded .navigation__list--parents > &,
            .header--no-description .navigation__list--parents > &,
            .navigation.is-ready .navigation__list--parents > & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*2 both;
    
                @include bp(md-min) {
                    animation: setVisible $transition-duration $transition-easing $transition-duration*1.2 both;
                }
            }
        }
    
        &:nth-child(7) {
            .navigation__item.is-active & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*1.8 both;
            }
    
            body.core-has-loaded .navigation__list--parents > &,
            .header--no-description .navigation__list--parents > &,
            .navigation.is-ready .navigation__list--parents > & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*2.2 both;
    
                @include bp(md-min) {
                    animation: setVisible $transition-duration $transition-easing $transition-duration*1.8 both;
                }
            }
        }
    
        &:nth-child(8) {
            .navigation__item.is-active & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*2.1 both;
            }
    
            body.core-has-loaded .navigation__list--parents > &,
            .header--no-description .navigation__list--parents > &,
            .navigation.is-ready .navigation__list--parents > & {
                animation: setVisible $transition-duration $transition-easing $transition-duration*2.4 both;
    
                @include bp(md-min) {
                    animation: setVisible $transition-duration $transition-easing $transition-duration*2.1 both;
                }
            }
        }
    }
    
    .navigation__link {
        position: relative;
        display: block;
        color: inherit;
        text-decoration: none;
        font-size: $font-size-h2-xs;
        line-height: $line-height-h3-xs;
        font-weight: $font-weight-medium;
    
        @include bp(sm-min) {
            transition-property: opacity;
            transition-timing-function: $transition-easing-in;
            transition-duration: $transition-duration;
        }
    
        @media only screen and (min-width: #{$bp-sm-min}) and (orientation: portrait) {
            font-size: $font-size-h2-lg;
            line-height: $line-height-h2-lg;
        }
    
        @include bp(md-min) {
            font-size: $font-size-h2-lg;
            line-height: $line-height-h2-lg;
        }
    
        .navigation--idle & {
            @include bp(md-min) {
                font-size: $font-size-tiny;
                line-height: $line-height-tiny;
                padding: 0 15px;
                display: flex;
                align-items: center;
            }
        }
    
        .navigation--footer & {
            font-size: $font-size-h3-xs;
            line-height: $line-height-h3-xs;
    
            @include bp(md-min) {
                font-size: $font-size-h3-lg;
                line-height: $line-height-h3-lg;
            }
        }
    
        .navigation__list--parents > .navigation__item > & {
            .navigation--idle & {
                @include bp(md-min) {
                    padding-bottom: 35px;
                }
            }
        }
    
        .navigation__list--children & {
            font-size: $font-size-tiny;
            line-height: $line-height-tiny;
            padding: 4px 0;
    
            @include bp(sm-min) {
                opacity: .6;
            }
    
            .navigation--footer & {
                opacity: 1;
                font-size: $font-size-small;
                line-height: $line-height-small;
                font-weight: $font-weight-regular;
                padding: 8px 0;
            }
    
            .navigation--idle & {
                @include bp(md-min) {
                    padding: 8px 15px;
                }
            }
        }
    
        &:before {
            .navigation__list--parents > .navigation__item > & {
                .navigation--idle & {
                    @include bp(md-min) {
                        content: '';
                        height: 1px;
                        background-color: $color-text-03;
                        position: absolute;
                        bottom: 0;
                        left: 0;
                        right: 0;
                        opacity: 0;
                        transition-duration: 0ms;
                        transition-property: opacity;
                        transition-delay: $transition-duration*2.6;
                    }
                }
    
                body.core-has-loaded &,
                .navigation--idle.is-ready & {
                    opacity: 1;
                }
            }
    
            .navigation__item:first-child & {
                .navigation__list--parents & {
                    left: 15px;
                }
            }
    
            .navigation__item:last-child & {
                .navigation__list--parents & {
                    right: 15px;
                }
            }
        }
    
        &:after {
            .navigation__list--parents > .navigation__item > & {
                .navigation--idle & {
                    @include bp(md-min) {
                        content: '';
                        height: 3px;
                        background-color: $color-text-03;
                        position: absolute;
                        bottom: -1px;
                        left: auto;
                        right: 15px;
                        width: 0;
                        transition-property: width, opacity;
                        transition-timing-function: $transition-easing-in;
                        transition-duration: $transition-duration;
                    }
                }
            }
    
            .navigation__item.is-current > & {
                .navigation__list--parents > & {
                    body.core-has-loaded &,
                    .navigation--idle.is-ready & {
                        @include bp(md-min) {
                            opacity: 1;
                            transition-delay: $transition-duration*1.75;
                            width: calc(100% - 30px); /* stylelint-disable-line plugin/no-unsupported-browser-features */
                            left: 15px;
                            right: auto;
                        }
                    }
                }
            }
    
            .navigation__item:hover > & {
                .navigation__list--parents > & {
                    .navigation--idle & {
                        @include bp(md-min) {
                            width: calc(100% - 30px); /* stylelint-disable-line plugin/no-unsupported-browser-features */
                            left: 15px;
                            right: auto;
                        }
                    }
                }
            }
        }
    
        .navigation__item:not(:hover) > & {
            .navigation__list--parents:hover > & {
                .navigation:not(.navigation--idle):not(.navigation--footer) & {
                    @include bp(md-min) {
                        @media (hover: hover) {
                            opacity: .6;
                            transition-timing-function: $transition-easing-out;
                        }
                    }
                }
            }
    
            .navigation__list--children:hover > & {
                .navigation--footer & {
                    @include bp(sm-min) {
                        opacity: .6;
                        transition-timing-function: $transition-easing-out;
                    }
                }
            }
        }
    
        &:hover {
            .navigation__list--children & {
                opacity: 1;
                transition-timing-function: $transition-easing-out;
            }
        }
    
        &:focus {
            html[data-whatintent='keyboard'] & {
                opacity: 1;
                transition-timing-function: $transition-easing-out;
            }
        }
    }
    
    .navigation__description {
        display: none;
        position: absolute;
        top: 60px;
        left: 0;
        pointer-events: none;
    
        .navigation--idle & {
            @include bp(md-min) {
                font-size: 14px;
                color: inherit;
                padding: 16px 15px 48px;
                opacity: 0;
                visibility: hidden;
                transition-property: visibility, opacity;
                transition-timing-function: $transition-easing-in;
                transition-duration: $transition-duration;
            }
    
            @include bp(lg-min) {
                display: block;
            }
        }
    
        .navigation__item:nth-child(1) & {
            transition-delay: $transition-duration;
        }
    
        .navigation__item:nth-child(2) & {
            transition-delay: $transition-duration*1.2;
        }
    
        .navigation__item:nth-child(3) & {
            transition-delay: $transition-duration*1.4;
        }
    
        .navigation__item:nth-child(4) & {
            transition-delay: $transition-duration*1.6;
        }
    
        .navigation__item:nth-child(5) & {
            transition-delay: $transition-duration*1.8;
        }
    
        .navigation__item:nth-child(6) & {
            transition-delay: $transition-duration*2;
        }
    
        .navigation__item:nth-child(7) & {
            transition-delay: $transition-duration*2.2;
        }
    
        .navigation__item:nth-child(8) & {
            transition-delay: $transition-duration*2.4;
        }
    
        body.core-has-loaded &,
        .navigation--idle.is-ready & {
            @include bp(md-min) {
                opacity: 1;
                visibility: visible;
                transition-timing-function: $transition-easing-out;
            }
    
            body.is-hovering-nav & {
                @include bp(md-min) {
                    opacity: 0;
                    visibility: hidden;
                    transition-timing-function: $transition-easing-out;
                    transition-delay: 0ms;
                }
            }
        }
    }
    
    .navigation__arrow-icon {
        transition-property: opacity;
        transition-timing-function: $transition-easing-in;
        transition-duration: $transition-duration;
        pointer-events: none;
        display: none;
    
        .navigation__item.is-current > & {
            .navigation__list--parents > & {
                @media only screen and (min-width: #{$bp-sm-min}) and (orientation: portrait) {
                    font-size: 54px;
                    position: absolute;
                    left: -70px;
                    top: 23px;
                    bottom: 0;
                    display: inline-block;
                }
    
                @include bp(md-min) {
                    font-size: 54px;
                    position: absolute;
                    left: -70px;
                    top: 23px;
                    bottom: 0;
                    display: inline-block;
                }
    
                .navigation--footer &,
                .navigation--idle & {
                    @include bp(md-min) {
                        display: none;
                    }
                }
            }
        }
    
        .navigation__list--children & {
            position: absolute;
            left: -25px;
            top: 12px;
            bottom: 0;
            font-size: 24px;
            opacity: 0;
            transform: translateX(-25px);
            transition-property: visibility, opacity, transform;
            transition-timing-function: $transition-easing-in;
            transition-duration: $transition-duration;
    
            @include bp(sm-min) {
                left: -32px;
                display: inline-block;
            }
    
            .navigation--idle & {
                @include bp(md-min) {
                    left: -25px;
                }
    
                @include bp(md-min) {
                    top: 8px;
                }
            }
    
            .navigation--footer & {
                display: none;
                left: -40px;
                top: 10px;
    
                @include bp(lg-min) {
                    display: inline-block;
                }
            }
        }
    
        .navigation__item:not(:hover) > & {
            .navigation__list--parents:hover > & {
                .navigation:not(.navigation--idle) & {
                    @include bp(md-min) {
                        opacity: .6;
                        transition-timing-function: $transition-easing-out;
                    }
                }
            }
        }
    
        .navigation__item:hover > & {
            .navigation__list--children & {
                transform: translateX(0);
                opacity: 1;
            }
        }
    
        .navigation__link:focus + & {
            .navigation__list--children & {
                html[data-whatintent='keyboard'] & {
                    transform: translateX(0);
                    opacity: 1;
                }
            }
        }
    }
    
    .navigation__chevron {
        display: none;
        font-size: 17px;
        margin-left: 2px;
    
        .navigation--idle & {
            @include bp(md-min) {
                display: block;
            }
        }
    }
    
    @keyframes setVisible {
        0% {
            transform: translateY(-10%);
            opacity: 0;
        }
    
        100% {
            transform: translateY(0);
            opacity: 1;
        }
    }
    
  • URL: /components/raw/navigation/navigation.scss
  • Filesystem Path: src/patterns/components/navigation/navigation.scss
  • Size: 21.8 KB
  • Content:
    import Component from '../component/component';
    import Helpers from '../helpers/helpers';
    
    import './navigation.scss';
    
    interface INavigationSettings {
        activeClass: string;
        animationSpeed: number;
        finishedClass: string;
        idleModifier: string;
        itemLinkClass: string;
        navHiddenClass: string;
        navHoverClass: string;
        readyClass: string;
    }
    
    export default class Navigation extends Component {
        static initSelector: string = '.js-navigation';
    
        public dropdownItems: JQuery;
        public dropdownLinks: JQuery;
        public initHeight: number;
        public continue: boolean;
        public body: JQuery;
        public animationDuration: number;
        public isOpen: boolean = false;
    
        settings: INavigationSettings;
    
        constructor(target: HTMLElement) {
            super(target);
    
            this.body = $('body');
    
            this.dropdownItems = this.element.find('.navigation__item.has-children');
            this.dropdownLinks = this.element.find('.navigation__list--children .navigation__link');
            this.initHeight = this.element.find('.navigation__item').first().outerHeight();
            this.continue = false;
    
            this.documentClickHandler = this.documentClickHandler.bind(this);
            this.openDropdown = this.openDropdown.bind(this);
            this.closeDropdown = this.closeDropdown.bind(this);
            this.toggleHandler = this.toggleHandler.bind(this);
    
            this.settings = {
                activeClass: 'is-active',
                animationSpeed: 250,
                finishedClass: 'is-finished-animating',
                idleModifier: 'navigation--idle',
                itemLinkClass: 'navigation__link',
                navHiddenClass: 'is-navigation-hidden',
                navHoverClass: 'is-hovering-nav',
                readyClass: 'is-ready',
            };
    
            this.init();
        }
    
        init(): void {
            setTimeout(() => {
                this.element.addClass(this.settings.readyClass);
            }, 250);
    
            setTimeout(() => {
                this.element.addClass(this.settings.finishedClass);
            }, 950);
    
            this.setAnimationSpeed();
    
            this.element.on('keyup.navigation', this.keyboardHandler.bind(this));
    
            this.addTriggerListeners();
            this.addFocusListener();
    
            $(window).on('resize', this.resizeHandler.bind(this));
    
            $(window).off('scroll', this.scrollHandler.bind(this));
            $(window).on('scroll', this.scrollHandler.bind(this));
        }
    
        setAnimationSpeed(): void {
            if ($(window).innerWidth() < Helpers.bp.md || this.body.hasClass(this.settings.navHiddenClass)) {
                this.animationDuration = this.settings.animationSpeed;
            } else {
                this.animationDuration = 5;
            }
        }
    
        scrollHandler(): void {
            setTimeout(() => {
                this.setAnimationSpeed();
            }, 100);
            this.addFocusListener();
        }
    
        resizeHandler(): void {
            this.closeDropdown();
            this.setIniHeights();
            this.setAnimationSpeed();
        }
    
        addFocusListener(): void {
            this.dropdownLinks.off('focus', this.sublinkFocusHandler.bind(this));
            this.dropdownLinks.off('blur', this.sublinkBlurHandler.bind(this));
    
            this.dropdownLinks.on('focus', this.sublinkFocusHandler.bind(this));
            this.dropdownLinks.on('blur', this.sublinkBlurHandler.bind(this));
        }
    
        addMouseListeners(): void {
            this.dropdownItems.on('mouseenter', this.openDropdown);
            this.dropdownItems.on('mouseleave', this.closeDropdown);
        }
    
        removeMouseListeners(): void {
            this.dropdownItems.off('mouseenter', this.openDropdown);
            this.dropdownItems.off('mouseleave', this.closeDropdown);
        }
    
        addClickListeners(): void {
            this.dropdownItems.children('.' + this.settings.itemLinkClass).on('click', this.toggleHandler);
        }
    
        removeClickListeners(): void {
            this.dropdownItems.children('.' + this.settings.itemLinkClass).off('click', this.toggleHandler);
        }
    
        toggleHandler(): void {
            event.preventDefault();
            this.toggleDropdown(event);
        }
    
        addEventListeners(): void {
            $(document).on('click.navigation', this.documentClickHandler);
        }
    
        addTriggerListeners(): void {
            if ($(window).width() < Helpers.bp.lg && Helpers.isMobileDevice || $(window).width() <= Helpers.bp.sm) {
                this.removeMouseListeners();
                this.addClickListeners();
            } else {
                this.addMouseListeners();
                this.removeClickListeners();
            }
        }
    
        sublinkFocusHandler(event: JQuery.TriggeredEvent): void {
            const targetElement: JQuery = $(event.currentTarget);
            const parentElement: JQuery = $(targetElement.closest('.navigation__item.has-children'));
            const inputDevice: string = $('html').attr('data-whatintent');
    
            if (inputDevice === 'keyboard' && !parentElement.hasClass(this.settings.activeClass)) {
                this.openDropdown();
            }
        }
    
        sublinkBlurHandler(): void {
            setTimeout(() => {
                const isSublinkFocused: JQuery = $('.navigation__list--children .navigation__link:focus');
    
                // avoid closing the dropdown if focus moved to another sublink
                if (!isSublinkFocused.length) {
                    this.closeDropdown();
                }
            }, 1);
        }
    
        documentClickHandler(event: JQuery.TriggeredEvent): void {
            if ($(event.target).closest(this.element.find('.navigation__list')).length === 0) {
                this.closeDropdown();
            }
        }
    
        setIniHeights(): void {
            this.dropdownItems.removeAttr('style');
            this.dropdownItems.each((index: number, element: HTMLElement) => {
                $(element).css({
                    height: $(element).outerHeight(),
                });
            });
        }
    
        toggleDropdown(event: Event): void {
            const previousOpen: JQuery = this.dropdownItems.filter('.' + this.settings.activeClass);
            const parentElement: JQuery = $(event.currentTarget).closest('.navigation__item') as JQuery;
    
            if (parentElement.hasClass(this.settings.activeClass)) {
                this.animateClose(parentElement);
                this.continue = true;
            }
    
            // Continue if there is nothing to close
            if (this.continue) {
                if (!parentElement.hasClass(this.settings.activeClass)) {
                    this.animateOpen(parentElement);
                    this.continue = false;
                } else {
                    this.animateClose(previousOpen);
                    this.continue = true;
                }
            } else {
                this.animateClose(previousOpen);
            }
        }
    
        open(menuItem: JQuery): void {
            menuItem.addClass(this.settings.activeClass);
            menuItem.children('.' + this.settings.itemLinkClass).attr('aria-expanded', 'true');
    
            this.addEventListeners();
        }
    
        animateOpen(parentElement: JQuery): void {
            const parentHeight: number = parentElement.outerHeight();
            const dropdownHeight: number = parentElement.find('.navigation__list').outerHeight();
    
            const calculatedHeight: number = parentHeight + dropdownHeight;
    
            if (parentElement.is(':animated')) {
                return;
            }
    
            this.body.addClass(this.settings.navHoverClass);
    
            this.initHeight = parentElement.outerHeight();
    
            parentElement.stop().animate({
                height: calculatedHeight,
            }, this.animationDuration, (): void => {
                this.open(parentElement);
            }).css('overflow', 'visible');
        }
    
        openDropdown(): void {
            if (!this.isOpen) {
                const parentElement: JQuery = $(event.currentTarget).closest('.navigation__item.has-children') as JQuery;
    
                this.animateOpen(parentElement);
                this.isOpen = true;
            }
        }
    
        closeDropdown(): void {
            if (this.isOpen) {
                this.animateClose($('.navigation__item.is-active') as JQuery);
    
                this.isOpen = false;
            }
        }
    
        close(): void {
            const currentActiveItem: JQuery = this.dropdownItems.filter('.' + this.settings.activeClass);
    
            currentActiveItem.removeClass(this.settings.activeClass);
            currentActiveItem.children('.' + this.settings.itemLinkClass).attr('aria-expanded', 'false');
            this.continue = true;
    
            this.destroy();
        }
    
        animateClose(current: JQuery): void {
            const currentActiveItem: JQuery = current;
    
            this.body.removeClass(this.settings.navHoverClass);
    
            if (currentActiveItem) {
                this.close();
    
                currentActiveItem.stop().animate({
                    height: this.initHeight,
                }, this.animationDuration).css('overflow', 'visible');
            }
        }
    
        keyboardHandler(event: KeyboardEvent): void {
            if (event.key === 'Escape') {
                this.close();
            }
        }
    
        destroy(): void {
            $(document).off('click.navigation', this.documentClickHandler);
        }
    }
    
    
  • URL: /components/raw/navigation/navigation.ts
  • Filesystem Path: src/patterns/components/navigation/navigation.ts
  • Size: 8.9 KB
  • Handle: @navigation--desktop-drawer
  • Filesystem Path: src/patterns/components/navigation/navigation.twig
  • References (1): @icon

Footer