Zoeken...  ⌘K GitHub

VideoAnnotated video

Video met tijdgestempelde annotaties naast de player.

/video-annotated
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