@ta-interaktiv/react-header-injection
v2.0.0
Published
Synchronously injects React content into Tamedia article headers with configurable title layouts.
Readme
@ta-interaktiv/react-header-injection
Injects React content immediately before a Tamedia article title and applies the header layouts shared by the package's 23 current consumers.
Installation
bun add @ta-interaktiv/react-header-injection@^2.0.0react and react-dom 18 or newer are peer dependencies. The package has no
runtime dependencies.
HeaderInjection
content is required:
import {
HeaderImage,
HeaderInjection
} from '@ta-interaktiv/react-header-injection'
export function Header() {
return (
<HeaderInjection
content={
<HeaderImage
desktop="https://example.com/header-desktop.jpg"
mobile="https://example.com/header-mobile.jpg"
alt="Bicycle traffic in Zurich"
/>
}
/>
)
}Props:
| Prop | Type | Default |
|---|---|---|
| content | ReactNode | required |
| layout | 'default' \| 'centered' \| 'stacked' | 'default' |
| fallback | 'none' \| 'inline' | 'none' |
| styles | HeaderInjectionStyles | — |
Layouts
defaultspans the injected container across the grid and centers the title.centeredadditionally centers the injected content.stackeduses a flex injection container and stacks the centered title vertically.
Style slots
styles supports container, title, firstSpan, and titleFirstSpan.
Overrides merge over the selected layout:
<HeaderInjection
layout="stacked"
styles={{
container: { width: '100%' },
title: { marginTop: '1em' },
titleFirstSpan: { minWidth: '80%' }
}}
content={<MyHeader />}
/>The slots target:
container: the injected#inject-into-header-contentelement.title: the first articleh2.firstSpan: the firstspanin the title's closest parentdiv.titleFirstSpan: the firstspaninside theh2.
A slot set to null disables all styles for that slot. A property explicitly
set to undefined removes that one property from the selected layout while
preserving its other styles:
styles={{
firstSpan: null,
title: { flexWrap: undefined }
}}Synchronous injection and fallback
On mount, the component immediately finds the first h2, resolves its closest
parent div, and inserts the portal container before that div. The article
DOM must already contain this structure when the layout effect runs.
If the target is unavailable or injection fails, fallback is immediate:
nonerenders nothing.inlinerenderscontentin a plaindivat the component's original location.
HeaderImage
HeaderImage renders a responsive picture. Its mobile breakpoint is fixed at
768px (max-width: 767px).
| Prop | Type | Default |
|---|---|---|
| desktop | string | required |
| mobile | string | desktop |
| darkDesktop | string | desktop |
| darkMobile | string | mobile, then the selected desktop source |
| colorMode | 'light' \| 'dark' | 'light' |
| alt | string | required |
| imageStyles | CSSProperties | — |
<HeaderImage
desktop="/header-light-desktop.jpg"
mobile="/header-light-mobile.jpg"
darkDesktop="/header-dark-desktop.jpg"
darkMobile="/header-dark-mobile.jpg"
colorMode="dark"
alt="Mountain landscape"
imageStyles={{ display: 'block', width: '100%' }}
/>Custom content
content accepts any React node. Keep project-specific videos, animations,
charts, parallax pictures, and SVG in the consumer:
<HeaderInjection
layout="centered"
fallback="inline"
content={<video autoPlay muted loop playsInline src="/header.mp4" />}
/><HeaderInjection
content={
<svg viewBox="0 0 100 20" role="img" aria-label="Timeline">
<path d="M0 10H100" stroke="currentColor" />
</svg>
}
/>Consumer corpus
The reviewed corpus contains these 23 package consumers:
- Default:
interaktiv-2022-kaffeerechner,interaktiv-2024-srg-halbierungsintiative,interaktiv-2025-300-reichste,interaktiv-2025-chat-gpt-dialog,interaktiv-2025-fragen-zu-kopfschmerzen,interaktiv-2025-fragen-zum-schlaf,interaktiv-2025-notaufnahme-quiz,interaktiv-2025-rueckenschmerzen,interaktiv-2025-schaad-im-tschad,interaktiv-2025-superforecaster-quiz,interaktiv-2026-alkoholrechner,interaktiv-2026-jobs,interaktiv-2026-kirschbluete,interaktiv-2026-sirenen-quiz, andinteraktiv-2026-so-alt-sind-ihre-nachbarn. - Centered:
interaktiv-2025-cancer,interaktiv-2025-wine-quiz-battle,interaktiv-2026-airtravel-quiz, andinteraktiv-2026-political-ads. - Stacked with inline fallback:
interaktiv-2025-3D-lakes,interaktiv-2026-immobilienpreise,interaktiv-2026-velounfaelle-verortung, andinteraktiv-2026-velounfaelle.
The exact layout, fallback, and style overrides are recorded in
__tests__/fixtures/migration-props.json and covered by the parity suite.
Test and build
Run from the monorepo root:
yarn jest --config packages/react-header-injection/jest.config.cjs --runInBand
yarn workspace @ta-interaktiv/react-header-injection prepare
yarn workspace @ta-interaktiv/react-header-injection verify:package