<nav class="rtds-side-navigation " aria-labelledby="sidebarLabel" id="sideNav">

    <span id="sidebarLabel" class="rtds-side-navigation__title rtds-sr-only md:rtds-not-sr-only md:rtds-pb-4 md:rtds-border-b md:rtds-border-gray-01">
        <span class="rtds-side-navigation__label-context">Titolo della sezione</span>
        <span class="rtds-block rtds-font-medium">Indice della sezione</span>
    </span>

    <button class="rtds-side-navigation__list-toggle rtds-nav-list-toggle md:rtds-hidden rtds-btn rtds-btn--icon-right rtds-btn--only-text rtds-btn--small rtds-group" aria-expanded="false" aria-controls="sideNavList">
        <span class="rtds-grid rtds-gap-2 rtds-text-left">

            <span class="rtds-side-navigation__label-context">Titolo della sezione</span>

            <span>Indice della sezione</span>
        </span>
        <svg class="rtds-icon rtds-fill-current rtds-w-5 rtds-h-5" aria-hidden="true" focusable="false" role="img">
            <use href="../../icons.svg#mini--chevron-up" />
        </svg>

    </button>
    <ul class="rtds-nav-list rtds-side-navigation__list has-nav-dropdown" id="sideNavList">

        <li class="rtds-side-navigation__item is-first-level is-current-trail">
            <div class="rtds-flex rtds-items-center rtds-justify-between rtds-pb-2">
                <a href="#" class="rtds-side-navigation__link rtds-nav-link rtds-font-bold rtds-text-lg is-current rtds-content-primary" aria-current="page">
                    <span class="rtds-side-navigation__label">

                        Current trail and current page
                    </span>
                </a>

                <button class="rtds-side-navigation__nav-toggle rtds-nav-toggle rtds-group rtds-ml-2 is-current rtds-content-primary" aria-expanded="true" aria-controls="sideNav-subnav-1">
                    <span class="rtds-sr-only">Dettaglio Current trail and current page</span>

                    <svg class="rtds-icon rtds-fill-current rtds-w-6 rtds-h-6 rtds-transition-all rtds-duration-200 rtds-ease-out group-aria-expanded:rtds-rotate-180" aria-hidden="true" focusable="false" role="img">
                        <use href="../../icons.svg#mini--chevron-down" />
                    </svg>

                </button>

            </div>

            <ul class="rtds-side-navigation__submenu rtds-block rtds-w-full rtds-pl-4" id="sideNav-subnav-1">

                <li class="rtds-side-navigation__item rtds-py-1">

                    <span class="rtds-side-navigation__second-level-label is-current rtds-flex rtds-items-center rtds-justify-between">
                        <a href="" class="rtds-side-navigation__link rtds-nav-link rtds-flex-grow rtds-font-bold rtds-text-base is-current rtds-content-primary" aria-current="page">
                            <span class="rtds-side-navigation__label">Subitem 2</span>
                        </a>
                        <button class="rtds-side-navigation__nav-toggle rtds-nav-toggle rtds-group rtds-ml-2 is-current rtds-content-primary" aria-expanded="false" aria-controls="sideNav-subsubnav--1">
                            <span class="rtds-sr-only">Dettaglio Subitem 2</span>
                            <svg class="rtds-icon rtds-fill-current rtds-w-6 rtds-h-6 rtds-transition-all rtds-duration-200 rtds-ease-out group-aria-expanded:rtds-rotate-180" aria-hidden="true" focusable="false" role="img">
                                <use href="../../icons.svg#mini--chevron-down" />
                            </svg>

                        </button>
                    </span>
                    <ul class="rtds-side-navigation__sub-submenu rtds-hidden rtds-w-full rtds-pl-4 rtds-space-y-2 rtds-mt-2" id="sideNav-subsubnav--1">

                        <li class="rtds-side-navigation__item">
                            <a href="" class="rtds-side-navigation__link rtds-nav-link rtds-pl-4 rtds-pt-0 rtds-pb-0  rtds-text-base rtds-content-03 ">
                                <span class="rtds-side-navigation__label">Sub-submenu</span>
                            </a>
                        </li>

                        <li class="rtds-side-navigation__item">
                            <a href="" class="rtds-side-navigation__link rtds-nav-link rtds-pl-4 rtds-pt-0 rtds-pb-0  rtds-text-base rtds-content-03 ">
                                <span class="rtds-side-navigation__label">sub-submenu 2</span>
                            </a>
                        </li>

                    </ul>

                </li>

            </ul>

        </li>

        <li class="rtds-side-navigation__item is-first-level is-current-trail">
            <div class="rtds-flex rtds-items-center rtds-justify-between rtds-pb-2">
                <a href="#" class="rtds-side-navigation__link rtds-nav-link rtds-font-bold rtds-text-lg">
                    <span class="rtds-side-navigation__label">

                        Current trail
                    </span>
                </a>

                <button class="rtds-side-navigation__nav-toggle rtds-nav-toggle rtds-group rtds-ml-2" aria-expanded="true" aria-controls="sideNav-subnav-2">
                    <span class="rtds-sr-only">Dettaglio Current trail</span>

                    <svg class="rtds-icon rtds-fill-current rtds-w-6 rtds-h-6 rtds-transition-all rtds-duration-200 rtds-ease-out group-aria-expanded:rtds-rotate-180" aria-hidden="true" focusable="false" role="img">
                        <use href="../../icons.svg#mini--chevron-down" />
                    </svg>

                </button>

            </div>

            <ul class="rtds-side-navigation__submenu rtds-block rtds-w-full rtds-pl-4" id="sideNav-subnav-2">

                <li class="rtds-side-navigation__item rtds-py-1">

                    <a href="" class="rtds-side-navigation__link rtds-nav-link rtds-font-bold rtds-text-base is-current rtds-content-primary " aria-current="page">
                        <span class="rtds-side-navigation__label">Subitem 1 current page</span>
                    </a>

                </li>

            </ul>

        </li>

        <li class="rtds-side-navigation__item is-first-level">
            <div class="rtds-flex rtds-items-center rtds-justify-between rtds-pb-2">
                <a href="#" class="rtds-side-navigation__link rtds-nav-link rtds-font-bold rtds-text-lg">
                    <span class="rtds-side-navigation__label">

                        Item 3
                    </span>
                </a>

                <button class="rtds-side-navigation__nav-toggle rtds-nav-toggle rtds-group rtds-ml-2" aria-expanded="false" aria-controls="sideNav-subnav-3">
                    <span class="rtds-sr-only">Dettaglio Item 3</span>

                    <svg class="rtds-icon rtds-fill-current rtds-w-6 rtds-h-6 rtds-transition-all rtds-duration-200 rtds-ease-out group-aria-expanded:rtds-rotate-180" aria-hidden="true" focusable="false" role="img">
                        <use href="../../icons.svg#mini--chevron-down" />
                    </svg>

                </button>

            </div>

            <ul class="rtds-side-navigation__submenu rtds-hidden rtds-w-full rtds-pl-4" id="sideNav-subnav-3">

                <li class="rtds-side-navigation__item rtds-py-1">

                    <a href="" class="rtds-side-navigation__link rtds-nav-link rtds-font-bold rtds-text-base">
                        <span class="rtds-side-navigation__label">Subitem 2</span>
                    </a>

                </li>

                <li class="rtds-side-navigation__item rtds-py-1">

                    <a href="" class="rtds-side-navigation__link rtds-nav-link rtds-font-bold rtds-text-base">
                        <span class="rtds-side-navigation__label">Item 4</span>
                    </a>

                </li>

                <li class="rtds-side-navigation__item rtds-py-1">

                    <span class="rtds-side-navigation__second-level-label rtds-flex rtds-items-center rtds-justify-between">
                        <a href="" class="rtds-side-navigation__link rtds-nav-link rtds-flex-grow rtds-font-bold rtds-text-base">
                            <span class="rtds-side-navigation__label">Item 5</span>
                        </a>
                        <button class="rtds-side-navigation__nav-toggle rtds-nav-toggle rtds-group rtds-ml-2" aria-expanded="false" aria-controls="sideNav-subsubnav--3">
                            <span class="rtds-sr-only">Dettaglio Item 5</span>
                            <svg class="rtds-icon rtds-fill-current rtds-w-6 rtds-h-6 rtds-transition-all rtds-duration-200 rtds-ease-out group-aria-expanded:rtds-rotate-180" aria-hidden="true" focusable="false" role="img">
                                <use href="../../icons.svg#mini--chevron-down" />
                            </svg>

                        </button>
                    </span>
                    <ul class="rtds-side-navigation__sub-submenu rtds-hidden rtds-w-full rtds-pl-4 rtds-space-y-2 rtds-mt-2" id="sideNav-subsubnav--3">

                        <li class="rtds-side-navigation__item">
                            <a href="" class="rtds-side-navigation__link rtds-nav-link rtds-pl-4 rtds-pt-0 rtds-pb-0  rtds-text-base rtds-content-03 ">
                                <span class="rtds-side-navigation__label">Sub-submenu</span>
                            </a>
                        </li>

                        <li class="rtds-side-navigation__item">
                            <a href="" class="rtds-side-navigation__link rtds-nav-link rtds-pl-4 rtds-pt-0 rtds-pb-0  rtds-text-base rtds-content-03 ">
                                <span class="rtds-side-navigation__label">sub-submenu 2</span>
                            </a>
                        </li>

                    </ul>

                </li>

            </ul>

        </li>

        <li class="rtds-side-navigation__item is-first-level">
            <div class="rtds-flex rtds-items-center rtds-justify-between rtds-pb-2">
                <a href="#" class="rtds-side-navigation__link rtds-nav-link rtds-font-bold rtds-text-lg">
                    <span class="rtds-side-navigation__label">

                        Item 4
                    </span>
                </a>

            </div>

        </li>

    </ul>
