Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions ui/all-translations-het-archief.json
Original file line number Diff line number Diff line change
Expand Up @@ -1724,19 +1724,19 @@
"app": "HET_ARCHIEF",
"component": "ADMIN_CORE",
"location": "modules/content-page/const/content-block",
"key": "poederblauw",
"key": "babyblauw",
"language": "nl",
"value": "Poederblauw",
"value": "Baby blauw",
"value_type": "TEXT"
},
{
"id": "",
"app": "HET_ARCHIEF",
"component": "ADMIN_CORE",
"location": "modules/content-page/const/content-block",
"key": "poederblauw",
"key": "babyblauw",
"language": "en",
"value": "Poederblauw",
"value": "Baby blauw",
"value_type": "TEXT"
},
{
Expand Down Expand Up @@ -58539,4 +58539,4 @@
"value": "You do not have the right permissions to call this route",
"value_type": "TEXT"
}
]
]
6 changes: 3 additions & 3 deletions ui/all-translations-het-archief.sql
Original file line number Diff line number Diff line change
Expand Up @@ -1563,6 +1563,8 @@ INSERT INTO app.translations ("component", "location", "key", "value", "value_ty
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('ADMIN_CORE', 'modules/content-page/components/content-page-renderer/content-page-renderer', 'bewerk-pagina-tooltip', 'Edit page tooltip', 'TEXT', 'en') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Edit page tooltip', value_type = 'TEXT';
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('ADMIN_CORE', 'modules/content-page/components/date-picker/date-picker', 'datum-input-aria-label', 'Kies hier de datum', 'TEXT', 'nl') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Kies hier de datum', value_type = 'TEXT';
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('ADMIN_CORE', 'modules/content-page/components/date-picker/date-picker', 'datum-input-aria-label', 'Specify the date here', 'TEXT', 'en') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Specify the date here', value_type = 'TEXT';
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('ADMIN_CORE', 'modules/content-page/const/content-block', 'babyblauw', 'Baby blauw', 'TEXT', 'en') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Baby blauw', value_type = 'TEXT';
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('ADMIN_CORE', 'modules/content-page/const/content-block', 'babyblauw', 'Baby blauw', 'TEXT', 'nl') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Baby blauw', value_type = 'TEXT';
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('ADMIN_CORE', 'modules/content-page/const/content-block', 'bloesem-roze', 'Bloesem roze', 'TEXT', 'en') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Bloesem roze', value_type = 'TEXT';
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('ADMIN_CORE', 'modules/content-page/const/content-block', 'bloesem-roze', 'Bloesem roze', 'TEXT', 'nl') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Bloesem roze', value_type = 'TEXT';
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('ADMIN_CORE', 'modules/content-page/const/content-block', 'honing-geel', 'Honing geel', 'TEXT', 'en') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Honing geel', value_type = 'TEXT';
Expand All @@ -1583,8 +1585,6 @@ INSERT INTO app.translations ("component", "location", "key", "value", "value_ty
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('ADMIN_CORE', 'modules/content-page/const/content-block', 'pistache-groen', 'Pistache groen', 'TEXT', 'nl') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Pistache groen', value_type = 'TEXT';
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('ADMIN_CORE', 'modules/content-page/const/content-block', 'platinum', 'Platinum', 'TEXT', 'en') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Platinum', value_type = 'TEXT';
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('ADMIN_CORE', 'modules/content-page/const/content-block', 'platinum', 'Platinum', 'TEXT', 'nl') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Platinum', value_type = 'TEXT';
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('ADMIN_CORE', 'modules/content-page/const/content-block', 'poederblauw', 'Poederblauw', 'TEXT', 'en') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Poederblauw', value_type = 'TEXT';
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('ADMIN_CORE', 'modules/content-page/const/content-block', 'poederblauw', 'Poederblauw', 'TEXT', 'nl') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Poederblauw', value_type = 'TEXT';
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('ADMIN_CORE', 'modules/content-page/const/content-block', 'salie-groen', 'Salie groen', 'TEXT', 'en') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Salie groen', value_type = 'TEXT';
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('ADMIN_CORE', 'modules/content-page/const/content-block', 'salie-groen', 'Salie groen', 'TEXT', 'nl') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Salie groen', value_type = 'TEXT';
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('ADMIN_CORE', 'modules/content-page/const/content-block', 'sky-blauw', 'Sky blauw', 'TEXT', 'en') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Sky blauw', value_type = 'TEXT';
Expand Down Expand Up @@ -5860,4 +5860,4 @@ INSERT INTO app.translations ("component", "location", "key", "value", "value_ty
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('FRONTEND', 'pages/zoeken/index', 'zoek-pagina-seo-omschrijving', 'Je kan op deze website centraal en online zoeken doorheen beschrijvingen van materiaal van meer dan 140 aanbieders, zonder dat je je hoeft te verplaatsen.', 'TEXT', 'nl') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Je kan op deze website centraal en online zoeken doorheen beschrijvingen van materiaal van meer dan 140 aanbieders, zonder dat je je hoeft te verplaatsen.', value_type = 'TEXT';
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('FRONTEND', 'pages/zoeken/index', 'zoek-pagina-seo-omschrijving', 'You can search centrally and online throughout descriptions of materials from more than 140 organisations without having to move.', 'TEXT', 'en') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'You can search centrally and online throughout descriptions of materials from more than 140 organisations without having to move.', value_type = 'TEXT';
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('FRONTEND', 'pages/zoeken/index', 'zoeken-pagina-titel', 'Search', 'TEXT', 'en') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Search', value_type = 'TEXT';
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('FRONTEND', 'pages/zoeken/index', 'zoeken-pagina-titel', 'Zoeken', 'TEXT', 'nl') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Zoeken', value_type = 'TEXT';
INSERT INTO app.translations ("component", "location", "key", "value", "value_type", "language") VALUES ('FRONTEND', 'pages/zoeken/index', 'zoeken-pagina-titel', 'Zoeken', 'TEXT', 'nl') ON CONFLICT (component, location, key, language) DO UPDATE SET value = 'Zoeken', value_type = 'TEXT';
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@use "../../../shared/styles/settings/colors" as colors;
@use "../../../shared/styles/utilities/background-text" as background-text;

.c-content-page-overview-block__header {
opacity: 0;
Expand Down Expand Up @@ -62,3 +63,19 @@
}
}
}

/* --------------------------------------------------------------------------
WCAG text colors on a content block's background color

ContentBlockRenderer sets --bg-text-primary / --bg-text-secondary / --bg-text-hyperlink from
the design record. The wrapper applies primary text by inheritance; elements that have their own
color rule are tagged explicitly with one of the role classes below. Rich-text containers use
u-background-text-links because their generated anchors cannot receive a React class directly.
https://meemoo.atlassian.net/browse/ARC-3848

ContentBlockRenderer emits the shared mixin in client.css; the utility index emits it separately
in admin.css. All role rules are scoped to u-background-text-colors, so AVO remains untouched.
Secondary and link roles fall back to primary when the design specifies no separate role color.
-------------------------------------------------------------------------- */

@include background-text.background-text-roles;
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ import { Container, Spacer } from '@viaa/avo2-components';

import clsx from 'clsx';
import { kebabCase, noop, omit } from 'es-toolkit';
import type { FunctionComponent, KeyboardEvent, RefObject } from 'react';
import type { CSSProperties, FunctionComponent, KeyboardEvent, RefObject } from 'react';
import React, { useCallback, useEffect, useRef } from 'react';
import { AdminConfigManager } from '~core/config/config.class';
import { getCommonUser } from '~core/config/config.selectors.ts';
import { GENERATED_CONTENT_BLOCK_ANCHOR_PREFIX } from '~modules/content-page/const/content-block-anchors.consts';
import type { ContentPageInfo } from '~modules/content-page/types/content-pages.types';
import { ContentPageWidth } from '~modules/content-page/types/content-pages.types';
import { generateSmartLink } from '~shared/components/SmartLink/SmartLink';
import { GET_DARK_BACKGROUND_COLOR_OPTIONS } from '../../const/get-color-options';
import { getBackgroundTextColorVariables } from '../../const/background-text-colors';
import { hasDarkBackground } from '../../const/get-color-options';
import {
Color,
type ContentBlockConfig,
Expand Down Expand Up @@ -122,9 +123,15 @@ const ContentBlockRenderer: FunctionComponent<ContentBlockPreviewProps> = ({
};
}

const hasDarkBg = GET_DARK_BACKGROUND_COLOR_OPTIONS().includes(
blockState?.backgroundColor || ('' as unknown as Color)
);
const hasDarkBg = hasDarkBackground(blockState?.backgroundColor);
// The Archief text colors specified for this background, published as css variables so text
// inside the block can take the primary, secondary or hyperlink role. On AVO this helper returns
// no variables, preserving AVO's own brand-book behavior.
// https://meemoo.atlassian.net/browse/ARC-3848
const textColorVariables = getBackgroundTextColorVariables(
blockState?.backgroundColor
) as CSSProperties;
const hasBackgroundTextColors = Object.keys(textColorVariables).length > 0;
const anchor =
blockState?.anchor?.replaceAll(' ', '-') ||
GENERATED_CONTENT_BLOCK_ANCHOR_PREFIX + contentBlockConfig.id;
Expand All @@ -146,6 +153,7 @@ const ContentBlockRenderer: FunctionComponent<ContentBlockPreviewProps> = ({
? Color.Transparent
: blockState?.backgroundColor,
...(blockState?.headerBackgroundColor !== Color.Transparent ? { zIndex: 1 } : {}),
...textColorVariables,
}}
data-anchor={anchor}
ref={blockRef}
Expand All @@ -161,11 +169,13 @@ const ContentBlockRenderer: FunctionComponent<ContentBlockPreviewProps> = ({
* to avoid overlapping a fixed header when we jump to this anchor
* https://meemoo.atlassian.net/browse/AVO-3351
*/}
<div className="c-content-block__anchor" id={anchor}></div>
<div className="c-content-block__anchor" id={anchor} />
<Spacer
className={clsx('c-content-block-preview', {
'c-content-block-preview--dark': hasDarkBg,
'u-color-white': hasDarkBg,
'u-background-text-colors': hasBackgroundTextColors,
// AVO has no Archief record and keeps its original blanket white text.
'u-color-white': hasDarkBg && !hasBackgroundTextColors,
})}
margin={[blockState?.margin?.top ?? 'none', blockState?.margin?.bottom ?? 'none']}
padding={[blockState?.padding?.top ?? 'none', blockState?.padding?.bottom ?? 'none']}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const BlockContentPageMeta: FunctionComponent<ContentPageMetaProps> = ({
// biome-ignore lint/suspicious/noExplicitAny: todo
return (labelObj as any).link_to ? (
<Button
className="u-background-text-hyperlink"
type="inline-link"
onClick={() =>
// biome-ignore lint/suspicious/noExplicitAny: todo
Expand Down Expand Up @@ -68,7 +69,7 @@ export const BlockContentPageMeta: FunctionComponent<ContentPageMetaProps> = ({

const publishedDate = getPublishedDate(contentPageInfo);
return (
<span>
<span className="u-background-text-secondary">
{tHtml(
'admin/content-block/components/wrappers/block-content-page-meta/block-content-page-meta___gepubliceerd-op'
)}{' '}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,24 @@ describe('<BlockHeading />', () => {
expect(heading).toHaveClass(customClass);
});

it('marks headings without an editor color as primary background text', () => {
render(<BlockHeading type="h2">Heading</BlockHeading>);

expect(screen.getByRole('heading', { level: 2 })).toHaveClass('u-background-text-primary');
});

it('preserves an explicit editor color instead of applying the background role', () => {
render(
<BlockHeading color="#123456" type="h2">
Heading
</BlockHeading>
);

const heading = screen.getByRole('heading', { level: 2 });
expect(heading).not.toHaveClass('u-background-text-primary');
expect(heading).toHaveStyle({ color: '#123456' });
});

it('Should correctly pass children', () => {
render(
<BlockHeading type="h1">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export const BlockHeading: FunctionComponent<BlockHeadingProps> = ({
<Type
className={clsx(className, `c-heading c-${Type}`, {
[`u-text-${align}`]: align !== 'left',
// Headings are primary text unless the editor supplied an explicit foreground color.
'u-background-text-primary': !color,
})}
onClick={onClick}
style={color ? { ...style, color } : style}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export const BlockHetArchiefHeaderSearch: FunctionComponent<BlockHetArchiefHeade
{subtitles.map((subtitle, index) => (
<li
key={`animation-text-${subtitle.label}-${index}`}
className={clsx({
className={clsx('u-background-text-primary', {
current: activeIndex === index,
next: activeIndex === (index - 1 + subtitles.length) % subtitles.length,
})}
Expand Down Expand Up @@ -103,7 +103,7 @@ export const BlockHetArchiefHeaderSearch: FunctionComponent<BlockHetArchiefHeade
onEnter={navigateToSearchPage}
value={searchTerm}
/>
<p>{textBelowSearch}</p>
<p className="u-background-text-secondary">{textBelowSearch}</p>
</div>
</article>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ export const BlockHetArchiefImageTextBackground: FunctionComponent<
// Only reads it once the image has finished loading — reading mid-load measures
// ~0px, which would shrink `.media` (and the image with it) with no way to
// recover, since a later re-measure would just report that same self-inflicted size.
// biome-ignore lint/correctness/useExhaustiveDependencies: refs are stable
const updateMediaMeasurements = useCallback(() => {
const imgEl = imgRef.current;
const measureEl = copyrightMeasureRef.current;
Expand Down Expand Up @@ -172,6 +171,7 @@ export const BlockHetArchiefImageTextBackground: FunctionComponent<
<BlockHeading
className="c-block-het-archief-image-text-background__heading"
type={headingType}
color={foregroundColor}
>
{heading}
</BlockHeading>
Expand Down Expand Up @@ -206,12 +206,7 @@ export const BlockHetArchiefImageTextBackground: FunctionComponent<
>
{image && (
<div className="c-block-het-archief-image-text-background__image">
<img
ref={imgRef}
src={image}
alt={imageAltText}
onLoad={updateMediaMeasurements}
/>
<img ref={imgRef} src={image} alt={imageAltText} onLoad={updateMediaMeasurements} />
</div>
)}
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@ import type { DefaultComponentProps } from '~modules/shared/types/components';
import './BlockHighligtText.scss';
import { Container } from '@viaa/avo2-components';
import clsx from 'clsx';
import { getBackgroundTextColorVariables } from '~modules/content-page/const/background-text-colors.ts';
import {
Color,
ColorSelectGradientColors,
CustomBackground,
type GradientColor,
} from '~modules/content-page/types/content-block.types';
import { ContentPageWidth } from '~modules/content-page/types/content-pages.types.ts';
import Html from '~shared/components/Html/Html.tsx';

export interface BlockHighlightTextProps extends DefaultComponentProps {
content: string;
highlightColor: string;
backgroundColor: string;
highlightColor: Color | GradientColor | CustomBackground;
backgroundColor: Color | GradientColor | CustomBackground;
pageWidth?: string;
}

Expand All @@ -29,6 +31,16 @@ export const BlockHighlightText: FunctionComponent<BlockHighlightTextProps> = ({
highlightColor === CustomBackground.MeemooLogo
? Color.Transparent
: ((ColorSelectGradientColors as Record<string, string>)[highlightColor] ?? highlightColor);
// Text colors follow the actual fill behind the content: gradients use the white content box,
// while the transparent meemoo logo variant keeps the outer block's inherited text color.
// https://meemoo.atlassian.net/browse/ARC-3848
const textBoxBackground = isGradient
? Color.White
: highlightColor === CustomBackground.MeemooLogo
? Color.Transparent
: highlightColor;
const textColorVariables = getBackgroundTextColorVariables(textBoxBackground);
const hasTextColors = Object.keys(textColorVariables).length > 0;

return (
<article
Expand Down Expand Up @@ -56,15 +68,18 @@ export const BlockHighlightText: FunctionComponent<BlockHighlightTextProps> = ({
/>
</div>
<Html
className="c-block-highlight-text__content-text"
className={clsx('c-block-highlight-text__content-text', {
'u-background-text-colors u-background-text-links': hasTextColors,
})}
style={
{
'--pattern-color': isGradient ? Color.White : patternColor,
'--pattern-color': textBoxBackground,
...textColorVariables,
} as CSSProperties
}
content={content}
type="p"
></Html>
/>
<div className="c-block-highlight-text__pattern-slot c-block-highlight-text__pattern-slot--bottom">
<div
className="c-block-highlight-text__pattern c-block-highlight-text__pattern--right"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ export const BlockHomepageBanner: FunctionComponent<BlockHomepageBannerProps> =
<BlockHeading className="c-block-homepage-banner__content-title" type="h4">
{title}
</BlockHeading>
<Html className="c-block-homepage-banner__content-text" content={content} type="p"></Html>
<Html
className="c-block-homepage-banner__content-text u-background-text-secondary u-background-text-links"
content={content}
type="p"
/>
<div className="c-block-homepage-banner__pattern-slot c-block-homepage-banner__pattern-slot--bottom">
<div
className="c-block-homepage-banner__pattern c-block-homepage-banner__pattern--right"
Expand Down
Loading