Blog-Übersicht: Featured-Hero, Neu-Badge, Org-Sektion, Sortierung, konsolidiertes Suchfeld
- SearchField-Atom (src/lib/ui/SearchField.svelte, light/dark) in Kalender, Beiträge und globaler Suche einheitlich eingesetzt - Featured-Hero (neuester Beitrag groß, Seite 1 ungefiltert, nur bei "newest") - Neu-Badge in PostCard (Beitrag < 7 Tage) - Org-/BI-Tags (tag-org-*) in eigene Sektion; Tags ohne Beiträge ausgeblendet - Inline-Newsletter-CTA, prominenter RSS-Link - Sortierung Neueste/Älteste (Server-Param + URL-State, Toggle neben Pagination, Pagination trägt sort weiter) - Pagination als Pills (rounded-full) - Kalender: Tag-Filter einklappbar, Filterleiste mit Suche + Heute Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
<script lang="ts">
|
||||
import Icon from "@iconify/svelte";
|
||||
import "$lib/iconify-offline";
|
||||
|
||||
let {
|
||||
value = $bindable(""),
|
||||
placeholder = "Suchen …",
|
||||
tone = "light" as "light" | "dark",
|
||||
ariaLabel = "Suche",
|
||||
autofocus = false,
|
||||
class: className = "",
|
||||
inputEl = $bindable<HTMLInputElement | null>(null),
|
||||
}: {
|
||||
value?: string;
|
||||
placeholder?: string;
|
||||
tone?: "light" | "dark";
|
||||
ariaLabel?: string;
|
||||
autofocus?: boolean;
|
||||
class?: string;
|
||||
inputEl?: HTMLInputElement | null;
|
||||
} = $props();
|
||||
|
||||
const toneClasses = $derived(
|
||||
tone === "dark"
|
||||
? "border-stein-0/20 bg-stein-800/70 text-stein-0 placeholder:text-stein-400 focus:border-wald-400"
|
||||
: "border-stein-300 bg-white text-stein-800 placeholder:text-stein-400 focus:border-wald-500 focus:ring-2 focus:ring-wald-200",
|
||||
);
|
||||
|
||||
function focusOnMount(node: HTMLInputElement, enabled: boolean) {
|
||||
if (enabled) setTimeout(() => node.focus({ preventScroll: true }), 0);
|
||||
}
|
||||
</script>
|
||||
|
||||
<label class="relative block {className}">
|
||||
<span class="sr-only">{ariaLabel}</span>
|
||||
<span class="pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-stein-400">
|
||||
<Icon icon="lucide:search" class="size-4" aria-hidden="true" />
|
||||
</span>
|
||||
<input
|
||||
bind:this={inputEl}
|
||||
type="search"
|
||||
bind:value
|
||||
{placeholder}
|
||||
aria-label={ariaLabel}
|
||||
use:focusOnMount={autofocus}
|
||||
class="w-full rounded-md border py-2 pl-8 pr-8 text-sm focus:outline-none {toneClasses}"
|
||||
/>
|
||||
{#if value}
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => (value = "")}
|
||||
aria-label="Suche leeren"
|
||||
class="absolute right-1.5 top-1/2 -translate-y-1/2 rounded p-1 {tone === 'dark'
|
||||
? 'text-stein-400 hover:bg-stein-0/10 hover:text-stein-0'
|
||||
: 'text-stein-400 hover:bg-stein-100 hover:text-stein-700'}"
|
||||
>
|
||||
<Icon icon="lucide:x" class="size-3.5" aria-hidden="true" />
|
||||
</button>
|
||||
{/if}
|
||||
</label>
|
||||
Reference in New Issue
Block a user