diff --git a/cardigan/stories/components/Cards/FeaturedCard/FeaturedCard.stories.tsx b/cardigan/stories/components/Cards/FeaturedCard/FeaturedCard.stories.tsx index 05513eceea..add7842135 100644 --- a/cardigan/stories/components/Cards/FeaturedCard/FeaturedCard.stories.tsx +++ b/cardigan/stories/components/Cards/FeaturedCard/FeaturedCard.stories.tsx @@ -1,22 +1,56 @@ import { Meta, StoryObj } from '@storybook/react'; import { ReadmeDecorator } from '@weco/cardigan/config/decorators'; +import { + contentAPIArticle, + exhibitionBasic, +} from '@weco/cardigan/stories/data/content'; import { image } from '@weco/cardigan/stories/data/images'; import { font } from '@weco/common/utils/classnames'; -import FeaturedCard from '@weco/content/components/FeaturedCard/FeaturedCard'; +import FeaturedCard from '@weco/content/components/FeaturedCard'; import Readme from '@weco/content/components/FeaturedCard/README.mdx'; const meta: Meta = { title: 'Components/Cards/FeaturedCard', component: FeaturedCard, args: { + type: 'card', image: image(), - labels: [{ text: 'Article' }], + labels: [{ text: 'Page' }], link: { url: '#', text: 'Remote diagnosis from wee to the web' }, background: 'neutral.700', textColor: 'white', isReversed: false, }, + argTypes: { + type: { + options: ['card', 'exhibition', 'article'], + control: { type: 'radio' }, + }, + background: { + options: ['neutral.700', 'warmNeutral.300'], + control: { type: 'select' }, + }, + textColor: { + options: ['white', 'black'], + control: { type: 'select' }, + }, + labels: { + table: { + disable: true, + }, + }, + link: { + table: { + disable: true, + }, + }, + image: { + table: { + disable: true, + }, + }, + }, }; export default meta; @@ -24,26 +58,27 @@ export default meta; type Story = StoryObj; export const Basic: Story = { name: 'FeaturedCard', - render: args => ( - -

Remote diagnosis from wee to the Web

-

- Medical practice might have moved on from when patients posted flasks of - their urine for doctors to taste, but telehealth today keeps up the - tradition of remote diagnosis – to our possible detriment. -

-
- ), + render: args => { + return ( + +

Remote diagnosis from wee to the Web

+

+ Medical practice might have moved on from when patients posted flasks + of their urine for doctors to taste, but telehealth today keeps up the + tradition of remote diagnosis – to our possible detriment. +

+
+ ); + }, }; diff --git a/cardigan/stories/data/content.ts b/cardigan/stories/data/content.ts index 6044b06d6c..a2eb6e3616 100644 --- a/cardigan/stories/data/content.ts +++ b/cardigan/stories/data/content.ts @@ -2,7 +2,11 @@ import { faker } from '@faker-js/faker'; import untransformedBody from '@weco/cardigan/stories/data/untransformed-body'; import { Props as QuoteProps } from '@weco/content/components/Quote/Quote'; -import { Article, ArticleBasic } from '@weco/content/types/articles'; +import { Article } from '@weco/content/services/wellcome/content/types/api'; +import { + ArticleBasic, + Article as TransformedPrismicArticle, +} from '@weco/content/types/articles'; import { Organisation as OrganisationType, Person as PersonType, @@ -12,6 +16,7 @@ import { ExhibitionBasic } from '@weco/content/types/exhibitions'; import { Season } from '@weco/content/types/seasons'; import { + contentAPIImage, darkCloudImageUrl, florenceWinterfloodImageUrl, image, @@ -257,7 +262,7 @@ export const organisation: OrganisationType = { sameAs: [], }; -export const article: Article = { +export const article: TransformedPrismicArticle = { type: 'articles', id: 'YLoCLhAAACEAfyuO', uid: 'a-dark-cloud', @@ -466,5 +471,49 @@ export const exhibitionBasic: ExhibitionBasic = { end: new Date('2021-09-29T23:00:00+0000'), isPermanent: false, contributors: [], - labels: [], + labels: [{ text: 'Exhibition' }], +}; + +export const contentAPIArticle: Article = { + type: 'Article', + id: 'Zz2g4BAAAB8AAs0L', + uid: 'the-personal-cost-of-mental-illness', + title: 'The personal cost of mental illness', + caption: + 'Laura Grace Simpkins is tired of hearing how much her mental ill health costs the country. What about how much it costs her?', + format: { + type: 'ArticleFormat', + id: 'W7TfJRAAAJ1D0eLK', + label: 'Article', + }, + publicationDate: '2024-12-11T10:00:07+0000', + contributors: [ + { + type: 'Contributor', + contributor: { + type: 'Person', + id: 'YRpIOREAANdN3wpG', + label: 'Laura Grace Simpkins', + }, + role: { + type: 'EditorialContributorRole', + id: 'WcUWeCgAAFws-nGh', + label: 'Author', + }, + }, + { + type: 'Contributor', + contributor: { + type: 'Person', + id: 'Yw8WwhAAADhyTh92', + label: 'Tanya Cooper', + }, + role: { + type: 'EditorialContributorRole', + id: 'YEu7zhAAACMAX7IG', + label: 'Artist', + }, + }, + ], + image: contentAPIImage, }; diff --git a/cardigan/stories/data/images.ts b/cardigan/stories/data/images.ts index d0ab197f3a..f6a4bec0d7 100644 --- a/cardigan/stories/data/images.ts +++ b/cardigan/stories/data/images.ts @@ -3,6 +3,7 @@ import { LicenseType } from '@weco/common/model/license'; import { Picture } from '@weco/common/model/picture'; import { CaptionedImageProps } from '@weco/content/components/CaptionedImage/CaptionedImage'; import { Props as ImageGalleryProps } from '@weco/content/components/ImageGallery'; +import { ContentApiImage } from '@weco/content/services/wellcome/content/types/api'; import { singleLineOfText } from './text'; @@ -112,3 +113,73 @@ export const imageWithCrops = { }, }, }; + +export const contentAPIImage: ContentApiImage = { + type: 'PrismicImage', + dimensions: { + width: 3543, + height: 1993, + }, + alt: 'A collage combining photos and illustration featuring a woman in a blue hairnet.', + copyright: + 'The personal cost of mental illness | Tanya Cooper for Wellcome Collection | | | CC-BY-NC-ND | |', + url: 'https://images.prismic.io/wellcomecollection/Z1BdtpbqstJ98BwR_WellcomeCollection_Main.jpg?auto=format,compress', + id: 'Z1BdtpbqstJ98BwR', + edit: { + x: 0, + y: 0, + zoom: 1, + background: 'transparent', + }, + '32:15': { + dimensions: { + width: 3200, + height: 1500, + }, + alt: 'A collage combining photos and illustration featuring a woman in a blue hairnet.', + copyright: + 'The personal cost of mental illness | Tanya Cooper for Wellcome Collection | | | CC-BY-NC-ND | |', + url: florenceWinterfloodImageUrl('3200x1500'), + id: 'Z1BdtpbqstJ98BwR', + edit: { + x: 0, + y: 166, + zoom: 1, + background: 'transparent', + }, + }, + '16:9': { + dimensions: { + width: 3200, + height: 1800, + }, + alt: 'A collage combining photos and illustration featuring a woman in a blue hairnet.', + copyright: + 'The personal cost of mental illness | Tanya Cooper for Wellcome Collection | | | CC-BY-NC-ND | |', + url: florenceWinterfloodImageUrl('3200x1800'), + id: 'Z1BdtpbqstJ98BwR', + edit: { + x: 0, + y: 0, + zoom: 1, + background: 'transparent', + }, + }, + square: { + dimensions: { + width: 3200, + height: 3200, + }, + alt: 'A collage combining photos and illustration featuring a woman in a blue hairnet.', + copyright: + 'The personal cost of mental illness | Tanya Cooper for Wellcome Collection | | | CC-BY-NC-ND | |', + url: florenceWinterfloodImageUrl('3200x3200'), + id: 'Z1BdtpbqstJ98BwR', + edit: { + x: 775, + y: 0, + zoom: 1, + background: 'transparent', + }, + }, +}; diff --git a/content/webapp/components/Body/Body.tsx b/content/webapp/components/Body/Body.tsx index 8afcc205fc..fc7bf3e3c7 100644 --- a/content/webapp/components/Body/Body.tsx +++ b/content/webapp/components/Body/Body.tsx @@ -26,7 +26,7 @@ import { Props as ComicPreviousNextProps } from '@weco/content/components/ComicP import FeaturedCard, { convertCardToFeaturedCardProps, convertItemToFeaturedCardProps, -} from '@weco/content/components/FeaturedCard/FeaturedCard'; +} from '@weco/content/components/FeaturedCard'; import FeaturedText from '@weco/content/components/FeaturedText/FeaturedText'; import { defaultSerializer } from '@weco/content/components/HTMLSerializers/HTMLSerializers'; import OnThisPageAnchors from '@weco/content/components/OnThisPageAnchors/OnThisPageAnchors'; diff --git a/content/webapp/components/FeaturedCard/FeaturedCard.helpers.ts b/content/webapp/components/FeaturedCard/FeaturedCard.helpers.ts new file mode 100644 index 0000000000..b36c77e9a6 --- /dev/null +++ b/content/webapp/components/FeaturedCard/FeaturedCard.helpers.ts @@ -0,0 +1,68 @@ +import { ImageType } from '@weco/common/model/image'; +import { Label } from '@weco/common/model/labels'; +import linkResolver from '@weco/common/services/prismic/link-resolver'; +import { ArticleBasic } from '@weco/content/types/articles'; +import { BookBasic } from '@weco/content/types/books'; +import { Card } from '@weco/content/types/card'; +import { EventSeries } from '@weco/content/types/event-series'; +import { EventBasic } from '@weco/content/types/events'; +import { ExhibitionBasic } from '@weco/content/types/exhibitions'; +import { Guide } from '@weco/content/types/guides'; +import { Link } from '@weco/content/types/link'; +import { Page } from '@weco/content/types/pages'; +import { Season } from '@weco/content/types/seasons'; +import { SeriesBasic } from '@weco/content/types/series'; + +export type PartialFeaturedCard = { + image?: ImageType; + labels: Label[]; + link: Link; +}; + +export function convertCardToFeaturedCardProps( + item: Card +): PartialFeaturedCard { + return { + // We intentionally omit the alt text on promos, so screen reader + // users don't have to listen to the alt text before hearing the + // title of the item in the list. + // + // See https://github.com/wellcomecollection/wellcomecollection.org/issues/6007 + image: item.image && { + ...item.image, + alt: '', + }, + labels: item.format ? [{ text: item.format.title }] : [], + link: { url: item.link || '', text: item.title || '' }, + }; +} + +export function convertItemToFeaturedCardProps( + item: + | ArticleBasic + | ExhibitionBasic + | Season + | Page + | EventSeries + | BookBasic + | SeriesBasic + | EventBasic + | Guide +): PartialFeaturedCard { + return { + image: item.promo?.image && { + ...item.promo.image, + // We intentionally omit the alt text on promos, so screen reader + // users don't have to listen to the alt text before hearing the + // title of the item in the list. + // + // See https://github.com/wellcomecollection/wellcomecollection.org/issues/6007 + alt: '', + }, + labels: item.labels, + link: { + url: linkResolver(item), + text: item.title, + }, + }; +} diff --git a/content/webapp/components/FeaturedCard/FeaturedCard.styles.ts b/content/webapp/components/FeaturedCard/FeaturedCard.styles.ts new file mode 100644 index 0000000000..c1a86e2b49 --- /dev/null +++ b/content/webapp/components/FeaturedCard/FeaturedCard.styles.ts @@ -0,0 +1,96 @@ +import styled from 'styled-components'; + +import { font, grid } from '@weco/common/utils/classnames'; +import Space from '@weco/common/views/components/styled/Space'; +import { PaletteColor } from '@weco/common/views/themes/config'; + +export const DateWrapper = styled(Space).attrs({ + className: font('intr', 4), + $v: { size: 'm', properties: ['margin-bottom'] }, +})` + margin: 0; + padding: 0; +`; + +export const FeaturedCardWrap = styled.div` + margin-left: -${props => props.theme.gutter.small}px; + margin-right: -${props => props.theme.gutter.small}px; + + ${props => props.theme.media('medium')` + margin-left: 0; + margin-right: 0; + `} +`; + +type HasIsReversed = { $isReversed: boolean }; +export const FeaturedCardLink = styled.a.attrs({ + className: 'grid', + 'data-gtm-trigger': 'featured_card_link', +})` + justify-content: flex-end; + flex-direction: ${props => (props.$isReversed ? 'row-reverse' : 'row')}; + + &, + &:link, + &:visited { + text-decoration: none; + border: none; + } +`; + +export const FeaturedCardLeft = styled.div.attrs({ + className: grid({ s: 12, m: 12, l: 7, xl: 7 }), +})``; + +export const FeaturedCardRight = styled.div` + display: flex; + flex-direction: column; + padding-left: ${props => + props.$isReversed ? 0 : props.theme.gutter.small}px; + padding-right: ${props => + props.$isReversed ? props.theme.gutter.small : 0}px; + transform: translateY(-28px); /* Height of a label (font size + padding) */ + width: 100%; + height: 100%; + min-height: 200px; + + ${props => props.theme.media('medium')` + padding-left: 0; + padding-right: 0; + `} + + ${props => + props.theme.media('large')(` + margin-left: ${props.$isReversed ? 0 : -props.theme.gutter.large + 'px'}; + transform: translateY(0); + `)} +`; + +export const FeaturedCardCopy = styled(Space).attrs({ + $h: { size: 'l', properties: ['padding-left', 'padding-right'] }, + $v: { size: 'l', properties: ['padding-top', 'padding-bottom'] }, +})<{ $textColor: PaletteColor; $background: PaletteColor }>` + flex: 1; + color: ${props => props.theme.color(props.$textColor)}; + background-color: ${props => props.theme.color(props.$background)}; + + ${props => + props.theme.media('large')(` + margin-right: -${props.theme.gutter.large}px; + `)} +`; + +export const FeaturedCardShim = styled.div.attrs<{ $background: PaletteColor }>( + { + className: `is-hidden-s is-hidden-m ${grid({ s: 12, m: 11, l: 5, xl: 5 })}`, + } +)` + position: relative; + background-color: ${props => props.theme.color(props.$background)}; + height: 21px; + + /* Prevent a white line appearing above the shim because of browser rounding errors */ + top: -1px; + margin-left: ${props => + props.$isReversed ? props.theme.gutter.large + 'px' : null}; +`; diff --git a/content/webapp/components/FeaturedCard/FeaturedCard.tsx b/content/webapp/components/FeaturedCard/FeaturedCard.tsx deleted file mode 100644 index 8678c975ca..0000000000 --- a/content/webapp/components/FeaturedCard/FeaturedCard.tsx +++ /dev/null @@ -1,323 +0,0 @@ -import { FunctionComponent, PropsWithChildren } from 'react'; -import styled from 'styled-components'; - -import { ImageType } from '@weco/common/model/image'; -import { Label } from '@weco/common/model/labels'; -import linkResolver from '@weco/common/services/prismic/link-resolver'; -import { transformImage } from '@weco/common/services/prismic/transformers/images'; -import { font, grid } from '@weco/common/utils/classnames'; -import LabelsList from '@weco/common/views/components/LabelsList/LabelsList'; -import PrismicImage from '@weco/common/views/components/PrismicImage/PrismicImage'; -import Space from '@weco/common/views/components/styled/Space'; -import { PaletteColor } from '@weco/common/views/themes/config'; -import DateRange from '@weco/content/components/DateRange/DateRange'; -import StatusIndicator from '@weco/content/components/StatusIndicator/StatusIndicator'; -import { Article } from '@weco/content/services/wellcome/content/types/api'; -import { ArticleBasic } from '@weco/content/types/articles'; -import { BookBasic } from '@weco/content/types/books'; -import { Card } from '@weco/content/types/card'; -import { EventSeries } from '@weco/content/types/event-series'; -import { EventBasic } from '@weco/content/types/events'; -import { ExhibitionBasic } from '@weco/content/types/exhibitions'; -import { Guide } from '@weco/content/types/guides'; -import { Link } from '@weco/content/types/link'; -import { Page } from '@weco/content/types/pages'; -import { Season } from '@weco/content/types/seasons'; -import { SeriesBasic } from '@weco/content/types/series'; - -type PartialFeaturedCard = { - image?: ImageType; - labels: Label[]; - link: Link; -}; - -type Props = PartialFeaturedCard & { - background: PaletteColor; - textColor: PaletteColor; - isReversed?: boolean; -}; - -export function convertCardToFeaturedCardProps( - item: Card -): PartialFeaturedCard { - return { - // We intentionally omit the alt text on promos, so screen reader - // users don't have to listen to the alt text before hearing the - // title of the item in the list. - // - // See https://github.com/wellcomecollection/wellcomecollection.org/issues/6007 - image: item.image && { - ...item.image, - alt: '', - }, - labels: item.format ? [{ text: item.format.title }] : [], - link: { url: item.link || '', text: item.title || '' }, - }; -} - -export function convertItemToFeaturedCardProps( - item: - | ArticleBasic - | ExhibitionBasic - | Season - | Page - | EventSeries - | BookBasic - | SeriesBasic - | EventBasic - | Guide -): PartialFeaturedCard { - return { - image: item.promo?.image && { - ...item.promo.image, - // We intentionally omit the alt text on promos, so screen reader - // users don't have to listen to the alt text before hearing the - // title of the item in the list. - // - // See https://github.com/wellcomecollection/wellcomecollection.org/issues/6007 - alt: '', - }, - labels: item.labels, - link: { - url: linkResolver(item), - text: item.title, - }, - }; -} - -type FeaturedCardArticleProps = { - article: Article; - background: PaletteColor; - textColor: PaletteColor; -}; - -type FeaturedCardArticleBodyProps = { - article: Article; -}; - -// TODO: make this e.g. just `CardArticleBody` and work it back into the existing promos/cards -const FeaturedCardArticleBody: FunctionComponent< - FeaturedCardArticleBodyProps -> = ({ article }) => { - return ( - <> -

{article.title}

- {article.caption &&

{article.caption}

} - {article.seriesTitle && ( - -

- Part of{' '} - {article.seriesTitle} -

-
- )} - - ); -}; - -type FeaturedCardExhibitionProps = { - exhibition: ExhibitionBasic; - background: PaletteColor; - textColor: PaletteColor; -}; - -const DateWrapper = styled(Space).attrs({ - className: font('intr', 4), - $v: { size: 'm', properties: ['margin-bottom'] }, -})` - margin: 0; - padding: 0; -`; - -type FeaturedCardExhibitionBodyProps = { - exhibition: ExhibitionBasic; -}; - -const FeaturedCardExhibitionBody = ({ - exhibition, -}: FeaturedCardExhibitionBodyProps) => { - return ( -
-

{exhibition.title}

- {!exhibition.statusOverride && exhibition.start && exhibition.end && ( - - - - )} - -
- ); -}; - -const FeaturedCardWrap = styled.div` - margin-left: -${props => props.theme.gutter.small}px; - margin-right: -${props => props.theme.gutter.small}px; - - ${props => props.theme.media('medium')` - margin-left: 0; - margin-right: 0; - `} -`; - -type HasIsReversed = { $isReversed: boolean }; -const FeaturedCardLink = styled.a.attrs({ - className: 'grid', - 'data-gtm-trigger': 'featured_card_link', -})` - justify-content: flex-end; - flex-direction: ${props => (props.$isReversed ? 'row-reverse' : 'row')}; - - &, - &:link, - &:visited { - text-decoration: none; - border: none; - } -`; - -const FeaturedCardLeft = styled.div.attrs({ - className: grid({ s: 12, m: 12, l: 7, xl: 7 }), -})``; - -const FeaturedCardRight = styled.div` - display: flex; - flex-direction: column; - padding-left: ${props => - props.$isReversed ? 0 : props.theme.gutter.small}px; - padding-right: ${props => - props.$isReversed ? props.theme.gutter.small : 0}px; - transform: translateY(-28px); /* Height of a label (font size + padding) */ - width: 100%; - height: 100%; - min-height: 200px; - - ${props => props.theme.media('medium')` - padding-left: 0; - padding-right: 0; - `} - - ${props => - props.theme.media('large')(` - margin-left: ${props.$isReversed ? 0 : -props.theme.gutter.large + 'px'}; - transform: translateY(0); - `)} -`; - -const FeaturedCardCopy = styled(Space).attrs({ - $h: { size: 'l', properties: ['padding-left', 'padding-right'] }, - $v: { size: 'l', properties: ['padding-top', 'padding-bottom'] }, -})<{ $textColor: PaletteColor; $background: PaletteColor }>` - flex: 1; - color: ${props => props.theme.color(props.$textColor)}; - background-color: ${props => props.theme.color(props.$background)}; - - ${props => - props.theme.media('large')(` - margin-right: -${props.theme.gutter.large}px; - `)} -`; - -const FeaturedCardShim = styled.div.attrs<{ $background: PaletteColor }>({ - className: `is-hidden-s is-hidden-m ${grid({ s: 12, m: 11, l: 5, xl: 5 })}`, -})` - position: relative; - background-color: ${props => props.theme.color(props.$background)}; - height: 21px; - - /* Prevent a white line appearing above the shim because of browser rounding errors */ - top: -1px; - margin-left: ${props => - props.$isReversed ? props.theme.gutter.large + 'px' : null}; -`; - -const FeaturedCard: FunctionComponent> = ({ - image, - labels, - children, - link, - textColor, - background, - isReversed = false, -}) => { - return ( - - - - {image && ( - - )} - -
- - {labels && labels.length > 0 ? ( - - ) : ( -
- )} - - {children} - - -
-
- - - - ); -}; - -export const FeaturedCardArticle: FunctionComponent< - FeaturedCardArticleProps -> = ({ article, background, textColor }) => { - const promoImage = article.image?.['16:9'] || article.image; - const image = promoImage && { - ...transformImage(promoImage), - alt: '', - }; - const link = { - url: linkResolver({ type: 'articles', uid: article.uid }), - text: article.title, - }; - const labels = [{ text: article.format.label }]; - return ( - - - - ); -}; - -export const FeaturedCardExhibition: FunctionComponent< - FeaturedCardExhibitionProps -> = ({ exhibition, background, textColor }) => { - const props = convertItemToFeaturedCardProps(exhibition); - - return ( - - - - ); -}; - -export default FeaturedCard; diff --git a/content/webapp/components/FeaturedCard/index.tsx b/content/webapp/components/FeaturedCard/index.tsx new file mode 100644 index 0000000000..9e4feb9054 --- /dev/null +++ b/content/webapp/components/FeaturedCard/index.tsx @@ -0,0 +1,184 @@ +import { FunctionComponent, PropsWithChildren } from 'react'; + +import linkResolver from '@weco/common/services/prismic/link-resolver'; +import { transformImage } from '@weco/common/services/prismic/transformers/images'; +import { font, grid } from '@weco/common/utils/classnames'; +import LabelsList from '@weco/common/views/components/LabelsList/LabelsList'; +import PrismicImage from '@weco/common/views/components/PrismicImage/PrismicImage'; +import Space from '@weco/common/views/components/styled/Space'; +import { PaletteColor } from '@weco/common/views/themes/config'; +import DateRange from '@weco/content/components/DateRange/DateRange'; +import StatusIndicator from '@weco/content/components/StatusIndicator/StatusIndicator'; +import { Article } from '@weco/content/services/wellcome/content/types/api'; +import { ExhibitionBasic } from '@weco/content/types/exhibitions'; + +import { + convertCardToFeaturedCardProps, + convertItemToFeaturedCardProps, + PartialFeaturedCard, +} from './FeaturedCard.helpers'; +import { + DateWrapper, + FeaturedCardCopy, + FeaturedCardLeft, + FeaturedCardLink, + FeaturedCardRight, + FeaturedCardShim, + FeaturedCardWrap, +} from './FeaturedCard.styles'; + +type FeaturedCardProps = PartialFeaturedCard & { + background: PaletteColor; + textColor: PaletteColor; + isReversed?: boolean; +}; + +type FeaturedCardArticleProps = { + article: Article; + background: PaletteColor; + textColor: PaletteColor; +}; + +type FeaturedCardExhibitionProps = { + exhibition: ExhibitionBasic; + background: PaletteColor; + textColor: PaletteColor; +}; + +const FeaturedCardBasic = props => { + const { + image, + labels, + children, + link, + textColor, + background, + isReversed = false, + } = props; + + return ( + + + + {image && ( + + )} + +
+ + {labels && labels.length > 0 ? ( + + ) : ( +
+ )} + + {children} + + +
+
+ + + + ); +}; + +const FeaturedCardArticle: FunctionComponent = ({ + article, + background, + textColor, + ...rest +}) => { + const promoImage = article.image?.['16:9'] || article.image; + const image = promoImage && { + ...transformImage(promoImage), + alt: '', + }; + const link = { + url: linkResolver({ type: 'articles', uid: article.uid }), + text: article.title, + }; + const labels = [{ text: article.format.label }]; + + return ( + +

{article.title}

+ {article.caption &&

{article.caption}

} + {article.seriesTitle && ( + +

+ Part of{' '} + {article.seriesTitle} +

+
+ )} +
+ ); +}; + +const FeaturedCardExhibition: FunctionComponent< + FeaturedCardExhibitionProps +> = ({ exhibition, background, textColor, ...rest }) => { + const props = convertItemToFeaturedCardProps(exhibition); + + return ( + +
+

{exhibition.title}

+ {!exhibition.statusOverride && exhibition.start && exhibition.end && ( + + + + )} + +
+
+ ); +}; + +const FeaturedCard: FunctionComponent< + | PropsWithChildren + | (FeaturedCardArticleProps & { type: 'article' }) + | (FeaturedCardExhibitionProps & { type: 'exhibition' }) +> = props => { + if (props.type === 'article') { + return ; + } + + if (props.type === 'exhibition') { + return ; + } + + return ; +}; + +export default FeaturedCard; +export { convertCardToFeaturedCardProps, convertItemToFeaturedCardProps }; diff --git a/content/webapp/components/SimpleCardGrid/SimpleCardGrid.tsx b/content/webapp/components/SimpleCardGrid/SimpleCardGrid.tsx index 9dcc98bb8a..65f76e923b 100644 --- a/content/webapp/components/SimpleCardGrid/SimpleCardGrid.tsx +++ b/content/webapp/components/SimpleCardGrid/SimpleCardGrid.tsx @@ -9,7 +9,7 @@ import { import CssGridContainer from '@weco/common/views/components/styled/CssGridContainer'; import Space from '@weco/common/views/components/styled/Space'; import Card from '@weco/content/components/Card/Card'; -import FeaturedCard from '@weco/content/components/FeaturedCard/FeaturedCard'; +import FeaturedCard from '@weco/content/components/FeaturedCard'; import { Card as CardType } from '@weco/content/types/card'; type Props = { diff --git a/content/webapp/pages/stories/index.tsx b/content/webapp/pages/stories/index.tsx index 14b6311851..369117cbdf 100644 --- a/content/webapp/pages/stories/index.tsx +++ b/content/webapp/pages/stories/index.tsx @@ -24,7 +24,7 @@ import Space from '@weco/common/views/components/styled/Space'; import SpacingComponent from '@weco/common/views/components/styled/SpacingComponent'; import SpacingSection from '@weco/common/views/components/styled/SpacingSection'; import CardGrid from '@weco/content/components/CardGrid/CardGrid'; -import { FeaturedCardArticle } from '@weco/content/components/FeaturedCard/FeaturedCard'; +import FeaturedCard from '@weco/content/components/FeaturedCard'; import FeaturedText from '@weco/content/components/FeaturedText/FeaturedText'; import { defaultSerializer } from '@weco/content/components/HTMLSerializers/HTMLSerializers'; import SectionHeader from '@weco/content/components/SectionHeader/SectionHeader'; @@ -203,7 +203,8 @@ const StoriesPage: FunctionComponent = ({ - = props => { {firstExhibition ? ( - { switch (content.type) { diff --git a/content/webapp/services/wellcome/content/types/api.ts b/content/webapp/services/wellcome/content/types/api.ts index a7b9f8c6b3..47cfd50dd8 100644 --- a/content/webapp/services/wellcome/content/types/api.ts +++ b/content/webapp/services/wellcome/content/types/api.ts @@ -23,7 +23,7 @@ export type ContentApiProps = { aggregations?: string[]; }; -type ContentApiImage = Image & { type: 'PrismicImage' }; +export type ContentApiImage = Image & { type: 'PrismicImage' }; export type Series = { id: string;