192 lines
7.2 KiB
PHP
192 lines
7.2 KiB
PHP
@php
|
|
$items = $items ?? [];
|
|
$active = $active ?? null;
|
|
$mode = $mode ?? 'side';
|
|
$isShop = $isShop ?? false;
|
|
$title = $title ?? null;
|
|
|
|
// 현재 활성화된 아이템 찾기
|
|
$activeItem = collect($items)->first(function($it) use ($active, $isShop) {
|
|
if($isShop) return $active == $it['id'];
|
|
return $active === ($it['key'] ?? $it['url']);
|
|
});
|
|
|
|
if (!$activeItem && $isShop) {
|
|
foreach($items as $it) {
|
|
if(!empty($it['children'])) {
|
|
$child = collect($it['children'])->firstWhere('id', $active);
|
|
if($child) { $activeItem = $child; break; }
|
|
}
|
|
}
|
|
}
|
|
@endphp
|
|
|
|
@if($mode === 'tabs')
|
|
{{-- 모바일 전용: 한 줄에 2개씩 배치되는 그리드 디자인 --}}
|
|
<nav class="mobile-subnav-grid" aria-label="모바일 카테고리">
|
|
<div class="m-grid-container">
|
|
@foreach($items as $it)
|
|
@php
|
|
$isActive = $isShop ? ($active == $it['id']) : ($active && $active === ($it['key'] ?? $it['url']));
|
|
$hasActiveChild = $isShop && !empty($it['children']) && collect($it['children'])->contains('id', $active);
|
|
$isOpen = $isActive || $hasActiveChild;
|
|
@endphp
|
|
|
|
<div class="m-grid-item {{ $isOpen ? 'is-open' : '' }}">
|
|
<a href="{{ $it['url'] ?? '#' }}"
|
|
class="m-grid-link {{ $isOpen ? 'is-active' : '' }}">
|
|
{{ $it['label'] ?? '' }}
|
|
</a>
|
|
|
|
{{-- 1차 메뉴 활성 시 2차 메뉴 노출 (그리드 아래로 펼쳐짐) --}}
|
|
@if($isShop && !empty($it['children']) && $isOpen)
|
|
<div class="m-grid-sub-wrap">
|
|
@foreach($it['children'] as $child)
|
|
<a href="{{ $child['url'] }}"
|
|
class="m-grid-sub-link {{ $active == $child['id'] ? 'is-active' : '' }}">
|
|
{{ $child['label'] }}
|
|
</a>
|
|
@endforeach
|
|
</div>
|
|
@endif
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
</nav>
|
|
@else
|
|
{{-- 데스크톱 전용: 프리미엄 사이드바 (기존 유지) --}}
|
|
<nav class="subnav subnav--side">
|
|
<div class="subnav-box premium-design">
|
|
@if($title)
|
|
<div class="subnav-head">
|
|
<div class="subnav-title">{{ $title }}</div>
|
|
<div class="subnav-accent"></div>
|
|
</div>
|
|
@endif
|
|
|
|
<ul class="subnav-list">
|
|
@foreach($items as $it)
|
|
@php
|
|
$isActive = $isShop ? ($active == $it['id']) : ($active && $active === ($it['key'] ?? $it['url']));
|
|
$hasActiveChild = $isShop && !empty($it['children']) && collect($it['children'])->contains('id', $active);
|
|
@endphp
|
|
<li class="nav-group {{ $isActive || $hasActiveChild ? 'is-open' : '' }}">
|
|
<a href="{{ $it['url'] ?? '#' }}" class="nav-main-link {{ $isActive ? 'is-active' : '' }}">
|
|
<span class="label-text">{{ $it['label'] ?? '' }}</span>
|
|
@if(!empty($it['children']))
|
|
<i class="bi bi-chevron-down arrow-icon"></i>
|
|
@endif
|
|
</a>
|
|
|
|
@if($isShop && !empty($it['children']))
|
|
<ul class="nav-sub-list">
|
|
@foreach($it['children'] as $child)
|
|
<li>
|
|
<a href="{{ $child['url'] }}"
|
|
class="nav-sub-link {{ $active == $child['id'] ? 'is-active' : '' }}">
|
|
{{ $child['label'] }}
|
|
</a>
|
|
</li>
|
|
@endforeach
|
|
</ul>
|
|
@endif
|
|
</li>
|
|
@endforeach
|
|
</ul>
|
|
</div>
|
|
</nav>
|
|
@endif
|
|
|
|
<style>
|
|
/* --- 모바일 그리드(Grid) 스타일 --- */
|
|
.mobile-subnav-grid {
|
|
margin-bottom: 25px;
|
|
}
|
|
|
|
.m-grid-container {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr; /* 한 줄에 2개 */
|
|
gap: 10px;
|
|
}
|
|
|
|
/* 2차 메뉴가 열릴 때 해당 행 전체를 차지하도록 설정 */
|
|
.m-grid-item.is-open {
|
|
grid-column: span 2; /* 활성화된 메뉴는 한 줄 전체 차지 (2차 메뉴 가독성) */
|
|
}
|
|
|
|
.m-grid-link {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
height: 50px;
|
|
background: #f8f9fa;
|
|
color: #444;
|
|
border-radius: 12px;
|
|
font-size: 0.95rem;
|
|
font-weight: 600;
|
|
text-decoration: none;
|
|
border: 1px solid #eee;
|
|
transition: all 0.2s;
|
|
text-align: center;
|
|
}
|
|
|
|
.m-grid-link.is-active {
|
|
background: #007bff;
|
|
color: #fff;
|
|
border-color: #007bff;
|
|
box-shadow: 0 4px 12px rgba(0, 123, 255, 0.2);
|
|
}
|
|
|
|
/* 모바일 2차 메뉴 리스트 */
|
|
.m-grid-sub-wrap {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr; /* 2차 메뉴도 2개씩 */
|
|
gap: 8px;
|
|
background: #f1f3f5;
|
|
padding: 12px;
|
|
border-radius: 12px;
|
|
margin-top: 8px;
|
|
}
|
|
|
|
.m-grid-sub-link {
|
|
display: block;
|
|
padding: 8px;
|
|
font-size: 0.85rem;
|
|
color: #666;
|
|
text-decoration: none;
|
|
background: #fff;
|
|
border-radius: 8px;
|
|
text-align: center;
|
|
border: 1px solid #e9ecef;
|
|
}
|
|
|
|
.m-grid-sub-link.is-active {
|
|
color: #007bff;
|
|
font-weight: 700;
|
|
border-color: #007bff;
|
|
}
|
|
|
|
/* --- 데스크톱 프리미엄 사이드바 (기존 유지) --- */
|
|
.premium-design { border: none; background: #fff; box-shadow: 0 4px 20px rgba(0,0,0,0.05); border-radius: 20px; padding: 15px; }
|
|
.subnav-head { padding: 10px 15px 15px; }
|
|
.subnav-title { font-size: 0.75rem; font-weight: 800; color: #bbb; letter-spacing: 1px; }
|
|
.subnav-accent { width: 20px; height: 3px; background: #007bff; margin-top: 6px; border-radius: 2px; }
|
|
.nav-main-link {
|
|
display: flex; align-items: center; justify-content: space-between;
|
|
padding: 12px 16px; color: #444; font-weight: 600; border-radius: 12px; transition: 0.3s; text-decoration: none; margin-bottom: 2px;
|
|
}
|
|
.nav-main-link:hover { background: #f8f9fa; }
|
|
.nav-main-link.is-active { background: #007bff; color: #fff; }
|
|
.nav-sub-list { list-style: none; padding: 5px 0 10px 15px; }
|
|
.nav-sub-link { display: block; padding: 7px 15px; font-size: 0.85rem; color: #777; text-decoration: none; border-radius: 8px; }
|
|
.nav-sub-link.is-active { color: #007bff; background: #f0f7ff; font-weight: 700; }
|
|
|
|
/* 화면 크기에 따른 노출 제어 */
|
|
@media (max-width: 991px) {
|
|
.subnav--side { display: none; }
|
|
}
|
|
@media (min-width: 992px) {
|
|
.mobile-subnav-grid { display: none; }
|
|
}
|
|
</style>
|