enhance footer mobile style & implement footer in each page
This commit is contained in:
@@ -15,12 +15,26 @@ import {
|
||||
} from '@ant-design/icons';
|
||||
import { Typography } from 'antd';
|
||||
import { motion } from 'framer-motion';
|
||||
import React from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import styles from './Footer.module.css';
|
||||
|
||||
const { Paragraph } = Typography;
|
||||
|
||||
const Footer: React.FC = () => {
|
||||
const [expandedSections, setExpandedSections] = useState<{ [key: string]: boolean }>({});
|
||||
const [isMobile, setIsMobile] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const checkMobile = () => {
|
||||
setIsMobile(window.innerWidth <= 768);
|
||||
};
|
||||
|
||||
checkMobile();
|
||||
window.addEventListener('resize', checkMobile);
|
||||
|
||||
return () => window.removeEventListener('resize', checkMobile);
|
||||
}, []);
|
||||
|
||||
const containerVariants = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
@@ -40,6 +54,70 @@ const Footer: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const toggleSection = (sectionKey: string) => {
|
||||
if (isMobile) {
|
||||
setExpandedSections(prev => ({
|
||||
...prev,
|
||||
[sectionKey]: !prev[sectionKey]
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
const footerSections = [
|
||||
{
|
||||
key: 'company',
|
||||
title: 'Company',
|
||||
icon: <TeamOutlined className={styles.footerColumnIcon} />,
|
||||
links: [
|
||||
{ href: '/about', text: 'About Us' },
|
||||
{ href: '/services', text: 'Our Services' },
|
||||
{ href: '/projects', text: 'Portfolio' },
|
||||
{ href: '/contact', text: 'Contact Us' }
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'services',
|
||||
title: 'Services',
|
||||
icon: <BulbOutlined className={styles.footerColumnIcon} />,
|
||||
links: [
|
||||
{ href: '/services#webdev', text: 'Web Development' },
|
||||
{ href: '/services#mobile', text: 'Mobile Apps' },
|
||||
{ href: '/services#ai', text: 'AI Solutions' },
|
||||
{ href: '/services#cloud', text: 'Cloud Services' }
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'resources',
|
||||
title: 'Resources',
|
||||
icon: <TrophyOutlined className={styles.footerColumnIcon} />,
|
||||
links: [
|
||||
{ href: '/blog', text: 'Blog & Insights' },
|
||||
{ href: '/case-studies', text: 'Case Studies' },
|
||||
{ href: '/whitepapers', text: 'Whitepapers' },
|
||||
{ href: '/webinars', text: 'Webinars' }
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'contact',
|
||||
title: 'Contact Info',
|
||||
icon: <MailOutlined className={styles.footerColumnIcon} />,
|
||||
links: [
|
||||
{ href: 'mailto:info@techmaster.com', text: 'info@techmaster.com' },
|
||||
{ href: 'tel:+15551234567', text: '+1 (555) 123-4567' },
|
||||
{ href: '#', text: 'San Francisco, CA' },
|
||||
{ href: '/support', text: '24/7 Support' }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const getLinkIcon = (href: string) => {
|
||||
if (href.startsWith('mailto:')) return <MailOutlined className={styles.footerLinkIcon} />;
|
||||
if (href.startsWith('tel:')) return <PhoneOutlined className={styles.footerLinkIcon} />;
|
||||
if (href.includes('support')) return <ArrowRightOutlined className={styles.footerLinkIcon} />;
|
||||
if (href.includes('San Francisco')) return <EnvironmentOutlined className={styles.footerLinkIcon} />;
|
||||
return <ArrowRightOutlined className={styles.footerLinkIcon} />;
|
||||
};
|
||||
|
||||
return (
|
||||
<footer className={styles.footer}>
|
||||
<div className={styles.footerBackground}>
|
||||
@@ -55,137 +133,49 @@ const Footer: React.FC = () => {
|
||||
viewport={{ once: true }}
|
||||
className={styles.footerContent}
|
||||
>
|
||||
<motion.div variants={itemVariants} className={styles.footerColumn}>
|
||||
<div className={styles.footerColumnTitle}>
|
||||
<TeamOutlined className={styles.footerColumnIcon} />
|
||||
Company
|
||||
</div>
|
||||
<ul className={styles.footerLinks}>
|
||||
<li className={styles.footerLink}>
|
||||
<a href="/about">
|
||||
<ArrowRightOutlined className={styles.footerLinkIcon} />
|
||||
About Us
|
||||
</a>
|
||||
</li>
|
||||
<li className={styles.footerLink}>
|
||||
<a href="/services">
|
||||
<ArrowRightOutlined className={styles.footerLinkIcon} />
|
||||
Our Services
|
||||
</a>
|
||||
</li>
|
||||
<li className={styles.footerLink}>
|
||||
<a href="/projects">
|
||||
<ArrowRightOutlined className={styles.footerLinkIcon} />
|
||||
Portfolio
|
||||
</a>
|
||||
</li>
|
||||
<li className={styles.footerLink}>
|
||||
<a href="/contact">
|
||||
<ArrowRightOutlined className={styles.footerLinkIcon} />
|
||||
Contact Us
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</motion.div>
|
||||
|
||||
<motion.div variants={itemVariants} className={styles.footerColumn}>
|
||||
<div className={styles.footerColumnTitle}>
|
||||
<BulbOutlined className={styles.footerColumnIcon} />
|
||||
Services
|
||||
</div>
|
||||
<ul className={styles.footerLinks}>
|
||||
<li className={styles.footerLink}>
|
||||
<a href="/services#webdev">
|
||||
<ArrowRightOutlined className={styles.footerLinkIcon} />
|
||||
Web Development
|
||||
</a>
|
||||
</li>
|
||||
<li className={styles.footerLink}>
|
||||
<a href="/services#mobile">
|
||||
<ArrowRightOutlined className={styles.footerLinkIcon} />
|
||||
Mobile Apps
|
||||
</a>
|
||||
</li>
|
||||
<li className={styles.footerLink}>
|
||||
<a href="/services#ai">
|
||||
<ArrowRightOutlined className={styles.footerLinkIcon} />
|
||||
AI Solutions
|
||||
</a>
|
||||
</li>
|
||||
<li className={styles.footerLink}>
|
||||
<a href="/services#cloud">
|
||||
<ArrowRightOutlined className={styles.footerLinkIcon} />
|
||||
Cloud Services
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</motion.div>
|
||||
|
||||
<motion.div variants={itemVariants} className={styles.footerColumn}>
|
||||
<div className={styles.footerColumnTitle}>
|
||||
<TrophyOutlined className={styles.footerColumnIcon} />
|
||||
Resources
|
||||
</div>
|
||||
<ul className={styles.footerLinks}>
|
||||
<li className={styles.footerLink}>
|
||||
<a href="/blog">
|
||||
<ArrowRightOutlined className={styles.footerLinkIcon} />
|
||||
Blog & Insights
|
||||
</a>
|
||||
</li>
|
||||
<li className={styles.footerLink}>
|
||||
<a href="/case-studies">
|
||||
<ArrowRightOutlined className={styles.footerLinkIcon} />
|
||||
Case Studies
|
||||
</a>
|
||||
</li>
|
||||
<li className={styles.footerLink}>
|
||||
<a href="/whitepapers">
|
||||
<ArrowRightOutlined className={styles.footerLinkIcon} />
|
||||
Whitepapers
|
||||
</a>
|
||||
</li>
|
||||
<li className={styles.footerLink}>
|
||||
<a href="/webinars">
|
||||
<ArrowRightOutlined className={styles.footerLinkIcon} />
|
||||
Webinars
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</motion.div>
|
||||
|
||||
<motion.div variants={itemVariants} className={styles.footerColumn}>
|
||||
<div className={styles.footerColumnTitle}>
|
||||
<MailOutlined className={styles.footerColumnIcon} />
|
||||
Contact Info
|
||||
</div>
|
||||
<ul className={styles.footerLinks}>
|
||||
<li className={styles.footerLink}>
|
||||
<a href="mailto:info@techmaster.com">
|
||||
<MailOutlined className={styles.footerLinkIcon} />
|
||||
info@techmaster.com
|
||||
</a>
|
||||
</li>
|
||||
<li className={styles.footerLink}>
|
||||
<a href="tel:+15551234567">
|
||||
<PhoneOutlined className={styles.footerLinkIcon} />
|
||||
+1 (555) 123-4567
|
||||
</a>
|
||||
</li>
|
||||
<li className={styles.footerLink}>
|
||||
<a href="#">
|
||||
<EnvironmentOutlined className={styles.footerLinkIcon} />
|
||||
San Francisco, CA
|
||||
</a>
|
||||
</li>
|
||||
<li className={styles.footerLink}>
|
||||
<a href="/support">
|
||||
<ArrowRightOutlined className={styles.footerLinkIcon} />
|
||||
24/7 Support
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</motion.div>
|
||||
{footerSections.map((section) => (
|
||||
<motion.div
|
||||
key={section.key}
|
||||
variants={itemVariants}
|
||||
className={`${styles.footerColumn} ${isMobile ? styles.mobileFooterColumn : ''}`}
|
||||
>
|
||||
<div
|
||||
className={`${styles.footerColumnTitle} ${isMobile && expandedSections[section.key] ? styles.expanded : ''}`}
|
||||
onClick={() => toggleSection(section.key)}
|
||||
role={isMobile ? 'button' : undefined}
|
||||
tabIndex={isMobile ? 0 : undefined}
|
||||
onKeyDown={(e) => {
|
||||
if (isMobile && (e.key === 'Enter' || e.key === ' ')) {
|
||||
e.preventDefault();
|
||||
toggleSection(section.key);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
||||
{section.icon}
|
||||
{section.title}
|
||||
</div>
|
||||
</div>
|
||||
<ul className={`${styles.footerLinks} ${isMobile && expandedSections[section.key] ? styles.expanded : ''}`}>
|
||||
{section.links.map((link, index) => (
|
||||
<li key={index} className={styles.footerLink}>
|
||||
<a
|
||||
href={link.href}
|
||||
onClick={(e) => {
|
||||
// Prevent navigation if it's a placeholder link
|
||||
if (link.href === '#') {
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
>
|
||||
{getLinkIcon(link.href)}
|
||||
{link.text}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</motion.div>
|
||||
))}
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
@@ -200,22 +190,46 @@ const Footer: React.FC = () => {
|
||||
</Paragraph>
|
||||
|
||||
<div className={styles.socialLinks}>
|
||||
<a href="#" className={styles.socialLink}>
|
||||
<a
|
||||
href="#"
|
||||
className={styles.socialLink}
|
||||
onClick={(e) => e.preventDefault()}
|
||||
aria-label="Facebook"
|
||||
>
|
||||
<FacebookOutlined />
|
||||
</a>
|
||||
<a href="#" className={styles.socialLink}>
|
||||
<a
|
||||
href="#"
|
||||
className={styles.socialLink}
|
||||
onClick={(e) => e.preventDefault()}
|
||||
aria-label="Twitter"
|
||||
>
|
||||
<TwitterOutlined />
|
||||
</a>
|
||||
<a href="#" className={styles.socialLink}>
|
||||
<a
|
||||
href="#"
|
||||
className={styles.socialLink}
|
||||
onClick={(e) => e.preventDefault()}
|
||||
aria-label="LinkedIn"
|
||||
>
|
||||
<LinkedinOutlined />
|
||||
</a>
|
||||
<a href="#" className={styles.socialLink}>
|
||||
<a
|
||||
href="#"
|
||||
className={styles.socialLink}
|
||||
onClick={(e) => e.preventDefault()}
|
||||
aria-label="Instagram"
|
||||
>
|
||||
<InstagramOutlined />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div className={styles.copyright}>
|
||||
© 2024 Tech Master. All rights reserved. | Privacy Policy | Terms of Service
|
||||
<span>© 2024 Tech Master. All rights reserved.</span>
|
||||
<div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap', justifyContent: 'center' }}>
|
||||
<a href="/privacy" onClick={(e) => e.preventDefault()}>Privacy Policy</a>
|
||||
<a href="/terms" onClick={(e) => e.preventDefault()}>Terms of Service</a>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user