Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
cf396fd
copy webcore
emilysaffron Jan 14, 2026
a7ffec9
with logs
emilysaffron Jan 15, 2026
cc2e36f
fix build
emilysaffron Jan 15, 2026
c105ad8
memoise modal
emilysaffron Jan 15, 2026
7783bf3
remove unused memo
emilysaffron Jan 15, 2026
dc81069
remove need for memo and fix autpplay
emilysaffron Jan 20, 2026
6f62af5
player ref
emilysaffron Jan 20, 2026
d5d7637
fix build
emilysaffron Jan 20, 2026
63fc4f8
share url
emilysaffron Jan 20, 2026
75288f0
remove unnecessary things
emilysaffron Jan 20, 2026
2e6fbc8
return is lite check to correct place
emilysaffron Jan 20, 2026
6d1074f
rename shareurl
emilysaffron Jan 20, 2026
84c5399
Merge branch 'latest' into portraitvideoshare
emilysaffron Jan 20, 2026
92d3c40
use fabl to fetch shareUrl
emilysaffron Jan 21, 2026
074a5bf
Merge branch 'portraitvideoshare' of github.com:bbc/simorgh into port…
emilysaffron Jan 21, 2026
895ea4c
update share link on each swipe/click to next pv
emilysaffron Jan 21, 2026
163a2f5
Merge branch 'latest' into portraitvideoshare
emilysaffron Jan 21, 2026
d4db280
extract share button into components and use in overlay
emilysaffron Jan 21, 2026
6549edf
Merge branch 'portraitvideoshare' of github.com:bbc/simorgh into port…
emilysaffron Jan 21, 2026
331e32d
Merge branch 'latest' into portraitvideoshare
emilysaffron Jan 21, 2026
d1bbfed
fix build
emilysaffron Jan 21, 2026
a94e9aa
Merge branch 'portraitvideoshare' of github.com:bbc/simorgh into port…
emilysaffron Jan 21, 2026
9cb2068
show share button on hover
emilysaffron Jan 22, 2026
3c29d4d
Merge branch 'latest' into portraitvideoshare
emilysaffron Jan 22, 2026
1deecce
simplify setCurrentItem
emilysaffron Jan 22, 2026
0bc5abc
Merge branch 'portraitvideoshare' of github.com:bbc/simorgh into port…
emilysaffron Jan 22, 2026
c7870f9
wrap handleCloseModal in useCallback
emilysaffron Jan 22, 2026
3e28b6e
Merge branch 'latest' into portraitvideoshare
emilysaffron Jan 22, 2026
73b3fc6
Merge branch 'latest' into portraitvideoshare
emilysaffron Jan 22, 2026
09b87d2
Bring components in line with our coding standards
emilysaffron Feb 10, 2026
10be5f3
only load plugin for carousel
emilysaffron Feb 10, 2026
b3f78f9
check .enabled
emilysaffron Feb 10, 2026
e662677
Merge branch 'latest' into portraitvideoshare
emilysaffron Feb 10, 2026
e69cf7a
fix build error
emilysaffron Feb 10, 2026
66f183e
WS-2106: Updates click tracking data for share button
Isabella-Mitchell Feb 10, 2026
88bce64
Merge branch 'latest' into portraitvideoshare
emilysaffron Feb 10, 2026
75579f3
increase bundle size
emilysaffron Feb 10, 2026
d978d41
update unit test mock
emilysaffron Feb 10, 2026
126e3ae
prevent cypress fail
emilysaffron Feb 10, 2026
bbf05f0
Merge branch 'latest' into portraitvideoshare
emilysaffron Feb 11, 2026
b1e1e5a
WS-2095: Refactors tracking data
Isabella-Mitchell Feb 11, 2026
39178ec
WS-2095: Add type
Isabella-Mitchell Feb 11, 2026
fca41d0
WS-2095: Fix
Isabella-Mitchell Feb 11, 2026
f94f8a4
dont render button if no share url is available
emilysaffron Feb 11, 2026
1b01ff1
Merge branch 'portraitvideoshare' of github.com:bbc/simorgh into port…
emilysaffron Feb 11, 2026
82c54d1
dont render share button if the share api is not available
emilysaffron Feb 11, 2026
fd39dea
WS-2095: Refactors Share Button to be a shared component
Isabella-Mitchell Feb 11, 2026
a08d9c8
use plugin from simorgh static assets
emilysaffron Feb 11, 2026
953cc1c
Merge branch 'portraitvideoshare' of github.com:bbc/simorgh into port…
emilysaffron Feb 11, 2026
691cc76
Merge branch 'latest' into portraitvideoshare
emilysaffron Feb 11, 2026
ba13491
WS-2095: Updates tracking values for post share button for consistency
Isabella-Mitchell Feb 11, 2026
cacb25a
WS-2095: Constructs plugin link outside of useEffect
Isabella-Mitchell Feb 11, 2026
bd5324d
Merge branch 'latest' into portraitvideoshare
emilysaffron Feb 11, 2026
8a6de08
Merge branch 'latest' into portraitvideoshare
emilysaffron Feb 12, 2026
a71e13a
Merge branch 'latest' into portraitvideoshare
Isabella-Mitchell Feb 12, 2026
f233373
Merge branch 'latest' into portraitvideoshare
Isabella-Mitchell Feb 12, 2026
f869dcf
Merge branch 'latest' into portraitvideoshare
emilysaffron Feb 13, 2026
453178e
WS-2095: Fix merge
Isabella-Mitchell Feb 13, 2026
4983e96
Merge branch 'latest' into portraitvideoshare
emilysaffron Feb 13, 2026
acd5708
Merge branch 'latest' into portraitvideoshare
Isabella-Mitchell Feb 16, 2026
ee4df83
WS-2095: Adds test coverage [copilot]
Isabella-Mitchell Feb 16, 2026
ec6eeb9
WS-2095: Adds unit test coverage [copilot]
Isabella-Mitchell Feb 16, 2026
a5e9d34
WS-2095: Renames constants and functions for clarity
Isabella-Mitchell Feb 16, 2026
ccbc68c
WS-2095: Simplify early return
Isabella-Mitchell Feb 16, 2026
e7d0158
Merge branch 'latest' into portraitvideoshare
Isabella-Mitchell Feb 16, 2026
3c74673
WS-2095: Refactors early returns
Isabella-Mitchell Feb 16, 2026
cb54829
TEMP change: hasShareApi as const
Isabella-Mitchell Feb 16, 2026
93b645a
TEMP change: hasShareApi as const
Isabella-Mitchell Feb 16, 2026
deb8bd0
WS-2095: Tidies
Isabella-Mitchell Feb 16, 2026
ef4f2d5
WS-2095: Adds story
Isabella-Mitchell Feb 16, 2026
a4d7121
WS-2095: Fix
Isabella-Mitchell Feb 16, 2026
543bae7
WS-2095: Removes text from share button (UX review)
Isabella-Mitchell Feb 16, 2026
fa14632
WS-2095: Focus indicator styles fix
Isabella-Mitchell Feb 16, 2026
e825b64
WS-2095: Reverts navigator change to try fix safari bug
Isabella-Mitchell Feb 16, 2026
f82ac17
Revert "WS-2095: Reverts navigator change to try fix safari bug"
Isabella-Mitchell Feb 17, 2026
afc41de
WS-2095: Temp to debug, fetch plugin from PS
Isabella-Mitchell Feb 17, 2026
b989159
Revert "WS-2095: Temp to debug, fetch plugin from PS"
Isabella-Mitchell Feb 17, 2026
f3920fb
WS-2095: Temp, reflects plugin update on A11y swarm branch
Isabella-Mitchell Feb 17, 2026
bb45716
WS-2095: Temp, refactors fullScreenPlugin
Isabella-Mitchell Feb 17, 2026
6ee15c2
WS-2095: temp, cache bust for videoOverlayPlugin
Isabella-Mitchell Feb 17, 2026
375e0af
Merge branch 'latest' into portraitvideoshare
emilysaffron Feb 18, 2026
8130750
Merge branch 'latest' into portraitvideoshare
emilysaffron Feb 18, 2026
0ca3ba5
WS-2095: Temp, adds fullscreen plugin cache busting
Isabella-Mitchell Feb 18, 2026
9a88adf
WS-2095: Try fix issues on mobile
Isabella-Mitchell Feb 18, 2026
187a50c
WS-2095: debug
Isabella-Mitchell Feb 18, 2026
1c5f76d
setCurrentVideo using mediaItemChanged smp event
emilysaffron Feb 18, 2026
0a37863
temporary logs for preview
emilysaffron Feb 18, 2026
7a8986a
WS-2095: HCM hover focus styles
Isabella-Mitchell Feb 18, 2026
7fa5b9f
WS-2095: Updates visually hidden text
Isabella-Mitchell Feb 18, 2026
21c2636
Merge branch 'latest' into portraitvideoshare
emilysaffron Feb 19, 2026
c79a60d
WS-2095: UX update - align share button spacing with PS
Isabella-Mitchell Feb 19, 2026
5dabca2
Merge branch 'latest' into portraitvideoshare
emilysaffron Feb 20, 2026
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
2 changes: 1 addition & 1 deletion scripts/bundleSize/bundleSizeConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
export const VARIANCE = 5;

