ghostguild-org/app/components/PageHeader.vue

135 lines
3.5 KiB
Vue

<template>
<header
class="relative py-16 md:py-24 bg-cover bg-center"
style="background-image: url('/background-dither.webp')"
>
<div class="absolute inset-0 bg-black/40"></div>
<UContainer class="relative z-10">
<div class="text-center max-w-4xl mx-auto">
<h1
class="font-bold mb-6 md:mb-8 text-white"
:class="titleSizeClass"
>
{{ title }}
</h1>
<p
v-if="subtitle"
class="text-lg md:text-xl leading-relaxed mb-8 text-white/90"
>
{{ subtitle }}
</p>
<!-- Interactive Content Area (for hero sections with carousels) -->
<div
v-if="showInteractiveArea"
class="rounded-2xl p-6 md:p-8 mb-12 backdrop-blur-sm bg-guild-800/60 border border-guild-700 candlelight-glow halftone-texture"
>
<div class="flex items-center justify-between gap-3 md:gap-4">
<button
class="p-2 md:p-3 rounded-full transition-all duration-300 flex-shrink-0 bg-candlelight-600/80 text-guild-100 hover:bg-candlelight-500 candlelight-glow"
@click="$emit('prev')"
>
<UIcon name="i-lucide-chevron-left" class="size-5 md:size-6" />
</button>
<div class="text-center flex-1 min-w-0">
<slot name="interactive-content">
<p class="text-base md:text-lg text-guild-200">
{{ interactiveContent }}
</p>
</slot>
</div>
<button
class="p-2 md:p-3 rounded-full transition-all duration-300 flex-shrink-0 bg-candlelight-600/80 text-guild-100 hover:bg-candlelight-500 candlelight-glow"
@click="$emit('next')"
>
<UIcon name="i-lucide-chevron-right" class="size-5 md:size-6" />
</button>
</div>
</div>
<!-- Illustration slot for designer-provided assets -->
<div v-if="$slots.illustration" class="mb-8">
<slot name="illustration" />
</div>
<!-- Call to Action Button -->
<div v-if="showCta" class="flex justify-center">
<UButton
:to="ctaLink"
:size="ctaSize"
:color="ctaColor"
class="font-semibold"
>
{{ ctaText }}
</UButton>
</div>
<!-- Custom Content Slot -->
<div v-if="$slots.default">
<slot />
</div>
</div>
</UContainer>
</header>
</template>
<script setup>
const props = defineProps({
title: {
type: String,
required: true,
},
subtitle: {
type: String,
default: '',
},
size: {
type: String,
default: 'large',
validator: (value) => ['small', 'medium', 'large', 'hero'].includes(value),
},
showInteractiveArea: {
type: Boolean,
default: false,
},
interactiveContent: {
type: String,
default: '',
},
showCta: {
type: Boolean,
default: false,
},
ctaText: {
type: String,
default: 'Get Started',
},
ctaLink: {
type: String,
default: '/join',
},
ctaSize: {
type: String,
default: 'lg',
},
ctaColor: {
type: String,
default: 'primary',
},
})
defineEmits(['prev', 'next'])
const titleSizeClass = computed(() => {
const sizes = {
small: 'text-display-sm',
medium: 'text-display',
large: 'text-display-lg',
hero: 'text-display-xl',
}
return sizes[props.size] || sizes.large
})
</script>