Implemented Hero Component and Full-Width Separator
Summary
Implemented a flexible, responsive Hero component with scroll-based animations using Intersection Observer API, supporting multiple background styles including glassmorphic effects. Also created a robust full-width separator component that spans the entire viewport width while maintaining content layout integrity.
Why Care
The Hero component provides a visually striking, accessible entry point for key pages with smooth animations that enhance user experience without external dependencies. The full-width separator solves a common layout challenge in responsive web design, allowing elements to break out of their containers and span the full viewport width. Together, these implementations demonstrate advanced CSS layout techniques and animation patterns in Astro.
Implementation
Changes Made
- Created new component files:
/site/src/components/basics/Hero.astro
- Main hero component with multiple background styles/site/src/components/basics/HeroLoader.astro
- Data-driven loader for hero content/site/src/components/basics/AnimationWrapper.astro
- Wrapper component for animations/site/src/components/basics/separators/ThinGradientBleedSeparator.astro
- Full-width separator component/site/src/utils/animationUtils.ts
- Animation utility using Intersection Observer API/site/src/styles/animations.css
- CSS animations for scroll-based effects/site/src/content/messages/heroContent.json
- JSON data for hero configurations/site/src/pages/examples/hero.astro
- Example page demonstrating hero variations
- Modified existing files:
/site/src/styles/global.css
- Added import for animations.css/site/src/components/MainContent.astro
- Restructured to support full-width elements/site/src/components/basics/Header.astro
- Added full-width separator to the bottom
Technical Details
Animation System
The animation system uses the Intersection Observer API to detect when elements enter the viewport:
typescript
// /site/src/utils/animationUtils.ts
export function initAnimations(): void {
// Only run on the client
if (typeof window === 'undefined' || typeof document === 'undefined') return;
// Get all elements with data-animate attribute
const animatedElements = document.querySelectorAll('[data-animate]');
// Create observer
observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
// If element is in viewport
if (entry.isIntersecting) {
const element = entry.target as HTMLElement;
const delay = element.dataset.animateDelay || '0';
// Add animation after delay
setTimeout(() => {
element.classList.add(ANIMATION_ACTIVE_CLASS);
}, parseFloat(delay) * 1000);
// Unobserve after animation is triggered
observer?.unobserve(element);
}
});
}, observerOptions);
// Observe all animated elements
animatedElements.forEach(element => {
observer?.observe(element);
});
}
CSS Animation Definitions
Created a comprehensive set of animations in
/site/src/styles/animations.css
: css
/* Base animation setup - initially hidden */
[data-animate] {
opacity: 0;
transform: translate(0, 0) scale(1) rotate(0);
transition-property: transform, opacity;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 0.8s;
will-change: transform, opacity;
backface-visibility: hidden;
}
/* Animation active state - visible */
[data-animate].animate-active {
opacity: 1;
transform: translate(0, 0) scale(1) rotate(0) !important;
}
/* Fade animations */
[data-animate="fade-in"] { opacity: 0; }
[data-animate="fade-up"] { opacity: 0; transform: translateY(30px); }
[data-animate="fade-down"] { opacity: 0; transform: translateY(-30px); }
/* Additional animations defined for slide, zoom effects */
Full-Width Separator Implementation
Created a robust separator component that spans the full viewport width:
astro
<!-- /site/src/components/basics/separators/ThinGradientBleedSeparator.astro -->
<div class="separator-wrapper">
<div class="separator--primary-bg-grd"></div>
</div>
<style>
.separator-wrapper {
position: relative;
width: 100%;
height: 2px;
margin: 0;
overflow: visible;
}
.separator--primary-bg-grd {
position: absolute;
left: 50%;
transform: translateX(-50%);
width: 100vw;
height: 2px;
background: var(--grd__primary-bg);
}
</style>
This solution uses:
- A wrapper element that maintains its place in the document flow
- An absolutely positioned child element that breaks out of the container
- The
width: 100vw
property to span the full viewport width left: 50%
andtransform: translateX(-50%)
for horizontal centeringoverflow: visible
to allow the separator to extend beyond its wrapper
Hero Component Interface
The Hero component supports multiple background styles and animation options:
typescript
// /site/src/components/basics/Hero.astro
interface Props {
title: string;
subtitle?: string;
description?: string;
ctaText?: string;
ctaUrl?: string;
image?: { src: string; alt: string; };
backgroundStyle?: 'gradient' | 'dark' | 'glass' | 'glassmorphic' | 'glassmorphic-vivid';
alignment?: 'left' | 'center';
fullBleed?: boolean;
classes?: string;
animate?: boolean;
}
Glassmorphic Effects
Implemented sophisticated blob styling for glassmorphic variants:
css
/* /site/src/components/basics/Hero.astro */
.blob {
position: absolute;
border-radius: 50%;
filter: blur(40px);
opacity: 0.15;
background: var(--grd--lossless-eastern-crimson);
}
.glassmorphic-blobs--vivid .blob {
opacity: 0.25;
filter: blur(60px);
}
Integration Points
- Integrates with the existing design system using CSS variables from
lossless-theme.css
- Works with Astro's view transitions via event listeners:javascript
document.addEventListener('astro:page-load', resetAnimations); document.addEventListener('astro:after-swap', resetAnimations);
- Data-driven approach allows content to be managed through JSON files
- Animation system can be reused across other components
- Separator component can be used throughout the site for consistent visual dividers
Accessibility
- Implemented reduced motion preferences support:css
@media (prefers-reduced-motion: reduce) { [data-animate] { transition-duration: 0.1s; } }
- Added
animate
prop to allow disabling animations programmatically - Maintained proper color contrast for text readability
- Ensured all interactive elements are keyboard accessible
- Separator implementation maintains document flow for proper screen reader navigation
Documentation
- Added comprehensive JSDoc comments to all components and utilities
- Created example page at
/site/src/pages/examples/hero.astro
demonstrating all variants - Updated the Hero component prompt with detailed implementation instructions
- Created an Issue Resolution Breadcrumb document for the full-width separator implementation at
/content/lost-in-public/prompts/workflow/Full-Width-Separator-Issue-Resolution.md