CtaSplit
apps/www/src/sections/CtaSplit.astro · 68 lines · group Call to action
CtaSplit — a call to action with a picture beside it: the hero's shape used mid-page, asking for the next step rather than opening the site. Use for: a prompt that has a picture worth showing — the product, the app, the team — typically on a dark band near the end of the page. Not for: the first screen (<HeroSplit>, which renders the page <h1>); a prompt without a picture (<CtaBanner>). Children: none. Picture: `image` (file name in images/) is shown whole, capped in height — a product shot or a screenshot; a wide photo gets small. Theme: "dark" by default; "light" and "muted" turn the text dark.
In the fleet
Used on 1 site built with this engine.
Samples 1
Try it for one seasonSend it back if it does not earn its place.
One station, one gateway, the full dashboard. No installation fee and no contract for the first season.

MDX of this sample
<CtaSplit
title="Try it for one season"
highlight="Send it back if it does not earn its place."
description="One station, one gateway, the full dashboard. No installation fee and no contract for the first season."
image="product-02.jpg"
primaryText="Start the season"
primaryHref="/trial/"
secondaryText="What it costs"
secondaryHref="/pricing/"
/>Props
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| id | string | anchor of the section | ||
| title | string | yes | the prompt | |
| highlight | string | a second line under the title, painted with the brand gradient | ||
| description | string | a sentence or two under the title | ||
| image | string | file name in images/, shown whole beside the text | ||
| imageSide | 'left' | 'right' | 'right' | which side the picture takes | |
| theme | 'light' | 'muted' | 'dark' | 'brand' | 'brand-dark' | 'dark' | background of the band (default "dark") | |
| primaryText | string | text of the solid brand button; omit to hide the button | ||
| primaryHref | string | '#' | link of the primary button | |
| secondaryText | string | text of the second, outlined button | ||
| secondaryHref | string | '#' | link of the secondary button |
Source apps/www/src/sections/CtaSplit.astro @ gitt.one
---
/**
* CtaSplit — a call to action with a picture beside it: the hero's shape used
* mid-page, asking for the next step rather than opening the site.
*
* Use for: a prompt that has a picture worth showing — the product, the app,
* the team — typically on a dark band near the end of the page.
* Not for: the first screen (<HeroSplit>, which renders the page <h1>); a
* prompt without a picture (<CtaBanner>).
* Children: none.
* Picture: `image` (file name in images/) is shown whole, capped in height — a
* product shot or a screenshot; a wide photo gets small.
* Theme: "dark" by default; "light" and "muted" turn the text dark.
*/
import { Image } from 'astro:assets';
import { resolveImage } from '../lib/images';
import Section from './_Section.astro';
import type { Theme } from './_Section.astro';
import Button from './_Button.astro';
interface Props {
/** anchor of the section */
id?: string;
/** the prompt */
title: string;
/** a second line under the title, painted with the brand gradient */
highlight?: string;
/** a sentence or two under the title */
description?: string;
/** file name in images/, shown whole beside the text */
image?: string;
/** which side the picture takes */
imageSide?: 'left' | 'right';
/** background of the band (default "dark") */
theme?: Theme;
/** text of the solid brand button; omit to hide the button */
primaryText?: string;
/** link of the primary button */
primaryHref?: string;
/** text of the second, outlined button */
secondaryText?: string;
/** link of the secondary button */
secondaryHref?: string;
}
const { id, title, highlight, description, image, imageSide = 'right', theme = 'dark', primaryText, primaryHref = '#', secondaryText, secondaryHref = '#' } = Astro.props;
const left = imageSide === 'left';
const img = image ? await resolveImage(image) : undefined;
---
<Section id={id} theme={theme}>
<div class="lg:grid lg:grid-cols-2 lg:items-center lg:gap-12">
<div class:list={[left && 'lg:order-2']}>
<h2 class="text-3xl font-extrabold tracking-tight sm:text-4xl">
{title}
{highlight && <span class="block bg-gradient-to-r from-primary-300 to-primary-alt-400 bg-clip-text text-transparent [.bg-white_&]:from-primary-500 [.bg-white_&]:to-primary-alt-600">{highlight}</span>}
</h2>
{description && <p class="mt-6 text-xl text-primary-100 [.bg-white_&]:text-gray-500 [.bg-gray-50_&]:text-gray-500">{description}</p>}
{(primaryText || secondaryText) && (
<div class="mt-8 flex flex-wrap gap-4">
{primaryText && <Button href={primaryHref}>{primaryText}</Button>}
{secondaryText && <Button href={secondaryHref} kind="secondary" onDark={theme !== 'light' && theme !== 'muted'}>{secondaryText}</Button>}
</div>
)}
</div>
{img && <Image src={img} alt="" widths={[400, 840, 1280]} class:list={['mt-10 w-full max-h-[26rem] object-contain lg:mt-0', left && 'lg:order-1']} />}
</div>
</Section>Source links point to engine-astro@7b686388. Samples are demo content: the components are the real ones, the copy and the pictures are made up.