From b8d1d4038b50fcfa9c5db876c93553c2b41fc600 Mon Sep 17 00:00:00 2001 From: Femke Reunes Date: Wed, 2 Sep 2026 11:12:02 +0200 Subject: [PATCH 01/13] ARC-3904: start on refactoring the flowplayer with custom controls --- .../IeObjectFlowPlayerWrapper.tsx | 7 ++++ .../BlockHeroCarouselActiveSlide.tsx | 33 +++++++++++++++++-- .../content-page/types/content-block.types.ts | 1 + 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/ui/src/react-admin/modules/content-page/components/IeObjectFlowPlayerWrapper/IeObjectFlowPlayerWrapper.tsx b/ui/src/react-admin/modules/content-page/components/IeObjectFlowPlayerWrapper/IeObjectFlowPlayerWrapper.tsx index 6eef0de8..c1585742 100644 --- a/ui/src/react-admin/modules/content-page/components/IeObjectFlowPlayerWrapper/IeObjectFlowPlayerWrapper.tsx +++ b/ui/src/react-admin/modules/content-page/components/IeObjectFlowPlayerWrapper/IeObjectFlowPlayerWrapper.tsx @@ -19,6 +19,9 @@ export interface IeObjectFlowPlayerWrapperProps extends DefaultComponentProps { onEnded?: () => void; isMuted?: boolean; onMutedChange?: (muted: boolean) => void; + /** Opt-in - defaults to FlowPlayer's own native controls, unchanged for existing callers. */ + controlsVariant?: FlowPlayerProps['controlsVariant']; + customControlsConfig?: FlowPlayerProps['customControlsConfig']; } export const IeObjectFlowPlayerWrapper: FunctionComponent = ({ @@ -29,6 +32,8 @@ export const IeObjectFlowPlayerWrapper: FunctionComponent { if (!isAudioVideoFormat(ieObject.dctermsFormat)) { @@ -75,6 +80,8 @@ export const IeObjectFlowPlayerWrapper: FunctionComponent ImageOrAudioWaveForm, which leaves `waveColor` unset and falls back to + // AudioWaveFormDisplay's own default) for the not-yet-played bars, large size since + // this is the active, full-size slide. AudioWaveFormDisplay's bar color is its own + // prop (not `currentColor`), so the "played" highlight needs its own render per + // state rather than a CSS trick - see PeakDisplay's `peakVisual` function form. + // No-op for video items: FlowPlayer only reads peakMode/peakVisual when audio. + peakVisual: (state: 'inactive' | 'active') => ( + + ), + // AudioWaveFormDisplay's bars don't fill its box edge-to-edge - see the constant. + peakVisualContentInset: WAVE_FORM_PADDING_X_PERCENT, + }} /> ); } 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 afcdfd77..129889de 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 @@ -88,6 +88,7 @@ export enum Color { AlertBackground = '#FFFFCC', AlertAccent = '#E9E994', TealBright200 = '#CFE3E9', + Teal40 = '#81ECDC', BorderColor = '#3FB1D6', InputBoxShadow = '#69C2DF', Transparent = 'TRANSPARENT', From 463fc26374d073e22463cbbc5e990b0717dbe745 Mon Sep 17 00:00:00 2001 From: Femke Reunes Date: Thu, 3 Sep 2026 16:53:05 +0200 Subject: [PATCH 02/13] ARC-3904: map audio fragment to correct audio still instead the ugly speaker --- .../content-page/hooks/useGetIeObjectsByIds.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ui/src/react-admin/modules/content-page/hooks/useGetIeObjectsByIds.ts b/ui/src/react-admin/modules/content-page/hooks/useGetIeObjectsByIds.ts index f46a2c4d..10641d34 100644 --- a/ui/src/react-admin/modules/content-page/hooks/useGetIeObjectsByIds.ts +++ b/ui/src/react-admin/modules/content-page/hooks/useGetIeObjectsByIds.ts @@ -1,5 +1,7 @@ import { useQuery } from '@tanstack/react-query'; import type { HetArchiefIeObject as IeObject } from '@viaa/avo2-types'; +import { AdminConfigManager } from '~core/config'; +import { isAudioFormat } from '~shared/helpers/is-audio-video-format.ts'; import { IeObjectsService } from '~shared/services/ie-objects-service/ie-objects.service.ts'; import { QUERY_KEYS } from '~shared/types'; @@ -17,7 +19,15 @@ export const useGetIeObjectsByIds = (schemaIdentifiers: string[], enabled = true // A pid the endpoint could not resolve comes back as null, so entries cannot be keyed blindly. (await IeObjectsService.getIeObjectsByIds(identifiers)) .filter((ieObject): ieObject is IeObject => !!ieObject?.schemaIdentifier) - .map((ieObject) => [ieObject.schemaIdentifier, ieObject]) + .map((ieObject) => [ + ieObject.schemaIdentifier, + { + ...ieObject, + thumbnailUrl: isAudioFormat(ieObject.dctermsFormat) + ? AdminConfigManager.getConfig().components.defaultAudioStill + : ieObject.thumbnailUrl, + }, + ]) ), enabled: enabled && identifiers.length > 0, staleTime: 60 * 60 * 1000, // 1 hour, same as the playable display data From fe0c59c2ea07837486e67e35423052eb17cc6290 Mon Sep 17 00:00:00 2001 From: Femke Reunes Date: Thu, 3 Sep 2026 16:53:39 +0200 Subject: [PATCH 03/13] ARC-3904: Move AudioWaveFormDisplay to react components --- .../AudioWaveFormDisplay.helpers.ts | 81 ------------------- .../AudioWaveFormDisplay.scss | 27 ------- .../AudioWaveFormDisplay.test.tsx | 50 ------------ .../AudioWaveFormDisplay.tsx | 72 ----------------- .../ImageOrAudioWaveForm.tsx | 5 +- 5 files changed, 1 insertion(+), 234 deletions(-) delete mode 100644 ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/AudioWaveFormDisplay/AudioWaveFormDisplay.helpers.ts delete mode 100644 ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/AudioWaveFormDisplay/AudioWaveFormDisplay.scss delete mode 100644 ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/AudioWaveFormDisplay/AudioWaveFormDisplay.test.tsx delete mode 100644 ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/AudioWaveFormDisplay/AudioWaveFormDisplay.tsx diff --git a/ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/AudioWaveFormDisplay/AudioWaveFormDisplay.helpers.ts b/ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/AudioWaveFormDisplay/AudioWaveFormDisplay.helpers.ts deleted file mode 100644 index 9ec7e7df..00000000 --- a/ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/AudioWaveFormDisplay/AudioWaveFormDisplay.helpers.ts +++ /dev/null @@ -1,81 +0,0 @@ -export type AudioWaveFormDisplaySize = 'small' | 'large'; - -export interface WaveFormBar { - x: number; - y1: number; - y2: number; -} - -// Bar geometry traced from Frame 1895.svg: 30 vertical bars, 3 units apart starting at x=0.9, -// centered on y=21.6, in a 92x44 viewBox. -const WAVE_FORM_VIEW_BOX_WIDTH = 92; -const WAVE_FORM_VIEW_BOX_HEIGHT = 44; -const WAVE_FORM_CENTER_Y = 21.6; -const WAVE_FORM_FIRST_BAR_X = 0.9; -const WAVE_FORM_BAR_SPACING = 3; -export const WAVE_FORM_STROKE_WIDTH = 1.8; - -// Padding around the bars, as a fraction of the display's box on each side. Baked into the -// viewBox rather than CSS padding so it can't collapse to zero on a short/narrow container -- -// `preserveAspectRatio="xMidYMid meet"` on the then scales and centers it without stretching. -const WAVE_FORM_PADDING_X_RATIO = 0.15; -const WAVE_FORM_PADDING_Y_RATIO = 0.3; - -// Half the height of each bar (viewBox units), left to right, traced from Frame 1895.svg. -const WAVE_FORM_BAR_HALF_HEIGHTS: readonly number[] = [ - 0.3, 3.3, 3.3, 6.9, 3.3, 6.9, 13.5, 20.7, 10.5, 6.9, 17.1, 13.5, 10.5, 3.3, 6.9, 3.3, 3.3, 6.9, - 10.5, 13.5, 6.9, 3.3, 3.3, 6.9, 3.3, 3.3, 6.9, 3.3, 3.3, 1.5, -]; - -const WAVE_FORM_BAR_COUNT = WAVE_FORM_BAR_HALF_HEIGHTS.length; - -// Right margin the reference asset leaves after its last bar, reused to size the large viewBox. -const WAVE_FORM_RIGHT_MARGIN = - WAVE_FORM_VIEW_BOX_WIDTH - - (WAVE_FORM_FIRST_BAR_X + (WAVE_FORM_BAR_COUNT - 1) * WAVE_FORM_BAR_SPACING); - -function buildWaveFormBars( - barCount: number, - halfHeightAt: (index: number) => number -): WaveFormBar[] { - return Array.from({ length: barCount }, (_, index) => { - const x = WAVE_FORM_FIRST_BAR_X + index * WAVE_FORM_BAR_SPACING; - const halfHeight = halfHeightAt(index); - return { x, y1: WAVE_FORM_CENTER_Y - halfHeight, y2: WAVE_FORM_CENTER_Y + halfHeight }; - }); -} - -function getWaveFormViewBoxWidth(barCount: number): number { - return WAVE_FORM_FIRST_BAR_X + (barCount - 1) * WAVE_FORM_BAR_SPACING + WAVE_FORM_RIGHT_MARGIN; -} - -const SMALL_WAVE_FORM_BARS: readonly WaveFormBar[] = buildWaveFormBars( - WAVE_FORM_BAR_COUNT, - (index) => WAVE_FORM_BAR_HALF_HEIGHTS[index] -); - -// Large: the small wave form immediately followed by its own mirror, on one continuous grid -- -// not two small viewBoxes side by side, which would double their outer margins into a bigger gap. -const LARGE_WAVE_FORM_BARS: readonly WaveFormBar[] = buildWaveFormBars( - WAVE_FORM_BAR_COUNT * 2, - (index) => - WAVE_FORM_BAR_HALF_HEIGHTS[ - index < WAVE_FORM_BAR_COUNT ? index : WAVE_FORM_BAR_COUNT * 2 - 1 - index - ] -); - -export function getWaveFormBars(size: AudioWaveFormDisplaySize): readonly WaveFormBar[] { - return size === 'large' ? LARGE_WAVE_FORM_BARS : SMALL_WAVE_FORM_BARS; -} - -// Expands the bars' bounding box to the full display box, per the padding ratios above. -export function getWaveFormViewBox(size: AudioWaveFormDisplaySize): string { - const contentWidth = getWaveFormViewBoxWidth(getWaveFormBars(size).length); - const contentHeight = WAVE_FORM_VIEW_BOX_HEIGHT; - - const width = contentWidth / (1 - 2 * WAVE_FORM_PADDING_X_RATIO); - const height = contentHeight / (1 - 2 * WAVE_FORM_PADDING_Y_RATIO); - const minX = -(width - contentWidth) / 2; - const minY = -(height - contentHeight) / 2; - return `${minX} ${minY} ${width} ${height}`; -} diff --git a/ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/AudioWaveFormDisplay/AudioWaveFormDisplay.scss b/ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/AudioWaveFormDisplay/AudioWaveFormDisplay.scss deleted file mode 100644 index 7bf2eec6..00000000 --- a/ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/AudioWaveFormDisplay/AudioWaveFormDisplay.scss +++ /dev/null @@ -1,27 +0,0 @@ -@use "../../../../shared/styles/settings/colors" as colors; - -.c-audio-wave-form-display { - display: block; - width: 100%; - height: 100%; - background-color: var(--c-audio-wave-form-display-bg, transparent); - - &__scaler { - display: block; - width: 100%; - height: 100%; - } - - &__svg { - display: block; - width: 100%; - height: 100%; - } - - &__bar { - stroke: var( - --c-audio-wave-form-display-bar-color, - var(--c-audio-wave-form-display-wave-color, colors.$white) - ); - } -} diff --git a/ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/AudioWaveFormDisplay/AudioWaveFormDisplay.test.tsx b/ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/AudioWaveFormDisplay/AudioWaveFormDisplay.test.tsx deleted file mode 100644 index 891e21e7..00000000 --- a/ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/AudioWaveFormDisplay/AudioWaveFormDisplay.test.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { cleanup, render } from '@testing-library/react'; -import React from 'react'; -import { afterEach, describe, expect, it } from 'vitest'; -import { Color } from '~modules/content-page/types/content-block.types.ts'; -import { AudioWaveFormDisplay } from './AudioWaveFormDisplay.tsx'; - -afterEach(() => { - cleanup(); -}); - -describe('', () => { - it('should be able to render', () => { - render(); - }); - - it('should render the large size with twice as many bars as the small size', () => { - const { container: small } = render(); - const { container: large } = render(); - - const smallBarCount = small.querySelectorAll('.c-audio-wave-form-display__bar').length; - const largeBarCount = large.querySelectorAll('.c-audio-wave-form-display__bar').length; - - expect(largeBarCount).toBe(smallBarCount * 2); - }); - - it('should default the wave color to white', () => { - const { container } = render(); - const outer = container.querySelector('.c-audio-wave-form-display') as HTMLElement; - - expect(outer.style.getPropertyValue('--c-audio-wave-form-display-wave-color')).toBe( - Color.White - ); - }); - - it('should pass the given wave and background colors through as CSS variables', () => { - const { container } = render( - - ); - const outer = container.querySelector('.c-audio-wave-form-display') as HTMLElement; - - expect(outer.style.getPropertyValue('--c-audio-wave-form-display-wave-color')).toBe(Color.Teal); - expect(outer.style.getPropertyValue('--c-audio-wave-form-display-bg')).toBe(Color.NightBlue); - }); - - it('should pass the given className through', () => { - const { container } = render(); - - expect(container.querySelector('.c-audio-wave-form-display.my-extra-class')).not.toBeNull(); - }); -}); diff --git a/ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/AudioWaveFormDisplay/AudioWaveFormDisplay.tsx b/ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/AudioWaveFormDisplay/AudioWaveFormDisplay.tsx deleted file mode 100644 index cff31d37..00000000 --- a/ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/AudioWaveFormDisplay/AudioWaveFormDisplay.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import clsx from 'clsx'; -import type { CSSProperties, FunctionComponent, ReactElement } from 'react'; -import React from 'react'; -import { Color } from '~modules/content-page/types/content-block.types.ts'; -import type { DefaultComponentProps } from '~modules/shared/types/components'; -import { - type AudioWaveFormDisplaySize, - getWaveFormBars, - getWaveFormViewBox, - WAVE_FORM_STROKE_WIDTH, -} from './AudioWaveFormDisplay.helpers'; - -import './AudioWaveFormDisplay.scss'; - -export type { AudioWaveFormDisplaySize }; - -export interface AudioWaveFormDisplayProps extends DefaultComponentProps { - waveColor?: Color; - backgroundColor?: Color; - size?: AudioWaveFormDisplaySize; - ariaLabel?: string; -} - -export const AudioWaveFormDisplay: FunctionComponent = ({ - className, - ariaLabel, - waveColor = Color.White, - backgroundColor, - size = 'small', -}): ReactElement => { - const bars = getWaveFormBars(size); - const viewBox = getWaveFormViewBox(size); - - return ( -
- {/* Plain box for consumers to hook a hover-zoom transform onto: transitioning `transform` - on an itself doesn't animate smoothly in every browser, unlike an ordinary element. */} -
- -
-
- ); -}; diff --git a/ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/ImageOrAudioWaveForm.tsx b/ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/ImageOrAudioWaveForm.tsx index a6254a55..13034e5f 100644 --- a/ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/ImageOrAudioWaveForm.tsx +++ b/ui/src/react-admin/modules/content-page/components/ImageOrAudioWaveForm/ImageOrAudioWaveForm.tsx @@ -1,11 +1,8 @@ +import { AudioWaveFormDisplay, type AudioWaveFormDisplayProps } from '@meemoo/react-components'; import { Image } from '@viaa/avo2-components'; import type { FunctionComponent, ReactElement } from 'react'; import React from 'react'; import { AdminConfigManager } from '~core/config'; -import { - AudioWaveFormDisplay, - type AudioWaveFormDisplayProps, -} from './AudioWaveFormDisplay/AudioWaveFormDisplay.tsx'; export interface ImageOrAudioWaveFormProps extends Omit { imageSrc?: string; From 6e7dfb9d1b397c01e00c4b0d43374701009127ec Mon Sep 17 00:00:00 2001 From: Femke Reunes Date: Thu, 3 Sep 2026 16:55:48 +0200 Subject: [PATCH 04/13] ARC-3904: replace image with audiowave form --- .../BlockDriekeuzespeler.scss | 12 +++++++++++- .../BlockDriekeuzespeler.tsx | 16 +++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockDriekeuzespeler/BlockDriekeuzespeler.scss b/ui/src/react-admin/modules/content-page/components/blocks/BlockDriekeuzespeler/BlockDriekeuzespeler.scss index 27346123..814ae1c4 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockDriekeuzespeler/BlockDriekeuzespeler.scss +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockDriekeuzespeler/BlockDriekeuzespeler.scss @@ -197,12 +197,22 @@ $pill-font-size: clamp(1.8rem, 1.964cqw, 2.4rem); inset: 0; width: 100%; height: 100%; - object-fit: cover; // An inactive tile is desaturated slightly. On the thumbnail alone, because the pill carries // colours the admin picked. filter: saturate(0.9); transition: filter $tile-rest-duration $tile-hover-easing; + + img { + width: 100%; + height: 100%; + object-fit: cover; + object-position: center; + } + + &--newspaper img { + object-position: top center; + } } &__tile-button { diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockDriekeuzespeler/BlockDriekeuzespeler.tsx b/ui/src/react-admin/modules/content-page/components/blocks/BlockDriekeuzespeler/BlockDriekeuzespeler.tsx index ca2990ca..7cba05c5 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockDriekeuzespeler/BlockDriekeuzespeler.tsx +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockDriekeuzespeler/BlockDriekeuzespeler.tsx @@ -3,6 +3,7 @@ import clsx from 'clsx'; import type { CSSProperties, FunctionComponent, ReactElement } from 'react'; import React, { useCallback, useEffect, useRef, useState } from 'react'; import { AdminCoreIconName } from '~core/config'; +import { ImageOrAudioWaveForm } from '~modules/content-page/components/ImageOrAudioWaveForm/ImageOrAudioWaveForm.tsx'; import { useGetIeObjectsByIds } from '~modules/content-page/hooks/useGetIeObjectsByIds'; import { useGetPlayableFileForIeObjects } from '~modules/content-page/hooks/useGetPlayableFileForIeObjects'; import type { @@ -10,6 +11,7 @@ import type { DriekeuzespelerTileColors, } from '~modules/content-page/types/content-block.types'; import { Icon } from '~shared/components/Icon/Icon'; +import { mapDcTermsFormatToSimpleType } from '~shared/helpers/map-format-to-type.ts'; import type { DefaultComponentProps } from '~shared/types/components'; import { useGetThemesByIds } from '../BlockOverviewThemes/hooks/useGetThemesByIds'; import { DRIEKEUZESPELER_TILE_COUNT } from './BlockDriekeuzespeler.editorconfig'; @@ -103,6 +105,7 @@ export const BlockDriekeuzespeler: FunctionComponent const { backgroundColor, textColor } = tileColors[tileIndex] ?? {}; const schemaIdentifier = selected?.interest?.mediaItem?.value; const ieObject = schemaIdentifier ? ieObjectsById?.[schemaIdentifier] : undefined; + const simpleType = mapDcTermsFormatToSimpleType(ieObject?.dctermsFormat); return (
  • style={{ '--tile-color': backgroundColor } as CSSProperties} > {!!ieObject?.thumbnailUrl && ( - )} {!!selected?.interest && ( From 2b209077662196f3347fce5840ec250326568aaf Mon Sep 17 00:00:00 2001 From: Femke Reunes Date: Thu, 3 Sep 2026 16:56:16 +0200 Subject: [PATCH 05/13] ARC-3904: Use new custom controls in FlowPlayer wrapper and add fallback background color --- .../IeObjectFlowPlayerWrapper.tsx | 25 +++++++++------ .../BlockHeroCarouselActiveSlide.tsx | 31 ++----------------- .../BlockThemeReels/BlockThemeReelSection.tsx | 2 +- 3 files changed, 19 insertions(+), 39 deletions(-) diff --git a/ui/src/react-admin/modules/content-page/components/IeObjectFlowPlayerWrapper/IeObjectFlowPlayerWrapper.tsx b/ui/src/react-admin/modules/content-page/components/IeObjectFlowPlayerWrapper/IeObjectFlowPlayerWrapper.tsx index c1585742..6e2dcd6f 100644 --- a/ui/src/react-admin/modules/content-page/components/IeObjectFlowPlayerWrapper/IeObjectFlowPlayerWrapper.tsx +++ b/ui/src/react-admin/modules/content-page/components/IeObjectFlowPlayerWrapper/IeObjectFlowPlayerWrapper.tsx @@ -1,6 +1,7 @@ import { FlowPlayer, type FlowPlayerProps } from '@meemoo/react-components'; -import React, { type FunctionComponent, type ReactNode } from 'react'; +import React, { type FunctionComponent, type ReactNode, useMemo } from 'react'; import { AdminConfigManager } from '~core/config'; +import { getRandomTertiaryBackgroundColor } from '~modules/content-page/helpers'; import { Color } from '~modules/content-page/types/content-block.types.ts'; import type { DefaultComponentProps } from '~modules/shared/types/components'; import { @@ -19,9 +20,7 @@ export interface IeObjectFlowPlayerWrapperProps extends DefaultComponentProps { onEnded?: () => void; isMuted?: boolean; onMutedChange?: (muted: boolean) => void; - /** Opt-in - defaults to FlowPlayer's own native controls, unchanged for existing callers. */ - controlsVariant?: FlowPlayerProps['controlsVariant']; - customControlsConfig?: FlowPlayerProps['customControlsConfig']; + backgroundColor?: string; } export const IeObjectFlowPlayerWrapper: FunctionComponent = ({ @@ -32,10 +31,11 @@ export const IeObjectFlowPlayerWrapper: FunctionComponent { + const fallbackBackgroundColor = useMemo(() => getRandomTertiaryBackgroundColor(), []); + if (!isAudioVideoFormat(ieObject.dctermsFormat)) { return null; } @@ -59,6 +59,7 @@ export const IeObjectFlowPlayerWrapper: FunctionComponent = { poster: poster ?? imageSrc, @@ -80,9 +81,15 @@ export const IeObjectFlowPlayerWrapper: FunctionComponent ImageOrAudioWaveForm, which leaves `waveColor` unset and falls back to - // AudioWaveFormDisplay's own default) for the not-yet-played bars, large size since - // this is the active, full-size slide. AudioWaveFormDisplay's bar color is its own - // prop (not `currentColor`), so the "played" highlight needs its own render per - // state rather than a CSS trick - see PeakDisplay's `peakVisual` function form. - // No-op for video items: FlowPlayer only reads peakMode/peakVisual when audio. - peakVisual: (state: 'inactive' | 'active') => ( - - ), - // AudioWaveFormDisplay's bars don't fill its box edge-to-edge - see the constant. - peakVisualContentInset: WAVE_FORM_PADDING_X_PERCENT, - }} + backgroundColor={item?.backgroundColor} /> ); } diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockThemeReels/BlockThemeReelSection.tsx b/ui/src/react-admin/modules/content-page/components/blocks/BlockThemeReels/BlockThemeReelSection.tsx index b7681180..55383e3d 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockThemeReels/BlockThemeReelSection.tsx +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockThemeReels/BlockThemeReelSection.tsx @@ -16,6 +16,7 @@ import { CarouselButtons } from '~modules/content-page/components/CarouselButton import { ImageOrAudioWaveForm } from '~modules/content-page/components/ImageOrAudioWaveForm/ImageOrAudioWaveForm.tsx'; import { getRandomTertiaryBackgroundColor } from '~modules/content-page/helpers/get-random-tertiary-background-color.ts'; import type { Color } from '~modules/content-page/types/content-block.types.ts'; +import { IeObjectsService } from '~modules/ie-objects/ie-objects.service.ts'; import type { DefaultComponentProps } from '~modules/shared/types/components'; import { App, Locale } from '~modules/translations/translations.core.types.ts'; import { Icon } from '~shared/components/Icon'; @@ -26,7 +27,6 @@ import { tText } from '~shared/helpers/translation-functions.ts'; import 'swiper/css'; import './BlockThemeReelsSection.scss'; -import { IeObjectsService } from '~modules/ie-objects/ie-objects.service.ts'; export interface BlockThemeReelSectionProps extends DefaultComponentProps { themeId: string; From 3e393292cb85b0031e7a6ff3194ed9701a6bfdc9 Mon Sep 17 00:00:00 2001 From: Femke Reunes Date: Fri, 4 Sep 2026 07:43:57 +0200 Subject: [PATCH 06/13] ARC-3904: Replace styled text with button --- .../BlockDriekeuzespelerModal.scss | 8 +------- .../BlockDriekeuzespelerModal.tsx | 15 ++++++++++----- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockDriekeuzespeler/BlockDriekeuzespelerModal.scss b/ui/src/react-admin/modules/content-page/components/blocks/BlockDriekeuzespeler/BlockDriekeuzespelerModal.scss index 33206a4c..b05394e8 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockDriekeuzespeler/BlockDriekeuzespelerModal.scss +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockDriekeuzespeler/BlockDriekeuzespelerModal.scss @@ -73,13 +73,8 @@ $card-radius: variables.$g-spacer-unit * 1.5; background-color: rgba(colors.$color-gray-1000, 0.12); } - &__theme-cta { - flex: 0 0 auto; - padding: variables.$g-spacer-unit variables.$g-spacer-unit * 2; - border-radius: 9.2rem; - background-color: colors.$color-silver; + &__theme-cta .c-button__label{ font-weight: 700; - white-space: nowrap; } // Mobile insets the media and stacks the metadata card under it, with the theme CTA on its own row. @@ -114,6 +109,5 @@ $card-radius: variables.$g-spacer-unit * 1.5; &__theme-cta { width: fit-content; } - } } diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockDriekeuzespeler/BlockDriekeuzespelerModal.tsx b/ui/src/react-admin/modules/content-page/components/blocks/BlockDriekeuzespeler/BlockDriekeuzespelerModal.tsx index ca23754b..baa0a08d 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockDriekeuzespeler/BlockDriekeuzespelerModal.tsx +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockDriekeuzespeler/BlockDriekeuzespelerModal.tsx @@ -1,3 +1,4 @@ +import { Button } from '@meemoo/react-components'; import { Modal, ModalBody } from '@viaa/avo2-components'; import { AvoCoreContentPickerType, @@ -137,11 +138,15 @@ export const BlockDriekeuzespelerModal: FunctionComponent - {tText( - 'modules/content-page/components/blocks/block-driekeuzespeler/block-driekeuzespeler___toon-meer-over-thema', - { theme: themeName }, - [HET_ARCHIEF] - )} +