feat: Implement Phase 1 enhancements - components and animations
Enterprise AI Code Review / ai-review (pull_request) Successful in 19s
Enterprise AI Code Review / ai-review (pull_request) Successful in 19s
Components: - Extract ServiceItem component with hover effects - Extract SupportItem component with hover animations - Extract Card component with scroll animations - Extract Section component for consistent layout Enhancements: - Add Intersection Observer for scroll-triggered animations - Implement hover effects on cards, services, and support items - Add PWA manifest (site.webmanifest) - Create SVG OG image placeholder for social sharing - Add comprehensive favicon meta tags (16x16, 32x32, apple-touch-icon) - Respect prefers-reduced-motion for accessibility Files modified: - src/pages/index.astro - Refactored to use new components - src/layouts/BaseLayout.astro - Enhanced favicon and meta tags Files created: - src/components/Card.astro - src/components/Section.astro - src/components/ServiceItem.astro - src/components/SupportItem.astro - public/og-image.svg - public/site.webmanifest - public/FAVICON_INSTRUCTIONS.md Note: PNG favicon variants still need to be generated (see FAVICON_INSTRUCTIONS.md)
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
---
|
||||
interface Props {
|
||||
class?: string;
|
||||
}
|
||||
|
||||
const { class: className } = Astro.props;
|
||||
---
|
||||
|
||||
<div class:list={["card", "scroll-animate", className]}>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.card {
|
||||
background: var(--color-bg-light);
|
||||
border-radius: 12px;
|
||||
padding: var(--space-lg);
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
|
||||
border: 1px solid rgba(212, 165, 116, 0.1);
|
||||
transition: box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.card :global(h2) {
|
||||
font-size: 2rem;
|
||||
margin-bottom: var(--space-md);
|
||||
}
|
||||
|
||||
.card :global(p) {
|
||||
margin-bottom: var(--space-md);
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.card :global(p:last-child) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Scroll animation states */
|
||||
.scroll-animate {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
transition: opacity 0.6s ease-out, transform 0.6s ease-out;
|
||||
}
|
||||
|
||||
.scroll-animate.visible {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.card {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.scroll-animate {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.card :global(h2) {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
interface Props {
|
||||
class?: string;
|
||||
ariaLabelledby?: string;
|
||||
}
|
||||
|
||||
const { class: className, ariaLabelledby } = Astro.props;
|
||||
---
|
||||
|
||||
<section class:list={["section", className]} aria-labelledby={ariaLabelledby}>
|
||||
<div class="container">
|
||||
<slot />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.section {
|
||||
padding: var(--space-lg) 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 0 var(--space-md);
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
interface Props {
|
||||
title: string;
|
||||
description: string;
|
||||
url?: string;
|
||||
comingSoon?: boolean;
|
||||
}
|
||||
|
||||
const { title, description, url, comingSoon = false } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="service-item" class:list={{ "coming-soon": comingSoon }} role="listitem">
|
||||
<h3>
|
||||
{url ? (
|
||||
<a
|
||||
href={url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label={`Visit ${title}`}
|
||||
>
|
||||
{title}
|
||||
</a>
|
||||
) : (
|
||||
title
|
||||
)}
|
||||
</h3>
|
||||
<p>{description}</p>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.service-item {
|
||||
background: var(--color-bg);
|
||||
padding: var(--space-md);
|
||||
border-radius: 8px;
|
||||
border-left: 4px solid var(--color-accent);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.service-item:hover {
|
||||
transform: translateX(4px);
|
||||
box-shadow: 0 4px 8px rgba(212, 165, 116, 0.2);
|
||||
}
|
||||
|
||||
.service-item.coming-soon {
|
||||
border-left-color: var(--color-warm);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.service-item h3 {
|
||||
margin-bottom: var(--space-xs);
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.service-item p {
|
||||
color: var(--color-text-dim);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.service-item {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.service-item:hover {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
interface Props {
|
||||
title: string;
|
||||
description: string;
|
||||
comingSoonNote?: string;
|
||||
}
|
||||
|
||||
const { title, description, comingSoonNote } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="support-item" role="listitem">
|
||||
<h3>{title}</h3>
|
||||
<p>
|
||||
{description}
|
||||
{comingSoonNote && (
|
||||
<span class="coming-soon-text">({comingSoonNote})</span>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.support-item {
|
||||
background: var(--color-bg);
|
||||
padding: var(--space-md);
|
||||
border-radius: 8px;
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.support-item:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(212, 165, 116, 0.15);
|
||||
}
|
||||
|
||||
.support-item h3 {
|
||||
margin-bottom: var(--space-xs);
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.support-item p {
|
||||
color: var(--color-text-dim);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.coming-soon-text {
|
||||
font-style: italic;
|
||||
color: var(--color-warm);
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.support-item {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.support-item:hover {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user