Refactor frontend sections to use Tailwind CSS

Convert custom CSS styling to Tailwind utility classes across marketing
and about pages. Improve responsive layouts in feature grids, service
lists, and sliders. Consolidate section headers using the shared
SectionHeader component to maintain visual consistency.
This commit is contained in:
2026-03-11 17:42:34 +08:00
parent df1efb4881
commit 2e32d52133
16 changed files with 510 additions and 1006 deletions

View File

@@ -6,304 +6,93 @@
*/
interface BenefitItem {
title: string
icon: string
title: string;
img: string;
}
interface Props {
benefits?: BenefitItem[]
benefits?: BenefitItem[];
}
const defaultBenefits: BenefitItem[] = [
{
title: '高績效、高獎金\n新人開張獎金',
icon: 'bonus',
title: "高績效、高獎金\n新人開張獎金",
img: "/api/media/file/61f24aa108528b79b2942d05_Make%20it%20rain-bro-%E6%96%B0%E4%BA%BA%E9%96%8B%E5%BC%B5%E7%8D%8E%E9%87%91.svg",
},
{
title: '生日慶生、電影日\n員工下午茶',
icon: 'birthday',
title: "生日慶生、電影日\n員工下午茶",
img: "/api/media/file/61f24aa108528be590942d06_Blowing%20out%20Birthday%20candles-bro-%E7%94%9F%E6%97%A5%E6%85%B6%E7%94%9F.svg",
},
{
title: '教育訓練補助',
icon: 'education',
title: "教育訓練補助",
img: "/api/media/file/61f24aa108528be22a942d03_Online%20learning-bro-%E6%95%99%E8%82%B2%E8%A8%93%E7%B7%B4%E8%A3%9C%E5%8A%A9.svg",
},
{
title: '寬敞的工作空間',
icon: 'workspace',
title: "寬敞的工作空間",
img: "/api/media/file/61f24aa108528be064942d08_Shared%20workspace-bro-%E5%AF%AC%E6%95%9E%E7%9A%84%E5%B7%A5%E4%BD%9C%E7%A9%BA%E9%96%93.svg",
},
{
title: '員工國內外旅遊\n部門聚餐、年終活動',
icon: 'travel',
title: "員工國內外旅遊\n部門聚餐、年終活動",
img: "/api/media/file/61f24aa108528b0960942d04_Flight%20Booking-bro-%E5%93%A1%E5%B7%A5%E6%97%85%E9%81%8A.svg",
},
{
title: '入職培訓及團隊建設',
icon: 'training',
title: "入職培訓及團隊建設",
img: "/api/media/file/61f24aa108528bf90b942d02_Brainstorming-bro-%E5%85%A5%E8%81%B7%E5%9F%B9%E8%A8%93.svg",
},
]
];
const benefits = Astro.props.benefits || defaultBenefits
// Icon SVG components (placeholder for now, replace with actual SVG)
const getIconSVG = (iconType: string) => {
const icons: Record<string, string> = {
bonus: `<svg viewBox="0 0 200 200" class="benefit-icon-svg">
<circle cx="100" cy="70" r="40" fill="#23608c" opacity="0.2"/>
<rect x="60" y="100" width="80" height="60" rx="8" fill="#23608c"/>
<text x="100" y="140" text-anchor="middle" fill="white" font-size="36">💰</text>
</svg>`,
birthday: `<svg viewBox="0 0 200 200" class="benefit-icon-svg">
<circle cx="100" cy="70" r="40" fill="#23608c" opacity="0.2"/>
<rect x="60" y="100" width="80" height="60" rx="8" fill="#23608c"/>
<text x="100" y="140" text-anchor="middle" fill="white" font-size="36">🎂</text>
</svg>`,
education: `<svg viewBox="0 0 200 200" class="benefit-icon-svg">
<circle cx="100" cy="70" r="40" fill="#23608c" opacity="0.2"/>
<rect x="60" y="100" width="80" height="60" rx="8" fill="#23608c"/>
<text x="100" y="140" text-anchor="middle" fill="white" font-size="36">📚</text>
</svg>`,
workspace: `<svg viewBox="0 0 200 200" class="benefit-icon-svg">
<circle cx="100" cy="70" r="40" fill="#23608c" opacity="0.2"/>
<rect x="60" y="100" width="80" height="60" rx="8" fill="#23608c"/>
<text x="100" y="140" text-anchor="middle" fill="white" font-size="36">🏢</text>
</svg>`,
travel: `<svg viewBox="0 0 200 200" class="benefit-icon-svg">
<circle cx="100" cy="70" r="40" fill="#23608c" opacity="0.2"/>
<rect x="60" y="100" width="80" height="60" rx="8" fill="#23608c"/>
<text x="100" y="140" text-anchor="middle" fill="white" font-size="36">✈️</text>
</svg>`,
training: `<svg viewBox="0 0 200 200" class="benefit-icon-svg">
<circle cx="100" cy="70" r="40" fill="#23608c" opacity="0.2"/>
<rect x="60" y="100" width="80" height="60" rx="8" fill="#23608c"/>
<text x="100" y="140" text-anchor="middle" fill="white" font-size="36">🤝</text>
</svg>`,
}
return icons[iconType] || icons.bonus
}
const benefits = Astro.props.benefits || defaultBenefits;
import SectionHeader from "../components/SectionHeader.astro";
---
<section class="section-benefit" aria-labelledby="benefits-heading">
<div class="container w-container">
<section
class="py-15 px-5 bg-white md:py-10 md:px-4"
aria-labelledby="benefits-heading"
>
<div class="max-w-6xl mx-auto">
<!-- Section Header -->
<div class="section_header_w_line">
<div class="divider_line"></div>
<div class="header_subtitle">
<h2 id="benefits-heading" class="header_subtitle_head">工作福利</h2>
<p class="header_subtitle_paragraph">Benefit Package</p>
</div>
<div class="divider_line"></div>
</div>
<SectionHeader
title="工作福利"
subtitle="Benefit Packages"
sectionBg="bg-white"
/>
<!-- Benefits Grid -->
<div class="benefit-grid-wrapper">
<!-- Benefits Grid: 2 cards per row -->
<div
class="max-w-md md:max-w-3xl mx-auto grid grid-cols-1 gap-x-2 gap-y-2 md:gap-y-6 md:grid-cols-2 py-18"
>
{
benefits.map((benefit, index) => (
<div class={`benefit-card ${index % 2 === 0 ? 'benefit-card' : 'benefit-card-opposite'}`}>
<!-- Odd: Icon on right, Even: Icon on left -->
{
index % 2 === 0 ? (
<>
<div class="benefit-content">
<h3 class="benefit-title-text">{benefit.title}</h3>
</div>
<div class="benefit-image-right" set:html={getIconSVG(benefit.icon)} />
</>
) : (
<>
<div class="benefit-image-left" set:html={getIconSVG(benefit.icon)} />
<div class="benefit-content">
<h3 class="benefit-title-text">{benefit.title}</h3>
</div>
</>
)
}
</div>
))
benefits.map((benefit, index) => {
const isLeft = index % 2 === 0;
return (
<div class="grid grid-cols-2 gap-2 items-center">
<div
class:list={[
isLeft ? "order-1 text-right" : "order-2 text-left",
]}
>
<h3 class="text-xl md:text-base lg:text-xl font-semibold text-(--color-enchunblue) whitespace-pre-wrap leading-snug">
{benefit.title}
</h3>
</div>
<div
class:list={[
"flex items-center",
isLeft ? "order-2 justify-start" : "order-1 justify-end",
]}
>
<img
src={`https://enchun-cms.anlstudio.cc${benefit.img}`}
alt={benefit.title}
class="size-35 object-contain"
loading="lazy"
decoding="async"
/>
</div>
</div>
);
})
}
</div>
</div>
</section>
<style>
/* Benefits Section Styles - Pixel-perfect from Webflow */
.section-benefit {
padding: 60px 20px;
background-color: #ffffff;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.w-container {
max-width: 1200px;
margin: 0 auto;
}
/* Section Header */
.section_header_w_line {
display: flex;
align-items: center;
justify-content: center;
gap: 16px;
margin-bottom: 48px;
}
.header_subtitle {
text-align: center;
}
.header_subtitle_head {
color: var(--color-enchunblue);
font-family: "Noto Sans TC", sans-serif;
font-weight: 700;
font-size: 2rem;
margin-bottom: 8px;
}
.header_subtitle_paragraph {
color: var(--color-gray-600);
font-family: "Quicksand", sans-serif;
font-weight: 400;
font-size: 1rem;
}
.divider_line {
width: 40px;
height: 2px;
background-color: var(--color-enchunblue);
}
/* Benefits Grid */
.benefit-grid-wrapper {
max-width: 1000px;
margin: 0 auto;
}
/* Benefit Card */
.benefit-card,
.benefit-card-opposite {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 40px;
align-items: center;
margin-bottom: 60px;
}
/* Odd cards: icon on right */
.benefit-card {
grid-template-areas: "content image";
}
.benefit-card .benefit-content {
grid-area: content;
text-align: left;
}
.benefit-card .benefit-image-right {
grid-area: image;
display: flex;
justify-content: center;
align-items: center;
}
/* Even cards: icon on left */
.benefit-card-opposite {
grid-template-areas: "image content";
}
.benefit-card-opposite .benefit-content {
grid-area: content;
text-align: left;
}
.benefit-card-opposite .benefit-image-left {
grid-area: image;
display: flex;
justify-content: center;
align-items: center;
}
/* Benefit Title */
.benefit-title-text {
font-size: 1.5rem;
font-weight: 600;
color: var(--color-tarawera, #23608c);
white-space: pre-line;
line-height: 1.4;
}
/* Benefit Icon */
.benefit-icon-svg {
width: 120px;
height: 120px;
}
.benefit-image-right,
.benefit-image-left {
display: flex;
justify-content: center;
align-items: center;
}
.benefit-image-right svg,
.benefit-image-left svg {
width: 120px;
height: 120px;
}
/* Responsive Adjustments */
@media (max-width: 991px) {
.benefit-card,
.benefit-card-opposite {
gap: 24px;
margin-bottom: 40px;
}
.benefit-title-text {
font-size: 1.25rem;
}
}
@media (max-width: 767px) {
.section-benefit {
padding: 40px 16px;
}
.section_header_w_line {
flex-wrap: wrap;
}
.benefit-card,
.benefit-card-opposite {
grid-template-columns: 1fr;
grid-template-areas: "image" "content" !important;
gap: 24px;
margin-bottom: 48px;
}
.benefit-content {
text-align: center !important;
}
.benefit-image-right,
.benefit-image-left {
order: -1;
}
.benefit-title-text {
font-size: 1.125rem;
}
.benefit-icon-svg {
width: 100px;
height: 100px;
}
.benefit-image-right svg,
.benefit-image-left svg {
width: 100px;
height: 100px;
}
}
</style>