Documentation
Page blocksComparator

Comparator Stack

A stacked plan-card comparison — one card per plan with its own price, CTA, and per-plan feature checklist.

v0.1.0Page blockComparator familyPlan cards
import type { Block } from 'payload'import { comparatorFields } from '@/blocks/shared/comparatorFields'import { linkGroup } from '@/fields/linkGroup'export const ComparatorStack: Block = {  slug: 'comparatorStack',  interfaceName: 'ComparatorStackBlock',  fields: [    // Shared comparator header (title, description). Variant-specific fields    // follow; edit the shared shape in @/blocks/shared/comparatorFields.    ...comparatorFields,    {      name: 'plans',      type: 'array',      required: true,      minRows: 2,      maxRows: 4,      admin: {        initCollapsed: true,      },      fields: [        {          name: 'name',          type: 'text',          required: true,        },        {          name: 'description',          type: 'text',        },        {          name: 'price',          type: 'text',        },        {          name: 'period',          type: 'text',          admin: {            description: 'Shown next to the price, e.g. "/month".',          },        },        {          name: 'badge',          type: 'text',          admin: {            description: 'Optional pill beside the plan name, e.g. "Most popular".',          },        },        {          name: 'highlighted',          type: 'checkbox',          admin: {            description: 'Adds an accent ring to draw the eye to the recommended plan.',          },        },        linkGroup({          overrides: {            maxRows: 1,          },        }),        {          name: 'features',          type: 'array',          admin: {            initCollapsed: true,          },          fields: [            {              name: 'label',              type: 'text',              required: true,            },            {              name: 'included',              type: 'checkbox',            },            {              name: 'value',              type: 'text',              admin: {                description: 'Text value for this feature. Leave "included" unticked and this empty for an excluded feature.',              },            },          ],        },      ],    },  ],  labels: {    plural: 'Comparator Stack Blocks',    singular: 'Comparator Stack',  },}

Installation

npx payload-components add comparator-stack

Copy the files straight from the registry, then wire the Payload fragments by hand:

pnpm dlx shadcn@latest add https://www.payload-components.xyz/r/comparator-stack.json

What it installs

Copies 3 source files into your project:

  • src/blocks/shared/comparatorFields.tsshared
  • src/blocks/ComparatorStack/config.ts
  • src/blocks/ComparatorStack/Component.tsx

…and makes 4 edits to wire the block into your project:

Registers the blocksrc/collections/Pages/index.ts
Maps the renderersrc/blocks/RenderBlocks.tsx
Regenerates typessrc/payload-types.ts
Regenerates the admin import mapsrc/app/(payload)/admin/importMap.js
comparatorFields.ts is the shared field core for this family — every variant composes it. Editing it updates each installed block at once, and re-running an install never overwrites a copy you have changed.

Re-running the install converges: it detects existing wiring, skips it, and records install state in .payload-components/state.json.

Content model

title and description come from the shared Comparator family base (src/blocks/shared/comparatorFields.ts); the plans stack is specific to this variant. Unlike the table and grid variants, each plan carries its own features checklist rather than sharing one matrix — good for mobile-first, plan-centric pages.

Prop

Type

Each item in plans carries:

Prop

Type

Each item in a plan's features carries:

Prop

Type

Usage

Add the block to a page. In the Payload admin, open (or create) a Page and add the ComparatorStack block to its layout.
Fill the content. Complete the fields from the content model above — the component ships sample content you can start from.
Publish. Save and publish the page; the block renders through RenderBlocks on the frontend, fully typed — no extra wiring.

Requirements

Target
payload-website-starter
Payload
v3
Next.js
15 / 16
shadcn UI
badge, card

Your project must already expose components.json, src/payload.config.ts, src/blocks/RenderBlocks.tsx, src/collections/Pages/index.ts — the surfaces payload-components add patches. The CLI verifies this against the support matrix before touching anything.

In this family