80 lines
1.7 KiB
Vue
80 lines
1.7 KiB
Vue
<template>
|
|
<section :class="sectionClasses">
|
|
<div :class="contentClasses">
|
|
<div :class="['space-y-4', maxWidthClass]">
|
|
<component :is="headingTag" v-if="title" class="text-4xl font-bold">
|
|
{{ title }}
|
|
</component>
|
|
<p v-if="subtitle" class="text-sm opacity-90">{{ subtitle }}</p>
|
|
<slot />
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed } from 'vue'
|
|
|
|
const props = defineProps({
|
|
title: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
subtitle: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
gradientFrom: {
|
|
type: String,
|
|
default: 'from-primary',
|
|
},
|
|
gradientTo: {
|
|
type: String,
|
|
default: 'to-secondary',
|
|
},
|
|
minHeight: {
|
|
type: String,
|
|
default: 'min-h-[25vh]',
|
|
},
|
|
maxWidth: {
|
|
type: String,
|
|
default: 'max-w-xl',
|
|
},
|
|
rounded: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
alignment: {
|
|
type: String,
|
|
default: 'center',
|
|
validator: (value) => ['center', 'start', 'end'].includes(value),
|
|
},
|
|
headingTag: {
|
|
type: String,
|
|
default: 'h1',
|
|
},
|
|
})
|
|
|
|
const sectionClasses = computed(() => {
|
|
const classes = ['hero', 'bg-gradient-to-r', props.gradientFrom, props.gradientTo, props.minHeight]
|
|
if (props.rounded) {
|
|
classes.push('rounded-lg')
|
|
}
|
|
return classes
|
|
})
|
|
|
|
const contentClasses = computed(() => {
|
|
const base = ['hero-content', 'text-neutral-content']
|
|
if (props.alignment === 'center') {
|
|
base.push('text-center')
|
|
} else if (props.alignment === 'start') {
|
|
base.push('justify-start', 'text-left')
|
|
} else if (props.alignment === 'end') {
|
|
base.push('justify-end', 'text-right')
|
|
}
|
|
return base
|
|
})
|
|
|
|
const maxWidthClass = computed(() => props.maxWidth)
|
|
</script>
|