</nav>
<nav class="rtds-side-navigation{% block classes %} {% if classes %}{{ classes }}{% endif %}{% endblock %}" aria-labelledby="{{ labelId }}"{% if id %} id="{{ id }}"{% endif %}{% block attributes %}{% endblock %}>
  
  <span id="{{ labelId }}" class="rtds-side-navigation__title{% if hiddenLabel %} rtds-sr-only{% else %} rtds-sr-only md:rtds-not-sr-only md:rtds-pb-4 md:rtds-border-b md:rtds-border-gray-01{% endif %}">
    {% if labelContext %}<span class="rtds-side-navigation__label-context">{{ labelContext | safe }}</span>{% endif %}
    <span class="rtds-block rtds-font-medium">{{ label | safe }}</span>
  </span>

  <button class="rtds-side-navigation__list-toggle rtds-nav-list-toggle md:rtds-hidden rtds-btn rtds-btn--icon-right rtds-btn--only-text rtds-btn--small rtds-group" aria-expanded="false" aria-controls="{{ listId }}">
    <span class="rtds-grid rtds-gap-2 rtds-text-left">
      {% if labelContext %}
        <span class="rtds-side-navigation__label-context">{{ labelContext | safe }}</span>
      {% endif %}
      <span>{{ label | safe }}</span>
    </span>
    {% render '@icon--small', { id: 'mini--chevron-up', size: 'rtds-w-5 rtds-h-5' }, true %}
  </button>
  <ul class="rtds-nav-list rtds-side-navigation__list has-nav-dropdown" id="{{ listId }}">
    {% for firstLevel in firstLevels %}
      <li class="rtds-side-navigation__item is-first-level{% if itemClasses %} {{ itemClasses }}{% endif %}{% if firstLevel.isCurrentTrail %} is-current-trail{% endif %}">
        <div class="rtds-flex rtds-items-center rtds-justify-between rtds-pb-2">
          <a href="{% if firstLevel.href %}{{ firstLevel.href }}{% else %}#{% endif %}" class="rtds-side-navigation__link rtds-nav-link rtds-font-bold rtds-text-lg{% if firstLevelLinkClasses %} {{ firstLevelLinkClasses }}{% endif %}{% if firstLevel.isCurrentPage %} is-current rtds-content-primary{% endif %}"{% if firstLevel.isCurrentPage and not singlePage %} aria-current="page"{% endif %}>
            <span class="rtds-side-navigation__label">
            {% if firstLevel.iconLeft %}
              {% render '@icon--small', { id: firstLevel.iconLeft, size: 'rtds-w-6 rtds-h-6' }, true %}
            {% endif %}
            {{ firstLevel.label }}
            </span>
          </a>
          
          {% if firstLevel.subItems %}
          <button
            class="rtds-side-navigation__nav-toggle rtds-nav-toggle rtds-group rtds-ml-2{% if firstLevel.isCurrentPage %} is-current{% endif %}{% if firstLevel.isCurrentPage %} rtds-content-primary{% endif %}"
            aria-expanded="{% if firstLevel.isCurrentTrail %}true{% else %}false{% endif %}"
            aria-controls="{{ id }}-subnav-{{ loop.index }}"
          >
            <span class="rtds-sr-only">Dettaglio {{ firstLevel.label }}</span>
            {% set buttonIcon = "" %}
            {% if firstLevel.iconRight %}
             {% set buttonIcon = firstLevel.iconRight %}
            {% else %}
             {% set buttonIcon = "mini--chevron-down" %}
            {% endif %}
            {% render '@icon--small', { id: buttonIcon, classes: 'rtds-transition-all rtds-duration-200 rtds-ease-out group-aria-expanded:rtds-rotate-180', size: 'rtds-w-6 rtds-h-6' }, true %}
          </button>
          {% endif %}
        </div>

        {% if firstLevel.subItems %}
        <ul class="rtds-side-navigation__submenu{% if firstLevel.isCurrentTrail %} rtds-block{% else %} rtds-hidden{% endif %} rtds-w-full rtds-pl-4{% if subnavClasses %} {{ subnavClasses }}{% endif %}" id="{{ id }}-subnav-{{ loop.index }}">
          {% for item in firstLevel.subItems %}
            <li class="rtds-side-navigation__item{% if item.isCurrentTrail %} is-current-trail{% endif %} rtds-py-1">
              {% if item.subSubItems %}
                <span class="rtds-side-navigation__second-level-label{% if item.isCurrentPage %} is-current{% endif %} rtds-flex rtds-items-center rtds-justify-between">
                  <a href="" class="rtds-side-navigation__link rtds-nav-link rtds-flex-grow rtds-font-bold rtds-text-base{% if subnavLinkClasses %} {{ subnavLinkClasses }}{% endif %}{% if item.isCurrentPage %} is-current rtds-content-primary{% endif %}"{% if item.isCurrentPage %} aria-current="page"{% endif %}>
                    <span class="rtds-side-navigation__label">{{ item.subitemLabel }}</span>
                  </a>
                  <button
                    class="rtds-side-navigation__nav-toggle rtds-nav-toggle rtds-group rtds-ml-2{% if item.isCurrentPage %} is-current{% endif %}{% if item.isCurrentPage %} rtds-content-primary{% endif %}"
                    aria-expanded="{% if item.isCurrentTrail %}true{% else %}false{% endif %}"
                    aria-controls="{{ id }}-subsubnav-{{ loop.parent.loop.index }}-{{ loop.index }}"
                  >
                    <span class="rtds-sr-only">Dettaglio {{ item.subitemLabel }}</span>
                    {% render '@icon--small', { id: 'mini--chevron-down', classes: 'rtds-transition-all rtds-duration-200 rtds-ease-out group-aria-expanded:rtds-rotate-180', size: 'rtds-w-6 rtds-h-6' }, true %}
                  </button>
                </span>
                <ul class="rtds-side-navigation__sub-submenu{% if item.isCurrentTrail %} rtds-block{% else %} rtds-hidden{% endif %} rtds-w-full rtds-pl-4 rtds-space-y-2 rtds-mt-2" id="{{ id }}-subsubnav-{{ loop.parent.loop.index }}-{{ loop.index }}">
                  {% for subSubItem in item.subSubItems %}
                    <li class="rtds-side-navigation__item">
                      <a href="" class="rtds-side-navigation__link rtds-nav-link rtds-pl-4 rtds-pt-0 rtds-pb-0  rtds-text-base rtds-content-03 {% if subSubItem.isCurrentPage %} rtds-content-primary is-current{% endif %}"{% if subSubItem.isCurrentPage %} aria-current="page"{% endif %}>
                        <span class="rtds-side-navigation__label">{{ subSubItem.label }}</span>
                      </a>
                    </li>
                  {% endfor %}
                </ul>
              {% else %}
                <a href="" class="rtds-side-navigation__link rtds-nav-link rtds-font-bold rtds-text-base{% if subnavLinkClasses %} {{ subnavLinkClasses }}{% endif %}{% if item.isCurrentPage %} is-current rtds-content-primary {% endif %}"{% if item.isCurrentPage %} aria-current="page"{% endif %}>
                  <span class="rtds-side-navigation__label">{{ item.subitemLabel }}</span>
                </a>
              {% endif %}
            </li>
          {% endfor %}
        </ul>
        {% endif %}
      </li>
    {% endfor %}
  </ul>
