Files
VITEC-website/packages/evo_megamenu_json/README.md
T
orascheandClaude Fable 5 6423b7c7f8 Megamenu goes visual: spotlight layout, page images on pagetree columns
- customer wish (via Olli, 2026-10-27): a more visual main menu in the
  style of rossvideo.com - image cards instead of plain link lists; for
  Insights a left-rail submenu whose hover swaps a visual area showing
  the latest news and the next events
- new entry layout "spotlight" in evo_megamenu_json, built strictly on
  the catalog pattern so the extension stays project-neutral: `nav` is
  a flat rail from the linked page's live children (abstract as teaser,
  first page media as 640px-webp image from stage 2 - the hover swap
  material), `spotlight` is emitted verbatim from the new
  BuildSpotlightEvent (null without a listener); curated columns are
  ignored like on pagetree
- new vitec listener ProvideInsightsSpotlight supplies the cards: the
  three latest news (storage pid 11, type 0 - the Solr convention;
  link /news/article/<path_segment> per the NewsDetail route enhancer;
  fal_media as processed 640px webp) and the next two events
  (hideonwebsite = 0, upcoming by eventstart/eventend; link = eventurl
  or the events page)
- pagetree columns can now carry an image (stage 2+, first page media
  of the column's page): attach images in the page properties and the
  markets/solutions panels turn into image cards without further code
- TCA select and label extended; README brought up to date (the
  pagetree layout had never been documented) with the spotlight JSON
  contract, reference mirror synced; frontend briefing updated
- activation is editorial: switch the Insights menu entry to the
  spotlight layout and link it to the Insights page

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-27 11:47:23 +01:00

6.3 KiB

EVO Megamenu JSON

An editable megamenu for headless TYPO3. One content element holds the whole menu; the extension publishes it as JSON, the front end renders it.

Project-neutral by design — nothing in here knows which site it runs on.

What the editor gets

A plugin called Megamenu. Inside it:

Level Holds
Entry one item in the main bar: label, target page, panel layout
Column a heading (optionally a link) and its items
Item label, link, teaser line, badge, thumbnail, “page not ready” flag
Teaser card kicker, headline, text, link, image — for editorial panels
Featured one highlighted block per entry, edited on the entry itself

Five panel layouts per entry: columns for a curated structure menu, teasers for a small link column next to cards (news, stories), pagetree for a structure menu built live from the page tree, catalog for a data-driven panel whose content comes from the site package, and spotlight for a visual panel with a left-rail nav and live content cards (see below).

Installation

composer require evomedien/evo-megamenu-json
vendor/bin/typo3 extension:setup
vendor/bin/typo3 database:updateschema "*.add,*.change"

In the site configuration, add the set EVO Megamenu (JSON) and set:

Setting Meaning

| megamenu.contentUid | uid of the Megamenu element to publish on every page | | megamenu.storagePid | alternative: folder whose first Megamenu element is used |

Leave both uid and pid at 0 and the menu is only rendered where the element sits — useful while building it.

Payload

"megaMenu": {
  "settings": {
    "stage": 3, "openOn": "hover", "closeDelay": 140, "columnsPerRow": 4,
    "panelWidth": "container", "pendingBehaviour": "fallback",
    "showCounts": true, "showViewAll": true, "viewAllLabel": "View all %s"
  },
  "entries": [
    {
      "title": "Products",
      "link": "/products",
      "layout": "columns",
      "columns": [
        {
          "title": "IP Video Streaming",
          "link": "/products/ip-video-streaming",
          "items": [
            { "title": "Appliances", "link": "/products/ip-video-streaming/appliances",
              "pending": true, "teaser": "MGW Diamond, Ace, Pico",
              "image": { "url": "/fileadmin/...", "alternative": "", "title": "", "width": 600, "height": 400 } }
          ]
        }
      ],
      "featured": { "kicker": "Datasheet", "title": "MGW Diamond-H", "text": "…", "link": "/product/…", "image": { } }
    }
  ]
}

settings travels with the menu on purpose: the front end reads hover behaviour, close delay, column count and labels from the payload instead of hard-coding them, so an editor can change them without a deploy.

Content stages

stage decides how much detail is emitted — 1 structure only, 2 adds images, teaser lines and cards, 3 adds the featured block. Later stages only add keys, so a front end written for stage 1 keeps working when the stage is raised.

pending

An item whose target page does not exist yet carries "pending": true. settings.pendingBehaviour says what to do with it: fallback (link to the column heading instead), mute (show, not clickable) or hide. This keeps a menu shippable while its deeper pages are still being built.

Layout catalog

For panels built from data rather than by hand — a product catalog with categories, groups and items, a search bar, whatever the site needs. The extension stays project-neutral: it dispatches Evomedien\EvoMegamenuJson\Event\BuildCatalogEvent for every catalog entry and emits whatever a listener sets via setCatalog() verbatim as catalog on the entry (null without a listener). The entry's teaser cards are emitted as teasers as usual and serve as the panel's featured tiles; its columns are ignored.

#[AsEventListener(identifier: 'site/megamenu-catalog')]
final class ProvideCatalog
{
    public function __invoke(BuildCatalogEvent $event): void
    {
        $event->setCatalog(['categories' => [/* … */]]);
    }
}

getEntry() hands the listener the raw entry row (to tell several catalog entries apart), getStage() the content stage.

Layout pagetree

A structure panel that can never age against the site: the columns mirror the live subtree of the page the entry links to - one column per child page, its children as the items. Hidden or nav-hidden pages leave the menu with the next cache flush. Curated columns are ignored; teasers and the featured slot stay editorial. From stage 2 a child page with media gets its first image as image on the column - attach images in the page properties and the panel turns visual by itself.

Layout spotlight

A visual panel ("rossvideo style"): nav is a flat left rail built live from the linked page's children - each item with title, link and, from stage 2, the page abstract as teaser plus the first page media as image, so the front end can swap the visual area on hover. Next to it the extension emits spotlight, filled by the site package: it dispatches Evomedien\EvoMegamenuJson\Event\BuildSpotlightEvent per spotlight entry and emits whatever a listener sets via setSpotlight() verbatim (null without a listener). Curated columns are ignored.

The VITEC site package ships ProvideInsightsSpotlight, which supplies

"spotlight": {
  "news":   [ {"title", "date", "link", "teaser?", "image?"} ],
  "events": [ {"title", "start", "end", "venue", "booth", "city",
               "country", "attendanceMode", "link", "teaser?", "image?"} ]
}
  • news: the three latest news records (storage pid 11, type 0 - the Solr convention), link = /news/article/<path_segment> per the NewsDetail route enhancer, image from fal_media as processed 640px webp.
  • events: the next two events (hideonwebsite = 0, upcoming by eventstart/eventend), link = the record's eventurl or the events page, image processed the same way.

Notes

  • Every link is a resolved URL — page, record, external or file, run through typolink at render time.
  • Translations are overlaid per record, so a menu can be localised entry by entry.
  • The renderer never throws: a broken menu returns an empty value rather than taking the page payload down.
  • Without friendsoftypo3/headless the element has no JSON envelope to render into — the extension is built for headless installations.