PlanItem

apps/www/src/components/PlanItem.astro · 89 lines · group Pricing

Used by

No site uses it, neither now nor in the content repos’ history.

Samples 1

synthetic sample — no site uses this componentshown inside <PlanSection>

Hosting plans

Three sizes of the same virtual machine

Small

$19Per month

For a landing page

  • 2 GB RAM
  • 1 CPU
  • 40 GB SSD
Order

Medium

Most popular

$39Per month

For a shop

  • 4 GB RAM
  • 2 CPU
  • 80 GB SSD
Order

Large

$79Per month

For everything else

  • 8 GB RAM
  • 4 CPU
  • 160 GB SSD
Order
MDX of this sample
<PlanSection title="Hosting plans" description="Three sizes of the same virtual machine">
  <PlanItem name="Small" price="19" description="For a landing page" ramCapacity="2 GB" coresAmount="1" ssdCapacity="40 GB" callToAction="Order" />
  <PlanItem name="Medium" price="39" recommended description="For a shop" ramCapacity="4 GB" coresAmount="2" ssdCapacity="80 GB" callToAction="Order" />
  <PlanItem name="Large" price="79" description="For everything else" ramCapacity="8 GB" coresAmount="4" ssdCapacity="160 GB" callToAction="Order" />
</PlanSection>

Props

NameTypeRequiredDefaultDescription
namestringyes
pricenumber | stringyes
recommendedbooleanfalse
descriptionstring
ramCapacitystring
coresAmountstring
ssdCapacitystring
callToActionstring
callToActionPathstring'/#contacts'

Source apps/www/src/components/PlanItem.astro @ gitt.one

---
import Check from 'astro-heroicons/solid/Check.astro';

interface Props {
  name: string;
  price: number | string;
  recommended?: boolean;
  description?: string;
  ramCapacity?: string;
  coresAmount?: string;
  ssdCapacity?: string;
  callToAction?: string;
  callToActionPath?: string;
}

const {
  name,
  price,
  recommended = false,
  description,
  ramCapacity,
  coresAmount,
  ssdCapacity,
  callToAction,
  callToActionPath = '/#contacts',
} = Astro.props;

const features = [
  ramCapacity && `${ramCapacity} RAM`,
  coresAmount && `${coresAmount} CPU`,
  ssdCapacity && `${ssdCapacity} SSD`,
].filter(Boolean) as string[];
---

<div
  class:list={[
    'relative flex flex-col rounded-2xl border bg-white p-8 shadow-sm',
    recommended ? 'border-primary-500' : 'border-gray-200',
  ]}
>
  <div class="flex-1">
    <h3 class="text-xl font-semibold text-gray-900">{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">
          Most popular
        </p>
      )
    }
    <p class="mt-4 flex items-baseline text-gray-900">
      <span class="text-5xl font-extrabold tracking-tight">${price}</span>
      <span class="ml-1 text-xl font-semibold">Per month</span>
    </p>
    {description && <p class="mt-6 text-gray-500">{description}</p>}

    {
      features.length > 0 && (
        <ul role="list" class="mt-6 list-none space-y-6">
          {features.map((feature) => (
            <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">{feature}</span>
            </li>
          ))}
        </ul>
      )
    }
  </div>

  {
    callToAction && (
      <a
        href={callToActionPath}
        class:list={[
          'mt-8 block w-full rounded-md border border-transparent px-6 py-3 text-center font-medium',
          recommended
            ? 'bg-primary-600 text-white hover:bg-primary-700'
            : 'bg-primary-50 text-primary-700 hover:bg-primary-100',
        ]}
      >
        {callToAction}
      </a>
    )
  }
</div>

Source links point to engine-astro@e857a859. Samples are cut from the sites' own content by scripts/gallery-extract.mjs; nothing is merged or removed yet.