212 lines
5.6 KiB
Vue
212 lines
5.6 KiB
Vue
<template>
|
|
<header
|
|
class="relative py-16 md:py-24 bg-cover bg-center"
|
|
style="background-image: url("/background-dither.png")"
|
|
>
|
|
<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"
|
|
:class="[titleSizeClass, titleColorClass]"
|
|
>
|
|
{{ title }}
|
|
</h1>
|
|
|
|
<p
|
|
v-if="subtitle"
|
|
class="text-lg md:text-xl leading-relaxed mb-8"
|
|
:class="subtitleColorClass"
|
|
>
|
|
{{ subtitle }}
|
|
</p>
|
|
|
|
<!-- Interactive Content Area (for hero sections with carousels, etc.) -->
|
|
<div
|
|
v-if="showInteractiveArea"
|
|
:class="[
|
|
'rounded-2xl p-6 md:p-8 mb-12 backdrop-blur-sm',
|
|
props.theme === 'ethereal'
|
|
? 'bg-ghost-800/60 border border-ghost-700 ethereal-glow halftone-texture'
|
|
: 'bg-[--ui-bg-elevated] shadow-xl border border-blue-200',
|
|
]"
|
|
>
|
|
<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',
|
|
props.theme === 'ethereal'
|
|
? 'bg-whisper-600/80 text-ghost-100 hover:bg-whisper-500 ethereal-glow'
|
|
: 'bg-blue-500 text-white hover:bg-blue-600',
|
|
]"
|
|
@click="$emit('prev')"
|
|
>
|
|
<svg
|
|
class="w-5 h-5 md:w-6 md:h-6"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M15 19l-7-7 7-7"
|
|
/>
|
|
</svg>
|
|
</button>
|
|
|
|
<div class="text-center flex-1 min-w-0">
|
|
<slot name="interactive-content">
|
|
<p
|
|
:class="[
|
|
'text-base md:text-lg',
|
|
props.theme === 'ethereal'
|
|
? 'text-ghost-200'
|
|
: 'text-[--ui-text-muted]',
|
|
]"
|
|
>
|
|
{{
|
|
interactiveContent ||
|
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
|
}}
|
|
</p>
|
|
</slot>
|
|
</div>
|
|
|
|
<button
|
|
:class="[
|
|
'p-2 md:p-3 rounded-full transition-all duration-300 flex-shrink-0',
|
|
props.theme === 'ethereal'
|
|
? 'bg-whisper-600/80 text-ghost-100 hover:bg-whisper-500 ethereal-glow'
|
|
: 'bg-blue-500 text-white hover:bg-blue-600',
|
|
]"
|
|
@click="$emit('next')"
|
|
>
|
|
<svg
|
|
class="w-5 h-5 md:w-6 md:h-6"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M9 5l7 7-7 7"
|
|
/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</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>
|
|
import { computed } from "vue";
|
|
|
|
const props = defineProps({
|
|
title: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
subtitle: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
theme: {
|
|
type: String,
|
|
default: "blue",
|
|
validator: (value) =>
|
|
["blue", "purple", "emerald", "gray", "ethereal"].includes(value),
|
|
},
|
|
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 backgroundClass = computed(() => {
|
|
const themes = {
|
|
blue: "bg-gradient-to-br from-blue-50 to-indigo-100",
|
|
purple: "bg-gradient-to-br from-purple-50 to-violet-100",
|
|
emerald: "bg-gradient-to-br from-emerald-50 to-teal-100",
|
|
gray: "bg-neutral-100",
|
|
ethereal:
|
|
"bg-gradient-to-br from-ghost-900 via-ghost-800 to-whisper-900 halftone-texture",
|
|
};
|
|
return themes[props.theme] || themes.blue;
|
|
});
|
|
|
|
const titleSizeClass = computed(() => {
|
|
const sizes = {
|
|
small: "text-2xl md:text-3xl",
|
|
medium: "text-3xl md:text-4xl",
|
|
large: "text-4xl md:text-5xl",
|
|
hero: "text-5xl md:text-6xl",
|
|
};
|
|
return sizes[props.size] || sizes.large;
|
|
});
|
|
|
|
const titleColorClass = computed(() => {
|
|
return "text-white";
|
|
});
|
|
|
|
const subtitleColorClass = computed(() => {
|
|
return "text-white";
|
|
});
|
|
|
|
const textColorClass = computed(() => {
|
|
return "text-white";
|
|
});
|
|
</script>
|