feat: liquid glass UI, blob background, redesign home/portfolio/about pages
- Liquid glass effect on navbar/cards with backdrop-filter invert - Animated blob gradient background (SVG-based) - Portfolio section: scene-dark invert, show 5 items on home - How Work section: step flow with numbers + connecting lines - Hero: Decision snapshot replacing problem selector - About page: inverted background with contrast fixes - Fix parallax JS bundling via Astro - Fix navbar fixed positioning after liquid glass CSS - Submenu hover fix - Clean up removed legacy files/assets
This commit is contained in:
@@ -1,314 +1,47 @@
|
||||
---
|
||||
import Base from '../layouts/Base.astro';
|
||||
import Hero from '../components/Hero.astro';
|
||||
import { getCollection } from 'astro:content';
|
||||
|
||||
const faqItems = await getCollection('faq');
|
||||
const categories = ['บริการ', 'ราคา', 'ระยะเวลา', 'AI & เทคนิค', 'หลังการขาย'];
|
||||
|
||||
// Group FAQ items by category (preserve original order within each category)
|
||||
const groupedFaq = categories
|
||||
.map(cat => ({
|
||||
category: cat,
|
||||
items: faqItems.filter(f => f.data.category === cat),
|
||||
}))
|
||||
.filter(g => g.items.length > 0);
|
||||
|
||||
// Split each category's items into chunks of 2 (or 3 for the last chunk if odd count)
|
||||
function chunkItems<T>(arr: T[], size: number): T[][] {
|
||||
const chunks: T[][] = [];
|
||||
for (let i = 0; i < arr.length; i += size) {
|
||||
chunks.push(arr.slice(i, i + size));
|
||||
}
|
||||
return chunks;
|
||||
}
|
||||
|
||||
// Pre-compute all FAQ tiles with assigned spans + surfaces for visual rhythm
|
||||
// Rotation: yellow, soft, purple-soft, mint, teal, dark, coral, purple, mint
|
||||
const surfaceRotation = ['yellow', 'soft', 'purple-soft', 'mint', 'teal', 'dark', 'coral', 'purple', 'mint'] as const;
|
||||
|
||||
// Span strategy for category tile pairs: 7+5, 5+7, 8+4, 4+8, 7+5 ... avoid 6+6
|
||||
const spanPairs = [[7, 5], [5, 7], [8, 4], [4, 8], [7, 5]] as const;
|
||||
|
||||
interface FaqTile {
|
||||
category: string;
|
||||
items: typeof faqItems;
|
||||
surface: typeof surfaceRotation[number];
|
||||
span: 4 | 5 | 7 | 8;
|
||||
tileIndex: number; // 0, 1 within category
|
||||
isFirst: boolean;
|
||||
isLast: boolean;
|
||||
}
|
||||
|
||||
const faqTiles: FaqTile[] = [];
|
||||
groupedFaq.forEach((group, gIdx) => {
|
||||
const chunks = chunkItems(group.items, 2);
|
||||
const pair = spanPairs[gIdx % spanPairs.length];
|
||||
chunks.forEach((chunk, cIdx) => {
|
||||
const tileSurface = surfaceRotation[faqTiles.length % surfaceRotation.length];
|
||||
faqTiles.push({
|
||||
category: group.category,
|
||||
items: chunk,
|
||||
surface: tileSurface,
|
||||
span: (pair[cIdx] ?? 6) as 4 | 5 | 7 | 8,
|
||||
tileIndex: cIdx,
|
||||
isFirst: cIdx === 0,
|
||||
isLast: cIdx === chunks.length - 1,
|
||||
});
|
||||
});
|
||||
});
|
||||
import PageShell from '../components/PageShell.astro';
|
||||
import { faqs } from '../data/site.js';
|
||||
---
|
||||
|
||||
<Base title="คำถามที่พบบ่อย | MoreminiMore | รับทำเว็บไซต์ SEO AI Chatbot">
|
||||
<Hero
|
||||
eyebrow="FAQ"
|
||||
title="คำถามที่ลูกค้าถามบ่อยที่สุด"
|
||||
lede="30+ คำถามที่รวบรวมจากแชต LINE จริง ๆ ไม่ใช่แต่งขึ้นเอง"
|
||||
showStats={false} />
|
||||
|
||||
<!-- FAQ CATEGORIES (BENTO) -->
|
||||
<section class="section section-bento">
|
||||
|
||||
|
||||
<div class="container" style="position: relative; z-index: 1;">
|
||||
<div class="bento-grid">
|
||||
|
||||
{faqTiles.map((tile) => (
|
||||
<div class="bento-tile">
|
||||
|
||||
<div class="faq-list">
|
||||
{tile.items.map((item) => (
|
||||
<details class="faq-item">
|
||||
<summary class="faq-question">
|
||||
<span class="question-text">{item.data.question}</span>
|
||||
<span class="faq-toggle">+</span>
|
||||
</summary>
|
||||
<div class="faq-answer">
|
||||
<p>{item.data.answer}</p>
|
||||
</div>
|
||||
</details>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
))}
|
||||
|
||||
<!-- OTHER TOPICS — full-width tile with tag cloud -->
|
||||
<div class="bento-tile span-12 surface-soft">
|
||||
|
||||
<div class="tag-cloud">
|
||||
<span class="topic-tag">โฮสติ้ง</span>
|
||||
<span class="topic-tag">โดเมน</span>
|
||||
<span class="topic-tag">SSL</span>
|
||||
<span class="topic-tag">ใบเสนอราคา</span>
|
||||
<span class="topic-tag">ใบกำกับภาษี</span>
|
||||
<span class="topic-tag">สัญญา</span>
|
||||
<span class="topic-tag">NDA</span>
|
||||
<span class="topic-tag">ลิขสิทธิ์งาน</span>
|
||||
<span class="topic-tag">ทีมงาน</span>
|
||||
<span class="topic-tag">ขนาดทีม</span>
|
||||
<span class="topic-tag">ที่ตั้งบริษัท</span>
|
||||
<span class="topic-tag">ตัวอย่างงาน</span>
|
||||
<span class="topic-tag">ขอดูเว็บจริง</span>
|
||||
<span class="topic-tag">นัดคุยนอกสถานที่</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- QUICK CHANNELS (BENTO) -->
|
||||
<section class="section section-bento">
|
||||
|
||||
|
||||
<div class="container" style="position: relative; z-index: 1;">
|
||||
<div class="section-header reveal">
|
||||
<span class="section-badge">ช่องทางติดต่อ</span>
|
||||
<h2 class="section-title">ไม่เจอคำตอบ? <span class="highlight">ถามตรง ๆ เลย</span></h2>
|
||||
<PageShell
|
||||
title="คำถามที่พบบ่อย | MoreminiMore"
|
||||
description="คำถามที่พบบ่อยเกี่ยวกับบริการ เว็บไซต์ การตลาด ระบบอัตโนมัติ AI ราคา และวิธีทำงานของ MoreminiMore"
|
||||
>
|
||||
<section class="page-hero scene scene-light" data-scene="light">
|
||||
<div class="page-hero-grid">
|
||||
<div>
|
||||
<p class="eyebrow">FAQ</p>
|
||||
<h1>คำถามที่ควรถามก่อนเริ่มทำอะไรเพิ่ม</h1>
|
||||
</div>
|
||||
<div class="bento-grid">
|
||||
|
||||
<div class="bento-tile span-4 surface-yellow">
|
||||
|
||||
<p>คนที่อยากคุยเร็ว ๆ แบบเป็นกันเอง</p>
|
||||
<p><strong>ตอบใน 30 นาที (เวลาทำการ)</strong></p>
|
||||
<a href="https://line.me/ti/p/~@539hdlul" target="_blank" rel="noopener" class="btn btn-dark" style="margin-top: 16px;">ทักเลย →</a>
|
||||
|
||||
</div>
|
||||
<div class="bento-tile span-4 surface-soft">
|
||||
|
||||
<p>คนที่อยากคุยยาว ๆ 5–10 นาที ถามตอบสด</p>
|
||||
<p><strong>จ-ศ 09:00-18:00</strong></p>
|
||||
<a href="tel:0809955945" class="btn btn-dark" style="margin-top: 16px;">โทรเลย →</a>
|
||||
|
||||
</div>
|
||||
<div class="bento-tile span-4 surface-purple-soft">
|
||||
|
||||
<p>คนที่อยากส่งรายละเอียดโปรเจกต์ + ไฟล์แนบ</p>
|
||||
<p><strong>ตอบภายใน 1 วัน</strong></p>
|
||||
<a href="mailto:contact@moreminimore.com" class="btn btn-dark" style="margin-top: 16px;">ส่งอีเมล →</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<p class="hero-lead">
|
||||
ถ้ายังไม่แน่ใจว่าควรทำเว็บ ยิงแอด วางระบบ หรือใช้ AI ก่อน คำตอบเหล่านี้จะช่วยให้เห็นภาพเบื้องต้น
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section section-yellow cta-section">
|
||||
<div class="container">
|
||||
<div class="cta-content reveal">
|
||||
<h2 class="cta-title">พร้อมคุยรายละเอียด?</h2>
|
||||
<p class="cta-desc">นัดปรึกษาฟรี 30 นาที ผ่าน Zoom หรือนัดเจอที่ออฟฟิศ (กรุงเทพ/สมุทรสาคร)</p>
|
||||
<div class="cta-actions">
|
||||
<a href="/contact" class="btn btn-dark btn-lg">นัดปรึกษา →</a>
|
||||
<a href="https://line.me/ti/p/~@539hdlul" target="_blank" rel="noopener" class="btn btn-outline-dark btn-lg">ทัก LINE ตอนนี้</a>
|
||||
</div>
|
||||
</div>
|
||||
<section class="page-section">
|
||||
<div class="faq-list">
|
||||
{faqs.map((item) => (
|
||||
<article class="faq-item liquid-glass liquidGlass-wrapper">
|
||||
<div class="liquidGlass-effect" aria-hidden="true"></div>
|
||||
<div class="liquidGlass-tint" aria-hidden="true"></div>
|
||||
<div class="liquidGlass-shine" aria-hidden="true"></div>
|
||||
<span>{item.category}</span>
|
||||
<h2>{item.question}</h2>
|
||||
<p>{item.answer}</p>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
.section-bento {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.faq-list { display: flex; flex-direction: column; gap: 10px; margin-top: 4px; }
|
||||
|
||||
.faq-item {
|
||||
background: var(--color-white);
|
||||
border-radius: var(--radius-md);
|
||||
border: 1px solid var(--color-gray-200);
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.faq-item[open] { border-color: var(--color-primary); }
|
||||
.faq-item:hover { box-shadow: var(--shadow-sm); }
|
||||
|
||||
/* When inside a yellow surface, change item background to be visible */
|
||||
.surface-yellow .faq-item { background: var(--color-white); }
|
||||
.surface-yellow .faq-item[open] { border-color: var(--color-black); }
|
||||
|
||||
.faq-question {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 14px 18px;
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
.faq-question::-webkit-details-marker { display: none; }
|
||||
.faq-question:hover { background: var(--color-bg-alt); }
|
||||
|
||||
.question-text {
|
||||
flex: 1;
|
||||
font-family: var(--font-display);
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
color: var(--color-black);
|
||||
padding-right: 16px;
|
||||
}
|
||||
.faq-toggle {
|
||||
font-size: 22px;
|
||||
font-weight: 300;
|
||||
color: var(--color-primary-dark);
|
||||
flex-shrink: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
.faq-item[open] .faq-toggle { transform: rotate(45deg); }
|
||||
|
||||
.faq-answer {
|
||||
padding: 0 18px 16px;
|
||||
}
|
||||
.faq-answer p {
|
||||
font-size: 14px;
|
||||
line-height: 1.7;
|
||||
color: var(--color-gray-700);
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
/* Tag cloud */
|
||||
.tag-cloud {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
.topic-tag {
|
||||
display: inline-block;
|
||||
padding: 8px 16px;
|
||||
background: var(--color-white);
|
||||
color: var(--color-gray-700);
|
||||
border: 1px solid var(--color-gray-200);
|
||||
border-radius: var(--radius-full);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
.topic-tag:hover {
|
||||
background: var(--color-primary);
|
||||
border-color: var(--color-primary);
|
||||
color: var(--color-black);
|
||||
}
|
||||
|
||||
/* Section header */
|
||||
.section-header { text-align: center; margin-bottom: 48px; }
|
||||
.section-badge {
|
||||
display: inline-block;
|
||||
background: var(--color-primary);
|
||||
color: var(--color-black);
|
||||
padding: 8px 20px;
|
||||
border-radius: var(--radius-full);
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.section-title {
|
||||
font-family: var(--font-display);
|
||||
font-size: clamp(28px, 4vw, 44px);
|
||||
font-weight: 900;
|
||||
line-height: 1.15;
|
||||
color: var(--color-black);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.section-title .highlight { color: var(--color-primary-dark); }
|
||||
.section-soft { background: var(--color-bg-alt); }
|
||||
.section-yellow { background: var(--color-primary); }
|
||||
|
||||
/* CTA */
|
||||
.cta-content { text-align: center; max-width: 700px; margin: 0 auto; }
|
||||
.cta-title {
|
||||
font-family: var(--font-display);
|
||||
font-size: clamp(28px, 4vw, 44px);
|
||||
font-weight: 900;
|
||||
color: var(--color-black);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.cta-desc {
|
||||
font-size: 18px;
|
||||
color: rgba(0, 0, 0, 0.7);
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.cta-actions {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.cta-actions { flex-direction: column; }
|
||||
.cta-actions .btn { width: 100%; justify-content: center; }
|
||||
.faq-question { padding: 14px 16px; }
|
||||
.question-text { font-size: 14px; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
</script>
|
||||
<section class="final-cta">
|
||||
<div class="glass-panel liquid-glass liquidGlass-wrapper">
|
||||
<div class="liquidGlass-effect" aria-hidden="true"></div>
|
||||
<div class="liquidGlass-tint" aria-hidden="true"></div>
|
||||
<div class="liquidGlass-shine" aria-hidden="true"></div>
|
||||
<p class="eyebrow">Still unsure?</p>
|
||||
<h2>ถ้าคำถามของคุณไม่อยู่ในนี้ ส่งโจทย์มาให้เราดูได้</h2>
|
||||
<button class="button button-primary" type="button" data-open-lead>ส่งโจทย์ให้เราดู</button>
|
||||
</div>
|
||||
</section>
|
||||
</PageShell>
|
||||
|
||||
Reference in New Issue
Block a user