diff --git a/src/app/components/Curation/HighImpactPromo/README.md b/src/app/components/Curation/HighImpactPromo/README.md
index d37bef10a27..8d529e1a8b2 100644
--- a/src/app/components/Curation/HighImpactPromo/README.md
+++ b/src/app/components/Curation/HighImpactPromo/README.md
@@ -18,22 +18,22 @@ Typically used when editors set a curation item's prominence to "Maximum" in Tip
- Renders promotional content with enhanced visual styling.
- Integrates with the existing Standard Grid flow.
- Provides clear visual distinction from standard curation items.
-- Attribution is automatically derived from the service context (e.g., brand name and service URL) but can be overridden with the `attribution` prop.
+- Subject link is derived from `relatedTopic` when present, otherwise it falls back to service context (brand name and service URL).
---
## Props
-| Prop | Type | Required | Description |
-| ------------------- | ------- | -------- | --------------------------------------------------------------------- |
-| `title` | string | Yes | The promotional headline. |
-| `link` | string | Yes | URL destination for the promo. |
-| `imageUrl` | string | Yes | Image URL for the promotional content. |
-| `imageAlt` | string | Yes | Alt text for the promotional image. |
-| `lazy` | boolean | No | Enables lazy loading for the image. |
-| `headingLevel` | number | No | The heading level for the title (defaults to 3). |
-| `eventTrackingData` | object | No | Tracking metadata for analytics. |
-| `attribution` | object | No | An object with `text` and `link` to override the default attribution. |
+| Prop | Type | Required | Description |
+| ------------------- | ------- | -------- | ---------------------------------------------------------------- |
+| `title` | string | Yes | The promotional headline. |
+| `link` | string | Yes | URL destination for the promo. |
+| `imageUrl` | string | Yes | Image URL for the promotional content. |
+| `imageAlt` | string | Yes | Alt text for the promotional image. |
+| `lazy` | boolean | No | Enables lazy loading for the image. |
+| `headingLevel` | number | No | The heading level for the title (defaults to 3). |
+| `eventTrackingData` | object | No | Tracking metadata for analytics. |
+| `relatedTopic` | object | No | An object with `title` and `link.url` used for the subject link. |
---
diff --git a/src/app/components/Curation/HighImpactPromo/index.stories.tsx b/src/app/components/Curation/HighImpactPromo/index.stories.tsx
index 48fe2d3413e..af2f8dad613 100644
--- a/src/app/components/Curation/HighImpactPromo/index.stories.tsx
+++ b/src/app/components/Curation/HighImpactPromo/index.stories.tsx
@@ -5,56 +5,47 @@ import metadata from './metadata.json';
import readme from './README.md';
const highImpactFixtureCuration = fixture.data.curations[0] as BaseCuration;
+const baseProps = highImpactFixtureCuration.summaries?.[0] as Summary;
-const Component = () => {
- return (
-
-
-
-
-
- );
-};
+interface ExternalProps {
+ relatedTopic?: { title: string; link: { url: string } } | null;
+}
+
+const Component = ({ relatedTopic }: ExternalProps) => (
+
+);
export default {
title: 'Components/Curation/High Impact Promo',
- component: Component,
+ Component,
+ decorators: [
+ Story => (
+
+
+
+ ),
+ ],
parameters: {
metadata,
docs: { readme },
chromatic: { disable: true },
},
+ args: {
+ relatedTopic: {
+ title: 'Related Topic Example',
+ link: { url: '/topic/example' },
+ },
+ },
+ argTypes: {
+ relatedTopic: { control: 'object' },
+ },
};
-export const Example = {};
+export const Example = Component;
diff --git a/src/app/components/Curation/HighImpactPromo/index.test.tsx b/src/app/components/Curation/HighImpactPromo/index.test.tsx
index f96b2b0a79f..f22d0850900 100644
--- a/src/app/components/Curation/HighImpactPromo/index.test.tsx
+++ b/src/app/components/Curation/HighImpactPromo/index.test.tsx
@@ -12,18 +12,18 @@ const promoFixtureData = summaries?.[0] as HighImpactPromoProps;
interface FixtureProps {
promoData?: HighImpactPromoProps;
headingLevel?: number;
- attributions?: { title: string; link: { url: string } }[] | null;
+ relatedTopic?: { title: string; link: { url: string } } | null | undefined;
}
const Fixture = ({
promoData = promoFixtureData,
headingLevel,
- attributions,
+ relatedTopic,
}: FixtureProps) => (
);
@@ -64,16 +64,16 @@ describe('High Impact Promo', () => {
);
});
- it('should render default values if attribution prop is not provided', () => {
+ it('should render default subject values when relatedTopic prop is not provided', () => {
render(, { service: 'mundo' });
- const attributionLink = screen.getByRole('link', {
+ const subjectLink = screen.getByRole('link', {
name: 'BBC News Mundo',
});
- expect(attributionLink).toBeInTheDocument();
- expect(attributionLink).toHaveAttribute('href', '/mundo');
+ expect(subjectLink).toBeInTheDocument();
+ expect(subjectLink).toHaveAttribute('href', '/mundo');
- const divider = attributionLink.previousElementSibling;
+ const divider = subjectLink.previousElementSibling;
expect(divider).toBeInTheDocument();
expect(divider).toHaveStyle({
'background-color': '#EB0000',
@@ -82,39 +82,6 @@ describe('High Impact Promo', () => {
});
});
- it('should render correct attribution when an attributions prop is provided', () => {
- const customAttributions = [
- {
- title: 'Pidgin Related Topic',
- link: { url: '/pidgin/topics/234567' },
- },
- ];
- render();
-
- const attributionLink = screen.getByRole('link', {
- name: 'Pidgin Related Topic',
- });
- expect(attributionLink).toBeInTheDocument();
- expect(attributionLink).toHaveAttribute('href', '/pidgin/topics/234567');
- });
- it('should render default attribution when attributions prop is null', () => {
- render(, { service: 'mundo' });
- const attributionLink = screen.getByRole('link', {
- name: 'BBC News Mundo',
- });
- expect(attributionLink).toBeInTheDocument();
- expect(attributionLink).toHaveAttribute('href', '/mundo');
- });
-
- it('should render default attribution when attributions prop is an empty array', () => {
- render(, { service: 'mundo' });
- const attributionLink = screen.getByRole('link', {
- name: 'BBC News Mundo',
- });
- expect(attributionLink).toBeInTheDocument();
- expect(attributionLink).toHaveAttribute('href', '/mundo');
- });
-
it.each<[Services, string]>([
['mundo', 'ltr'],
['arabic', 'rtl'],
@@ -123,4 +90,21 @@ describe('High Impact Promo', () => {
const promo = screen.getByTestId('high-impact-promo');
expect(promo).toHaveAttribute('dir', dir);
});
+
+ it('should render relatedTopic when provided', () => {
+ const relatedTopic = {
+ title: 'Россия',
+ link: { url: 'https://www.bbc.com/russian/topics/cw6eyw7m0m1t' },
+ };
+ render();
+
+ const relatedTopicLink = screen.getByRole('link', {
+ name: 'Россия',
+ });
+ expect(relatedTopicLink).toBeInTheDocument();
+ expect(relatedTopicLink).toHaveAttribute(
+ 'href',
+ 'https://www.bbc.com/russian/topics/cw6eyw7m0m1t',
+ );
+ });
});
diff --git a/src/app/components/Curation/HighImpactPromo/index.tsx b/src/app/components/Curation/HighImpactPromo/index.tsx
index c8d75ab8dcd..67b9d96b456 100644
--- a/src/app/components/Curation/HighImpactPromo/index.tsx
+++ b/src/app/components/Curation/HighImpactPromo/index.tsx
@@ -7,19 +7,19 @@ import { ServiceContext } from '#app/contexts/ServiceContext';
import { getBrandPath } from '#app/legacy/containers/Brand';
import styles from './index.styles';
-type AttributionLink = {
+type RelatedTopicLink = {
url: string;
scheme?: string;
host?: string;
path?: string;
};
-type Attribution = {
+type RelatedTopic = {
+ link: RelatedTopicLink;
title: string;
- link: AttributionLink;
};
export interface HighImpactPromoProps extends Summary {
- attributions?: Attribution[] | null;
+ relatedTopic?: RelatedTopic | null;
}
const HighImpactPromo = ({
@@ -30,16 +30,15 @@ const HighImpactPromo = ({
link,
headingLevel = 3,
eventTrackingData,
- attributions,
+ relatedTopic,
}: HighImpactPromoProps) => {
const { isAmp } = use(RequestContext);
const { dir, service, brandName } = use(ServiceContext) || {};
- const [firstAttribution] = attributions || [];
- const attributionLink =
- firstAttribution?.link?.url || (service ? getBrandPath(service) : null);
- const attributionText = firstAttribution?.title || brandName;
- const hasAttribution = Boolean(attributionLink && attributionText);
+ const subjectLink =
+ relatedTopic?.link?.url || (service ? getBrandPath(service) : undefined);
+ const subjectText = relatedTopic?.title || brandName;
+ const hasSubject = Boolean(subjectLink && subjectText);
const clickTrackerHandler = useClickTrackerHandler(eventTrackingData);
@@ -65,14 +64,14 @@ const HighImpactPromo = ({
{title}
- {hasAttribution && }
- {hasAttribution && attributionLink && (
+ {hasSubject && }
+ {hasSubject && (
- {attributionText}
+ {subjectText}
)}