Skip to content

feat(sanity): add FeatureColumns and ProcessSteps sections on a shared Heading - #121

Open
Guseyn wants to merge 1 commit into
mainfrom
feat/heading-sections
Open

Guseyn wants to merge 1 commit into
mainfrom
feat/heading-sections

Conversation

@Guseyn

@Guseyn Guseyn commented Sep 11, 2026

Copy link
Copy Markdown

Adds two page-builder sections and the shared heading component they both reuse.

The shared heading

There was no heading primitive and no title/description schema fragment in the kit — every section declares its own ad hoc title field today. Both halves are new:

  • apps/sanity/src/lib/schemas/heading.ts — a registered object type (required title, optional description), modelled on customImage / customLink. Both sections reference it as type: "heading", so the pair is declared once.
  • packages/ui/components/ui/heading/ — the matching primitive, following the button cva-with-enum pattern.

Alignment is a component prop, not a schema field: no section lets an author choose it, each one knows how it lays itself out. Modelling a knob nobody asked for seemed worse than a default.

The sections

Type Heading Children
section.featureColumns title only featureColumn — icon, title, description
section.processSteps title and description processStep — title, description

Step numbers (01., 02. …) are derived from array position at render time, so reordering in Studio renumbers the list and there is no number field to drift out of sync.

Neither section needs a query.ts GROQ fragment. CARDS_GRID_FRAGMENT exists only to dereference an internal page link via LINK_FRAGMENT; images resolve through prepareImageProps without GROQ help, which is why Carousel has images and no fragment.

Popover fix

packages/sanity-template-selector rendered its popover with no height constraint. The preset grid grows with the number of registered sections, so past a handful it runs off the bottom of the viewport and the last rows cannot be reached. Adding two presets was enough to trigger it.

This is not cosmetic: the selector replaces the array's default add button, so the template browser is the only way to insert a section. Fixed with stock PopoverPropsconstrainSize (cap to available space) plus overflow="auto" — no new dependency, no custom CSS.

Worth knowing: Blog and Carousel are registered but have no presets, which means they cannot currently be added to a page at all.

Verification

  • pnpm gen:types regenerated; Heading is one type, referenced by both SectionFeatureColumns and SectionProcessSteps
  • tsc --noEmit clean on apps/sanity and packages/sanity-template-selector
  • next lint clean (the no-anonymous-default-export warning on the two new schemas matches every existing section schema)
  • Both types present in page.sectionsBody; both preset payloads validated against the registered schema names

Presets ship the copy the sections were designed from, so dropping both onto a page shows the optional-description contrast without typing anything.

Notes for review

Four pre-existing defects surfaced while building this. None are fixed here — happy to send separate PRs:

  1. README says pnpm gen; no such script exists. It is pnpm turbo gen.
  2. templates/sanitySection.hbs imports I<Name>SectionProps but sanitySectionTypes.hbs exports I<Name>Props — generated code does not compile.
  3. templates/sanitySectionSchema.hbs imports sectionMarginFields, which commonFields.tsx does not export (it is sectionCommonFields) — also does not compile.
  4. The schema template writes name: "section.{{ sectionName }}" from raw input while the render map uses {{ loweraseFirstLetter sectionName }}. Entering FeatureColumns yields schema section.FeatureColumns against map key section.featureColumns — the section saves fine in Studio and silently renders nothing. Entering camelCase avoids it. This one fails silently, unlike 2 and 3.

Separately, pnpm format is broken repo-wide: prettier.config.js sets tailwindConfig: "./packages/ui/tailwind.config.ts", which no longer exists after the Tailwind v4 migration. The generator's inserted lines are hand-formatted in this PR as a result.

🤖 Generated with Claude Code

…d Heading

Adds two page-builder sections and, more to the point, the shared heading they
both reuse — there was no heading primitive or title/description schema
fragment in the kit, so every section declared its own ad hoc `title` field.

- `lib/schemas/heading.ts`: a registered object type (required `title`,
  optional `description`), modelled on `customImage`/`customLink`, referenced
  by both sections as `type: "heading"`.
- `packages/ui/components/ui/heading`: the matching primitive, following the
  `button` cva-with-enum pattern. Alignment is a prop rather than a schema
  field — no section lets an author choose it, each knows its own layout.
- `section.featureColumns`: heading (title only) plus `featureColumn` items.
- `section.processSteps`: heading (title and description) plus `processStep`
  items. Numbering is derived from array position at render, so reordering in
  Studio renumbers the list and there is no number field to keep in sync.

Both presets ship the real copy they were designed from, which also makes the
optional-description contrast visible without typing anything.

Also fixes the template-selector popover, which had no height constraint: the
preset grid grows with the number of registered sections and was running off
the bottom of the viewport, making the last rows unreachable. This is the only
way to insert a section, since the selector replaces the array's default add
button, so it blocked the new sections outright.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
turbo-cms-kit-sanity Ready Ready Preview Sep 11, 2026 5:33am UTC
turbo-cms-kit-storyblok Ready Ready Preview Sep 11, 2026 5:33am UTC
turbo-cms-kit-storyblok-preview Ready Ready Preview Sep 11, 2026 5:33am UTC

Request Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant