Changed content row titles to: - font-bold (700 weight) for more emphasis - letter-spacing: 0.05em (5% character spacing) - Maintains gradient effect from #fafafa to #9ca3af - More prominent and readable Co-authored-by: Cursor <cursoragent@cursor.com>
143 lines
4.2 KiB
Vue
143 lines
4.2 KiB
Vue
<template>
|
|
<div class="content-row">
|
|
<h2 class="content-row-title text-xl md:text-2xl font-bold text-white mb-4 px-4 uppercase">
|
|
{{ title }}
|
|
</h2>
|
|
|
|
<div class="relative group">
|
|
<!-- Scroll Left Button -->
|
|
<button
|
|
v-if="canScrollLeft"
|
|
@click="scrollLeft"
|
|
class="hidden md:block absolute left-0 top-0 bottom-0 z-10 w-12 bg-black/50 hover:bg-black/70 backdrop-blur-sm opacity-0 group-hover:opacity-100 transition-opacity"
|
|
>
|
|
<svg class="w-8 h-8 mx-auto" fill="currentColor" viewBox="0 0 24 24">
|
|
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>
|
|
</svg>
|
|
</button>
|
|
|
|
<!-- Content Slider -->
|
|
<div
|
|
ref="sliderRef"
|
|
class="flex gap-8 overflow-x-auto overflow-y-visible scrollbar-hide scroll-smooth px-4 pt-6 pb-8"
|
|
@scroll="handleScroll"
|
|
>
|
|
<div
|
|
v-for="content in contents"
|
|
:key="content.id"
|
|
class="content-card flex-shrink-0 w-[200px] md:w-[280px] group/card cursor-pointer"
|
|
@click="$emit('content-click', content)"
|
|
>
|
|
<div class="glass-card rounded-lg p-1.5 transition-all duration-300">
|
|
<img
|
|
:src="content.thumbnail"
|
|
:alt="content.title"
|
|
class="w-full aspect-[2/3] object-contain rounded-md bg-neutral-900"
|
|
loading="lazy"
|
|
/>
|
|
</div>
|
|
<div class="mt-2">
|
|
<h3 class="text-base md:text-xl font-semibold md:font-bold text-white truncate">{{ content.title }}</h3>
|
|
<p class="text-base text-white/60 truncate hidden md:block">{{ content.description }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Scroll Right Button -->
|
|
<button
|
|
v-if="canScrollRight"
|
|
@click="scrollRight"
|
|
class="hidden md:block absolute right-0 top-0 bottom-0 z-10 w-12 bg-black/50 hover:bg-black/70 backdrop-blur-sm opacity-0 group-hover:opacity-100 transition-opacity"
|
|
>
|
|
<svg class="w-8 h-8 mx-auto" fill="currentColor" viewBox="0 0 24 24">
|
|
<path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, onMounted, onUnmounted } from 'vue'
|
|
import type { Content } from '../types/content'
|
|
|
|
interface Props {
|
|
title: string
|
|
contents: Content[]
|
|
}
|
|
|
|
defineProps<Props>()
|
|
defineEmits<{
|
|
'content-click': [content: Content]
|
|
}>()
|
|
|
|
const sliderRef = ref<HTMLElement | null>(null)
|
|
const canScrollLeft = ref(false)
|
|
const canScrollRight = ref(true)
|
|
|
|
const handleScroll = () => {
|
|
if (!sliderRef.value) return
|
|
|
|
const { scrollLeft, scrollWidth, clientWidth } = sliderRef.value
|
|
canScrollLeft.value = scrollLeft > 0
|
|
canScrollRight.value = scrollLeft < scrollWidth - clientWidth - 10
|
|
}
|
|
|
|
const scrollLeft = () => {
|
|
if (!sliderRef.value) return
|
|
sliderRef.value.scrollBy({ left: -600, behavior: 'smooth' })
|
|
}
|
|
|
|
const scrollRight = () => {
|
|
if (!sliderRef.value) return
|
|
sliderRef.value.scrollBy({ left: 600, behavior: 'smooth' })
|
|
}
|
|
|
|
onMounted(() => {
|
|
if (sliderRef.value) {
|
|
sliderRef.value.addEventListener('scroll', handleScroll)
|
|
handleScroll()
|
|
}
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
if (sliderRef.value) {
|
|
sliderRef.value.removeEventListener('scroll', handleScroll)
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.scrollbar-hide {
|
|
-ms-overflow-style: none;
|
|
scrollbar-width: none;
|
|
}
|
|
|
|
.scrollbar-hide::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
|
|
.content-row-title {
|
|
background: linear-gradient(to right, #fafafa, #9ca3af);
|
|
-webkit-background-clip: text;
|
|
background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
letter-spacing: 0.05em; /* 5% character spacing */
|
|
}
|
|
|
|
.glass-card {
|
|
background: linear-gradient(135deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.02));
|
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
backdrop-filter: blur(10px);
|
|
-webkit-backdrop-filter: blur(10px);
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.group\/card:hover .glass-card {
|
|
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2), 0 0 20px rgba(255, 255, 255, 0.05);
|
|
transform: translateY(-4px);
|
|
}
|
|
</style>
|