enhance footer mobile style & implement footer in each page
This commit is contained in:
@@ -14,6 +14,7 @@ import { Avatar, Card, Col, Row } from "antd";
|
|||||||
import Paragraph from "antd/es/typography/Paragraph";
|
import Paragraph from "antd/es/typography/Paragraph";
|
||||||
import Title from "antd/es/typography/Title";
|
import Title from "antd/es/typography/Title";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
|
import Footer from "../components/Footer/Footer";
|
||||||
import styles from "./page.module.css";
|
import styles from "./page.module.css";
|
||||||
|
|
||||||
export default function AboutPage() {
|
export default function AboutPage() {
|
||||||
@@ -391,6 +392,8 @@ export default function AboutPage() {
|
|||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<Footer />
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,17 +73,30 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
padding: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerColumnTitle:hover {
|
||||||
|
color: #a855f7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footerColumnIcon {
|
.footerColumnIcon {
|
||||||
color: #a855f7;
|
color: #a855f7;
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerColumnTitle:hover .footerColumnIcon {
|
||||||
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.footerLinks {
|
.footerLinks {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footerLink {
|
.footerLink {
|
||||||
@@ -98,12 +111,17 @@
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 4px 0;
|
padding: 8px 0;
|
||||||
|
min-height: 44px; /* Better touch target */
|
||||||
|
border-radius: 6px;
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footerLink a:hover {
|
.footerLink a:hover {
|
||||||
color: #a855f7;
|
color: #a855f7;
|
||||||
transform: translateX(6px);
|
transform: translateX(6px);
|
||||||
|
background: rgba(168, 85, 247, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.footerLinkIcon {
|
.footerLinkIcon {
|
||||||
@@ -124,6 +142,7 @@
|
|||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.socialLinks {
|
.socialLinks {
|
||||||
@@ -131,6 +150,7 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.socialLink {
|
.socialLink {
|
||||||
@@ -146,6 +166,8 @@
|
|||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
backdrop-filter: blur(8px);
|
backdrop-filter: blur(8px);
|
||||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
min-width: 45px; /* Ensure minimum touch target */
|
||||||
|
min-height: 45px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.socialLink:hover {
|
.socialLink:hover {
|
||||||
@@ -155,20 +177,77 @@
|
|||||||
box-shadow: 0 8px 25px rgba(139, 92, 246, 0.3);
|
box-shadow: 0 8px 25px rgba(139, 92, 246, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.socialLink:active {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 4px 15px rgba(139, 92, 246, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
.copyright {
|
.copyright {
|
||||||
color: #64748b;
|
color: #64748b;
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.copyright a {
|
.copyright a {
|
||||||
color: #94a3b8;
|
color: #94a3b8;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
transition: color 0.3s ease;
|
transition: color 0.3s ease;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
min-height: 32px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.copyright a:hover {
|
.copyright a:hover {
|
||||||
color: #a855f7;
|
color: #a855f7;
|
||||||
|
background: rgba(168, 85, 247, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mobile-specific enhancements */
|
||||||
|
.mobileFooterColumn {
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
padding-bottom: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileFooterColumn:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileFooterTitle {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 12px 0;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileFooterTitle::after {
|
||||||
|
content: '+';
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: #a855f7;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileFooterTitle.expanded::after {
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileFooterLinks {
|
||||||
|
max-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: max-height 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileFooterLinks.expanded {
|
||||||
|
max-height: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Responsive Design */
|
/* Responsive Design */
|
||||||
@@ -184,36 +263,99 @@
|
|||||||
padding: 60px 0 30px;
|
padding: 60px 0 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.footerContainer {
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
.footerContent {
|
.footerContent {
|
||||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
grid-template-columns: 1fr;
|
||||||
gap: 30px;
|
gap: 0;
|
||||||
margin-bottom: 40px;
|
margin-bottom: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footerColumn {
|
.footerColumn {
|
||||||
text-align: center;
|
text-align: left;
|
||||||
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footerColumnTitle {
|
.footerColumnTitle {
|
||||||
justify-content: center;
|
justify-content: space-between;
|
||||||
|
font-size: 1.05rem;
|
||||||
|
padding: 16px 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerColumnTitle::after {
|
||||||
|
content: '+';
|
||||||
|
font-size: 1.3rem;
|
||||||
|
color: #a855f7;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerColumnTitle.expanded::after {
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerLinks {
|
||||||
|
max-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: max-height 0.3s ease;
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerLinks.expanded {
|
||||||
|
max-height: 300px;
|
||||||
|
padding-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerLink {
|
||||||
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footerLink a {
|
.footerLink a {
|
||||||
justify-content: center;
|
justify-content: flex-start;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
padding: 12px 0;
|
||||||
|
min-height: 48px;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding-left: 12px;
|
||||||
|
padding-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerLink a:hover {
|
||||||
|
transform: translateX(4px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.socialLinks {
|
.socialLinks {
|
||||||
gap: 15px;
|
gap: 16px;
|
||||||
|
margin-bottom: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.socialLink {
|
.socialLink {
|
||||||
width: 40px;
|
width: 48px;
|
||||||
height: 40px;
|
height: 48px;
|
||||||
|
min-width: 48px;
|
||||||
|
min-height: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footerBottomText {
|
.footerBottomText {
|
||||||
font-size: 0.9rem;
|
font-size: 0.95rem;
|
||||||
margin-bottom: 25px;
|
margin-bottom: 25px;
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright a {
|
||||||
|
padding: 8px 12px;
|
||||||
|
min-height: 36px;
|
||||||
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,29 +364,131 @@
|
|||||||
padding: 50px 0 25px;
|
padding: 50px 0 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.footerContainer {
|
||||||
|
padding: 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.footerContent {
|
.footerContent {
|
||||||
grid-template-columns: 1fr;
|
gap: 0;
|
||||||
gap: 25px;
|
margin-bottom: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footerColumnTitle {
|
.footerColumnTitle {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
|
padding: 14px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerColumnTitle::after {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerLinks.expanded {
|
||||||
|
padding-top: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footerLink a {
|
.footerLink a {
|
||||||
font-size: 0.85rem;
|
font-size: 0.9rem;
|
||||||
|
padding: 10px 0;
|
||||||
|
min-height: 44px;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.socialLinks {
|
.socialLinks {
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.socialLink {
|
.socialLink {
|
||||||
width: 35px;
|
width: 44px;
|
||||||
height: 35px;
|
height: 44px;
|
||||||
|
min-width: 44px;
|
||||||
|
min-height: 44px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerBottomText {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 0 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.copyright {
|
.copyright {
|
||||||
font-size: 0.8rem;
|
font-size: 0.75rem;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright a {
|
||||||
|
padding: 6px 10px;
|
||||||
|
min-height: 32px;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 360px) {
|
||||||
|
.footer {
|
||||||
|
padding: 40px 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerContainer {
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerColumnTitle {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
padding: 12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerLink a {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 8px 0;
|
||||||
|
min-height: 40px;
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.socialLinks {
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.socialLink {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
min-width: 40px;
|
||||||
|
min-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerBottomText {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
font-size: 0.7rem;
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Touch device optimizations */
|
||||||
|
@media (hover: none) and (pointer: coarse) {
|
||||||
|
.footerLink a:hover {
|
||||||
|
transform: none;
|
||||||
|
background: rgba(168, 85, 247, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.socialLink:hover {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.socialLink:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerColumnTitle:hover {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerColumnTitle:hover .footerColumnIcon {
|
||||||
|
transform: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,12 +15,26 @@ import {
|
|||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { Typography } from 'antd';
|
import { Typography } from 'antd';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import React from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import styles from './Footer.module.css';
|
import styles from './Footer.module.css';
|
||||||
|
|
||||||
const { Paragraph } = Typography;
|
const { Paragraph } = Typography;
|
||||||
|
|
||||||
const Footer: React.FC = () => {
|
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 = {
|
const containerVariants = {
|
||||||
hidden: { opacity: 0 },
|
hidden: { opacity: 0 },
|
||||||
visible: {
|
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 (
|
return (
|
||||||
<footer className={styles.footer}>
|
<footer className={styles.footer}>
|
||||||
<div className={styles.footerBackground}>
|
<div className={styles.footerBackground}>
|
||||||
@@ -55,137 +133,49 @@ const Footer: React.FC = () => {
|
|||||||
viewport={{ once: true }}
|
viewport={{ once: true }}
|
||||||
className={styles.footerContent}
|
className={styles.footerContent}
|
||||||
>
|
>
|
||||||
<motion.div variants={itemVariants} className={styles.footerColumn}>
|
{footerSections.map((section) => (
|
||||||
<div className={styles.footerColumnTitle}>
|
<motion.div
|
||||||
<TeamOutlined className={styles.footerColumnIcon} />
|
key={section.key}
|
||||||
Company
|
variants={itemVariants}
|
||||||
</div>
|
className={`${styles.footerColumn} ${isMobile ? styles.mobileFooterColumn : ''}`}
|
||||||
<ul className={styles.footerLinks}>
|
>
|
||||||
<li className={styles.footerLink}>
|
<div
|
||||||
<a href="/about">
|
className={`${styles.footerColumnTitle} ${isMobile && expandedSections[section.key] ? styles.expanded : ''}`}
|
||||||
<ArrowRightOutlined className={styles.footerLinkIcon} />
|
onClick={() => toggleSection(section.key)}
|
||||||
About Us
|
role={isMobile ? 'button' : undefined}
|
||||||
</a>
|
tabIndex={isMobile ? 0 : undefined}
|
||||||
</li>
|
onKeyDown={(e) => {
|
||||||
<li className={styles.footerLink}>
|
if (isMobile && (e.key === 'Enter' || e.key === ' ')) {
|
||||||
<a href="/services">
|
e.preventDefault();
|
||||||
<ArrowRightOutlined className={styles.footerLinkIcon} />
|
toggleSection(section.key);
|
||||||
Our Services
|
}
|
||||||
</a>
|
}}
|
||||||
</li>
|
>
|
||||||
<li className={styles.footerLink}>
|
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
||||||
<a href="/projects">
|
{section.icon}
|
||||||
<ArrowRightOutlined className={styles.footerLinkIcon} />
|
{section.title}
|
||||||
Portfolio
|
</div>
|
||||||
</a>
|
</div>
|
||||||
</li>
|
<ul className={`${styles.footerLinks} ${isMobile && expandedSections[section.key] ? styles.expanded : ''}`}>
|
||||||
<li className={styles.footerLink}>
|
{section.links.map((link, index) => (
|
||||||
<a href="/contact">
|
<li key={index} className={styles.footerLink}>
|
||||||
<ArrowRightOutlined className={styles.footerLinkIcon} />
|
<a
|
||||||
Contact Us
|
href={link.href}
|
||||||
</a>
|
onClick={(e) => {
|
||||||
</li>
|
// Prevent navigation if it's a placeholder link
|
||||||
</ul>
|
if (link.href === '#') {
|
||||||
</motion.div>
|
e.preventDefault();
|
||||||
|
}
|
||||||
<motion.div variants={itemVariants} className={styles.footerColumn}>
|
}}
|
||||||
<div className={styles.footerColumnTitle}>
|
>
|
||||||
<BulbOutlined className={styles.footerColumnIcon} />
|
{getLinkIcon(link.href)}
|
||||||
Services
|
{link.text}
|
||||||
</div>
|
</a>
|
||||||
<ul className={styles.footerLinks}>
|
</li>
|
||||||
<li className={styles.footerLink}>
|
))}
|
||||||
<a href="/services#webdev">
|
</ul>
|
||||||
<ArrowRightOutlined className={styles.footerLinkIcon} />
|
</motion.div>
|
||||||
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>
|
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
<motion.div
|
<motion.div
|
||||||
@@ -200,22 +190,46 @@ const Footer: React.FC = () => {
|
|||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
|
||||||
<div className={styles.socialLinks}>
|
<div className={styles.socialLinks}>
|
||||||
<a href="#" className={styles.socialLink}>
|
<a
|
||||||
|
href="#"
|
||||||
|
className={styles.socialLink}
|
||||||
|
onClick={(e) => e.preventDefault()}
|
||||||
|
aria-label="Facebook"
|
||||||
|
>
|
||||||
<FacebookOutlined />
|
<FacebookOutlined />
|
||||||
</a>
|
</a>
|
||||||
<a href="#" className={styles.socialLink}>
|
<a
|
||||||
|
href="#"
|
||||||
|
className={styles.socialLink}
|
||||||
|
onClick={(e) => e.preventDefault()}
|
||||||
|
aria-label="Twitter"
|
||||||
|
>
|
||||||
<TwitterOutlined />
|
<TwitterOutlined />
|
||||||
</a>
|
</a>
|
||||||
<a href="#" className={styles.socialLink}>
|
<a
|
||||||
|
href="#"
|
||||||
|
className={styles.socialLink}
|
||||||
|
onClick={(e) => e.preventDefault()}
|
||||||
|
aria-label="LinkedIn"
|
||||||
|
>
|
||||||
<LinkedinOutlined />
|
<LinkedinOutlined />
|
||||||
</a>
|
</a>
|
||||||
<a href="#" className={styles.socialLink}>
|
<a
|
||||||
|
href="#"
|
||||||
|
className={styles.socialLink}
|
||||||
|
onClick={(e) => e.preventDefault()}
|
||||||
|
aria-label="Instagram"
|
||||||
|
>
|
||||||
<InstagramOutlined />
|
<InstagramOutlined />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.copyright}>
|
<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>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { BellOutlined, SearchOutlined, UserOutlined } from "@ant-design/icons";
|
import { BellOutlined, UserOutlined } from "@ant-design/icons";
|
||||||
import { Avatar, Button, Menu, MenuProps, Typography } from "antd";
|
import { Avatar, Button, Menu, MenuProps, Typography } from "antd";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
@@ -81,22 +81,22 @@ const Header = () => {
|
|||||||
className={styles.actionsSection}
|
className={styles.actionsSection}
|
||||||
>
|
>
|
||||||
<div className={styles.actionButtons}>
|
<div className={styles.actionButtons}>
|
||||||
<Button
|
{/* <Button
|
||||||
type="text"
|
type="text"
|
||||||
icon={<SearchOutlined />}
|
icon={<SearchOutlined />}
|
||||||
className={styles.actionButton}
|
className={styles.actionButton}
|
||||||
/>
|
/> */}
|
||||||
<Button
|
<Button
|
||||||
type="text"
|
type="text"
|
||||||
icon={<BellOutlined />}
|
icon={<BellOutlined />}
|
||||||
className={styles.actionButton}
|
className={styles.actionButton}
|
||||||
/>
|
/>
|
||||||
<Button
|
{/* <Button
|
||||||
type="primary"
|
type="primary"
|
||||||
className={styles.ctaButton}
|
className={styles.ctaButton}
|
||||||
>
|
>
|
||||||
Get Started
|
Get Started
|
||||||
</Button>
|
</Button> */}
|
||||||
<Avatar
|
<Avatar
|
||||||
icon={<UserOutlined />}
|
icon={<UserOutlined />}
|
||||||
className={styles.userAvatar}
|
className={styles.userAvatar}
|
||||||
|
|||||||
@@ -1,23 +1,22 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CloseOutlined,
|
CloseOutlined,
|
||||||
EyeOutlined,
|
EyeOutlined,
|
||||||
GithubOutlined,
|
LeftOutlined,
|
||||||
LeftOutlined,
|
LinkOutlined,
|
||||||
LinkOutlined,
|
RightOutlined
|
||||||
RightOutlined,
|
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import {
|
import {
|
||||||
Badge,
|
Badge,
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
Carousel,
|
Carousel,
|
||||||
Col,
|
Col,
|
||||||
Modal,
|
Modal,
|
||||||
Row,
|
Row,
|
||||||
Tag,
|
Tag,
|
||||||
Typography,
|
Typography,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import { AnimatePresence, motion, useAnimation } from "framer-motion";
|
import { AnimatePresence, motion, useAnimation } from "framer-motion";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
@@ -262,7 +261,7 @@ const ProjectsShowcaseClient: React.FC<ProjectsShowcaseClientProps> = ({
|
|||||||
Live Demo
|
Live Demo
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{selectedProject.githubUrl && (
|
{/* {selectedProject.githubUrl && (
|
||||||
<Button
|
<Button
|
||||||
icon={<GithubOutlined />}
|
icon={<GithubOutlined />}
|
||||||
href={selectedProject.githubUrl}
|
href={selectedProject.githubUrl}
|
||||||
@@ -271,7 +270,7 @@ const ProjectsShowcaseClient: React.FC<ProjectsShowcaseClientProps> = ({
|
|||||||
>
|
>
|
||||||
View Code
|
View Code
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)} */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
import { Button, Form, Input, message, Typography } from "antd";
|
import { Button, Form, Input, message, Typography } from "antd";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import Footer from "../components/Footer/Footer";
|
||||||
import styles from "./page.module.css";
|
import styles from "./page.module.css";
|
||||||
|
|
||||||
const { Title, Paragraph, Text } = Typography;
|
const { Title, Paragraph, Text } = Typography;
|
||||||
@@ -405,6 +406,8 @@ export default function ContactPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<Footer />
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,9 @@
|
|||||||
import {
|
import {
|
||||||
CloseOutlined,
|
CloseOutlined,
|
||||||
EyeOutlined,
|
EyeOutlined,
|
||||||
GithubOutlined,
|
|
||||||
LinkOutlined,
|
LinkOutlined,
|
||||||
RocketOutlined,
|
RocketOutlined,
|
||||||
UserOutlined,
|
UserOutlined
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import {
|
import {
|
||||||
Badge,
|
Badge,
|
||||||
@@ -561,7 +560,7 @@ export default function ProjectsPage() {
|
|||||||
Live Demo
|
Live Demo
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{selectedProject.githubUrl && (
|
{/* {selectedProject.githubUrl && (
|
||||||
<Button
|
<Button
|
||||||
icon={<GithubOutlined />}
|
icon={<GithubOutlined />}
|
||||||
href={selectedProject.githubUrl}
|
href={selectedProject.githubUrl}
|
||||||
@@ -569,7 +568,7 @@ export default function ProjectsPage() {
|
|||||||
>
|
>
|
||||||
View Code
|
View Code
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)} */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -9,11 +9,12 @@ import {
|
|||||||
MobileOutlined,
|
MobileOutlined,
|
||||||
RobotOutlined,
|
RobotOutlined,
|
||||||
RocketOutlined,
|
RocketOutlined,
|
||||||
ShoppingOutlined
|
ShoppingOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import { Button, Typography } from "antd";
|
import { Button, Typography } from "antd";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
|
import Footer from "../components/Footer/Footer";
|
||||||
import styles from "./page.module.css";
|
import styles from "./page.module.css";
|
||||||
|
|
||||||
const { Title, Paragraph } = Typography;
|
const { Title, Paragraph } = Typography;
|
||||||
@@ -281,7 +282,7 @@ export default function ServicesPage() {
|
|||||||
variants={itemVariants}
|
variants={itemVariants}
|
||||||
whileHover={{
|
whileHover={{
|
||||||
scale: 1.02,
|
scale: 1.02,
|
||||||
transition: { duration: 0.2 }
|
transition: { duration: 0.2 },
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className={styles.serviceCard}>
|
<div className={styles.serviceCard}>
|
||||||
@@ -292,7 +293,7 @@ export default function ServicesPage() {
|
|||||||
{service.icon}
|
{service.icon}
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.serviceBadge}>
|
<div className={styles.serviceBadge}>
|
||||||
Service {String(index + 1).padStart(2, '0')}
|
Service {String(index + 1).padStart(2, "0")}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -380,29 +381,7 @@ export default function ServicesPage() {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* CTA Section */}
|
<Footer />
|
||||||
<section className={styles.ctaSection}>
|
|
||||||
<div className={styles.ctaContainer}>
|
|
||||||
<motion.div
|
|
||||||
initial={{ opacity: 0, y: 30 }}
|
|
||||||
whileInView={{ opacity: 1, y: 0 }}
|
|
||||||
transition={{ duration: 0.8 }}
|
|
||||||
viewport={{ once: true }}
|
|
||||||
>
|
|
||||||
<Title level={2} className={styles.ctaTitle}>
|
|
||||||
Ready to Start Your{" "}
|
|
||||||
<span className={styles.gradientText}>Project</span>?
|
|
||||||
</Title>
|
|
||||||
<Paragraph className={styles.ctaSubtitle}>
|
|
||||||
Let's discuss how we can help bring your vision to life. Our team
|
|
||||||
is ready to create something amazing together.
|
|
||||||
</Paragraph>
|
|
||||||
<Button size="large" className={styles.ctaButton}>
|
|
||||||
Get Started Today <ArrowRightOutlined />
|
|
||||||
</Button>
|
|
||||||
</motion.div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user