FairGarden Design

CTA Block

The page's one closing invitation before the footer: "Keep exploring", "Find a land trust near you". A labelled section with a kicker, a centered serif headline, an optional support line, the action pill with its leading arrow and an optional outline twin. The saturated and deep kinds are a CTA field, an inset Ground of kind="field", never a full-bleed band.

import { CTABlock } from '@fairgarden-private/design/components/CTABlock'

action and secondaryAction take a title-case label and an href (or onClick); the block builds the 48 px solid pill and its outline twin. Never use it for a form (use Newsletter), a repeated mid-page promo or a floating bar.

Kinds

Kinds

sunburst (default) and mission sit on their band's page ground, with the headline in --primary12 because only that ink sits on a pattern. The sunburst kind draws its own ornament: the dashed trail before the kicker, in the accent, and the dotted sunburst in the tint, rising from 40 px below the block and clipped at that line. Pass trail or decor to replace them with your own art, or null to leave them out. mission sets its mount mark on the blob mount: a hand-cut disc in the secondary's step 9 (green by default) over a larger, turned under-disc in step 7, with the mark in the disc's contrast ink; its speckle belongs on the band's Ground (patternSpeckle), so it runs full-bleed. The kicker starts about 15% of the column in while the headline centers. deep is a forest (or royal) field; saturated a campaign field (amber by default, leaf, clay, royal or brick) with one ink and the ink pill. Fields take a 20 px radius and their one-ink edge, and keep a gutter of page ground from other fields and the band's padding from the night footer. framed draws the crop-mark box for technical pages. From 768 px of its own width, the deep and framed kinds split headline 7, actions 5.

Keep exploring

Find a land trust near you

We protect the places you love

Local land trusts work with their neighbors to keep farms, forests and trails open for good.

Become a member and protect the places you love

Members fund easements, stewardship and the trails you walk.

Plant 10,000 trees this spring

Request a survey of your land

CTABlockKinds.tsx
import { CTABlock } from '@fairgarden-private/design/components/CTABlock'
import styles from './kinds.module.css'

/** A simple leaf mark for the blob mount, drawn in currentColor (the front disc's contrast ink). */
function LeafMark() {
  return (
    <svg className={styles.mark} viewBox="0 0 48 48" aria-hidden="true" focusable="false">
      <path d="M10 38C10 20 22 9 40 8c0 18-11 30-29 30Z" />
      <path d="M10 38 28 20" />
    </svg>
  )
}

/**
 * The page-ground sunburst kind (its trail and sunburst drawn by default),
 * the mission kind on its blob mount, the deep forest field, the saturated
 * amber field and the framed box.
 */
export function CTABlockKinds() {
  return (
    <div className={styles.stack}>
      <CTABlock
        kicker="Keep exploring"
        headline="Find a land trust near you"
        action={{ label: 'Find a Land Trust', href: 'https://example.org/find' }}
      />
      <CTABlock
        kind="mission"
        mount={<LeafMark />}
        headline="We protect the places you love"
        support="Local land trusts work with their neighbors to keep farms, forests and trails open for good."
        action={{ label: 'Our Mission', href: 'https://example.org/mission' }}
      />
      <CTABlock
        kind="deep"
        headline="Become a member and protect the places you love"
        support="Members fund easements, stewardship and the trails you walk."
        action={{ label: 'Join Today', href: 'https://example.org/join' }}
        secondaryAction={{ label: 'Learn More', href: 'https://example.org/membership' }}
      />
      <CTABlock
        kind="saturated"
        headline="Plant 10,000 trees this spring"
        action={{ label: 'Give a Tree', href: 'https://example.org/trees' }}
      />
      <CTABlock
        kind="framed"
        headline="Request a survey of your land"
        action={{ label: 'Enquire', href: 'https://example.org/survey' }}
      />
    </div>
  )
}

In print

The sunburst and the blob's discs drop and the block reads completely without them; the trail prints black at 0.75 pt, the blob's mark prints black, and the actions print "Label (URL)". A CTA field prints its edge as a black frame, the page-ground kinds print between rules, and the framed kind's dashed frame and corner marks print as they are.

API Reference

