feat(conversion): add Interactive Luxury FAQ Accordion and Sticky Mobile Quick Connect Dock

This commit is contained in:
2026-08-30 09:12:13 -07:00
parent e1f03401a8
commit fca19b1b91
4 changed files with 307 additions and 0 deletions
+15
View File
@@ -182,3 +182,18 @@ h1, h2, h3, h4 {
font-size: 16px !important; /* Prevents auto-zoom on iOS */ font-size: 16px !important; /* Prevents auto-zoom on iOS */
} }
} }
.mobile-only-quick-bar {
display: none !important;
}
@media (max-width: 768px) {
.mobile-only-quick-bar {
display: flex !important;
}
}
@keyframes slideUpBar {
from { transform: translateY(100%); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
+4
View File
@@ -9,9 +9,11 @@ import PillarsSection from '@/components/PillarsSection';
import ServicesSection from '@/components/ServicesSection'; import ServicesSection from '@/components/ServicesSection';
import TestimonialsSection from '@/components/TestimonialsSection'; import TestimonialsSection from '@/components/TestimonialsSection';
import AboutSection from '@/components/AboutSection'; import AboutSection from '@/components/AboutSection';
import FaqSection from '@/components/FaqSection';
import BookingForm from '@/components/BookingForm'; import BookingForm from '@/components/BookingForm';
import Footer from '@/components/Footer'; import Footer from '@/components/Footer';
import GoldSparkles from '@/components/GoldSparkles'; import GoldSparkles from '@/components/GoldSparkles';
import MobileQuickBar from '@/components/MobileQuickBar';
export default function Home() { export default function Home() {
useEffect(() => { useEffect(() => {
@@ -37,8 +39,10 @@ export default function Home() {
<ServicesSection /> <ServicesSection />
<TestimonialsSection /> <TestimonialsSection />
<AboutSection /> <AboutSection />
<FaqSection />
<BookingForm /> <BookingForm />
<Footer /> <Footer />
<MobileQuickBar />
</main> </main>
); );
} }
+201
View File
@@ -0,0 +1,201 @@
'use client';
import React, { useState } from 'react';
interface FaqItem {
question: string;
answer: string;
category: string;
}
const faqs: FaqItem[] = [
{
category: 'Booking & Timing',
question: 'How far in advance should I book my event decor?',
answer: 'We recommend booking 4 to 8 weeks in advance for weekend milestones, birthdays, and baby showers, and 2 to 4 months for weddings and large corporate galas. However, if your event is sooner, reach out! If our setup crew has availability, we gladly accommodate rush dates.',
},
{
category: 'Full-Service Experience',
question: 'Do you handle delivery, setup, and teardown?',
answer: 'Yes! Every Wise Hearted installation is 100% full-service. We arrive on-site early to professionally assemble and style every balloon garland, backdrop panel, and floral accent. After your celebration concludes, our team returns to safely strike and remove all rental backdrop structures.',
},
{
category: 'Customization & Themes',
question: 'Can you match my exact Pinterest board, theme, or invitation colors?',
answer: 'Absolutely! Custom color matching is our specialty. We use premium, professional-grade balloons and advanced custom double-stuffing techniques to create bespoke color palettes (e.g., custom matte terracotta, dusty rose, chrome gold, or pearl tones) that flawlessly match your invitations and venue mood board.',
},
{
category: 'Outdoor Events',
question: 'Can balloon garlands and arched backdrops be installed outdoors?',
answer: 'Yes! We use heavy-duty commercial baseplates, reinforced framing, and specialized rigging techniques designed specifically for Southern California weather. We also advise on ideal shaded placement to keep balloons looking glossy and vibrant all day.',
},
{
category: 'Service Areas',
question: 'What areas throughout Southern California do you serve?',
answer: 'We proudly serve the entire Antelope Valley (Palmdale, Lancaster, Quartz Hill), Santa Clarita Valley (Valencia, Stevenson Ranch, Canyon Country), San Fernando Valley, Greater Los Angeles, and surrounding counties. We are also available for select destination events.',
},
{
category: 'Payment & Quotes',
question: 'How does the quote and booking process work?',
answer: 'It starts with submitting a custom quote request on our website. Jackie will review your date, theme, and vision, then provide a detailed design proposal. A 50% retainer and signed contract officially locks your date on our calendar, with the remaining balance due prior to event setup.',
},
];
export default function FaqSection() {
const [openIndex, setOpenIndex] = useState<number | null>(0);
const toggleFaq = (index: number) => {
setOpenIndex(openIndex === index ? null : index);
};
return (
<section
id="faq"
style={{
padding: 'clamp(60px, 10vw, 100px) 0',
backgroundColor: '#0A0A0A',
position: 'relative',
borderBottom: '1px solid var(--border-gold)',
}}
>
<div className="container" style={{ maxWidth: '940px' }}>
{/* Header */}
<div style={{ textAlign: 'center', marginBottom: '45px', padding: '0 8px' }}>
<span
style={{
fontSize: '0.85rem',
fontWeight: 800,
color: 'var(--color-pink-light)',
letterSpacing: '0.15em',
textTransform: 'uppercase',
display: 'block',
marginBottom: '10px',
}}
>
Frequently Asked Questions
</span>
<h2
style={{
fontSize: 'clamp(2rem, 3.8vw, 2.8rem)',
fontWeight: 800,
marginBottom: '16px',
}}
>
Everything You Need <span className="gold-gradient-text">To Know</span>
</h2>
<p
style={{
fontSize: '1.05rem',
color: '#94A3B8',
maxWidth: '680px',
margin: '0 auto',
lineHeight: 1.6,
}}
>
Got questions about setup timing, color customization, or booking deposits? Here are answers to our most common client inquiries.
</p>
</div>
{/* FAQ Accordion List */}
<div style={{ display: 'flex', flexDirection: 'column', gap: '14px' }}>
{faqs.map((faq, idx) => {
const isOpen = openIndex === idx;
return (
<div
key={idx}
className="glass-panel"
style={{
border: isOpen ? '1.5px solid var(--color-gold)' : '1px solid rgba(255, 255, 255, 0.08)',
borderRadius: '16px',
overflow: 'hidden',
transition: 'all 0.25s ease',
boxShadow: isOpen ? '0 8px 25px rgba(212, 175, 55, 0.15)' : 'none',
}}
>
<button
type="button"
onClick={() => toggleFaq(idx)}
style={{
width: '100%',
padding: '20px 24px',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
background: 'transparent',
border: 'none',
color: '#FFFFFF',
textAlign: 'left',
cursor: 'pointer',
gap: '16px',
}}
aria-expanded={isOpen}
>
<div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
<span style={{ color: 'var(--color-pink-light)', fontSize: '0.9rem' }}></span>
<span style={{ fontSize: '1.05rem', fontWeight: 700, color: isOpen ? 'var(--color-gold-light)' : '#F8FAFC' }}>
{faq.question}
</span>
</div>
<span
style={{
fontSize: '1.3rem',
fontWeight: 700,
color: isOpen ? 'var(--color-gold)' : '#94A3B8',
transform: isOpen ? 'rotate(45deg)' : 'rotate(0deg)',
transition: 'transform 0.25s ease, color 0.25s ease',
flexShrink: 0,
}}
>
+
</span>
</button>
{isOpen && (
<div
style={{
padding: '0 24px 22px 42px',
color: '#CBD5E1',
fontSize: '0.95rem',
lineHeight: 1.7,
borderTop: '1px solid rgba(255, 255, 255, 0.05)',
paddingTop: '14px',
}}
>
{faq.answer}
</div>
)}
</div>
);
})}
</div>
{/* Bottom Help Callout */}
<div
style={{
marginTop: '36px',
textAlign: 'center',
background: 'rgba(255, 255, 255, 0.03)',
borderRadius: '16px',
padding: '18px 24px',
border: '1px solid rgba(255, 255, 255, 0.08)',
}}
>
<span style={{ color: '#94A3B8', fontSize: '0.92rem' }}>
Have a custom design inquiry or special venue requirement?{' '}
</span>
<a
href="#contact"
style={{
color: 'var(--color-gold)',
fontWeight: 800,
textDecoration: 'none',
marginLeft: '4px',
}}
>
Chat with Jackie directly
</a>
</div>
</div>
</section>
);
}
+87
View File
@@ -0,0 +1,87 @@
'use client';
import React, { useState, useEffect } from 'react';
import Link from 'next/link';
export default function MobileQuickBar() {
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
const handleScroll = () => {
// Show only after scrolling down 150px
const scrollPos = window.scrollY;
setIsVisible(scrollPos > 150);
};
window.addEventListener('scroll', handleScroll, { passive: true });
return () => window.removeEventListener('scroll', handleScroll);
}, []);
if (!isVisible) return null;
return (
<div
className="mobile-only-quick-bar"
style={{
position: 'fixed',
bottom: 0,
left: 0,
right: 0,
zIndex: 9999,
padding: '10px 14px clamp(12px, 3vw, 18px)',
background: 'rgba(8, 8, 8, 0.94)',
backdropFilter: 'blur(20px)',
WebkitBackdropFilter: 'blur(20px)',
borderTop: '1.5px solid var(--border-gold)',
boxShadow: '0 -10px 30px rgba(0, 0, 0, 0.8), 0 0 20px rgba(212, 175, 55, 0.15)',
display: 'flex',
alignItems: 'center',
gap: '10px',
animation: 'slideUpBar 0.3s ease-out',
}}
>
<a
href="tel:+16619936669"
style={{
flex: '1',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '6px',
background: 'rgba(255, 255, 255, 0.08)',
border: '1px solid rgba(255, 255, 255, 0.18)',
color: '#FFFFFF',
padding: '12px 10px',
borderRadius: '50px',
fontSize: '0.86rem',
fontWeight: 700,
textDecoration: 'none',
textAlign: 'center',
}}
>
<span>📞</span> Call / Text
</a>
<Link
href="#contact"
className="btn-gold"
style={{
flex: '1.3',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '6px',
padding: '12px 14px',
borderRadius: '50px',
fontSize: '0.86rem',
fontWeight: 800,
textDecoration: 'none',
textAlign: 'center',
boxShadow: '0 4px 15px rgba(212, 175, 55, 0.4)',
}}
>
<span></span> Get Quote
</Link>
</div>
);
}