Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 7 additions & 7 deletions docs/coding-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,10 @@ blocks
When creating a new block, you must register it in the following locations:

1. **`src/blocks/RenderBlocks.tsx`** - For standalone page blocks
- Set `isLexical={false}`
- Set `isLayoutBlock={true}` so the block gets its own `container` wrapper

2. **`src/components/RichText/index.tsx`** - For blocks used inline within rich text editors
- Set `isLexical={true}` to avoid double-wrapping
- Set `isLayoutBlock={false}` to avoid double-wrapping (the RichText component already provides a container)
- Only add blocks that should be available in Lexical editors

3. **`src/constants/defaults.ts`** - Add the block to the defaults configuration
Expand All @@ -194,9 +194,9 @@ When creating a new block, you must register it in the following locations:
- A `richText` field's `BlocksFeature` configuration
- This ensures Payload generates TypeScript types for your block

**Why the different `isLexical` values?**
- Standalone blocks (`RenderBlocks.tsx`) are not rendered by a Lexical editor → `isLexical={false}`
- Inline Lexical blocks (`RichText/index.tsx`) are rendered inside a Lexical editor → `isLexical={true}`
**Why the different `isLayoutBlock` values?**
- Standalone blocks (`RenderBlocks.tsx`) are top-level page layout blocks that need their own container → `isLayoutBlock={true}`
- Inline Lexical blocks (`RichText/index.tsx`) are embedded inside a rich text field that already provides a container → `isLayoutBlock={false}`


### BackgroundColorWrapper
Expand All @@ -205,15 +205,15 @@ A reusable layout component that wraps content with configurable background colo

**Props:**
- `backgroundColor` - Tailwind background color class name
- `isLexical` - Whether the block is rendered within a Lexical editor (`default: false`)
- `isLayoutBlock` - Whether the block is a standalone page layout block that needs its own container (`default: false`)
- `containerClassName` - Optional - additional classes for the inner container div
- `outerClassName` - Optional - additional classes for the outer wrapper div

