Files
emdash-patch-imageupload/templates/marketing/src/components/blocks/Features.astro
kunthawat 2d1be52177 Emdash source with visual editor image upload fix
Fixes:
1. media.ts: wrap placeholder generation in try-catch
2. toolbar.ts: check r.ok, display error message in popover
2026-05-03 10:44:54 +07:00

136 lines
2.8 KiB
Plaintext

---
import { Icon } from "astro-iconset/components";
interface Props {
node: {
_key?: string;
headline?: string;
subheadline?: string;
features: Array<{
icon: string;
title: string;
description: string;
}>;
};
}
const { node } = Astro.props;
const { _key, headline, subheadline, features } = node;
const iconMap: Record<string, string> = {
zap: "ph:lightning",
shield: "ph:shield-check",
users: "ph:users-three",
chart: "ph:chart-bar",
code: "ph:code",
globe: "ph:globe",
heart: "ph:heart",
star: "ph:star",
check: "ph:check-circle",
lock: "ph:lock",
clock: "ph:clock",
cloud: "ph:cloud",
};
---
<section class="features section" id={_key}>
<div class="container">
{(headline || subheadline) && (
<header class="features-header">
{headline && <h2 class="features-headline">{headline}</h2>}
{subheadline && <p class="features-subheadline">{subheadline}</p>}
</header>
)}
<div class="features-grid">
{features.map((feature) => (
<div class="feature-card">
<div class="feature-icon">
<Icon name={iconMap[feature.icon] || "ph:sparkle"} aria-hidden="true" />
</div>
<h3 class="feature-title">{feature.title}</h3>
<p class="feature-description">{feature.description}</p>
</div>
))}
</div>
</div>
</section>
<style>
.features-header {
text-align: center;
max-width: var(--max-width);
margin: 0 auto var(--spacing-4xl);
}
.features-headline {
font-size: var(--font-size-3xl);
font-weight: 800;
margin-bottom: var(--spacing-md);
}
.features-subheadline {
font-size: var(--font-size-lg);
color: var(--color-muted);
}
.features-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--spacing-xl);
}
.feature-card {
padding: var(--spacing-xl);
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius-lg);
transition:
transform var(--transition-base),
box-shadow var(--transition-base),
border-color var(--transition-base);
}
.feature-card:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-lg);
border-color: var(--color-primary-light);
}
.feature-icon {
width: 48px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
color: white;
background: linear-gradient(135deg, var(--color-primary), var(--color-accent));
border-radius: var(--radius);
margin-bottom: var(--spacing-lg);
}
.feature-title {
font-size: var(--font-size-lg);
font-weight: 700;
margin-bottom: var(--spacing-sm);
}
.feature-description {
font-size: var(--font-size-sm);
color: var(--color-muted);
line-height: 1.6;
}
@media (max-width: 900px) {
.features-grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 600px) {
.features-grid {
grid-template-columns: 1fr;
}
}
</style>