Immobilien, sidebar nav mobile

This commit is contained in:
Kevin Adametz 2026-05-11 11:02:47 +02:00
parent 6799325f71
commit 0762e3beac
2 changed files with 72 additions and 0 deletions

View file

@ -292,6 +292,77 @@
->all();
@endphp
<nav x-show="!selectedProject" x-cloak x-transition.opacity x-data="{
open: false,
active: '',
sections: @js($sidebarSections),
update() {
const offset = window.innerHeight * 0.35
let current = ''
for (const s of this.sections) {
const el = document.getElementById(s.id)
if (el && el.getBoundingClientRect().top - offset <= 0) {
current = s.id
}
}
this.active = current
},
scrollToSection(id) {
const el = document.getElementById(id)
if (!el) {
return
}
el.scrollIntoView({ behavior: 'smooth', block: 'start' })
this.open = false
},
activeLabel() {
return this.sections.find(section => section.id === this.active)?.label || this.sections[0]?.label || ''
},
}" x-init="update();
window.addEventListener('scroll', () => update(), { passive: true });
window.addEventListener('resize', () => update(), { passive: true });"
@keydown.escape.window="open = false" aria-label="{{ data_get($ui, 'sidebar.toggle_open') }}"
class="fixed right-14 top-3 z-[60] lg:hidden">
<div x-show="open" x-transition.origin.top.right
class="fixed inset-x-3 top-16 rounded-2xl border border-border bg-background p-3 shadow-2xl shadow-zinc-950/25">
<div class="mb-3 flex items-center justify-between gap-3 border-b border-border pb-3">
<p class="text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground">
{{ data_get($ui, 'sidebar.mobile_label', 'Abschnitt') }}
</p>
<p class="min-w-0 truncate text-sm font-semibold text-foreground" x-text="activeLabel()"></p>
</div>
<ul class="sidebar-nav grid max-h-[58vh] grid-cols-2 gap-2 overflow-y-auto sm:grid-cols-3">
<template x-for="s in sections" :key="s.id">
<li>
<button type="button" @click="scrollToSection(s.id)"
class="flex min-h-11 w-full items-center gap-2 rounded-xl border px-3 py-2 text-left text-sm font-medium transition"
:class="active === s.id ?
'border-secondary bg-secondary/10 text-secondary' :
'border-border bg-card text-foreground hover:border-secondary/50 hover:text-secondary'"
:aria-current="active === s.id ? 'true' : 'false'">
<span class="flex h-3 w-3 shrink-0 items-center justify-center">
<span class="block rounded-full"
:class="active === s.id ? 'h-2 w-2 bg-secondary' : 'h-1.5 w-1.5 bg-muted-foreground/45'"></span>
</span>
<span class="min-w-0 truncate" x-text="s.label"></span>
</button>
</li>
</template>
</ul>
</div>
<button type="button" @click="open = !open" :aria-expanded="open.toString()"
title="{{ data_get($ui, 'sidebar.toggle_open') }}"
class="sidebar-nav inline-flex h-10 w-10 items-center justify-center rounded-full border border-border bg-background text-foreground shadow-lg shadow-zinc-950/10 transition hover:border-secondary hover:text-secondary focus:outline-none focus:ring-2 focus:ring-secondary focus:ring-offset-2 focus:ring-offset-background">
<span class="sr-only">{{ data_get($ui, 'sidebar.mobile_label', 'Abschnitt') }}: <span
x-text="activeLabel()"></span></span>
<span class="transition" :class="open ? 'rotate-90 text-secondary' : ''">
@svg('heroicon-o-list-bullet', 'h-5 w-5')
</span>
</button>
</nav>
<aside x-show="!selectedProject" x-cloak x-transition.opacity x-data="{
expanded: false,
active: '',

View file

@ -103,6 +103,7 @@ it('dev azizi immobilien page shows curated projects', function () {
->assertSee('Kategorien')
->assertSee('Stadtteile')
->assertSee('Al Furjan')
->assertSee('Abschnitt')
->assertSee('Zurück zum Anfang der Projektübersicht')
->assertSee('Dubai als Wachstumsentscheidung')
->assertSee('Dubai braucht Entscheidungskraft')