CompareItempopular

apps/www/src/sections/CompareItem.astro · 55 lines · group Compare

CompareItem — one side of a <Compare>: a card with a picture, a code sample (`code` + `file`), an icon, bullets, and markdown children. *emphasis* inside `description` strings is painted in the brand color (the convention inherited from the older sites).

In the fleet

Used on 3 sites built with this engine.

Samples 1

sampleshown inside <Compare>

TWO WAYS TO RUN IT

Cloud or your own server

The stations do not care; the data can live where your policy says it should.

Nordvind Cloud

Nordvind Cloud

We keep the servers, the backups and the forecasts up to date.

  • Nothing to install
  • Forecasts included
  • Updates on the day they ship
On your own server

On your own server

The same software inside your network, on your hardware.

  • Data never leaves the farm
  • Your backup policy
  • Yearly licence
MDX of this sample
<Compare columns={2} kicker="TWO WAYS TO RUN IT" title="Cloud or your own server" description="The stations do not care; the data can live where your policy says it should.">
  <CompareItem title="Nordvind Cloud" description="We keep the servers, the backups and the forecasts up to date." bullets={['Nothing to install', 'Forecasts included', 'Updates on the day they ship']} image="screen-01.png" />
  <CompareItem title="On your own server" description="The same software inside your network, on your hardware." bullets={['Data never leaves the farm', 'Your backup policy', 'Yearly licence']} image="screen-02.png" />
</Compare>

Props

NameTypeRequiredDefaultDescription
titlestringyes
kickerstring
descriptionstring | string[]
imagestring
Iconany
bulletsstring[][]
codestring
filestring

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

---
/**
 * CompareItem — one side of a <Compare>: a card with a picture, a code
 * sample (`code` + `file`), an icon, bullets, and markdown children.
 * *emphasis* inside `description` strings is painted in the brand color
 * (the convention inherited from the older sites).
 */
import { Image } from 'astro:assets';
import { resolveImage } from '../lib/images';

interface Props {
  title: string;
  kicker?: string;
  description?: string | string[];
  image?: string;
  Icon?: any;
  bullets?: string[];
  code?: string;
  file?: string;
}
const { title, kicker, description, image, Icon, bullets = [], code, file } = Astro.props;
const img = image ? await resolveImage(image) : undefined;
const paragraphs = description === undefined ? [] : Array.isArray(description) ? description : [description];
---

<div class="flex flex-col overflow-hidden rounded-lg bg-white text-gray-900 shadow-lg">
  {img && <Image src={img} alt={title} widths={[400, 840]} class="h-48 w-full max-w-full flex-shrink-0 object-contain" />}
  <div class="flex flex-1 flex-col p-6">
    <div class="flex items-center gap-3">
      {Icon && <span class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-md bg-gradient-to-r from-primary-500 to-primary-alt-600"><Icon class="h-5 w-5 text-white" aria-hidden="true" /></span>}
      {kicker && <code class="rounded bg-gray-50 px-2 py-1 font-mono text-sm text-primary-700 ring-1 ring-inset ring-primary-100">{kicker}</code>}
    </div>
    <h3 class:list={['text-xl font-semibold', (Icon || kicker) && 'mt-4']}>{title}</h3>
    {paragraphs.length > 0 && (
      <div class="mt-3 text-base text-gray-500">
        {paragraphs.map((p) => (
          <p class="my-2">{p.split('*').map((chunk, i) => <span class:list={[i % 2 === 1 && 'text-primary-600']}>{chunk}</span>)}</p>
        ))}
      </div>
    )}
    {bullets.length > 0 && (
      <ul class="mt-4 list-none space-y-3 text-base text-gray-500">
        {bullets.map((b) => <li class="flex"><span aria-hidden="true" class="mr-3 mt-2 h-1.5 w-1.5 flex-none rounded-full bg-gradient-to-r from-primary-500 to-primary-alt-600" /><span>{b}</span></li>)}
      </ul>
    )}
    {code !== undefined && (
      <div class="mt-4 flex flex-grow flex-col overflow-hidden rounded-xl bg-gray-900 shadow-lg">
        {file && <div class="border-b border-white/10 px-4 py-2 font-mono text-xs uppercase tracking-wide text-gray-400">{file}</div>}
        <pre class="flex-grow overflow-x-auto px-4 py-4 text-sm leading-relaxed text-gray-100"><code>{code}</code></pre>
      </div>
    )}
    <div class="text-base text-gray-500 [&>p]:mt-2"><slot /></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.