feat(headline): optionaler SectionHeader-Modus (kicker/number/action)
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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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' },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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 h1–h3; h4–h6 → 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>
|
||||
|
||||
Reference in New Issue
Block a user