// ─────────── Shared atoms & icons ─────────── const Icon = ({ name, size = 18 }) => { const s = { width: size, height: size, fill: 'none', stroke: 'currentColor', strokeWidth: 1.6, strokeLinecap: 'round', strokeLinejoin: 'round' }; switch (name) { case 'arrow': return ; case 'phone': return ; case 'mail': return ; case 'pin': return ; case 'calendar': return ; case 'tooth': return ; case 'sparkle': return ; case 'shield': return ; case 'smile': return ; case 'syringe': return ; case 'kid': return ; case 'xray': return ; case 'crown': return ; case 'play': return ; case 'star': return ; case 'check': return ; case 'plus': return ; case 'minus': return ; case 'chevron-left': return ; case 'chevron-right': return ; case 'instagram': return ; case 'facebook': return ; case 'whatsapp': return ; case 'menu': return ; case 'drag': return ; case 'car': return ; default: return null; } }; const Btn = ({ kind = 'primary', children, icon = 'arrow', ...rest }) => ( ); // reveal-on-scroll const useReveal = () => { React.useEffect(() => { const els = document.querySelectorAll('.reveal'); const io = new IntersectionObserver((entries) => { entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add('in'); io.unobserve(e.target); } }); }, { threshold: 0.12 }); els.forEach(el => io.observe(el)); return () => io.disconnect(); }, []); }; // Smooth scroll to section const scrollTo = (id) => { const el = document.getElementById(id); if (el) { const off = 90; const top = el.getBoundingClientRect().top + window.scrollY - off; window.scrollTo({ top, behavior: 'smooth' }); } }; // ─────────── Top bar ─────────── const TopBar = () => { const [scrolled, setScrolled] = React.useState(false); const [active, setActive] = React.useState('home'); const [menuOpen, setMenuOpen] = React.useState(false); React.useEffect(() => { const onScroll = () => { setScrolled(window.scrollY > 30); const sections = ['home', 'doctors', 'treatments', 'book']; for (let i = sections.length - 1; i >= 0; i--) { const el = document.getElementById(sections[i]); if (el && el.getBoundingClientRect().top < 200) { setActive(sections[i]); break; } } }; window.addEventListener('scroll', onScroll); return () => window.removeEventListener('scroll', onScroll); }, []); React.useEffect(() => { document.body.style.overflow = menuOpen ? 'hidden' : ''; return () => { document.body.style.overflow = ''; }; }, [menuOpen]); const navItems = [ { href: '#home', l: 'Home', onClick: (e) => { e.preventDefault(); scrollTo('home'); } }, { href: '/doctors', l: 'Doctors' }, { href: '/treatments', l: 'Treatments' }, { href: '/branches', l: 'Branches' }, { href: '/patients', l: 'Patient Stories' }, ]; return ( <>
{ e.preventDefault(); scrollTo('home'); }}> Align-O-Dent
+91 93218 59061 scrollTo('book')}>Book Visit
+91 93218 59061
); }; // ─────────── Shared top bar for sub-pages (treatments, patients, etc.) ─────────── // Identical scroll behaviour to TopBar — transparent → frosted glass on scroll. // Pass `active` prop matching the page id: 'treatments' | 'patients' const PageTopBar = ({ active = '' }) => { const [scrolled, setScrolled] = React.useState(false); const [menuOpen, setMenuOpen] = React.useState(false); React.useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 30); window.addEventListener('scroll', onScroll); return () => window.removeEventListener('scroll', onScroll); }, []); React.useEffect(() => { document.body.style.overflow = menuOpen ? 'hidden' : ''; return () => { document.body.style.overflow = ''; }; }, [menuOpen]); const links = [ { href: '/', l: 'Home', id: 'home' }, { href: '/doctors', l: 'Doctors', id: 'doctors' }, { href: '/treatments', l: 'Treatments', id: 'treatments' }, { href: '/branches', l: 'Branches', id: 'branches' }, { href: '/patients', l: 'Patient Stories', id: 'patients' }, ]; return ( <>
Align-O-Dent
+91 93218 59061 Book Visit
+91 93218 59061 setMenuOpen(false)}> Book Visit
); }; Object.assign(window, { Icon, Btn, useReveal, scrollTo, TopBar, PageTopBar });