Skip to content

Commit

Permalink
✨ Add big title for rich text and improve code #1890
Browse files Browse the repository at this point in the history
  • Loading branch information
fernandolucchesi committed Oct 4, 2023
1 parent 0656f5a commit b4a64a5
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 63 deletions.
36 changes: 15 additions & 21 deletions sanityv3/schemas/objects/teaser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export type Teaser = {
overline?: string
title?: PortableTextBlock[]
text?: PortableTextBlock[]
bigTextTeaser?: boolean
isBigText?: boolean
bigText?: PortableTextBlock[]
action?: (LinkSelector | DownloadableFile | DownloadableImage)[]
image: ImageWithAlt
Expand All @@ -80,7 +80,7 @@ export default {
collapsible: true,
collapsed: true,
},
hidden: ({ parent }: TeaserDocument) => parent.bigTextTeaser,
hidden: ({ parent }: TeaserDocument) => parent.isBigText,
},
{
name: 'link',
Expand All @@ -94,8 +94,8 @@ export default {
],
fields: [
{
title: 'Big text teaser',
name: 'bigTextTeaser',
title: 'Big text',
name: 'isBigText',
type: 'boolean',
},
{
Expand All @@ -111,7 +111,7 @@ export default {
input: CompactBlockEditor,
},
of: [titleContentType],
hidden: ({ parent }: TeaserDocument) => parent.bigTextTeaser,
hidden: ({ parent }: TeaserDocument) => parent.isBigText,
},
{
name: 'text',
Expand All @@ -120,12 +120,12 @@ export default {
of: [blockContentType],
validation: (Rule: Rule) =>
Rule.custom((value: PortableTextBlock[], ctx: ValidationContext) => {
if (!(ctx.parent as Teaser)?.bigTextTeaser) {
if (!(ctx.parent as Teaser)?.isBigText) {
return validateCharCounterEditor(value, 600)
}
return true
}).warning(),
hidden: ({ parent }: TeaserDocument) => parent.bigTextTeaser,
hidden: ({ parent }: TeaserDocument) => parent.isBigText,
},
{
name: 'bigText',
Expand All @@ -134,12 +134,12 @@ export default {
of: [blockContentTypeForBigText],
validation: (Rule: Rule) =>
Rule.custom((value: PortableTextBlock[], ctx: ValidationContext) => {
if ((ctx.parent as Teaser)?.bigTextTeaser) {
if ((ctx.parent as Teaser)?.isBigText) {
return validateCharCounterEditor(value, 600)
}
return true
}),
hidden: ({ parent }: TeaserDocument) => !parent.bigTextTeaser,
hidden: ({ parent }: TeaserDocument) => !parent.isBigText,
},
{
name: 'action',
Expand Down Expand Up @@ -211,34 +211,28 @@ export default {
select: {
title: 'title',
text: 'text',
bigTextTeaser: 'bigTextTeaser',
isBigText: 'isBigText',
bigText: 'bigText',
image: 'image.asset',
},
prepare({
title,
text,
bigTextTeaser,
isBigText,
bigText,
image,
}: {
title: PortableTextBlock[]
text: PortableTextBlock[]
bigTextTeaser: boolean
isBigText: boolean
bigText: PortableTextBlock[]
image: Reference
}) {
let plainTitle = undefined

if (bigTextTeaser) {
plainTitle = bigText ? blocksToText(bigText) : undefined
} else {
plainTitle = title || text ? blocksToText(title || text) : undefined
}
const plainTitle = isBigText ? blocksToText(bigText) : blocksToText(title || text)

return {
title: plainTitle || 'Missing title/text',
subtitle: bigTextTeaser ? 'Big text teaser component' : 'Teaser component',
title: plainTitle || 'Missing title/content',
subtitle: isBigText ? 'Teaser component (BIG TEXT)' : 'Teaser component',
media: image,
}
},
Expand Down
88 changes: 66 additions & 22 deletions sanityv3/schemas/objects/textBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { text_field } from '@equinor/eds-icons'
import type { Reference, Rule } from 'sanity'
import type { PortableTextBlock, Reference, Rule, SanityDocument, ValidationContext } from 'sanity'
import type { ColorSelectorValue } from '../components/ColorSelector'
import blocksToText from '../../helpers/blocksToText'
import { EdsIcon } from '../../icons'
import { SchemaType } from '../../types'
import CompactBlockEditor from '../components/CompactBlockEditor'
import { configureBlockContent, configureTitleBlockContent } from '../editors'
import { validateComponentAnchor } from '../validations/validateAnchorReference'
Expand All @@ -16,13 +15,29 @@ const blockContentType = configureBlockContent({
h4: false,
attachment: false,
})

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

const ingressContentTypeForBigText = configureBlockContent({
h1: false,
h2: false,
h3: false,
h4: false,
attachment: false,
smallText: false,
normalTextOverride: {
title: 'Normal',
value: 'normal',
component: ({ children }: { children: React.ReactNode }) => <span style={{ fontSize: '42px' }}>{children}</span>,
},
})

const titleContentType = configureTitleBlockContent()

type TextBlock = {
Expand All @@ -31,12 +46,18 @@ type TextBlock = {
anchor?: string
ingress?: string
text?: string
isBigText?: boolean
bigText?: PortableTextBlock[]
action?: Reference[]
splitList?: boolean
overrideButtonStyle?: boolean
background?: ColorSelectorValue
}

type TextBlockDocument = {
parent: TextBlock
}

export default {
name: 'textBlock',
title: 'Text block',
Expand All @@ -50,6 +71,7 @@ export default {
collapsible: true,
collapsed: true,
},
hidden: ({ parent }: TextBlockDocument) => parent.isBigText,
},
{
title: 'Eyebrow headline',
Expand All @@ -59,6 +81,7 @@ export default {
collapsible: true,
collapsed: true,
},
hidden: ({ parent }: TextBlockDocument) => parent.isBigText,
},
{
title: 'Call to action(s)',
Expand All @@ -84,6 +107,11 @@ export default {
},
],
fields: [
{
title: 'Big text',
name: 'isBigText',
type: 'boolean',
},
{
name: 'image',
type: 'imageWithAlt',
Expand All @@ -105,7 +133,11 @@ export default {
input: CompactBlockEditor,
},
of: [titleContentType],
validation: (Rule: SchemaType.ValidationRule) => Rule.required().warning('A title is recommended'),
validation: (Rule: Rule) =>
Rule.custom((value: PortableTextBlock[], ctx: ValidationContext) =>
!value && !(ctx.parent as TextBlock)?.isBigText ? 'A title is recommended' : true,
).warning(),
hidden: ({ parent }: TextBlockDocument) => parent.isBigText,
},
{
name: 'anchor',
Expand All @@ -124,6 +156,18 @@ export default {
title: 'Ingress',
type: 'array',
of: [ingressContentType],
hidden: ({ parent }: TextBlockDocument) => parent.isBigText,
},
{
name: 'bigIngress',
title: 'Ingress',
type: 'array',
of: [ingressContentTypeForBigText],
hidden: ({ parent }: TextBlockDocument) => !parent.isBigText,
validation: (Rule: Rule) =>
Rule.custom((value: PortableTextBlock[], ctx: ValidationContext) =>
!value && (ctx.parent as TextBlock)?.isBigText ? 'Ingress is required' : true,
),
},
{
name: 'text',
Expand Down Expand Up @@ -176,27 +220,27 @@ export default {
title: 'title',
ingress: 'ingress',
text: 'text',
},
prepare({ title = [], ingress, text }: { title: any[]; ingress: any; text: any }) {
const textBlock = (text || []).find((introBlock: any) => introBlock._type === 'block')
const ingressBlock = (ingress || []).find((introBlock: any) => introBlock._type === 'block')
const plainTitle = title ? blocksToText(title) : undefined
isBigText: 'isBigText',
bigIngress: 'bigIngress',
},
prepare({
title,
isBigText,
bigIngress,
ingress,
text,
}: {
title: PortableTextBlock[]
ingress: PortableTextBlock[]
isBigText: boolean
bigIngress: PortableTextBlock[]
text: PortableTextBlock[]
}) {
const plainTitle = isBigText ? blocksToText(bigIngress) : blocksToText(title || ingress || text)

return {
title:
plainTitle ||
(textBlock &&
textBlock.children
.filter((child: any) => child._type === 'span')
.map((span: any) => span.text)
.join('')) ||
(ingressBlock &&
ingressBlock.children
.filter((child: any) => child._type === 'span')
.map((span: any) => span.text)
.join('')) ||
'Missing content!',
subtitle: `Text block component.`,
title: plainTitle || 'Missing title/content',
subtitle: isBigText ? 'Text block component (BIG TEXT)' : 'Text block component',
media: EdsIcon(text_field),
}
},
Expand Down
14 changes: 8 additions & 6 deletions web/lib/queries/common/pageContentFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ const pageContentFields = /* groq */ `
"id": _key,
overline,
title,
bigTextTeaser,
isBigText,
"text": select(
bigTextTeaser =>
isBigText =>
bigText[]{..., ${markDefs}},
text[]{..., ${markDefs}}
),
Expand All @@ -44,10 +44,12 @@ const pageContentFields = /* groq */ `
image,
overline,
title,
ingress[]{
...,
${markDefs},
},
isBigText,
"ingress": select(
isBigText =>
bigIngress[]{..., ${markDefs}},
ingress[]{..., ${markDefs}}
),
text[]{
...,
${markDefs},
Expand Down
8 changes: 3 additions & 5 deletions web/pageComponents/shared/Teaser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const TeaserAction = ({ action }: { action: LinkData }) => {
}

const Teaser = ({ data, anchor }: TeaserProps) => {
const { title, overline, text, image, action, designOptions, bigTextTeaser } = data
const { title, overline, text, image, action, designOptions, isBigText } = data
const { background, imageSize, imagePosition } = designOptions

if ([title, overline, text, image?.asset, action].every((i) => !i)) {
Expand All @@ -89,15 +89,13 @@ const Teaser = ({ data, anchor }: TeaserProps) => {
{image?.asset && <TeaserImage image={image} />}
</Media>
<Content>
{bigTextTeaser ? (
{isBigText ? (
text && (
<IngressText
value={text}
components={{
block: {
normal: ({ children }: { children: React.ReactNode }) => {
return <Text size="lg">{children}</Text>
},
normal: ({ children }: { children: React.ReactNode }) => <Text size="lg">{children}</Text>,
} as BlockType,
}}
/>
Expand Down
33 changes: 25 additions & 8 deletions web/pageComponents/topicPages/TextBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Eyebrow, BackgroundContainer } from '@components'
import { Eyebrow, BackgroundContainer, Text } from '@components'
import IngressText from '../shared/portableText/IngressText'
import RichText from '../shared/portableText/RichText'
import TitleText from '../shared/portableText/TitleText'
import Image, { Ratios } from '../shared/SanityImage'
import styled from 'styled-components'
import type { TextBlockData } from '../../types/types'
import CallToActions from './CallToActions'
import { BlockType } from '../shared/portableText/helpers/defaultSerializers'

export const StyledTextBlockWrapper = styled(BackgroundContainer)<{ id: string | undefined }>`
${({ id }) =>
Expand Down Expand Up @@ -62,6 +63,7 @@ const TextBlock = ({ data, anchor }: TextBlockProps) => {
callToActions,
splitList,
overrideButtonStyle = false,
isBigText,
} = data
/* Don't render the component if it only has an eyebrow */
if (!title && !ingress && !text && (!callToActions || callToActions.length === 0)) return null
Expand All @@ -70,14 +72,29 @@ const TextBlock = ({ data, anchor }: TextBlockProps) => {
return (
<StyledTextBlockWrapper background={background} id={anchor || data.anchor}>
<StyledTextBlock>
{image?.asset && (
<ImgContainer>
<Image image={image} maxWidth={300} aspectRatio={Ratios.NINE_TO_SIXTEEN} />
</ImgContainer>
{isBigText ? (
ingress && (
<IngressText
value={ingress}
components={{
block: {
normal: ({ children }: { children: React.ReactNode }) => <Text size="lg">{children}</Text>,
} as BlockType,
}}
/>
)
) : (
<>
{image?.asset && (
<ImgContainer>
<Image image={image} maxWidth={300} aspectRatio={Ratios.NINE_TO_SIXTEEN} />
</ImgContainer>
)}
{overline && <Eyebrow>{overline}</Eyebrow>}
{title && <TitleText value={title} />}
{ingress && <IngressText value={ingress} />}
</>
)}
{overline && <Eyebrow>{overline}</Eyebrow>}
{title && <TitleText value={title} />}
{ingress && <IngressText value={ingress} />}
{text && (
<TextContainer>
<RichText value={text} />
Expand Down
Loading

0 comments on commit b4a64a5

Please sign in to comment.