</nav>
{
  "label": "Indice della sezione",
  "labelId": "sidebarLabel",
  "id": "sideNav",
  "listId": "sideNavList",
  "firstLevels": [
    {
      "label": "Current trail and current page",
      "isCurrentTrail": true,
      "isCurrentPage": true,
      "subItems": [
        {
          "subitemLabel": "Subitem 2",
          "isCurrentPage": true,
          "subSubItems": [
            {
              "label": "Sub-submenu"
            },
            {
              "label": "sub-submenu 2"
            }
          ]
        }
      ]
    },
    {
      "label": "Current trail",
      "isCurrentTrail": true,
      "subItems": [
        {
          "subitemLabel": "Subitem 1 current page",
          "isCurrentPage": true
        }
      ]
    },
    {
      "label": "Item 3",
      "subItems": [
        {
          "subitemLabel": "Subitem 2"
        },
        {
          "subitemLabel": "Item 4"
        },
        {
          "subitemLabel": "Item 5",
          "subSubItems": [
            {
              "label": "Sub-submenu"
            },
            {
              "label": "sub-submenu 2"
            }
          ]
        }
      ]
    },
    {
      "label": "Item 4"
    }
  ],
  "labelContext": "Titolo della sezione"
}
  • Content:
    /**
     * SIDE NAVIGATION
     * Supporta sia vertical che horizontal tramite modifier class
     */
    /* ============================================
           BASE STYLES - Common to all layouts
           ============================================ */
    .rtds-side-navigation__title {
        gap: var(--spacing-3);
        font-size: var(--fontsize-text-base);
            color: var(--color-content-03);
        display: grid;
        font-weight: 700;
    }
    .rtds-side-navigation__label-context {
        font-family: var(--fontfamily-sans), sans-serif;
        font-size: var(--fontsize-text-lg);
        font-weight: 700;
    }
    @media (min-width: 1024px) {
        .rtds-side-navigation__label-context {
            font-size: var(--fontsize-text-xl);
        }
    }
    @media (min-width: 1280px) {
        .rtds-side-navigation__label-context {
            font-size: var(--fontsize-text-xl);
        }
    }
    @media (min-width: 1536px) {
        .rtds-side-navigation__label-context {
            font-size: var(--fontsize-text-xl);
        }
    }
    .rtds-side-navigation__label-context {
        display: block;
            color: var(--color-content-01);
        font-family: var(--fontfamily-sans), sans-serif;
        font-size: var(--fontsize-text-lg);
        font-weight: 700;
    }
    @media (min-width: 1024px) {
        .rtds-side-navigation__label-context {
            font-size: var(--fontsize-text-xl);
        }
    }
    @media (min-width: 1280px) {
        .rtds-side-navigation__label-context {
            font-size: var(--fontsize-text-xl);
        }
    }
    @media (min-width: 1536px) {
        .rtds-side-navigation__label-context {
            font-size: var(--fontsize-text-xl);
        }
    }
    @media (min-width: 768px) {
        .rtds-side-navigation__label-context {
            font-size: var(--fontsize-text-xl);
        }
    }
    @media (min-width: 1024px) {
        .rtds-side-navigation__label-context {
            font-size: var(--fontsize-text-2xl);
        }
    }
    .rtds-side-navigation__item {
        flex-wrap: wrap;
        align-items: stretch;
        --tw-bg-opacity: 1;
        background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
        font-size: var(--fontsize-text-base);
            color: var(--color-content-03);
        display: flex;
    }
    .rtds-side-navigation__first-level-label {
        flex: 1 1 0%;
        display: flex;
        font-weight: 700;
    }
    .rtds-side-navigation__link {
        flex: 1 1 0%;
        border-color: transparent;
        padding: var(--spacing-4);
        color: currentColor;
        transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
        transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
        transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
        transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
        transition-duration: 150ms;
        display: flex;
        align-items: center;
        gap: var(--spacing-2);
    }
    .rtds-side-navigation__link:hover {
        text-decoration-line: underline;
            color: var(--color-content-primary);
    }
    .rtds-side-navigation__label {
        display: inline-block;
    }
    .rtds-side-navigation__link:where(.is-current) {
        border-color: currentColor;
            color: var(--color-content-primary);
    }
    :where(.rtds-side-navigation__link.is-current) .rtds-side-navigation__label {
        border-bottom-width: 2px;
        border-color: currentColor;
        padding-bottom: var(--spacing-1);
    }
    .rtds-side-navigation__nav-toggle {
        width: var(--spacing-8);
        display: flex;
        justify-content: center;
        align-items: center;
    }
    .rtds-side-navigation__nav-toggle:hover {
            color: var(--color-content-primary);
        }
    /* MOBILE */
    .rtds-side-navigation__list-toggle {
        width: 100%;
        align-items: flex-end;
        justify-content: space-between;
        border-radius: 0px;
        border-top-width: 0px;
        border-left-width: 0px;
        border-right-width: 0px;
        border-bottom-width: 1px;
        padding-left: var(--spacing-0);
        font-size: var(--fontsize-text-sm);
        font-weight: 500;
            color: var(--color-content-03);
            border-color: var(--color-border-gray-01);
    }
    .rtds-side-navigation__list-toggle:hover {
        --tw-bg-opacity: 1;
        background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
            border-color: var(--color-border-gray-02);
    }
    .rtds-side-navigation__list-toggle:focus {
        --tw-bg-opacity: 1;
        background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
    }
    @media (min-width: 768px) {
        .rtds-side-navigation__list-toggle {
            font-size: var(--fontsize-text-base);
        }
    }
    .rtds-side-navigation__list-toggle:where([aria-expanded="false"]) .rtds-icon {
        --tw-rotate: -180deg;
        transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
    }
    .rtds-side-navigation__list-toggle:where([aria-expanded="false"]) ~ .rtds-side-navigation__list {
        display: none;
    }
    @media (min-width: 768px) {
        .rtds-side-navigation__list-toggle:where([aria-expanded="false"]) ~ .rtds-side-navigation__list {
            display: block;
        }
    }
    /* sub-navigation */
    .rtds-side-navigation__submenu {
        padding-left: var(--spacing-4);
    }
    /* ============================================
           HORIZONTAL MODIFIER - Layout orizzontale da MD
           ============================================ */
    .rtds-side-navigation--horizontal {
            @media (min-width: 768px) {
                /* Title nascosto per horizontal */
                .rtds-side-navigation__title {
                position: absolute;
                width: 1px;
                height: 1px;
                padding: 0;
                margin: -1px;
                overflow: hidden;
                clip: rect(0, 0, 0, 0);
                white-space: nowrap;
                border-width: 0;
            }
    
        
        .rtds-article-body  .rtds-side-navigation__title + * {
                margin-top: var(--spacing-0);
            }
    .rtds-side-navigation__title {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border-width: 0;
    }
    
                /* Lista: flex horizontal */
                .rtds-side-navigation__list {
                display: flex;
            }
                .rtds-side-navigation__list {
                flex-wrap: wrap;
            }
                .rtds-side-navigation__list {
                gap: var(--spacing-0);
            }
                .rtds-side-navigation__list {
                border-top-width: 0px;
            }
                .rtds-side-navigation__list {
                padding-top: var(--spacing-4);
                padding-bottom: var(--spacing-4);
            }
    .rtds-side-navigation__list {
        display: flex;
    }
    
                /* Items: no wrap, posizione relativa */
                .rtds-side-navigation__item {
                position: relative;
            }
                .rtds-side-navigation__item {
                flex-wrap: nowrap;
            }
    
                /* First level label: inline con toggle */
                .rtds-side-navigation__first-level-label {
                display: flex;
            }
                .rtds-side-navigation__first-level-label {
                align-items: center;
            }
    .rtds-side-navigation__first-level-label {
        display: flex;
    }
    .rtds-side-navigation__first-level-label {
        align-items: center;
    }
    
                /* Link: padding ridotto, border-bottom, no underline */
                .rtds-side-navigation__link {
                margin-left: var(--spacing-4);
                margin-right: var(--spacing-4);
            }
                .rtds-side-navigation__link {
                border-bottom-width: 2px;
            }
                .rtds-side-navigation__link {
                border-color: transparent;
            }
                .rtds-side-navigation__link {
                padding-left: var(--spacing-2);
                padding-right: var(--spacing-2);
            }
                .rtds-side-navigation__link {
                padding-top: var(--spacing-0);
                padding-bottom: var(--spacing-0);
            }
                .rtds-side-navigation__link {
                font-size: var(--fontsize-text-sm);
            }
                .rtds-side-navigation__link {
                font-weight: 600;
            }
                .rtds-side-navigation__link:hover {
                text-decoration-line: none;
            }
    
        .rtds-side-navigation__link:hover {
            border-color: var(--color-border-primary);
        }
                @media (min-width: 768px) {
                .rtds-side-navigation__link {
                    font-size: var(--fontsize-text-base);
                }
            }
    
        .rtds-side-navigation__link:where(.is-current) {
            color: var(--color-content-primary);
        }
    
        .rtds-side-navigation__link:where(.is-current) {
            border-color: var(--color-border-primary);
        }
    
                :where(.rtds-side-navigation__link.is-current) .rtds-side-navigation__label {
                border-bottom-width: 0px;
            }
    
                :where(.rtds-side-navigation__link.is-current) .rtds-side-navigation__label {
                padding-bottom: var(--spacing-0);
            }
    
                /* Toggle button per horizontal */
                .rtds-side-navigation__nav-toggle {
                width: auto;
            }
                .rtds-side-navigation__nav-toggle {
                padding-left: var(--spacing-2);
                padding-right: var(--spacing-2);
            }
                .rtds-side-navigation__nav-toggle {
                padding-top: var(--spacing-2);
                padding-bottom: var(--spacing-2);
            }
    
                /* Submenu: dropdown assoluto */
                .rtds-side-navigation__submenu {
                position: absolute;
            }
                .rtds-side-navigation__submenu {
                top: 100%;
            }
                .rtds-side-navigation__submenu {
                left: var(--spacing-0);
            }
                .rtds-side-navigation__submenu {
                z-index: 10;
            }
                .rtds-side-navigation__submenu {
                min-width: 200px;
            }
                .rtds-side-navigation__submenu {
                border-width: 1px;
            }
                .rtds-side-navigation__submenu {
                --tw-bg-opacity: 1;
                background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
            }
                .rtds-side-navigation__submenu {
                padding-left: var(--spacing-0);
            }
                .rtds-side-navigation__submenu {
                --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
                --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
                box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
            }
        .rtds-side-navigation__submenu {
            border-color: var(--color-border-gray-01);
        }
    .rtds-side-navigation__submenu {
        border-width: 1px;
    }
    
                /* Submenu items */
                .rtds-side-navigation__submenu .rtds-side-navigation__item {
                width: 100%;
            }
                .rtds-side-navigation__submenu .rtds-side-navigation__item {
                flex-wrap: wrap;
            }
    
                /* Submenu links con hover background */
                .rtds-side-navigation__submenu .rtds-side-navigation__link {
                margin-left: var(--spacing-0);
                margin-right: var(--spacing-0);
            }
                .rtds-side-navigation__submenu .rtds-side-navigation__link {
                border-bottom-width: 0px;
            }
                .rtds-side-navigation__submenu .rtds-side-navigation__link {
                padding-left: var(--spacing-6);
                padding-right: var(--spacing-6);
            }
                .rtds-side-navigation__submenu .rtds-side-navigation__link {
                padding-top: var(--spacing-3);
                padding-bottom: var(--spacing-3);
            }
                .rtds-side-navigation__submenu .rtds-side-navigation__link {
                font-size: var(--fontsize-text-sm);
            }
    .rtds-side-navigation__submenu .rtds-side-navigation__link {
        padding-top: var(--spacing-3);
        padding-bottom: var(--spacing-3);
    }
                .rtds-side-navigation__submenu .rtds-side-navigation__link:hover {
                border-color: transparent;
            }
        .rtds-side-navigation__submenu .rtds-side-navigation__link:hover {
            background-color: var(--color-background-01);
        }
    
                /* Submenu link corrente con background */
                .rtds-side-navigation__submenu .rtds-side-navigation__link:where(.is-current) {
                border-color: transparent;
            }
                .rtds-side-navigation__submenu .rtds-side-navigation__link:where(.is-current) {
                font-weight: 500;
            }
    
        .rtds-side-navigation__submenu .rtds-side-navigation__link:where(.is-current) {
            background-color: var(--color-background-02);
        }
    
                .rtds-side-navigation__submenu .rtds-side-navigation__link:where(.is-current) .rtds-side-navigation__label {
                border-bottom-width: 0px;
            }
            }
        }
    /* ============================================
           ANCHOR NAVIGATION
           ============================================ */
    .rtds-side-navigation--anchor {
        scroll-margin: var(--header-height);
    }
    @media (min-width: 768px) {
        .rtds-side-navigation--anchor {
            scroll-margin: var(--spacing-0);
        }
    }
    :where(.rtds-side-navigation--anchor) .rtds-side-navigation__link {
        border-bottom-width: 0px;
        border-left-width: 4px;
    }
    :where(.rtds-side-navigation--anchor .rtds-side-navigation__link.is-current) .rtds-side-navigation__label {
        border-bottom-width: 0px;
        padding-bottom: var(--spacing-0);
    }
    /* Anchor + horizontal: usa border-bottom */
    .rtds-side-navigation--anchor.rtds-side-navigation--horizontal {
            @media (min-width: 768px) {
                :where(.rtds-side-navigation__link) {
                border-left-width: 0px;
            }
                :where(.rtds-side-navigation__link) {
                border-bottom-width: 2px;
            }
            }
        }
    
  • URL: /components/raw/side-navigation/side-navigation.built.css
  • Filesystem Path: components/04-organisms/side-navigation/side-navigation.built.css
  • Size: 13.9 KB
  • Content:
    /**
     * SIDE NAVIGATION
     * Supporta sia vertical che horizontal tramite modifier class
     */
     @layer components {
        /* ============================================
           BASE STYLES - Common to all layouts
           ============================================ */
        
        .rtds-side-navigation__title {
            @apply rtds-grid rtds-gap-3 rtds-content-03 rtds-text-base rtds-font-bold;
        }
    
        .rtds-side-navigation__label-context {
            @apply rtds-text-lg md:rtds-text-xl lg:rtds-text-2xl rtds-block rtds-heading-3 rtds-content-01;
        }
    
        .rtds-side-navigation__item {
            @apply rtds-content-03 rtds-bg-white rtds-flex rtds-flex-wrap rtds-items-stretch rtds-text-base;
        }
    
        .rtds-side-navigation__first-level-label {
            @apply rtds-flex rtds-flex-1 rtds-font-bold;
        }
    
        .rtds-side-navigation__link {
            @apply rtds-text-current rtds-border-transparent rtds-flex rtds-flex-1 rtds-items-center rtds-gap-2 rtds-p-4 rtds-transition hover:rtds-content-primary hover:rtds-underline;
        }
    
        .rtds-side-navigation__label {
            @apply rtds-inline-block;
        }
    
        .rtds-side-navigation__link:where(.is-current) {
            @apply rtds-content-primary rtds-border-current;
        }
    
        :where(.rtds-side-navigation__link.is-current) .rtds-side-navigation__label {
            @apply rtds-pb-1 rtds-border-b-2 rtds-border-current;
        }
    
        .rtds-side-navigation__nav-toggle {
            @apply rtds-flex rtds-items-center rtds-justify-center rtds-w-8 hover:rtds-content-primary;
        }
    
        /* MOBILE */
        .rtds-side-navigation__list-toggle {
            @apply rtds-w-full rtds-justify-between rtds-items-end rtds-pl-0 rtds-border-y-0 rtds-border-l-0 rtds-border-r-0 rtds-border-b rtds-rounded-none rtds-border-gray-01 rtds-font-medium rtds-content-03 rtds-text-sm md:rtds-text-base hover:rtds-bg-white focus:rtds-bg-white hover:rtds-border-gray-02;
        }
    
        .rtds-side-navigation__list-toggle:where([aria-expanded="false"]) .rtds-icon {
            @apply -rtds-rotate-180;
        }
    
        .rtds-side-navigation__list-toggle:where([aria-expanded="false"]) ~ .rtds-side-navigation__list {
            @apply rtds-hidden md:rtds-block;
        }
    
        /* sub-navigation */
        .rtds-side-navigation__submenu {
            @apply rtds-pl-4;
        }
    
    
        /* ============================================
           HORIZONTAL MODIFIER - Layout orizzontale da MD
           ============================================ */
        
        .rtds-side-navigation--horizontal {
            @screen md {
                /* Title nascosto per horizontal */
                .rtds-side-navigation__title {
                    @apply rtds-sr-only;
                }
    
                /* Lista: flex horizontal */
                .rtds-side-navigation__list {
                    @apply rtds-flex rtds-flex-wrap rtds-gap-0 rtds-py-4 rtds-border-t-0;
                }
    
                /* Items: no wrap, posizione relativa */
                .rtds-side-navigation__item {
                    @apply rtds-flex-nowrap rtds-relative;
                }
    
                /* First level label: inline con toggle */
                .rtds-side-navigation__first-level-label {
                    @apply rtds-flex rtds-items-center;
                }
    
                /* Link: padding ridotto, border-bottom, no underline */
                .rtds-side-navigation__link {
                    @apply rtds-mx-4 rtds-px-2 rtds-py-0 rtds-text-sm md:rtds-text-base rtds-font-semibold rtds-border-b-2 rtds-border-transparent hover:rtds-border-primary hover:rtds-no-underline;
                }
    
                .rtds-side-navigation__link:where(.is-current) {
                    @apply rtds-border-primary rtds-content-primary;
                }
    
                :where(.rtds-side-navigation__link.is-current) .rtds-side-navigation__label {
                    @apply rtds-pb-0 rtds-border-b-0;
                }
    
                /* Toggle button per horizontal */
                .rtds-side-navigation__nav-toggle {
                    @apply rtds-px-2 rtds-py-2 rtds-w-auto;
                }
    
                /* Submenu: dropdown assoluto */
                .rtds-side-navigation__submenu {
                    @apply rtds-absolute rtds-top-full rtds-left-0 rtds-min-w-[200px] rtds-pl-0 rtds-bg-white rtds-border rtds-border-gray-01 rtds-shadow-lg rtds-z-10;
                }
    
                /* Submenu items */
                .rtds-side-navigation__submenu .rtds-side-navigation__item {
                    @apply rtds-w-full rtds-flex-wrap;
                }
    
                /* Submenu links con hover background */
                .rtds-side-navigation__submenu .rtds-side-navigation__link {
                    @apply rtds-mx-0 rtds-px-6 rtds-py-3 rtds-text-sm rtds-border-b-0 hover:rtds-background-01 hover:rtds-border-transparent;
                }
    
                /* Submenu link corrente con background */
                .rtds-side-navigation__submenu .rtds-side-navigation__link:where(.is-current) {
                    @apply rtds-background-02 rtds-font-medium rtds-border-transparent;
                }
    
                .rtds-side-navigation__submenu .rtds-side-navigation__link:where(.is-current) .rtds-side-navigation__label {
                    @apply rtds-border-b-0;
                }
            }
        }
    
    
        /* ============================================
           ANCHOR NAVIGATION
           ============================================ */
        
        .rtds-side-navigation--anchor {
            @apply rtds-scroll-m-[--header-height] md:rtds-scroll-m-0;
        }
    
        :where(.rtds-side-navigation--anchor) .rtds-side-navigation__link {
            @apply rtds-border-b-0 rtds-border-l-4;
        }
    
        :where(.rtds-side-navigation--anchor .rtds-side-navigation__link.is-current) .rtds-side-navigation__label {
            @apply rtds-pb-0 rtds-border-b-0;
        }
    
        /* Anchor + horizontal: usa border-bottom */
        .rtds-side-navigation--anchor.rtds-side-navigation--horizontal {
            @screen md {
                :where(.rtds-side-navigation__link) {
                    @apply rtds-border-l-0 rtds-border-b-2;
                }
            }
        }
    }
  • URL: /components/raw/side-navigation/side-navigation.css
  • Filesystem Path: components/04-organisms/side-navigation/side-navigation.css
  • Size: 5.9 KB
  • Content:
    'use strict';
    
    /**
     * SIDE NAVIGATION - JavaScript
     * Gestisce sia vertical che horizontal navigation
     * Supporta keyboard navigation, ESC key, e focus management
     */
    
    // Helper function to find the closest ancestor with a specific tag name
    function findAncestor(element, tagName) {
      while (element) {
        if (element.tagName.toLowerCase() === tagName) {
          return element;
        }
        element = element.parentElement;
      }
      return null;
    }
    
    class submenuDisclosure {
      constructor(domNode) {
        this.rootNode = domNode;
        this.parentNav = domNode.closest('.rtds-side-navigation');
        this.isHorizontal = this.parentNav?.classList.contains('rtds-side-navigation--horizontal');
        this.controlledNodes = [];
        this.openIndex = null;
        this.useArrowKeys = true;
        
        // Trova tutti i link e toggle button di primo livello
        this.topLevelNodes = [
          ...this.rootNode.querySelectorAll('.rtds-nav-link, .rtds-nav-toggle'),
        ];
    
        this.init();
      }
    
      init() {
        this.topLevelNodes.forEach((node) => {
          // Gestisci button + menu
          if (
            node.tagName.toLowerCase() === 'button' &&
            node.hasAttribute('aria-controls')
          ) {
            const menuLiParent = node.closest('li');
            const menu = menuLiParent.querySelector('ul');
    
            if (menu) {
              // Salva riferimento al menu controllato
              this.controlledNodes.push(menu);
    
              // Inizializza stato (aperto se current trail, chiuso altrimenti)
              if (menu.querySelector('.is-current') || node.classList.contains('is-current')) {
                node.setAttribute('aria-expanded', 'true');
                this.toggleMenu(menu, true);
              } else {
                node.setAttribute('aria-expanded', 'false');
                this.toggleMenu(menu, false);
              }
    
              // Attach event listeners
              menu.addEventListener('keydown', this.onMenuKeyDown.bind(this));
              node.addEventListener('click', this.onButtonClick.bind(this));
              node.addEventListener('keydown', this.onButtonKeyDown.bind(this));
            }
          }
          // Gestisci link semplici
          else {
            this.controlledNodes.push(null);
            node.addEventListener('keydown', this.onLinkKeyDown.bind(this));
          }
        });
    
        // Riferimento al toggle button principale (mobile)
        this.mainMenuToggle = this.parentNav?.querySelector('.rtds-nav-list-toggle');
    
        // ESC chiude il menu principale su mobile
        this.rootNode.addEventListener('keydown', (event) => {
          if (event.key === 'Escape' && window.innerWidth < 768) {
            if (this.mainMenuToggle?.getAttribute('aria-expanded') === 'true') {
              this.mainMenuToggle.setAttribute('aria-expanded', 'false');
              this.mainMenuToggle.focus();
            }
          }
        });
      }
    
      // Gestisce navigazione con arrow keys
      controlFocusByKey(keyboardEvent, nodeList, currentIndex) {
        switch (keyboardEvent.key) {
          case 'ArrowUp':
          case 'ArrowLeft':
            keyboardEvent.preventDefault();
            if (currentIndex > -1) {
              var prevIndex = Math.max(0, currentIndex - 1);
              nodeList[prevIndex].focus();
            }
            break;
          case 'ArrowDown':
          case 'ArrowRight':
            keyboardEvent.preventDefault();
            if (currentIndex > -1) {
              var nextIndex = Math.min(nodeList.length - 1, currentIndex + 1);
              nodeList[nextIndex].focus();
            }
            break;
          case 'Home':
            keyboardEvent.preventDefault();
            nodeList[0].focus();
            break;
          case 'End':
            keyboardEvent.preventDefault();
            nodeList[nodeList.length - 1].focus();
            break;
        }
      }
    
      // Chiude il submenu aperto
      close() {
        this.toggleExpand(this.openIndex, false);
      }
    
      // Click su toggle button
      onButtonClick(event) {
        var target = event.target;
    
        if (target.tagName.toLowerCase() !== 'button') {
          var buttonAncestor = findAncestor(target, 'button');
          if (buttonAncestor) {
            buttonAncestor.click();
            return;
          }
        }
    
        var button = event.currentTarget;
        var buttonIndex = this.topLevelNodes.indexOf(button);
        var buttonExpanded = button.getAttribute('aria-expanded') === 'true';
        this.toggleExpand(buttonIndex, !buttonExpanded);
      }
    
      // Keyboard events su toggle button
      onButtonKeyDown(event) {
        var targetButtonIndex = this.topLevelNodes.indexOf(document.activeElement);
    
        if (event.key === 'Escape') {
          this.toggleExpand(this.openIndex, false);
        }
        else if (
          this.useArrowKeys &&
          this.openIndex === targetButtonIndex &&
          event.key === 'ArrowDown'
        ) {
          event.preventDefault();
          this.controlledNodes[this.openIndex].querySelector('a').focus();
        }
        else if (this.useArrowKeys) {
          this.controlFocusByKey(event, this.topLevelNodes, targetButtonIndex);
        }
      }
    
      // Keyboard events su link semplici
      onLinkKeyDown(event) {
        var targetLinkIndex = this.topLevelNodes.indexOf(document.activeElement);
        if (this.useArrowKeys) {
          this.controlFocusByKey(event, this.topLevelNodes, targetLinkIndex);
        }
      }
    
      // Keyboard events nel submenu
      onMenuKeyDown(event) {
        if (this.openIndex === null) {
          return;
        }
    
        var menuLinks = Array.prototype.slice.call(
          this.controlledNodes[this.openIndex].querySelectorAll('a')
        );
        var currentIndex = menuLinks.indexOf(document.activeElement);
    
        if (event.key === 'Escape') {
          this.topLevelNodes[this.openIndex].focus();
          this.toggleExpand(this.openIndex, false);
        }
        else if (this.useArrowKeys) {
          this.controlFocusByKey(event, menuLinks, currentIndex);
        }
      }
    
      // Apre/chiude submenu
      toggleExpand(index, expanded) {
        // Chiudi altri submenu aperti
        if (this.openIndex !== index) {
          this.toggleExpand(this.openIndex, false);
        }
    
        if (this.topLevelNodes[index]) {
          this.openIndex = expanded ? index : null;
          this.topLevelNodes[index].setAttribute('aria-expanded', expanded);
          this.toggleMenu(this.controlledNodes[index], expanded);
        }
      }
    
      // Mostra/nascondi menu
      toggleMenu(domNode, show) {
        if (domNode) {
          domNode.style.display = show ? 'block' : 'none';
        }
      }
    
      // Abilita/disabilita arrow keys
      updateKeyControls(useArrowKeys) {
        this.useArrowKeys = useArrowKeys;
      }
    }
    
    /* Initialize Disclosure Menus */
    window.addEventListener('load', function () {
      // Toggle per mobile menu
      const navListToggle = document.querySelector('.rtds-nav-list-toggle');
      if (navListToggle) {
        navListToggle.addEventListener('click', function() {
          const currentState = this.getAttribute('aria-expanded') === 'true';
          this.setAttribute('aria-expanded', (!currentState).toString());
        });
    
        // Mantieni menu aperto durante scroll up su mobile
        let lastScrollTop = 0;
        window.addEventListener('scroll', function() {
          const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
          if (scrollTop < lastScrollTop && navListToggle.getAttribute('aria-expanded') === 'true') {
            navListToggle.setAttribute('aria-expanded', 'true');
          }
          lastScrollTop = scrollTop;
        });
      }
    
      // Inizializza tutti i menu con dropdown
      var dropdownMenus = document.querySelectorAll('.has-nav-dropdown');
      var disclosureMenus = [];
    
      for (var i = 0; i < dropdownMenus.length; i++) {
        disclosureMenus[i] = new submenuDisclosure(dropdownMenus[i]);
      }
    
      // Optional: switch per abilitare/disabilitare arrow keys
      var arrowKeySwitch = document.getElementById('arrow-behavior-switch');
      if (arrowKeySwitch) {
        arrowKeySwitch.addEventListener('change', function () {
          var checked = arrowKeySwitch.checked;
          for (var i = 0; i < disclosureMenus.length; i++) {
            disclosureMenus[i].updateKeyControls(checked);
          }
        });
      }
    }, false);
  • URL: /components/raw/side-navigation/side-navigation.js
  • Filesystem Path: components/04-organisms/side-navigation/side-navigation.js
  • Size: 7.8 KB