**Usage:**
```tsx
<BackgroundColorWrapper
backgroundColor={backgroundColor} // Intended for prop from colorPickerField prop
isLexical={isLexical} // Intended for prop from standalone or lexical block declaration
isLayoutBlock={isLayoutBlock} // Intended for prop from standalone or lexical block declaration
containerClassName="py-8"
>
<YourContent />
Expand Down
6 changes: 3 additions & 3 deletions src/blocks/BlogList/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { cn } from '@/utilities/ui'
import { useEffect, useState } from 'react'

type BlogListComponentProps = BlogListBlockProps & {
isLexical: boolean
isLayoutBlock: boolean
className?: string
}

Expand All @@ -24,7 +24,7 @@ export const BlogListBlockComponent = (args: BlogListComponentProps) => {
belowHeadingContent,
backgroundColor,
className,
isLexical = true,
isLayoutBlock = true,
postOptions,
} = args

Expand Down Expand Up @@ -91,7 +91,7 @@ export const BlogListBlockComponent = (args: BlogListComponentProps) => {
return (
<BackgroundColorWrapper
backgroundColor={backgroundColor}
isLexical={isLexical}
isLayoutBlock={isLayoutBlock}
containerClassName={className}
>
<div className="bg-card text-card-foreground p-6 border shadow rounded-lg flex flex-col gap-6">
Expand Down
6 changes: 3 additions & 3 deletions src/blocks/Document/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import { getHostnameFromTenant } from '@/utilities/tenancy/getHostnameFromTenant
import { cn } from '@/utilities/ui'

type Props = DocumentBlockProps & {
isLexical: boolean
isLayoutBlock: boolean
}

export const DocumentBlockComponent = (props: Props) => {
const { document, isLexical = true } = props
const { document, isLayoutBlock = true } = props
const { tenant } = useTenant()

if (!isValidRelationship(document) || !document.url) {
Expand All @@ -21,7 +21,7 @@ export const DocumentBlockComponent = (props: Props) => {
const src = getMediaURL(document.url, null, getHostnameFromTenant(tenant))

return (
<div className={cn('my-4', { container: isLexical })}>
<div className={cn('my-4', { container: isLayoutBlock })}>
<iframe src={src} width="100%" height="600px" title="Document PDF" />
</div>
)
Expand Down
6 changes: 3 additions & 3 deletions src/blocks/EventList/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { format } from 'date-fns'
import { useEffect, useState } from 'react'

type EventListComponentProps = EventListBlockProps & {
isLexical: boolean
isLayoutBlock: boolean
className?: string
}

Expand All @@ -22,7 +22,7 @@ export const EventListBlockComponent = (args: EventListComponentProps) => {
belowHeadingContent,
backgroundColor,
className,
isLexical = true,
isLayoutBlock = true,
eventOptions,
} = args

Expand Down Expand Up @@ -98,7 +98,7 @@ export const EventListBlockComponent = (args: EventListComponentProps) => {
return (
<BackgroundColorWrapper
backgroundColor={backgroundColor}
isLexical={isLexical}
isLayoutBlock={isLayoutBlock}
containerClassName={className}
>
<div className="bg-card text-card-foreground p-6 border shadow rounded-lg flex flex-col gap-6">
Expand Down
8 changes: 4 additions & 4 deletions src/blocks/EventTable/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { format } from 'date-fns'
import { useEffect, useState } from 'react'

type EventTableComponentProps = EventTableBlockProps & {
isLexical: boolean
isLayoutBlock: boolean
className?: string
}

Expand All @@ -22,7 +22,7 @@ export const EventTableBlockComponent = (args: EventTableComponentProps) => {
className,
eventOptions,
backgroundColor,
isLexical = true,
isLayoutBlock = true,
} = args
const { byTypes, byGroups, byTags, maxEvents } = args.dynamicOpts || {}
const { staticEvents } = args.staticOpts || {}
Expand Down Expand Up @@ -101,10 +101,10 @@ export const EventTableBlockComponent = (args: EventTableComponentProps) => {
return (
<BackgroundColorWrapper
backgroundColor={backgroundColor}
isLexical={isLexical}
isLayoutBlock={isLayoutBlock}
containerClassName={className}
>
<div className={cn('container bg-card text-card-foreground p-6 rounded-lg', className)}>
<div className={cn('bg-card text-card-foreground', className)}>
<div className="flex flex-col justify-start gap-1">
{heading && (
<div className="prose md:prose-md dark:prose-invert">
Expand Down
6 changes: 3 additions & 3 deletions src/blocks/Form/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ export interface Data {
[key: string]: Property | Property[]
}

type FormBlockTypeProps = { isLexical?: boolean } & FormBlockType
type FormBlockTypeProps = { isLayoutBlock?: boolean } & FormBlockType

export const FormBlockComponent = (props: FormBlockTypeProps) => {
const { enableIntro, introContent, isLexical = true } = props
const { enableIntro, introContent, isLayoutBlock = true } = props

const uniqueFormId = useId()

Expand Down Expand Up @@ -129,7 +129,7 @@ export const FormBlockComponent = (props: FormBlockTypeProps) => {
}

return (
<div className={cn('lg:max-w-[48rem]', isLexical && 'container')}>
<div className={cn('lg:max-w-[48rem]', isLayoutBlock && 'container')}>
{enableIntro && introContent && !hasSubmitted && (
<RichText className="mb-8 lg:mb-12" data={introContent} enableGutter={false} />
)}
Expand Down
6 changes: 3 additions & 3 deletions src/blocks/GenericEmbed/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { useEffect, useState } from 'react'
import type { GenericEmbedBlock as GenericEmbedBlockProps } from 'src/payload-types'

type Props = GenericEmbedBlockProps & {
isLexical: boolean
isLayoutBlock: boolean
className?: string
}

Expand All @@ -18,7 +18,7 @@ export const GenericEmbedBlockComponent = ({
backgroundColor,
alignContent = 'left',
className,
isLexical = true,
isLayoutBlock = true,
}: Props) => {
const [blobUrl, setBlobUrl] = useState<string | null>(null)

Expand Down Expand Up @@ -83,7 +83,7 @@ export const GenericEmbedBlockComponent = ({
<div className={cn(bgColorClass, textColor)}>
<div
className={cn(
isLexical && 'container py-10',
isLayoutBlock && 'container py-10',
'flex flex-col',
alignContent === 'left' && 'items-start',
alignContent === 'center' && 'items-center',
Expand Down
8 changes: 4 additions & 4 deletions src/blocks/Header/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import getTextColorFromBgColor from '@/utilities/getTextColorFromBgColor'
import { cn } from '@/utilities/ui'

type Props = HeaderBlockProps & {
isLexical: boolean
isLayoutBlock: boolean
fullWidthColor?: boolean
}

export const HeaderBlockComponent = (props: Props) => {
const { backgroundColor, fullWidthColor, richText, isLexical } = props
const { backgroundColor, fullWidthColor, richText, isLayoutBlock } = props

const bgColorClass = `bg-${backgroundColor}`
const textColor = getTextColorFromBgColor(backgroundColor)
Expand All @@ -20,11 +20,11 @@ export const HeaderBlockComponent = (props: Props) => {
className={cn(
'py-4 w-full',
textColor,
{ container: isLexical },
{ container: isLayoutBlock },
!fullWidthColor && `${bgColorClass}`,
)}
>
<RichText data={richText} enableGutter={false} className={cn(!isLexical && 'px-4')} />
<RichText data={richText} enableGutter={false} className={cn(!isLayoutBlock && 'px-4')} />
</div>
</div>
)
Expand Down
6 changes: 3 additions & 3 deletions src/blocks/Media/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import getTextColorFromBgColor from '@/utilities/getTextColorFromBgColor'
const { breakpoints } = cssVariables

type Props = MediaBlockProps & {
isLexical: boolean
isLayoutBlock: boolean
captionClassName?: string
className?: string
imgClassName?: string
Expand All @@ -24,7 +24,7 @@ export const MediaBlockComponent = (props: Props) => {
caption,
captionClassName,
className,
isLexical = true,
isLayoutBlock = true,
imgClassName,
media,
staticImage,
Expand Down Expand Up @@ -74,7 +74,7 @@ export const MediaBlockComponent = (props: Props) => {
<div className={cn(bgColorClass, textColor)}>
<div
className={cn(
isLexical && 'container py-10',
isLayoutBlock && 'container py-10',
'flex flex-col',
alignContent === 'left' && 'items-start',
alignContent === 'center' && 'items-center',
Expand Down
24 changes: 12 additions & 12 deletions src/blocks/RenderBlocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const RenderBlocks = (props: { blocks: Page['layout'][0][]; payload: Payl
{blocks.map((block) => {
return (
<div key={`${block.id}__${block.blockType}`}>
<RenderBlock block={block} payload={props.payload} />
<RenderBlock block={block} />
</div>
)
})}
Expand All @@ -43,42 +43,42 @@ export const RenderBlocks = (props: { blocks: Page['layout'][0][]; payload: Payl
return null
}

export const RenderBlock = ({ block, payload }: { block: Page['layout'][0]; payload: Payload }) => {
export const RenderBlock = ({ block }: { block: Page['layout'][0] }) => {
const { blockType } = block
// if a block has two variants - to make TS happy we fallback to the default for the block variant
switch (blockType) {
case 'blogList':
return <BlogListBlockComponent {...block} isLexical={true} />
return <BlogListBlockComponent {...block} isLayoutBlock={true} />
case 'content':
return <ContentBlockComponent {...block} />
case 'documentBlock':
return <DocumentBlockComponent {...block} isLexical={true} />
return <DocumentBlockComponent {...block} isLayoutBlock={true} />
case 'eventList':
return <EventListBlockComponent {...block} isLexical={true} />
return <EventListBlockComponent {...block} isLayoutBlock={true} />
case 'eventTable':
return <EventTableBlockComponent {...block} isLexical={true} />
return <EventTableBlockComponent {...block} isLayoutBlock={true} />
case 'formBlock':
return <FormBlockComponent {...block} />
case 'genericEmbed':
return <GenericEmbedBlockComponent {...block} isLexical={true} />
return <GenericEmbedBlockComponent {...block} isLayoutBlock={true} />
case 'headerBlock':
return <HeaderBlockComponent {...block} isLexical={true} />
return <HeaderBlockComponent {...block} isLayoutBlock={true} />
case 'imageLinkGrid':
return <ImageLinkGridBlockComponent {...block} />
case 'imageText':
return <ImageTextBlockComponent {...block} />
case 'linkPreview':
return <LinkPreviewBlockComponent {...block} />
case 'mediaBlock':
return <MediaBlockComponent {...block} isLexical={true} />
return <MediaBlockComponent {...block} isLayoutBlock={true} />
case 'nacMediaBlock':
return <NACMediaBlockComponent {...block} />
case 'singleBlogPost':
return <SingleBlogPostBlockComponent {...block} isLexical={true} />
return <SingleBlogPostBlockComponent {...block} isLayoutBlock={true} />
case 'singleEvent':
return <SingleEventBlockComponent {...block} isLexical={true} />
return <SingleEventBlockComponent {...block} isLayoutBlock={true} />
case 'sponsorsBlock':
return <SponsorsBlockComponent {...block} isLexical={true} />
return <SponsorsBlockComponent {...block} isLayoutBlock={true} />
case 'team':
return <TeamBlockComponent {...block} />
}
Expand Down
6 changes: 3 additions & 3 deletions src/blocks/SingleBlogPost/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import { isValidPublishedRelationship } from '@/utilities/relationships'
import { cn } from '@/utilities/ui'

type SingleBlogPostComponentProps = SingleBlogPostBlockProps & {
isLexical: boolean
isLayoutBlock: boolean
className?: string
}

export const SingleBlogPostBlockComponent = ({
post,
backgroundColor,
className,
isLexical = true,
isLayoutBlock = true,
}: SingleBlogPostComponentProps) => {
if (!isValidPublishedRelationship(post)) {
return null
Expand All @@ -22,7 +22,7 @@ export const SingleBlogPostBlockComponent = ({
return (
<BackgroundColorWrapper
backgroundColor={backgroundColor}
isLexical={isLexical}
isLayoutBlock={isLayoutBlock}
containerClassName={className}
>
<PostPreview doc={post} className={cn('not-prose')} />
Expand Down
6 changes: 3 additions & 3 deletions src/blocks/SingleEvent/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import type { SingleEventBlock as SingleEventBlockProps } from '@/payload-types'
import { cn } from '@/utilities/ui'

type SingleEventComponentProps = SingleEventBlockProps & {
isLexical: boolean
isLayoutBlock: boolean
className?: string
}

export const SingleEventBlockComponent = ({
event,
backgroundColor,
className,
isLexical = true,
isLayoutBlock = true,
}: SingleEventComponentProps) => {
if (!event || typeof event !== 'object') {
return null
Expand All @@ -21,7 +21,7 @@ export const SingleEventBlockComponent = ({
return (
<BackgroundColorWrapper
backgroundColor={backgroundColor}
isLexical={isLexical}
isLayoutBlock={isLayoutBlock}
containerClassName={className}
>
<EventPreview event={event} className={cn('not-prose')} />
Expand Down
6 changes: 3 additions & 3 deletions src/blocks/Sponsors/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import { SponsorsBlockCarousel } from './Carousel'
import { SponsorsBlockStatic } from './Static'

type Props = SponsorsBlockProps & {
isLexical: boolean
isLayoutBlock: boolean
}
export const SponsorsBlockComponent = ({
backgroundColor,
sponsors,
sponsorsLayout,
isLexical = false,
isLayoutBlock = false,
}: Props) => {
const now = new Date()

Expand All @@ -26,7 +26,7 @@ export const SponsorsBlockComponent = ({
if (validSponsors.length === 0) return null

return (
<BackgroundColorWrapper backgroundColor={backgroundColor} isLexical={isLexical}>
<BackgroundColorWrapper backgroundColor={backgroundColor} isLayoutBlock={isLayoutBlock}>
<div className="flex flex-wrap justify-evenly items-center">
{(() => {
switch (sponsorsLayout) {
Expand Down
Loading