style(header mobile): Menü kompakter + Such-Overlay an Menü-Look angeglichen
- Menü: Hauptpunkte text-sm + py-2.5 (kein Größensprung zu Subpunkten), Active nur per Farbe (kein font-bold), CTA-Buttons Ghost + Icons - Search.svelte: dunkel-frosted Overlay (bg-stein-900/90 + blur), absolute statt in-flow, dunkler Input, helle Ergebnisse — konsistent mit dem Menü Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -311,8 +311,14 @@
|
|||||||
aria-label={t(T.header_nav_aria)}
|
aria-label={t(T.header_nav_aria)}
|
||||||
>
|
>
|
||||||
<div class="grid grid-cols-2 gap-2.5 pb-4 mb-2 border-b border-stein-0/10">
|
<div class="grid grid-cols-2 gap-2.5 pb-4 mb-2 border-b border-stein-0/10">
|
||||||
<a href="/mitmachen/" class="btn-primary btn-sm justify-center rounded-full py-2 shadow-sm" onclick={closeMenu}>Mitmachen</a>
|
<a href="/mitmachen/" class="inline-flex items-center justify-center gap-1.5 rounded-full border border-wald-400/40 px-3 py-2 text-sm font-medium text-wald-200 transition-colors hover:bg-stein-0/10" onclick={closeMenu}>
|
||||||
<a href="/termin-melden" class="btn-warning btn-sm justify-center rounded-full py-2 shadow-sm" onclick={closeMenu}>Termin melden</a>
|
<Icon icon="lucide:heart-handshake" class="size-4 shrink-0" aria-hidden="true" />
|
||||||
|
Mitmachen
|
||||||
|
</a>
|
||||||
|
<a href="/termin-melden" class="inline-flex items-center justify-center gap-1.5 rounded-full border border-gelb-400/40 px-3 py-2 text-sm font-medium text-gelb-300 transition-colors hover:bg-stein-0/10" onclick={closeMenu}>
|
||||||
|
<Icon icon="lucide:calendar-plus" class="size-4 shrink-0" aria-hidden="true" />
|
||||||
|
Termin melden
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{#each links as link}
|
{#each links as link}
|
||||||
{@const active = isActiveTree(link, $page.url.pathname)}
|
{@const active = isActiveTree(link, $page.url.pathname)}
|
||||||
@@ -321,7 +327,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="flex w-full items-center justify-between py-4 px-3 rounded-xs transition-colors text-base text-stein-100 hover:bg-stein-0/10 border-l-4 {active ? 'border-wald-400 font-bold text-wald-300' : 'border-transparent'}"
|
class="flex w-full items-center justify-between py-2.5 px-3 rounded-xs transition-colors text-sm text-stein-100 hover:bg-stein-0/10 border-l-4 {active ? 'border-wald-400 text-wald-300' : 'border-transparent'}"
|
||||||
aria-expanded={expanded}
|
aria-expanded={expanded}
|
||||||
onclick={() => toggleSubmenu(link.label)}
|
onclick={() => toggleSubmenu(link.label)}
|
||||||
>
|
>
|
||||||
@@ -334,7 +340,7 @@
|
|||||||
{@const pActive = isActiveLink(link.href, $page.url.pathname)}
|
{@const pActive = isActiveLink(link.href, $page.url.pathname)}
|
||||||
<a
|
<a
|
||||||
href={link.href}
|
href={link.href}
|
||||||
class="block py-3 px-3 text-sm {pActive ? 'font-bold text-wald-300' : 'text-stein-200 hover:text-stein-0'}"
|
class="block py-2 px-3 text-sm {pActive ? 'text-wald-300' : 'text-stein-200 hover:text-stein-0'}"
|
||||||
aria-current={pActive ? "page" : undefined}
|
aria-current={pActive ? "page" : undefined}
|
||||||
onclick={closeMenu}
|
onclick={closeMenu}
|
||||||
>
|
>
|
||||||
@@ -345,7 +351,7 @@
|
|||||||
{@const cActive = isActiveLink(child.href, $page.url.pathname)}
|
{@const cActive = isActiveLink(child.href, $page.url.pathname)}
|
||||||
<a
|
<a
|
||||||
href={child.href}
|
href={child.href}
|
||||||
class="block py-3 px-3 text-sm {cActive ? 'font-bold text-wald-300' : 'text-stein-200 hover:text-stein-0'}"
|
class="block py-2 px-3 text-sm {cActive ? 'text-wald-300' : 'text-stein-200 hover:text-stein-0'}"
|
||||||
aria-current={cActive ? "page" : undefined}
|
aria-current={cActive ? "page" : undefined}
|
||||||
onclick={closeMenu}
|
onclick={closeMenu}
|
||||||
>
|
>
|
||||||
@@ -358,8 +364,8 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<a
|
<a
|
||||||
href={link.href}
|
href={link.href}
|
||||||
class="block py-4 px-3 rounded-xs transition-colors text-base {active
|
class="block py-2.5 px-3 rounded-xs transition-colors text-sm {active
|
||||||
? 'font-bold text-wald-300 bg-wald-700/20 border-l-4 border-wald-400'
|
? 'text-wald-300 bg-wald-700/20 border-l-4 border-wald-400'
|
||||||
: 'text-stein-100 hover:text-stein-0 hover:bg-stein-0/10 border-l-4 border-transparent'}"
|
: 'text-stein-100 hover:text-stein-0 hover:bg-stein-0/10 border-l-4 border-transparent'}"
|
||||||
aria-current={active ? "page" : undefined}
|
aria-current={active ? "page" : undefined}
|
||||||
onclick={closeMenu}
|
onclick={closeMenu}
|
||||||
@@ -381,8 +387,8 @@
|
|||||||
rel={isInternal
|
rel={isInternal
|
||||||
? undefined
|
? undefined
|
||||||
: "noopener noreferrer"}
|
: "noopener noreferrer"}
|
||||||
class="flex items-center gap-3 py-4 px-3 rounded-xs transition-colors text-base border-l-4 {sActive
|
class="flex items-center gap-3 py-2.5 px-3 rounded-xs transition-colors text-sm border-l-4 {sActive
|
||||||
? 'font-bold text-wald-300 bg-wald-700/20 border-wald-400'
|
? 'text-wald-300 bg-wald-700/20 border-wald-400'
|
||||||
: 'text-stein-100 hover:text-stein-0 hover:bg-stein-0/10 border-transparent'}"
|
: 'text-stein-100 hover:text-stein-0 hover:bg-stein-0/10 border-transparent'}"
|
||||||
aria-current={sActive ? "page" : undefined}
|
aria-current={sActive ? "page" : undefined}
|
||||||
aria-label={social.label ||
|
aria-label={social.label ||
|
||||||
@@ -391,7 +397,7 @@
|
|||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
icon={social.icon}
|
icon={social.icon}
|
||||||
class="text-base"
|
class="text-sm"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
{#if social.label}
|
{#if social.label}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@
|
|||||||
.join("|");
|
.join("|");
|
||||||
return safe.replace(
|
return safe.replace(
|
||||||
new RegExp(`(${pattern})`, "gi"),
|
new RegExp(`(${pattern})`, "gi"),
|
||||||
'<mark class="bg-wald-100 text-inherit rounded-xs px-0.5">$1</mark>',
|
'<mark class="bg-wald-400/30 text-wald-100 rounded-xs px-0.5">$1</mark>',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,16 +154,16 @@
|
|||||||
{#if open}
|
{#if open}
|
||||||
<div
|
<div
|
||||||
id="search-panel"
|
id="search-panel"
|
||||||
class="border-t border-white/30 bg-white/95 backdrop-blur overflow-hidden"
|
class="absolute left-0 right-0 top-full z-30 shadow-2xl border-t border-stein-0/10 bg-stein-900/90 backdrop-blur-lg max-h-[calc(100dvh-3.5rem)] overflow-y-auto overscroll-contain"
|
||||||
role="region"
|
role="region"
|
||||||
aria-label="Suche"
|
aria-label="Suche"
|
||||||
in:slide={{ duration: 200 }}
|
in:slide={{ duration: 200 }}
|
||||||
out:slide={{ duration: 150 }}
|
out:slide={{ duration: 150 }}
|
||||||
>
|
>
|
||||||
<div class="container-custom py-4 overflow-auto max-h-[calc(100vh-120px)]">
|
<div class="container-custom pt-4 pb-[calc(2rem+env(safe-area-inset-bottom))]">
|
||||||
<label class="relative block max-w-xl mx-auto">
|
<label class="relative block max-w-xl mx-auto">
|
||||||
<span class="sr-only">Suche</span>
|
<span class="sr-only">Suche</span>
|
||||||
<span class="pointer-events-none absolute top-1/2 left-3 -translate-y-1/2 text-stein-500">
|
<span class="pointer-events-none absolute top-1/2 left-3 -translate-y-1/2 text-stein-300">
|
||||||
<Icon icon="lucide:search" class="h-5 w-5" />
|
<Icon icon="lucide:search" class="h-5 w-5" />
|
||||||
</span>
|
</span>
|
||||||
<input
|
<input
|
||||||
@@ -171,14 +171,14 @@
|
|||||||
type="search"
|
type="search"
|
||||||
bind:value={query}
|
bind:value={query}
|
||||||
placeholder="Seiten und Beiträge durchsuchen…"
|
placeholder="Seiten und Beiträge durchsuchen…"
|
||||||
class="w-full rounded-xs border border-stein-300 bg-white py-3 pl-10 pr-10 text-sm focus:border-stein-500 focus:outline-none"
|
class="w-full rounded-xs border border-stein-0/20 bg-stein-800/70 py-3 pl-10 pr-10 text-sm text-stein-0 placeholder:text-stein-400 focus:border-wald-400 focus:outline-none"
|
||||||
/>
|
/>
|
||||||
{#if query}
|
{#if query}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onclick={() => (query = "")}
|
onclick={() => (query = "")}
|
||||||
aria-label="Eingabe leeren"
|
aria-label="Eingabe leeren"
|
||||||
class="absolute top-1/2 right-2 -translate-y-1/2 rounded-xs p-1 text-stein-500 hover:bg-stein-100 hover:text-stein-900"
|
class="absolute top-1/2 right-2 -translate-y-1/2 rounded-xs p-1 text-stein-300 hover:bg-stein-0/10 hover:text-stein-0"
|
||||||
>
|
>
|
||||||
<Icon icon="lucide:x" class="h-4 w-4" />
|
<Icon icon="lucide:x" class="h-4 w-4" />
|
||||||
</button>
|
</button>
|
||||||
@@ -192,18 +192,18 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</p>
|
</p>
|
||||||
{#if loading}
|
{#if loading}
|
||||||
<p class="text-stein-500 text-center py-2">Lade Suchindex…</p>
|
<p class="text-stein-300 text-center py-2">Lade Suchindex…</p>
|
||||||
{:else if loadError}
|
{:else if loadError}
|
||||||
<p class="text-fire-600 text-center py-2">Suche nicht verfügbar: {loadError}</p>
|
<p class="text-fire-400 text-center py-2">Suche nicht verfügbar: {loadError}</p>
|
||||||
{:else if normalizedQuery.length < 2}
|
{:else if normalizedQuery.length < 2}
|
||||||
<p class="text-stein-500 text-center py-2">Mindestens 2 Zeichen eingeben.</p>
|
<p class="text-stein-300 text-center py-2">Mindestens 2 Zeichen eingeben.</p>
|
||||||
{:else if results.length === 0}
|
{:else if results.length === 0}
|
||||||
<p class="text-stein-500 text-center py-2">Keine Treffer.</p>
|
<p class="text-stein-300 text-center py-2">Keine Treffer.</p>
|
||||||
{:else}
|
{:else}
|
||||||
<p class="text-stein-400 text-xs mb-2">
|
<p class="text-stein-400 text-xs mb-2">
|
||||||
{results.length === MAX_RESULTS ? `${MAX_RESULTS}+ Treffer` : `${results.length} Treffer`} · ↑↓ zum Wählen, ⏎ zum Öffnen
|
{results.length === MAX_RESULTS ? `${MAX_RESULTS}+ Treffer` : `${results.length} Treffer`} · ↑↓ zum Wählen, ⏎ zum Öffnen
|
||||||
</p>
|
</p>
|
||||||
<ul class="divide-y divide-stein-200">
|
<ul class="divide-y divide-stein-0/10">
|
||||||
{#each results as hit, i}
|
{#each results as hit, i}
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
@@ -212,32 +212,32 @@
|
|||||||
onclick={closeSearch}
|
onclick={closeSearch}
|
||||||
onmouseenter={() => (activeIndex = i)}
|
onmouseenter={() => (activeIndex = i)}
|
||||||
aria-current={i === activeIndex ? "true" : undefined}
|
aria-current={i === activeIndex ? "true" : undefined}
|
||||||
class="flex items-start gap-3 py-3 rounded-xs px-2 -mx-2 no-underline {i === activeIndex ? 'bg-stein-100' : 'hover:bg-stein-50'}"
|
class="flex items-start gap-3 py-3 rounded-xs px-2 -mx-2 no-underline {i === activeIndex ? 'bg-stein-0/10' : 'hover:bg-stein-0/10'}"
|
||||||
>
|
>
|
||||||
{#if hit.image}
|
{#if hit.image}
|
||||||
<img
|
<img
|
||||||
src={hit.image}
|
src={hit.image}
|
||||||
alt=""
|
alt=""
|
||||||
class="w-20 h-12 object-cover shrink-0 rounded-xs border border-stein-200"
|
class="w-20 h-12 object-cover shrink-0 rounded-xs border border-stein-0/10"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<span class="w-20 h-12 shrink-0 bg-stein-100 rounded-xs border border-stein-200 flex items-center justify-center text-stein-400">
|
<span class="w-20 h-12 shrink-0 bg-stein-0/10 rounded-xs border border-stein-0/10 flex items-center justify-center text-stein-400">
|
||||||
<Icon icon={hit.type === "post" ? "lucide:file-text" : "lucide:file"} class="h-5 w-5" />
|
<Icon icon={hit.type === "post" ? "lucide:file-text" : "lucide:file"} class="h-5 w-5" />
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="min-w-0 flex-1">
|
<div class="min-w-0 flex-1">
|
||||||
<div class="flex items-center gap-2 text-[.65rem] uppercase tracking-wide text-stein-500">
|
<div class="flex items-center gap-2 text-[.65rem] uppercase tracking-wide text-stein-300">
|
||||||
<span>{hit.type === "post" ? "Beitrag" : "Seite"}</span>
|
<span>{hit.type === "post" ? "Beitrag" : "Seite"}</span>
|
||||||
{#if hit.isEvent && hit.eventDate}
|
{#if hit.isEvent && hit.eventDate}
|
||||||
<span class="text-wald-700">{formatDate(hit.eventDate)}</span>
|
<span class="text-wald-300">{formatDate(hit.eventDate)}</span>
|
||||||
{:else if hit.created}
|
{:else if hit.created}
|
||||||
<span>{formatDate(hit.created)}</span>
|
<span>{formatDate(hit.created)}</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="font-medium text-stein-900 truncate">{@html highlight(hit.title)}</div>
|
<div class="font-medium text-stein-0 truncate">{@html highlight(hit.title)}</div>
|
||||||
{#if hit.excerpt}
|
{#if hit.excerpt}
|
||||||
<div class="text-xs text-stein-600 line-clamp-2">{@html highlight(hit.excerpt)}</div>
|
<div class="text-xs text-stein-300 line-clamp-2">{@html highlight(hit.excerpt)}</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
Reference in New Issue
Block a user