export const MIN_SIZE = 913;
export const MAX_SIZE = 1282;
export const MAX_SIZE = 1289;
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export default ({
plugins: {
toLoad: [
{
html: `${SIMORGH_PUBLIC_STATIC_ASSETS_ORIGIN}${SIMORGH_PUBLIC_STATIC_ASSETS_PATH}smpPlugins/fullscreen.js`,
html: `${SIMORGH_PUBLIC_STATIC_ASSETS_ORIGIN}${SIMORGH_PUBLIC_STATIC_ASSETS_PATH}smpPlugins/fullscreen.js?v=1`,
playerOnly: true,
},
],
Expand Down
66 changes: 62 additions & 4 deletions src/app/components/MediaLoader/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { use, useEffect, useRef, useState } from 'react';
import {
Dispatch,
RefObject,
SetStateAction,
use,
useEffect,
useRef,
useState,
} from 'react';
import { Helmet } from 'react-helmet';
import { RequestContext } from '#contexts/RequestContext';
import { MEDIA_PLAYER_STATUS } from '#app/lib/logger.const';
Expand All @@ -13,6 +21,7 @@ import {
import filterForBlockType from '#lib/utilities/blockHandlers';
import { PageTypes } from '#app/models/types/global';
import { EventTrackingContext } from '#app/contexts/EventTrackingContext';
import { getEnvConfig } from '#app/lib/utilities/getEnvConfig';
import {
BumpType,
EventMapping,
Expand Down Expand Up @@ -109,6 +118,10 @@ type MediaContainerProps = {
uniqueId?: string;
noJsMessage?: string;
eventMapping?: EventMapping;
setVideoOverlayContainerRef?: RefObject<
Dispatch<SetStateAction<HTMLElement | null>>
>;
playerKey: string;
};

const isAudioPlayer = (playerConfig: PlayerConfig) =>
Expand All @@ -120,11 +133,21 @@ const MediaContainer = ({
uniqueId,
noJsMessage,
eventMapping,
setVideoOverlayContainerRef,
playerKey,
}: MediaContainerProps) => {
const playerElementRef = useRef<HTMLDivElement>(null);
const isAudio = isAudioPlayer(playerConfig);

const playerKeyRef = useRef<string | null>(null);
const {
SIMORGH_PUBLIC_STATIC_ASSETS_ORIGIN,
SIMORGH_PUBLIC_STATIC_ASSETS_PATH,
} = getEnvConfig();
const videoOverlayPlugin = `${SIMORGH_PUBLIC_STATIC_ASSETS_ORIGIN}${SIMORGH_PUBLIC_STATIC_ASSETS_PATH}smpPlugins/video-overlay-plugin.js?v=1`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Temp- busts cache on preview

useEffect(() => {
if (!playerElementRef.current || playerKeyRef.current === playerKey) return;

playerKeyRef.current = playerKey;
try {
window.requirejs(['bump-4'], (Bump: BumpType) => {
if (playerElementRef?.current && playerConfig) {
Expand Down Expand Up @@ -185,7 +208,21 @@ const MediaContainer = ({
}
});
}

if (
setVideoOverlayContainerRef &&
playerConfig.ui?.swipable?.enabled
) {
mediaPlayer.loadPlugin(
{
html: videoOverlayPlugin,
playerOnly: true, // do not enable this plugin for old J2 version of the SMP player due to different UI },
waitOnPluginLoad: true,
},
{
setPluginContainer: setVideoOverlayContainerRef.current,
},
);
}
mediaPlayer.load();
};

Expand All @@ -195,7 +232,15 @@ const MediaContainer = ({
} catch (error) {
logger.error(MEDIA_PLAYER_STATUS, error);
}
}, [playerConfig, showAds, uniqueId, eventMapping]);
}, [
eventMapping,
playerConfig,
playerKey,
setVideoOverlayContainerRef,
showAds,
uniqueId,
videoOverlayPlugin,
]);

return (
<div
Expand All @@ -217,6 +262,9 @@ type Props = {
embedded?: boolean;
uniqueId?: string;
eventMapping?: EventMapping;
setVideoOverlayContainerRef?: RefObject<
Dispatch<SetStateAction<HTMLElement | null>>
>;
};

const MediaLoader = ({
Expand All @@ -225,6 +273,7 @@ const MediaLoader = ({
embedded,
uniqueId,
eventMapping,
setVideoOverlayContainerRef,
}: Props) => {
const { lang, service, translations } = use(ServiceContext);
const { pageIdentifier } = use(EventTrackingContext);
Expand Down Expand Up @@ -277,6 +326,13 @@ const MediaLoader = ({
ampIframeUrl,
} = config;

const { clipPID } = playerConfig?.statsObject || {};
const { skin } = playerConfig?.ui || {};

const playerKey = `${clipPID}-${skin}-${showAds}`;

if (isLite || !config || !playerConfig) return null;

const captionBlock = getCaptionBlock(blocks, pageType);
const isPortrait = orientation === 'portrait';
const isLandscape = orientation === 'landscape';
Expand Down Expand Up @@ -340,6 +396,8 @@ const MediaLoader = ({
uniqueId={uniqueId}
noJsMessage={noJsMessage}
eventMapping={eventMapping}
setVideoOverlayContainerRef={setVideoOverlayContainerRef}
playerKey={playerKey}
/>
)}
</>
Expand Down
22 changes: 17 additions & 5 deletions src/app/components/MediaLoader/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ import {
} from '#app/models/types/media';
import { OptimoImageBlock } from '#app/models/types/optimo';
import { Translations } from '#app/models/types/translations';
import { Dispatch, SetStateAction } from 'react';

export type SMPEvent = {
detail?: {
url?: string;
};
playlist?: {
items: PlaylistItem[];
};
Expand All @@ -23,7 +27,10 @@ export type MediaPlayerEvents =
| 'pluginLoaded'
| 'fullscreenExit'
| 'statsNavigation'
| 'pause';
| 'pause'
| 'uiControlBarShown'
| 'uiControlBarHidden'
| 'mediaItemChanged';

export type EventMapping = Partial<
Record<MediaPlayerEvents, (_e: SMPEvent) => void>
Expand All @@ -34,6 +41,7 @@ export type Playlist = {
summary?: string;
holdingImageURL?: string;
items: PlaylistItem[] | LegacyPlayListItem[];
shareUrl?: string | null;
guidance?: string;
embedRights?: 'allowed';
liveRewind?: boolean;
Expand Down Expand Up @@ -163,11 +171,14 @@ export type Player = {
next: () => void;
bind: (event: MediaPlayerEvents, callback: (e: SMPEvent) => void) => void;
loadPlugin: (
pluginName: { [key: string]: string },
pluginName: {
[key: string]: string | boolean | undefined;
},
parameters?: {
name: string;
data: {
adTag: string;
name?: string;
setPluginContainer?: Dispatch<SetStateAction<HTMLElement | null>>;
data?: {
adTag?: string;
};
},
) => void;
Expand Down Expand Up @@ -288,6 +299,7 @@ export type PortraitClipMediaBlock = {
altText?: string;
}[];
video: {
shareUrl?: string | null;
id: string;
title: string;
holdingImageURL?: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { css, Theme } from '@emotion/react';

const styles = {
overlayWrapper: () =>
css({
zIndex: 200,
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
containerType: 'inline-size',
containerName: 'overlayWrapper',
'@supports not (container-type: inline-size)': {
display: 'none',
},
}),
overlayFooterContents: ({ spacings }: Theme) =>
css({
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
gap: `${spacings.DOUBLE}rem`,
maxWidth: `77.5rem`,
margin: 'auto',
alignItems: 'flex-end',
}),
overlayFooter: ({ spacings }: Theme) =>
css({
position: 'absolute',
left: `${spacings.FULL}rem`,
right: `${spacings.FULL}rem`,
bottom: 0,
paddingBottom: '1rem',
'@supports not (container-type: inline-size)': {
display: 'none',
},

'@container overlayWrapper (min-width: 20rem)': {
paddingBottom: '5rem',
left: `${spacings.DOUBLE}rem`,
right: `${spacings.DOUBLE}rem`,
},

// @container (min-width: 500px)
'@container overlayWrapper (min-width: 31.25rem)': {
left: `${spacings.TRIPLE}rem`,
right: `${spacings.TRIPLE}rem`,
},

// @container (min-width: 860px)
'@container overlayWrapper (min-width: 53.75rem)': {
paddingBottom: '8.75rem',
left: `${spacings.DOUBLE}rem`,
right: `${spacings.DOUBLE}rem`,
},
}),
shareToolWrapper: () =>
css({
marginLeft: 'auto',
pointerEvents: 'auto',
}),
};

export default styles;
63 changes: 63 additions & 0 deletions src/app/components/PortraitVideoCarousel/VideoOverlay/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { useEffect, useState } from 'react';
import { EventTrackingData } from '#app/lib/analyticsUtils/types';
import { PortraitClipMediaBlock } from '#app/components/MediaLoader/types';
import ShareButton from '../../ShareButton';
import styles from './index.styles';

const ShareToolComponent = ({ shareUrlPath, title, id }) => {
const [shareUrl, setShareUrl] = useState('');

useEffect(() => {
setShareUrl(`https://bbc.com${shareUrlPath}`);
}, [shareUrlPath]);

const eventTrackingData: EventTrackingData = {
componentName: 'share-button-portrait-video-carousel',
itemTracker: {
resourceId: id,
},
};

return (
<div key={shareUrlPath} css={styles.shareToolWrapper}>
<ShareButton
title={title}
url={shareUrl}
eventTrackingData={eventTrackingData}
/>
</div>
);
};

const VideoOverlay = ({
currentVideo,
controlsDisplayed,
}: {
currentVideo: PortraitClipMediaBlock | undefined;
controlsDisplayed: boolean;
}) => {
const { shareUrl, title, id } = currentVideo?.model?.video || {};

return (
<div css={[styles.overlayWrapper, !shareUrl && 'display: none']}>
<div
className="video-overlay-footer fadedIn fadedOut"
// The video-overlay plugin will use this attribute to instruct SMP not to render subtitles in the space occupied by this div.
data-region-exclude-subtitles
css={[
styles.overlayFooter,
controlsDisplayed ? 'opacity: 1' : 'opacity: 0',
]}
>
<div
className="video-overlay-footer-contents"
css={styles.overlayFooterContents}
>
<ShareToolComponent shareUrlPath={shareUrl} title={title} id={id} />
</div>
</div>
</div>
);
};

export default VideoOverlay;
Loading
Loading