mirror of
https://github.com/ThatGuySam/doesitarm.git
synced 2026-05-18 06:44:46 -07:00
Add video copmenents
This commit is contained in:
parent
cd3b3f13a2
commit
6acaee1b5a
3 changed files with 173 additions and 0 deletions
63
src/components/video/card.astro
Normal file
63
src/components/video/card.astro
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
---
|
||||||
|
import Poster from './poster.astro'
|
||||||
|
|
||||||
|
const {
|
||||||
|
video,
|
||||||
|
width = '325px',
|
||||||
|
classes = 'w-full flex-shrink-0 flex-grow-0 border-2 border-transparent rounded-2xl overflow-hidden'
|
||||||
|
} = Astro.props
|
||||||
|
|
||||||
|
const cardClasses = `video-card ${ classes }`
|
||||||
|
|
||||||
|
---
|
||||||
|
<div
|
||||||
|
class={ cardClasses }
|
||||||
|
style={ `max-width: ${ width }; flex-basis: ${ width }; scroll-snap-align: start;` }
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href={video.endpoint}
|
||||||
|
class=""
|
||||||
|
>
|
||||||
|
<div class="video-card-container relative overflow-hidden bg-black">
|
||||||
|
<div class="video-card-image ratio-wrapper">
|
||||||
|
<div class="relative overflow-hidden w-full pb-16/9">
|
||||||
|
<Poster video={video} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="--gradient-from-color: rgba(0, 0, 0, 1); --gradient-to-color: rgba(0, 0, 0, 0.7)"
|
||||||
|
class="video-card-overlay absolute inset-0 flex justify-between items-start bg-gradient-to-tr from-black to-transparent p-4"
|
||||||
|
>
|
||||||
|
<div class="play-circle w-8 h-8 bg-white-2 flex justify-center items-center outline-0 rounded-full ease">
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 18 18"
|
||||||
|
style="width:18px;height:18px;margin-left:3px"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M15.562 8.1L3.87.225c-.818-.562-1.87 0-1.87.9v15.75c0 .9 1.052 1.462 1.87.9L15.563 9.9c.584-.45.584-1.35 0-1.8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{ ( video.tags.includes('benchmark') ) ?
|
||||||
|
<div
|
||||||
|
class="video-pill h-5 text-xs bg-white-2 flex justify-center items-center outline-0 rounded-full ease px-2"
|
||||||
|
>
|
||||||
|
Benchmark
|
||||||
|
</div> : ''
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Video Text Content -->
|
||||||
|
<div class="video-card-content absolute inset-0 flex items-end py-4 px-6">
|
||||||
|
<div class="w-full text-sm text-left whitespace-normal">{ video.name }</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import 'lazysizes'
|
||||||
|
</script>
|
||||||
31
src/components/video/poster.astro
Normal file
31
src/components/video/poster.astro
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
---
|
||||||
|
const {
|
||||||
|
video
|
||||||
|
} = Astro.props
|
||||||
|
|
||||||
|
const webpSource = {
|
||||||
|
...video.thumbnail,
|
||||||
|
srcset: video.thumbnail.srcset.replaceAll('ytimg.com/vi/', 'ytimg.com/vi_webp/').replace(/.png|.jpg|.jpeg/g, '.webp')
|
||||||
|
}
|
||||||
|
|
||||||
|
const mergedSources = {
|
||||||
|
webp: webpSource,
|
||||||
|
jpeg: video.thumbnail
|
||||||
|
}
|
||||||
|
---
|
||||||
|
<picture>
|
||||||
|
|
||||||
|
{ Object.entries( mergedSources ).map( ([ key, source ]) => (
|
||||||
|
<source
|
||||||
|
sizes={ source.sizes }
|
||||||
|
data-srcset={ source.srcset }
|
||||||
|
type={ `image/${ key }` }
|
||||||
|
>
|
||||||
|
) ) }
|
||||||
|
|
||||||
|
<img
|
||||||
|
data-src={ video.thumbnail.src }
|
||||||
|
alt={ video.name }
|
||||||
|
class="absolute inset-0 h-full w-full object-cover lazyload"
|
||||||
|
>
|
||||||
|
</picture>
|
||||||
79
src/components/video/row.astro
Normal file
79
src/components/video/row.astro
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
---
|
||||||
|
import Card from './card.astro'
|
||||||
|
|
||||||
|
const {
|
||||||
|
videos,
|
||||||
|
cardWidth = '325',
|
||||||
|
classes = ''
|
||||||
|
} = Astro.props
|
||||||
|
|
||||||
|
// Math.random should be unique because of its seeding algorithm.
|
||||||
|
// Convert it to base 36 (numbers + letters), and grab the first 9 characters
|
||||||
|
// after the decimal.
|
||||||
|
const uid = Math.random().toString(36).substr(2, 9)
|
||||||
|
const rowId = `row-${ uid }`
|
||||||
|
const rowSelector = `#${ rowId }`
|
||||||
|
|
||||||
|
---
|
||||||
|
<div class="video-row relative w-full ${ classes }">
|
||||||
|
|
||||||
|
<div
|
||||||
|
id={ rowId }
|
||||||
|
class="video-row-contents flex overflow-x-auto whitespace-no-wrap py-2 space-x-6"
|
||||||
|
style="scroll-snap-type:x mandatory;"
|
||||||
|
>
|
||||||
|
{ videos.map(video => (
|
||||||
|
<Card
|
||||||
|
key={ video.id }
|
||||||
|
video={ video }
|
||||||
|
cardWidth={ cardWidth }
|
||||||
|
/>
|
||||||
|
)) }
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="scroll-button absolute left-0 h-10 w-10 flex justify-center items-center transform -translate-y-1/2 -translate-x-1/2 bg-darker rounded-full"
|
||||||
|
style="top:50%;"
|
||||||
|
distance={ cardWidth * -1 }
|
||||||
|
scroll-target={ rowSelector }
|
||||||
|
aria-label="Scroll to previous videos"
|
||||||
|
>
|
||||||
|
<svg viewBox="0 0 20 20" fill="currentColor" class="h-5 w-5 text-gray-400" style="transform: scaleX(-1);">
|
||||||
|
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="scroll-button absolute right-0 h-10 w-10 flex justify-center items-center transform -translate-y-1/2 translate-x-1/2 bg-darker rounded-full"
|
||||||
|
style="top:50%;"
|
||||||
|
distance={ cardWidth }
|
||||||
|
scroll-target={ rowSelector }
|
||||||
|
aria-label="Scroll to next videos"
|
||||||
|
>
|
||||||
|
<svg viewBox="0 0 20 20" fill="currentColor" class="h-5 w-5 text-gray-400">
|
||||||
|
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script is:inline>
|
||||||
|
function scrollHorizontalCarousel ( event ) {
|
||||||
|
event.stopPropagation()
|
||||||
|
|
||||||
|
// console.log('event.target', event.currentTarget)
|
||||||
|
// console.log('distance', event.currentTarget.getAttribute('distance'))
|
||||||
|
|
||||||
|
const distance = Number(event.currentTarget.getAttribute('distance'))
|
||||||
|
const scrollTarget = document.querySelector(event.currentTarget.getAttribute('scroll-target'))
|
||||||
|
|
||||||
|
scrollTarget.scrollBy({ left: distance, behavior: 'smooth' })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add Click listeners to all buttons
|
||||||
|
Array.from( document.querySelectorAll(`button.scroll-button`) ).forEach( button => {
|
||||||
|
// console.log('button', button)
|
||||||
|
button.addEventListener('click', scrollHorizontalCarousel)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue