StatsBanner

apps/www/src/sections/StatsBanner.astro · 61 lines · group Stats

StatsBanner — numbers on a wide dark band, the photo bleeding across the right half under a fade, the figures in two columns (<Stat value label detail />): the "in numbers" band of a landing page.

In the fleet

Used on 1 site built with this engine.

Samples 1

sample

IN NUMBERS

Measured, not estimated

Every figure below comes from stations that are running right now, in orchards, greenhouses and open fields.

stations installedfrom a single greenhouse to a forty-field estate
>3 000
uptime last seasoncounted per station, not per network
99,4%
of readingsthe oldest station still reporting today
8 yrs
countrieswherever the crop and the frost meet
14
MDX of this sample
<StatsBanner
  kicker="IN NUMBERS"
  title="Measured, not estimated"
  description="Every figure below comes from stations that are running right now, in orchards, greenhouses and open fields."
  image="photo-wide-03.jpg"
  primaryText="See the coverage"
  primaryHref="/coverage/"
>
  <Stat value=">3 000" label="stations installed" detail="from a single greenhouse to a forty-field estate" />
  <Stat value="99,4%" label="uptime last season" detail="counted per station, not per network" />
  <Stat value="8 yrs" label="of readings" detail="the oldest station still reporting today" />
  <Stat value="14" label="countries" detail="wherever the crop and the frost meet" />
</StatsBanner>

Props

NameTypeRequiredDefaultDescription
idstring
kickerstring
titlestring
descriptionstring | string[]
imagestring
primaryTextstring
primaryHrefstring
secondaryTextstring
secondaryHrefstring

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

---
/**
 * StatsBanner — numbers on a wide dark band, the photo bleeding across the
 * right half under a fade, the figures in two columns (<Stat value label
 * detail />): the "in numbers" band of a landing page.
 */
import { Image } from 'astro:assets';
import { resolveImage } from '../lib/images';
import Button from './_Button.astro';

interface Props {
  id?: string;
  kicker?: string;
  title?: string;
  description?: string | string[];
  image?: string;
  primaryText?: string;
  primaryHref?: string;
  secondaryText?: string;
  secondaryHref?: string;
}
const p = Astro.props;
const paragraphs = p.description === undefined ? [] : Array.isArray(p.description) ? p.description : [p.description];
const img = p.image ? await resolveImage(p.image) : undefined;
const primaryHref = p.primaryHref ?? '#';
const secondaryHref = p.secondaryHref ?? '#';
---

<section id={p.id} class="relative bg-gray-900 text-white">
  {img && (
    <div class="absolute inset-x-0 bottom-0 h-80 xl:inset-y-0 xl:h-full" aria-hidden="true">
      <div class="h-full w-full xl:grid xl:grid-cols-2">
        <div class="h-full xl:relative xl:col-start-2">
          <Image src={img} alt="" widths={[400, 840, 1280]} class="absolute inset-0 h-full w-full max-w-none object-cover opacity-25" />
          <div class="absolute inset-x-0 top-0 h-32 bg-gradient-to-b from-gray-900 xl:inset-y-0 xl:left-0 xl:h-full xl:w-32 xl:bg-gradient-to-r" />
        </div>
      </div>
    </div>
  )}
  <div class="mx-auto max-w-4xl px-4 sm:px-6 lg:max-w-7xl lg:px-8 xl:grid xl:grid-flow-col-dense xl:grid-cols-2 xl:gap-x-8">
    <div class="relative pb-64 pt-12 sm:pb-64 sm:pt-24 xl:col-start-1 xl:pb-24">
      {p.kicker && (
        <h2 class="text-sm font-semibold uppercase tracking-wide">
          <span class="bg-gradient-to-r from-primary-300 to-primary-alt-400 bg-clip-text text-transparent">{p.kicker}</span>
        </h2>
      )}
      {p.title && <p class="mt-3 text-3xl font-extrabold text-white">{p.title}</p>}
      {paragraphs.map((x) => <p class="mt-5 text-lg text-gray-300">{x}</p>)}
      <dl class="mt-12 grid grid-cols-1 gap-x-6 gap-y-12 sm:grid-cols-2" data-variant="banner">
        <slot />
      </dl>
      {(p.primaryText || p.secondaryText) && (
        <div class="mt-10 flex flex-wrap gap-4">
          {p.primaryText && <Button href={primaryHref}>{p.primaryText}</Button>}
          {p.secondaryText && <Button href={secondaryHref} kind="secondary" onDark>{p.secondaryText}</Button>}
        </div>
      )}
    </div>
  </div>
</section>

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.