+ {(halves || []).map((half: DoubleBannerHalf, index: number) => {
+ const content = renderHalf(half, index);
+ // Every half after the first mirrors the previous one: image towards the middle.
+ const halfClassName = clsx('c-block-double-banner__half', {
+ 'c-block-double-banner__half--mirrored': index % 2 === 1,
+ });
+
+ if (!half.link) {
+ return (
+ // biome-ignore lint/suspicious/noArrayIndexKey: the halves have no id of their own
+
+ {content}
+
+ );
+ }
+
+ return (
+
+ {content}
+
+ );
+ })}
+
+ );
+};
diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockDoubleBanner/BlockDoubleBanner.types.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockDoubleBanner/BlockDoubleBanner.types.ts
new file mode 100644
index 00000000..0900ce97
--- /dev/null
+++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockDoubleBanner/BlockDoubleBanner.types.ts
@@ -0,0 +1,22 @@
+import type { ButtonAction } from '@viaa/avo2-components';
+import type { DefaultComponentProps } from '~shared/types';
+
+/**
+ * One of the two mirrored halves of the double banner.
+ * The FA requires every field except the icons to be filled in.
+ * https://meemoo.atlassian.net/browse/ARC-3833
+ */
+export interface DoubleBannerHalf {
+ label: string;
+ icon1?: string;
+ icon2?: string;
+ icon3?: string;
+ link?: ButtonAction;
+ image: string;
+ textColor: string;
+ backgroundColor: string;
+}
+
+export interface BlockDoubleBannerProps extends DefaultComponentProps {
+ halves: DoubleBannerHalf[];
+}
diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockDoubleBanner/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockDoubleBanner/index.ts
new file mode 100644
index 00000000..cba2f2dc
--- /dev/null
+++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockDoubleBanner/index.ts
@@ -0,0 +1,6 @@
+export { BlockDoubleBanner } from './BlockDoubleBanner';
+export {
+ DOUBLE_BANNER_BLOCK_CONFIG,
+ INITIAL_DOUBLE_BANNER_BLOCK_STATE,
+ INITIAL_DOUBLE_BANNER_COMPONENTS_STATE,
+} from './BlockDoubleBanner.editorconfig';
diff --git a/ui/src/react-admin/modules/content-page/const/content-block-config-map.ts b/ui/src/react-admin/modules/content-page/const/content-block-config-map.ts
index 9406f588..0cf08327 100644
--- a/ui/src/react-admin/modules/content-page/const/content-block-config-map.ts
+++ b/ui/src/react-admin/modules/content-page/const/content-block-config-map.ts
@@ -7,6 +7,7 @@ import { CARDS_WITHOUT_DESCRIPTION_BLOCK_CONFIG } from '~content-blocks/BlockCar
import { CONTENT_ENCLOSE_BLOCK_CONFIG } from '~content-blocks/BlockContentEnclose';
import { CONTENT_PAGE_META_BLOCK_CONFIG } from '~content-blocks/BlockContentPageMeta';
import { CTAS_BLOCK_CONFIG } from '~content-blocks/BlockCTAs';
+import { DOUBLE_BANNER_BLOCK_CONFIG } from '~content-blocks/BlockDoubleBanner';
import { EVENTBRITE_BLOCK_CONFIG } from '~content-blocks/BlockEventbrite';
import { HEADING_BLOCK_CONFIG } from '~content-blocks/BlockHeading';
import { HET_ARCHIEF_HEADER_SEARCH_BLOCK_CONFIG } from '~content-blocks/BlockHetArchiefHeaderSearch/BlockHetArchiefHeaderSearch.editorconfig';
@@ -95,4 +96,5 @@ export const CONTENT_BLOCK_CONFIG_MAP: Record<
[ContentBlockType.HighlightText]: CONTENT_HIGHLIGHT_TEXT_CONFIG,
[ContentBlockType.ThemeReels]: THEME_REELS_BLOCK_CONFIG,
[ContentBlockType.OverviewThemes]: OVERVIEW_THEMES_BLOCK_CONFIG,
+ [ContentBlockType.DoubleBanner]: DOUBLE_BANNER_BLOCK_CONFIG,
};
diff --git a/ui/src/react-admin/modules/content-page/const/content-block-initial-state-map.ts b/ui/src/react-admin/modules/content-page/const/content-block-initial-state-map.ts
index 61b21ca0..55a81bde 100644
--- a/ui/src/react-admin/modules/content-page/const/content-block-initial-state-map.ts
+++ b/ui/src/react-admin/modules/content-page/const/content-block-initial-state-map.ts
@@ -7,6 +7,7 @@ import { INITIAL_CARDS_WITHOUT_DESCRIPTION_COMPONENTS_STATE } from '~content-blo
import { INITIAL_CONTENT_ENCLOSE_BLOCK_STATE } from '~content-blocks/BlockContentEnclose/BlockContentEnclose.editorconfig';
import { INITIAL_CONTENT_PAGE_META_COMPONENTS_STATE } from '~content-blocks/BlockContentPageMeta';
import { INITIAL_CTAS_COMPONENTS_STATE } from '~content-blocks/BlockCTAs';
+import { INITIAL_DOUBLE_BANNER_COMPONENTS_STATE } from '~content-blocks/BlockDoubleBanner/BlockDoubleBanner.editorconfig';
import { INITIAL_EVENTBRITE_COMPONENTS_STATE } from '~content-blocks/BlockEventbrite';
import { INITIAL_HEADING_COMPONENTS_STATE } from '~content-blocks/BlockHeading';
import { INITIAL_HET_ARCHIEF_HEADER_SEARCH_BLOCK_STATE } from '~content-blocks/BlockHetArchiefHeaderSearch/BlockHetArchiefHeaderSearch.editorconfig';
@@ -98,4 +99,5 @@ export const CONTENT_BLOCK_INITIAL_STATE_MAP: {
[ContentBlockType.HighlightText]: INITIAL_CONTENT_HIGHLIGHT_TEXT_BLOCK_STATE,
[ContentBlockType.ThemeReels]: INITIAL_THEME_REELS_COMPONENTS_STATE,
[ContentBlockType.OverviewThemes]: INITIAL_OVERVIEW_THEMES_COMPONENTS_STATE,
+ [ContentBlockType.DoubleBanner]: INITIAL_DOUBLE_BANNER_COMPONENTS_STATE,
};
diff --git a/ui/src/react-admin/modules/content-page/const/get-content-block-type-options.ts b/ui/src/react-admin/modules/content-page/const/get-content-block-type-options.ts
index 18f589ed..8e955f28 100644
--- a/ui/src/react-admin/modules/content-page/const/get-content-block-type-options.ts
+++ b/ui/src/react-admin/modules/content-page/const/get-content-block-type-options.ts
@@ -214,6 +214,14 @@ export const GET_CONTENT_BLOCK_TYPE_OPTIONS: () => SelectOption