Plan

apps/www/src/sections/Plan.astro · 57 lines · group Pricing

Plan — one item of <Pricing>: name, price + note, features, button. `recommended` highlights the card; `badge` is its label.

In the fleet

Used on 1 site built with this engine.

Samples 1

sampleshown inside <PricingCards>

What a season costs

Hardware included; cancel at the end of any season.

One field

A single station, the essentials.

  • One station
  • Air and soil sensors
  • SMS alerts

€19per month

Estate

Most popular

Up to ten stations and a gateway.

  • Ten stations
  • Leaf wetness and wind
  • Shared forecasts
  • Priority replacement

€39per month

Co-op

Several farms behind one gateway.

  • Unlimited stations
  • Per-farm access
  • API and exports
  • Named support

€79per month

MDX of this sample
<PricingCards title="What a season costs" description="Hardware included; cancel at the end of any season.">
  <Plan name="One field" price="€19" priceNote="per month" description="A single station, the essentials." features={['One station', 'Air and soil sensors', 'SMS alerts']} primaryText="Start" />
  <Plan name="Estate" price="€39" priceNote="per month" recommended description="Up to ten stations and a gateway." features={['Ten stations', 'Leaf wetness and wind', 'Shared forecasts', 'Priority replacement']} primaryText="Start" />
  <Plan name="Co-op" price="€79" priceNote="per month" description="Several farms behind one gateway." features={['Unlimited stations', 'Per-farm access', 'API and exports', 'Named support']} primaryText="Talk to us" />
</PricingCards>

Props

NameTypeRequiredDefaultDescription
namestringyes
pricestringyes
priceNotestring
descriptionstring
featuresstring[][]
featuresTitlestring
recommendedbooleanfalse
badgestring'Most popular'
primaryTextstring
cta'primary' | 'secondary'the button's weight; a lone plan carries the primary action
primaryHrefstring'/#contacts'
linkTextstring
hrefstring

Source apps/www/src/sections/Plan.astro @ gitt.one

---
/**
 * Plan — one item of <Pricing>: name, price + note, features, button.
 * `recommended` highlights the card; `badge` is its label.
 */
import Check from 'astro-heroicons/outline/Check.astro';
import Button from './_Button.astro';

interface Props {
  name: string;
  price: string;
  priceNote?: string;
  description?: string;
  features?: string[];
  featuresTitle?: string;
  recommended?: boolean;
  badge?: string;
  primaryText?: string;
  /** the button's weight; a lone plan carries the primary action */
  cta?: 'primary' | 'secondary';
  primaryHref?: string;
  linkText?: string;
  href?: string;
}
const {
  name, price, priceNote, description, features = [], featuresTitle, recommended = false,
  badge = 'Most popular', primaryText, primaryHref = '/#contacts', linkText, href, cta,
} = Astro.props;
---

<div class:list={['relative flex flex-col rounded-2xl border bg-white shadow-sm [div[data-variant=wide]_&]:lg:flex-row', recommended ? 'border-primary-500' : 'border-gray-200']}>
  <div class="flex-1 p-8 [div[data-variant=single]_&]:pb-0 lg:[div[data-variant=wide]_&]:p-12">
    <h3 class="text-xl font-semibold text-gray-900 [div[data-variant=single]_&]:text-lg [div[data-variant=single]_&]:font-medium [div[data-variant=single]_&]:text-center [div[data-variant=wide]_&]:text-3xl [div[data-variant=wide]_&]:font-extrabold">{name}</h3>
    {recommended && <p class="absolute top-0 -translate-y-1/2 rounded-full bg-primary-600 px-4 py-1.5 text-xs font-semibold uppercase tracking-wide text-white">{badge}</p>}
    {description && <p class="mt-4 text-gray-500">{description}</p>}
    {features.length > 0 && (
      <div class="mt-6">
        {featuresTitle && <h4 class="text-sm font-semibold uppercase tracking-wider text-primary-700">{featuresTitle}</h4>}
        <ul role="list" class="mt-4 list-none space-y-4 [div[data-variant=wide]_&]:lg:grid [div[data-variant=wide]_&]:lg:grid-cols-2 [div[data-variant=wide]_&]:lg:gap-x-8 [div[data-variant=wide]_&]:lg:space-y-0 [div[data-variant=wide]_&]:lg:gap-y-4">
          {features.map((f) => (
            <li class="flex"><Check class="h-6 w-6 flex-shrink-0 text-primary-500" aria-hidden="true" /><span class="ml-3 text-gray-500">{f}</span></li>
          ))}
        </ul>
      </div>
    )}
    <slot />
  </div>
  <div class="border-t border-gray-100 p-8 text-center [div[data-variant=single]_&]:border-t-0 [div[data-variant=single]_&]:pt-0 [div[data-variant=wide]_&]:bg-gray-50 [div[data-variant=wide]_&]:lg:flex [div[data-variant=wide]_&]:lg:flex-col [div[data-variant=wide]_&]:lg:justify-center [div[data-variant=wide]_&]:lg:border-t-0 [div[data-variant=wide]_&]:lg:p-12">
    <p class="flex items-baseline justify-center gap-2 text-gray-900">
      <span class="text-5xl font-extrabold tracking-tight">{price}</span>
      {priceNote && <span class="text-xl font-medium text-gray-500">{priceNote}</span>}
    </p>
    {linkText && href && <p class="mt-4 text-sm"><a href={href} class="font-medium text-gray-500 underline">{linkText}</a></p>}
    {primaryText && <div class="mt-6"><Button href={primaryHref} kind={cta ?? (recommended ? 'primary' : 'secondary')}>{primaryText}</Button></div>}
  </div>
</div>

Source links point to engine-astro@38c294d9. Samples are demo content: the components are the real ones, the copy and the pictures are made up.