Module:ElementHubNavigation: Difference between revisions

// via Wikitext Extension for VSCode
 
// via Wikitext Extension for VSCode
Line 4: Line 4:
* Description: Hub navigation module for Main Page with zero-CLS responsive design
* Description: Hub navigation module for Main Page with zero-CLS responsive design
* Notes: Single SSR block with data-URI icons; mobile sticky bottom bar; desktop inline grid
* Notes: Single SSR block with data-URI icons; mobile sticky bottom bar; desktop inline grid
* Uses mw.html builder to prevent HTML escaping
]]
]]


Line 26: Line 27:
}
}


-- Generate a single hub link item
-- Generate a single hub link item using mw.html
local function generateHubLink(hub)
local function generateHubLink(hub)
     local parts = {
     local li = mw.html.create('li'):addClass('cdx-hub__item')
        '<li class="cdx-hub__item">',
   
         string.format('<a href="/wiki/%s" class="cdx-hub__link" data-hub="%s">', hub.url, hub.id),
    local a = li:tag('a')
        '<span class="cdx-hub__icon">',
         :attr('href', '/wiki/' .. hub.url)
         string.format('<img src="%s" alt="" width="24" height="24" aria-hidden="true">', hub.icon),
        :addClass('cdx-hub__link')
         '</span>',
        :attr('data-hub', hub.id)
         string.format('<span class="cdx-hub__label">%s</span>', hub.label),
   
         '</a>',
    -- Icon span with img
         '</li>'
    local iconSpan = a:tag('span'):addClass('cdx-hub__icon')
     }
    iconSpan:tag('img')
     return table.concat(parts)
         :attr('src', hub.icon)
        :attr('alt', '')
         :attr('width', '24')
         :attr('height', '24')
         :attr('aria-hidden', 'true')
   
    -- Label span
    a:tag('span')
         :addClass('cdx-hub__label')
        :wikitext(hub.label)
      
     return tostring(li)
end
end


-- Main render function
-- Main render function
function p.render(frame)
function p.render(frame)
     -- Build hub links
     -- Create main hub container
     local hubLinks = {}
    local container = mw.html.create('div')
     for i, hub in ipairs(hubs) do
        :attr('id', 'hub')
         hubLinks[i] = generateHubLink(hub)
        :addClass('cdx-hub')
        :attr('role', 'navigation')
        :attr('aria-label', 'Hub Navigation')
   
    -- Create list
     local ul = container:tag('ul'):addClass('cdx-hub__list')
   
    -- Add hub links
     for _, hub in ipairs(hubs) do
         ul:wikitext(generateHubLink(hub))
     end
     end
      
      
     -- Construct the complete hub navigation markup
     -- Add empty panel for future use
    container:tag('div')
        :addClass('cdx-hub__panel')
        :attr('aria-hidden', 'true')
   
    -- Create spacer
    local spacer = mw.html.create('div')
        :attr('id', 'hub-spacer')
        :attr('aria-hidden', 'true')
   
    -- Wrap in MediaWiki table syntax for compatibility
     local output = {
     local output = {
         '{| class="hub-nav-table"',
         '{| class="hub-nav-table"',
         '|- class="hub-nav-row"',
         '|- class="hub-nav-row"',
         '| colspan="2" |',
         '| colspan="2" |',
         '<div id="hub" class="cdx-hub" role="navigation" aria-label="Hub Navigation">',
         tostring(container),
        '  <ul class="cdx-hub__list">',
         tostring(spacer),
        '    ' .. table.concat(hubLinks, '\n    '),
         '  </ul>',
        '  <div class="cdx-hub__panel" aria-hidden="true"></div>',
        '</div>',
        '<div id="hub-spacer" aria-hidden="true"></div>',
         '|}'
         '|}'
     }
     }