The CTA block. At most one per page, the page’s ornament peak; never a form (use Newsletter), a repeated mid-page promo or a floating bar. In print the ornament drops, the action prints “Label (short URL)” and a CTA field prints its edge as a black frame.

PropTypeDescription
action
CTAAction

The primary action: the solid pill at --size-px-8 with a leading arrow.

decor
React.ReactNode | undefined

Decoration behind the content, in --role-tint, clipped by the block (the sunburst kind’s reaches --ds-space-40 below it). Omitted, the sunburst kind draws pattern-sunburst from an origin --ds-space-40 below the block’s bottom edge, and the other kinds none; pass your own art in currentColor (centred on the bottom edge), or null for none. A mission band’s pattern-speckle belongs on its band’s Ground, which is full-bleed. Dropped in print; the block reads completely without it. Sunburst ≤ 1 per page.

field
CTASaturatedField | CTADeepField | undefined
headingLevel
2 | 3 | undefined

The headline’s level. Default 2.

headline
React.ReactNode

The headline, type-h2, centered, ≤ 45ch and ≤ 4 lines. It names the section.

kicker
React.ReactNode | undefined

The kicker (type-kicker, --role-heading), starting ≈ 15% of the column in while the headline centers (LTA).

kind
| 'sunburst'
| 'mission'
| 'framed'
| 'saturated'
| 'deep'
| undefined

sunburst (default): trail kicker, centered serif headline, arrow pill, the sunburst rising behind (white or the page ground, just before the footer). mission: blob mount, centered H2, body, pill. framed: the crop-mark box (technical pages). saturated: the campaign field, one ink. deep: a forest or royal field with the pill and its outline twin.

mount
React.ReactNode | undefined

mission only: the mark on the blob mount (ornament-blob, an OrnamentBlob): a logo, block icon or numeral in currentColor, which takes the front disc’s --secondary-contrast, about 57 px wide. The discs are --secondary9 over --secondary7; once per page, never on fields. In print the discs drop and the mark prints black.

patterned
boolean | undefined

patterned: the headline takes --primary12, since only --primary12 text sits on a pattern. Always on for sunburst and mission. Default false.

primary
| 'ruby'
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'crimson'
| 'tomato'
| 'pink'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| null
| undefined

Primary Radix scale: text, rules, marks and the outline twin. Never defaulted; omitted, it inherits the scope [D133].

secondary
| 'ruby'
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'crimson'
| 'tomato'
| 'pink'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| 'amber'
| 'blue'
| 'cyan'
| 'grass'
| 'green'
| 'jade'
| 'lime'
| 'mint'
| 'orange'
| 'sky'
| 'teal'
| 'yellow'
| null
| undefined

Secondary Radix scale: kicker and unpatterned headline, trail, blob discs. Never defaulted.

secondaryAction
CTAAction | undefined

The optional outline twin, same height.

support
React.ReactNode | undefined

An optional support line, --primary12.

trail
React.ReactNode | undefined

The trail before the kicker, in --role-accent, ≤ --size-px-12 wide. Omitted, the sunburst kind draws ornament-trail (<OrnamentTrail />, the short tail) and the other kinds none; pass your own aria-hidden SVG in currentColor, or null for none. It prints at 0.75 pt.

CTAAction

An action: title-case label, authored [D160]; a destination prints as “Label (short URL)".

type CTAAction = {
  /** Verb plus object, title case: "Find a Land Trust". */
  label: string;
  /** Where it goes; the Button renders an anchor. */
  href?: string;
  /** Called on click (with or without `href`). */
  onClick?: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
}
ctaBlock
CTABlockProps

Props for CTABlock: section props, the kind (with its field for the field kinds), the headline and its companions, the actions, the decoration and the color axes.

type CTABlockProps = CTABlockPageProps | CTABlockSaturatedProps | CTABlockDeepProps
CTADeepField

The deep field’s presets: forest, or royal (the companion of tide and heather) [D177].

type CTADeepField = 'forest' | 'royal'
CTASaturatedField

The saturated campaign field’s presets [D177, D180].

type CTASaturatedField = 'amber' | 'leaf' | 'clay' | 'royal' | 'brick'

Specification: DESIGN-SYSTEM.md §11.10 (CTA banner; the CTA field per D177 and D180) and §4.5.5 (crop marks).