From 11717adea650fd99e5a8d4d73fbc592564fcb694 Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Tue, 11 Aug 2026 16:07:43 +0200 Subject: [PATCH 1/4] feat(ARC-3822): show breadcrumbs as overlay on the next content block --- .../ContentBlockRenderer.const.tsx | 1 + .../ContentBlockRenderer.scss | 45 +++++++++++++++++++ .../ContentBlockRenderer.tsx | 16 ++++++- .../BlockBreadcrumbs.editorconfig.ts | 12 +++++ .../content-page/types/content-block.types.ts | 1 + ui/src/shared/translations/hetArchief/nl.json | 1 + 6 files changed, 75 insertions(+), 1 deletion(-) diff --git a/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.const.tsx b/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.const.tsx index e398109ee..fa18d503b 100644 --- a/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.const.tsx +++ b/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.const.tsx @@ -157,6 +157,7 @@ export const IGNORE_BLOCK_LEVEL_PROPS = [ 'backgroundColor', 'blockType', 'elements', + 'overlayNextBlock', 'padding', 'position', ]; diff --git a/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.scss b/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.scss index 4c64bae06..be44fb78b 100644 --- a/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.scss +++ b/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.scss @@ -1,4 +1,5 @@ @use "../../../shared/styles/settings/colors" as colors; +@use "../../../shared/styles/settings/variables" as variables; .c-content-page-overview-block__header { opacity: 0; @@ -40,6 +41,50 @@ } } +// Lifts the block out of the flow so the block below it slides up underneath and this one paints +// on top of it: https://meemoo.atlassian.net/browse/ARC-3822 +// The block keeps its place in the DOM, so its links stay clickable and in the tab order. +// The z-index that puts it above that block is set in ContentBlockRenderer. +.c-content-block--overlay-next-block { + height: 0; + + // Dark scrim so light text stays legible over a photo. Taken from the design: 120px at 56% on + // desktop, 160px on mobile, where the breadcrumbs wrap over several lines. + // Desktop: https://www.figma.com/design/mps3ITECqMBQtdk8vheYOp/?node-id=455-3958 + // Mobile: https://www.figma.com/design/mps3ITECqMBQtdk8vheYOp/?node-id=455-6978 + // 1rem = 10px here, see font-size: 62.5% in shared/styles/elements/_base.scss. + &::before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 12rem; + background: linear-gradient(to bottom, rgb(0 0 0 / 56%), rgb(0 0 0 / 0%)); + + // Behind the breadcrumbs, but still above the block underneath, because the z-index on this + // block makes it a stacking context + z-index: -1; + + // Never swallow clicks meant for the block underneath + pointer-events: none; + + @media (max-width: variables.$g-bp2) { + height: 16rem; + } + } + + // The design puts the breadcrumbs 48px below the top of the block they cover, 24px on mobile. + // Overrides the block's padding field, which avo2-components applies with !important. + .c-content-block-preview { + padding-top: 4.8rem !important; + + @media (max-width: variables.$g-bp2) { + padding-top: 2.4rem !important; + } + } +} + .c-content-block-preview--dark { // Here you can overwrite styles on content-blocks for previews with a dark background .c-block-media-list { diff --git a/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.tsx b/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.tsx index 29054995a..fc8263f15 100644 --- a/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.tsx +++ b/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.tsx @@ -126,6 +126,19 @@ const ContentBlockRenderer: FunctionComponent = ({ blockState?.anchor?.replaceAll(' ', '-') || GENERATED_CONTENT_BLOCK_ANCHOR_PREFIX + contentBlockConfig.id; + // Blocks with a header background need a z-index, so the absolutely positioned background stays + // behind the block content. A block that overlays the next one has to beat that z-index, since + // the block it covers can carry one too: https://meemoo.atlassian.net/browse/ARC-3822 + const getZIndex = (): number | undefined => { + if (blockState?.overlayNextBlock) { + return 3; + } + if (blockState?.headerBackgroundColor !== Color.Transparent) { + return 1; + } + return undefined; + }; + return (
= ({ { 'c-content-block__meemoo-custom-background': blockState?.backgroundColor === CustomBackground.MeemooLogo, // https://meemoo.atlassian.net/browse/ARC-1237 + 'c-content-block--overlay-next-block': blockState?.overlayNextBlock, // https://meemoo.atlassian.net/browse/ARC-3822 } )} style={{ @@ -142,7 +156,7 @@ const ContentBlockRenderer: FunctionComponent = ({ blockState?.backgroundColor === CustomBackground.MeemooLogo ? Color.Transparent : blockState?.backgroundColor, - ...(blockState?.headerBackgroundColor !== Color.Transparent ? { zIndex: 1 } : {}), + zIndex: getZIndex(), }} data-anchor={anchor} ref={blockRef} diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockBreadcrumbs/BlockBreadcrumbs.editorconfig.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockBreadcrumbs/BlockBreadcrumbs.editorconfig.ts index 4186f0609..60fdd8f82 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockBreadcrumbs/BlockBreadcrumbs.editorconfig.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockBreadcrumbs/BlockBreadcrumbs.editorconfig.ts @@ -1,3 +1,4 @@ +import type { CheckboxProps } from '@viaa/avo2-components'; import type { AvoCoreContentPickerType } from '@viaa/avo2-types'; import { BLOCK_FIELD_DEFAULTS, BLOCK_STATE_DEFAULTS, TEXT_FIELD } from '~content-blocks/defaults'; import { GET_FOREGROUND_COLOR_OPTIONS_ARCHIEF } from '~modules/content-page/const/get-color-options'; @@ -32,6 +33,7 @@ export const INITIAL_BREADCRUMBS_BLOCK_STATE = (): DefaultContentBlockState => ( bottom: 'none', }, }), + overlayNextBlock: false, }); export const CONTENT_BREADCRUMBS_CONFIG = (position = 0): ContentBlockConfig => ({ @@ -104,6 +106,16 @@ export const CONTENT_BREADCRUMBS_CONFIG = (position = 0): ContentBlockConfig => state: INITIAL_BREADCRUMBS_BLOCK_STATE(), fields: { ...BLOCK_FIELD_DEFAULTS(), + overlayNextBlock: { + editorType: ContentBlockEditor.Checkbox, + editorProps: { + label: tText( + 'modules/content-page/components/blocks/block-breadcrumbs/block-breadcrumbs___overlay-op-andere-contentblokken', + {}, + [HET_ARCHIEF] + ), + } as CheckboxProps, + }, }, }, }); diff --git a/ui/src/react-admin/modules/content-page/types/content-block.types.ts b/ui/src/react-admin/modules/content-page/types/content-block.types.ts index d68f2e15f..acff30416 100644 --- a/ui/src/react-admin/modules/content-page/types/content-block.types.ts +++ b/ui/src/react-admin/modules/content-page/types/content-block.types.ts @@ -236,6 +236,7 @@ export interface DefaultContentBlockState { margin: PaddingFieldState; userGroupIds: number[]; fullWidth?: boolean; + overlayNextBlock?: boolean; // Renders the block on top of the block below it instead of above it: https://meemoo.atlassian.net/browse/ARC-3822 anchor?: string; // Contains an id that the user can enter, so they can link to this block using the anchor-block buttons } diff --git a/ui/src/shared/translations/hetArchief/nl.json b/ui/src/shared/translations/hetArchief/nl.json index b72f70321..acf19b8ca 100644 --- a/ui/src/shared/translations/hetArchief/nl.json +++ b/ui/src/shared/translations/hetArchief/nl.json @@ -655,6 +655,7 @@ "modules/content-page/components/blocks/block-breadcrumbs/block-breadcrumbs___breadcrumbs": "Breadcrumbs", "modules/content-page/components/blocks/block-breadcrumbs/block-breadcrumbs___label": "Label", "modules/content-page/components/blocks/block-breadcrumbs/block-breadcrumbs___link": "Link", + "modules/content-page/components/blocks/block-breadcrumbs/block-breadcrumbs___overlay-op-andere-contentblokken": "Overlay op andere contentblokken", "modules/content-page/components/blocks/block-breadcrumbs/block-breadcrumbs___tekstkleur": "Tekstkleur", "modules/content-page/components/blocks/block-breadcrumbs/block-breadcrumbs___verwijder-object": "Verwijder object", "modules/content-page/components/blocks/block-breadcrumbs/block-breadcrumbs___voeg-object-toe": "Voeg object toe", From 3acde0049d8bb29077d17979414d327c4b3f7f23 Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Wed, 12 Aug 2026 11:16:42 +0200 Subject: [PATCH 2/4] fix(ARC-3822): let the overlay block escape its zero-height box Doubles the class so it outranks the .c-content-block overflow: hidden that hetarchief-client loads after this file, and expresses the sizes in spacer units. --- .../ContentBlockRenderer.scss | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.scss b/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.scss index be44fb78b..9e0a3b44a 100644 --- a/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.scss +++ b/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.scss @@ -45,21 +45,26 @@ // on top of it: https://meemoo.atlassian.net/browse/ARC-3822 // The block keeps its place in the DOM, so its links stay clickable and in the tab order. // The z-index that puts it above that block is set in ContentBlockRenderer. -.c-content-block--overlay-next-block { +// The class is doubled to outrank `.c-content-block { overflow: hidden }` in hetarchief-client +// (src/styles/admin-core/_content-pages.scss), which loads after this file and would otherwise +// clip both the breadcrumbs and the scrim out of the zero-height box. +.c-content-block.c-content-block--overlay-next-block { height: 0; + // The whole mechanism relies on the content escaping this zero-height box + overflow: visible; + // Dark scrim so light text stays legible over a photo. Taken from the design: 120px at 56% on // desktop, 160px on mobile, where the breadcrumbs wrap over several lines. // Desktop: https://www.figma.com/design/mps3ITECqMBQtdk8vheYOp/?node-id=455-3958 // Mobile: https://www.figma.com/design/mps3ITECqMBQtdk8vheYOp/?node-id=455-6978 - // 1rem = 10px here, see font-size: 62.5% in shared/styles/elements/_base.scss. &::before { content: ""; position: absolute; top: 0; left: 0; right: 0; - height: 12rem; + height: variables.$g-spacer-unit * 15; // 120px background: linear-gradient(to bottom, rgb(0 0 0 / 56%), rgb(0 0 0 / 0%)); // Behind the breadcrumbs, but still above the block underneath, because the z-index on this @@ -70,17 +75,17 @@ pointer-events: none; @media (max-width: variables.$g-bp2) { - height: 16rem; + height: variables.$g-spacer-unit * 20; // 160px } } // The design puts the breadcrumbs 48px below the top of the block they cover, 24px on mobile. // Overrides the block's padding field, which avo2-components applies with !important. .c-content-block-preview { - padding-top: 4.8rem !important; + padding-top: variables.$g-spacer-unit * 6 !important; // 48px @media (max-width: variables.$g-bp2) { - padding-top: 2.4rem !important; + padding-top: variables.$g-spacer-unit * 1.75 !important; // 14px } } } From 260556d3914d4c869e3cb9805d73876ceffc3fd9 Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Wed, 12 Aug 2026 11:41:20 +0200 Subject: [PATCH 3/4] style(ARC-3822): drop ticket links from the overlay comments --- .../components/ContentBlockRenderer/ContentBlockRenderer.scss | 4 ++-- .../components/ContentBlockRenderer/ContentBlockRenderer.tsx | 4 ++-- .../modules/content-page/types/content-block.types.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.scss b/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.scss index 9e0a3b44a..c1252a21d 100644 --- a/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.scss +++ b/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.scss @@ -42,8 +42,8 @@ } // Lifts the block out of the flow so the block below it slides up underneath and this one paints -// on top of it: https://meemoo.atlassian.net/browse/ARC-3822 -// The block keeps its place in the DOM, so its links stay clickable and in the tab order. +// on top of it. The block keeps its place in the DOM, so its links stay clickable and in the tab +// order. // The z-index that puts it above that block is set in ContentBlockRenderer. // The class is doubled to outrank `.c-content-block { overflow: hidden }` in hetarchief-client // (src/styles/admin-core/_content-pages.scss), which loads after this file and would otherwise diff --git a/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.tsx b/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.tsx index d9652a7ba..18e84af99 100644 --- a/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.tsx +++ b/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.tsx @@ -131,7 +131,7 @@ const ContentBlockRenderer: FunctionComponent = ({ // Blocks with a header background need a z-index, so the absolutely positioned background stays // behind the block content. A block that overlays the next one has to beat that z-index, since - // the block it covers can carry one too: https://meemoo.atlassian.net/browse/ARC-3822 + // the block it covers can carry one too. const getZIndex = (): number | undefined => { if (blockState?.overlayNextBlock) { return 3; @@ -151,7 +151,7 @@ const ContentBlockRenderer: FunctionComponent = ({ { 'c-content-block__meemoo-custom-background': blockState?.backgroundColor === CustomBackground.MeemooLogo, // https://meemoo.atlassian.net/browse/ARC-1237 - 'c-content-block--overlay-next-block': blockState?.overlayNextBlock, // https://meemoo.atlassian.net/browse/ARC-3822 + 'c-content-block--overlay-next-block': blockState?.overlayNextBlock, } )} style={{ diff --git a/ui/src/react-admin/modules/content-page/types/content-block.types.ts b/ui/src/react-admin/modules/content-page/types/content-block.types.ts index aea6b1410..09d16412f 100644 --- a/ui/src/react-admin/modules/content-page/types/content-block.types.ts +++ b/ui/src/react-admin/modules/content-page/types/content-block.types.ts @@ -263,7 +263,7 @@ export interface DefaultContentBlockState { margin: PaddingFieldState; userGroupIds: number[]; fullWidth?: boolean; - overlayNextBlock?: boolean; // Renders the block on top of the block below it instead of above it: https://meemoo.atlassian.net/browse/ARC-3822 + overlayNextBlock?: boolean; // Renders the block on top of the block below it instead of above it anchor?: string; // Contains an id that the user can enter, so they can link to this block using the anchor-block buttons } From 7de1a7e60ed703297f03e2eff85396a979cdeb80 Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Thu, 13 Aug 2026 14:35:25 +0200 Subject: [PATCH 4/4] fix(ARC-3822): respect configured breadcrumb padding --- .../ContentBlockRenderer/ContentBlockRenderer.scss | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.scss b/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.scss index c1252a21d..20d1dd077 100644 --- a/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.scss +++ b/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.scss @@ -78,16 +78,6 @@ height: variables.$g-spacer-unit * 20; // 160px } } - - // The design puts the breadcrumbs 48px below the top of the block they cover, 24px on mobile. - // Overrides the block's padding field, which avo2-components applies with !important. - .c-content-block-preview { - padding-top: variables.$g-spacer-unit * 6 !important; // 48px - - @media (max-width: variables.$g-bp2) { - padding-top: variables.$g-spacer-unit * 1.75 !important; // 14px - } - } } .c-content-block-preview--dark {