From a55c6693b3d75e448ad682afd5ea9ad13d572de7 Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Tue, 4 Aug 2026 13:39:59 +0200 Subject: [PATCH 01/17] refactor(ARC-3816): rename the quote block symbols to avo quote --- ui/src/client.ts | 2 +- .../ContentBlockRenderer.const.tsx | 4 ++-- .../BlockAvoQuote.editorconfig.ts} | 14 +++++++------- .../BlockAvoQuote.scss} | 0 .../BlockAvoQuote.test.tsx} | 6 +++--- .../BlockAvoQuote.tsx} | 6 +++--- .../components/blocks/BlockAvoQuote/index.ts | 2 ++ .../components/blocks/BlockQuote/index.ts | 2 -- .../content-page/const/content-block-config-map.ts | 4 ++-- .../const/content-block-initial-state-map.ts | 4 ++-- .../const/get-content-block-type-options.ts | 2 +- .../content-page/types/content-block.types.ts | 6 +++--- ui/src/react-admin/modules/index.ts | 2 +- ui/src/shared/helpers/admin-core-config.tsx | 2 +- 14 files changed, 28 insertions(+), 28 deletions(-) rename ui/src/react-admin/modules/content-page/components/blocks/{BlockQuote/BlockQuote.editorconfig.ts => BlockAvoQuote/BlockAvoQuote.editorconfig.ts} (79%) rename ui/src/react-admin/modules/content-page/components/blocks/{BlockQuote/BlockQuote.scss => BlockAvoQuote/BlockAvoQuote.scss} (100%) rename ui/src/react-admin/modules/content-page/components/blocks/{BlockQuote/BlockQuote.test.tsx => BlockAvoQuote/BlockAvoQuote.test.tsx} (86%) rename ui/src/react-admin/modules/content-page/components/blocks/{BlockQuote/BlockQuote.tsx => BlockAvoQuote/BlockAvoQuote.tsx} (76%) create mode 100644 ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/index.ts delete mode 100644 ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/index.ts diff --git a/ui/src/client.ts b/ui/src/client.ts index 1588c6387..fd9f16923 100644 --- a/ui/src/client.ts +++ b/ui/src/client.ts @@ -21,7 +21,7 @@ export { BlockMaintainersGrid } from '~content-blocks/BlockMaintainersGrid'; export { BlockOverviewNewspaperTitles } from '~content-blocks/BlockOverviewNewspaperTitles'; export { BlockOverviewWithCarousel } from '~content-blocks/BlockOverviewWithCarousel'; export { BlockPageOverviewWrapper } from '~content-blocks/BlockPageOverview/BlockPageOverview.wrapper'; -export { BlockQuote } from '~content-blocks/BlockQuote'; +export { BlockAvoQuote } from '~content-blocks/BlockAvoQuote'; export { BlockRichText } from '~content-blocks/BlockRichText'; export { BlockRichTextWrapper } from '~content-blocks/BlockRichText/BlockRichText.wrapper'; export { BlockScrollDownNudge } from '~content-blocks/BlockScrollDownNudge'; 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 53a9fb6a6..798258d1f 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 @@ -24,7 +24,7 @@ import { BlockMaintainersGrid } from '~content-blocks/BlockMaintainersGrid'; import { BlockOverviewNewspaperTitles } from '~content-blocks/BlockOverviewNewspaperTitles'; import { BlockOverviewWithCarousel } from '~content-blocks/BlockOverviewWithCarousel/BlockOverviewWithCarousel.tsx'; import { BlockPageOverviewWrapper } from '~content-blocks/BlockPageOverview'; -import { BlockQuote } from '~content-blocks/BlockQuote'; +import { BlockAvoQuote } from '~content-blocks/BlockAvoQuote'; import { BlockRichTextWrapper } from '~content-blocks/BlockRichText'; import { BlockScrollDownNudge } from '~content-blocks/BlockScrollDownNudge'; import { BlockProjectSpotlightWrapper, BlockSpotlight } from '~content-blocks/BlockSpotlight'; @@ -61,7 +61,7 @@ export function GET_BLOCK_COMPONENT( [ContentBlockType.MediaPlayer]: BlockVideoWrapper, [ContentBlockType.PageOverview]: BlockPageOverviewWrapper, [ContentBlockType.ProjectsSpotlight]: BlockProjectSpotlightWrapper, - [ContentBlockType.Quote]: BlockQuote, + [ContentBlockType.AvoQuote]: BlockAvoQuote, [ContentBlockType.RichTextTwoColumns]: BlockRichTextWrapper, [ContentBlockType.RichText]: BlockRichTextWrapper, [ContentBlockType.Spotlight]: BlockSpotlight, diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/BlockQuote.editorconfig.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.editorconfig.ts similarity index 79% rename from ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/BlockQuote.editorconfig.ts rename to ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.editorconfig.ts index b03e416c0..55ee3ef88 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/BlockQuote.editorconfig.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.editorconfig.ts @@ -1,21 +1,21 @@ import type { FileUploadProps } from '~shared/components/FileUpload/FileUpload'; import { tText } from '~shared/helpers/translation-functions'; import type { + AvoQuoteBlockComponentState, ContentBlockConfig, DefaultContentBlockState, - QuoteBlockComponentState, } from '../../../types/content-block.types'; import { ContentBlockType } from '../../../types/content-block.types'; import { BLOCK_FIELD_DEFAULTS, BLOCK_STATE_DEFAULTS, FILE_FIELD, TEXT_FIELD } from '../defaults'; -export const INITIAL_QUOTE_COMPONENTS_STATE = (): QuoteBlockComponentState => ({ +export const INITIAL_AVO_QUOTE_COMPONENTS_STATE = (): AvoQuoteBlockComponentState => ({ quote: '', authorName: '', authorInitials: '', }); -export const INITIAL_QUOTE_BLOCK_STATE = (): DefaultContentBlockState => +export const INITIAL_AVO_QUOTE_BLOCK_STATE = (): DefaultContentBlockState => BLOCK_STATE_DEFAULTS({ padding: { top: 'top-small', @@ -23,12 +23,12 @@ export const INITIAL_QUOTE_BLOCK_STATE = (): DefaultContentBlockState => }, }); -export const QUOTE_BLOCK_CONFIG = (position = 0): ContentBlockConfig => ({ +export const AVO_QUOTE_BLOCK_CONFIG = (position = 0): ContentBlockConfig => ({ position, name: tText('admin/content-block/helpers/generators/quote___quote'), - type: ContentBlockType.Quote, + type: ContentBlockType.AvoQuote, components: { - state: INITIAL_QUOTE_COMPONENTS_STATE(), + state: INITIAL_AVO_QUOTE_COMPONENTS_STATE(), fields: { quote: TEXT_FIELD( { @@ -54,7 +54,7 @@ export const QUOTE_BLOCK_CONFIG = (position = 0): ContentBlockConfig => ({ }, }, block: { - state: INITIAL_QUOTE_BLOCK_STATE(), + state: INITIAL_AVO_QUOTE_BLOCK_STATE(), fields: BLOCK_FIELD_DEFAULTS(), }, }); diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/BlockQuote.scss b/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.scss similarity index 100% rename from ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/BlockQuote.scss rename to ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.scss diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/BlockQuote.test.tsx b/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.test.tsx similarity index 86% rename from ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/BlockQuote.test.tsx rename to ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.test.tsx index 2384f83a6..332acf546 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/BlockQuote.test.tsx +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.test.tsx @@ -3,7 +3,7 @@ import { loremIpsum } from 'lorem-ipsum'; import React from 'react'; import { afterEach, describe, it } from 'vitest'; -import { BlockQuote } from './BlockQuote'; +import { BlockAvoQuote } from './BlockAvoQuote'; const customClass = 'c-block-custom'; const quote = loremIpsum({ count: 10 }); @@ -12,7 +12,7 @@ const authorName = loremIpsum({ count: 2 }); const authorInitials = 'AE'; const quoteExample = ( -
{ cleanup(); }); -describe('
', () => { +describe('', () => { it('Should be able to render', () => { render(quoteExample); }); diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/BlockQuote.tsx b/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.tsx similarity index 76% rename from ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/BlockQuote.tsx rename to ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.tsx index 96c8e2961..27aa6c9de 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/BlockQuote.tsx +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.tsx @@ -4,16 +4,16 @@ import clsx from 'clsx'; import type { FunctionComponent } from 'react'; import React from 'react'; -import './BlockQuote.scss'; +import './BlockAvoQuote.scss'; -export interface BlockQuoteProps extends DefaultProps { +export interface BlockAvoQuoteProps extends DefaultProps { quote: string; authorImage?: string; authorName: string; authorInitials?: string; } -export const BlockQuote: FunctionComponent = ({ +export const BlockAvoQuote: FunctionComponent = ({ className, quote, authorImage, diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/index.ts new file mode 100644 index 000000000..cc549247d --- /dev/null +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/index.ts @@ -0,0 +1,2 @@ +export * from './BlockAvoQuote'; +export * from './BlockAvoQuote.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/index.ts deleted file mode 100644 index a03d999c1..000000000 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './BlockQuote'; -export * from './BlockQuote.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 470d2a55d..7f98ede5f 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 @@ -25,7 +25,7 @@ import { MAINTAINERS_GRID_BLOCK_CONFIG } from '~content-blocks/BlockMaintainersG import { MEDIA_GRID_BLOCK_CONFIG } from '~content-blocks/BlockMediaGrid'; import { OVERVIEW_NEWSPAPER_TITLES_BLOCK_CONFIG } from '~content-blocks/BlockOverviewNewspaperTitles'; import { CONTENT_OVERVIEW_WITH_CAROUSEL_CONFIG } from '~content-blocks/BlockOverviewWithCarousel'; -import { QUOTE_BLOCK_CONFIG } from '~content-blocks/BlockQuote'; +import { AVO_QUOTE_BLOCK_CONFIG } from '~content-blocks/BlockAvoQuote'; import { RICH_TEXT_BLOCK_CONFIG, RICH_TEXT_TWO_COLUMNS_BLOCK_CONFIG, @@ -62,7 +62,7 @@ export const CONTENT_BLOCK_CONFIG_MAP: Record< [ContentBlockType.MediaGrid]: MEDIA_GRID_BLOCK_CONFIG, [ContentBlockType.MediaPlayer]: MEDIA_PLAYER_BLOCK_CONFIG, [ContentBlockType.MediaPlayerTitleTextButton]: MEDIA_PLAYER_TITLE_TEXT_BUTTON_BLOCK_CONFIG, - [ContentBlockType.Quote]: QUOTE_BLOCK_CONFIG, + [ContentBlockType.AvoQuote]: AVO_QUOTE_BLOCK_CONFIG, [ContentBlockType.PageOverview]: PAGE_OVERVIEW_BLOCK_CONFIG, [ContentBlockType.ProjectsSpotlight]: PROJECTS_SPOTLIGHT_BLOCK_CONFIG, [ContentBlockType.Spotlight]: SPOTLIGHT_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 a864713a5..10ff3f862 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 @@ -26,7 +26,7 @@ import { INITIAL_MEDIA_GRID_COMPONENTS_STATE } from '~content-blocks/BlockMediaG import { INITIAL_OVERVIEW_NEWSPAPER_TITLES_BLOCK_STATE } from '~content-blocks/BlockOverviewNewspaperTitles'; import { INITIAL_CONTENT_OVERVIEW_WITH_CAROUSEL_BLOCK_STATE } from '~content-blocks/BlockOverviewWithCarousel/BlockOverviewWithCarousel.editorconfig.ts'; import { INITIAL_PAGE_OVERVIEW_COMPONENTS_STATE } from '~content-blocks/BlockPageOverview'; -import { INITIAL_QUOTE_COMPONENTS_STATE } from '~content-blocks/BlockQuote'; +import { INITIAL_AVO_QUOTE_COMPONENTS_STATE } from '~content-blocks/BlockAvoQuote'; import { INITIAL_RICH_TEXT_COMPONENTS_STATE, INITIAL_RICH_TEXT_TWO_COLUMNS_COMPONENTS_STATE, @@ -67,7 +67,7 @@ export const CONTENT_BLOCK_INITIAL_STATE_MAP: { [ContentBlockType.PageOverview]: INITIAL_PAGE_OVERVIEW_COMPONENTS_STATE, [ContentBlockType.ProjectsSpotlight]: INITIAL_PROJECTS_SPOTLIGHT_COMPONENTS_STATE, [ContentBlockType.Spotlight]: INITIAL_SPOTLIGHT_COMPONENTS_STATE, - [ContentBlockType.Quote]: INITIAL_QUOTE_COMPONENTS_STATE, + [ContentBlockType.AvoQuote]: INITIAL_AVO_QUOTE_COMPONENTS_STATE, [ContentBlockType.RichText]: INITIAL_RICH_TEXT_COMPONENTS_STATE, [ContentBlockType.RichTextTwoColumns]: INITIAL_RICH_TEXT_TWO_COLUMNS_COMPONENTS_STATE, [ContentBlockType.Search]: INITIAL_SEARCH_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 94bcf7c77..0bc4a2327 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 @@ -80,7 +80,7 @@ export const GET_CONTENT_BLOCK_TYPE_OPTIONS: () => SelectOption[] = () = }, { label: tText('admin/content-block/content-block___quote'), - value: ContentBlockType.Quote, + value: ContentBlockType.AvoQuote, }, { label: tText('admin/content-block/helpers/generators/anchor-links___links'), 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 5135bb255..a6152761b 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 @@ -168,7 +168,7 @@ export enum ContentBlockType { MediaPlayerTitleTextButton = 'MEDIA_PLAYER_TITLE_TEXT_BUTTON', PageOverview = 'PAGE_OVERVIEW', ProjectsSpotlight = 'PROJECTS_SPOTLIGHT', - Quote = 'QUOTE', + AvoQuote = 'QUOTE', // Avo RichText = 'RICH_TEXT', RichTextTwoColumns = 'RICH_TEXT_TWO_COLUMNS', Search = 'SEARCH', @@ -358,7 +358,7 @@ export interface IFrameBlockComponentState { src: string; } -export interface QuoteBlockComponentState { +export interface AvoQuoteBlockComponentState { quote: string; authorName: string; authorInitials: string; @@ -456,7 +456,7 @@ export type SingleContentBlockComponentState = | MediaPlayerBlockComponentState | MediaPlayerTitleTextButtonBlockComponentState | PageOverviewBlockComponentStateFields - | QuoteBlockComponentState + | AvoQuoteBlockComponentState | RichTextBlockComponentState // biome-ignore lint/complexity/noBannedTypes: todo | {}; // Search block & content page meta diff --git a/ui/src/react-admin/modules/index.ts b/ui/src/react-admin/modules/index.ts index 540ced09a..0b385439a 100644 --- a/ui/src/react-admin/modules/index.ts +++ b/ui/src/react-admin/modules/index.ts @@ -118,7 +118,7 @@ export * from './content-page/components/blocks/BlockMaintainersGrid/BlockMainta export * from './content-page/components/blocks/BlockMediaGrid/BlockMediaGrid.editorconfig'; export * from './content-page/components/blocks/BlockOverviewNewspaperTitles/BlockOverviewNewspaperTitles'; export * from './content-page/components/blocks/BlockPageOverview/BlockPageOverview'; -export * from './content-page/components/blocks/BlockQuote/BlockQuote'; +export * from './content-page/components/blocks/BlockAvoQuote/BlockAvoQuote'; export * from './content-page/components/blocks/BlockRichText/BlockRichText'; export * from './content-page/components/blocks/BlockSpotlight/BlockSpotlight'; export * from './content-page/components/blocks/BlockTagsWithLink/BlockTagsWithLink'; diff --git a/ui/src/shared/helpers/admin-core-config.tsx b/ui/src/shared/helpers/admin-core-config.tsx index c9e68078d..5a3d9bd50 100644 --- a/ui/src/shared/helpers/admin-core-config.tsx +++ b/ui/src/shared/helpers/admin-core-config.tsx @@ -78,7 +78,7 @@ export function getAdminCoreConfigForLocalTestApp(navigateFunc: NavigateFunction ContentBlockType.ImageGrid, ContentBlockType.PageOverview, ContentBlockType.UspGrid, - ContentBlockType.Quote, + ContentBlockType.AvoQuote, ContentBlockType.CTAs, // AVO ContentBlockType.AnchorLinks, From 506dc42001af56340d868301d86a9aa8096434e2 Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Tue, 4 Aug 2026 13:47:56 +0200 Subject: [PATCH 02/17] fix(ARC-3816): honour the explicit default value in the colour field helpers --- .../components/blocks/defaults.test.ts | 30 +++++++++++++++++++ .../components/blocks/defaults.ts | 17 +++++------ 2 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 ui/src/react-admin/modules/content-page/components/blocks/defaults.test.ts diff --git a/ui/src/react-admin/modules/content-page/components/blocks/defaults.test.ts b/ui/src/react-admin/modules/content-page/components/blocks/defaults.test.ts new file mode 100644 index 000000000..11336ef29 --- /dev/null +++ b/ui/src/react-admin/modules/content-page/components/blocks/defaults.test.ts @@ -0,0 +1,30 @@ +import { describe, expect, it, vi } from 'vitest'; + +vi.mock('~shared/helpers/is-avo', () => ({ isAvo: () => false })); +vi.mock('~shared/helpers/translation-functions', () => ({ + tText: (key: string) => key, + tHtml: (key: string) => key, +})); + +import { Color } from '../../types/content-block.types'; +import { BACKGROUND_COLOR_FIELD, FOREGROUND_COLOR_FIELD } from './defaults'; + +describe('colour field helpers', () => { + it('BACKGROUND_COLOR_FIELD honours an explicit defaultValue', () => { + const field = BACKGROUND_COLOR_FIELD('Kleur kader', { + label: 'Zwart', + value: Color.Black, + }); + + expect(field.editorProps.defaultValue.value).toEqual(Color.Black); + }); + + it('FOREGROUND_COLOR_FIELD honours an explicit defaultValue', () => { + const field = FOREGROUND_COLOR_FIELD('Tekstkleur', { + label: 'Wit', + value: Color.White, + }); + + expect(field.editorProps.defaultValue.value).toEqual(Color.White); + }); +}); diff --git a/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts b/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts index bd5fe4469..3949ac640 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts @@ -81,24 +81,22 @@ export const FOREGROUND_COLOR_FIELD = ( editorProps: { options: isAvo() ? GET_FOREGROUND_COLOR_OPTIONS_AVO() : GET_FOREGROUND_COLOR_OPTIONS_ARCHIEF(), defaultValue: - defaultValue || isAvo() - ? GET_FOREGROUND_COLOR_OPTIONS_AVO()[0] - : GET_FOREGROUND_COLOR_OPTIONS_ARCHIEF()[0], + defaultValue ?? + (isAvo() ? GET_FOREGROUND_COLOR_OPTIONS_AVO()[0] : GET_FOREGROUND_COLOR_OPTIONS_ARCHIEF()[0]), }, }); export const BACKGROUND_COLOR_FIELD = ( label: string, - defaultValue: SelectOption + defaultValue?: SelectOption ): ContentBlockField => ({ label, editorType: ContentBlockEditor.ColorSelect, editorProps: { options: isAvo() ? GET_BACKGROUND_COLOR_OPTIONS_AVO() : GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF(), defaultValue: - defaultValue || isAvo() - ? GET_BACKGROUND_COLOR_OPTIONS_AVO()[0] - : GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF()[0], + defaultValue ?? + (isAvo() ? GET_BACKGROUND_COLOR_OPTIONS_AVO()[0] : GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF()[0]), }, }); @@ -111,9 +109,8 @@ export const BACKGROUND_COLOR_EXTENDED_FIELD = ( editorProps: { options: isAvo() ? GET_COLOR_OPTIONS_EXTENDED_AVO() : GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF(), defaultValue: - defaultValue || isAvo() - ? GET_COLOR_OPTIONS_EXTENDED_AVO()[0] - : GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF()[0], + defaultValue ?? + (isAvo() ? GET_COLOR_OPTIONS_EXTENDED_AVO()[0] : GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF()[0]), }, }); From 9776dc09f0de87825a65c479f19df1ddd0b2370d Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Tue, 4 Aug 2026 13:58:20 +0200 Subject: [PATCH 03/17] feat(ARC-3816): add the hetarchief quote block component --- .../BlockHetarchiefQuote.scss | 58 +++++++++++++++++++ .../BlockHetarchiefQuote.test.tsx | 50 ++++++++++++++++ .../BlockHetarchiefQuote.tsx | 41 +++++++++++++ .../blocks/BlockHetarchiefQuote/index.ts | 1 + .../content-page/types/content-block.types.ts | 9 +++ 5 files changed, 159 insertions(+) create mode 100644 ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.scss create mode 100644 ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.test.tsx create mode 100644 ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.tsx create mode 100644 ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/index.ts diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.scss b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.scss new file mode 100644 index 000000000..17bd33481 --- /dev/null +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.scss @@ -0,0 +1,58 @@ +.c-block-hetarchief-quote { + display: grid; + grid-template-columns: 10.4rem 1fr; + grid-template-areas: + 'mark quote' + '. author'; + align-content: center; + margin: 0; + // 19.2rem is the space Figma leaves between the text column (ends at x=816) and the frame + // edge (1008px), which keeps the text clear of the semicircular curve. + padding: 4rem 19.2rem 4rem 0; + background: var(--frame-color); + color: var(--text-color); + // Square left, true semicircular right end at any height, per Figma (r = height / 2). + border-radius: 0 9999px 9999px 0; + + &__mark { + grid-area: mark; + // Figma node 455:5723: icon font "meemoocons-light", size 64/line-height 72. + font-family: 'meemoocons-light'; + font-size: 6.4rem; + font-weight: normal; + line-height: 7.2rem; + letter-spacing: normal; + } + + &__quote { + grid-area: quote; + margin: 0; + // Figma node 455:5724, style "P - XL": Sofia Pro Medium, 32/40, letter-spacing 0. + font-family: 'SofiaPro'; + font-size: 3.2rem; + font-weight: 500; + line-height: 4rem; + letter-spacing: normal; + } + + &__author { + grid-area: author; + margin-top: 0.8rem; + // Figma node 455:5725, style "P - S": Sofia Pro Medium, 14/20, letter-spacing 0. + font-family: 'SofiaPro'; + font-size: 1.4rem; + font-weight: 500; + line-height: 2rem; + letter-spacing: normal; + } + + @media (max-width: 768px) { + grid-template-columns: 1fr; + grid-template-areas: + 'mark' + 'quote' + 'author'; + padding: 2.4rem 2.4rem 2.4rem 1.6rem; + border-radius: 0 2.4rem 2.4rem 0; + } +} diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.test.tsx b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.test.tsx new file mode 100644 index 000000000..71a7ee7ba --- /dev/null +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.test.tsx @@ -0,0 +1,50 @@ +import { cleanup, render, screen } from '@testing-library/react'; +import React from 'react'; +import { afterEach, describe, expect, it } from 'vitest'; + +import { Color } from '../../../types/content-block.types'; +import { BlockHetarchiefQuote } from './BlockHetarchiefQuote'; + +afterEach(() => { + cleanup(); +}); + +describe('', () => { + it('renders the quote and the author', () => { + render( + + ); + + expect(screen.getByText('Een citaat')).toBeTruthy(); + expect(screen.getByText('John Doe')).toBeTruthy(); + }); + + it('exposes the chosen colours as custom properties', () => { + const { container } = render( + + ); + + const figure = container.querySelector('.c-block-hetarchief-quote') as HTMLElement; + + expect(figure.style.getPropertyValue('--text-color')).toEqual(Color.White); + expect(figure.style.getPropertyValue('--frame-color')).toEqual(Color.OceanGreen); + }); + + it('omits the caption when there is no author', () => { + const { container } = render( + + ); + + expect(container.querySelector('figcaption')).toBeNull(); + }); +}); diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.tsx b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.tsx new file mode 100644 index 000000000..f7a94752e --- /dev/null +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.tsx @@ -0,0 +1,41 @@ +import type { DefaultProps } from '@viaa/avo2-components'; +import clsx from 'clsx'; +import type { CSSProperties, FunctionComponent } from 'react'; +import React from 'react'; + +import type { Color, CustomBackground, GradientColor } from '../../../types/content-block.types'; + +import './BlockHetarchiefQuote.scss'; + +export interface BlockHetarchiefQuoteProps extends DefaultProps { + quote: string; + authorName?: string; + textColor: Color; + frameColor: Color | GradientColor | CustomBackground; +} + +export const BlockHetarchiefQuote: FunctionComponent = ({ + className, + quote, + authorName, + textColor, + frameColor, +}) => ( +
+ +
{quote}
+ {authorName && ( +
{authorName}
+ )} +
+); diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/index.ts new file mode 100644 index 000000000..d635d8ac3 --- /dev/null +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/index.ts @@ -0,0 +1 @@ +export * from './BlockHetarchiefQuote'; 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 a6152761b..9345d20e3 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 @@ -181,6 +181,7 @@ export enum ContentBlockType { HetArchiefImageTextBackground = 'IMAGE_TEXT_BACKGROUND', // Hetarchief MaintainersGrid = 'MAINTAINERS_GRID', HetArchiefHeaderSearch = 'HETARCHIEF__HEADER_SEARCH', + HetarchiefQuote = 'HETARCHIEF_QUOTE', // Hetarchief OverviewNewspaperTitles = 'OVERVIEW_NEWSPAPER_TITLES', ContentEncloseGrid = 'CONTENT_ENCLOSE_GRID', Breadcrumbs = 'BREADCRUMBS', @@ -457,6 +458,7 @@ export type SingleContentBlockComponentState = | MediaPlayerTitleTextButtonBlockComponentState | PageOverviewBlockComponentStateFields | AvoQuoteBlockComponentState + | HetarchiefQuoteBlockComponentState | RichTextBlockComponentState // biome-ignore lint/complexity/noBannedTypes: todo | {}; // Search block & content page meta @@ -591,6 +593,13 @@ export interface HetArchiefHeaderSearchBlockComponentState { textBelowSearch?: string; } +export interface HetarchiefQuoteBlockComponentState { + quote: string; + authorName: string; + textColor: Color; + frameColor: Color | GradientColor | CustomBackground; +} + export interface HetArchiefIeObject { name: string; schemaIdentifier: string; From 7a77b807b3ab92d87dd0f4ea6a7addd034643903 Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Tue, 4 Aug 2026 14:15:00 +0200 Subject: [PATCH 04/17] feat(ARC-3816): register the hetarchief quote content block --- ui/src/client.ts | 1 + .../ContentBlockRenderer.const.tsx | 2 + .../BlockHetarchiefQuote.editorconfig.ts | 70 +++++++++++++++++++ .../blocks/BlockHetarchiefQuote/index.ts | 1 + .../const/content-block-config-map.ts | 2 + .../const/content-block-initial-state-map.ts | 2 + .../const/get-content-block-type-options.ts | 8 +++ ui/src/react-admin/modules/index.ts | 1 + ui/src/shared/helpers/admin-core-config.tsx | 1 + 9 files changed, 88 insertions(+) create mode 100644 ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.editorconfig.ts diff --git a/ui/src/client.ts b/ui/src/client.ts index fd9f16923..c2a92f3dd 100644 --- a/ui/src/client.ts +++ b/ui/src/client.ts @@ -9,6 +9,7 @@ export { BlockEventbrite } from '~content-blocks/BlockEventbrite'; export { BlockHeading } from '~content-blocks/BlockHeading/BlockHeading'; export { BlockHetArchiefHeaderSearch } from '~content-blocks/BlockHetArchiefHeaderSearch'; export { BlockHetArchiefImageTextBackground } from '~content-blocks/BlockHetArchiefImageTextBackground'; +export { BlockHetarchiefQuote } from '~content-blocks/BlockHetarchiefQuote'; export { BlockIFrame } from '~content-blocks/BlockIFrame'; export { BlockImage } from '~content-blocks/BlockImage'; export { BlockImageGridWrapper } from '~content-blocks/BlockImageGrid/BlockImageGrid.wrapper'; 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 798258d1f..7191ac9bf 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 @@ -10,6 +10,7 @@ import { BlockEventbrite } from '~content-blocks/BlockEventbrite'; import { BlockHeading } from '~content-blocks/BlockHeading'; import { BlockHetArchiefHeaderSearch } from '~content-blocks/BlockHetArchiefHeaderSearch/BlockHetArchiefHeaderSearch'; import { BlockHetArchiefImageTextBackground } from '~content-blocks/BlockHetArchiefImageTextBackground'; +import { BlockHetarchiefQuote } from '~content-blocks/BlockHetarchiefQuote'; import { BlockIFrame } from '~content-blocks/BlockIFrame'; import { BlockImage } from '~content-blocks/BlockImage'; import { @@ -87,6 +88,7 @@ export function GET_BLOCK_COMPONENT( [ContentBlockType.Breadcrumbs]: BlockBreadcrumbs, [ContentBlockType.HetArchiefImageTextBackground]: BlockHetArchiefImageTextBackground, [ContentBlockType.OverviewWithCarousel]: BlockOverviewWithCarousel, + [ContentBlockType.HetarchiefQuote]: BlockHetarchiefQuote, // Avo specific blocks [ContentBlockType.MediaGrid]: loadComponentFromConfig(ContentBlockType.MediaGrid), diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.editorconfig.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.editorconfig.ts new file mode 100644 index 000000000..3f945d162 --- /dev/null +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.editorconfig.ts @@ -0,0 +1,70 @@ +import { tText } from '~shared/helpers/translation-functions'; +import type { + ContentBlockConfig, + DefaultContentBlockState, + HetarchiefQuoteBlockComponentState, +} from '../../../types/content-block.types'; +import { Color, ContentBlockEditor, ContentBlockType } from '../../../types/content-block.types'; + +import { + BACKGROUND_COLOR_FIELD, + BLOCK_FIELD_DEFAULTS, + BLOCK_STATE_DEFAULTS, + TEXT_FIELD, +} from '../defaults'; + +export const INITIAL_HETARCHIEF_QUOTE_COMPONENTS_STATE = + (): HetarchiefQuoteBlockComponentState => ({ + quote: '', + authorName: '', + textColor: Color.White, + frameColor: Color.Black, + }); + +export const INITIAL_HETARCHIEF_QUOTE_BLOCK_STATE = (): DefaultContentBlockState => + BLOCK_STATE_DEFAULTS({ + padding: { + top: 'top-small', + bottom: 'bottom-small', + }, + }); + +export const HETARCHIEF_QUOTE_BLOCK_CONFIG = (position = 0): ContentBlockConfig => ({ + position, + name: tText('admin/content-block/helpers/generators/hetarchief-quote___quote-kader'), + type: ContentBlockType.HetarchiefQuote, + components: { + state: INITIAL_HETARCHIEF_QUOTE_COMPONENTS_STATE(), + fields: { + quote: TEXT_FIELD( + { + label: tText('admin/content-block/helpers/generators/quote___quote'), + editorType: ContentBlockEditor.TextArea, + }, + tText('admin/content-block/helpers/generators/quote___quote-is-verplicht') + ), + authorName: TEXT_FIELD({ + label: tText('admin/content-block/helpers/generators/quote___auteur'), + validator: undefined, + }), + textColor: BACKGROUND_COLOR_FIELD( + tText('admin/content-block/helpers/generators/hetarchief-quote___tekstkleur'), + { + label: tText('admin/content-block/content-block___wit'), + value: Color.White, + } + ), + frameColor: BACKGROUND_COLOR_FIELD( + tText('admin/content-block/helpers/generators/hetarchief-quote___kleur-kader'), + { + label: tText('modules/content-page/const/content-block___zwart'), + value: Color.Black, + } + ), + }, + }, + block: { + state: INITIAL_HETARCHIEF_QUOTE_BLOCK_STATE(), + fields: BLOCK_FIELD_DEFAULTS(), + }, +}); diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/index.ts index d635d8ac3..5b2eec1ae 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/index.ts @@ -1 +1,2 @@ export * from './BlockHetarchiefQuote'; +export * from './BlockHetarchiefQuote.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 7f98ede5f..cca00c886 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 @@ -11,6 +11,7 @@ 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'; import { HET_ARCHIEF_IMAGE_TEXT_BACKGROUND_BLOCK_CONFIG } from '~content-blocks/BlockHetArchiefImageTextBackground'; +import { HETARCHIEF_QUOTE_BLOCK_CONFIG } from '~content-blocks/BlockHetarchiefQuote'; import { IFRAME_BLOCK_CONFIG } from '~content-blocks/BlockIFrame'; import { IMAGE_BLOCK_CONFIG } from '~content-blocks/BlockImage'; import { @@ -63,6 +64,7 @@ export const CONTENT_BLOCK_CONFIG_MAP: Record< [ContentBlockType.MediaPlayer]: MEDIA_PLAYER_BLOCK_CONFIG, [ContentBlockType.MediaPlayerTitleTextButton]: MEDIA_PLAYER_TITLE_TEXT_BUTTON_BLOCK_CONFIG, [ContentBlockType.AvoQuote]: AVO_QUOTE_BLOCK_CONFIG, + [ContentBlockType.HetarchiefQuote]: HETARCHIEF_QUOTE_BLOCK_CONFIG, [ContentBlockType.PageOverview]: PAGE_OVERVIEW_BLOCK_CONFIG, [ContentBlockType.ProjectsSpotlight]: PROJECTS_SPOTLIGHT_BLOCK_CONFIG, [ContentBlockType.Spotlight]: SPOTLIGHT_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 10ff3f862..0f0876806 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 @@ -11,6 +11,7 @@ import { INITIAL_EVENTBRITE_COMPONENTS_STATE } from '~content-blocks/BlockEventb import { INITIAL_HEADING_COMPONENTS_STATE } from '~content-blocks/BlockHeading'; import { INITIAL_HET_ARCHIEF_HEADER_SEARCH_BLOCK_STATE } from '~content-blocks/BlockHetArchiefHeaderSearch/BlockHetArchiefHeaderSearch.editorconfig'; import { INITIAL_HET_ARCHIEF_IMAGE_TEXT_BACKGROUND_BLOCK_STATE } from '~content-blocks/BlockHetArchiefImageTextBackground'; +import { INITIAL_HETARCHIEF_QUOTE_COMPONENTS_STATE } from '~content-blocks/BlockHetarchiefQuote'; import { INITIAL_IFRAME_COMPONENTS_STATE } from '~content-blocks/BlockIFrame'; import { INITIAL_IMAGE_COMPONENTS_STATE } from '~content-blocks/BlockImage'; import { @@ -68,6 +69,7 @@ export const CONTENT_BLOCK_INITIAL_STATE_MAP: { [ContentBlockType.ProjectsSpotlight]: INITIAL_PROJECTS_SPOTLIGHT_COMPONENTS_STATE, [ContentBlockType.Spotlight]: INITIAL_SPOTLIGHT_COMPONENTS_STATE, [ContentBlockType.AvoQuote]: INITIAL_AVO_QUOTE_COMPONENTS_STATE, + [ContentBlockType.HetarchiefQuote]: INITIAL_HETARCHIEF_QUOTE_COMPONENTS_STATE, [ContentBlockType.RichText]: INITIAL_RICH_TEXT_COMPONENTS_STATE, [ContentBlockType.RichTextTwoColumns]: INITIAL_RICH_TEXT_TWO_COLUMNS_COMPONENTS_STATE, [ContentBlockType.Search]: INITIAL_SEARCH_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 0bc4a2327..daa7ecc08 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 @@ -184,6 +184,14 @@ export const GET_CONTENT_BLOCK_TYPE_OPTIONS: () => SelectOption[] = () = ), value: ContentBlockType.OverviewWithCarousel, }, + { + label: tText( + 'modules/content-page/const/get-content-block-type-options___quote-kader', + {}, + [HET_ARCHIEF] + ), + value: ContentBlockType.HetarchiefQuote, + }, ]; // Only show the content blocks that the client enabled through the config object diff --git a/ui/src/react-admin/modules/index.ts b/ui/src/react-admin/modules/index.ts index 0b385439a..553b0f193 100644 --- a/ui/src/react-admin/modules/index.ts +++ b/ui/src/react-admin/modules/index.ts @@ -108,6 +108,7 @@ export * from './content-page/components/blocks/BlockEventbrite/BlockEventbrite' export * from './content-page/components/blocks/BlockHeading/BlockHeading'; export * from './content-page/components/blocks/BlockHetArchiefHeaderSearch/BlockHetArchiefHeaderSearch'; export * from './content-page/components/blocks/BlockHetArchiefImageTextBackground/BlockHetArchiefImageTextBackground'; +export * from './content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote'; export * from './content-page/components/blocks/BlockIFrame/BlockIFrame'; export * from './content-page/components/blocks/BlockImage/BlockImage'; export * from './content-page/components/blocks/BlockImageGrid/BlockImageGrid'; diff --git a/ui/src/shared/helpers/admin-core-config.tsx b/ui/src/shared/helpers/admin-core-config.tsx index 5a3d9bd50..831f91639 100644 --- a/ui/src/shared/helpers/admin-core-config.tsx +++ b/ui/src/shared/helpers/admin-core-config.tsx @@ -97,6 +97,7 @@ export function getAdminCoreConfigForLocalTestApp(navigateFunc: NavigateFunction // ContentBlockType.ContentEncloseGrid, // ContentBlockType.Breadcrumbs, ContentBlockType.OverviewWithCarousel, + ContentBlockType.HetarchiefQuote, ], defaultPageWidth: ContentPageWidth.LARGE, onSaveContentPage: async (contentPageInfo: ContentPageInfo) => { From c4162f3580a666c8f94efa59ec1074168e1719c5 Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Tue, 4 Aug 2026 15:04:37 +0200 Subject: [PATCH 05/17] fix(ARC-3816): render the quote ligature, fix casing, lint, and widen textColor - BlockHetArchiefQuote: render the meemoocons-light ligature via the literal word "quotes" instead of U+201D, which the icon font has no glyph for. font-feature-settings/font-variant-ligatures enable the ligature, with a sans-serif fallback since admin-core doesn't ship the font. - Rename HetarchiefQuote symbols to HetArchiefQuote casing to match sibling HetArchief* blocks (enum VALUE and tText keys stay byte-identical). - Fix the 6 biome ci regressions: reorder the Avo quote block's imports/exports back beside BlockAvoHero, and reformat the wrapped tText call. - Widen textColor to Color | GradientColor | CustomBackground to match what BACKGROUND_COLOR_FIELD actually allows. - Use the shared $g-bp2 breakpoint instead of a hardcoded 768px value. - Clear stylelint violations in the new SCSS (unquoted font names, generic fallbacks, comment spacing, media-feature range notation). - Preserve authored line breaks in the quote text via white-space: pre-line. Co-Authored-By: Claude Opus 5 --- ui/src/client.ts | 4 ++-- .../ContentBlockRenderer.const.tsx | 6 ++--- .../BlockHetArchiefQuote.editorconfig.ts} | 16 ++++++------- .../BlockHetArchiefQuote.scss} | 24 ++++++++++++++----- .../BlockHetArchiefQuote.test.tsx} | 23 +++++++++++++----- .../BlockHetArchiefQuote.tsx} | 18 +++++++------- .../blocks/BlockHetArchiefQuote/index.ts | 2 ++ .../blocks/BlockHetarchiefQuote/index.ts | 2 -- .../const/content-block-config-map.ts | 6 ++--- .../const/content-block-initial-state-map.ts | 6 ++--- .../const/get-content-block-type-options.ts | 10 ++++---- .../content-page/types/content-block.types.ts | 8 +++---- ui/src/react-admin/modules/index.ts | 4 ++-- ui/src/shared/helpers/admin-core-config.tsx | 2 +- 14 files changed, 76 insertions(+), 55 deletions(-) rename ui/src/react-admin/modules/content-page/components/blocks/{BlockHetarchiefQuote/BlockHetarchiefQuote.editorconfig.ts => BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts} (77%) rename ui/src/react-admin/modules/content-page/components/blocks/{BlockHetarchiefQuote/BlockHetarchiefQuote.scss => BlockHetArchiefQuote/BlockHetArchiefQuote.scss} (71%) rename ui/src/react-admin/modules/content-page/components/blocks/{BlockHetarchiefQuote/BlockHetarchiefQuote.test.tsx => BlockHetArchiefQuote/BlockHetArchiefQuote.test.tsx} (60%) rename ui/src/react-admin/modules/content-page/components/blocks/{BlockHetarchiefQuote/BlockHetarchiefQuote.tsx => BlockHetArchiefQuote/BlockHetArchiefQuote.tsx} (54%) create mode 100644 ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/index.ts delete mode 100644 ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/index.ts diff --git a/ui/src/client.ts b/ui/src/client.ts index c2a92f3dd..5a8f90954 100644 --- a/ui/src/client.ts +++ b/ui/src/client.ts @@ -1,5 +1,6 @@ export { AvoHeroWrapper } from '~content-blocks/BlockAvoHero/AvoHeroWrapper'; export { BlockAvoImageTextBackground } from '~content-blocks/BlockAvoImageTextBackground'; +export { BlockAvoQuote } from '~content-blocks/BlockAvoQuote'; export { BlockBreadcrumbs } from '~content-blocks/BlockBreadcrumbs'; export { BlockButtonsWrapper } from '~content-blocks/BlockButtons/BlockButtons.wrapper'; export { BlockCardsWithoutDescription } from '~content-blocks/BlockCardsWithoutDescription'; @@ -9,7 +10,7 @@ export { BlockEventbrite } from '~content-blocks/BlockEventbrite'; export { BlockHeading } from '~content-blocks/BlockHeading/BlockHeading'; export { BlockHetArchiefHeaderSearch } from '~content-blocks/BlockHetArchiefHeaderSearch'; export { BlockHetArchiefImageTextBackground } from '~content-blocks/BlockHetArchiefImageTextBackground'; -export { BlockHetarchiefQuote } from '~content-blocks/BlockHetarchiefQuote'; +export { BlockHetArchiefQuote } from '~content-blocks/BlockHetArchiefQuote'; export { BlockIFrame } from '~content-blocks/BlockIFrame'; export { BlockImage } from '~content-blocks/BlockImage'; export { BlockImageGridWrapper } from '~content-blocks/BlockImageGrid/BlockImageGrid.wrapper'; @@ -22,7 +23,6 @@ export { BlockMaintainersGrid } from '~content-blocks/BlockMaintainersGrid'; export { BlockOverviewNewspaperTitles } from '~content-blocks/BlockOverviewNewspaperTitles'; export { BlockOverviewWithCarousel } from '~content-blocks/BlockOverviewWithCarousel'; export { BlockPageOverviewWrapper } from '~content-blocks/BlockPageOverview/BlockPageOverview.wrapper'; -export { BlockAvoQuote } from '~content-blocks/BlockAvoQuote'; export { BlockRichText } from '~content-blocks/BlockRichText'; export { BlockRichTextWrapper } from '~content-blocks/BlockRichText/BlockRichText.wrapper'; export { BlockScrollDownNudge } from '~content-blocks/BlockScrollDownNudge'; 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 7191ac9bf..b34202b16 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 @@ -1,6 +1,7 @@ import type { FC, FunctionComponent } from 'react'; import { AvoHeroWrapper } from '~content-blocks/BlockAvoHero/AvoHeroWrapper'; import { BlockAvoImageTextBackground } from '~content-blocks/BlockAvoImageTextBackground'; +import { BlockAvoQuote } from '~content-blocks/BlockAvoQuote'; import { BlockBreadcrumbs } from '~content-blocks/BlockBreadcrumbs'; import { BlockButtonsWrapper } from '~content-blocks/BlockButtons'; import { BlockCardsWithoutDescription } from '~content-blocks/BlockCardsWithoutDescription'; @@ -10,7 +11,7 @@ import { BlockEventbrite } from '~content-blocks/BlockEventbrite'; import { BlockHeading } from '~content-blocks/BlockHeading'; import { BlockHetArchiefHeaderSearch } from '~content-blocks/BlockHetArchiefHeaderSearch/BlockHetArchiefHeaderSearch'; import { BlockHetArchiefImageTextBackground } from '~content-blocks/BlockHetArchiefImageTextBackground'; -import { BlockHetarchiefQuote } from '~content-blocks/BlockHetarchiefQuote'; +import { BlockHetArchiefQuote } from '~content-blocks/BlockHetArchiefQuote'; import { BlockIFrame } from '~content-blocks/BlockIFrame'; import { BlockImage } from '~content-blocks/BlockImage'; import { @@ -25,7 +26,6 @@ import { BlockMaintainersGrid } from '~content-blocks/BlockMaintainersGrid'; import { BlockOverviewNewspaperTitles } from '~content-blocks/BlockOverviewNewspaperTitles'; import { BlockOverviewWithCarousel } from '~content-blocks/BlockOverviewWithCarousel/BlockOverviewWithCarousel.tsx'; import { BlockPageOverviewWrapper } from '~content-blocks/BlockPageOverview'; -import { BlockAvoQuote } from '~content-blocks/BlockAvoQuote'; import { BlockRichTextWrapper } from '~content-blocks/BlockRichText'; import { BlockScrollDownNudge } from '~content-blocks/BlockScrollDownNudge'; import { BlockProjectSpotlightWrapper, BlockSpotlight } from '~content-blocks/BlockSpotlight'; @@ -88,7 +88,7 @@ export function GET_BLOCK_COMPONENT( [ContentBlockType.Breadcrumbs]: BlockBreadcrumbs, [ContentBlockType.HetArchiefImageTextBackground]: BlockHetArchiefImageTextBackground, [ContentBlockType.OverviewWithCarousel]: BlockOverviewWithCarousel, - [ContentBlockType.HetarchiefQuote]: BlockHetarchiefQuote, + [ContentBlockType.HetArchiefQuote]: BlockHetArchiefQuote, // Avo specific blocks [ContentBlockType.MediaGrid]: loadComponentFromConfig(ContentBlockType.MediaGrid), diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.editorconfig.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts similarity index 77% rename from ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.editorconfig.ts rename to ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts index 3f945d162..765254c4f 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.editorconfig.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts @@ -2,7 +2,7 @@ import { tText } from '~shared/helpers/translation-functions'; import type { ContentBlockConfig, DefaultContentBlockState, - HetarchiefQuoteBlockComponentState, + HetArchiefQuoteBlockComponentState, } from '../../../types/content-block.types'; import { Color, ContentBlockEditor, ContentBlockType } from '../../../types/content-block.types'; @@ -13,15 +13,15 @@ import { TEXT_FIELD, } from '../defaults'; -export const INITIAL_HETARCHIEF_QUOTE_COMPONENTS_STATE = - (): HetarchiefQuoteBlockComponentState => ({ +export const INITIAL_HET_ARCHIEF_QUOTE_COMPONENTS_STATE = + (): HetArchiefQuoteBlockComponentState => ({ quote: '', authorName: '', textColor: Color.White, frameColor: Color.Black, }); -export const INITIAL_HETARCHIEF_QUOTE_BLOCK_STATE = (): DefaultContentBlockState => +export const INITIAL_HET_ARCHIEF_QUOTE_BLOCK_STATE = (): DefaultContentBlockState => BLOCK_STATE_DEFAULTS({ padding: { top: 'top-small', @@ -29,12 +29,12 @@ export const INITIAL_HETARCHIEF_QUOTE_BLOCK_STATE = (): DefaultContentBlockState }, }); -export const HETARCHIEF_QUOTE_BLOCK_CONFIG = (position = 0): ContentBlockConfig => ({ +export const HET_ARCHIEF_QUOTE_BLOCK_CONFIG = (position = 0): ContentBlockConfig => ({ position, name: tText('admin/content-block/helpers/generators/hetarchief-quote___quote-kader'), - type: ContentBlockType.HetarchiefQuote, + type: ContentBlockType.HetArchiefQuote, components: { - state: INITIAL_HETARCHIEF_QUOTE_COMPONENTS_STATE(), + state: INITIAL_HET_ARCHIEF_QUOTE_COMPONENTS_STATE(), fields: { quote: TEXT_FIELD( { @@ -64,7 +64,7 @@ export const HETARCHIEF_QUOTE_BLOCK_CONFIG = (position = 0): ContentBlockConfig }, }, block: { - state: INITIAL_HETARCHIEF_QUOTE_BLOCK_STATE(), + state: INITIAL_HET_ARCHIEF_QUOTE_BLOCK_STATE(), fields: BLOCK_FIELD_DEFAULTS(), }, }); diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.scss b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.scss similarity index 71% rename from ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.scss rename to ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.scss index 17bd33481..7c376116d 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.scss +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.scss @@ -1,4 +1,6 @@ -.c-block-hetarchief-quote { +@use "../../../../shared/styles/settings/variables" as variables; + +.c-block-het-archief-quote { display: grid; grid-template-columns: 10.4rem 1fr; grid-template-areas: @@ -6,18 +8,25 @@ '. author'; align-content: center; margin: 0; + // 19.2rem is the space Figma leaves between the text column (ends at x=816) and the frame // edge (1008px), which keeps the text clear of the semicircular curve. padding: 4rem 19.2rem 4rem 0; background: var(--frame-color); color: var(--text-color); + // Square left, true semicircular right end at any height, per Figma (r = height / 2). border-radius: 0 9999px 9999px 0; &__mark { grid-area: mark; - // Figma node 455:5723: icon font "meemoocons-light", size 64/line-height 72. - font-family: 'meemoocons-light'; + + // Figma node 455:5723: icon font "meemoocons-light", size 64/line-height 72. The span + // content is the ligature name "quotes" — meemoocons-light is a ligature icon font, it + // has no glyph for the quote-mark character itself. + font-family: meemoocons-light, sans-serif; + font-feature-settings: 'liga'; + font-variant-ligatures: discretionary-ligatures; font-size: 6.4rem; font-weight: normal; line-height: 7.2rem; @@ -27,8 +36,10 @@ &__quote { grid-area: quote; margin: 0; + white-space: pre-line; + // Figma node 455:5724, style "P - XL": Sofia Pro Medium, 32/40, letter-spacing 0. - font-family: 'SofiaPro'; + font-family: SofiaPro, sans-serif; font-size: 3.2rem; font-weight: 500; line-height: 4rem; @@ -38,15 +49,16 @@ &__author { grid-area: author; margin-top: 0.8rem; + // Figma node 455:5725, style "P - S": Sofia Pro Medium, 14/20, letter-spacing 0. - font-family: 'SofiaPro'; + font-family: SofiaPro, sans-serif; font-size: 1.4rem; font-weight: 500; line-height: 2rem; letter-spacing: normal; } - @media (max-width: 768px) { + @media (width <= #{variables.$g-bp2}) { grid-template-columns: 1fr; grid-template-areas: 'mark' diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.test.tsx b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.test.tsx similarity index 60% rename from ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.test.tsx rename to ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.test.tsx index 71a7ee7ba..6db729b98 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.test.tsx +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.test.tsx @@ -3,16 +3,16 @@ import React from 'react'; import { afterEach, describe, expect, it } from 'vitest'; import { Color } from '../../../types/content-block.types'; -import { BlockHetarchiefQuote } from './BlockHetarchiefQuote'; +import { BlockHetArchiefQuote } from './BlockHetArchiefQuote'; afterEach(() => { cleanup(); }); -describe('', () => { +describe('', () => { it('renders the quote and the author', () => { render( - ', () => { it('exposes the chosen colours as custom properties', () => { const { container } = render( - ', () => { /> ); - const figure = container.querySelector('.c-block-hetarchief-quote') as HTMLElement; + const figure = container.querySelector('.c-block-het-archief-quote') as HTMLElement; expect(figure.style.getPropertyValue('--text-color')).toEqual(Color.White); expect(figure.style.getPropertyValue('--frame-color')).toEqual(Color.OceanGreen); @@ -42,9 +42,20 @@ describe('', () => { it('omits the caption when there is no author', () => { const { container } = render( - + ); expect(container.querySelector('figcaption')).toBeNull(); }); + + it('renders the quote mark as the ligature icon name, hidden from assistive tech', () => { + const { container } = render( + + ); + + const mark = container.querySelector('.c-block-het-archief-quote__mark'); + + expect(mark?.textContent).toEqual('quotes'); + expect(mark?.getAttribute('aria-hidden')).toEqual('true'); + }); }); diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.tsx b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.tsx similarity index 54% rename from ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.tsx rename to ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.tsx index f7a94752e..e1c6c9d19 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote.tsx +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.tsx @@ -5,16 +5,16 @@ import React from 'react'; import type { Color, CustomBackground, GradientColor } from '../../../types/content-block.types'; -import './BlockHetarchiefQuote.scss'; +import './BlockHetArchiefQuote.scss'; -export interface BlockHetarchiefQuoteProps extends DefaultProps { +export interface BlockHetArchiefQuoteProps extends DefaultProps { quote: string; authorName?: string; - textColor: Color; + textColor: Color | GradientColor | CustomBackground; frameColor: Color | GradientColor | CustomBackground; } -export const BlockHetarchiefQuote: FunctionComponent = ({ +export const BlockHetArchiefQuote: FunctionComponent = ({ className, quote, authorName, @@ -22,7 +22,7 @@ export const BlockHetarchiefQuote: FunctionComponent frameColor, }) => (
} as CSSProperties } > -
); diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/index.ts new file mode 100644 index 000000000..27ff5a9f4 --- /dev/null +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/index.ts @@ -0,0 +1,2 @@ +export * from './BlockHetArchiefQuote'; +export * from './BlockHetArchiefQuote.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/index.ts deleted file mode 100644 index 5b2eec1ae..000000000 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetarchiefQuote/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './BlockHetarchiefQuote'; -export * from './BlockHetarchiefQuote.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 cca00c886..115f49e47 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 @@ -1,6 +1,7 @@ import { ANCHOR_LINKS_BLOCK_CONFIG } from '~content-blocks/anchor-links.ts'; import { AVO_HERO_BLOCK_CONFIG } from '~content-blocks/BlockAvoHero'; import { AVO_IMAGE_TEXT_BACKGROUND_BLOCK_CONFIG } from '~content-blocks/BlockAvoImageTextBackground'; +import { AVO_QUOTE_BLOCK_CONFIG } from '~content-blocks/BlockAvoQuote'; import { CONTENT_BREADCRUMBS_CONFIG } from '~content-blocks/BlockBreadcrumbs'; import { BUTTONS_BLOCK_CONFIG } from '~content-blocks/BlockButtons'; import { CARDS_WITHOUT_DESCRIPTION_BLOCK_CONFIG } from '~content-blocks/BlockCardsWithoutDescription'; @@ -11,7 +12,7 @@ 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'; import { HET_ARCHIEF_IMAGE_TEXT_BACKGROUND_BLOCK_CONFIG } from '~content-blocks/BlockHetArchiefImageTextBackground'; -import { HETARCHIEF_QUOTE_BLOCK_CONFIG } from '~content-blocks/BlockHetarchiefQuote'; +import { HET_ARCHIEF_QUOTE_BLOCK_CONFIG } from '~content-blocks/BlockHetArchiefQuote'; import { IFRAME_BLOCK_CONFIG } from '~content-blocks/BlockIFrame'; import { IMAGE_BLOCK_CONFIG } from '~content-blocks/BlockImage'; import { @@ -26,7 +27,6 @@ import { MAINTAINERS_GRID_BLOCK_CONFIG } from '~content-blocks/BlockMaintainersG import { MEDIA_GRID_BLOCK_CONFIG } from '~content-blocks/BlockMediaGrid'; import { OVERVIEW_NEWSPAPER_TITLES_BLOCK_CONFIG } from '~content-blocks/BlockOverviewNewspaperTitles'; import { CONTENT_OVERVIEW_WITH_CAROUSEL_CONFIG } from '~content-blocks/BlockOverviewWithCarousel'; -import { AVO_QUOTE_BLOCK_CONFIG } from '~content-blocks/BlockAvoQuote'; import { RICH_TEXT_BLOCK_CONFIG, RICH_TEXT_TWO_COLUMNS_BLOCK_CONFIG, @@ -64,7 +64,7 @@ export const CONTENT_BLOCK_CONFIG_MAP: Record< [ContentBlockType.MediaPlayer]: MEDIA_PLAYER_BLOCK_CONFIG, [ContentBlockType.MediaPlayerTitleTextButton]: MEDIA_PLAYER_TITLE_TEXT_BUTTON_BLOCK_CONFIG, [ContentBlockType.AvoQuote]: AVO_QUOTE_BLOCK_CONFIG, - [ContentBlockType.HetarchiefQuote]: HETARCHIEF_QUOTE_BLOCK_CONFIG, + [ContentBlockType.HetArchiefQuote]: HET_ARCHIEF_QUOTE_BLOCK_CONFIG, [ContentBlockType.PageOverview]: PAGE_OVERVIEW_BLOCK_CONFIG, [ContentBlockType.ProjectsSpotlight]: PROJECTS_SPOTLIGHT_BLOCK_CONFIG, [ContentBlockType.Spotlight]: SPOTLIGHT_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 0f0876806..fe9173feb 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 @@ -1,6 +1,7 @@ import { INITIAL_ANCHOR_LINKS_COMPONENTS_STATE } from '~content-blocks/anchor-links'; import { INITIAL_AVO_HERO_COMPONENTS_STATE } from '~content-blocks/BlockAvoHero'; import { INITIAL_AVO_IMAGE_TEXT_BACKGROUND_BLOCK_STATE } from '~content-blocks/BlockAvoImageTextBackground'; +import { INITIAL_AVO_QUOTE_COMPONENTS_STATE } from '~content-blocks/BlockAvoQuote'; import { INITIAL_BREADCRUMBS_BLOCK_STATE } from '~content-blocks/BlockBreadcrumbs/BlockBreadcrumbs.editorconfig'; import { INITIAL_BUTTONS_COMPONENTS_STATE } from '~content-blocks/BlockButtons'; import { INITIAL_CARDS_WITHOUT_DESCRIPTION_COMPONENTS_STATE } from '~content-blocks/BlockCardsWithoutDescription'; @@ -11,7 +12,7 @@ import { INITIAL_EVENTBRITE_COMPONENTS_STATE } from '~content-blocks/BlockEventb import { INITIAL_HEADING_COMPONENTS_STATE } from '~content-blocks/BlockHeading'; import { INITIAL_HET_ARCHIEF_HEADER_SEARCH_BLOCK_STATE } from '~content-blocks/BlockHetArchiefHeaderSearch/BlockHetArchiefHeaderSearch.editorconfig'; import { INITIAL_HET_ARCHIEF_IMAGE_TEXT_BACKGROUND_BLOCK_STATE } from '~content-blocks/BlockHetArchiefImageTextBackground'; -import { INITIAL_HETARCHIEF_QUOTE_COMPONENTS_STATE } from '~content-blocks/BlockHetarchiefQuote'; +import { INITIAL_HET_ARCHIEF_QUOTE_COMPONENTS_STATE } from '~content-blocks/BlockHetArchiefQuote'; import { INITIAL_IFRAME_COMPONENTS_STATE } from '~content-blocks/BlockIFrame'; import { INITIAL_IMAGE_COMPONENTS_STATE } from '~content-blocks/BlockImage'; import { @@ -27,7 +28,6 @@ import { INITIAL_MEDIA_GRID_COMPONENTS_STATE } from '~content-blocks/BlockMediaG import { INITIAL_OVERVIEW_NEWSPAPER_TITLES_BLOCK_STATE } from '~content-blocks/BlockOverviewNewspaperTitles'; import { INITIAL_CONTENT_OVERVIEW_WITH_CAROUSEL_BLOCK_STATE } from '~content-blocks/BlockOverviewWithCarousel/BlockOverviewWithCarousel.editorconfig.ts'; import { INITIAL_PAGE_OVERVIEW_COMPONENTS_STATE } from '~content-blocks/BlockPageOverview'; -import { INITIAL_AVO_QUOTE_COMPONENTS_STATE } from '~content-blocks/BlockAvoQuote'; import { INITIAL_RICH_TEXT_COMPONENTS_STATE, INITIAL_RICH_TEXT_TWO_COLUMNS_COMPONENTS_STATE, @@ -69,7 +69,7 @@ export const CONTENT_BLOCK_INITIAL_STATE_MAP: { [ContentBlockType.ProjectsSpotlight]: INITIAL_PROJECTS_SPOTLIGHT_COMPONENTS_STATE, [ContentBlockType.Spotlight]: INITIAL_SPOTLIGHT_COMPONENTS_STATE, [ContentBlockType.AvoQuote]: INITIAL_AVO_QUOTE_COMPONENTS_STATE, - [ContentBlockType.HetarchiefQuote]: INITIAL_HETARCHIEF_QUOTE_COMPONENTS_STATE, + [ContentBlockType.HetArchiefQuote]: INITIAL_HET_ARCHIEF_QUOTE_COMPONENTS_STATE, [ContentBlockType.RichText]: INITIAL_RICH_TEXT_COMPONENTS_STATE, [ContentBlockType.RichTextTwoColumns]: INITIAL_RICH_TEXT_TWO_COLUMNS_COMPONENTS_STATE, [ContentBlockType.Search]: INITIAL_SEARCH_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 daa7ecc08..55a262a69 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 @@ -185,12 +185,10 @@ export const GET_CONTENT_BLOCK_TYPE_OPTIONS: () => SelectOption[] = () = value: ContentBlockType.OverviewWithCarousel, }, { - label: tText( - 'modules/content-page/const/get-content-block-type-options___quote-kader', - {}, - [HET_ARCHIEF] - ), - value: ContentBlockType.HetarchiefQuote, + label: tText('modules/content-page/const/get-content-block-type-options___quote-kader', {}, [ + HET_ARCHIEF, + ]), + value: ContentBlockType.HetArchiefQuote, }, ]; 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 9345d20e3..8cfd74546 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 @@ -181,7 +181,7 @@ export enum ContentBlockType { HetArchiefImageTextBackground = 'IMAGE_TEXT_BACKGROUND', // Hetarchief MaintainersGrid = 'MAINTAINERS_GRID', HetArchiefHeaderSearch = 'HETARCHIEF__HEADER_SEARCH', - HetarchiefQuote = 'HETARCHIEF_QUOTE', // Hetarchief + HetArchiefQuote = 'HETARCHIEF_QUOTE', // Hetarchief OverviewNewspaperTitles = 'OVERVIEW_NEWSPAPER_TITLES', ContentEncloseGrid = 'CONTENT_ENCLOSE_GRID', Breadcrumbs = 'BREADCRUMBS', @@ -458,7 +458,7 @@ export type SingleContentBlockComponentState = | MediaPlayerTitleTextButtonBlockComponentState | PageOverviewBlockComponentStateFields | AvoQuoteBlockComponentState - | HetarchiefQuoteBlockComponentState + | HetArchiefQuoteBlockComponentState | RichTextBlockComponentState // biome-ignore lint/complexity/noBannedTypes: todo | {}; // Search block & content page meta @@ -593,10 +593,10 @@ export interface HetArchiefHeaderSearchBlockComponentState { textBelowSearch?: string; } -export interface HetarchiefQuoteBlockComponentState { +export interface HetArchiefQuoteBlockComponentState { quote: string; authorName: string; - textColor: Color; + textColor: Color | GradientColor | CustomBackground; frameColor: Color | GradientColor | CustomBackground; } diff --git a/ui/src/react-admin/modules/index.ts b/ui/src/react-admin/modules/index.ts index 553b0f193..0440c6394 100644 --- a/ui/src/react-admin/modules/index.ts +++ b/ui/src/react-admin/modules/index.ts @@ -98,6 +98,7 @@ export * from './content-page/components/blocks/anchor-links'; export * from './content-page/components/blocks/BlockAccordions/BlockAccordions'; export * from './content-page/components/blocks/BlockAvoHero/BlockAvoHero'; export * from './content-page/components/blocks/BlockAvoImageTextBackground/BlockAvoImageTextBackground'; +export * from './content-page/components/blocks/BlockAvoQuote/BlockAvoQuote'; export * from './content-page/components/blocks/BlockBreadcrumbs/BlockBreadcrumbs'; export * from './content-page/components/blocks/BlockButtons/BlockButtons'; export * from './content-page/components/blocks/BlockCardsWithoutDescription/BlockCardsWithoutDescription'; @@ -108,7 +109,7 @@ export * from './content-page/components/blocks/BlockEventbrite/BlockEventbrite' export * from './content-page/components/blocks/BlockHeading/BlockHeading'; export * from './content-page/components/blocks/BlockHetArchiefHeaderSearch/BlockHetArchiefHeaderSearch'; export * from './content-page/components/blocks/BlockHetArchiefImageTextBackground/BlockHetArchiefImageTextBackground'; -export * from './content-page/components/blocks/BlockHetarchiefQuote/BlockHetarchiefQuote'; +export * from './content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote'; export * from './content-page/components/blocks/BlockIFrame/BlockIFrame'; export * from './content-page/components/blocks/BlockImage/BlockImage'; export * from './content-page/components/blocks/BlockImageGrid/BlockImageGrid'; @@ -119,7 +120,6 @@ export * from './content-page/components/blocks/BlockMaintainersGrid/BlockMainta export * from './content-page/components/blocks/BlockMediaGrid/BlockMediaGrid.editorconfig'; export * from './content-page/components/blocks/BlockOverviewNewspaperTitles/BlockOverviewNewspaperTitles'; export * from './content-page/components/blocks/BlockPageOverview/BlockPageOverview'; -export * from './content-page/components/blocks/BlockAvoQuote/BlockAvoQuote'; export * from './content-page/components/blocks/BlockRichText/BlockRichText'; export * from './content-page/components/blocks/BlockSpotlight/BlockSpotlight'; export * from './content-page/components/blocks/BlockTagsWithLink/BlockTagsWithLink'; diff --git a/ui/src/shared/helpers/admin-core-config.tsx b/ui/src/shared/helpers/admin-core-config.tsx index 831f91639..29a161239 100644 --- a/ui/src/shared/helpers/admin-core-config.tsx +++ b/ui/src/shared/helpers/admin-core-config.tsx @@ -97,7 +97,7 @@ export function getAdminCoreConfigForLocalTestApp(navigateFunc: NavigateFunction // ContentBlockType.ContentEncloseGrid, // ContentBlockType.Breadcrumbs, ContentBlockType.OverviewWithCarousel, - ContentBlockType.HetarchiefQuote, + ContentBlockType.HetArchiefQuote, ], defaultPageWidth: ContentPageWidth.LARGE, onSaveContentPage: async (contentPageInfo: ContentPageInfo) => { From f2c7d304bd02fa3b51097d899b21f216b80fdb22 Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Thu, 6 Aug 2026 09:58:58 +0200 Subject: [PATCH 06/17] fix(ARC-3816): match the figma desktop and mobile specs for the quote block --- .../BlockHetArchiefQuote.scss | 50 +++++++++++++++---- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.scss b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.scss index 7c376116d..8f262fec3 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.scss +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.scss @@ -6,24 +6,34 @@ grid-template-areas: 'mark quote' '. author'; - align-content: center; margin: 0; // 19.2rem is the space Figma leaves between the text column (ends at x=816) and the frame - // edge (1008px), which keeps the text clear of the semicircular curve. + // edge (1008px), which keeps the text clear of the curve. padding: 4rem 19.2rem 4rem 0; background: var(--frame-color); color: var(--text-color); - // Square left, true semicircular right end at any height, per Figma (r = height / 2). - border-radius: 0 9999px 9999px 0; + // Figma emits the deprecated `word-break: break-word`; this is its modern equivalent. + overflow-wrap: break-word; + + // Figma node 455:5722: rounded-tr-[400px] rounded-br-[400px], square on the left. At the + // design's 228px height CSS scales both radii down to height/2, so this looks like a pill; + // past ~800px of height it stops growing, which is the point — an unbounded 9999px radius + // would keep eating into the text on a long quote. + border-radius: 0 40rem 40rem 0; &__mark { grid-area: mark; - // Figma node 455:5723: icon font "meemoocons-light", size 64/line-height 72. The span - // content is the ligature name "quotes" — meemoocons-light is a ligature icon font, it - // has no glyph for the quote-mark character itself. + // Figma node 455:5723 sits at top 28 while the quote sits at top 40, so the mark is + // raised 12px out of the shared grid row, and centred in its 104px column. + margin-top: -1.2rem; + text-align: center; + + // Icon font "meemoocons-light", size 64/line-height 72. The span content is the + // ligature name "quotes" — meemoocons-light is a ligature icon font and has no glyph + // for the quote-mark character itself. font-family: meemoocons-light, sans-serif; font-feature-settings: 'liga'; font-variant-ligatures: discretionary-ligatures; @@ -31,6 +41,13 @@ font-weight: normal; line-height: 7.2rem; letter-spacing: normal; + + @media (width <= #{variables.$g-bp2}) { + // Figma node 455:7187: in the stacked layout the mark is in normal flow and + // left-aligned with the text below it. + margin-top: 0; + text-align: left; + } } &__quote { @@ -44,6 +61,13 @@ font-weight: 500; line-height: 4rem; letter-spacing: normal; + + @media (width <= #{variables.$g-bp2}) { + // Figma node 455:7186: 8px flex gap below the mark, plus the 8px padding on the + // text group that holds the quote and the author. + margin-top: 1.6rem; + margin-left: 0.8rem; + } } &__author { @@ -56,6 +80,11 @@ font-weight: 500; line-height: 2rem; letter-spacing: normal; + + @media (width <= #{variables.$g-bp2}) { + margin-bottom: 0.8rem; + margin-left: 0.8rem; + } } @media (width <= #{variables.$g-bp2}) { @@ -64,7 +93,10 @@ 'mark' 'quote' 'author'; - padding: 2.4rem 2.4rem 2.4rem 1.6rem; - border-radius: 0 2.4rem 2.4rem 0; + + // Figma node 455:7186: 24/20 padding and a single 120px top-right radius — the + // desktop's two-corner pill does not carry over to mobile. + padding: 2.4rem 2rem; + border-radius: 0 12rem 0 0; } } From 1064d88acb1b5bf2c5d8f67b5c90beb2a9a8dcf2 Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Thu, 6 Aug 2026 11:48:10 +0200 Subject: [PATCH 07/17] fix(ARC-3816): limit the quote colour fields to plain css colours The background colour list contains three entries that are not a CSS colour: "Geen" (TRANSPARENT) rendered the text invisible, the meemoo logo sentinel and the black/white gradient were invalid in `color` and silently dropped the frame background. --- .../BlockHetArchiefQuote.editorconfig.ts | 6 ++-- .../BlockHetArchiefQuote.tsx | 6 ++-- .../components/blocks/defaults.test.ts | 26 +++++++++++++++-- .../components/blocks/defaults.ts | 22 +++++++++++++++ .../content-page/const/get-color-options.ts | 28 +++++++++++++++++++ .../content-page/types/content-block.types.ts | 6 ++-- 6 files changed, 84 insertions(+), 10 deletions(-) diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts index 765254c4f..72591672b 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts @@ -7,9 +7,9 @@ import type { import { Color, ContentBlockEditor, ContentBlockType } from '../../../types/content-block.types'; import { - BACKGROUND_COLOR_FIELD, BLOCK_FIELD_DEFAULTS, BLOCK_STATE_DEFAULTS, + SOLID_COLOR_FIELD, TEXT_FIELD, } from '../defaults'; @@ -47,14 +47,14 @@ export const HET_ARCHIEF_QUOTE_BLOCK_CONFIG = (position = 0): ContentBlockConfig label: tText('admin/content-block/helpers/generators/quote___auteur'), validator: undefined, }), - textColor: BACKGROUND_COLOR_FIELD( + textColor: SOLID_COLOR_FIELD( tText('admin/content-block/helpers/generators/hetarchief-quote___tekstkleur'), { label: tText('admin/content-block/content-block___wit'), value: Color.White, } ), - frameColor: BACKGROUND_COLOR_FIELD( + frameColor: SOLID_COLOR_FIELD( tText('admin/content-block/helpers/generators/hetarchief-quote___kleur-kader'), { label: tText('modules/content-page/const/content-block___zwart'), diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.tsx b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.tsx index e1c6c9d19..d98e79f0d 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.tsx +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.tsx @@ -3,15 +3,15 @@ import clsx from 'clsx'; import type { CSSProperties, FunctionComponent } from 'react'; import React from 'react'; -import type { Color, CustomBackground, GradientColor } from '../../../types/content-block.types'; +import type { Color } from '../../../types/content-block.types'; import './BlockHetArchiefQuote.scss'; export interface BlockHetArchiefQuoteProps extends DefaultProps { quote: string; authorName?: string; - textColor: Color | GradientColor | CustomBackground; - frameColor: Color | GradientColor | CustomBackground; + textColor: Color; + frameColor: Color; } export const BlockHetArchiefQuote: FunctionComponent = ({ diff --git a/ui/src/react-admin/modules/content-page/components/blocks/defaults.test.ts b/ui/src/react-admin/modules/content-page/components/blocks/defaults.test.ts index 11336ef29..f68a19eba 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/defaults.test.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/defaults.test.ts @@ -6,8 +6,30 @@ vi.mock('~shared/helpers/translation-functions', () => ({ tHtml: (key: string) => key, })); -import { Color } from '../../types/content-block.types'; -import { BACKGROUND_COLOR_FIELD, FOREGROUND_COLOR_FIELD } from './defaults'; +import { Color, CustomBackground, GradientColor } from '../../types/content-block.types'; +import { BACKGROUND_COLOR_FIELD, FOREGROUND_COLOR_FIELD, SOLID_COLOR_FIELD } from './defaults'; + +describe('SOLID_COLOR_FIELD', () => { + it('drops the options that are not a plain CSS colour', () => { + const values = SOLID_COLOR_FIELD('Kleur kader').editorProps.options.map( + (option: { value: string }) => option.value + ); + + expect(values).not.toContain(Color.Transparent); + expect(values).not.toContain(CustomBackground.MeemooLogo); + expect(values).not.toContain(GradientColor.BlackWhite); + }); + + it('keeps the plain colours, including the tertiary ones', () => { + const values = SOLID_COLOR_FIELD('Tekstkleur').editorProps.options.map( + (option: { value: string }) => option.value + ); + + expect(values).toContain(Color.White); + expect(values).toContain(Color.Black); + expect(values).toContain(Color.Mustard); + }); +}); describe('colour field helpers', () => { it('BACKGROUND_COLOR_FIELD honours an explicit defaultValue', () => { diff --git a/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts b/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts index 3949ac640..593ce91e1 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts @@ -6,6 +6,8 @@ import { GET_COLOR_OPTIONS_EXTENDED_AVO, GET_FOREGROUND_COLOR_OPTIONS_ARCHIEF, GET_FOREGROUND_COLOR_OPTIONS_AVO, + GET_SOLID_COLOR_OPTIONS_ARCHIEF, + GET_SOLID_COLOR_OPTIONS_AVO, } from '~modules/content-page/const/get-color-options'; import type { FileUploadProps } from '~shared/components/FileUpload/FileUpload'; @@ -100,6 +102,26 @@ export const BACKGROUND_COLOR_FIELD = ( }, }); +/** + * Same colours as BACKGROUND_COLOR_FIELD, minus the entries that are not a plain CSS colour. + * Use this wherever the picked value ends up in `color` or in a `background` that has to stay a + * flat fill, since "Geen", "meemoo logo" and the black/white gradient silently render as nothing + * there. See NON_SOLID_COLOR_VALUES in get-color-options.ts. + */ +export const SOLID_COLOR_FIELD = ( + label: string, + defaultValue?: SelectOption +): ContentBlockField => ({ + label, + editorType: ContentBlockEditor.ColorSelect, + editorProps: { + options: isAvo() ? GET_SOLID_COLOR_OPTIONS_AVO() : GET_SOLID_COLOR_OPTIONS_ARCHIEF(), + defaultValue: + defaultValue ?? + (isAvo() ? GET_SOLID_COLOR_OPTIONS_AVO()[0] : GET_SOLID_COLOR_OPTIONS_ARCHIEF()[0]), + }, +}); + export const BACKGROUND_COLOR_EXTENDED_FIELD = ( label: string, defaultValue?: SelectOption diff --git a/ui/src/react-admin/modules/content-page/const/get-color-options.ts b/ui/src/react-admin/modules/content-page/const/get-color-options.ts index d63483f47..6b8a6fa68 100644 --- a/ui/src/react-admin/modules/content-page/const/get-color-options.ts +++ b/ui/src/react-admin/modules/content-page/const/get-color-options.ts @@ -154,6 +154,34 @@ export const GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF: () => SelectOption< mustardOption(), ]; +/** + * The background colour lists contain three entries that are not a plain CSS colour and can + * therefore not be used everywhere a colour is picked: + * - Color.Transparent ("Geen") renders invisible text + * - CustomBackground.MeemooLogo is a sentinel that only ContentBlockRenderer knows how to expand + * - GradientColor.BlackWhite is only valid for `background`, never for `color` + * Blocks that need a real colour (text colour, a frame colour, …) filter them out with this list, + * so that newly added colours keep flowing through automatically. + */ +const NON_SOLID_COLOR_VALUES: (Color | GradientColor | CustomBackground)[] = [ + Color.Transparent, + CustomBackground.MeemooLogo, + GradientColor.BlackWhite, +]; + +const toSolidColorOptions = ( + options: SelectOption[] +): SelectOption[] => + options.filter( + (option) => !NON_SOLID_COLOR_VALUES.includes(option.value) + ) as SelectOption[]; + +export const GET_SOLID_COLOR_OPTIONS_AVO: () => SelectOption[] = () => + toSolidColorOptions(GET_BACKGROUND_COLOR_OPTIONS_AVO()); + +export const GET_SOLID_COLOR_OPTIONS_ARCHIEF: () => SelectOption[] = () => + toSolidColorOptions(GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF()); + export const GET_AVO_HERO_BACKGROUND_COLOR_OPTIONS: () => SelectOption[] = () => [ softBlueOption(), nightBlueOption(), 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 8cfd74546..7e4c1caf6 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 @@ -596,8 +596,10 @@ export interface HetArchiefHeaderSearchBlockComponentState { export interface HetArchiefQuoteBlockComponentState { quote: string; authorName: string; - textColor: Color | GradientColor | CustomBackground; - frameColor: Color | GradientColor | CustomBackground; + // Plain colours only: these end up in `color` and `background` as-is, so the gradient and + // the meemoo-logo sentinel from the background colour list would render as nothing. + textColor: Color; + frameColor: Color; } export interface HetArchiefIeObject { From b7fbb173c7d2e849d67d83e997230ff7649a24bf Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Thu, 6 Aug 2026 11:49:14 +0200 Subject: [PATCH 08/17] feat(ARC-3816): add the quote block translations The block writes its translation keys explicitly, so nl.json is the only place that can carry their Dutch text. Scope the keys to HET_ARCHIEF so they are not extracted into the avo translation set. --- .../BlockHetArchiefQuote.editorconfig.ts | 13 ++++++++++--- ui/src/shared/translations/hetArchief/nl.json | 4 ++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts index 72591672b..9229025c4 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts @@ -1,4 +1,5 @@ import { tText } from '~shared/helpers/translation-functions'; +import { HET_ARCHIEF } from '~shared/types'; import type { ContentBlockConfig, DefaultContentBlockState, @@ -31,7 +32,9 @@ export const INITIAL_HET_ARCHIEF_QUOTE_BLOCK_STATE = (): DefaultContentBlockStat export const HET_ARCHIEF_QUOTE_BLOCK_CONFIG = (position = 0): ContentBlockConfig => ({ position, - name: tText('admin/content-block/helpers/generators/hetarchief-quote___quote-kader'), + name: tText('admin/content-block/helpers/generators/hetarchief-quote___quote-kader', {}, [ + HET_ARCHIEF, + ]), type: ContentBlockType.HetArchiefQuote, components: { state: INITIAL_HET_ARCHIEF_QUOTE_COMPONENTS_STATE(), @@ -48,14 +51,18 @@ export const HET_ARCHIEF_QUOTE_BLOCK_CONFIG = (position = 0): ContentBlockConfig validator: undefined, }), textColor: SOLID_COLOR_FIELD( - tText('admin/content-block/helpers/generators/hetarchief-quote___tekstkleur'), + tText('admin/content-block/helpers/generators/hetarchief-quote___tekstkleur', {}, [ + HET_ARCHIEF, + ]), { label: tText('admin/content-block/content-block___wit'), value: Color.White, } ), frameColor: SOLID_COLOR_FIELD( - tText('admin/content-block/helpers/generators/hetarchief-quote___kleur-kader'), + tText('admin/content-block/helpers/generators/hetarchief-quote___kleur-kader', {}, [ + HET_ARCHIEF, + ]), { label: tText('modules/content-page/const/content-block___zwart'), value: Color.Black, diff --git a/ui/src/shared/translations/hetArchief/nl.json b/ui/src/shared/translations/hetArchief/nl.json index b72f70321..2d7ac3128 100644 --- a/ui/src/shared/translations/hetArchief/nl.json +++ b/ui/src/shared/translations/hetArchief/nl.json @@ -138,6 +138,9 @@ "admin/content-block/helpers/generators/heading___titel-kleur": "Titel kleur", "admin/content-block/helpers/generators/heading___type": "Type", "admin/content-block/helpers/generators/hero___alt-title-text": "Alt. titel tekst", + "admin/content-block/helpers/generators/hetarchief-quote___kleur-kader": "Kleur kader", + "admin/content-block/helpers/generators/hetarchief-quote___quote-kader": "Quote kader", + "admin/content-block/helpers/generators/hetarchief-quote___tekstkleur": "Tekstkleur", "admin/content-block/helpers/generators/iframe___i-frame": "iFrame", "admin/content-block/helpers/generators/iframe___titel": "Alt-tekst", "admin/content-block/helpers/generators/iframe___titel-is-verplicht": "Alt-tekst is verplicht voor SEO en slechtzienden.", @@ -734,6 +737,7 @@ "modules/content-page/const/get-content-block-type-options___breadcrumbs": "Breadcrumbs", "modules/content-page/const/get-content-block-type-options___content-enclose-grid": "Content insluiten grid", "modules/content-page/const/get-content-block-type-options___overzicht-krantentitels": "Overzicht krantentitels", + "modules/content-page/const/get-content-block-type-options___quote-kader": "Quote kader", "modules/content-page/const/get-content-block-type-options___scroll-down-nudge": "Nudge om te scrollen", "modules/content-page/const/get-heading-type-options___groot": "Groot", "modules/content-page/const/get-heading-type-options___klein": "Klein", From 5b78f4c5297dec864c0d51a616749165fcb6d7f8 Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Mon, 10 Aug 2026 21:36:43 +0200 Subject: [PATCH 09/17] refactor(content-blocks): use the shared colour lists for the quote block --- .../BlockHetArchiefQuote.editorconfig.ts | 31 ++++++++++--------- .../BlockHetArchiefQuote.tsx | 4 +-- .../components/blocks/defaults.test.ts | 26 ++-------------- .../components/blocks/defaults.ts | 24 +------------- .../content-page/const/get-color-options.ts | 28 ----------------- .../content-page/types/content-block.types.ts | 8 ++--- 6 files changed, 25 insertions(+), 96 deletions(-) diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts index 9229025c4..9fc8907b6 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts @@ -1,3 +1,7 @@ +import { + GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF, + GET_FOREGROUND_COLOR_OPTIONS_ARCHIEF, +} from '~modules/content-page/const/get-color-options'; import { tText } from '~shared/helpers/translation-functions'; import { HET_ARCHIEF } from '~shared/types'; import type { @@ -5,21 +9,26 @@ import type { DefaultContentBlockState, HetArchiefQuoteBlockComponentState, } from '../../../types/content-block.types'; -import { Color, ContentBlockEditor, ContentBlockType } from '../../../types/content-block.types'; +import { ContentBlockEditor, ContentBlockType } from '../../../types/content-block.types'; import { + BACKGROUND_COLOR_FIELD, BLOCK_FIELD_DEFAULTS, BLOCK_STATE_DEFAULTS, - SOLID_COLOR_FIELD, + FOREGROUND_COLOR_FIELD, TEXT_FIELD, } from '../defaults'; +// White in the foreground colour list, black in the background colour list +const DEFAULT_TEXT_COLOR_OPTION = () => GET_FOREGROUND_COLOR_OPTIONS_ARCHIEF()[1]; +const DEFAULT_FRAME_COLOR_OPTION = () => GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF()[5]; + export const INITIAL_HET_ARCHIEF_QUOTE_COMPONENTS_STATE = (): HetArchiefQuoteBlockComponentState => ({ quote: '', authorName: '', - textColor: Color.White, - frameColor: Color.Black, + textColor: DEFAULT_TEXT_COLOR_OPTION().value, + frameColor: DEFAULT_FRAME_COLOR_OPTION().value, }); export const INITIAL_HET_ARCHIEF_QUOTE_BLOCK_STATE = (): DefaultContentBlockState => @@ -50,23 +59,17 @@ export const HET_ARCHIEF_QUOTE_BLOCK_CONFIG = (position = 0): ContentBlockConfig label: tText('admin/content-block/helpers/generators/quote___auteur'), validator: undefined, }), - textColor: SOLID_COLOR_FIELD( + textColor: FOREGROUND_COLOR_FIELD( tText('admin/content-block/helpers/generators/hetarchief-quote___tekstkleur', {}, [ HET_ARCHIEF, ]), - { - label: tText('admin/content-block/content-block___wit'), - value: Color.White, - } + DEFAULT_TEXT_COLOR_OPTION() ), - frameColor: SOLID_COLOR_FIELD( + frameColor: BACKGROUND_COLOR_FIELD( tText('admin/content-block/helpers/generators/hetarchief-quote___kleur-kader', {}, [ HET_ARCHIEF, ]), - { - label: tText('modules/content-page/const/content-block___zwart'), - value: Color.Black, - } + DEFAULT_FRAME_COLOR_OPTION() ), }, }, diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.tsx b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.tsx index d98e79f0d..4680b6687 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.tsx +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.tsx @@ -3,7 +3,7 @@ import clsx from 'clsx'; import type { CSSProperties, FunctionComponent } from 'react'; import React from 'react'; -import type { Color } from '../../../types/content-block.types'; +import type { Color, CustomBackground, GradientColor } from '../../../types/content-block.types'; import './BlockHetArchiefQuote.scss'; @@ -11,7 +11,7 @@ export interface BlockHetArchiefQuoteProps extends DefaultProps { quote: string; authorName?: string; textColor: Color; - frameColor: Color; + frameColor: Color | GradientColor | CustomBackground; } export const BlockHetArchiefQuote: FunctionComponent = ({ diff --git a/ui/src/react-admin/modules/content-page/components/blocks/defaults.test.ts b/ui/src/react-admin/modules/content-page/components/blocks/defaults.test.ts index f68a19eba..11336ef29 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/defaults.test.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/defaults.test.ts @@ -6,30 +6,8 @@ vi.mock('~shared/helpers/translation-functions', () => ({ tHtml: (key: string) => key, })); -import { Color, CustomBackground, GradientColor } from '../../types/content-block.types'; -import { BACKGROUND_COLOR_FIELD, FOREGROUND_COLOR_FIELD, SOLID_COLOR_FIELD } from './defaults'; - -describe('SOLID_COLOR_FIELD', () => { - it('drops the options that are not a plain CSS colour', () => { - const values = SOLID_COLOR_FIELD('Kleur kader').editorProps.options.map( - (option: { value: string }) => option.value - ); - - expect(values).not.toContain(Color.Transparent); - expect(values).not.toContain(CustomBackground.MeemooLogo); - expect(values).not.toContain(GradientColor.BlackWhite); - }); - - it('keeps the plain colours, including the tertiary ones', () => { - const values = SOLID_COLOR_FIELD('Tekstkleur').editorProps.options.map( - (option: { value: string }) => option.value - ); - - expect(values).toContain(Color.White); - expect(values).toContain(Color.Black); - expect(values).toContain(Color.Mustard); - }); -}); +import { Color } from '../../types/content-block.types'; +import { BACKGROUND_COLOR_FIELD, FOREGROUND_COLOR_FIELD } from './defaults'; describe('colour field helpers', () => { it('BACKGROUND_COLOR_FIELD honours an explicit defaultValue', () => { diff --git a/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts b/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts index 593ce91e1..6eb441a51 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts @@ -6,8 +6,6 @@ import { GET_COLOR_OPTIONS_EXTENDED_AVO, GET_FOREGROUND_COLOR_OPTIONS_ARCHIEF, GET_FOREGROUND_COLOR_OPTIONS_AVO, - GET_SOLID_COLOR_OPTIONS_ARCHIEF, - GET_SOLID_COLOR_OPTIONS_AVO, } from '~modules/content-page/const/get-color-options'; import type { FileUploadProps } from '~shared/components/FileUpload/FileUpload'; @@ -90,7 +88,7 @@ export const FOREGROUND_COLOR_FIELD = ( export const BACKGROUND_COLOR_FIELD = ( label: string, - defaultValue?: SelectOption + defaultValue: SelectOption ): ContentBlockField => ({ label, editorType: ContentBlockEditor.ColorSelect, @@ -102,26 +100,6 @@ export const BACKGROUND_COLOR_FIELD = ( }, }); -/** - * Same colours as BACKGROUND_COLOR_FIELD, minus the entries that are not a plain CSS colour. - * Use this wherever the picked value ends up in `color` or in a `background` that has to stay a - * flat fill, since "Geen", "meemoo logo" and the black/white gradient silently render as nothing - * there. See NON_SOLID_COLOR_VALUES in get-color-options.ts. - */ -export const SOLID_COLOR_FIELD = ( - label: string, - defaultValue?: SelectOption -): ContentBlockField => ({ - label, - editorType: ContentBlockEditor.ColorSelect, - editorProps: { - options: isAvo() ? GET_SOLID_COLOR_OPTIONS_AVO() : GET_SOLID_COLOR_OPTIONS_ARCHIEF(), - defaultValue: - defaultValue ?? - (isAvo() ? GET_SOLID_COLOR_OPTIONS_AVO()[0] : GET_SOLID_COLOR_OPTIONS_ARCHIEF()[0]), - }, -}); - export const BACKGROUND_COLOR_EXTENDED_FIELD = ( label: string, defaultValue?: SelectOption diff --git a/ui/src/react-admin/modules/content-page/const/get-color-options.ts b/ui/src/react-admin/modules/content-page/const/get-color-options.ts index 6b8a6fa68..d63483f47 100644 --- a/ui/src/react-admin/modules/content-page/const/get-color-options.ts +++ b/ui/src/react-admin/modules/content-page/const/get-color-options.ts @@ -154,34 +154,6 @@ export const GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF: () => SelectOption< mustardOption(), ]; -/** - * The background colour lists contain three entries that are not a plain CSS colour and can - * therefore not be used everywhere a colour is picked: - * - Color.Transparent ("Geen") renders invisible text - * - CustomBackground.MeemooLogo is a sentinel that only ContentBlockRenderer knows how to expand - * - GradientColor.BlackWhite is only valid for `background`, never for `color` - * Blocks that need a real colour (text colour, a frame colour, …) filter them out with this list, - * so that newly added colours keep flowing through automatically. - */ -const NON_SOLID_COLOR_VALUES: (Color | GradientColor | CustomBackground)[] = [ - Color.Transparent, - CustomBackground.MeemooLogo, - GradientColor.BlackWhite, -]; - -const toSolidColorOptions = ( - options: SelectOption[] -): SelectOption[] => - options.filter( - (option) => !NON_SOLID_COLOR_VALUES.includes(option.value) - ) as SelectOption[]; - -export const GET_SOLID_COLOR_OPTIONS_AVO: () => SelectOption[] = () => - toSolidColorOptions(GET_BACKGROUND_COLOR_OPTIONS_AVO()); - -export const GET_SOLID_COLOR_OPTIONS_ARCHIEF: () => SelectOption[] = () => - toSolidColorOptions(GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF()); - export const GET_AVO_HERO_BACKGROUND_COLOR_OPTIONS: () => SelectOption[] = () => [ softBlueOption(), nightBlueOption(), 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 7d13beec7..0244e003c 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 @@ -168,7 +168,7 @@ export enum ContentBlockType { MediaPlayerTitleTextButton = 'MEDIA_PLAYER_TITLE_TEXT_BUTTON', PageOverview = 'PAGE_OVERVIEW', ProjectsSpotlight = 'PROJECTS_SPOTLIGHT', - AvoQuote = 'QUOTE', // Avo + AvoQuote = 'QUOTE', RichText = 'RICH_TEXT', RichTextTwoColumns = 'RICH_TEXT_TWO_COLUMNS', Search = 'SEARCH', @@ -181,7 +181,7 @@ export enum ContentBlockType { HetArchiefImageTextBackground = 'IMAGE_TEXT_BACKGROUND', // Hetarchief MaintainersGrid = 'MAINTAINERS_GRID', HetArchiefHeaderSearch = 'HETARCHIEF__HEADER_SEARCH', - HetArchiefQuote = 'HETARCHIEF_QUOTE', // Hetarchief + HetArchiefQuote = 'HETARCHIEF_QUOTE', OverviewNewspaperTitles = 'OVERVIEW_NEWSPAPER_TITLES', ContentEncloseGrid = 'CONTENT_ENCLOSE_GRID', Breadcrumbs = 'BREADCRUMBS', @@ -599,10 +599,8 @@ export interface HetArchiefHeaderSearchBlockComponentState { export interface HetArchiefQuoteBlockComponentState { quote: string; authorName: string; - // Plain colours only: these end up in `color` and `background` as-is, so the gradient and - // the meemoo-logo sentinel from the background colour list would render as nothing. textColor: Color; - frameColor: Color; + frameColor: Color | GradientColor | CustomBackground; } export interface HetArchiefIeObject { From 5b163e2238fc7d3f1f697e35dea1eddf7ce662b0 Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Mon, 10 Aug 2026 21:36:47 +0200 Subject: [PATCH 10/17] style(content-blocks): rewrite the quote block styling on the shared mixins --- .../BlockHetArchiefQuote.scss | 108 +++++++++--------- 1 file changed, 57 insertions(+), 51 deletions(-) diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.scss b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.scss index 8f262fec3..ece4553bc 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.scss +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.scss @@ -1,48 +1,56 @@ @use "../../../../shared/styles/settings/variables" as variables; +@use "../../../../shared/styles/mixins/typography" as typography; + +// Width of the column holding the quote mark (Figma node 455:5722). +$mark-column-width: variables.$g-spacer-unit * 13; + +// Space between the end of the text column and the frame edge, so the text stays clear of the +// rounded right side. 24 units is the gap Figma leaves at the design's 1008px frame width. +$text-inset-right: variables.$g-spacer-unit * 24; +$text-inset-right-tablet: variables.$g-spacer-unit * 8; + +// Figma node 455:5722: rounded-tr/br only, square on the left. At the design's 228px height CSS +// clamps both radii to height/2 so this reads as a pill; past ~800px of height it stops growing, +// which is the point - an unbounded 9999px radius would keep eating into a long quote. +$frame-radius: 40rem; +$frame-radius-mobile: 12rem; + +// meemoocons-light is a ligature icon font, provided by the host app (hetarchief-client), and has +// no glyph for the quote-mark character itself - hence the "quotes" ligature in the markup. +$mark-font-family: meemoocons-light, sans-serif; +$mark-font-size: variables.$g-spacer-unit * 8; +$mark-line-height: variables.$g-spacer-unit * 9; .c-block-het-archief-quote { display: grid; - grid-template-columns: 10.4rem 1fr; + grid-template-columns: $mark-column-width 1fr; grid-template-areas: 'mark quote' '. author'; margin: 0; - - // 19.2rem is the space Figma leaves between the text column (ends at x=816) and the frame - // edge (1008px), which keeps the text clear of the curve. - padding: 4rem 19.2rem 4rem 0; + padding: variables.$g-spacer-unit * 5 $text-inset-right variables.$g-spacer-unit * 5 0; background: var(--frame-color); color: var(--text-color); + border-radius: 0 $frame-radius $frame-radius 0; // Figma emits the deprecated `word-break: break-word`; this is its modern equivalent. overflow-wrap: break-word; - // Figma node 455:5722: rounded-tr-[400px] rounded-br-[400px], square on the left. At the - // design's 228px height CSS scales both radii down to height/2, so this looks like a pill; - // past ~800px of height it stops growing, which is the point — an unbounded 9999px radius - // would keep eating into the text on a long quote. - border-radius: 0 40rem 40rem 0; - &__mark { grid-area: mark; // Figma node 455:5723 sits at top 28 while the quote sits at top 40, so the mark is - // raised 12px out of the shared grid row, and centred in its 104px column. - margin-top: -1.2rem; + // raised out of the shared grid row and centred in its own column. + margin-top: -(variables.$g-spacer-unit * 1.5); text-align: center; - - // Icon font "meemoocons-light", size 64/line-height 72. The span content is the - // ligature name "quotes" — meemoocons-light is a ligature icon font and has no glyph - // for the quote-mark character itself. - font-family: meemoocons-light, sans-serif; + font-family: $mark-font-family; font-feature-settings: 'liga'; font-variant-ligatures: discretionary-ligatures; - font-size: 6.4rem; + font-size: $mark-font-size; font-weight: normal; - line-height: 7.2rem; - letter-spacing: normal; + line-height: $mark-line-height; - @media (width <= #{variables.$g-bp2}) { + @media (max-width: variables.$g-bp2) { // Figma node 455:7187: in the stacked layout the mark is in normal flow and // left-aligned with the text below it. margin-top: 0; @@ -55,48 +63,46 @@ margin: 0; white-space: pre-line; - // Figma node 455:5724, style "P - XL": Sofia Pro Medium, 32/40, letter-spacing 0. - font-family: SofiaPro, sans-serif; - font-size: 3.2rem; - font-weight: 500; - line-height: 4rem; - letter-spacing: normal; - - @media (width <= #{variables.$g-bp2}) { - // Figma node 455:7186: 8px flex gap below the mark, plus the 8px padding on the - // text group that holds the quote and the author. - margin-top: 1.6rem; - margin-left: 0.8rem; + // Figma node 455:5724, style "P - XL". + @include typography.sofia-pro(3.2rem, 500, 4rem); + + @media (max-width: variables.$g-bp2) { + // Figma node 455:7186: gap below the mark, plus the padding on the text group that + // holds the quote and the author. + margin-top: variables.$g-spacer-unit * 2; + margin-left: variables.$g-spacer-unit; } } &__author { grid-area: author; - margin-top: 0.8rem; - - // Figma node 455:5725, style "P - S": Sofia Pro Medium, 14/20, letter-spacing 0. - font-family: SofiaPro, sans-serif; - font-size: 1.4rem; - font-weight: 500; - line-height: 2rem; - letter-spacing: normal; - - @media (width <= #{variables.$g-bp2}) { - margin-bottom: 0.8rem; - margin-left: 0.8rem; + margin-top: variables.$g-spacer-unit; + + // Figma node 455:5725, style "P - S". + @include typography.sofia-pro(1.4rem, 500, 2rem); + + @media (max-width: variables.$g-bp2) { + margin-bottom: variables.$g-spacer-unit; + margin-left: variables.$g-spacer-unit; } } - @media (width <= #{variables.$g-bp2}) { + // Below the design's 1008px frame width the desktop inset eats too much of the text column, + // so it scales back to a third while the pill shape is kept. + @media (max-width: variables.$g-bp4) { + padding-right: $text-inset-right-tablet; + } + + @media (max-width: variables.$g-bp2) { grid-template-columns: 1fr; grid-template-areas: 'mark' 'quote' 'author'; - // Figma node 455:7186: 24/20 padding and a single 120px top-right radius — the - // desktop's two-corner pill does not carry over to mobile. - padding: 2.4rem 2rem; - border-radius: 0 12rem 0 0; + // Figma node 455:7186: a single top-right radius - the desktop's two-corner pill does + // not carry over to mobile. + padding: variables.$g-spacer-unit * 3 variables.$g-spacer-unit * 2.5; + border-radius: 0 $frame-radius-mobile 0 0; } } From eb1aa13fdfdfe4c196adee55df56aab7a3f2381b Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Mon, 10 Aug 2026 21:36:48 +0200 Subject: [PATCH 11/17] docs(content-blocks): document the colour and styling conventions --- .../content-page/components/blocks/README.md | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/ui/src/react-admin/modules/content-page/components/blocks/README.md b/ui/src/react-admin/modules/content-page/components/blocks/README.md index ebdc28287..6a427b45e 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/README.md +++ b/ui/src/react-admin/modules/content-page/components/blocks/README.md @@ -120,6 +120,55 @@ component. --- +## Colour fields + +Colours come from the shared lists in +[`../../const/get-color-options.ts`](../../const/get-color-options.ts), through the helpers in +[`defaults.ts`](./defaults.ts): `FOREGROUND_COLOR_FIELD` for text colours, +`BACKGROUND_COLOR_FIELD` / `BACKGROUND_COLOR_EXTENDED_FIELD` for backgrounds. + +- **Don't build a filtered variant of a list.** Some entries are not a plain CSS colour + (`Color.Transparent`, the `GradientColor.BlackWhite` gradient string, and the + `CustomBackground.MeemooLogo` sentinel that only `ContentBlockRenderer` expands). Whether a + given combination is legible or useful is the editor's call, not something we narrow down in + code — pick the list that fits (`GET_FOREGROUND_COLOR_OPTIONS_*` is already gradient-free) and + pass it through unchanged. +- **Take defaults out of the list, never hand-write them.** `GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF()[5]`, + not `{ label: tText('…___zwart'), value: Color.Black }` — a literal copy silently drifts when + the label behind that translation key changes. +- Use the same option for the field default and for `INITIAL_…_COMPONENTS_STATE`, so the form and + the stored state agree. + +## Styling + +Block styles are a plain `Block.scss` next to the component, imported by it. Reuse what +`~shared/styles` already provides instead of re-deriving values out of Figma: + +```scss +@use "../../../../shared/styles/settings/variables" as variables; +@use "../../../../shared/styles/mixins/typography" as typography; +``` + +- **Spacing** is `variables.$g-spacer-unit` (0.8rem) multiples — `variables.$g-spacer-unit * 3`, + not `2.4rem`. +- **Breakpoints** are `variables.$g-bp1`…`$g-bp4`, written as + `@media (max-width: variables.$g-bp2)`. +- **Type** goes through [`mixins/_typography.scss`](../../../shared/styles/mixins/_typography.scss): + a preset (`sofia-pro-body()`, `sofia-pro-heading-lg()`, …) when the size/weight matches, otherwise + `sofia-pro($size, $weight, $line-height)`. Don't re-declare `font-family`/`font-size`/`font-weight` + by hand. +- **Colours** come from `settings/colors`, or from a CSS custom property when the editor picks them + (`background: var(--frame-color)`). +- A value that genuinely is design-specific (a frame radius, an icon-column width) becomes a named + `$variable` at the top of the file with a comment saying where it comes from — no bare literals + in the rules. +- Check the block at tablet and mobile widths before opening the PR; review asks about it every + time. + +`BlockOverviewWithCarousel.scss` and `BlockHetArchiefQuote.scss` are reasonable reference files. + +--- + ## Key files - [`../ContentBlockForm/ContentBlockForm.tsx`](../ContentBlockForm/ContentBlockForm.tsx) — From 9692535779bb69fc6c854c243fe4d2d5b76051cb Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Tue, 11 Aug 2026 09:00:04 +0200 Subject: [PATCH 12/17] revert(content-blocks): move the colour field defaultValue fix out of this pr --- .../components/blocks/defaults.test.ts | 30 ------------------- .../components/blocks/defaults.ts | 15 ++++++---- 2 files changed, 9 insertions(+), 36 deletions(-) delete mode 100644 ui/src/react-admin/modules/content-page/components/blocks/defaults.test.ts diff --git a/ui/src/react-admin/modules/content-page/components/blocks/defaults.test.ts b/ui/src/react-admin/modules/content-page/components/blocks/defaults.test.ts deleted file mode 100644 index 11336ef29..000000000 --- a/ui/src/react-admin/modules/content-page/components/blocks/defaults.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { describe, expect, it, vi } from 'vitest'; - -vi.mock('~shared/helpers/is-avo', () => ({ isAvo: () => false })); -vi.mock('~shared/helpers/translation-functions', () => ({ - tText: (key: string) => key, - tHtml: (key: string) => key, -})); - -import { Color } from '../../types/content-block.types'; -import { BACKGROUND_COLOR_FIELD, FOREGROUND_COLOR_FIELD } from './defaults'; - -describe('colour field helpers', () => { - it('BACKGROUND_COLOR_FIELD honours an explicit defaultValue', () => { - const field = BACKGROUND_COLOR_FIELD('Kleur kader', { - label: 'Zwart', - value: Color.Black, - }); - - expect(field.editorProps.defaultValue.value).toEqual(Color.Black); - }); - - it('FOREGROUND_COLOR_FIELD honours an explicit defaultValue', () => { - const field = FOREGROUND_COLOR_FIELD('Tekstkleur', { - label: 'Wit', - value: Color.White, - }); - - expect(field.editorProps.defaultValue.value).toEqual(Color.White); - }); -}); diff --git a/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts b/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts index 6eb441a51..bd5fe4469 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts @@ -81,8 +81,9 @@ export const FOREGROUND_COLOR_FIELD = ( editorProps: { options: isAvo() ? GET_FOREGROUND_COLOR_OPTIONS_AVO() : GET_FOREGROUND_COLOR_OPTIONS_ARCHIEF(), defaultValue: - defaultValue ?? - (isAvo() ? GET_FOREGROUND_COLOR_OPTIONS_AVO()[0] : GET_FOREGROUND_COLOR_OPTIONS_ARCHIEF()[0]), + defaultValue || isAvo() + ? GET_FOREGROUND_COLOR_OPTIONS_AVO()[0] + : GET_FOREGROUND_COLOR_OPTIONS_ARCHIEF()[0], }, }); @@ -95,8 +96,9 @@ export const BACKGROUND_COLOR_FIELD = ( editorProps: { options: isAvo() ? GET_BACKGROUND_COLOR_OPTIONS_AVO() : GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF(), defaultValue: - defaultValue ?? - (isAvo() ? GET_BACKGROUND_COLOR_OPTIONS_AVO()[0] : GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF()[0]), + defaultValue || isAvo() + ? GET_BACKGROUND_COLOR_OPTIONS_AVO()[0] + : GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF()[0], }, }); @@ -109,8 +111,9 @@ export const BACKGROUND_COLOR_EXTENDED_FIELD = ( editorProps: { options: isAvo() ? GET_COLOR_OPTIONS_EXTENDED_AVO() : GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF(), defaultValue: - defaultValue ?? - (isAvo() ? GET_COLOR_OPTIONS_EXTENDED_AVO()[0] : GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF()[0]), + defaultValue || isAvo() + ? GET_COLOR_OPTIONS_EXTENDED_AVO()[0] + : GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF()[0], }, }); From d50e30adcf868613d700c82552ebd27da86f1b80 Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Tue, 11 Aug 2026 09:21:46 +0200 Subject: [PATCH 13/17] refactor(content-blocks): inline the quote block colour defaults --- .../BlockHetArchiefQuote.editorconfig.ts | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts index 9fc8907b6..c352237de 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.editorconfig.ts @@ -9,7 +9,7 @@ import type { DefaultContentBlockState, HetArchiefQuoteBlockComponentState, } from '../../../types/content-block.types'; -import { ContentBlockEditor, ContentBlockType } from '../../../types/content-block.types'; +import { Color, ContentBlockEditor, ContentBlockType } from '../../../types/content-block.types'; import { BACKGROUND_COLOR_FIELD, @@ -19,16 +19,12 @@ import { TEXT_FIELD, } from '../defaults'; -// White in the foreground colour list, black in the background colour list -const DEFAULT_TEXT_COLOR_OPTION = () => GET_FOREGROUND_COLOR_OPTIONS_ARCHIEF()[1]; -const DEFAULT_FRAME_COLOR_OPTION = () => GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF()[5]; - export const INITIAL_HET_ARCHIEF_QUOTE_COMPONENTS_STATE = (): HetArchiefQuoteBlockComponentState => ({ quote: '', authorName: '', - textColor: DEFAULT_TEXT_COLOR_OPTION().value, - frameColor: DEFAULT_FRAME_COLOR_OPTION().value, + textColor: Color.White, + frameColor: Color.Black, }); export const INITIAL_HET_ARCHIEF_QUOTE_BLOCK_STATE = (): DefaultContentBlockState => @@ -50,26 +46,32 @@ export const HET_ARCHIEF_QUOTE_BLOCK_CONFIG = (position = 0): ContentBlockConfig fields: { quote: TEXT_FIELD( { - label: tText('admin/content-block/helpers/generators/quote___quote'), + label: tText('admin/content-block/helpers/generators/hetarchief-quote___quote', {}, [ + HET_ARCHIEF, + ]), editorType: ContentBlockEditor.TextArea, }, - tText('admin/content-block/helpers/generators/quote___quote-is-verplicht') + tText('admin/content-block/helpers/generators/hetarchief-quote___quote-is-verplicht', {}, [ + HET_ARCHIEF, + ]) ), authorName: TEXT_FIELD({ - label: tText('admin/content-block/helpers/generators/quote___auteur'), + label: tText('admin/content-block/helpers/generators/hetarchief-quote___auteur', {}, [ + HET_ARCHIEF, + ]), validator: undefined, }), textColor: FOREGROUND_COLOR_FIELD( tText('admin/content-block/helpers/generators/hetarchief-quote___tekstkleur', {}, [ HET_ARCHIEF, ]), - DEFAULT_TEXT_COLOR_OPTION() + GET_FOREGROUND_COLOR_OPTIONS_ARCHIEF()[1] ), frameColor: BACKGROUND_COLOR_FIELD( tText('admin/content-block/helpers/generators/hetarchief-quote___kleur-kader', {}, [ HET_ARCHIEF, ]), - DEFAULT_FRAME_COLOR_OPTION() + GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF()[5] ), }, }, From 33211ded5635e6a8cc4f342bde079499e375a107 Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Tue, 11 Aug 2026 09:21:47 +0200 Subject: [PATCH 14/17] refactor(content-blocks): render the quote mark with the icon component --- ui/src/react-admin/core/config/config.types.ts | 1 + .../BlockHetArchiefQuote.test.tsx | 11 ++++++++--- .../BlockHetArchiefQuote/BlockHetArchiefQuote.tsx | 4 +++- ui/src/shared/helpers/admin-core-config.tsx | 1 + 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/ui/src/react-admin/core/config/config.types.ts b/ui/src/react-admin/core/config/config.types.ts index 0b00f6779..c64025e3b 100644 --- a/ui/src/react-admin/core/config/config.types.ts +++ b/ui/src/react-admin/core/config/config.types.ts @@ -195,6 +195,7 @@ export interface IconConfig { newspaper: IconComponentProps; noAudio: IconComponentProps; noVideo: IconComponentProps; + quotes: IconComponentProps; }; list: () => { label: string; value: string }[]; alerts: () => { key: string; label: string; value: string }[]; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.test.tsx b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.test.tsx index 6db729b98..5fe9d7c8c 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.test.tsx +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.test.tsx @@ -1,6 +1,11 @@ import { cleanup, render, screen } from '@testing-library/react'; import React from 'react'; -import { afterEach, describe, expect, it } from 'vitest'; +import { afterEach, describe, expect, it, vi } from 'vitest'; + +// The real Icon reads the injected client config, which a unit test has no business setting up. +vi.mock('~shared/components/Icon/Icon', () => ({ + Icon: ({ name }: { name: string }) => , +})); import { Color } from '../../../types/content-block.types'; import { BlockHetArchiefQuote } from './BlockHetArchiefQuote'; @@ -48,14 +53,14 @@ describe('', () => { expect(container.querySelector('figcaption')).toBeNull(); }); - it('renders the quote mark as the ligature icon name, hidden from assistive tech', () => { + it('renders the quote mark as a decorative icon, hidden from assistive tech', () => { const { container } = render( ); const mark = container.querySelector('.c-block-het-archief-quote__mark'); - expect(mark?.textContent).toEqual('quotes'); expect(mark?.getAttribute('aria-hidden')).toEqual('true'); + expect(mark?.querySelector('[data-icon="quotes"]')).toBeTruthy(); }); }); diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.tsx b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.tsx index 4680b6687..e4e606e76 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.tsx +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.tsx @@ -3,6 +3,7 @@ import clsx from 'clsx'; import type { CSSProperties, FunctionComponent } from 'react'; import React from 'react'; +import { Icon } from '~shared/components/Icon/Icon'; import type { Color, CustomBackground, GradientColor } from '../../../types/content-block.types'; import './BlockHetArchiefQuote.scss'; @@ -30,8 +31,9 @@ export const BlockHetArchiefQuote: FunctionComponent } as CSSProperties } > + {/* Decorative: the quote itself carries the meaning, so keep it out of the a11y tree */}
{quote}
{authorName && ( diff --git a/ui/src/shared/helpers/admin-core-config.tsx b/ui/src/shared/helpers/admin-core-config.tsx index 29a161239..d8dc95bd4 100644 --- a/ui/src/shared/helpers/admin-core-config.tsx +++ b/ui/src/shared/helpers/admin-core-config.tsx @@ -156,6 +156,7 @@ export function getAdminCoreConfigForLocalTestApp(navigateFunc: NavigateFunction newspaper: { name: 'newspaper' }, noAudio: { name: 'no-audio' }, noVideo: { name: 'no-video' }, + quotes: { name: 'quotes' }, }, list: (): { value: IconName; label: string }[] => { return Object.values(IconName).map((iconName: IconName) => ({ From b1df68dc16c5842ad7fc09b3e407e84739632ffc Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Tue, 11 Aug 2026 09:21:48 +0200 Subject: [PATCH 15/17] style(content-blocks): add the body-xl and body-xs sofia pro presets --- .../BlockHetArchiefQuote/BlockHetArchiefQuote.scss | 11 ++--------- .../modules/shared/styles/mixins/_typography.scss | 8 ++++++++ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.scss b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.scss index ece4553bc..96af282a9 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.scss +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefQuote/BlockHetArchiefQuote.scss @@ -15,9 +15,6 @@ $text-inset-right-tablet: variables.$g-spacer-unit * 8; $frame-radius: 40rem; $frame-radius-mobile: 12rem; -// meemoocons-light is a ligature icon font, provided by the host app (hetarchief-client), and has -// no glyph for the quote-mark character itself - hence the "quotes" ligature in the markup. -$mark-font-family: meemoocons-light, sans-serif; $mark-font-size: variables.$g-spacer-unit * 8; $mark-line-height: variables.$g-spacer-unit * 9; @@ -43,11 +40,7 @@ $mark-line-height: variables.$g-spacer-unit * 9; // raised out of the shared grid row and centred in its own column. margin-top: -(variables.$g-spacer-unit * 1.5); text-align: center; - font-family: $mark-font-family; - font-feature-settings: 'liga'; - font-variant-ligatures: discretionary-ligatures; font-size: $mark-font-size; - font-weight: normal; line-height: $mark-line-height; @media (max-width: variables.$g-bp2) { @@ -64,7 +57,7 @@ $mark-line-height: variables.$g-spacer-unit * 9; white-space: pre-line; // Figma node 455:5724, style "P - XL". - @include typography.sofia-pro(3.2rem, 500, 4rem); + @include typography.sofia-pro-body-xl(); @media (max-width: variables.$g-bp2) { // Figma node 455:7186: gap below the mark, plus the padding on the text group that @@ -79,7 +72,7 @@ $mark-line-height: variables.$g-spacer-unit * 9; margin-top: variables.$g-spacer-unit; // Figma node 455:5725, style "P - S". - @include typography.sofia-pro(1.4rem, 500, 2rem); + @include typography.sofia-pro-body-xs(); @media (max-width: variables.$g-bp2) { margin-bottom: variables.$g-spacer-unit; diff --git a/ui/src/react-admin/modules/shared/styles/mixins/_typography.scss b/ui/src/react-admin/modules/shared/styles/mixins/_typography.scss index f048a56cd..e18bf1df2 100644 --- a/ui/src/react-admin/modules/shared/styles/mixins/_typography.scss +++ b/ui/src/react-admin/modules/shared/styles/mixins/_typography.scss @@ -37,6 +37,10 @@ $font-family: "SofiaPro", sans-serif; @include sofia-pro(1.8rem, 800, 2.8rem, $important); } +@mixin sofia-pro-body-xl($important: false) { + @include sofia-pro(3.2rem, 500, 4rem, $important); +} + @mixin sofia-pro-body($important: false) { @include sofia-pro(1.8rem, 500, 2.8rem, $important); } @@ -45,6 +49,10 @@ $font-family: "SofiaPro", sans-serif; @include sofia-pro(1.6rem, 500, 2.4rem, $important); } +@mixin sofia-pro-body-xs($important: false) { + @include sofia-pro(1.4rem, 500, 2rem, $important); +} + // Single-line truncation with an ellipsis - shared with .u-truncate (utilities/_text.scss). @mixin truncate() { white-space: nowrap; From 98cab9fd2db5fcf109e549044ee09a702831027c Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Tue, 11 Aug 2026 09:21:49 +0200 Subject: [PATCH 16/17] fix(content-blocks): make the quote block translations app specific --- .../BlockAvoQuote/BlockAvoQuote.editorconfig.ts | 11 ++++++----- .../const/get-content-block-type-options.ts | 2 +- ui/src/shared/translations/hetArchief/nl.json | 3 +++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.editorconfig.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.editorconfig.ts index 55ee3ef88..f56d4f28e 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.editorconfig.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.editorconfig.ts @@ -1,5 +1,6 @@ import type { FileUploadProps } from '~shared/components/FileUpload/FileUpload'; import { tText } from '~shared/helpers/translation-functions'; +import { AVO } from '~shared/types'; import type { AvoQuoteBlockComponentState, ContentBlockConfig, @@ -25,23 +26,23 @@ export const INITIAL_AVO_QUOTE_BLOCK_STATE = (): DefaultContentBlockState => export const AVO_QUOTE_BLOCK_CONFIG = (position = 0): ContentBlockConfig => ({ position, - name: tText('admin/content-block/helpers/generators/quote___quote'), + name: tText('admin/content-block/helpers/generators/quote___quote', {}, [AVO]), type: ContentBlockType.AvoQuote, components: { state: INITIAL_AVO_QUOTE_COMPONENTS_STATE(), fields: { quote: TEXT_FIELD( { - label: tText('admin/content-block/helpers/generators/quote___quote'), + label: tText('admin/content-block/helpers/generators/quote___quote', {}, [AVO]), }, - tText('admin/content-block/helpers/generators/quote___quote-is-verplicht') + tText('admin/content-block/helpers/generators/quote___quote-is-verplicht', {}, [AVO]) ), authorName: TEXT_FIELD({ - label: tText('admin/content-block/helpers/generators/quote___auteur'), + label: tText('admin/content-block/helpers/generators/quote___auteur', {}, [AVO]), validator: undefined, }), authorInitials: TEXT_FIELD({ - label: tText('admin/content-block/helpers/generators/quote___initialen'), + label: tText('admin/content-block/helpers/generators/quote___initialen', {}, [AVO]), validator: undefined, }), authorImage: FILE_FIELD( 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 6c41e52df..e2e2bd970 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 @@ -79,7 +79,7 @@ export const GET_CONTENT_BLOCK_TYPE_OPTIONS: () => SelectOption[] = () = value: ContentBlockType.Spotlight, }, { - label: tText('admin/content-block/content-block___quote'), + label: tText('admin/content-block/content-block___quote', {}, [AVO]), value: ContentBlockType.AvoQuote, }, { diff --git a/ui/src/shared/translations/hetArchief/nl.json b/ui/src/shared/translations/hetArchief/nl.json index 57380af84..e62a4f2ea 100644 --- a/ui/src/shared/translations/hetArchief/nl.json +++ b/ui/src/shared/translations/hetArchief/nl.json @@ -137,7 +137,10 @@ "admin/content-block/helpers/generators/heading___titel-kleur": "Titel kleur", "admin/content-block/helpers/generators/heading___type": "Type", "admin/content-block/helpers/generators/hero___alt-title-text": "Alt. titel tekst", + "admin/content-block/helpers/generators/hetarchief-quote___auteur": "Auteur", "admin/content-block/helpers/generators/hetarchief-quote___kleur-kader": "Kleur kader", + "admin/content-block/helpers/generators/hetarchief-quote___quote": "Quote", + "admin/content-block/helpers/generators/hetarchief-quote___quote-is-verplicht": "Quote is verplicht", "admin/content-block/helpers/generators/hetarchief-quote___quote-kader": "Quote kader", "admin/content-block/helpers/generators/hetarchief-quote___tekstkleur": "Tekstkleur", "admin/content-block/helpers/generators/iframe___i-frame": "iFrame", From 47ff92f315c842bb8bbd966baf762f3326886340 Mon Sep 17 00:00:00 2001 From: Robbe Bierebeeck Date: Tue, 11 Aug 2026 11:41:17 +0200 Subject: [PATCH 17/17] fix(content-blocks): keep the avo quote translations available in both apps --- .../BlockAvoQuote.editorconfig.ts | 24 ++++++++++++++----- .../const/get-content-block-type-options.ts | 2 +- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.editorconfig.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.editorconfig.ts index f56d4f28e..fb3ab35fd 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.editorconfig.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoQuote/BlockAvoQuote.editorconfig.ts @@ -1,6 +1,6 @@ import type { FileUploadProps } from '~shared/components/FileUpload/FileUpload'; import { tText } from '~shared/helpers/translation-functions'; -import { AVO } from '~shared/types'; +import { AVO, HET_ARCHIEF } from '~shared/types'; import type { AvoQuoteBlockComponentState, ContentBlockConfig, @@ -26,23 +26,35 @@ export const INITIAL_AVO_QUOTE_BLOCK_STATE = (): DefaultContentBlockState => export const AVO_QUOTE_BLOCK_CONFIG = (position = 0): ContentBlockConfig => ({ position, - name: tText('admin/content-block/helpers/generators/quote___quote', {}, [AVO]), + name: tText('admin/content-block/helpers/generators/quote___quote', {}, [AVO, HET_ARCHIEF]), type: ContentBlockType.AvoQuote, components: { state: INITIAL_AVO_QUOTE_COMPONENTS_STATE(), fields: { quote: TEXT_FIELD( { - label: tText('admin/content-block/helpers/generators/quote___quote', {}, [AVO]), + label: tText('admin/content-block/helpers/generators/quote___quote', {}, [ + AVO, + HET_ARCHIEF, + ]), }, - tText('admin/content-block/helpers/generators/quote___quote-is-verplicht', {}, [AVO]) + tText('admin/content-block/helpers/generators/quote___quote-is-verplicht', {}, [ + AVO, + HET_ARCHIEF, + ]) ), authorName: TEXT_FIELD({ - label: tText('admin/content-block/helpers/generators/quote___auteur', {}, [AVO]), + label: tText('admin/content-block/helpers/generators/quote___auteur', {}, [ + AVO, + HET_ARCHIEF, + ]), validator: undefined, }), authorInitials: TEXT_FIELD({ - label: tText('admin/content-block/helpers/generators/quote___initialen', {}, [AVO]), + label: tText('admin/content-block/helpers/generators/quote___initialen', {}, [ + AVO, + HET_ARCHIEF, + ]), validator: undefined, }), authorImage: FILE_FIELD( 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 e2e2bd970..4e656cd23 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 @@ -79,7 +79,7 @@ export const GET_CONTENT_BLOCK_TYPE_OPTIONS: () => SelectOption[] = () = value: ContentBlockType.Spotlight, }, { - label: tText('admin/content-block/content-block___quote', {}, [AVO]), + label: tText('admin/content-block/content-block___quote', {}, [AVO, HET_ARCHIEF]), value: ContentBlockType.AvoQuote, }, {