src/components/ui/Card.astro
---
/**
* Card
* Basis kaart component. Slot-based voor flexibele content.
*
* Props:
* - variant?: 'default' | 'bordered' | 'elevated' | 'flat'
* - href?: string — maakt kaart klikbaar als link
* - image?: string — optionele header image
* - imageAlt?: string
* - padding?: 'sm' | 'md' | 'lg'
*/
interface Props {
variant?: 'default' | 'bordered' | 'elevated' | 'flat';
href?: string;
image?: string;
imageAlt?: string;
padding?: 'sm' | 'md' | 'lg';
}
const {
variant = 'default',
href,
image,
imageAlt = '',
padding = 'md',
} = Astro.props;
const Tag = href ? 'a' : 'div';
---
<Tag
class={`card card--${variant} card--pad-${padding}`}
href={href}
{...(href ? { 'data-card-link': '' } : {})}
>
{image && (
<div class="card__image-wrap">
<img src={image} alt={imageAlt} class="card__image" loading="lazy" />
</div>
)}
<div class="card__body">
<slot />
</div>
</Tag>
<style>
.card {
display: flex;
flex-direction: column;
border-radius: calc(var(--radius) * 2);
overflow: hidden;
color: var(--color-text);
text-decoration: none;
transition: transform 0.2s, box-shadow 0.2s;
}
.card--default { background: color-mix(in srgb, var(--color-text) 4%, transparent); }
.card--bordered { background: var(--color-bg); border: 1px solid color-mix(in srgb, var(--color-text) 12%, transparent); }
.card--elevated { background: var(--color-bg); box-shadow: 0 4px 24px -6px rgba(0,0,0,0.12); }
.card--flat { background: transparent; }
[data-card-link]:hover {
transform: translateY(-3px);
box-shadow: 0 12px 40px -8px rgba(0,0,0,0.12);
}
.card__image-wrap { overflow: hidden; aspect-ratio: 16/9; }
.card__image { width: 100%; height: 100%; object-fit: cover; display: block; }
.card__body--pad-sm { padding: 1rem; }
.card--pad-sm .card__body { padding: 1rem; }
.card--pad-md .card__body { padding: 1.5rem; }
.card--pad-lg .card__body { padding: 2rem; }
</style>
Props
| Prop | Type | Default | Beschrijving |
|---|---|---|---|
variant | 'default' | 'bordered' | 'elevated' | 'flat' | 'default' | Visuele stijl |
href | string | — | Maakt kaart klikbaar als link |
image | string | — | Optionele header afbeelding |
padding | 'sm' | 'md' | 'lg' | 'md' | Interne ruimte |
* = verplicht