Skip to content

Video blockΒ #34

@otabekoff

Description

@otabekoff

🎯 Type of feature

New functionality

πŸ€” Is your feature request related to a problem?

Yes, we don't have video block. We may add YouTube video extension, but we don't have pure HTML 5 video block.

πŸ’‘ Desired solution

Using useMediaControls from VueUse library and having a nice look that fits for TipTap Editor and ShadCN Vue design.

πŸ”„ Alternatives considered

Maybe we could do this via pure code without VueUse but this takes time, complicates, long lines of code and maybe one day discontinued. So, let's use ready solution.

πŸ” Examples from other projects

You can see VueUse Demo

πŸ“ Additional context

Here is the starter code.

<script setup lang="ts">
import { useMediaControls } from '@vueuse/core'
import { ref, onMounted } from 'vue'

import type { UseMediaTextTrackSource } from '@vueuse/core'
type VideoTrack = UseMediaTextTrackSource;
const props = defineProps<{ src: string, tracks?: VideoTrack[] }>()
const video = ref<HTMLVideoElement | null>(null)
const controls = useMediaControls(video, {
  src: props.src,
  tracks: props.tracks || [],
})

onMounted(() => {
  controls.volume.value = 0.7
})
</script>

<template>
  <div class="video-block">
    <video ref="video" controls class="rounded-lg shadow w-full max-w-2xl">
      <template v-for="track in props.tracks" :key="track.label">
        <track
          :src="track.src"
          :kind="track.kind"
          :label="track.label"
          :srclang="track.srcLang"
          :default="track.default"
        />
      </template>
    </video>
    <div class="flex gap-2 items-center mt-2">
      <button @click="controls.playing.value = !controls.playing.value" class="btn">
        {{ controls.playing.value ? 'Pause' : 'Play' }}
      </button>
      <span>{{ Math.round(controls.currentTime.value) }} / {{ Math.round(controls.duration.value) }}s</span>
      <input type="range" min="0" :max="controls.duration.value" v-model="controls.currentTime.value" />
      <input type="range" min="0" max="1" step="0.01" v-model="controls.volume.value" />
      <button @click="controls.muted.value = !controls.muted.value" class="btn">
        {{ controls.muted.value ? 'Unmute' : 'Mute' }}
      </button>
    </div>
  </div>
</template>

<style scoped>
.video-block {
  margin: 1.5rem 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.btn {
  background: #2563eb;
  color: white;
  border: none;
  border-radius: 4px;
  padding: 0.25rem 0.75rem;
  cursor: pointer;
}
.btn:hover {
  background: #1d4ed8;
}
</style>

βœ… Before submitting

  • πŸ” I've searched for existing feature requests and this hasn't been suggested before
  • πŸ™‹ I'm willing to help implement or test this feature if needed

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions