FeatureCardspopular
apps/www/src/sections/FeatureCards.astro · 81 lines · group Features & lists
FeatureCards — a grid of cards, one <Feature> per card: services, benefits, reasons to choose, audiences. Use for: three to six parallel items of equal weight, each with an icon or a picture and a sentence or two. The most used section of the library. Not for: a dense list of many short points (<FeatureList>, no cards); one topic explained in several points beside a heading (<FeatureAside>); a numbered process (<Steps>); a choice between two or three things (<Compare>). Children: <Feature> tags only, three or more. Content written directly between the tags is not rendered. Layout: `columns` 1–4 (default 3); the cards wrap to one column on phones. `overlap` pulls the grid up over the previous section — pair it with a <HeroCover> right above (its default overlapNext keeps the room). `heading="left"` or a `kicker` moves the heading out of the centre. Look: `icons="soft"` paints the icon squares in a pale tint instead of the brand gradient; `decor="dots"` adds the decorative dot grid; on theme="brand" the cards turn translucent white on the gradient. Link: `linkText` + `href` add one centered button under the grid.
In the fleet
Used on 4 sites built with this engine.
Samples 3
WHY NORDVIND
What the station actually changes
Frost alerts
Threshold, rate of fall and dew point, checked every minute inside the crop.
Leaf wetness
Tells you whether the spray will hold before you fill the tank.
Offline buffer
The gateway keeps a week of readings when the uplink drops.
MDX of this sample
import BoltIcon from 'astro-heroicons/outline/Bolt.astro';
import SignalIcon from 'astro-heroicons/outline/Signal.astro';
import CloudIcon from 'astro-heroicons/outline/Cloud.astro';
<FeatureCards kicker="WHY NORDVIND" title="What the station actually changes" columns={3}>
<Feature title="Frost alerts" description="Threshold, rate of fall and dew point, checked every minute inside the crop." Icon={BoltIcon} />
<Feature title="Leaf wetness" description="Tells you whether the spray will hold before you fill the tank." Icon={CloudIcon} />
<Feature title="Offline buffer" description="The gateway keeps a week of readings when the uplink drops." Icon={SignalIcon} />
</FeatureCards>Built to be left alone
One battery
A full season on a single charge.
One bolt
Mounts on any standard post.
No tools
Sensors swap by hand, in the field.
No visits
Firmware arrives over the air.
MDX of this sample
<FeatureCards theme="dark" icons="soft" columns={4} heading="left" title="Built to be left alone">
<Feature number="1" title="One battery" description="A full season on a single charge." />
<Feature number="2" title="One bolt" description="Mounts on any standard post." />
<Feature number="3" title="No tools" description="Sensors swap by hand, in the field." />
<Feature number="4" title="No visits" description="Firmware arrives over the air." />
</FeatureCards>Three things growers ask us first
Does it work without coverage?
Yes — the gateway buffers and syncs when the network returns.
- A week of storage
- No lost readings
Can I export the data?
CSV, PDF and an open API. The readings belong to the farm.
What if a sensor fails?
You hear it from us before you notice it, and the spare fits in a pocket.
MDX of this sample
import SignalIcon from 'astro-heroicons/outline/Signal.astro';
import ShieldIcon from 'astro-heroicons/outline/ShieldCheck.astro';
import BatteryIcon from 'astro-heroicons/outline/Battery50.astro';
<FeatureCards overlap columns={3} title="Three things growers ask us first" decor="dots">
<Feature title="Does it work without coverage?" description="Yes — the gateway buffers and syncs when the network returns." Icon={SignalIcon} bullets={['A week of storage', 'No lost readings']} />
<Feature title="Can I export the data?" description="CSV, PDF and an open API. The readings belong to the farm." Icon={ShieldIcon} />
<Feature title="What if a sensor fails?" description="You hear it from us before you notice it, and the spare fits in a pocket." Icon={BatteryIcon} linkText="Warranty" href="/warranty/" />
</FeatureCards>Props
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| id | string | anchor of the section, e.g. "services" → /#services | ||
| kicker | string | short uppercase line above the title, painted with the brand gradient | ||
| title | string | the section heading | ||
| description | string | one or two sentences under the heading | ||
| columns | 1 | 2 | 3 | 4 | 3 | cards per row on desktop | |
| theme | 'light' | 'muted' | 'dark' | 'brand' | 'brand-dark' | 'light' | background of the section | |
| decor | 'none' | 'dots' | 'dots-left' | 'none' | decorative dot grid behind the content | |
| overlap | boolean | false | hang the cards over the bottom edge of the section above (a <HeroCover>) | |
| heading | 'center' | 'left' | 'center' | where the heading sits | |
| icons | 'brand' | 'soft' | 'brand' | "brand" gradient squares behind the icons, "soft" a pale tint | |
| linkText | string | text of one centered button under the grid; shown only with href | ||
| href | string | link of that button | ||
| class | string | escape hatch for compositions: extra classes for the section shell |
Source apps/www/src/sections/FeatureCards.astro @ gitt.one
---
/**
* FeatureCards — a grid of cards, one <Feature> per card: services, benefits,
* reasons to choose, audiences.
*
* Use for: three to six parallel items of equal weight, each with an icon or a
* picture and a sentence or two. The most used section of the library.
* Not for: a dense list of many short points (<FeatureList>, no cards); one
* topic explained in several points beside a heading (<FeatureAside>); a
* numbered process (<Steps>); a choice between two or three things
* (<Compare>).
* Children: <Feature> tags only, three or more. Content written directly
* between the tags is not rendered.
* Layout: `columns` 1–4 (default 3); the cards wrap to one column on phones.
* `overlap` pulls the grid up over the previous section — pair it with a
* <HeroCover> right above (its default overlapNext keeps the room).
* `heading="left"` or a `kicker` moves the heading out of the centre.
* Look: `icons="soft"` paints the icon squares in a pale tint instead of the
* brand gradient; `decor="dots"` adds the decorative dot grid; on
* theme="brand" the cards turn translucent white on the gradient.
* Link: `linkText` + `href` add one centered button under the grid.
*/
import Section from './_Section.astro';
import type { Theme } from './_Section.astro';
import Button from './_Button.astro';
interface Props {
/** anchor of the section, e.g. "services" → /#services */
id?: string;
/** short uppercase line above the title, painted with the brand gradient */
kicker?: string;
/** the section heading */
title?: string;
/** one or two sentences under the heading */
description?: string;
/** cards per row on desktop */
columns?: 1 | 2 | 3 | 4;
/** background of the section */
theme?: Theme;
/** decorative dot grid behind the content */
decor?: 'none' | 'dots' | 'dots-left';
/** hang the cards over the bottom edge of the section above (a <HeroCover>) */
overlap?: boolean;
/** where the heading sits */
heading?: 'center' | 'left';
/** "brand" gradient squares behind the icons, "soft" a pale tint */
icons?: 'brand' | 'soft';
/** text of one centered button under the grid; shown only with href */
linkText?: string;
/** link of that button */
href?: string;
/** escape hatch for compositions: extra classes for the section shell */
class?: string;
}
const { id, kicker, title, description, columns = 3, theme = 'light', decor = 'none', overlap = false, heading = 'center', icons = 'brand', linkText, href, class: extra = '' } = Astro.props;
const cols = { 1: '', 2: 'sm:grid-cols-2', 3: 'sm:grid-cols-2 lg:grid-cols-3', 4: 'sm:grid-cols-2 lg:grid-cols-4' }[columns];
// the shell centers a plain title; a kicker or a left heading is our own block
const ownHeader = Boolean(title) && (Boolean(kicker) || heading === 'left');
---
<Section id={id} title={ownHeader ? undefined : title} description={ownHeader ? undefined : description} theme={theme} overlap={overlap} heading={title && !ownHeader ? heading : 'sr'} class={extra} decor={decor}>
{ownHeader && (
<div class:list={['mb-12 max-w-3xl', heading === 'center' && 'mx-auto text-center']}>
{kicker && <p class="text-sm font-semibold uppercase tracking-wide"><span class="bg-gradient-to-r from-primary-500 to-primary-alt-600 bg-clip-text text-transparent [.bg-gradient-to-r_&]:from-primary-100 [.bg-gradient-to-r_&]:to-primary-alt-400">{kicker}</span></p>}
<h2 class="mt-3 text-3xl font-extrabold tracking-tight sm:text-4xl">{title}</h2>
{description && <p class="mt-4 text-lg text-gray-500 [.bg-stone-800_&]:text-primary-100 [.bg-gradient-to-r_&]:text-primary-100">{description}</p>}
</div>
)}
<ul
class:list={['grid list-none grid-cols-1 gap-8', cols, 'gap-y-16 sm:gap-y-8', overlap && 'gap-y-20 sm:gap-y-12']}
data-variant="cards"
data-overlap={overlap ? '' : undefined}
data-on-dark={theme === 'brand' ? '' : undefined}
data-icons={icons}
>
<slot />
</ul>
{linkText && href && <p class="mt-10 text-center"><Button href={href}>{linkText}</Button></p>}
</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.