forked from cms/tibi-svelte-starter
✨ feat: add new contact form, hero, features, and richtext blocks; implement scroll-reveal action and update styles
- Introduced ContactFormBlock, FeaturesBlock, HeroBlock, and RichtextBlock components. - Implemented a scroll-reveal action for animations on element visibility. - Enhanced CSS styles for better theming and prose formatting. - Added localization support for new components and updated existing translations. - Created e2e tests for demo pages including contact form validation and navigation. - Added a video tour showcasing the demo pages and interactions.
This commit is contained in:
73
frontend/src/blocks/HeroBlock.svelte
Normal file
73
frontend/src/blocks/HeroBlock.svelte
Normal file
@@ -0,0 +1,73 @@
|
||||
<script lang="ts">
|
||||
import { reveal } from "../lib/actions/reveal"
|
||||
|
||||
let { block }: { block: ContentBlockEntry } = $props()
|
||||
|
||||
const hasImage = $derived(block.heroImage?.externalUrl || block.heroImage?.image)
|
||||
</script>
|
||||
|
||||
<section
|
||||
data-block="hero"
|
||||
class="hero-section relative flex items-center justify-center overflow-hidden"
|
||||
class:min-h-[70vh]={block.containerWidth === "full"}
|
||||
class:min-h-[50vh]={block.containerWidth !== "full"}
|
||||
>
|
||||
<!-- Background image -->
|
||||
{#if hasImage}
|
||||
<div class="absolute inset-0 z-0">
|
||||
{#if block.heroImage?.externalUrl}
|
||||
<img src={block.heroImage.externalUrl} alt="" class="w-full h-full object-cover" loading="lazy" />
|
||||
{/if}
|
||||
<div class="absolute inset-0 bg-linear-to-b from-brand-950/80 via-brand-900/70 to-brand-950/90"></div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="absolute inset-0 bg-linear-to-br from-brand-900 via-brand-800 to-brand-950"></div>
|
||||
{/if}
|
||||
|
||||
<!-- Content -->
|
||||
<div class="relative z-10 max-w-4xl mx-auto px-6 py-20 text-center" use:reveal>
|
||||
{#if block.tagline}
|
||||
<span class="inline-block text-brand-300 text-sm font-semibold tracking-widest uppercase mb-4">
|
||||
{block.tagline}
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
{#if block.headlineH1}
|
||||
<h1 class="text-4xl sm:text-5xl lg:text-6xl font-display font-extrabold text-white leading-tight mb-6">
|
||||
{block.headline}
|
||||
</h1>
|
||||
{:else}
|
||||
<h2 class="text-3xl sm:text-4xl lg:text-5xl font-display font-bold text-white leading-tight mb-6">
|
||||
{block.headline}
|
||||
</h2>
|
||||
{/if}
|
||||
|
||||
{#if block.subline}
|
||||
<p class="text-lg sm:text-xl text-brand-200 max-w-2xl mx-auto mb-8 leading-relaxed">
|
||||
{block.subline}
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
{#if block.callToAction?.buttonText}
|
||||
<div class="flex justify-center gap-4">
|
||||
<a
|
||||
href={block.callToAction.buttonLink || "#"}
|
||||
target={block.callToAction.buttonTarget || undefined}
|
||||
class="inline-flex items-center gap-2 bg-brand-500 hover:bg-brand-400 text-white font-bold px-8 py-4 rounded-xl text-lg transition-all duration-300 hover:shadow-lg hover:shadow-brand-500/25 hover:-translate-y-0.5"
|
||||
>
|
||||
{block.callToAction.buttonText}
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- Decorative bottom wave -->
|
||||
<div class="absolute bottom-0 left-0 right-0 z-10">
|
||||
<svg viewBox="0 0 1440 80" fill="none" class="w-full h-auto">
|
||||
<path d="M0 80V40C240 10 480 0 720 20C960 40 1200 50 1440 30V80H0Z" fill="white"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</section>
|
||||
Reference in New Issue
Block a user