fix(ui): refine responsive catalog navigation
Quality / quality (ubuntu-latest) (push) Failing after 9m54s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-08-25 13:46:19 +05:30
parent 9f6552ea62
commit 64db7da08d
6 changed files with 104 additions and 29 deletions
+42 -20
View File
@@ -100,19 +100,29 @@ size: string = "default"
}
return [{ heading: item.description || "", items: legacy }]
}
client function toggleNavigation() {
mobileOpen = !mobileOpen
output.toggle({ open: mobileOpen })
output[mobileOpen ? "open" : "close"]({ source: "mobile" })
client function setMobileNavigation(open, trigger) {
const root = trigger && trigger.closest ? trigger.closest("[data-wrn-navbar]") : null
if (!root) return
const collapse = root.querySelector(".wrn-navbar__collapse")
const toggle = root.querySelector(".wrn-navbar__toggle")
if (collapse) collapse.classList.toggle("is-open", open)
if (toggle) toggle.setAttribute("aria-expanded", open ? "true" : "false")
}
client function selectItem(item, level) {
mobileOpen = false
client function toggleNavigation(event) {
const open = event.currentTarget.getAttribute("aria-expanded") !== "true"
setMobileNavigation(open, event.currentTarget)
output.toggle({ open: open })
output[open ? "open" : "close"]({ source: "mobile" })
}
client function selectItem(item, level, event) {
setMobileNavigation(false, event.currentTarget)
output.select({ item: item, value: item.value || "", level: level })
}
client function selectAction(item) {
mobileOpen = false
client function selectAction(item, event) {
setMobileNavigation(false, event.currentTarget)
output.action({ item: item, value: item.value || "" })
}
@@ -161,6 +171,7 @@ size: string = "default"
</div>
<div class="wrn-navbar__main">
<slot name="brand">
{#if brand.logo || brand.icon || brand.label || brand.description}
<a class="wrn-navbar__brand" href="{brand.href || '/'}" aria-label="{brand.ariaLabel || brand.label || label}">
{#if brand.logo}
@@ -177,6 +188,7 @@ size: string = "default"
{/if}
</a>
{/if}
</slot>
<div class="wrn-navbar__collapse {mobileOpen ? 'is-open' : ''}">
<nav class="wrn-navbar__menus" aria-label="{label}" data-wrn-roving="horizontal">
@@ -187,22 +199,26 @@ size: string = "default"
data-active="{isItemActive(item) ? 'true' : 'false'}"
label="{item.label}"
icon="{item.icon || ''}"
columns="{megaColumns(item)}"
rail="{megaData(item).rail || []}"
featured="{megaData(item).featured || {}}"
columns={megaColumns(item)}
rail={megaData(item).rail || []}
featured={megaData(item).featured || {}}
variant="{megaData(item).variant || 'default'}"
density="{megaData(item).density || 'default'}"
panelWidth="{megaData(item).panelWidth || 'xl'}"
panelAlign="{megaData(item).panelAlign || 'start'}"
columnCount="{megaData(item).columnCount || 0}"
fullWidth="{megaData(item).fullWidth || false}"
openOnHover="{openOnHover}"
columnCount={megaData(item).columnCount || 0}
fullWidth={megaData(item).fullWidth || false}
openOnHover={openOnHover}
activeCategory="{megaData(item).activeCategory || ''}"
actionLabel="{megaData(item).actionLabel || ''}"
actionHref="{megaData(item).actionHref || ''}"
actionIcon="{megaData(item).actionIcon || 'icon-[lucide--arrow-right]'}"
footer="{megaData(item).footer || ''}"
/>
<a class="wrn-navbar__menu-link wrn-navbar__mobile-mega-link" data-wrn-roving-item="true" href="{item.href || megaData(item).actionHref || '#'}" target="{item.target || ''}" rel="{item.rel || ''}" aria-current="{isItemActive(item) ? 'page' : 'false'}" @click="selectItem(item, 1, event)">
{#if item.icon}<span class="{item.icon}" aria-hidden="true"></span>{/if}
<span data-t="{translationKey(item, 'label')}">{item.label}</span>
</a>
{:else if itemType(item) === "dropdown"}
<details class="wrn-navbar__dropdown wrn-navbar__dropdown--{item.type || 'dropdown'}" name="wrn-navbar-menu" @toggle="toggleDropdown(event, item)">
<summary data-wrn-roving-item="true" aria-current="{isItemActive(item) ? 'page' : 'false'}">
@@ -218,13 +234,13 @@ size: string = "default"
{#if child.label}<strong class="wrn-navbar__group-title" data-t="{translationKey(child, 'label')}">{child.label}</strong>{/if}
{#if child.description}<small data-t="{translationKey(child, 'description')}">{child.description}</small>{/if}
{#each dropdownGroupItems(child) as nested}
<a href="{nested.href || '#'}" target="{nested.target || ''}" rel="{nested.rel || ''}" aria-current="{nested.value === active ? 'page' : 'false'}" @click="selectItem(nested, 3)">
<a href="{nested.href || '#'}" target="{nested.target || ''}" rel="{nested.rel || ''}" aria-current="{nested.value === active ? 'page' : 'false'}" @click="selectItem(nested, 3, event)">
{#if nested.icon}<span class="{nested.icon}" aria-hidden="true"></span>{/if}
<span><strong data-t="{translationKey(nested, 'label')}">{nested.label}</strong>{#if nested.description}<small data-t="{translationKey(nested, 'description')}">{nested.description}</small>{/if}</span>
</a>
{/each}
{:else}
<a href="{child.href || '#'}" target="{child.target || ''}" rel="{child.rel || ''}" aria-current="{child.value === active ? 'page' : 'false'}" @click="selectItem(child, 2)">
<a href="{child.href || '#'}" target="{child.target || ''}" rel="{child.rel || ''}" aria-current="{child.value === active ? 'page' : 'false'}" @click="selectItem(child, 2, event)">
{#if child.icon}<span class="{child.icon}" aria-hidden="true"></span>{/if}
<span><strong data-t="{translationKey(child, 'label')}">{child.label}</strong>{#if child.description}<small data-t="{translationKey(child, 'description')}">{child.description}</small>{/if}</span>
</a>
@@ -234,7 +250,7 @@ size: string = "default"
</div>
</details>
{:else}
<a class="wrn-navbar__menu-link" data-wrn-roving-item="true" href="{item.href || '#'}" target="{item.target || ''}" rel="{item.rel || ''}" aria-current="{item.value === active ? 'page' : 'false'}" @click="selectItem(item, 1)">
<a class="wrn-navbar__menu-link" data-wrn-roving-item="true" href="{item.href || '#'}" target="{item.target || ''}" rel="{item.rel || ''}" aria-current="{item.value === active ? 'page' : 'false'}" @click="selectItem(item, 1, event)">
{#if item.icon}<span class="{item.icon}" aria-hidden="true"></span>{/if}
<span data-t="{translationKey(item, 'label')}">{item.label}</span>
</a>
@@ -243,19 +259,19 @@ size: string = "default"
</nav>
<div class="wrn-navbar__actions">
<slot name="actions" />
{#each actions as item}
<a class="wrn-navbar__action wrn-navbar__action--{item.variant || 'link'}" href="{item.href || '#'}" target="{item.target || ''}" rel="{item.rel || ''}" @click="selectAction(item)">
<a class="wrn-navbar__action wrn-navbar__action--{item.variant || 'link'}" href="{item.href || '#'}" target="{item.target || ''}" rel="{item.rel || ''}" @click="selectAction(item, event)">
{#if item.icon}<span class="{item.icon}" aria-hidden="true"></span>{/if}
<span data-t="{translationKey(item, 'label')}">{item.label}</span>
</a>
{/each}
<slot name="actions" />
</div>
</div>
<div class="wrn-navbar__utilities"><slot name="utilities" /></div>
<button type="button" class="wrn-navbar__toggle" aria-label="{mobileLabel}" aria-expanded="{mobileOpen}" @click="toggleNavigation()">
<button type="button" class="wrn-navbar__toggle" aria-label="{mobileLabel}" aria-expanded="{mobileOpen}" @click="toggleNavigation(event)">
<span aria-hidden="true"></span><span aria-hidden="true"></span><span aria-hidden="true"></span>
</button>
</div>
@@ -672,6 +688,8 @@ size: string = "default"
background: currentColor;
}
.wrn-navbar__mobile-mega-link { display: none; }
@media (max-width: 900px) {
.wrn-navbar__main {
min-height: 3.5rem;
@@ -724,6 +742,8 @@ size: string = "default"
.wrn-navbar__mega .wrn-mega__trigger {
width: 100%;
}
.wrn-navbar__mega { display: none; }
.wrn-navbar__mobile-mega-link { display: flex; }
.wrn-navbar__menu-link,
.wrn-navbar__dropdown > summary,
.wrn-navbar__action {
@@ -785,6 +805,8 @@ size: string = "default"
}
.wrn-navbar[data-collapse-at="1100px"] :is(.wrn-navbar__menu-link, .wrn-navbar__dropdown > summary, .wrn-navbar__action) { width: 100%; }
.wrn-navbar[data-collapse-at="1100px"] :is(.wrn-navbar__mega, .wrn-navbar__mega .wrn-mega__trigger) { width: 100%; }
.wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__mega { display: none; }
.wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__mobile-mega-link { display: flex; }
.wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__panel { position: static; width: 100%; max-width: none; transform: none; }
.wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__mega[data-full-width="true"] .wrn-mega__panel { position: static; width: 100%; max-width: 100%; margin-top: 0.25rem; }
}