src/components/video/VideoAnnotated.astro
---
interface Annotation {
time: string;
label: string;
note: string;
}
interface Props {
poster?: string;
title?: string;
annotations?: Annotation[];
}
const {
poster = '',
title = 'Case walkthrough: TechFlow campagne',
annotations = [
{ time: '0:00', label: 'Intro', note: 'Uitgangssituatie en doelstelling' },
{ time: '1:20', label: 'Strategie', note: 'Hoe we de doelgroep definieerden' },
{ time: '3:45', label: 'Lancering', note: 'Eerste campagneweek live' },
{ time: '6:10', label: 'Resultaten', note: '+280% leads in 90 dagen' },
],
} = Astro.props;
---
<section class="van">
<div class="van__player">
{poster ? (
<img class="van__poster" src={poster} alt={title} />
) : (
<div class="van__placeholder" aria-label={title}>
<span class="van__play-hint" aria-hidden="true">▶</span>
</div>
)}
<div class="van__timeline">
{annotations.map((a) => (
<div class="van__marker" title={a.label}>
<span class="van__marker-dot" aria-hidden="true"></span>
<span class="van__marker-time">{a.time}</span>
</div>
))}
</div>
</div>
<div class="van__notes">
<h3 class="van__title">{title}</h3>
<ol class="van__list">
{annotations.map((a) => (
<li class="van__note">
<span class="van__time">{a.time}</span>
<div class="van__note-content">
<p class="van__note-label">{a.label}</p>
<p class="van__note-text">{a.note}</p>
</div>
</li>
))}
</ol>
</div>
</section>
<style>
:root {
--color-accent: #6366f1;
--color-primary: #0a0a0a;
}
.van {
display: grid;
grid-template-columns: 3fr 2fr;
gap: 2rem;
align-items: start;
padding: 2rem 0;
}
.van__player {
position: relative;
aspect-ratio: 16/9;
border-radius: 10px;
overflow: hidden;
background: #111;
}
.van__poster { width: 100%; height: 100%; object-fit: cover; }
.van__placeholder {
width: 100%;
height: 100%;
background: linear-gradient(135deg, #0a0a1a 0%, #1a1a3a 100%);
display: flex;
align-items: center;
justify-content: center;
font-size: 3rem;
color: rgba(255,255,255,0.3);
}
.van__timeline {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 3rem;
background: rgba(10,10,10,0.8);
display: flex;
align-items: center;
padding: 0 1rem;
gap: 1.5rem;
}
.van__marker {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.2rem;
cursor: pointer;
}
.van__marker-dot {
width: 8px;
height: 8px;
background: var(--color-accent, #6366f1);
border-radius: 50%;
}
.van__marker-time {
font-size: 0.65rem;
color: rgba(255,255,255,0.7);
font-weight: 600;
}
.van__notes {}
.van__title {
font-size: 1.1rem;
font-weight: 700;
color: var(--color-primary, #0a0a0a);
margin: 0 0 1.25rem;
}
.van__list {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.van__note {
display: flex;
gap: 1rem;
align-items: flex-start;
padding: 0.75rem;
border-radius: 8px;
border: 1px solid #eee;
cursor: pointer;
transition: background 0.15s;
}
.van__note:hover { background: #f5f5f5; }
.van__time {
font-size: 0.75rem;
font-weight: 700;
color: var(--color-accent, #6366f1);
white-space: nowrap;
flex-shrink: 0;
margin-top: 0.15rem;
}
.van__note-label {
font-size: 0.85rem;
font-weight: 700;
color: var(--color-primary, #0a0a0a);
margin: 0 0 0.2rem;
}
.van__note-text {
font-size: 0.8rem;
color: #777;
margin: 0;
}
@media (max-width: 768px) {
.van { grid-template-columns: 1fr; }
}
</style>
Props
| Prop | Type | Default | Beschrijving |
|---|---|---|---|
poster | string | — | Thumbnail URL |
title | string | — | Video-titel |
annotations | { time: string; label: string; note: string }[] | — | Tijdgestempelde annotaties |
* = verplicht