<div class="rtds-dropdown-menu">
<button class="rtds-dropdown-menu__trigger rtds-dropdown-trigger rtds-group rtds-w-full rtds-flex rtds-items-center hover:rtds-content-primary aria-expanded:rtds-bg-white lg:aria-expanded:rtds-bg-transparent aria-expanded:rtds-content-primary aria-expanded:rtds-relative rtds-p-3 rtds-gap-2 rtds-text-sm lg:rtds-text-base" aria-expanded="false" aria-controls="submenuId01">
Menu item
<svg class="rtds-icon rtds-fill-current rtds-w-5 rtds-h-5 rtds-ml-auto rtds-transition-all rtds-dropdown-menu__trigger-icon group-aria-expanded:-rtds-rotate-180" aria-hidden="true" focusable="false" role="img">
<use href="../../icons.svg#mini--chevron-down" />
</svg>
</button>
<ul class="rtds-dropdown-menu__list rtds-hidden rtds-border rtds-border-t-0 rtds-w-full lg:rtds-border-t lg:rtds-rounded lg:rtds-shadow-md lg:rtds-absolute" id="submenuId01">
<li class="rtds-dropdown-menu__item rtds-group/menu-item">
<a class="rtds-dropdown-menu__link rtds-block rtds-transition group-first/menu-item:rtds-rounded-t group-last/menu-item:rtds-rounded-b" href="">
<div class="rtds-flex rtds-gap-2 rtds-items-center">
<svg class="rtds-icon rtds-fill-current rtds-w-4 rtds-h-4 md:rtds-w-5 md:rtds-h-5 lg:rtds-w-6 lg:rtds-h-6 rtds-mr-2" aria-hidden="true" focusable="false" role="img">
<use href="../../icons.svg#solid--cube-transparent" />
</svg>
<span class="rtds-grow">Item label 1</span>
</div>
</a>
</li>
<li class="rtds-dropdown-menu__item rtds-group/menu-item">
<a class="rtds-dropdown-menu__link rtds-block rtds-transition group-first/menu-item:rtds-rounded-t group-last/menu-item:rtds-rounded-b" href="">
<div class="rtds-flex rtds-gap-2 rtds-items-center">
<span class="rtds-grow">Item label 3</span>
<svg class="rtds-icon rtds-fill-current rtds-w-4 rtds-h-4 md:rtds-w-5 md:rtds-h-5 lg:rtds-w-6 lg:rtds-h-6 rtds-ml-2 rtds-transition-all rtds-duration-200 rtds-ease-out rtds-transform group-hover:rtds-translate-x-1" aria-hidden="true" focusable="false" role="img">
<use href="../../icons.svg#mini--chevron-right" />
</svg>
</div>
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua</div>
</a>
</li>
<li class="rtds-dropdown-menu__item rtds-group/menu-item">
<a class="rtds-dropdown-menu__link rtds-block rtds-transition group-first/menu-item:rtds-rounded-t group-last/menu-item:rtds-rounded-b" href="">
<div class="rtds-flex rtds-gap-2 rtds-items-center">
<svg class="rtds-icon rtds-fill-current rtds-w-4 rtds-h-4 md:rtds-w-5 md:rtds-h-5 lg:rtds-w-6 lg:rtds-h-6 rtds-mr-2" aria-hidden="true" focusable="false" role="img">
<use href="../../icons.svg#solid--cube-transparent" />
</svg>
<span class="rtds-grow">Item label 4</span>
<svg class="rtds-icon rtds-fill-current rtds-w-4 rtds-h-4 md:rtds-w-5 md:rtds-h-5 lg:rtds-w-6 lg:rtds-h-6 rtds-ml-2 rtds-transition-all rtds-duration-200 rtds-ease-out rtds-transform group-hover:rtds-translate-x-1" aria-hidden="true" focusable="false" role="img">
<use href="../../icons.svg#mini--chevron-right" />
</svg>
</div>
</a>
</li>
<li class="rtds-dropdown-menu__item rtds-group/menu-item">
<a class="rtds-dropdown-menu__link rtds-block rtds-transition group-first/menu-item:rtds-rounded-t group-last/menu-item:rtds-rounded-b" href="">
<div class="rtds-flex rtds-gap-2 rtds-items-center">
<span class="rtds-grow">Item label 5</span>
</div>
</a>
</li>
</ul>
</div>
<{% if listItem %}li{% else %}div{% endif %} class="rtds-dropdown-menu{% if listItem %} has-dropdown-menu{% endif %}{% block classes %}{% if classes %} {{ classes }}{% endif %}{% endblock classes %}">
<button class="rtds-dropdown-menu__trigger rtds-dropdown-trigger rtds-group rtds-w-full rtds-flex rtds-items-center {% if hoverStyles %} {{ hoverStyles }}{% endif %}{% if triggerAriaExpandedStyles %} {{ triggerAriaExpandedStyles }}{% endif %}{% if triggerSpacing %} {{ triggerSpacing }}{% endif %}{% if triggerFontSize %} {{ triggerFontSize }}{% endif %}{% if triggerTextColor %} {{ triggerTextColor }}{% endif %}{% if triggerClasses %} {{ triggerClasses }}{% endif %}" aria-expanded="false" aria-controls="{{ id }}">
{% block triggerContent %}
{{ label }}
{% endblock triggerContent %}
{% block triggerIcon %}
{%- render '@icon--small', {id: 'mini--chevron-down',size: 'rtds-w-5 rtds-h-5', classes: 'rtds-ml-auto rtds-transition-all rtds-dropdown-menu__trigger-icon group-aria-expanded:-rtds-rotate-180'},true -%}
{% endblock triggerIcon %}
</button>
{% block listStart %}
<ul class="rtds-dropdown-menu__list rtds-hidden rtds-border rtds-border-t-0{% if listWidth %} {{ listWidth }}{% endif %}{% if listPosition %} {{ listPosition }}{% endif %}{% if listResponsiveStyles %} {{ listResponsiveStyles }}{% endif %}{% if listClasses %} {{ listClasses }}{% endif %}" id="{{ id }}">
{% endblock listStart %}
{% for item in items %}
<li class="rtds-dropdown-menu__item rtds-group/menu-item{% if listItemClasses %} {{ listItemClasses }}{% endif %}">
<a class="rtds-dropdown-menu__link rtds-block rtds-transition{% if listItemLinkFontSize %} {{ listItemLinkFontSize }}{% endif %}{% if listItemLinkRadius %} {{ listItemLinkRadius }}{% endif %}" href="">
<div class="rtds-flex rtds-gap-2 rtds-items-center">
{% if item.iconLeft %}
{% render '@icon--small', { id: item.iconLeft, classes: 'rtds-mr-2', size: 'rtds-w-4 rtds-h-4 md:rtds-w-5 md:rtds-h-5 lg:rtds-w-6 lg:rtds-h-6' }, true %}
{% endif %}
<span class="rtds-grow">{% if item.label %}{{ item.label }}{% else %} Item {% endif %}</span>
{% if item.iconRight %}
{% render '@icon--small', { id: item.iconRight, classes: 'rtds-ml-2 rtds-transition-all rtds-duration-200 rtds-ease-out rtds-transform group-hover:rtds-translate-x-1', size: 'rtds-w-4 rtds-h-4 md:rtds-w-5 md:rtds-h-5 lg:rtds-w-6 lg:rtds-h-6' }, true %}
{% endif %}
</div>
{% if item.description %}<div>{{ item.description }}</div>{% endif %}
</a>
</li>
{% endfor %}
{% block listEnd %}
</ul>
{% endblock listEnd %}
</{% if listItem %}li{% else %}div{% endif %}>
{
"label": "Menu item",
"id": "submenuId01",
"triggerSpacing": "rtds-p-3 rtds-gap-2",
"triggerFontSize": "rtds-text-sm lg:rtds-text-base",
"triggerAriaExpandedStyles": "aria-expanded:rtds-bg-white lg:aria-expanded:rtds-bg-transparent aria-expanded:rtds-content-primary aria-expanded:rtds-relative",
"items": [
{
"label": "Item label 1",
"iconLeft": "solid--cube-transparent"
},
{
"label": "Item label 3",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua",
"iconRight": "mini--chevron-right"
},
{
"label": "Item label 4",
"iconLeft": "solid--cube-transparent",
"iconRight": "mini--chevron-right"
},
{
"label": "Item label 5"
}
],
"listWidth": "rtds-w-full",
"listResponsiveStyles": "lg:rtds-border-t lg:rtds-rounded lg:rtds-shadow-md lg:rtds-absolute",
"listItemLinkRadius": "group-first/menu-item:rtds-rounded-t group-last/menu-item:rtds-rounded-b",
"hoverStyles": "hover:rtds-content-primary"
}
/**
* DROPDOWN MENU
*
*/
/* DROPDOWN MENU STYLES */
.rtds-dropdown-menu__list[style*="block"] {
z-index: 10;
}
.rtds-dropdown-menu__list,
.rtds-dropdown-menu__item {
border-color: var(--color-border-gray-01);
}
@media (min-width: 1024px) {
.rtds-dropdown-menu__list:where(.is-open) {
top: 100%;
}
}
.rtds-dropdown-menu__item {
border-bottom-width: 1px;
}
.rtds-dropdown-menu__item:last-of-type {
border-bottom-width: 0px;
}
.rtds-dropdown-menu__link {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
padding: var(--spacing-3);
}
.rtds-dropdown-menu__link:hover {
text-decoration-line: underline;
background-color: var(--color-background-02);
}
.rtds-dropdown-menu__link:focus {
background-color: var(--color-background-02);
}
/* DROPDOWN TRIGGER */
.rtds-dropdown-menu__trigger[aria-expanded="true"]::after {
position: absolute;
left: var(--spacing-0);
bottom: var(--spacing-0);
display: block;
height: 1px;
width: 100%;
border-top-width: 2px;
border-color: currentColor;
content: var(--tw-content);
background-color: transparent;
}
/* ACTIONS VARIANT STYLES */
.is-dropdown-menu--actions {
position: relative;
justify-content: flex-end;
display: flex;
}
.is-dropdown-menu--actions .rtds-dropdown-menu__trigger {
background-color: var(--color-button-inverted);
border-color: var(--color-button-inverted);
color: var(--color-button-inverted-text);
}
.is-dropdown-menu--actions .rtds-dropdown-menu__trigger:hover {
background-color: var(--color-button-inverted-hover);
border-color: var(--color-button-inverted-hover);
color: var(--color-button-inverted-text-hover);
}
.is-dropdown-menu--actions .rtds-dropdown-menu__trigger:focus {
background-color: var(--color-button-inverted-focus);
border-color: var(--color-button-inverted-focus);
color: var(--color-button-inverted-text-focus);
}
.is-dropdown-menu--actions .rtds-dropdown-menu__trigger:active {
background-color: var(--color-button-inverted-active);
border-color: var(--color-button-inverted-active);
color: var(--color-button-inverted-text-active);
}
.is-dropdown-menu--actions .rtds-dropdown-menu__trigger {
height: var(--spacing-10);
width: var(--spacing-10);
border-radius: 9999px;
color: var(--color-content-01);
border-color: var(--color-border-gray-04);
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
border-width: 1px;
}
.is-dropdown-menu--actions .rtds-dropdown-menu__trigger[aria-expanded="true"] {
color: var(--color-content-inverse);
background-color: var(--color-background-08);
}
.is-dropdown-menu--actions .rtds-dropdown-menu__list {
position: absolute;
right: var(--spacing-0);
top: var(--spacing-10);
z-index: 10;
width: 25ch;
border-radius: 0.25rem;
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
--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);
border-color: var(--color-border-gray-01);
border-width: 1px;
}
.is-dropdown-menu--actions .rtds-dropdown-menu__item {
border-style: none;
display: flex;
}
.is-dropdown-menu--actions .rtds-dropdown-menu__link {
gap: var(--spacing-0-5);
font-size: var(--fontsize-text-sm);
}
.is-dropdown-menu--actions .rtds-dropdown-menu__link:where(.rtds-btn--icon),.is-dropdown-menu--actions .rtds-dropdown-menu__link:where(.rtds-btn--icon-square) {
width: var(--spacing-6);
height: var(--spacing-6);
}
.is-dropdown-menu--actions .rtds-dropdown-menu__link:where(.rtds-btn--icon-right),.is-dropdown-menu--actions .rtds-dropdown-menu__link:where(.rtds-btn--icon-left) {
gap: var(--spacing-1-5);
}
.is-dropdown-menu--actions .rtds-dropdown-menu__link:where(.rtds-btn--icon-right) {
padding-right: var(--spacing-3);
}
.is-dropdown-menu--actions .rtds-dropdown-menu__link:where(.rtds-btn--icon-left) {
padding-left: var(--spacing-3);
}
.is-dropdown-menu--actions .rtds-dropdown-menu__link:where(.rtds-btn--icon),.is-dropdown-menu--actions .rtds-dropdown-menu__link:where(.rtds-btn--icon-square) {
padding-left: var(--spacing-0);
padding-right: var(--spacing-0);
}
.is-dropdown-menu--actions .rtds-dropdown-menu__link {
width: 100%;
justify-content: flex-start;
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
padding: var(--spacing-3);
font-size: var(--fontsize-text-sm);
font-weight: 500;
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;
color: var(--color-content-primary-dark);
display: flex;
align-items: center;
gap: var(--spacing-2);
}
.is-dropdown-menu--actions .rtds-dropdown-menu__link:hover {
text-decoration-line: underline;
background-color: var(--color-background-02);
}
.is-dropdown-menu--actions .rtds-dropdown-menu__link:focus {
background-color: var(--color-background-02);
}
/* MEGAMENU STYLES */
@media (min-width: 1024px) {
.rtds-dropdown-menu__megamenu.is-open {
background-color: var(--color-background-02);
}
}
.has-megamenu .rtds-dropdown-menu__item {
border-style: dashed;
border-color: var(--color-border-gray-03);
font-weight: 700;
}
.has-megamenu .rtds-dropdown-menu__item:last-of-type {
border-bottom-width: 1px;
}
.has-megamenu .rtds-dropdown-menu__list {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
}
@media (min-width: 1024px) {
.has-megamenu .rtds-dropdown-menu__list {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
-moz-column-gap: var(--spacing-8);
column-gap: var(--spacing-8);
background-color: transparent;
padding: var(--spacing-4);
}
}
@media (min-width: 1280px) {
.has-megamenu .rtds-dropdown-menu__list {
grid-template-columns: repeat(4, minmax(0, 1fr));
-moz-column-gap: var(--spacing-10);
column-gap: var(--spacing-10);
}
}
.has-megamenu .rtds-dropdown-menu__link {
padding: var(--spacing-4);
font-size: var(--fontsize-text-base);
color: var(--color-content-02);
}
@media (min-width: 1024px) {
.has-megamenu .rtds-dropdown-menu__link {
background-color: transparent;
}
}
@media (min-width: 1280px) {
.has-megamenu .rtds-dropdown-menu__link {
font-size: var(--fontsize-text-lg);
}
}
body.rtds-dropdown-menu__megamenu.is-hidden .rtds-primary-navigation__backdrop,
:root.rtds-dropdown-menu__megamenu.is-hidden .rtds-primary-navigation__backdrop {
position: fixed;
right: var(--spacing-0);
bottom: var(--spacing-0);
left: var(--spacing-0);
z-index: 10;
}
@media (min-width: 1024px) {
body.rtds-dropdown-menu__megamenu.is-hidden .rtds-primary-navigation__backdrop,
:root.rtds-dropdown-menu__megamenu.is-hidden .rtds-primary-navigation__backdrop {
display: none;
}
}
body.rtds-dropdown-menu__megamenu.is-hidden .rtds-primary-navigation__backdrop,
:root.rtds-dropdown-menu__megamenu.is-hidden .rtds-primary-navigation__backdrop {
position: fixed;
right: var(--spacing-0);
bottom: var(--spacing-0);
left: var(--spacing-0);
z-index: 10;
}
@media (min-width: 1024px) {
body.rtds-dropdown-menu__megamenu.is-hidden .rtds-primary-navigation__backdrop,
:root.rtds-dropdown-menu__megamenu.is-hidden .rtds-primary-navigation__backdrop {
display: none;
}
}
.rtds-dropdown-menu__megamenu.is-hidden {
visibility: hidden;
position: absolute;
overflow: hidden;
}
@media (min-width: 1024px) {
.rtds-dropdown-menu__megamenu.is-hidden {
position: static;
display: none;
}
}
/* MEGAMENU MOBILE */
.rtds-dropdown-menu.has-megamenu {
z-index: 20;
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
}
@media (min-width: 1024px) {
.rtds-dropdown-menu.has-megamenu {
position: static;
top: auto;
left: auto;
right: auto;
bottom: auto;
z-index: auto;
}
}
.rtds-dropdown-menu.has-megamenu.has-dropdown-open {
position: absolute;
top: var(--spacing-0);
left: var(--spacing-0);
right: var(--spacing-0);
bottom: var(--spacing-0);
z-index: 30;
}
@media (min-width: 1024px) {
.rtds-dropdown-menu.has-megamenu.has-dropdown-open {
position: static;
top: auto;
left: auto;
right: auto;
bottom: auto;
}
}
.rtds-dropdown-menu__megamenu .rtds-dropdown-menu__list {
visibility: hidden;
position: relative;
left: 100%;
right: var(--spacing-0);
height: var(--spacing-0);
width: var(--spacing-0);
--tw-translate-x: 100%;
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));
opacity: 0;
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
@media (min-width: 1024px) {
.rtds-dropdown-menu__megamenu .rtds-dropdown-menu__list {
left: auto;
right: auto;
height: auto;
width: 100%;
--tw-translate-x: var(--spacing-0);
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-dropdown-menu__megamenu.is-open .rtds-dropdown-menu__list {
visibility: visible;
left: var(--spacing-0);
width: 100%;
--tw-translate-x: var(--spacing-0);
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));
opacity: 1;
}
/* MANAGING NAV PANEL DROPDOWN OPEN */
:where(.rtds-primary-navigation.has-megamenu) .has-inner-dropdown-open {
position: absolute;
top: var(--spacing-0);
left: var(--spacing-0);
right: var(--spacing-0);
bottom: var(--spacing-0);
z-index: 30;
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
}
@media (min-width: 1280px) {
:where(.rtds-primary-navigation.has-megamenu) .has-inner-dropdown-open {
position: static;
top: auto;
left: auto;
right: auto;
bottom: auto;
z-index: auto;
background-color: transparent;
}
}
/**
* DROPDOWN MENU
*
*/
@layer components {
/* DROPDOWN MENU STYLES */
.rtds-dropdown-menu__list[style*="block"] {
@apply rtds-z-10;
}
.rtds-dropdown-menu__list,
.rtds-dropdown-menu__item {
@apply rtds-border-gray-01;
}
.rtds-dropdown-menu__list:where(.is-open) {
@apply lg:rtds-top-full;
}
.rtds-dropdown-menu__item {
@apply rtds-border-b last-of-type:rtds-border-b-0;
}
.rtds-dropdown-menu__link {
@apply rtds-p-3 rtds-bg-white hover:rtds-underline hover:rtds-background-02 focus:rtds-background-02;
}
/* DROPDOWN TRIGGER */
.rtds-dropdown-menu__trigger[aria-expanded="true"] {
@apply after:rtds-absolute after:rtds-block after:rtds-bg-transparent after:rtds-border-t-2 after:rtds-border-current after:rtds-h-[1px] after:rtds-w-full after:rtds-left-0 after:rtds-bottom-0;
}
/* ACTIONS VARIANT STYLES */
.is-dropdown-menu--actions {
@apply rtds-flex rtds-justify-end rtds-relative;
}
.is-dropdown-menu--actions .rtds-dropdown-menu__trigger {
@apply rtds-rounded-full rtds-border rtds-border-gray-04 rtds-w-10 rtds-h-10 rtds-content-01 rtds-btn--inverted rtds-transition-all;
}
.is-dropdown-menu--actions .rtds-dropdown-menu__trigger[aria-expanded="true"] {
@apply rtds-background-08 rtds-content-inverse;
}
.is-dropdown-menu--actions .rtds-dropdown-menu__list {
@apply rtds-w-[25ch] rtds-absolute rtds-right-0 rtds-top-10 rtds-bg-white rtds-shadow-lg rtds-z-10 rtds-rounded rtds-border rtds-border-gray-01;
}
.is-dropdown-menu--actions .rtds-dropdown-menu__item {
@apply rtds-flex rtds-border-none;
}
.is-dropdown-menu--actions .rtds-dropdown-menu__link {
@apply rtds-flex rtds-justify-start rtds-gap-2 rtds-items-center rtds-p-3 rtds-btn--s rtds-w-full rtds-transition rtds-bg-white rtds-font-medium rtds-text-sm rtds-content-primary-dark hover:rtds-underline hover:rtds-background-02 focus:rtds-background-02;
}
/* MEGAMENU STYLES */
.rtds-dropdown-menu__megamenu.is-open {
@apply lg:rtds-background-02;
}
.has-megamenu .rtds-dropdown-menu__item {
@apply rtds-border-dashed rtds-border-gray-03 last-of-type:rtds-border-b rtds-font-bold;
}
.has-megamenu .rtds-dropdown-menu__list {
@apply rtds-bg-white lg:rtds-bg-transparent lg:rtds-grid lg:rtds-gap-x-8 xl:rtds-gap-x-10 lg:rtds-grid-cols-3 xl:rtds-grid-cols-4 lg:rtds-p-4;
}
.has-megamenu .rtds-dropdown-menu__link {
@apply rtds-p-4 lg:rtds-bg-transparent rtds-content-02 rtds-text-base xl:rtds-text-lg;
}
.rtds-dropdown-menu__megamenu.is-hidden {
@apply rtds-invisible rtds-absolute lg:rtds-hidden lg:rtds-static rtds-overflow-hidden;
}
/* MEGAMENU MOBILE */
.rtds-dropdown-menu.has-megamenu {
@apply rtds-z-20 rtds-bg-white lg:rtds-static lg:rtds-z-auto lg:rtds-top-auto lg:rtds-left-auto lg:rtds-right-auto lg:rtds-bottom-auto;
}
.rtds-dropdown-menu.has-megamenu.has-dropdown-open {
@apply rtds-top-0 rtds-left-0 rtds-right-0 rtds-bottom-0 rtds-absolute rtds-z-30 lg:rtds-static lg:rtds-top-auto lg:rtds-left-auto lg:rtds-right-auto lg:rtds-bottom-auto;
}
.rtds-dropdown-menu__megamenu .rtds-dropdown-menu__list {
@apply rtds-invisible rtds-transition-all rtds-opacity-0 rtds-translate-x-full lg:rtds-translate-x-0 rtds-relative rtds-left-full rtds-right-0 rtds-w-0 rtds-h-0 lg:rtds-h-auto lg:rtds-w-full lg:rtds-left-auto lg:rtds-right-auto;
}
.rtds-dropdown-menu__megamenu.is-open .rtds-dropdown-menu__list {
@apply rtds-visible rtds-opacity-100 rtds-translate-x-0 rtds-left-0 rtds-w-full;
}
/* MANAGING NAV PANEL DROPDOWN OPEN */
:where(.rtds-primary-navigation.has-megamenu) .has-inner-dropdown-open {
@apply rtds-absolute rtds-top-0 rtds-left-0 rtds-right-0 rtds-bottom-0 rtds-z-30 rtds-bg-white xl:rtds-bg-transparent xl:rtds-z-auto xl:rtds-top-auto xl:rtds-left-auto xl:rtds-right-auto xl:rtds-bottom-auto xl:rtds-static;
}
}
/*
* This content is licensed according to the W3C Software License at
* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
*
* Supplemental JS for the disclosure menu keyboard behavior
*/
'use strict';
// 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 DisclosureNav {
constructor(domNode) {
this.rootNode = domNode;
this.controlledNodes = [];
this.openIndex = null;
this.useArrowKeys = true;
this.topLevelNodes = [
...this.rootNode.querySelectorAll(
'.main-link, .rtds-dropdown-trigger'
),
];
this.topLevelNodes.forEach((node) => {
if (
node.tagName.toLowerCase() === 'button' &&
node.hasAttribute('aria-controls')
) {
// Supporta sia <ul> che <div>
const menu = node.parentNode.querySelector('ul, div');
if (menu) {
this.controlledNodes.push(menu);
node.setAttribute('aria-expanded', 'false');
this.toggleMenu(menu, false);
menu.addEventListener('keydown', this.onMenuKeyDown.bind(this));
node.addEventListener('click', this.onButtonClick.bind(this));
node.addEventListener('keydown', this.onButtonKeyDown.bind(this));
}
} else {
this.controlledNodes.push(null);
node.addEventListener('keydown', this.onLinkKeyDown.bind(this));
}
});
// Aggiungiamo un event listener per il click globale
document.addEventListener('click', this.onDocumentClick.bind(this));
// Manteniamo anche l'evento focusout per la navigazione da tastiera
this.rootNode.addEventListener('focusout', this.onBlur.bind(this));
}
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;
}
}
close() {
this.toggleExpand(this.openIndex, false);
}
onBlur(event) {
// Verifichiamo se il nuovo elemento focusato è all'interno del menu
const menuContainsFocus = this.rootNode.contains(event.relatedTarget);
// Se il focus è uscito dal menu e non è stato spostato su un altro elemento del menu
if (!menuContainsFocus && this.openIndex !== null) {
// Aggiungiamo un piccolo delay per permettere al focus di stabilizzarsi
setTimeout(() => {
if (!this.rootNode.contains(document.activeElement)) {
this.toggleExpand(this.openIndex, false);
}
}, 0);
}
}
onButtonClick(event) {
var target = event.target;
if (target.tagName.toLowerCase() !== 'button') {
var buttonAncestor = findAncestor(target, 'button');
if (buttonAncestor) {
buttonAncestor.click();
return;
}
}
var button = event.target;
var buttonIndex = this.topLevelNodes.indexOf(button);
var buttonExpanded = button.getAttribute('aria-expanded') === 'true';
this.toggleExpand(buttonIndex, !buttonExpanded);
}
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);
}
}
onLinkKeyDown(event) {
var targetLinkIndex = this.topLevelNodes.indexOf(document.activeElement);
if (this.useArrowKeys) {
this.controlFocusByKey(event, this.topLevelNodes, targetLinkIndex);
}
}
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);
}
}
toggleExpand(index, expanded) {
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);
}
}
toggleMenu(domNode, show) {
if (domNode) {
// Trova l'elemento padre con la classe has-dropdown-menu
const parentMenu = domNode.closest('.has-dropdown-menu');
// Trova il modulo di navigazione principale
const navModule = domNode.closest('.rtds-primary-navigation__module');
// Verifica se è un mega menu
const isMegaMenu = parentMenu && parentMenu.classList.contains('has-megamenu');
// Gestione delle classi per mostrare/nascondere il menu
if (show) {
// Rimuove la classe appropriata in base al tipo di menu
domNode.classList.remove(isMegaMenu ? 'is-hidden' : 'rtds-hidden');
domNode.classList.add('is-open');
if (parentMenu) {
parentMenu.classList.add('has-dropdown-open');
}
if (navModule) {
navModule.classList.add('has-inner-dropdown-open');
}
} else {
domNode.classList.remove('is-open');
// Aggiunge la classe appropriata in base al tipo di menu
domNode.classList.add(isMegaMenu ? 'is-hidden' : 'rtds-hidden');
if (parentMenu) {
parentMenu.classList.remove('has-dropdown-open');
}
if (navModule) {
navModule.classList.remove('has-inner-dropdown-open');
}
}
const rect = domNode.getBoundingClientRect();
const isOverflowingRight = rect.right > window.innerWidth;
const isOverflowingLeft = rect.left < 0;
domNode.classList.toggle('rtds-right-0', isOverflowingRight);
domNode.classList.toggle('rtds-left-0', isOverflowingLeft);
}
}
updateKeyControls(useArrowKeys) {
this.useArrowKeys = useArrowKeys;
}
// Aggiungiamo un nuovo metodo per gestire i click globali
onDocumentClick(event) {
// Se il click è all'interno del menu, non facciamo nulla
if (this.rootNode.contains(event.target)) {
return;
}
// Se c'è un menu aperto, lo chiudiamo
if (this.openIndex !== null) {
this.toggleExpand(this.openIndex, false);
}
}
}
/* Inizializza i Disclosure Menus */
window.addEventListener(
'load',
function () {
// Seleziona sia gli elementi con la classe .has-dropdown-menu che i div con la classe .dropdown
var menus = document.querySelectorAll('.has-dropdown-menu, div.rtds-dropdown-menu');
var disclosureMenus = [];
for (var i = 0; i < menus.length; i++) {
disclosureMenus[i] = new DisclosureNav(menus[i]);
}
},
false
);
Il componente Dropdown Menu fornisce un menu a discesa accessibile e interattivo, con supporto per navigazione da tastiera e screen reader. Supporta diverse varianti, inclusa una versione megamenu per contenuti più complessi e una variante actions per menu di azioni.
Il componente può essere renderizzato come:
<div> — wrapper di default per dropdown indipendente<li> — quando listItem: true nel contesto Fractal/Nunjucks; da inserire all’interno di una <ul> di navigazioneApertura/chiusura al click sul trigger; chiusura automatica quando il focus si sposta fuori dal menu; transizioni fluide; gestione intelligente del posizionamento per evitare overflow.
default: Menu a discesa standard, larghezza completa, stili responsive con bordo e ombra su desktoplist-item: Versione compatibile con liste, larghezza fissa su desktop (52), stili responsive con bordo e ombramegamenu: Menu a discesa a larghezza piena, layout a container su desktop, icone diverse per mobile e desktopactions: Menu di azioni compatto con icona ellipsis verticale, posizionamento a destra con larghezza fissa (25ch), ideale per menu contestuali in card e tabelleContesto di sviluppo Fractal/Nunjucks — Questa sezione riguarda esclusivamente i parametri del context
.config.ymlusati durante lo sviluppo nella libreria. Non descrive attributi HTML o proprietà da usare nei temi, CMS o ambienti di implementazione: per quello, fare riferimento alla sezione Esempi di utilizzo.
id (stringa, obbligatorio): ID univoco per il dropdown (necessario per l’accessibilità)label (stringa, obbligatorio): Testo del pulsante triggeritems (array, obbligatorio): Lista degli elementi del menulabel (stringa, obbligatorio): Testo dell’elementodescription (stringa, opzionale): Descrizione opzionale dell’elementoiconLeft (stringa, opzionale): ID dell’icona da mostrare a sinistraiconRight (stringa, opzionale): ID dell’icona da mostrare a destralistItem (booleano, opzionale): Se true, il componente viene renderizzato come <li> invece di <div>classes (stringa, opzionale): Classi CSS aggiuntive per personalizzare l’aspettohasMegamenu (booleano, opzionale): Se true, il dropdown ha un megamenucontext (stringa, opzionale): Contesto accessibile per il trigger nella variante actions (es. nome della persona nella card)triggerSpacing (stringa, opzionale): Spaziatura del pulsante triggertriggerFontSize (stringa, opzionale): Dimensione del font del pulsante triggertriggerTextColor (stringa, opzionale): Colore del testo del triggertriggerAriaExpandedStyles (stringa, opzionale): Stili applicati quando il menu è espansolistWidth (stringa, opzionale): Larghezza del menu a discesalistResponsiveStyles (stringa, opzionale): Stili responsive per il menulistItemLinkRadius (stringa, opzionale): Bordi arrotondati per gli elementi del menulistItemLinkFontSize (stringa, opzionale): Dimensione del font per i link degli elementilistPosition (stringa, opzionale): Posizione del menu a discesa (gestisce il posizionamento a sinistra/destra)hoverStyles (stringa, opzionale): Stili per l’hover sugli elementiLivello AA — criteri pertinenti:
<button> trigger e <ul> per la lista degli elementiaria-expanded riflette lo stato aperto/chiuso; aria-controls collega il trigger alla lista<div> — wrapper di default; usare per dropdown indipendenti<li> — usare quando il dropdown è elemento di una lista di navigazione; con classe has-dropdown-menu, da inserire all’interno di una <ul><button> (trigger) — ruolo implicito button; attivabile con Enter e Space; controlla apertura/chiusura tramite aria-expanded e aria-controls<ul> + <li> + <a> (lista) — struttura semantica di navigazione; ogni elemento è un link nativo| Attributo | Valori | Condizione |
|---|---|---|
aria-expanded |
"true" / "false" |
sempre presente sul <button> trigger |
aria-controls |
ID della lista | sempre presente sul <button> trigger |
| Tasto | Azione |
|---|---|
Tab / Shift+Tab |
Navigazione standard tra elementi focusabili |
Enter / Space |
Apre o chiude il menu sul trigger |
Arrow Down / Arrow Up |
Navigazione tra gli elementi del menu aperto |
Arrow Left / Arrow Right |
Navigazione tra i trigger del menu (quando usato in barra di navigazione) |
Home / End |
Sposta il focus al primo / ultimo elemento del menu |
Escape |
Chiude il menu e riporta il focus al trigger |
:focus-visible è sempre visibile e non viene rimosso via CSSaria-expanded — lo screen reader annuncia il nome del menu e lo stato aperto/chiuso<span class="rtds-sr-only"> nel trigger aggiunge il contesto necessario (es. “Opzioni [nome persona]”) — lo screen reader lo legge come parte del nome del pulsante, disambiguando trigger identici in liste di card.rtds-dropdown-menu: Classe base del componente.rtds-dropdown-menu__trigger: Pulsante trigger.rtds-dropdown-menu__list: Lista degli elementi del menu.rtds-dropdown-menu__item: Elemento del menu.rtds-dropdown-menu__link: Link dell’elemento.rtds-dropdown-menu__megamenu: Contenitore per la variante megamenu.has-dropdown-menu: Classe per elementi che contengono un dropdown.has-dropdown-open: Classe per elementi con dropdown aperto.is-open: Classe per menu aperti.is-hidden: Classe per menu nascosti (megamenu).is-dropdown-menu--actions: Classe specifica per la variante actions<!-- Dropdown standard -->
<div class="rtds-dropdown-menu">
<button class="rtds-dropdown-menu__trigger rtds-dropdown-trigger rtds-group rtds-w-full rtds-flex rtds-items-center"
aria-expanded="false" aria-controls="submenuId01">
Menu item
<svg class="rtds-ml-auto rtds-transition-all rtds-dropdown-menu__trigger-icon group-aria-expanded:-rtds-rotate-180">...</svg>
</button>
<ul class="rtds-dropdown-menu__list rtds-hidden rtds-border rtds-border-t-0" id="submenuId01">
<li class="rtds-dropdown-menu__item rtds-group/menu-item">
<a class="rtds-dropdown-menu__link rtds-block rtds-transition" href="">
<div class="rtds-flex rtds-gap-2 rtds-items-center">
<span class="rtds-grow">Item label</span>
</div>
</a>
</li>
</ul>
</div>DisclosureNav per gestire il comportamento del menu da tastiera