HeroCoverpopular

apps/www/src/sections/HeroCover.astro · 71 lines · group Hero

HeroCover — the first screen: a full-width photo under the brand gradient, the title, pitch and buttons centered on top of it. Use for: a landing that opens with a wide, atmospheric photo (a landscape, a workplace, a team) and one short promise. Not for: a product shot that must stay whole (<HeroSplit imageFit="contain">); a page that opens with words alone (<HeroText>). Children: optional markdown between the tags, rendered under the description and above the buttons. No sub-block tags. Picture: LANDSCAPE. It is cropped to fill the section and tinted with the brand colour, so it must not carry text or a logo. Without `image` the section is a plain brand-coloured band. Follow-up: by default the bottom keeps room for a <FeatureCards overlap> row that hangs over the edge. Set overlapNext={false} when the next section is anything else, or the hero ends with an empty band. Buttons: a button appears only when its text is given; primary is the solid brand button, secondary the translucent one.

In the fleet

Used on 3 sites built with this engine.

Samples 2

sample

Weather that pays offin the field, not on a grid cell

A station you install in an hour and forget about for a season. Frost, wind and leaf wetness measured inside the crop, not at the airport twenty kilometres away.

MDX of this sample
<HeroCover
  title="Weather that pays off"
  highlight="in the field, not on a grid cell"
  description="A station you install in an hour and forget about for a season. Frost, wind and leaf wetness measured inside the crop, not at the airport twenty kilometres away."
  image="photo-wide-01.jpg"
  primaryText="Order a station"
  primaryHref="/stations/"
  secondaryText="How it works"
  secondaryHref="/how-it-works/"
/>
sample

Every field on one screen

One dashboard for one orchard or forty. No buttons you will never press.

MDX of this sample
<HeroCover
  title="Every field on one screen"
  description="One dashboard for one orchard or forty. No buttons you will never press."
  image="photo-wide-02.jpg"
  overlapNext={false}
  primaryText="Book a demo"
  primaryHref="/demo/"
/>

Props

NameTypeRequiredDefaultDescription
titlestringyesthe headline, one line
highlightstringa second line of the headline, painted with the brand gradient
descriptionstringthe pitch under the headline, one or two sentences
imagestringfile name in images/, landscape; cropped to fill the section
overlapNextbooleantruekeep room at the bottom for a <FeatureCards overlap> row; false when nothing hangs over
primaryTextstringtext of the solid brand button; omit to hide the button
primaryHrefstring'#'link of the primary button, e.g. "/contacts/" or "#contacts"
secondaryTextstringtext of the second, translucent button
secondaryHrefstring'#'link of the secondary button

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

---
/**
 * HeroCover — the first screen: a full-width photo under the brand gradient,
 *   the title, pitch and buttons centered on top of it.
 *
 * Use for: a landing that opens with a wide, atmospheric photo (a landscape, a
 *   workplace, a team) and one short promise.
 * Not for: a product shot that must stay whole (<HeroSplit
 *   imageFit="contain">); a page that opens with words alone (<HeroText>).
 * Children: optional markdown between the tags, rendered under the description
 *   and above the buttons. No sub-block tags.
 * Picture: LANDSCAPE. It is cropped to fill the section and tinted with the
 *   brand colour, so it must not carry text or a logo. Without `image` the
 *   section is a plain brand-coloured band.
 * Follow-up: by default the bottom keeps room for a <FeatureCards overlap> row
 *   that hangs over the edge. Set overlapNext={false} when the next section is
 *   anything else, or the hero ends with an empty band.
 * Buttons: a button appears only when its text is given; primary is the solid
 *   brand button, secondary the translucent one.
 */
import { Image } from 'astro:assets';
import { resolveImage } from '../lib/images';
import Button from './_Button.astro';

interface Props {
  /** the headline, one line */
  title: string;
  /** a second line of the headline, painted with the brand gradient */
  highlight?: string;
  /** the pitch under the headline, one or two sentences */
  description?: string;
  /** file name in images/, landscape; cropped to fill the section */
  image?: string;
  /** keep room at the bottom for a <FeatureCards overlap> row; false when nothing hangs over */
  overlapNext?: boolean;
  /** text of the solid brand button; omit to hide the button */
  primaryText?: string;
  /** link of the primary button, e.g. "/contacts/" or "#contacts" */
  primaryHref?: string;
  /** text of the second, translucent button */
  secondaryText?: string;
  /** link of the secondary button */
  secondaryHref?: string;
}
const { title, highlight, description, image: imageName, overlapNext = true, primaryText, primaryHref = '#', secondaryText, secondaryHref = '#' } = Astro.props;
const image = imageName ? await resolveImage(imageName) : undefined;
---

<section class:list={['relative bg-primary-900', overlapNext && 'pb-32']}>
  {image && (
    <div class="absolute inset-0">
      <Image src={image} alt="" widths={[400, 840, 1280, 1680]} loading="eager" fetchpriority="high" class="h-full w-full object-cover" />
      <div class="absolute inset-0 bg-gradient-to-r from-primary-800 to-primary-alt-700 mix-blend-multiply" aria-hidden="true" />
    </div>
  )}
  <div class="relative mx-auto max-w-7xl px-4 py-24 text-center sm:px-6 sm:py-32 lg:px-8">
    <h1 class="text-4xl font-extrabold tracking-tight text-white md:text-5xl lg:text-6xl">
      {title}
      {highlight && <span class="block bg-gradient-to-r from-primary-200 to-primary-alt-300 bg-clip-text text-transparent">{highlight}</span>}
    </h1>
    {description && <p class="mx-auto mt-6 max-w-3xl text-xl text-primary-100">{description}</p>}
    <slot />
    {(primaryText || secondaryText) && (
      <div class="mt-10 flex flex-wrap justify-center gap-4">
        {primaryText && <Button href={primaryHref}>{primaryText}</Button>}
        {secondaryText && <Button href={secondaryHref} kind="secondary" onDark>{secondaryText}</Button>}
      </div>
    )}
  </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.