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 dc4d6e65..fce8fe64 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 @@ -171,6 +171,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 4c64bae0..20d1dd07 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,45 @@ } } +// Lifts the block out of the flow so the block below it slides up underneath and this one paints +// 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 +// 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 + &::before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + 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 + // 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: variables.$g-spacer-unit * 20; // 160px + } + } +} + .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 ebe4043b..18e84af9 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 @@ -129,6 +129,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. + 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, } )} style={{ @@ -145,7 +159,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 4186f060..60fdd8f8 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 b8462c62..09d16412 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,6 +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 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 81ff1716..9c5f7dca 100644 --- a/ui/src/shared/translations/hetArchief/nl.json +++ b/ui/src/shared/translations/hetArchief/nl.json @@ -654,6 +654,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",