diff --git a/dotcom-rendering/src/components/AudioPlayer.tsx b/dotcom-rendering/src/components/AudioPlayer.tsx new file mode 100644 index 00000000000..ddb489b8f96 --- /dev/null +++ b/dotcom-rendering/src/components/AudioPlayer.tsx @@ -0,0 +1,52 @@ +import { css } from '@emotion/react'; +import { space } from '@guardian/source/foundations'; +import { StraightLines } from '@guardian/source-development-kitchen/react-components'; +import { palette } from '../palette'; +import { AppsAudioPlayer } from './AppsAudioPlayer.island'; +import { AudioPlayerWrapper } from './AudioPlayerWrapper.island'; +import { formatAudioDuration } from './ListenToArticle.island'; + +export const AudioPlayer = ({ + audioData, + isSensitive, + isAcastEnabled, + isApps, +}: { + audioData: { + audioDownloadUrl: string; + durationSeconds?: number; + mediaId: string; + }; + isSensitive: boolean; + isAcastEnabled: boolean; + isApps: boolean; +}) => { + return ( + <> + {isApps ? ( + + ) : ( + + )} + + > + ); +}; diff --git a/dotcom-rendering/src/layouts/AudioLayout.stories.tsx b/dotcom-rendering/src/layouts/AudioLayout.stories.tsx index 9227a2e43d9..9b13f7271c8 100644 --- a/dotcom-rendering/src/layouts/AudioLayout.stories.tsx +++ b/dotcom-rendering/src/layouts/AudioLayout.stories.tsx @@ -5,12 +5,12 @@ import { ArticleDesign } from '../lib/articleFormat'; import { getCurrentPillar } from '../lib/layoutHelpers'; import { extractNAV } from '../model/extract-nav'; import { enhanceArticleType } from '../types/article'; -import { AudioLayout } from './AudioLayout'; +import { StandardLayout } from './StandardLayout'; const meta = { title: 'Layouts/Audio', - component: AudioLayout, -} satisfies Meta; + component: StandardLayout, +} satisfies Meta; export default meta; diff --git a/dotcom-rendering/src/layouts/AudioLayout.tsx b/dotcom-rendering/src/layouts/AudioLayout.tsx deleted file mode 100644 index 94aebed7489..00000000000 --- a/dotcom-rendering/src/layouts/AudioLayout.tsx +++ /dev/null @@ -1,757 +0,0 @@ -import { css } from '@emotion/react'; -import { - from, - palette as sourcePalette, - space, - until, -} from '@guardian/source/foundations'; -import { StraightLines } from '@guardian/source-development-kitchen/react-components'; -import { AdPortals } from '../components/AdPortals.island'; -import { AdSlot, MobileStickyContainer } from '../components/AdSlot.web'; -import { AffiliateDisclaimer } from '../components/AffiliateDisclaimer'; -import { AppsAudioPlayer } from '../components/AppsAudioPlayer.island'; -import { AppsFooter } from '../components/AppsFooter.island'; -import { ArticleBody } from '../components/ArticleBody'; -import { ArticleContainer } from '../components/ArticleContainer'; -import { ArticleHeadline } from '../components/ArticleHeadline'; -import { ArticleMetaApps } from '../components/ArticleMeta.apps'; -import { ArticleMeta } from '../components/ArticleMeta.web'; -import { ArticleTitle } from '../components/ArticleTitle'; -import { AudioPlayerWrapper } from '../components/AudioPlayerWrapper.island'; -import { Border } from '../components/Border'; -import { Carousel } from '../components/Carousel.island'; -import { DirectoryPageNavIsland } from '../components/DirectoryPageNavIsland'; -import { DiscussionLayout } from '../components/DiscussionLayout'; -import { Footer } from '../components/Footer'; -import { GridItem } from '../components/GridItem'; -import { HeaderAdSlot } from '../components/HeaderAdSlot'; -import { Island } from '../components/Island'; -import { LabsHeader } from '../components/LabsHeader'; -import { formatAudioDuration } from '../components/ListenToArticle.island'; -import { Masthead } from '../components/Masthead/Masthead'; -import { MostViewedFooterData } from '../components/MostViewedFooterData.island'; -import { MostViewedFooterLayout } from '../components/MostViewedFooterLayout'; -import { MostViewedRightWithAd } from '../components/MostViewedRightWithAd.island'; -import { OnwardsUpper } from '../components/OnwardsUpper.island'; -import { RightColumn } from '../components/RightColumn'; -import { Section } from '../components/Section'; -import { SlotBodyEnd } from '../components/SlotBodyEnd.island'; -import { Standfirst } from '../components/Standfirst'; -import { StickyBottomBanner } from '../components/StickyBottomBanner.island'; -import { SubMeta } from '../components/SubMeta'; -import { SubNav } from '../components/SubNav.island'; -import { type ArticleFormat, ArticleSpecial } from '../lib/articleFormat'; -import { getAudioData } from '../lib/audio-data'; -import { canRenderAds } from '../lib/canRenderAds'; -import { getContributionsServiceUrl } from '../lib/contributions'; -import { decideStoryPackageTrails } from '../lib/decideTrail'; -import { parse } from '../lib/slot-machine-flags'; -import { worldCupTagId } from '../lib/worldCup2026'; -import type { NavType } from '../model/extract-nav'; -import { palette as themePalette } from '../palette'; -import type { ArticleDeprecated } from '../types/article'; -import type { RenderingTarget } from '../types/renderingTarget'; -import { BannerWrapper, Stuck } from './lib/stickiness'; - -const AudioGrid = ({ children }: { children: React.ReactNode }) => ( - - {children} - -); - -const maxWidth = css` - ${from.desktop} { - max-width: 620px; - } -`; - -interface Props { - article: ArticleDeprecated; - format: ArticleFormat; - renderingTarget: RenderingTarget; - serverTime?: number; -} - -interface WebProps extends Props { - NAV: NavType; - renderingTarget: 'Web'; -} - -interface AppProps extends Props { - renderingTarget: 'Apps'; -} - -export const AudioLayout = (props: WebProps | AppProps) => { - const { article, format, renderingTarget, serverTime } = props; - const isWeb = renderingTarget === 'Web'; - const isApps = renderingTarget === 'Apps'; - const audioData = getAudioData(article.mainMediaElements); - - const { - config: { isPaidContent, host, hasSurveyAd }, - editionId, - } = article; - - const showBodyEndSlot = parse(article.slotMachineFlags ?? '').showBodyEnd; - - const showComments = article.isCommentable && !isPaidContent; - - const { branding } = article.commercialProperties[article.editionId]; - - const contributionsServiceUrl = getContributionsServiceUrl(article); - - const isLabs = format.theme === ArticleSpecial.Labs; - - const isWorldCup2026 = article.tags.some((tag) => tag.id === worldCupTagId); - - const renderAds = canRenderAds(article); - - return ( - <> - {isWeb && ( - - {renderAds && ( - - - - - - )} - tag.id)} - contentType={article.contentType} - /> - - )} - - {isWeb && format.theme === ArticleSpecial.Labs && ( - - - - - - )} - - {isWeb && renderAds && hasSurveyAd && ( - - )} - - - {isApps && renderAds && ( - - - - )} - - - - - - - - - {format.theme === ArticleSpecial.Labs ? ( - <>> - ) : ( - - )} - - - - - - - - - {renderingTarget === 'Web' ? ( - - ) : ( - - )} - {!!article.affiliateLinksDisclaimer && ( - - )} - - - - {isWeb && audioData && ( - - - - )} - {isApps && audioData && ( - - - - )} - - - - - - - - - {isWeb && showBodyEndSlot && ( - - - - )} - - - - - - {isWeb && ( - - - - - - - - )} - - - - - {isWeb && renderAds && !isLabs && ( - - - - )} - - {article.storyPackage && ( - - - - - - )} - - - - - {isWeb && showComments && ( - - - - )} - - {!isPaidContent && ( - - - - - - - - )} - - {isWeb && renderAds && !isLabs && ( - - - - )} - - - {isWeb && ( - <> - {props.NAV.subNavSections && ( - - - - - - )} - - - - - - - - - {renderAds && ( - - )} - > - )} - {isApps && ( - - - - - - )} - > - ); -}; diff --git a/dotcom-rendering/src/layouts/DecideLayout.tsx b/dotcom-rendering/src/layouts/DecideLayout.tsx index b6dd7f4a27c..7724a3dbd64 100644 --- a/dotcom-rendering/src/layouts/DecideLayout.tsx +++ b/dotcom-rendering/src/layouts/DecideLayout.tsx @@ -2,7 +2,6 @@ import { ArticleDesign, ArticleDisplay } from '../lib/articleFormat'; import type { NavType } from '../model/extract-nav'; import type { Article } from '../types/article'; import type { RenderingTarget } from '../types/renderingTarget'; -import { AudioLayout } from './AudioLayout'; import { CommentLayout } from './CommentLayout'; import { CrosswordLayout } from './CrosswordLayout'; import { FullPageInteractiveLayout } from './FullPageInteractiveLayout'; @@ -191,7 +190,7 @@ const DecideLayoutApps = ({ article, renderingTarget }: AppProps) => { ); case ArticleDesign.Audio: return ( - { ); case ArticleDesign.Audio: return ( - { format.design === ArticleDesign.Video || format.design === ArticleDesign.Audio; - const isVideo = format.design === ArticleDesign.Video; - const isShowcase = format.display === ArticleDisplay.Showcase; const showComments = article.isCommentable && !isPaidContent; @@ -181,6 +181,8 @@ export const StandardLayout = (props: WebProps | AppProps) => { const renderAds = canRenderAds(article); + const audioData = getAudioData(article.mainMediaElements); + const layoutType: LayoutType = isMedia ? 'media' : isShowcase @@ -283,25 +285,36 @@ export const StandardLayout = (props: WebProps | AppProps) => { ]} > - + {audioData ? ( + + ) : ( + + )} { layoutType={layoutType} element="aside" > - - {isWeb && - format.theme === ArticleSpecial.Labs && - format.design !== ArticleDesign.Video ? ( - - ) : ( - - )} - + {!audioData && ( + + {isWeb && + format.theme === ArticleSpecial.Labs && + format.design !== ArticleDesign.Video ? ( + + ) : ( + + )} + + )} {isApps ? ( <> @@ -452,7 +469,7 @@ export const StandardLayout = (props: WebProps | AppProps) => { {/* Only show Listen to Article button on App landscape views */} {isApps && ( - {!isVideo && ( + {!isMedia && ( { !!article.config .shouldHideReaderRevenue } + shouldHideMostViewed={!!audioData} />