Side Navigation

Componente di navigazione laterale. Può essere usato come navigazione multi-pagina o come navigazione ad ancore all’interno di una singola pagina.

Per la navigazione multi-pagina, il link alla pagina corrente deve avere aria-current="page" (gestito tramite isCurrentPage: true).

Il componente può essere visualizzato con una sola etichetta (titolo della sezione o della pagina) oppure con un’etichetta di contesto (labelContext) e un’etichetta di navigazione (label) — utile quando è necessario un titolo visivamente più prominente in cima, accompagnato da un’etichetta descrittiva come “Indice della pagina” o “Indice della sezione”.


Comportamento

Il componente è renderizzato come <nav aria-labelledby=""> — elemento landmark di navigazione etichettato con il titolo visibile.

Su mobile, la lista di navigazione è collassabile tramite un pulsante toggle (visibile solo sotto il breakpoint md). Su desktop, la lista è sempre visibile.

Quando il parametro horizontal: true è attivo, su schermi md e superiori la navigazione assume layout orizzontale con i submenu resi come dropdown assoluti.


Varianti

Varianti di Struttura

  • default: Navigazione verticale base con etichetta visibile su desktop
  • hidden-label (hiddenLabel: true): Etichetta di navigazione nascosta visivamente ma disponibile agli screen reader tramite rtds-sr-only
  • has-context-label (labelContext): Visualizza un’etichetta di contesto prominente sopra l’etichetta di navigazione — utile per mostrare il titolo della sezione come heading visivo
  • anchor (singlePage: true): Navigazione ad ancore per pagina singola; i link usano href con ancore (#id); non viene applicato aria-current="page"
  • horizontal (horizontal: true): Layout orizzontale su tablet e desktop con submenu a dropdown; il titolo è nascosto con rtds-sr-only
  • complete-example: Esempio completo con labelContext, più livelli e voci con isCurrentTrail e subItems
  • third-level: Navigazione a tre livelli con subSubItems — terzo livello nidificato sotto il secondo

Parametri di configurazione

Contesto di sviluppo Fractal/Nunjucks — Questa sezione riguarda esclusivamente i parametri del context .config.yml usati durante lo sviluppo nella libreria.

Parametri Base

  • label (stringa, obbligatorio): Etichetta della navigazione — usata come testo del titolo e come label del pulsante toggle mobile
  • labelId (stringa, obbligatorio): ID dell’elemento titolo — collegato a aria-labelledby sul <nav>
  • id (stringa, opzionale): ID del <nav>
  • listId (stringa, opzionale): ID della <ul> principale — usato da aria-controls sul pulsante toggle mobile
  • labelContext (stringa, opzionale): Etichetta di contesto prominente sopra l’etichetta di navigazione (es. titolo della sezione o della pagina); se presente, viene mostrata anche nel pulsante toggle mobile
  • hiddenLabel (booleano, opzionale): Se true, nasconde visivamente l’etichetta di navigazione (rtds-sr-only), mantenendola accessibile agli screen reader
  • singlePage (booleano, opzionale): Se true, la navigazione è ad ancore (pagina singola); i link non ricevono aria-current="page" anche se isCurrentPage: true
  • horizontal (booleano, opzionale): Se true, aggiunge la classe .rtds-side-navigation--horizontal che attiva il layout orizzontale su md e superiori
  • classes (stringa, opzionale): Classi CSS aggiuntive per il <nav>

Parametri di Stile

  • itemClasses (stringa, opzionale): Classi CSS aggiuntive per ogni elemento <li> di primo livello
  • firstLevelLinkClasses (stringa, opzionale): Classi CSS aggiuntive per i link di primo livello
  • subnavClasses (stringa, opzionale): Classi CSS aggiuntive per le liste di submenu
  • subnavLinkClasses (stringa, opzionale): Classi CSS aggiuntive per i link di submenu

Parametri per le Voci (firstLevels[])

  • label (stringa, obbligatorio): Etichetta del link di primo livello
  • href (stringa, opzionale): URL del link; se assente, viene usato #
  • isCurrentPage (booleano, opzionale): Se true, applica la classe is-current e aria-current="page" al link (solo se singlePage non è attivo)
  • isCurrentTrail (booleano, opzionale): Se true, applica la classe is-current-trail all’elemento e imposta aria-expanded="true" sul pulsante toggle del submenu
  • iconLeft (stringa, opzionale): ID dell’icona da mostrare a sinistra dell’etichetta (dallo sprite SVG)
  • iconRight (stringa, opzionale): ID dell’icona da mostrare nel pulsante toggle submenu; se assente, usa mini--chevron-down
  • subItems (array, opzionale): Voci del submenu di secondo livello
    • subitemLabel (stringa, obbligatorio): Etichetta del link di secondo livello
    • href (stringa, opzionale): URL del link
    • isCurrentPage (booleano, opzionale): Marca la voce come pagina corrente
    • isCurrentTrail (booleano, opzionale): Marca la voce come trail corrente (per terzo livello)
    • subSubItems (array, opzionale): Voci del submenu di terzo livello (solo nella variante third-level)
      • label (stringa, obbligatorio): Etichetta del link di terzo livello
      • isCurrentPage (booleano, opzionale): Marca la voce come pagina corrente

Accessibilità

WCAG 2.1

Livello AA — criteri pertinenti:

  • 1.3.1 Informazioni e correlazioni — struttura semantica con <nav> e aria-labelledby; link con aria-current="page" sulla pagina corrente
  • 2.1.1 Tastiera — tutti i link e pulsanti toggle sono raggiungibili da tastiera
  • 4.1.2 Nome, Ruolo, Valore — pulsanti di espansione subnavigazione usano aria-expanded e aria-controls; il toggle mobile usa aria-expanded e aria-controls

Struttura e semantica

  • <nav aria-labelledby=""> — landmark navigation; etichettato con il titolo della navigazione; identificabile nella lista dei landmark degli screen reader
  • <span id="" class="rtds-side-navigation__title"> — titolo della navigazione; visibile su desktop (salvo hiddenLabel: true), sempre disponibile agli screen reader
  • <a aria-current="page"> — link alla pagina corrente; aria-current è omesso se singlePage: true
  • <button aria-expanded aria-controls> — pulsante toggle del submenu; controlla la visibilità del <ul> corrispondente

Attributi ARIA

Attributo Valori Condizione
aria-labelledby su <nav> valore di labelId sempre presente
aria-current="page" sui link "page" solo sul link della pagina corrente (isCurrentPage: true) quando singlePage non è attivo
aria-expanded sul toggle mobile "false" / "true" gestito da JavaScript
aria-controls sul toggle mobile valore di listId sempre presente
aria-expanded sui toggle submenu "true" se isCurrentTrail, "false" altrimenti sempre presente sui pulsanti di espansione
aria-controls sui toggle submenu "-subnav-" sempre presente
Tasto Azione
Tab / Shift+Tab Sposta il focus tra i link e i pulsanti toggle
Enter Segue il link o attiva il toggle di espansione
Space Attiva il pulsante toggle della subnavigazione

Gestione del focus

  • Focus visibile: lo stile :focus-visible è sempre visibile e non viene rimosso via CSS

Screen reader

  • Il <nav> viene annunciato con l’etichetta fornita da label tramite aria-labelledby
  • Il titolo visivamente nascosto con hiddenLabel: true rimane disponibile agli screen reader tramite rtds-sr-only
  • <span class="rtds-sr-only">Dettaglio </span> nel pulsante toggle descrive l’azione per gli screen reader
  • Nella variante anchor, i link non hanno aria-current="page" anche se isCurrentPage: true — usato per navigazione intra-pagina

Stili CSS

Classi Base

  • .rtds-side-navigation: Stile base del componente — nessun override visivo diretto; la struttura è costruita dagli elementi BEM

Classi Modificatori

  • .rtds-side-navigation--horizontal: Attiva il layout orizzontale da md — lista flex, submenu come dropdown assoluti, link con border-bottom
  • .rtds-side-navigation--anchor: Stile per navigazione ad ancore — link con border-left al posto di border-bottom; combina con --horizontal per layout anchor orizzontale

Classi Elementi (BEM)

  • .rtds-side-navigation__title: Titolo/etichetta della navigazione — griglia con gap, testo bold
  • .rtds-side-navigation__label-context: Etichetta di contesto prominente — testo xl responsivo, heading-3
  • .rtds-side-navigation__list-toggle: Pulsante toggle mobile — visibile solo sotto md; button senza stile con bordo inferiore
  • .rtds-side-navigation__item: Elemento di primo livello — flex, flex-wrap, items-stretch
  • .rtds-side-navigation__first-level-label: Wrapper del link di primo livello — flex, flex-1
  • .rtds-side-navigation__link: Link di navigazione — padding, hover con underline e colore primario; modificatore is-current per voce attiva
  • .rtds-side-navigation__label: Testo del link — inline-block; nella voce corrente riceve border-bottom
  • .rtds-side-navigation__nav-toggle: Pulsante toggle submenu — larghezza fissa w-8, hover colore primario
  • .rtds-side-navigation__submenu: Lista submenu di secondo livello — rientro pl-4; dropdown assoluto in layout horizontal
  • .rtds-side-navigation__sub-submenu: Lista submenu di terzo livello (solo variante third-level) — rientro pl-4

Esempi di utilizzo


<nav class="rtds-side-navigation " 
     aria-labelledby="sideNav1Label"
     id="sideNav1"
     >
  
  <span id="sideNav1Label" class="rtds-side-navigation__title rtds-sr-only md:rtds-not-sr-only md:rtds-pb-4 md:rtds-border-b md:rtds-border-gray-01">
    
    <span class="rtds-block rtds-font-medium">Navigazione sezione</span>
  </span>

  <!-- Mobile toggle button -->
  <button class="rtds-side-navigation__list-toggle rtds-nav-list-toggle md:rtds-hidden rtds-btn rtds-btn--icon-right rtds-btn--only-text rtds-btn--small rtds-group" 
          aria-expanded="false" 
          aria-controls="sideNav1List">
    <span class="rtds-grid rtds-gap-2 rtds-text-left">
      
      <span>Navigazione sezione</span>
    </span>
    <svg
  class="rtds-icon rtds-fill-current rtds-w-5 rtds-h-5"
  aria-hidden="true"
  focusable="false"
  role="img"
>
  <use href="../../icons.svg#mini--chevron-up" />
</svg>

  </button>

  <!-- Navigation list -->
  <ul class="rtds-nav-list rtds-side-navigation__list has-nav-dropdown" id="sideNav1List">
    
      <li class="rtds-side-navigation__item is-first-level">
        <span class="rtds-side-navigation__first-level-label is-current">
          <a href="#" 
             class="rtds-side-navigation__link rtds-nav-link is-current"
              aria-current="page">
            <span class="rtds-side-navigation__label">
              
              Pagina 1
            </span>
          </a>
        
          
        </span>
          

        
      </li>
    
      <li class="rtds-side-navigation__item is-first-level">
        <span class="rtds-side-navigation__first-level-label">
          <a href="#" 
             class="rtds-side-navigation__link rtds-nav-link"
             >
            <span class="rtds-side-navigation__label">
              
              Pagina 2
            </span>
          </a>
        
          
        </span>
          

        
      </li>
    
      <li class="rtds-side-navigation__item is-first-level">
        <span class="rtds-side-navigation__first-level-label">
          <a href="#" 
             class="rtds-side-navigation__link rtds-nav-link"
             >
            <span class="rtds-side-navigation__label">
              
              Pagina 3
            </span>
          </a>
        
          
        </span>
          

        
      </li>
    
  </ul>
</nav>


<nav class="rtds-side-navigation " 
     aria-labelledby="sideNav2Label"
     id="sideNav2"
     >
  
  <span id="sideNav2Label" class="rtds-side-navigation__title rtds-sr-only md:rtds-not-sr-only md:rtds-pb-4 md:rtds-border-b md:rtds-border-gray-01">
    <span class="rtds-side-navigation__label-context">Titolo della sezione</span>
    <span class="rtds-block rtds-font-medium">Indice della sezione</span>
  </span>

  <!-- Mobile toggle button -->
  <button class="rtds-side-navigation__list-toggle rtds-nav-list-toggle md:rtds-hidden rtds-btn rtds-btn--icon-right rtds-btn--only-text rtds-btn--small rtds-group" 
          aria-expanded="false" 
          aria-controls="sideNav2List">
    <span class="rtds-grid rtds-gap-2 rtds-text-left">
      
        <span class="rtds-side-navigation__label-context">Titolo della sezione</span>
      
      <span>Indice della sezione</span>
    </span>
    <svg
  class="rtds-icon rtds-fill-current rtds-w-5 rtds-h-5"
  aria-hidden="true"
  focusable="false"
  role="img"
>
  <use href="../../icons.svg#mini--chevron-up" />
</svg>

  </button>

  <!-- Navigation list -->
  <ul class="rtds-nav-list rtds-side-navigation__list has-nav-dropdown" id="sideNav2List">
    
      <li class="rtds-side-navigation__item is-first-level is-current-trail">
        <span class="rtds-side-navigation__first-level-label">
          <a href="#" 
             class="rtds-side-navigation__link rtds-nav-link"
             >
            <span class="rtds-side-navigation__label">
              
              Sezione principale
            </span>
          </a>
        
          

        
          <button class="rtds-side-navigation__nav-toggle rtds-nav-toggle rtds-group"
                  aria-expanded="true"
                  aria-controls="sideNav2-subnav-1">
            <span class="rtds-sr-only">Dettaglio Sezione principale</span>
            
            
              
            
            <svg
  class="rtds-icon rtds-fill-current rtds-w-4 rtds-h-4 rtds-transition-all rtds-duration-200 rtds-ease-out group-aria-expanded:rtds-rotate-180"
  aria-hidden="true"
  focusable="false"
  role="img"
>
  <use href="../../icons.svg#mini--chevron-down" />
</svg>

          </button>
        </span>
          
          <ul class="rtds-side-navigation__submenu rtds-block rtds-w-full" 
              id="sideNav2-subnav-1">
            
              <li class="rtds-side-navigation__item">
                <a href="#" 
                   class="rtds-side-navigation__link rtds-nav-link is-current"
                    aria-current="page">
                  <span class="rtds-side-navigation__label">Sottopagina 1</span>
                </a>
              </li>
            
              <li class="rtds-side-navigation__item">
                <a href="#" 
                   class="rtds-side-navigation__link rtds-nav-link"
                   >
                  <span class="rtds-side-navigation__label">Sottopagina 2</span>
                </a>
              </li>
            
          </ul>
        
      </li>
    
  </ul>
</nav>


<nav class="rtds-side-navigation  rtds-side-navigation--anchor is-anchor-navigation" 
     aria-labelledby="anchorNavLabel"
     id="anchorNav"
     
  tabindex="-1"
>
  
  <span id="anchorNavLabel" class="rtds-side-navigation__title rtds-sr-only md:rtds-not-sr-only md:rtds-pb-4 md:rtds-border-b md:rtds-border-gray-01">
    
    <span class="rtds-block rtds-font-medium">Indice della pagina</span>
  </span>

  <!-- Mobile toggle button -->
  <button class="rtds-side-navigation__list-toggle rtds-nav-list-toggle md:rtds-hidden rtds-btn rtds-btn--icon-right rtds-btn--only-text rtds-btn--small rtds-group" 
          aria-expanded="false" 
          aria-controls="anchorNavList">
    <span class="rtds-grid rtds-gap-2 rtds-text-left">
      
      <span>Indice della pagina</span>
    </span>
    <svg
  class="rtds-icon rtds-fill-current rtds-w-5 rtds-h-5"
  aria-hidden="true"
  focusable="false"
  role="img"
>
  <use href="../../icons.svg#mini--chevron-up" />
</svg>

  </button>

  <!-- Navigation list -->
  <ul class="rtds-nav-list rtds-side-navigation__list has-nav-dropdown" id="anchorNavList">
    
      <li class="rtds-side-navigation__item is-first-level">
        <span class="rtds-side-navigation__first-level-label is-current">
          <a href="#sezione-1" 
             class="rtds-side-navigation__link rtds-nav-link is-current"
             >
            <span class="rtds-side-navigation__label">
              
              Sezione 1
            </span>
          </a>
        
          
        </span>
          

        
      </li>
    
      <li class="rtds-side-navigation__item is-first-level">
        <span class="rtds-side-navigation__first-level-label">
          <a href="#sezione-2" 
             class="rtds-side-navigation__link rtds-nav-link"
             >
            <span class="rtds-side-navigation__label">
              
              Sezione 2
            </span>
          </a>
        
          
        </span>
          

        
      </li>
    
  </ul>
</nav>

Note

  • Il terzo livello (subSubItems) è disponibile solo nel template side-navigation--third-level.njk che estende il template principale
  • La variante anchor è definita nel file side-navigation--anchor.njk che aggiunge tabindex="-1" sul <nav> e la classe rtds-side-navigation--anchor is-anchor-navigation
  • Il parametro singlePage: true sopprime aria-current="page" su tutti i link — usare per navigazione ad ancore dove non esiste una “pagina corrente”
  • La gestione del toggle mobile e dei submenu è affidata a JavaScript (side-navigation.js)