feat(header): icon nav redesign + migrate icons mdi→lucide
Deploy / verify (push) Successful in 1m26s
Deploy / deploy (push) Successful in 2m26s

- Header desktop nav: social icons grouped in a wald-tinted pill with
  labels, active-state (aria-current + bold), opacity hover (no per-item bg)
- Mobile overlay: social links as icon+label rows with active-state
- Search button: lucide:search, icon-only
- Migrate all icons mdi→lucide app-wide (234 refs); brand/language logos
  (google, whatsapp, mastodon, telegram, language-*) stay on mdi
- generate-icons: emit mdi + lucide subsets; add @iconify-json/lucide
- iconify-offline: register lucide collection
- scripts/icon-map|validate|apply: reusable migration tooling

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Peter Meier
2026-06-24 10:44:56 +02:00
parent e434ee3620
commit 0ab2c58eb4
46 changed files with 823 additions and 598 deletions
+14 -14
View File
@@ -110,7 +110,7 @@
class="shrink-0 rounded-md p-1.5 text-stein-400 hover:bg-stein-100 hover:text-stein-700 transition-colors"
aria-label={t(T.windkarte_panel_close)}
>
<Icon icon="mdi:close" class="size-5" />
<Icon icon="lucide:x" class="size-5" />
</button>
</div>
@@ -121,7 +121,7 @@
{#if area.flaeche_ha != null}
<div class="flex items-center justify-between px-3 py-1.5">
<span class="flex items-center gap-1.5 text-xs text-stein-500">
<Icon icon="mdi:ruler-square" class="size-3.5 text-stein-400" />
<Icon icon="lucide:ruler" class="size-3.5 text-stein-400" />
{t(T.windkarte_label_flaeche)}
</span>
<span class="font-semibold text-stein-800">{area.flaeche_ha.toFixed(1)} ha</span>
@@ -130,13 +130,13 @@
{#if area.anlagen_geplant != null}
<div class="flex items-center justify-between px-3 py-1.5">
<span class="flex items-center gap-1.5 text-xs text-stein-500">
<Icon icon="mdi:wind-turbine" class="size-3.5 text-stein-400" />
<Icon icon="lucide:fan" class="size-3.5 text-stein-400" />
{t(T.windkarte_label_anlagen_geplant)}
</span>
<span class="flex items-center gap-1.5 font-semibold text-stein-800">
{area.anlagen_geplant}
{#if area.anlagen_geplant_hinweis}
<Icon icon="mdi:information-outline" class="size-3.5 text-amber-700" />
<Icon icon="lucide:info" class="size-3.5 text-amber-700" />
{/if}
</span>
</div>
@@ -144,7 +144,7 @@
{#if area.investor}
<div class="flex items-center justify-between px-3 py-1.5">
<span class="flex items-center gap-1.5 text-xs text-stein-500">
<Icon icon="mdi:domain" class="size-3.5 text-stein-400" />
<Icon icon="lucide:building-2" class="size-3.5 text-stein-400" />
{t(T.windkarte_label_investor)}
</span>
<span class="font-semibold text-stein-800">{area.investor}</span>
@@ -164,7 +164,7 @@
{#if area.gemeinden && area.gemeinden.length > 0}
<div>
<p class="mb-2 flex items-center gap-1.5 text-xs font-medium uppercase tracking-wide text-stein-500">
<Icon icon="mdi:map-marker" class="size-3.5 text-stein-400" />
<Icon icon="lucide:map-pin" class="size-3.5 text-stein-400" />
{t(T.windkarte_label_gemeinden)}
</p>
<div class="flex flex-wrap gap-1.5">
@@ -186,7 +186,7 @@
<!-- Stellungnahme-Kriterien -->
{#if loadingKriterien}
<div class="flex items-center gap-2 text-xs text-stein-400">
<Icon icon="mdi:loading" class="size-3.5 animate-spin" />
<Icon icon="lucide:loader-circle" class="size-3.5 animate-spin" />
<span>{t(T.windkarte_kriterien_loading)}</span>
</div>
{:else if kriterien.length > 0}
@@ -201,7 +201,7 @@
>
<span class="min-w-0 line-clamp-2">{k.title ?? k._slug}</span>
<Icon
icon={expandedSlug === k._slug ? "mdi:chevron-up" : "mdi:chevron-down"}
icon={expandedSlug === k._slug ? "lucide:chevron-up" : "lucide:chevron-down"}
class="size-3.5 shrink-0 mt-0.5 text-stein-400"
/>
</button>
@@ -222,7 +222,7 @@
href={area.stellungnahmeUrl}
class="flex items-center gap-2 rounded-lg bg-wald-700 px-4 py-3 text-sm font-semibold text-white no-underline hover:bg-wald-800 transition-colors"
>
<Icon icon="mdi:file-document-edit-outline" class="size-4 shrink-0" />
<Icon icon="lucide:file-pen" class="size-4 shrink-0" />
Einwendung erstellen
</a>
{/if}
@@ -233,7 +233,7 @@
href={stellungnahmeHref(area.stellungnahme)}
class="flex items-center gap-2 rounded-lg border border-wald-300 bg-wald-50 px-4 py-3 text-sm font-medium text-wald-700 hover:bg-wald-100 transition-colors"
>
<Icon icon="mdi:file-document-edit-outline" class="size-4 shrink-0" />
<Icon icon="lucide:file-pen" class="size-4 shrink-0" />
{t(T.windkarte_stellungnahme_link)}
</a>
{/if}
@@ -244,7 +244,7 @@
onclick={copyLink}
class="flex flex-1 items-center justify-center gap-1.5 rounded-lg border border-stein-200 px-2 py-2 text-xs font-medium text-stein-600 hover:bg-stein-50 transition-colors whitespace-nowrap"
>
<Icon icon={copied ? "mdi:check" : "mdi:link-variant"} class="size-3.5 shrink-0" />
<Icon icon={copied ? "lucide:check" : "lucide:link"} class="size-3.5 shrink-0" />
{copied ? t(T.windkarte_action_copied) : t(T.windkarte_action_copy_link)}
</button>
{#if osmHref(center)}
@@ -254,7 +254,7 @@
rel="noopener noreferrer"
class="flex flex-1 items-center justify-center gap-1.5 rounded-lg border border-stein-200 px-2 py-2 text-xs font-medium text-stein-600 hover:bg-stein-50 transition-colors whitespace-nowrap"
>
<Icon icon="mdi:map-outline" class="size-3.5 shrink-0" />
<Icon icon="lucide:map" class="size-3.5 shrink-0" />
{t(T.windkarte_action_osm)}
</a>
{/if}
@@ -270,7 +270,7 @@
title={`${t(T.windkarte_action_download_geojson)}\n${exportInfo}`}
class="flex flex-1 items-center justify-center gap-1.5 rounded-lg border border-stein-200 px-2 py-2 text-xs font-medium text-stein-600 no-underline hover:bg-stein-50 transition-colors whitespace-nowrap"
>
<Icon icon="mdi:download" class="size-3.5 shrink-0" />
<Icon icon="lucide:download" class="size-3.5 shrink-0" />
GeoJSON
</a>
<a
@@ -279,7 +279,7 @@
title={`${t(T.windkarte_action_download_kml)}\n${exportInfo}`}
class="flex flex-1 items-center justify-center gap-1.5 rounded-lg border border-stein-200 px-2 py-2 text-xs font-medium text-stein-600 no-underline hover:bg-stein-50 transition-colors whitespace-nowrap"
>
<Icon icon="mdi:download" class="size-3.5 shrink-0" />
<Icon icon="lucide:download" class="size-3.5 shrink-0" />
KML
</a>
</div>