feat: add class-variance-authority for card styling and enhance color palettes
Deploy / verify (push) Failing after 1m40s
Deploy / deploy (push) Has been skipped

- Introduced `class-variance-authority` to manage card component styles, allowing for flexible variant and layout options.
- Added a new color palette for "Fire" to the CSS for improved theming.
- Updated `Card` and `PostCard` components to utilize the new styling system, enhancing visual consistency and responsiveness.
- Refined layout and styling in various components for better user experience.
This commit is contained in:
Peter Meier
2026-04-20 22:09:43 +02:00
parent a18c0a8cf7
commit d327798ce6
9 changed files with 191 additions and 119 deletions
@@ -56,10 +56,6 @@
)
);
const addOrganisationCardClass = $derived(
`border-dashed border-wald-300 bg-wald-50! p-3! gap-1.5!${addOrganisationCtaLink ? " cursor-pointer" : ""}`,
);
let scroller: HTMLDivElement | undefined = $state();
function scrollByPage(dir: 1 | -1) {
if (!scroller) return;
@@ -68,8 +64,8 @@
</script>
{#snippet defaultCard(o: OrganisationEntry, linkUrl: string | undefined, logoField: ReturnType<typeof organisationLogoField>, orgIndex: number)}
<Card href={linkUrl} class="p-3! gap-1.5! h-full">
<div class="h-11 w-11 rounded-md border border-stein-100 bg-stein-50 flex items-center justify-center overflow-hidden shrink-0">
<Card href={linkUrl} class="h-full">
<div class="flex h-11 w-11 shrink-0 items-center justify-center overflow-hidden bg-gray-100">
{#if logoField}
<RustyImage
src={logoField.url}
@@ -84,7 +80,7 @@
/>
{:else}
{@const fishMaskId = `org-logo-fallback-mask-${orgIndex}`}
<svg class="h-8 w-8 text-stein-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="currentColor" aria-hidden="true">
<svg class="h-8 w-8 text-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="currentColor" aria-hidden="true">
<defs>
<mask id={fishMaskId}>
<g fill="none">
@@ -103,19 +99,20 @@
<Badge color={o.badge.color}>{o.badge.label}</Badge>
</div>
{/if}
<h5 class="min-w-0 text-sm font-semibold leading-snug text-stein-900 truncate">{o.name ?? ""}</h5>
<h5 class="mb-1 min-w-0 truncate text-sm font-medium leading-tight text-slate-950">{o.name ?? ""}</h5>
{#if o.description}
<p class="text-xs text-stein-600 line-clamp-2">{o.description}</p>
<p class="line-clamp-2 text-xs font-light text-slate-600">{o.description}</p>
{/if}
</Card>
{/snippet}
{#snippet ctaCard()}
<Card
variant="callout"
href={addOrganisationCtaLink?.url}
target={addOrganisationCtaLink?.newTab ? "_blank" : undefined}
rel={addOrganisationCtaLink?.newTab ? "noopener noreferrer" : undefined}
class="{addOrganisationCardClass} h-full"
class="h-full"
>
{#if block.addOrganisationTitle}
<h5 class="text-sm font-semibold text-wald-800 leading-snug">{block.addOrganisationTitle}</h5>
@@ -138,7 +135,7 @@
<div class="relative">
<div
bind:this={scroller}
class="flex gap-3 overflow-x-auto scroll-smooth snap-x snap-mandatory pb-2 -mx-2 px-2 [scrollbar-width:thin]"
class="flex gap-4 overflow-x-auto scroll-smooth snap-x snap-mandatory pb-2 [scrollbar-width:thin]"
>
{#each orgs as org, orgIndex}
{#if typeof org === "object" && org !== null}
@@ -151,7 +148,9 @@
? o.link.url.trim()
: undefined}
{@const logoField = organisationLogoField(o)}
<div class="shrink-0 snap-start basis-1/2 lg:basis-1/3">
<div
class="shrink-0 snap-start w-[calc((100%-1rem)/2)] lg:w-[calc((100%-2rem)/3)]"
>
{@render defaultCard(o, linkUrl, logoField, orgIndex)}
</div>
{/if}
@@ -177,27 +176,16 @@
{/if}
</div>
{#if showAddOrganisationCard}
<div class="mt-4 rounded-md border border-dashed border-wald-300 bg-wald-50 p-3 text-sm text-wald-800">
{#if block.addOrganisationTitle}
<div class="font-semibold">{block.addOrganisationTitle}</div>
{/if}
{#if ctaHtml}
<div class="markdown text-xs text-wald-700 [&>p]:mb-0">{@html ctaHtml}</div>
{/if}
{#if addOrganisationCtaLink}
<a
href={addOrganisationCtaLink.url}
target={addOrganisationCtaLink.newTab ? "_blank" : undefined}
rel={addOrganisationCtaLink.newTab ? "noopener noreferrer" : undefined}
class="mt-1 inline-block font-medium underline-offset-2 hover:underline"
>
{addOrganisationCtaLink.linkName}
</a>
{/if}
<div class="mt-2 min-w-0">
{@render ctaCard()}
</div>
{/if}
{:else}
<div class={compact ? "grid gap-2 sm:grid-cols-2 lg:grid-cols-3" : "grid gap-4 sm:grid-cols-2 lg:grid-cols-3"}>
<div
class={compact
? "grid grid-cols-1 gap-2 md:grid-cols-2 lg:grid-cols-3"
: "grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3"}
>
{#each orgs as org, orgIndex}
{#if typeof org === "object" && org !== null}
{@const o = org as OrganisationEntry}
@@ -210,8 +198,8 @@
: undefined}
{@const logoField = organisationLogoField(o)}
{#if compact}
<Card href={linkUrl} class="flex! flex-row! items-start! gap-3! p-3! gap-y-0!">
<div class="h-10 w-10 rounded-md border border-stein-100 bg-stein-50 flex items-center justify-center overflow-hidden shrink-0">
<Card href={linkUrl} layout="inline" class="h-full">
<div class="flex h-10 w-10 shrink-0 items-center justify-center overflow-hidden bg-gray-100">
{#if logoField}
<RustyImage
src={logoField.url}
@@ -226,7 +214,7 @@
/>
{:else}
{@const fishMaskId = `org-logo-fallback-mask-c-${orgIndex}`}
<svg class="h-7 w-7 text-stein-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="currentColor" aria-hidden="true">
<svg class="h-7 w-7 text-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="currentColor" aria-hidden="true">
<defs>
<mask id={fishMaskId}>
<g fill="none">
@@ -240,10 +228,10 @@
</svg>
{/if}
</div>
<div class="min-w-0 flex-1 flex flex-col gap-0.5">
<h5 class="text-sm font-semibold text-stein-900 leading-snug">{o.name ?? ""}</h5>
<div class="flex min-w-0 flex-1 flex-col gap-0.5">
<h5 class="text-sm font-medium leading-tight text-slate-950">{o.name ?? ""}</h5>
{#if o.description}
<p class="text-xs text-stein-600 line-clamp-2">{o.description}</p>
<p class="line-clamp-2 text-xs font-light text-slate-600">{o.description}</p>
{/if}
</div>
</Card>