feat(headline): optionaler SectionHeader-Modus (kicker/number/action)
Deploy / verify (push) Successful in 1m28s
Deploy / deploy (push) Successful in 1m36s

HeadlineBlock rendert als SectionHeader sobald kicker oder action gesetzt ist,
sonst schlichte Text-Headline wie bisher (rückwärtskompatibel, opt-in).
SectionHeader-Titel unterstützt jetzt \n → <br>. headline-Schema extends
section_header.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Peter Meier
2026-07-11 23:48:23 +02:00
parent 03e84c1f28
commit b60da59c92
4 changed files with 48 additions and 8 deletions
+6
View File
@@ -45,6 +45,12 @@ export interface HeadlineBlockData {
_slug?: string;
tag?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
text?: string;
/** SectionHeader: Label über dem Titel (uppercase). Gesetzt → Headline rendert als Sektionskopf. */
kicker?: string;
/** SectionHeader: Index vor dem Kicker, z.B. "03". */
number?: string;
/** SectionHeader: CTA-Link (aufgelöst: url, linkName). */
action?: string | { url?: string; linkName?: string; newTab?: boolean };
align?: "left" | "center" | "right";
layout?: BlockLayout;
}
+2 -2
View File
@@ -51,9 +51,9 @@
</div>
{/if}
<!-- Titel -->
<!-- Titel (\n → harter Umbruch, wie HeadlineBlock) -->
<svelte:element this={tag} class="text-3xl font-bold tracking-[-0.02em] text-stein-800 lg:text-[34px]">
{title}
{#each title.split('\n') as line, i}{#if i > 0}<br />{/if}{line}{/each}
</svelte:element>
{#if subtitle}
@@ -36,3 +36,15 @@ export const MitUmbruch: Story = {
},
},
};
// Sobald kicker/action gesetzt → Headline rendert als SectionHeader.
export const AlsSektionskopf: Story = {
args: {
block: {
tag: 'h2',
text: 'Wir sind keine Lobby,\nkeine Partei, keine NGO.',
kicker: 'Über uns',
action: { url: '/about', linkName: 'Mehr über uns' },
},
},
};
+28 -6
View File
@@ -1,10 +1,21 @@
<script lang="ts">
import { getBlockLayoutClasses } from "$lib/block-layout";
import SectionHeader from "$lib/components/SectionHeader.svelte";
import type { HeadlineBlockData } from "$lib/block-types";
let { block }: { block: HeadlineBlockData } = $props();
const layoutClasses = $derived(getBlockLayoutClasses(block.layout));
// Sektionskopf-Modus: sobald kicker ODER action gesetzt ist, rendert die
// Headline als SectionHeader. Sonst schlichte Text-Headline wie bisher.
const actionRef = $derived(
block.action && typeof block.action === "object" ? block.action : null,
);
const useSection = $derived(!!block.kicker || !!actionRef);
// SectionHeader kennt nur h1h3; h4h6 → h2.
const sectionTag = $derived(
block.tag === "h1" || block.tag === "h2" || block.tag === "h3" ? block.tag : "h2",
);
const alignClass = $derived(
block.align === "center"
? "text-center"
@@ -20,10 +31,21 @@
</script>
<div class={layoutClasses} data-block="Headline" data-block-type="headline" data-block-slug={block._slug}>
<svelte:element
this={Tag}
class={alignClass}
>
{#each lines as line, i}{#if i > 0}<br />{/if}{line}{/each}
</svelte:element>
{#if useSection}
<SectionHeader
number={block.number}
kicker={block.kicker}
title={block.text ?? ""}
tag={sectionTag}
actionLabel={actionRef?.linkName}
actionHref={actionRef?.url}
/>
{:else}
<svelte:element
this={Tag}
class={alignClass}
>
{#each lines as line, i}{#if i > 0}<br />{/if}{line}{/each}
</svelte:element>
{/if}
</div>