Skip to content

Commit

Permalink
Add Key numbers component. #2048 (#2054)
Browse files Browse the repository at this point in the history
* ✨ Key numbers component #2048

* Missing commit #2028

* ♻️ Remove any #2048

* ✨ horizontal scroll option for mobiles #2048

* 💄 Increased width of item #2048

* 💄 Fix padding issue and scroll offset

* Remove duplicate item #2048
  • Loading branch information
padms authored Jan 29, 2024
1 parent dd390f7 commit bec3287
Show file tree
Hide file tree
Showing 12 changed files with 392 additions and 31 deletions.
4 changes: 4 additions & 0 deletions sanityv3/schemas/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ import videoPlayer from './objects/videoPlayer'
import videoPlayerCarousel from './objects/videoPlayerCarousel'
import videoControls from './objects/videoControls'
import hlsVideo from './objects/hlsVideo'
import keyNumbers from './objects/keyNumbers'
import keyNumberItem from './objects/keyNumberItem'

const routeSchemas = languages.map(({ name, title }) => {
return route(name, title)
Expand Down Expand Up @@ -164,6 +166,8 @@ const RemainingSchemas = [
videoPlayerCarousel,
videoControls,
hlsVideo,
keyNumbers,
keyNumberItem,
]

// Then we give our schema to the builder and provide the result to Sanity
Expand Down
44 changes: 44 additions & 0 deletions sanityv3/schemas/objects/keyNumberItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Rule } from 'sanity'
import { NumberIcon } from '@sanity/icons'

export default {
name: 'keyNumberItem',
type: 'object',
title: 'Key Number',
fields: [
{
name: 'keyNumber',
title: 'Key Number',
type: 'number',
validation: (Rule: Rule) => Rule.required(),
},
{
name: 'unit',
title: 'Unit',
description: 'A short abbreviated text describing the unit of the key number',
type: 'string',
},
{
name: 'description',
title: 'Description',
type: 'string',
description: 'Short description to show below the key number',
},
],

preview: {
select: {
keyNumber: 'keyNumber',
unit: 'unit',
description: 'description',
},
prepare(selection: Record<string, string | number>) {
const { keyNumber, unit, description } = selection
return {
title: `${keyNumber} ${unit ?? ''}`,
subtitle: description,
media: NumberIcon,
}
},
},
}
116 changes: 116 additions & 0 deletions sanityv3/schemas/objects/keyNumbers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import CompactBlockEditor from '../components/CompactBlockEditor'
import { configureBlockContent, configureTitleBlockContent } from '../editors'
import { PortableTextBlock, Rule } from 'sanity'
import { NumberIcon } from '@sanity/icons'
import blocksToText from '../../helpers/blocksToText'

const titleContentType = configureTitleBlockContent()
const ingressContentType = configureBlockContent({
h1: false,
h2: false,
h3: false,
h4: false,
attachment: false,
})

const disclaimerContentType = configureBlockContent({
h1: false,
h2: false,
h3: false,
h4: false,
attachment: false,
smallText: true,
})

export default {
name: 'keyNumbers',
title: 'Key Numbers',
type: 'object',
fieldsets: [
{
name: 'link',
title: 'Link',
description: 'Select either an internal link or external URL.',
},
{
name: 'design',
title: 'Design options',
},
],

fields: [
{
title: 'Title',
name: 'title',
type: 'array',
components: {
input: CompactBlockEditor,
},
of: [titleContentType],
validation: (Rule: Rule) => Rule.required().warning('In most cases you should add a title'),
},
{
name: 'ingress',
title: 'Ingress',
type: 'array',
of: [ingressContentType],
},
{
name: 'keyNumberItems',
title: 'Key Number Items',
type: 'array',
of: [{ type: 'keyNumberItem' }],
validation: (Rule: Rule) => Rule.min(2).error('Need minimum 2 key numbers'),
},
{
name: 'useHorizontalScroll',
title: 'Use horizontal scroll',
description:
'When this is enabled, the key numbers will use horizontal scroll if the amount of content is greater than the screen size allows. Only for mobiles.',
type: 'boolean',
initialValue: false,
},
{
name: 'disclaimer',
title: 'Disclaimer',
type: 'array',
components: {
input: CompactBlockEditor,
},
of: [disclaimerContentType],
},
{
name: 'action',
title: 'Link/action',
description: 'Select the link or downloadable file for the teaser',
fieldset: 'link',
type: 'array',
of: [
{ type: 'linkSelector', title: 'Link' },
{ type: 'downloadableImage', title: 'Downloadable image' },
{ type: 'downloadableFile', title: 'Downloadable file' },
],
validation: (Rule: Rule) => Rule.max(1).error('Only one action is permitted'),
},
{
title: 'Background',
description: 'Pick a colour for the background. Default is white.',
name: 'background',
type: 'colorlist',
fieldset: 'design',
},
],
preview: {
select: {
title: 'title',
items: 'keyNumberItems',
},
prepare(selection: { title: PortableTextBlock[]; items: Array<object> }) {
return {
title: blocksToText(selection.title),
subtitle: `Showing ${selection.items.length} key numbers`,
media: NumberIcon,
}
},
},
}
27 changes: 27 additions & 0 deletions web/lib/queries/common/keyNumbersFields.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import downloadableFileFields from './actions/downloadableFileFields'
import downloadableImageFields from './actions/downloadableImageFields'
import linkSelectorFields from './actions/linkSelectorFields'
import markDefs from './blockEditorMarks'

export const keyNumbersFields = /*groq*/ `
"type": _type,
"id" : _key,
title,
ingress[]{..., ${markDefs}},
disclaimer[]{..., ${markDefs}},
useHorizontalScroll,
"designOptions": {
"background": coalesce(background.title, 'White'),
},
"action": action[0]{
${linkSelectorFields},
${downloadableFileFields},
${downloadableImageFields},
},
"items" : keyNumberItems[]{
"id": _key,
keyNumber,
unit,
description,
},
`
4 changes: 4 additions & 0 deletions web/lib/queries/common/pageContentFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@ import linkSelectorFields, { linkReferenceFields } from './actions/linkSelectorF
import markDefs from './blockEditorMarks'
import { eventPromotionFields, futureEventsQuery, pastEventsQuery } from './eventPromotion'
import { imageCarouselFields } from './imageCarouselFields'
import { keyNumbersFields } from './keyNumbersFields'
import { noDrafts, sameLang } from './langAndDrafts'
import promoteMagazine from './promotions/promoteMagazine'
import { publishDateTimeQuery } from './publishDateTime'

const pageContentFields = /* groq */ `
_type == "keyNumbers" =>{
${keyNumbersFields}
},
_type == "teaser" => {
"type": _type,
"id": _key,
Expand Down
6 changes: 6 additions & 0 deletions web/pageComponents/pageTemplates/shared/SharedPageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import ImageCarousel from '../../shared/ImageCarousel/ImageCarousel'
import IframeCarousel from '../../shared/IframeCarousel/IframeCarousel'
import VideoPlayer from '../../shared/VideoPlayer'
import VideoPlayerCarousel from '../../shared/VideoPlayerCarousel'
import KeyNumbers from '../../topicPages/KeyNumbers/KeyNumbers'
import {
AnchorLinkData,
TopicPageSchema,
Expand All @@ -45,6 +46,7 @@ import {
IframeCarouselData,
VideoPlayerData,
VideoPlayerCarouselData,
KeyNumbersData,
} from '../../../types/types'

// How could we do this for several different component types?
Expand All @@ -68,6 +70,7 @@ type ComponentProps =
| VideoPlayerData
| VideoPlayerCarouselData
| CookieDeclarationData
| KeyNumbersData

type PageContentProps = { data: TopicPageSchema | MagazinePageSchema }

Expand Down Expand Up @@ -121,6 +124,9 @@ export const PageContent = ({ data }: PageContentProps) => {
return <VideoPlayer key={c.id} data={c as VideoPlayerData} anchor={anchorReference} />
case 'videoPlayerCarousel':
return <VideoPlayerCarousel key={c.id} data={c as VideoPlayerCarouselData} anchor={anchorReference} />
case 'keyNumbers':
return <KeyNumbers key={c.id} data={c as KeyNumbersData} anchor={anchorReference} />

default:
return null
}
Expand Down
7 changes: 6 additions & 1 deletion web/pageComponents/shared/Carousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,12 @@ export const Carousel = ({ children, scrollOffset, horizontalPadding = false, ..
const handleScroll = (scrollType: string) => {
const container = scrollRef.current
if (container) {
const offset = scrollOffset || Math.max(0.5 * container.offsetWidth, 320)
const noOfItems = container?.childElementCount - 2 // exclude right & left arrow from children count.
const itemWidth = container?.lastElementChild?.clientWidth || 0
const padding = (container?.scrollWidth - itemWidth * noOfItems) / (noOfItems - 1)
const calculatedOffset = itemWidth + padding / 2
const offset = scrollOffset || calculatedOffset

container.scrollBy({
left: scrollType === 'forward' ? offset : -offset,
behavior: prefersReducedMotion ? 'auto' : 'smooth',
Expand Down
34 changes: 34 additions & 0 deletions web/pageComponents/shared/ReadMoreLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { LinkData } from '../../types'
import { getUrlFromAction } from '../../common/helpers'
import { getLocaleFromName } from '../../lib/localization'
import { Link } from '@components/Link'
import styled from 'styled-components'

const StyledLink = styled(Link)`
font-size: var(--typeScale-1);
`
const ReadMoreLink = ({ action }: { action: LinkData }) => {
const { type, label, extension } = action
const url = getUrlFromAction(action)
if (!url) {
console.warn(`Missing URL on 'TeaserAction' link with type: '${type}' and label: '${label}'`)
return null
}

if (action.type === 'internalUrl') {
const locale = getLocaleFromName(action.link?.lang)
return (
<StyledLink href={url} locale={locale} variant="readMore" aria-label={action.ariaLabel}>
{action.label}
</StyledLink>
)
}

return (
<StyledLink variant="readMore" href={url} type={action.type} aria-label={action.ariaLabel}>
{action.label} {extension && `(${extension.toUpperCase()})`}
</StyledLink>
)
}

export default ReadMoreLink
34 changes: 4 additions & 30 deletions web/pageComponents/shared/Teaser.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { Teaser as EnvisTeaser, Link, Eyebrow, BackgroundContainer, Text } from '@components'
import { Teaser as EnvisTeaser, Eyebrow, BackgroundContainer, Text } from '@components'
import styled from 'styled-components'
import IngressText from './portableText/IngressText'
import TitleText from './portableText/TitleText'
import { urlFor } from '../../common/helpers'
import Img from 'next/image'
import Image from './SanityImage'
import { getUrlFromAction } from '../../common/helpers/getUrlFromAction'

import type { TeaserData, ImageWithAlt, LinkData } from '../../types/types'
import { getLocaleFromName } from '../../lib/localization'
import type { TeaserData, ImageWithAlt } from '../../types/types'
import ReadMoreLink from './ReadMoreLink'
import { BlockType } from './portableText/helpers/defaultSerializers'

const { Content, Media } = EnvisTeaser
Expand Down Expand Up @@ -57,30 +55,6 @@ const TeaserImage = ({ image }: { image: ImageWithAlt }) => {
)
}

const TeaserAction = ({ action }: { action: LinkData }) => {
const { type, label, extension } = action
const url = getUrlFromAction(action)
if (!url) {
console.warn(`Missing URL on 'TeaserAction' link with type: '${type}' and label: '${label}'`)
return null
}

if (action.type === 'internalUrl') {
const locale = getLocaleFromName(action.link?.lang)
return (
<Link href={url} locale={locale} variant="readMore" aria-label={action.ariaLabel}>
{action.label}
</Link>
)
}

return (
<Link variant="readMore" href={url} type={action.type} aria-label={action.ariaLabel}>
{action.label} {extension && `(${extension.toUpperCase()})`}
</Link>
)
}

const Teaser = ({ data, anchor }: TeaserProps) => {
const { title, overline, text, image, action, designOptions, isBigText } = data
const { background, imageSize, imagePosition } = designOptions
Expand Down Expand Up @@ -125,7 +99,7 @@ const Teaser = ({ data, anchor }: TeaserProps) => {
{text && <IngressText value={text} />}
</ContentWrapper>
)}
{action && <TeaserAction action={action} />}
{action && <ReadMoreLink action={action} />}
</Content>
</StyledEnvisTeaser>
</BackgroundContainer>
Expand Down
Loading

0 comments on commit bec3287

Please sign in to comment.