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