Initial commit: Family business website with summer vibes
This commit is contained in:
commit
d01562cf03
|
|
@ -0,0 +1,36 @@
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
||||||
|
|
||||||
|
# large files
|
||||||
|
/public/images/
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
# Family Business Website
|
||||||
|
|
||||||
|
A beautiful, responsive website for a family business with summer sunset vibes. This project is built with Next.js, React, TypeScript, Tailwind CSS, and Framer Motion.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Modern, responsive design with summer sunset color palette
|
||||||
|
- Smooth animations and transitions with Framer Motion
|
||||||
|
- Fully responsive for all device sizes
|
||||||
|
- Contact form with validation
|
||||||
|
- Optimized images and performance
|
||||||
|
|
||||||
|
## Tech Stack
|
||||||
|
|
||||||
|
- **Next.js**: React framework for production
|
||||||
|
- **React**: JavaScript library for building user interfaces
|
||||||
|
- **TypeScript**: Typed JavaScript
|
||||||
|
- **Tailwind CSS**: Utility-first CSS framework
|
||||||
|
- **Framer Motion**: Animation library for React
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Node.js 14.0 or later
|
||||||
|
- npm or yarn
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
1. Clone the repository
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/yourusername/family-business.git
|
||||||
|
cd family-business
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Install dependencies
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
# or
|
||||||
|
yarn install
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Run the development server
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
# or
|
||||||
|
yarn dev
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
- `src/app`: Next.js App Router pages
|
||||||
|
- `src/components`: Reusable React components
|
||||||
|
- `public`: Static assets
|
||||||
|
- `tailwind.config.js`: Tailwind CSS configuration
|
||||||
|
|
||||||
|
## Color Palette
|
||||||
|
|
||||||
|
The website uses a summer sunset-inspired color palette:
|
||||||
|
|
||||||
|
- Sunset Orange: `#FF7B54`
|
||||||
|
- Sunset Pink: `#FFB26B`
|
||||||
|
- Sunset Yellow: `#FFD56F`
|
||||||
|
- Sunset Purple: `#939B62`
|
||||||
|
- Evening Blue: `#1A5F7A`
|
||||||
|
- Night Blue: `#002B5B`
|
||||||
|
- Warm White: `#FFF8EA`
|
||||||
|
- Sand: `#E1D7C6`
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the MIT License - see the LICENSE file for details.
|
||||||
|
|
||||||
|
## Acknowledgments
|
||||||
|
|
||||||
|
- Design inspiration from [Dribbble](https://dribbble.com/shots/25718593-Coolest-Meme-Coin-Website)
|
||||||
|
- Images from [PlaceKitten](https://placekitten.com/)
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
const nextConfig = {
|
||||||
|
reactStrictMode: true,
|
||||||
|
images: {
|
||||||
|
remotePatterns: [
|
||||||
|
{
|
||||||
|
protocol: 'https',
|
||||||
|
hostname: 'placekitten.com',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = nextConfig;
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
"name": "family-buisness",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"description": "",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-slot": "^1.1.2",
|
||||||
|
"@tailwindcss/postcss": "^4.0.12",
|
||||||
|
"@types/node": "^22.13.10",
|
||||||
|
"@types/react": "^19.0.10",
|
||||||
|
"@types/react-dom": "^19.0.4",
|
||||||
|
"autoprefixer": "^10.4.20",
|
||||||
|
"class-variance-authority": "^0.7.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"framer-motion": "^12.4.10",
|
||||||
|
"lucide-react": "^0.479.0",
|
||||||
|
"next": "^15.2.1",
|
||||||
|
"postcss": "^8.5.3",
|
||||||
|
"react": "^19.0.0",
|
||||||
|
"react-dom": "^19.0.0",
|
||||||
|
"tailwind-merge": "^3.0.2",
|
||||||
|
"tailwindcss": "^4.0.12",
|
||||||
|
"typescript": "^5.8.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
'@tailwindcss/postcss': {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--foreground-rgb: 0, 0, 0;
|
||||||
|
--background-start-rgb: 255, 248, 234; /* warm-white */
|
||||||
|
--background-end-rgb: 225, 215, 198; /* sand */
|
||||||
|
|
||||||
|
/* Custom colors */
|
||||||
|
--sunset-orange: #FF7B54;
|
||||||
|
--sunset-pink: #FFB26B;
|
||||||
|
--sunset-yellow: #FFD56F;
|
||||||
|
--sunset-purple: #939B62;
|
||||||
|
--evening-blue: #1A5F7A;
|
||||||
|
--night-blue: #002B5B;
|
||||||
|
--warm-white: #FFF8EA;
|
||||||
|
--sand: #E1D7C6;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: rgb(var(--foreground-rgb));
|
||||||
|
background: linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
transparent,
|
||||||
|
rgb(var(--background-end-rgb))
|
||||||
|
)
|
||||||
|
rgb(var(--background-start-rgb));
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
p, span, a, button {
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer components {
|
||||||
|
.btn-primary {
|
||||||
|
background-color: var(--sunset-orange);
|
||||||
|
color: var(--warm-white);
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border-radius: 9999px;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover {
|
||||||
|
background-color: var(--sunset-pink);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
background-color: var(--evening-blue);
|
||||||
|
color: var(--warm-white);
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border-radius: 9999px;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary:hover {
|
||||||
|
background-color: var(--night-blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
padding-top: 4rem;
|
||||||
|
padding-bottom: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.section {
|
||||||
|
padding-top: 6rem;
|
||||||
|
padding-bottom: 6rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-custom {
|
||||||
|
max-width: 80rem;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.container-custom {
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
padding-right: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.container-custom {
|
||||||
|
padding-left: 2rem;
|
||||||
|
padding-right: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
import './globals.css';
|
||||||
|
import type { Metadata } from 'next';
|
||||||
|
import { Inter } from 'next/font/google';
|
||||||
|
|
||||||
|
const inter = Inter({
|
||||||
|
subsets: ['latin'],
|
||||||
|
display: 'swap',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Family Business - Summer Vibes',
|
||||||
|
description: 'A family business with summer sunset vibes',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function RootLayout({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<html lang="en">
|
||||||
|
<body className={inter.className}>
|
||||||
|
{children}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
import Image from 'next/image';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { Navbar } from '@/components/navbar';
|
||||||
|
import { Footer } from '@/components/footer';
|
||||||
|
import { HeroSection } from '@/components/hero-section';
|
||||||
|
import { FeaturesSection } from '@/components/features-section';
|
||||||
|
import { AboutSection } from '@/components/about-section';
|
||||||
|
import { ContactSection } from '@/components/contact-section';
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
return (
|
||||||
|
<main className="flex min-h-screen flex-col">
|
||||||
|
<Navbar />
|
||||||
|
<HeroSection />
|
||||||
|
<FeaturesSection />
|
||||||
|
<AboutSection />
|
||||||
|
<ContactSection />
|
||||||
|
<Footer />
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import Image from 'next/image';
|
||||||
|
import { CheckCircle } from 'lucide-react';
|
||||||
|
|
||||||
|
export function AboutSection() {
|
||||||
|
const benefits = [
|
||||||
|
'Family-owned and operated since 2005',
|
||||||
|
'Dedicated to exceptional customer service',
|
||||||
|
'Creating summer vibes all year round',
|
||||||
|
'Supporting our local community',
|
||||||
|
'Environmentally conscious practices',
|
||||||
|
'Satisfaction guaranteed on all services',
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section id="about" className="section bg-warm-white">
|
||||||
|
<div className="container-custom">
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-center">
|
||||||
|
{/* Image Side */}
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: -50 }}
|
||||||
|
whileInView={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ duration: 0.8 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
className="relative"
|
||||||
|
>
|
||||||
|
<div className="relative h-[600px] rounded-2xl overflow-hidden shadow-xl">
|
||||||
|
<Image
|
||||||
|
src="/images/about.jpg"
|
||||||
|
alt="Our Family Business"
|
||||||
|
fill
|
||||||
|
className="object-cover"
|
||||||
|
/>
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-t from-night-blue/50 to-transparent"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Floating Card */}
|
||||||
|
<div className="absolute -bottom-8 -right-8 bg-warm-white p-6 rounded-xl shadow-lg max-w-xs">
|
||||||
|
<div className="flex items-center space-x-4 mb-4">
|
||||||
|
<div className="w-12 h-12 bg-sunset-orange rounded-full flex items-center justify-center">
|
||||||
|
<span className="text-warm-white text-xl" style={{ fontWeight: 700 }}>18</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4 className="text-night-blue" style={{ fontWeight: 700 }}>Years of Experience</h4>
|
||||||
|
<p className="text-sm text-evening-blue/80">Serving our community</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="h-1 w-full bg-sand mb-4"></div>
|
||||||
|
<p className="text-evening-blue italic">
|
||||||
|
"We started this business with a simple mission: bring the joy of summer to families all year round."
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Decorative Elements */}
|
||||||
|
<div className="absolute -top-8 -left-8 w-24 h-24 bg-sunset-yellow/20 rounded-full blur-xl"></div>
|
||||||
|
<div className="absolute top-1/2 -left-4 w-8 h-8 bg-sunset-orange rounded-full"></div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Content Side */}
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: 50 }}
|
||||||
|
whileInView={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ duration: 0.8 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
className="space-y-6"
|
||||||
|
>
|
||||||
|
<span className="inline-block px-4 py-2 bg-sunset-orange/10 text-sunset-orange rounded-full" style={{ fontWeight: 500 }}>
|
||||||
|
About Us
|
||||||
|
</span>
|
||||||
|
<h2 className="text-3xl md:text-4xl text-night-blue" style={{ fontWeight: 700 }}>
|
||||||
|
A Family Business With <span className="text-sunset-orange">Summer at Heart</span>
|
||||||
|
</h2>
|
||||||
|
<p className="text-evening-blue/80">
|
||||||
|
Founded in 2005, our family business has been bringing the warm, relaxed feeling of summer to our community for over 18 years. What started as a small operation has grown into a beloved local institution, but our core values remain the same.
|
||||||
|
</p>
|
||||||
|
<p className="text-evening-blue/80">
|
||||||
|
We believe in creating experiences that make people feel like they're enjoying a perfect summer evening - relaxed, happy, and surrounded by those they love. Our team, many of whom are family members, are dedicated to providing exceptional service with that special summer touch.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="pt-4 grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
{benefits.map((benefit, index) => (
|
||||||
|
<motion.div
|
||||||
|
key={index}
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ duration: 0.5, delay: index * 0.1 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
className="flex items-start space-x-3"
|
||||||
|
>
|
||||||
|
<CheckCircle className="h-6 w-6 text-sunset-orange flex-shrink-0 mt-0.5" />
|
||||||
|
<span className="text-evening-blue">{benefit}</span>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="pt-6">
|
||||||
|
<div className="flex items-center space-x-4">
|
||||||
|
<div className="relative w-16 h-16 rounded-full overflow-hidden">
|
||||||
|
<Image
|
||||||
|
src="/images/founder.jpg"
|
||||||
|
alt="Founder"
|
||||||
|
fill
|
||||||
|
className="object-cover"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4 className="text-night-blue" style={{ fontWeight: 700 }}>Jane & John Smith</h4>
|
||||||
|
<p className="text-evening-blue/80">Founders</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,441 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { Mail, Phone, MapPin, Send } from 'lucide-react';
|
||||||
|
|
||||||
|
export function ContactSection() {
|
||||||
|
const [formState, setFormState] = useState({
|
||||||
|
name: '',
|
||||||
|
email: '',
|
||||||
|
phone: '',
|
||||||
|
message: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
|
const [isSubmitted, setIsSubmitted] = useState(false);
|
||||||
|
|
||||||
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
||||||
|
const { name, value } = e.target;
|
||||||
|
setFormState((prev) => ({ ...prev, [name]: value }));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setIsSubmitting(true);
|
||||||
|
|
||||||
|
// Simulate form submission
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsSubmitting(false);
|
||||||
|
setIsSubmitted(true);
|
||||||
|
setFormState({
|
||||||
|
name: '',
|
||||||
|
email: '',
|
||||||
|
phone: '',
|
||||||
|
message: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Reset success message after 5 seconds
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsSubmitted(false);
|
||||||
|
}, 5000);
|
||||||
|
}, 1500);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section id="contact" className="section" style={{
|
||||||
|
background: 'linear-gradient(to bottom, rgba(225, 215, 198, 0.3), var(--warm-white))'
|
||||||
|
}}>
|
||||||
|
<div className="container-custom">
|
||||||
|
<div style={{ textAlign: 'center', maxWidth: '48rem', margin: '0 auto', marginBottom: '4rem' }}>
|
||||||
|
<motion.span
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
whileInView={{ opacity: 1 }}
|
||||||
|
transition={{ duration: 0.5 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
style={{
|
||||||
|
display: 'inline-block',
|
||||||
|
padding: '0.5rem 1rem',
|
||||||
|
backgroundColor: 'rgba(255, 123, 84, 0.1)',
|
||||||
|
color: 'var(--sunset-orange)',
|
||||||
|
borderRadius: '9999px',
|
||||||
|
fontWeight: 500,
|
||||||
|
marginBottom: '1rem'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Get In Touch
|
||||||
|
</motion.span>
|
||||||
|
<motion.h2
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ duration: 0.5, delay: 0.1 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
style={{
|
||||||
|
fontSize: 'clamp(1.875rem, 3vw, 2.25rem)',
|
||||||
|
fontWeight: 700,
|
||||||
|
color: 'var(--night-blue)',
|
||||||
|
marginBottom: '1rem'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Contact Us Today
|
||||||
|
</motion.h2>
|
||||||
|
<motion.p
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ duration: 0.5, delay: 0.2 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
style={{ color: 'rgba(26, 95, 122, 0.8)' }}
|
||||||
|
>
|
||||||
|
Have questions or ready to experience our summer vibes? Reach out to us and we'll get back to you as soon as possible.
|
||||||
|
</motion.p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{
|
||||||
|
display: 'grid',
|
||||||
|
gridTemplateColumns: '1fr',
|
||||||
|
gap: '3rem'
|
||||||
|
}} className="lg:grid-cols-2">
|
||||||
|
{/* Contact Info */}
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: -50 }}
|
||||||
|
whileInView={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ duration: 0.8 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}
|
||||||
|
>
|
||||||
|
<div style={{
|
||||||
|
backgroundColor: 'var(--warm-white)',
|
||||||
|
padding: '2rem',
|
||||||
|
borderRadius: '0.75rem',
|
||||||
|
boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1)',
|
||||||
|
border: '1px solid var(--sand)'
|
||||||
|
}}>
|
||||||
|
<h3 style={{
|
||||||
|
fontSize: '1.5rem',
|
||||||
|
fontWeight: 700,
|
||||||
|
color: 'var(--night-blue)',
|
||||||
|
marginBottom: '1.5rem'
|
||||||
|
}}>Contact Information</h3>
|
||||||
|
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'flex-start', gap: '1rem' }}>
|
||||||
|
<div style={{
|
||||||
|
width: '2.5rem',
|
||||||
|
height: '2.5rem',
|
||||||
|
backgroundColor: 'rgba(255, 123, 84, 0.1)',
|
||||||
|
borderRadius: '9999px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
flexShrink: 0
|
||||||
|
}}>
|
||||||
|
<Phone style={{ height: '1.25rem', width: '1.25rem', color: 'var(--sunset-orange)' }} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4 style={{ fontWeight: 500, color: 'var(--night-blue)' }}>Phone</h4>
|
||||||
|
<p style={{ color: 'var(--evening-blue)' }}>(555) 123-4567</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ display: 'flex', alignItems: 'flex-start', gap: '1rem' }}>
|
||||||
|
<div style={{
|
||||||
|
width: '2.5rem',
|
||||||
|
height: '2.5rem',
|
||||||
|
backgroundColor: 'rgba(255, 123, 84, 0.1)',
|
||||||
|
borderRadius: '9999px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
flexShrink: 0
|
||||||
|
}}>
|
||||||
|
<Mail style={{ height: '1.25rem', width: '1.25rem', color: 'var(--sunset-orange)' }} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4 style={{ fontWeight: 500, color: 'var(--night-blue)' }}>Email</h4>
|
||||||
|
<p style={{ color: 'var(--evening-blue)' }}>hello@familybusiness.com</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ display: 'flex', alignItems: 'flex-start', gap: '1rem' }}>
|
||||||
|
<div style={{
|
||||||
|
width: '2.5rem',
|
||||||
|
height: '2.5rem',
|
||||||
|
backgroundColor: 'rgba(255, 123, 84, 0.1)',
|
||||||
|
borderRadius: '9999px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
flexShrink: 0
|
||||||
|
}}>
|
||||||
|
<MapPin style={{ height: '1.25rem', width: '1.25rem', color: 'var(--sunset-orange)' }} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4 style={{ fontWeight: 500, color: 'var(--night-blue)' }}>Address</h4>
|
||||||
|
<p style={{ color: 'var(--evening-blue)' }}>123 Summer Lane, Beachside, CA 90210</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{
|
||||||
|
marginTop: '2rem',
|
||||||
|
paddingTop: '2rem',
|
||||||
|
borderTop: '1px solid var(--sand)'
|
||||||
|
}}>
|
||||||
|
<h4 style={{ fontWeight: 500, color: 'var(--night-blue)', marginBottom: '1rem' }}>Business Hours</h4>
|
||||||
|
<div style={{
|
||||||
|
display: 'grid',
|
||||||
|
gridTemplateColumns: '1fr',
|
||||||
|
gap: '0.5rem'
|
||||||
|
}} className="sm:grid-cols-2">
|
||||||
|
<div>
|
||||||
|
<p style={{ fontWeight: 500, color: 'var(--evening-blue)' }}>Monday - Friday</p>
|
||||||
|
<p style={{ color: 'rgba(26, 95, 122, 0.8)' }}>9:00 AM - 6:00 PM</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p style={{ fontWeight: 500, color: 'var(--evening-blue)' }}>Saturday</p>
|
||||||
|
<p style={{ color: 'rgba(26, 95, 122, 0.8)' }}>10:00 AM - 4:00 PM</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p style={{ fontWeight: 500, color: 'var(--evening-blue)' }}>Sunday</p>
|
||||||
|
<p style={{ color: 'rgba(26, 95, 122, 0.8)' }}>Closed</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Contact Form */}
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: 50 }}
|
||||||
|
whileInView={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ duration: 0.8 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
>
|
||||||
|
<div style={{
|
||||||
|
backgroundColor: 'var(--warm-white)',
|
||||||
|
padding: '2rem',
|
||||||
|
borderRadius: '0.75rem',
|
||||||
|
boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1)',
|
||||||
|
border: '1px solid var(--sand)'
|
||||||
|
}}>
|
||||||
|
<h3 style={{
|
||||||
|
fontSize: '1.5rem',
|
||||||
|
fontWeight: 700,
|
||||||
|
color: 'var(--night-blue)',
|
||||||
|
marginBottom: '1.5rem'
|
||||||
|
}}>Send Us a Message</h3>
|
||||||
|
|
||||||
|
{isSubmitted ? (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'rgba(255, 123, 84, 0.1)',
|
||||||
|
padding: '1.5rem',
|
||||||
|
borderRadius: '0.5rem',
|
||||||
|
textAlign: 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{
|
||||||
|
width: '4rem',
|
||||||
|
height: '4rem',
|
||||||
|
backgroundColor: 'var(--sunset-orange)',
|
||||||
|
borderRadius: '9999px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
margin: '0 auto',
|
||||||
|
marginBottom: '1rem'
|
||||||
|
}}>
|
||||||
|
<Send style={{ height: '2rem', width: '2rem', color: 'var(--warm-white)' }} />
|
||||||
|
</div>
|
||||||
|
<h4 style={{
|
||||||
|
fontSize: '1.25rem',
|
||||||
|
fontWeight: 700,
|
||||||
|
color: 'var(--night-blue)',
|
||||||
|
marginBottom: '0.5rem'
|
||||||
|
}}>Message Sent!</h4>
|
||||||
|
<p style={{ color: 'var(--evening-blue)' }}>
|
||||||
|
Thank you for reaching out. We'll get back to you as soon as possible.
|
||||||
|
</p>
|
||||||
|
</motion.div>
|
||||||
|
) : (
|
||||||
|
<form onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}>
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="name"
|
||||||
|
style={{
|
||||||
|
display: 'block',
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
fontWeight: 500,
|
||||||
|
color: 'var(--night-blue)',
|
||||||
|
marginBottom: '0.25rem'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Your Name
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="name"
|
||||||
|
name="name"
|
||||||
|
value={formState.name}
|
||||||
|
onChange={handleChange}
|
||||||
|
required
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
padding: '0.75rem 1rem',
|
||||||
|
borderRadius: '0.5rem',
|
||||||
|
border: '1px solid var(--sand)',
|
||||||
|
outline: 'none',
|
||||||
|
backgroundColor: 'var(--warm-white)'
|
||||||
|
}}
|
||||||
|
placeholder="John Smith"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{
|
||||||
|
display: 'grid',
|
||||||
|
gridTemplateColumns: '1fr',
|
||||||
|
gap: '1.5rem'
|
||||||
|
}} className="md:grid-cols-2">
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="email"
|
||||||
|
style={{
|
||||||
|
display: 'block',
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
fontWeight: 500,
|
||||||
|
color: 'var(--night-blue)',
|
||||||
|
marginBottom: '0.25rem'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Email Address
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
id="email"
|
||||||
|
name="email"
|
||||||
|
value={formState.email}
|
||||||
|
onChange={handleChange}
|
||||||
|
required
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
padding: '0.75rem 1rem',
|
||||||
|
borderRadius: '0.5rem',
|
||||||
|
border: '1px solid var(--sand)',
|
||||||
|
outline: 'none',
|
||||||
|
backgroundColor: 'var(--warm-white)'
|
||||||
|
}}
|
||||||
|
placeholder="john@example.com"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="phone"
|
||||||
|
style={{
|
||||||
|
display: 'block',
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
fontWeight: 500,
|
||||||
|
color: 'var(--night-blue)',
|
||||||
|
marginBottom: '0.25rem'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Phone Number
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="tel"
|
||||||
|
id="phone"
|
||||||
|
name="phone"
|
||||||
|
value={formState.phone}
|
||||||
|
onChange={handleChange}
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
padding: '0.75rem 1rem',
|
||||||
|
borderRadius: '0.5rem',
|
||||||
|
border: '1px solid var(--sand)',
|
||||||
|
outline: 'none',
|
||||||
|
backgroundColor: 'var(--warm-white)'
|
||||||
|
}}
|
||||||
|
placeholder="(555) 123-4567"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="message"
|
||||||
|
style={{
|
||||||
|
display: 'block',
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
fontWeight: 500,
|
||||||
|
color: 'var(--night-blue)',
|
||||||
|
marginBottom: '0.25rem'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Your Message
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
id="message"
|
||||||
|
name="message"
|
||||||
|
value={formState.message}
|
||||||
|
onChange={handleChange}
|
||||||
|
required
|
||||||
|
rows={5}
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
padding: '0.75rem 1rem',
|
||||||
|
borderRadius: '0.5rem',
|
||||||
|
border: '1px solid var(--sand)',
|
||||||
|
outline: 'none',
|
||||||
|
resize: 'vertical',
|
||||||
|
backgroundColor: 'var(--warm-white)'
|
||||||
|
}}
|
||||||
|
placeholder="How can we help you?"
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={isSubmitting}
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
backgroundColor: 'var(--sunset-orange)',
|
||||||
|
color: 'var(--warm-white)',
|
||||||
|
padding: '0.75rem 1.5rem',
|
||||||
|
borderRadius: '9999px',
|
||||||
|
fontWeight: 500,
|
||||||
|
border: 'none',
|
||||||
|
cursor: 'pointer',
|
||||||
|
transition: 'background-color 0.3s ease'
|
||||||
|
}}
|
||||||
|
onMouseOver={(e) => e.currentTarget.style.backgroundColor = 'var(--sunset-pink)'}
|
||||||
|
onMouseOut={(e) => e.currentTarget.style.backgroundColor = 'var(--sunset-orange)'}
|
||||||
|
>
|
||||||
|
{isSubmitting ? (
|
||||||
|
<>
|
||||||
|
<svg className="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||||
|
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
||||||
|
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||||
|
</svg>
|
||||||
|
Sending...
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
Send Message
|
||||||
|
<Send style={{ marginLeft: '0.5rem', height: '1.25rem', width: '1.25rem' }} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { Sun, Umbrella, Users, Award, Clock, Heart } from 'lucide-react';
|
||||||
|
|
||||||
|
interface FeatureCardProps {
|
||||||
|
icon: React.ReactNode;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
index: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const features = [
|
||||||
|
{
|
||||||
|
icon: <Sun className="h-8 w-8 text-sunset-orange" />,
|
||||||
|
title: 'Summer Vibes All Year',
|
||||||
|
description: 'We bring the warm, relaxed feeling of summer to everything we do, no matter the season.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <Umbrella className="h-8 w-8 text-sunset-orange" />,
|
||||||
|
title: 'Relaxed Atmosphere',
|
||||||
|
description: 'Enjoy our laid-back, stress-free environment that makes you feel like you\'re on vacation.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <Users className="h-8 w-8 text-sunset-orange" />,
|
||||||
|
title: 'Family-Focused',
|
||||||
|
description: 'As a family business, we understand the importance of creating experiences for the whole family.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <Award className="h-8 w-8 text-sunset-orange" />,
|
||||||
|
title: 'Quality Guaranteed',
|
||||||
|
description: 'We stand behind our work with a 100% satisfaction guarantee on all our services.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <Clock className="h-8 w-8 text-sunset-orange" />,
|
||||||
|
title: 'Prompt Service',
|
||||||
|
description: 'We respect your time and always strive to provide timely, efficient service.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <Heart className="h-8 w-8 text-sunset-orange" />,
|
||||||
|
title: 'Community Love',
|
||||||
|
description: 'We\'re proud to be part of this community and give back through various local initiatives.',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
function FeatureCard({ icon, title, description, index }: FeatureCardProps) {
|
||||||
|
return (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ duration: 0.5, delay: index * 0.1 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
className="bg-warm-white p-6 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300 border border-sand"
|
||||||
|
>
|
||||||
|
<div className="w-14 h-14 bg-sunset-orange/10 rounded-full flex items-center justify-center mb-4">
|
||||||
|
{icon}
|
||||||
|
</div>
|
||||||
|
<h3 className="text-xl text-night-blue mb-2" style={{ fontWeight: 700 }}>{title}</h3>
|
||||||
|
<p className="text-evening-blue/80">{description}</p>
|
||||||
|
</motion.div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function FeaturesSection() {
|
||||||
|
return (
|
||||||
|
<section id="services" className="section bg-sand/30">
|
||||||
|
<div className="container-custom">
|
||||||
|
<div className="text-center max-w-3xl mx-auto mb-16">
|
||||||
|
<motion.span
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
whileInView={{ opacity: 1 }}
|
||||||
|
transition={{ duration: 0.5 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
className="inline-block px-4 py-2 bg-sunset-orange/10 text-sunset-orange rounded-full mb-4"
|
||||||
|
style={{ fontWeight: 500 }}
|
||||||
|
>
|
||||||
|
Our Services
|
||||||
|
</motion.span>
|
||||||
|
<motion.h2
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ duration: 0.5, delay: 0.1 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
className="text-3xl md:text-4xl text-night-blue mb-4"
|
||||||
|
style={{ fontWeight: 700 }}
|
||||||
|
>
|
||||||
|
What Makes Us Special
|
||||||
|
</motion.h2>
|
||||||
|
<motion.p
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ duration: 0.5, delay: 0.2 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
className="text-evening-blue/80"
|
||||||
|
>
|
||||||
|
We combine the warmth of summer with exceptional service to create memorable experiences for your family.
|
||||||
|
</motion.p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||||
|
{features.map((feature, index) => (
|
||||||
|
<FeatureCard
|
||||||
|
key={index}
|
||||||
|
icon={feature.icon}
|
||||||
|
title={feature.title}
|
||||||
|
description={feature.description}
|
||||||
|
index={index}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { Facebook, Instagram, Twitter, Mail, Phone, MapPin } from 'lucide-react';
|
||||||
|
|
||||||
|
export function Footer() {
|
||||||
|
const currentYear = new Date().getFullYear();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<footer className="bg-night-blue text-warm-white">
|
||||||
|
<div className="container-custom py-16">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-12">
|
||||||
|
{/* Company Info */}
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<div className="relative w-10 h-10">
|
||||||
|
<div className="absolute inset-0 bg-sunset-orange rounded-full"></div>
|
||||||
|
<div className="absolute inset-1 bg-warm-white rounded-full flex items-center justify-center">
|
||||||
|
<span className="text-sunset-orange text-lg" style={{ fontWeight: 700 }}>FB</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span className="text-xl text-warm-white" style={{ fontWeight: 700 }}>Family Business</span>
|
||||||
|
</div>
|
||||||
|
<p className="text-sand/80 max-w-xs">
|
||||||
|
A family-owned business bringing summer vibes and quality service since 2005.
|
||||||
|
</p>
|
||||||
|
<div className="flex space-x-4">
|
||||||
|
<Link href="#" className="text-sand hover:text-sunset-orange transition-colors duration-300">
|
||||||
|
<Facebook size={20} />
|
||||||
|
</Link>
|
||||||
|
<Link href="#" className="text-sand hover:text-sunset-orange transition-colors duration-300">
|
||||||
|
<Instagram size={20} />
|
||||||
|
</Link>
|
||||||
|
<Link href="#" className="text-sand hover:text-sunset-orange transition-colors duration-300">
|
||||||
|
<Twitter size={20} />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Quick Links */}
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h3 className="text-xl" style={{ fontWeight: 700 }}>Quick Links</h3>
|
||||||
|
<ul className="space-y-2">
|
||||||
|
<li>
|
||||||
|
<Link href="/" className="text-sand hover:text-sunset-orange transition-colors duration-300">
|
||||||
|
Home
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Link href="#about" className="text-sand hover:text-sunset-orange transition-colors duration-300">
|
||||||
|
About Us
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Link href="#services" className="text-sand hover:text-sunset-orange transition-colors duration-300">
|
||||||
|
Our Services
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Link href="#gallery" className="text-sand hover:text-sunset-orange transition-colors duration-300">
|
||||||
|
Gallery
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Link href="#contact" className="text-sand hover:text-sunset-orange transition-colors duration-300">
|
||||||
|
Contact
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Contact Info */}
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h3 className="text-xl" style={{ fontWeight: 700 }}>Contact Us</h3>
|
||||||
|
<ul className="space-y-3">
|
||||||
|
<li className="flex items-start space-x-3">
|
||||||
|
<MapPin size={20} className="text-sunset-orange flex-shrink-0 mt-1" />
|
||||||
|
<span className="text-sand">123 Summer Lane, Beachside, CA 90210</span>
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center space-x-3">
|
||||||
|
<Phone size={20} className="text-sunset-orange flex-shrink-0" />
|
||||||
|
<span className="text-sand">(555) 123-4567</span>
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center space-x-3">
|
||||||
|
<Mail size={20} className="text-sunset-orange flex-shrink-0" />
|
||||||
|
<span className="text-sand">hello@familybusiness.com</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Copyright */}
|
||||||
|
<div className="border-t border-evening-blue/30 mt-12 pt-8 text-center text-sand/60">
|
||||||
|
<p>© {currentYear} Family Business. All rights reserved.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,195 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import Image from 'next/image';
|
||||||
|
|
||||||
|
export function HeroSection() {
|
||||||
|
return (
|
||||||
|
<section style={{
|
||||||
|
position: 'relative',
|
||||||
|
overflow: 'hidden',
|
||||||
|
background: 'linear-gradient(to bottom, var(--warm-white), var(--sand))',
|
||||||
|
minHeight: '90vh',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center'
|
||||||
|
}}>
|
||||||
|
{/* Background Elements */}
|
||||||
|
<div style={{ position: 'absolute', inset: 0, overflow: 'hidden' }}>
|
||||||
|
{/* Sun */}
|
||||||
|
<div style={{
|
||||||
|
position: 'absolute',
|
||||||
|
right: '-5rem',
|
||||||
|
top: '-5rem',
|
||||||
|
width: '16rem',
|
||||||
|
height: '16rem',
|
||||||
|
borderRadius: '9999px',
|
||||||
|
backgroundColor: 'var(--sunset-yellow)',
|
||||||
|
opacity: 0.2,
|
||||||
|
filter: 'blur(3rem)'
|
||||||
|
}}></div>
|
||||||
|
|
||||||
|
{/* Abstract shapes */}
|
||||||
|
<motion.div
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
width: '100%',
|
||||||
|
height: '8rem',
|
||||||
|
backgroundColor: 'var(--sunset-orange)',
|
||||||
|
opacity: 0.1
|
||||||
|
}}
|
||||||
|
initial={{ y: 100 }}
|
||||||
|
animate={{ y: 0 }}
|
||||||
|
transition={{ duration: 1.5, ease: "easeOut" }}
|
||||||
|
></motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: '25%',
|
||||||
|
right: '25%',
|
||||||
|
width: '16rem',
|
||||||
|
height: '16rem',
|
||||||
|
borderRadius: '9999px',
|
||||||
|
backgroundColor: 'var(--sunset-pink)',
|
||||||
|
opacity: 0.1
|
||||||
|
}}
|
||||||
|
initial={{ scale: 0 }}
|
||||||
|
animate={{ scale: 1 }}
|
||||||
|
transition={{ duration: 1.5, ease: "easeOut" }}
|
||||||
|
></motion.div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="container-custom" style={{ position: 'relative', zIndex: 10 }}>
|
||||||
|
<div style={{
|
||||||
|
display: 'grid',
|
||||||
|
gridTemplateColumns: '1fr',
|
||||||
|
gap: '3rem',
|
||||||
|
alignItems: 'center'
|
||||||
|
}} className="lg:grid-cols-2">
|
||||||
|
{/* Text Content */}
|
||||||
|
<motion.div
|
||||||
|
style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}
|
||||||
|
initial={{ opacity: 0, x: -50 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ duration: 0.8, delay: 0.2 }}
|
||||||
|
>
|
||||||
|
<span style={{
|
||||||
|
display: 'inline-block',
|
||||||
|
padding: '0.5rem 1rem',
|
||||||
|
backgroundColor: 'rgba(255, 123, 84, 0.1)',
|
||||||
|
color: 'var(--sunset-orange)',
|
||||||
|
borderRadius: '9999px',
|
||||||
|
fontWeight: 500
|
||||||
|
}}>
|
||||||
|
Family Owned Since 2005
|
||||||
|
</span>
|
||||||
|
<h1 style={{
|
||||||
|
fontSize: 'clamp(2.25rem, 5vw, 3.75rem)',
|
||||||
|
fontWeight: 700,
|
||||||
|
color: 'var(--night-blue)',
|
||||||
|
lineHeight: 1.2
|
||||||
|
}}>
|
||||||
|
Bringing <span style={{ color: 'var(--sunset-orange)' }}>Summer Vibes</span> To Your Family
|
||||||
|
</h1>
|
||||||
|
<p style={{
|
||||||
|
fontSize: '1.125rem',
|
||||||
|
color: 'rgba(26, 95, 122, 0.8)',
|
||||||
|
maxWidth: '36rem'
|
||||||
|
}}>
|
||||||
|
We're a family business dedicated to providing exceptional service with the warm, relaxed feeling of a perfect summer evening.
|
||||||
|
</p>
|
||||||
|
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '1rem', paddingTop: '1rem' }}>
|
||||||
|
<Link href="#services" className="btn-primary">
|
||||||
|
Our Services
|
||||||
|
</Link>
|
||||||
|
<Link href="#contact" className="btn-secondary">
|
||||||
|
Contact Us
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Trust Indicators */}
|
||||||
|
<div style={{ paddingTop: '2rem', display: 'flex', alignItems: 'center', gap: '1.5rem' }}>
|
||||||
|
<div style={{ display: 'flex' }}>
|
||||||
|
{[1, 2, 3, 4].map((i) => (
|
||||||
|
<div key={i} style={{
|
||||||
|
width: '2.5rem',
|
||||||
|
height: '2.5rem',
|
||||||
|
borderRadius: '9999px',
|
||||||
|
backgroundColor: 'var(--sunset-orange)',
|
||||||
|
border: '2px solid var(--warm-white)',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
color: 'var(--warm-white)',
|
||||||
|
fontWeight: 700,
|
||||||
|
marginLeft: i > 1 ? '-0.5rem' : 0
|
||||||
|
}}>
|
||||||
|
{i}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p style={{ fontWeight: 500, color: 'var(--evening-blue)' }}>Trusted by 2,000+ families</p>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', color: 'var(--sunset-yellow)' }}>
|
||||||
|
{[1, 2, 3, 4, 5].map((i) => (
|
||||||
|
<svg key={i} xmlns="http://www.w3.org/2000/svg" style={{ height: '1.25rem', width: '1.25rem' }} viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
|
||||||
|
</svg>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Image */}
|
||||||
|
<motion.div
|
||||||
|
style={{
|
||||||
|
position: 'relative',
|
||||||
|
height: '500px',
|
||||||
|
borderRadius: '1rem',
|
||||||
|
overflow: 'hidden',
|
||||||
|
boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25)'
|
||||||
|
}}
|
||||||
|
initial={{ opacity: 0, y: 50 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ duration: 0.8, delay: 0.5 }}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
src="/images/hero.jpg"
|
||||||
|
alt="Family Business"
|
||||||
|
fill
|
||||||
|
style={{ objectFit: 'cover' }}
|
||||||
|
priority
|
||||||
|
/>
|
||||||
|
<div style={{
|
||||||
|
position: 'absolute',
|
||||||
|
inset: 0,
|
||||||
|
background: 'linear-gradient(to top, rgba(0, 43, 91, 0.4), transparent)'
|
||||||
|
}}></div>
|
||||||
|
<div style={{
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: '1.5rem',
|
||||||
|
left: '1.5rem',
|
||||||
|
right: '1.5rem',
|
||||||
|
padding: '1.5rem',
|
||||||
|
backgroundColor: 'rgba(255, 248, 234, 0.9)',
|
||||||
|
backdropFilter: 'blur(4px)',
|
||||||
|
borderRadius: '0.75rem'
|
||||||
|
}}>
|
||||||
|
<h3 style={{
|
||||||
|
fontWeight: 700,
|
||||||
|
color: 'var(--night-blue)',
|
||||||
|
fontSize: '1.25rem',
|
||||||
|
marginBottom: '0.5rem'
|
||||||
|
}}>Summer Special Offer</h3>
|
||||||
|
<p style={{ color: 'var(--evening-blue)' }}>Get 20% off on all our premium services until August 31st!</p>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,160 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useState } from 'react';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import Image from 'next/image';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { Menu, X } from 'lucide-react';
|
||||||
|
|
||||||
|
interface NavItem {
|
||||||
|
label: string;
|
||||||
|
href: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const navItems: NavItem[] = [
|
||||||
|
{ label: 'Home', href: '/' },
|
||||||
|
{ label: 'About', href: '#about' },
|
||||||
|
{ label: 'Services', href: '#services' },
|
||||||
|
{ label: 'Gallery', href: '#gallery' },
|
||||||
|
{ label: 'Contact', href: '#contact' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export function Navbar() {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const toggleMenu = () => {
|
||||||
|
setIsOpen(!isOpen);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav style={{
|
||||||
|
position: 'sticky',
|
||||||
|
top: 0,
|
||||||
|
zIndex: 50,
|
||||||
|
backgroundColor: 'rgba(255, 248, 234, 0.9)',
|
||||||
|
backdropFilter: 'blur(4px)',
|
||||||
|
borderBottom: '1px solid var(--sand)'
|
||||||
|
}}>
|
||||||
|
<div className="container-custom" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '1rem 0' }}>
|
||||||
|
{/* Logo */}
|
||||||
|
<Link href="/" style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
||||||
|
<div style={{ position: 'relative', width: '2.5rem', height: '2.5rem' }}>
|
||||||
|
<div style={{
|
||||||
|
position: 'absolute',
|
||||||
|
inset: 0,
|
||||||
|
backgroundColor: 'var(--sunset-orange)',
|
||||||
|
borderRadius: '9999px'
|
||||||
|
}}></div>
|
||||||
|
<div style={{
|
||||||
|
position: 'absolute',
|
||||||
|
inset: '0.25rem',
|
||||||
|
backgroundColor: 'var(--warm-white)',
|
||||||
|
borderRadius: '9999px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center'
|
||||||
|
}}>
|
||||||
|
<span style={{
|
||||||
|
color: 'var(--sunset-orange)',
|
||||||
|
fontSize: '1.125rem',
|
||||||
|
fontWeight: 700
|
||||||
|
}}>FB</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span style={{
|
||||||
|
fontSize: '1.25rem',
|
||||||
|
fontWeight: 700,
|
||||||
|
color: 'var(--night-blue)'
|
||||||
|
}}>Family Business</span>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
{/* Desktop Navigation */}
|
||||||
|
<div style={{
|
||||||
|
display: 'none',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: '2rem'
|
||||||
|
}} className="hidden md:flex">
|
||||||
|
{navItems.map((item) => (
|
||||||
|
<Link
|
||||||
|
key={item.label}
|
||||||
|
href={item.href}
|
||||||
|
style={{
|
||||||
|
color: 'var(--evening-blue)',
|
||||||
|
fontWeight: 500,
|
||||||
|
transition: 'color 0.3s ease'
|
||||||
|
}}
|
||||||
|
onMouseOver={(e) => e.currentTarget.style.color = 'var(--sunset-orange)'}
|
||||||
|
onMouseOut={(e) => e.currentTarget.style.color = 'var(--evening-blue)'}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
<Link href="#contact" className="btn-primary">
|
||||||
|
Get in Touch
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Mobile Menu Button */}
|
||||||
|
<button
|
||||||
|
style={{
|
||||||
|
display: 'block',
|
||||||
|
color: 'var(--evening-blue)'
|
||||||
|
}}
|
||||||
|
className="md:hidden"
|
||||||
|
onClick={toggleMenu}
|
||||||
|
aria-label="Toggle menu"
|
||||||
|
>
|
||||||
|
{isOpen ? <X size={24} /> : <Menu size={24} />}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Mobile Navigation */}
|
||||||
|
{isOpen && (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: -20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
exit={{ opacity: 0, y: -20 }}
|
||||||
|
transition={{ duration: 0.3 }}
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'var(--warm-white)',
|
||||||
|
borderTop: '1px solid var(--sand)'
|
||||||
|
}}
|
||||||
|
className="md:hidden"
|
||||||
|
>
|
||||||
|
<div className="container-custom" style={{
|
||||||
|
padding: '1rem 0',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
gap: '1rem'
|
||||||
|
}}>
|
||||||
|
{navItems.map((item) => (
|
||||||
|
<Link
|
||||||
|
key={item.label}
|
||||||
|
href={item.href}
|
||||||
|
style={{
|
||||||
|
color: 'var(--evening-blue)',
|
||||||
|
fontWeight: 500,
|
||||||
|
padding: '0.5rem 0',
|
||||||
|
transition: 'color 0.3s ease'
|
||||||
|
}}
|
||||||
|
onClick={() => setIsOpen(false)}
|
||||||
|
onMouseOver={(e) => e.currentTarget.style.color = 'var(--sunset-orange)'}
|
||||||
|
onMouseOut={(e) => e.currentTarget.style.color = 'var(--evening-blue)'}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
<Link
|
||||||
|
href="#contact"
|
||||||
|
className="btn-primary"
|
||||||
|
style={{ display: 'inline-block', textAlign: 'center' }}
|
||||||
|
onClick={() => setIsOpen(false)}
|
||||||
|
>
|
||||||
|
Get in Touch
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: [
|
||||||
|
"./src/**/*.{js,ts,jsx,tsx}",
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
// Summer sunset palette
|
||||||
|
'sunset-orange': '#FF7B54', // Warm orange
|
||||||
|
'sunset-pink': '#FFB26B', // Soft pink/peach
|
||||||
|
'sunset-yellow': '#FFD56F', // Golden yellow
|
||||||
|
'sunset-purple': '#939B62', // Dusky purple/green
|
||||||
|
'evening-blue': '#1A5F7A', // Deep evening blue
|
||||||
|
'night-blue': '#002B5B', // Night sky blue
|
||||||
|
'warm-white': '#FFF8EA', // Warm white
|
||||||
|
'sand': '#E1D7C6', // Sandy beige
|
||||||
|
},
|
||||||
|
fontFamily: {
|
||||||
|
sans: ['var(--font-inter)', 'sans-serif'],
|
||||||
|
display: ['var(--font-montserrat)', 'sans-serif'],
|
||||||
|
},
|
||||||
|
backgroundImage: {
|
||||||
|
'gradient-sunset': 'linear-gradient(to right, var(--tw-colors-sunset-orange), var(--tw-colors-sunset-pink))',
|
||||||
|
'gradient-evening': 'linear-gradient(to right, var(--tw-colors-evening-blue), var(--tw-colors-night-blue))',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue