<section class="rtds-context-menu">
    <div class="rtds-context-menu__container rtds-container">
        <div class="rtds-context-menu__header rtds-flex-2 md:rtds-flex-none">
            <div class="rtds-site-logo rtds-max-w-16 md:rtds-max-w-20 lg:rtds-max-w-24">
                <img class="rtds-w-full rtds-h-full rtds-object-contain rtds-object-left-top" src="../../images/icona-tema-sociale.svg" alt="Regione Toscana - home page" width="118" height="24" />
            </div>

            <div class="rtds-flex rtds-items-baseline rtds-gap-2">
                <span class="rtds-context-menu__title rtds-text-sm md:rtds-text-base xl:rtds-text-lg rtds-leading-none rtds-grid rtds-gap-1 md:rtds-block" id="contextMenuTitle">

                    <a class="rtds-font-bold hover:rtds-underline" href=""><span class="rtds-sr-only">Homepage del tema: </span>Sociale</a>

                </span>

            </div>
        </div>

    </div>
</section>
{% extends '@context-menu' %}

{% block contextMenu %}
{% endblock contextMenu %}
{
  "title": "Sociale",
  "menuListGridClasses": "md:rtds-grid-cols-2 lg:rtds-grid-cols-4 xl:rtds-grid-cols-5",
  "logo": {
    "path": "/images/icona-tema-sociale.svg",
    "width": "118",
    "height": "24",
    "classes": "rtds-max-w-16 md:rtds-max-w-20 lg:rtds-max-w-24"
  },
  "items": [
    {
      "title": "Torna alla pagina precedente"
    }
  ],
  "titleSuffix": "",
  "description": ""
}
  • Content:
    /* base style */
    .rtds-context-menu {
        position: relative;
        border-bottom-width: 2px;
            border-color: var(--color-border-gray-02);
    }
    .rtds-context-menu__container {
        gap: var(--spacing-4);
        padding-top: var(--spacing-4);
        padding-bottom: var(--spacing-2);
        display: grid;
        align-items: center;
    }
    @media (min-width: 768px) {
        .rtds-context-menu__container {
            padding-bottom: var(--spacing-2-5);
        }
    }
    @media (min-width: 1024px) {
        .rtds-context-menu__container {
            display: flex;
            padding-top: var(--spacing-3);
            padding-bottom: var(--spacing-3);
        }
    }
    .rtds-context-menu__header {
            color: var(--color-content-02);
        display: flex;
        align-items: center;
        gap: var(--spacing-2);
    }
    .rtds-context-menu__nav {
        display: flex;
    }
    .rtds-context-menu__list-container {
        position: absolute;
        top: 100%;
        left: var(--spacing-0);
        z-index: 50;
        width: 100%;
        border-bottom-width: 2px;
        border-top-width: 2px;
        --tw-bg-opacity: 1;
        background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
        padding-top: var(--spacing-4);
        padding-bottom: var(--spacing-4);
            border-color: var(--color-border-gray-02);
    }
    .rtds-context-menu__list-container.is-open {
        display: flex;
        justify-content: center;
    }
    /* interactivity */
    :where(.rtds-context-menu__toggle-text.is-show-less) {
        display: none;
    }
    :where(.has-dropdown-open .rtds-context-menu__toggle-text.is-show-more) {
        display: none;
    }
    :where(.has-dropdown-open .rtds-context-menu__toggle-text.is-show-less) {
        display: block;
    }
    .rtds-context-menu__trigger .rtds-icon {
        transition-property: all;
        transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
        transition-duration: 150ms;
    }
    .rtds-context-menu__trigger:where([aria-expanded="true"]) .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-MENU-CARD */
    .rtds-menu-card {
        --tw-bg-opacity: 1;
        background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
        padding: var(--spacing-6);
        background-image: var(--gradient-04);
    }
    .rtds-menu-card__link {
        flex-direction: column;
        display: flex;
        gap: var(--spacing-2);
    }
    .rtds-menu-card__title {
            color: var(--color-content-02);
        }
    .rtds-menu-card__text {
        font-size: var(--fontsize-text-sm);
            color: var(--color-content-01);
    }
    .rtds-context-menu__item--more {
        grid-column: 1 / -1;
        display: flex;
        justify-content: center;
        align-items: center;
    }
    
  • URL: /components/raw/context-menu/context-menu.built.css
  • Filesystem Path: components/04-organisms/context-menu/context-menu.built.css
  • Size: 2.7 KB
  • Content:
    @layer components {
        /* base style */
        .rtds-context-menu {
            @apply rtds-border-b-2 rtds-border-gray-02 rtds-relative;
        }
    
        .rtds-context-menu__container {
            @apply rtds-grid lg:rtds-flex rtds-pt-4 rtds-pb-2 md:rtds-pb-2.5 lg:rtds-py-3 rtds-gap-4 rtds-items-center;
        }
    
        .rtds-context-menu__header {
            @apply rtds-flex rtds-items-center rtds-gap-2 rtds-content-02;
        }
    
        .rtds-context-menu__nav {
            @apply rtds-flex;
        }
    
        .rtds-context-menu__list-container {
            @apply rtds-absolute rtds-top-full rtds-left-0 rtds-w-full rtds-bg-white rtds-z-50 rtds-py-4 rtds-border-b-2 rtds-border-t-2 rtds-border-gray-02;
        }
    
        .rtds-context-menu__list-container.is-open {
            @apply rtds-flex rtds-justify-center;
        }
    
    
        /* interactivity */
        :where(.rtds-context-menu__toggle-text.is-show-less) {
            @apply rtds-hidden;
        }
    
        :where(.has-dropdown-open .rtds-context-menu__toggle-text.is-show-more) {
            @apply rtds-hidden;
        }
    
        :where(.has-dropdown-open .rtds-context-menu__toggle-text.is-show-less) {
            @apply rtds-block;
        }
    
        .rtds-context-menu__trigger .rtds-icon {
            @apply rtds-transition-all;
        }
    
        .rtds-context-menu__trigger:where([aria-expanded="true"]) .rtds-icon {
            @apply -rtds-rotate-180;
        }
    
        /* RTDS-MENU-CARD */
        .rtds-menu-card {
            @apply rtds-bg-white rtds-p-6 rtds-bg-gradient-04;
        }
    
        .rtds-menu-card__link {
            @apply rtds-flex rtds-flex-col rtds-gap-2;
        }
    
        .rtds-menu-card__title {
            @apply rtds-content-02;
        }
    
        .rtds-menu-card__text {
            @apply rtds-text-sm rtds-content-01;
        }
    
        .rtds-context-menu__item--more {
            @apply rtds-col-span-full rtds-flex rtds-justify-center rtds-items-center;
        }
    
    
    }
  • URL: /components/raw/context-menu/context-menu.css
  • Filesystem Path: components/04-organisms/context-menu/context-menu.css
  • Size: 1.8 KB

Context Menu

Il componente Context Menu è un organismo che implementa un menu di navigazione contestuale con dropdown per la visualizzazione di argomenti correlati.

Comportamento

Il componente offre le seguenti funzionalità:

  1. Menu Dropdown: Un pulsante che permette di espandere/collassare una lista di argomenti correlati
  2. Navigazione Contestuale: Link rapidi per approfondimenti e servizi correlati
  3. Responsive: Layout adattivo che si modifica in base alla dimensione dello schermo
  4. Stato Attivo: Supporto per la visualizzazione dell’argomento attualmente selezionato

Accessibilità

WCAG 2.1

Livello AA — criteri pertinenti:

  • 1.3.1 Informazioni e correlazioni — struttura con <section>, <nav> e liste semantiche
  • 4.1.2 Nome, Ruolo, Valore — pulsante dropdown usa aria-expanded e aria-controls; la navigazione usa aria-labelledby
  • 2.1.1 Tastiera — tutti i controlli interattivi sono raggiungibili e attivabili da tastiera

Struttura e semantica

  • Il componente è renderizzato come <section class="rtds-context-menu"> — identifica il menu contestuale come regione autonoma
  • La navigazione è un <nav> con aria-labelledby="contextMenuTitle" — collegato al titolo del menu contestuale tramite id
  • Il titolo è un elemento <span id="contextMenuTitle"> — usato come label del <nav>
  • Il link al titolo ha <span class="rtds-sr-only">Homepage del tema: </span> per fornire contesto aggiuntivo agli screen reader

Attributi ARIA

Attributo Valori Condizione
aria-labelledby su <nav> "contextMenuTitle" sempre presente — collega la nav al titolo
aria-expanded su .rtds-context-menu__trigger "false" / "true" gestito da JavaScript all’apertura/chiusura del dropdown
aria-controls su .rtds-context-menu__trigger "contextMenu01" sempre presente — riferimento al contenitore del dropdown
Tasto Azione
Tab / Shift+Tab Sposta il focus tra i controlli del menu
Enter / Space Attiva il pulsante trigger per aprire/chiudere il dropdown
Escape Chiude il dropdown (gestito da JavaScript)

Gestione del focus

  • Focus iniziale: nessun focus automatico all’apertura della pagina
  • Focus trap: non implementato nel template — il dropdown si apre in contesto di navigazione nella pagina
  • Focus visibile: lo stile :focus-visible è sempre visibile e non viene rimosso via CSS

Screen reader

  • Il testo <span class="rtds-sr-only">Homepage del tema: </span> nel link al titolo aggiunge contesto alla destinazione
  • La navigazione è annunciata con il nome del tema grazie ad aria-labelledby
  • Il pulsante dropdown annuncia il proprio stato espanso/collassato tramite aria-expanded
  • La classe rtds-sr-only md:rtds-not-sr-only rende il testo “Tutti gli argomenti” visibile solo su desktop, visibile agli screen reader su tutti i breakpoint

Struttura

Il componente è strutturato in tre sezioni principali:

  • Header con logo e titolo
  • Menu di navigazione con dropdown per gli argomenti
  • Link rapidi per approfondimenti e servizi

Configurazioni - sviluppo in NJK

Il componente può essere configurato attraverso il file context-menu.config.yml. Ecco una spiegazione dettagliata dei parametri disponibili:

Parametri Principali

title

  • Tipo: Stringa
  • Descrizione: Titolo principale del menu contestuale
  • Utilizzo: Viene visualizzato come link principale nell’header
  • Esempio:
    title: "Beni, Servizi e Lavori pubblici"

titlePrefix e titleSuffix

  • Tipo: Stringa (HTML)
  • Descrizione: Testo opzionale da visualizzare prima e dopo il titolo principale
  • Utilizzo: Permette di aggiungere contesto o formattazione al titolo
  • Esempio:
    titlePrefix: "<span class='rtds-text-sm'>Area:</span>"
    titleSuffix: "<span class='rtds-text-xs'>Ultimo aggiornamento: 2024</span>"

description

  • Tipo: Stringa (HTML)
  • Descrizione: Descrizione opzionale del menu contestuale
  • Utilizzo: Visibile su schermi grandi (lg e superiori)
  • Esempio:
    description: "Esplora le tematiche relative ai beni, servizi e lavori pubblici"
  • Tipo: Stringa
  • Descrizione: Classi CSS per il layout a griglia del menu
  • Utilizzo: Controlla il numero di colonne su diversi breakpoint
  • Esempio:
    menuListGridClasses: "md:rtds-grid-cols-2 lg:rtds-grid-cols-4 xl:rtds-grid-cols-5"
  • Tipo: Oggetto
  • Descrizione: Configurazione del logo
  • Proprietà:
    • path: Percorso dell’immagine
    • width: Larghezza del logo
    • height: Altezza del logo
    • classes: Classi CSS per il dimensionamento responsive
  • Esempio:
    logo:
      path: '/images/icona-tema-sociale.svg'
      width: '118'
      height: '24'
      classes: 'rtds-max-w-16 md:rtds-max-w-20 lg:rtds-max-w-24'

items

  • Tipo: Array di oggetti
  • Descrizione: Lista degli argomenti nel menu dropdown
  • Proprietà per ogni item:
    • title: Titolo dell’argomento (obbligatorio)
    • text: Descrizione breve (obbligatorio)
    • url: Link di destinazione (obbligatorio)
    • isActive: Stato attivo (opzionale, booleano)
  • Esempio:
    items:
      - title: "Terza età"
        text: "Le politiche della Regione per le persone anziane."
        url: "#"
      - title: "Carcere"
        text: "I progetti di supporto ai percorsi di riabilitazione."
        url: "#"
        isActive: true

Varianti

Il componente supporta diverse varianti predefinite, ognuna ottimizzata per un numero specifico di elementi:

  1. default

    • Layout standard con 5 colonne su schermi extra-large
    • Utilizza le classi grid: md:rtds-grid-cols-2 lg:rtds-grid-cols-4 xl:rtds-grid-cols-5
    • Ideale per menu con 5 o più elementi
  2. 2-cols

    • Layout a 2 colonne su desktop
    • Utilizza le classi grid: md:rtds-grid-cols-2
    • Ottimale per menu con 2 o meno elementi
  3. 3-cols

    • Layout a 3 colonne su desktop
    • Utilizza le classi grid: md:rtds-grid-cols-2 lg:rtds-grid-cols-3
    • Ideale per menu con esattamente 3 elementi
  4. 4-cols

    • Layout a 4 colonne su desktop
    • Utilizza le classi grid: md:rtds-grid-cols-2 lg:rtds-grid-cols-4
    • Ottimale per menu con 4 elementi
  5. backlink-only

    • Versione semplificata con solo link di ritorno
    • Rimuove il dropdown e i link rapidi
    • Ideale per la navigazione di ritorno
  6. has-description

    • Versione con descrizione aggiuntiva
    • Include un separatore e una descrizione testuale
    • Utile per contestualizzare meglio il menu

Classi CSS

  • rtds-context-menu: Contenitore principale del componente
  • rtds-context-menu__container: Contenitore del contenuto
  • rtds-context-menu__header: Sezione header con logo e titolo
  • rtds-context-menu__title: Titolo del menu
  • rtds-context-menu__description: Descrizione opzionale
  • rtds-context-menu__nav: Menu di navigazione
  • rtds-context-menu__nav-list: Lista degli elementi di navigazione
  • rtds-context-menu__trigger: Pulsante per il dropdown
  • rtds-context-menu__list-container: Contenitore del menu dropdown
  • rtds-context-menu__list: Lista degli argomenti nel dropdown
  • rtds-context-menu__item: Singolo elemento del menu
  • rtds-context-menu__link: Link dell’elemento del menu
  • rtds-context-menu__item--more: Elemento “mostra di più”