81 lines
4.8 KiB
HTML
81 lines
4.8 KiB
HTML
{#
|
|
UI/UX V2 Phase 1A — Desktop navigation component (INERT UNTIL INCLUDED)
|
|
|
|
Expected optional context:
|
|
navigation_items_v2: list of mappings with:
|
|
label (required), url, active, visible, badge, children
|
|
navigation_aria_label_v2: accessible label (default: "Primary navigation")
|
|
|
|
The component is deliberately data-driven and contains no role or permission
|
|
assumptions. A later role pilot will build navigation_items_v2 from the
|
|
existing permission helpers without changing current access rules.
|
|
#}
|
|
{% set _nav_items = navigation_items_v2|default([], true) %}
|
|
{% set _nav_label = navigation_aria_label_v2|default('Primary navigation', true) %}
|
|
|
|
{% if _nav_items %}
|
|
<nav aria-label="{{ _nav_label }}" class="hidden border-b border-slate-200 bg-white lg:block" data-uiux-v2="desktop-navigation">
|
|
<div class="mx-auto max-w-[1500px] px-4 sm:px-6 lg:px-8">
|
|
<ul class="flex min-h-12 items-stretch gap-1" role="list">
|
|
{% for item in _nav_items %}
|
|
{% set _visible = item.get('visible', true) %}
|
|
{% set _children = item.get('children', []) or [] %}
|
|
{% set _active = item.get('active', false) %}
|
|
{% if _visible %}
|
|
<li class="relative flex items-stretch">
|
|
{% if _children %}
|
|
<details class="group relative flex items-stretch">
|
|
<summary
|
|
class="flex cursor-pointer list-none items-center gap-2 border-b-2 px-3 py-3 text-sm font-semibold transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-2 {{ 'border-brand-600 text-brand-700' if _active else 'border-transparent text-slate-700 hover:border-slate-300 hover:text-slate-950' }}"
|
|
aria-haspopup="menu"
|
|
>
|
|
<span>{{ item.get('label', '') }}</span>
|
|
{% if item.get('badge') is not none %}
|
|
<span class="rounded-full bg-brand-50 px-2 py-0.5 text-[11px] font-bold text-brand-700">{{ item.get('badge') }}</span>
|
|
{% endif %}
|
|
<svg class="h-4 w-4 transition-transform group-open:rotate-180" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
<path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 0 1 1.06.02L10 11.168l3.71-3.938a.75.75 0 1 1 1.08 1.04l-4.25 4.51a.75.75 0 0 1-1.08 0l-4.25-4.51a.75.75 0 0 1 .02-1.06Z" clip-rule="evenodd" />
|
|
</svg>
|
|
</summary>
|
|
|
|
<div class="absolute left-0 top-full z-50 mt-1 min-w-64 overflow-hidden rounded-2xl border border-slate-200 bg-white p-2 shadow-card" role="menu">
|
|
{% for child in _children %}
|
|
{% if child.get('visible', true) %}
|
|
{% set _child_active = child.get('active', false) %}
|
|
<a
|
|
href="{{ child.get('url', '#') }}"
|
|
class="flex items-center justify-between gap-3 rounded-xl px-3 py-2.5 text-sm font-medium transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 {{ 'bg-brand-50 text-brand-700' if _child_active else 'text-slate-700 hover:bg-slate-50 hover:text-slate-950' }}"
|
|
role="menuitem"
|
|
{% if _child_active %}aria-current="page"{% endif %}
|
|
{% if child.get('external', false) %}target="_blank" rel="noopener noreferrer"{% endif %}
|
|
>
|
|
<span>{{ child.get('label', '') }}</span>
|
|
{% if child.get('badge') is not none %}
|
|
<span class="rounded-full bg-slate-100 px-2 py-0.5 text-[11px] font-bold text-slate-600">{{ child.get('badge') }}</span>
|
|
{% endif %}
|
|
</a>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</div>
|
|
</details>
|
|
{% else %}
|
|
<a
|
|
href="{{ item.get('url', '#') }}"
|
|
class="flex items-center gap-2 border-b-2 px-3 py-3 text-sm font-semibold transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-2 {{ 'border-brand-600 text-brand-700' if _active else 'border-transparent text-slate-700 hover:border-slate-300 hover:text-slate-950' }}"
|
|
{% if _active %}aria-current="page"{% endif %}
|
|
{% if item.get('external', false) %}target="_blank" rel="noopener noreferrer"{% endif %}
|
|
>
|
|
<span>{{ item.get('label', '') }}</span>
|
|
{% if item.get('badge') is not none %}
|
|
<span class="rounded-full bg-brand-50 px-2 py-0.5 text-[11px] font-bold text-brand-700">{{ item.get('badge') }}</span>
|
|
{% endif %}
|
|
</a>
|
|
{% endif %}
|
|
</li>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</ul>
|
|
</div>
|
|
</nav>
|
|
{% endif %}
|