src/components/video/VideoModal.astro
---
interface Props {
poster?: string;
alt?: string;
title?: string;
description?: string;
ctaLabel?: string;
modalId?: string;
}
const {
poster = '',
alt = 'Video thumbnail',
title = 'Bekijk onze showreel',
description = '3 minuten die laten zien waar BLURR voor staat.',
ctaLabel = 'Video bekijken',
modalId = 'video-modal',
} = Astro.props;
---
<div class="vmo">
<div class="vmo__trigger-wrap">
<div class="vmo__thumb">
{poster ? (
<img class="vmo__poster" src={poster} alt={alt} />
) : (
<div class="vmo__placeholder" aria-label={alt}></div>
)}
</div>
<div class="vmo__meta">
<p class="vmo__title">{title}</p>
{description && <p class="vmo__desc">{description}</p>}
<button class="vmo__btn" type="button" onclick={`document.getElementById('${modalId}').showModal()`}>
<svg width="18" height="18" viewBox="0 0 18 18" fill="currentColor" style="margin-right:0.4rem">
<polygon points="4,2 16,9 4,16"/>
</svg>
{ctaLabel}
</button>
</div>
</div>
<dialog class="vmo__dialog" id={modalId}>
<form method="dialog" class="vmo__close-form">
<button class="vmo__close" type="submit" aria-label="Sluit video">✕</button>
</form>
<div class="vmo__dialog-player">
<div class="vmo__player-placeholder" aria-label="Video speler">
<p style="color:rgba(255,255,255,0.5); font-size:0.9rem; text-align:center">Video wordt hier geladen<br/><small>Voeg een <video> of iframe toe</small></p>
</div>
</div>
</dialog>
</div>
<style>
:root {
--color-accent: #6366f1;
--color-primary: #0a0a0a;
}
.vmo__trigger-wrap {
display: flex;
gap: 1.5rem;
align-items: center;
}
.vmo__thumb {
width: 200px;
flex-shrink: 0;
aspect-ratio: 16/9;
border-radius: 8px;
overflow: hidden;
}
.vmo__poster { width: 100%; height: 100%; object-fit: cover; }
.vmo__placeholder {
width: 100%;
height: 100%;
background: linear-gradient(135deg, #1a1a2e 0%, #2a2a4e 100%);
}
.vmo__meta {}
.vmo__title {
font-size: 1.15rem;
font-weight: 700;
color: var(--color-primary, #0a0a0a);
margin: 0 0 0.4rem;
}
.vmo__desc {
font-size: 0.9rem;
color: #777;
margin: 0 0 1rem;
line-height: 1.5;
}
.vmo__btn {
display: inline-flex;
align-items: center;
padding: 0.6rem 1.4rem;
background: var(--color-accent, #6366f1);
color: #fff;
border: none;
border-radius: 6px;
font-weight: 700;
font-size: 0.9rem;
cursor: pointer;
transition: opacity 0.2s;
}
.vmo__btn:hover { opacity: 0.85; }
.vmo__dialog {
position: fixed;
inset: 0;
width: 90vw;
max-width: 900px;
border: none;
border-radius: 12px;
padding: 0;
background: #0a0a0a;
box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}
.vmo__dialog::backdrop {
background: rgba(0,0,0,0.8);
backdrop-filter: blur(4px);
}
.vmo__close-form {
position: absolute;
top: 0.75rem;
right: 0.75rem;
z-index: 10;
}
.vmo__close {
background: rgba(255,255,255,0.15);
border: none;
color: #fff;
width: 36px;
height: 36px;
border-radius: 50%;
font-size: 1rem;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
.vmo__close:hover { background: rgba(255,255,255,0.25); }
.vmo__dialog-player {
aspect-ratio: 16/9;
border-radius: 12px;
overflow: hidden;
}
.vmo__player-placeholder {
width: 100%;
height: 100%;
background: #111;
display: flex;
align-items: center;
justify-content: center;
}
</style>
Props
| Prop | Type | Default | Beschrijving |
|---|---|---|---|
poster | string | — | Thumbnail URL |
alt | string | — | Alt-tekst |
title | string | — | Video-titel |
description | string | — | Korte beschrijving |
ctaLabel | string | — | Knoplabel |
modalId | string | — | ID voor de modal |
* = verplicht