payload-components
blockcall-to-action-centeredsource: ok · hit
Call To Action Centered
Centered Payload call-to-action block: heading, copy, and one or two CTA links.
npx shadcn add "https://www.payload-components.xyz/r/call-to-action-centered.json"free
Where it goes
cta
Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.
Files3 · source cached 10/9/2026, 4:48:18 AM
payload-components/source/blocks/shared/callToActionFields.ts
import type { Field } from 'payload'
/**
* Shared field core for the Call To Action component family.
*
* Every call-to-action variant (call-to-action-centered, call-to-action-boxed,
* call-to-action-signup, …) spreads these heading fields first and then appends
* its own variant-specific shape — the CTA link group for the centered and boxed
* layouts, or the email-capture fields for the signup layout. Editing the shared
* title/description here updates every installed call-to-action block at once, so
* the family never drifts field-by-field across a repo.
*
* Installed once per repo at `src/blocks/shared/callToActionFields.ts`; re-running
* `payload-components add call-to-action-*` never overwrites a copy you have already edited.
*/
export const callToActionFields: Field[] = [
{
name: 'title',
type: 'text',
custom: { payloadComponents: { localization: 'localized' } },
required: true,
},
{
name: 'description',
type: 'textarea',
custom: { payloadComponents: { localization: 'localized' } },
},
]
payload-components/source/blocks/CallToActionCentered/config.ts
import type { Block } from 'payload'
import { callToActionFields } from '@/blocks/shared/callToActionFields'
import { linkGroup } from '@/fields/linkGroup'
export const CallToActionCentered: Block = {
slug: 'callToActionCentered',
// Existing apps must migrate stored data before adopting this identifier:
// https://www.payload-components.xyz/docs/registry#installed-source-and-migrations
dbName: 'pc_cal_to_act_cen',
interfaceName: 'CallToActionCenteredBlock',
fields: [
// Shared call-to-action core (title, description). Variant-specific fields
// follow; edit the shared shape in @/blocks/shared/callToActionFields.
...callToActionFields,
linkGroup({
overrides: {
admin: {
initCollapsed: true,
},
maxRows: 2,
minRows: 1,
},
}),
],
labels: {
plural: 'Call To Action Centered Blocks',
singular: 'Call To Action Centered',
},
}
payload-components/source/blocks/CallToActionCentered/Component.tsx
import React from 'react'
import type { CallToActionCenteredBlock as CallToActionCenteredBlockData } from '@/payload-types'
import { CMSLink } from '@/components/Link'
import { cn } from '@/utilities/ui'
type Props = CallToActionCenteredBlockData & {
id?: string
className?: string
disableInnerContainer?: boolean
}
export const CallToActionCenteredBlock: React.FC<Props> = ({
className,
description,
disableInnerContainer,
id,
links,
title,
}) => {
return (
<section className={cn('container', className)} id={id ? `block-${id}` : undefined}>
<div className="overflow-hidden rounded-frame border border-border/70 bg-card/35 px-6 py-10 sm:px-8 lg:px-12 lg:py-14">
<div
className={cn('flex flex-col items-center gap-4 text-center', {
'mx-auto max-w-2xl': !disableInnerContainer,
})}
>
<h2 className="text-4xl font-medium tracking-display text-balance sm:text-5xl">{title}</h2>
{description ? (
<p className="text-base leading-7 text-muted-foreground sm:text-lg">{description}</p>
) : null}
{links && links.length > 0 ? (
<div className="flex flex-col justify-center gap-3 pt-2 sm:flex-row">
{links.map(({ link }, index) => (
<CMSLink
key={index}
appearance={link.appearance === 'outline' ? 'outline' : 'default'}
{...link}
/>
))}
</div>
) : null}
</div>
</div>
</section>
)
}