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
+7 -7
View File
@@ -332,7 +332,7 @@
onclick={() => startEdit(c)}
class="text-xs text-stein-600 hover:text-stein-900 inline-flex items-center gap-1"
>
<Icon icon="mdi:pencil-outline" class="size-3" />
<Icon icon="lucide:pencil" class="size-3" />
{t(T.comments_edit)}
</button>
<button
@@ -340,7 +340,7 @@
onclick={() => deleteComment(c.id)}
class="text-xs text-stein-600 hover:text-fire-700 inline-flex items-center gap-1"
>
<Icon icon="mdi:trash-can-outline" class="size-3" />
<Icon icon="lucide:trash-2" class="size-3" />
{t(T.comments_delete)}
</button>
</div>
@@ -364,7 +364,7 @@
{/if}
{#if c.status === "pending"}
<span class="ml-auto inline-flex items-center gap-1 rounded-full bg-erde-100 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-erde-800">
<Icon icon="mdi:clock-outline" class="size-3" />
<Icon icon="lucide:clock" class="size-3" />
{t(T.comments_pending_short)}
</span>
{/if}
@@ -387,7 +387,7 @@
</ul>
{:else if loadError}
<div class="flex items-start gap-2 rounded-xs border border-fire-200 bg-fire-50 p-3 text-sm text-fire-800">
<Icon icon="mdi:alert-circle-outline" class="size-5 shrink-0 mt-0.5" />
<Icon icon="lucide:circle-alert" class="size-5 shrink-0 mt-0.5" />
<div class="flex-1">
<p class="font-medium">{t(T.comments_load_error_title)}</p>
<p class="mt-1 text-xs text-fire-700">{loadError}</p>
@@ -401,7 +401,7 @@
{:else}
{#if topLevel.length === 0}
<div class="flex flex-col items-center gap-1 py-8 text-center sm:flex-row sm:items-center sm:text-left sm:py-4 sm:gap-1.5">
<Icon icon="mdi:comment-text-outline" class="size-5 text-stein-300 shrink-0" />
<Icon icon="lucide:message-square-text" class="size-5 text-stein-300 shrink-0" />
<p class="text-sm font-semibold text-stein-300">{t(T.comments_empty)}</p>
</div>
{:else}
@@ -424,7 +424,7 @@
onclick={() => (replyTo = replyTo === c.id ? null : c.id)}
class="text-xs text-stein-600 hover:text-stein-900 inline-flex items-center gap-1"
>
<Icon icon="mdi:reply" class="size-3" />
<Icon icon="lucide:reply" class="size-3" />
{replyTo === c.id
? t(T.comments_cancel)
: replies.length === 0
@@ -531,7 +531,7 @@
</button>
{#if requireApproval}
<span class="text-stein-500 inline-flex items-center gap-1">
<Icon icon="mdi:shield-check-outline" class="size-3.5" />
<Icon icon="lucide:shield-check" class="size-3.5" />
{t(T.comments_approval_hint)}
</span>
{/if}