ImageShowcase image
Showcase-grid met 2-4 kaarten: beeld, tag-badge, titel en omschrijving. Geschikt voor diensten, cases of producten.
src/components/image/ImageShowcase.astro
---
/**
* ImageShowcase
* Showcase-sectie: 2–4 kaarten elk met beeld, tag-badge, titel en omschrijving.
* Geschikt om diensten, cases of producten visueel te presenteren.
*
* Props:
* - heading?: string
* - sub?: string
* - items: { image?: { src: string; alt?: string }; tag?: string; title: string; description?: string }[]
* - columns?: 2 | 3 | 4 aantal kolommen op desktop, default 3
* - theme?: 'light' | 'dark' default 'light'
*/
interface ShowcaseItem {
image?: { src: string; alt?: string };
tag?: string;
title: string;
description?: string;
}
interface Props {
heading?: string;
sub?: string;
items: ShowcaseItem[];
columns?: 2 | 3 | 4;
theme?: 'light' | 'dark';
}
const {
heading,
sub,
items,
columns = 3,
theme = 'light',
} = Astro.props;
---
<section class:list={['bl-section', 'ish', `ish--${theme}`]}>
<div class="bl-inner ish-inner">
{heading && <h2 class="ish-heading">{heading}</h2>}
{sub && <p class="ish-sub">{sub}</p>}
<div class="ish-list" style={`--ish-cols: ${columns}`}>
{items.map((item) => (
<div class="ish-item">
<div class="ish-media">
{item.image
? <img src={item.image.src} alt={item.image.alt ?? ''} class="ish-img" loading="lazy" decoding="async" />
: <div class="ish-placeholder" aria-hidden="true"></div>
}
{item.tag && <span class="ish-tag">{item.tag}</span>}
</div>
<h3 class="ish-title">{item.title}</h3>
{item.description && <p class="ish-desc">{item.description}</p>}
</div>
))}
</div>
</div>
</section>
<style>
.ish--light { background: var(--color-bg, #fff); color: var(--color-text, #0a0a0a); }
.ish--dark { background: #0a0a0a; color: #e8e8e8; }
.ish-heading {
font-size: clamp(1.75rem, 3vw, 2.5rem);
font-weight: 700;
margin: 0 0 .75rem;
}
.ish-sub {
font-size: 1.125rem;
color: var(--color-muted, #6b7280);
margin: 0 0 2.5rem;
line-height: 1.65;
}
.ish--dark .ish-sub { color: #aaa; }
.ish-list {
display: grid;
grid-template-columns: repeat(var(--ish-cols, 3), 1fr);
gap: 2rem;
}
@media (max-width: 900px) {
.ish-list { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
.ish-list { grid-template-columns: 1fr; }
}
.ish-item { display: flex; flex-direction: column; }
.ish-media {
position: relative;
aspect-ratio: 16 / 10;
border-radius: 10px;
overflow: hidden;
margin-bottom: 1.25rem;
}
.ish-img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.ish-placeholder {
width: 100%;
height: 100%;
background: linear-gradient(135deg, #e0e4f8, #c8cef0);
}
.ish--dark .ish-placeholder {
background: linear-gradient(135deg, #1e2240, #2a2f55);
}
.ish-tag {
position: absolute;
top: .75rem;
left: .75rem;
background: var(--color-text, #0a0a0a);
color: #fff;
font-size: .7rem;
font-weight: 700;
letter-spacing: .08em;
text-transform: uppercase;
padding: .25rem .6rem;
border-radius: 4px;
}
.ish--dark .ish-tag {
background: #fff;
color: #0a0a0a;
}
.ish-title {
font-size: 1.1rem;
font-weight: 700;
margin: 0 0 .5rem;
color: inherit;
}
.ish-desc {
font-size: 1rem;
color: var(--color-muted, #6b7280);
line-height: 1.65;
margin: 0;
}
.ish--dark .ish-desc { color: #aaa; }
</style>
Props
| Prop | Type | Default | Beschrijving |
|---|---|---|---|
heading | string | - | Sectie-kop |
sub | string | - | Ondertitel |
items * | { image?: { src: string; alt?: string }; tag?: string; title: string; description?: string }[] | - | Showcase-kaarten (2–4) |
columns | 2 | 3 | 4 | 3 | Aantal kolommen op desktop |
theme | 'light' | 'dark' | 'light' | Achtergrond-mode |
* = verplicht