Initial commit
This commit is contained in:
105
src/app/blog/page.tsx
Normal file
105
src/app/blog/page.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
"use client";
|
||||
|
||||
import ReactLenis from "lenis/react";
|
||||
import BlogCardTwo from '@/components/sections/blog/BlogCardTwo';
|
||||
import FooterBaseCard from '@/components/sections/footer/FooterBaseCard';
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleFullscreen from '@/components/navbar/NavbarStyleFullscreen/NavbarStyleFullscreen';
|
||||
import { useBlogPosts } from "@/hooks/useBlogPosts";
|
||||
|
||||
export default function BlogPage() {
|
||||
const { posts, isLoading } = useBlogPosts();
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="icon-arrow"
|
||||
defaultTextAnimation="background-highlight"
|
||||
borderRadius="rounded"
|
||||
contentWidth="medium"
|
||||
sizing="medium"
|
||||
background="none"
|
||||
cardStyle="gradient-bordered"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="layered"
|
||||
headingFontWeight="semibold"
|
||||
>
|
||||
<ReactLenis root>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleFullscreen
|
||||
navItems={[
|
||||
{ name: "Home", id: "/" },
|
||||
{ name: "Features", id: "features" },
|
||||
{ name: "Pricing", id: "pricing" },
|
||||
{ name: "Testimonials", id: "testimonials" },
|
||||
{ name: "Blog", id: "blog" },
|
||||
{ name: "Contact", id: "contact" }
|
||||
]}
|
||||
brandName="Linear"
|
||||
bottomLeftText="Global Sales Platform"
|
||||
bottomRightText="sales@linear.io"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{isLoading ? (
|
||||
<div className="w-content-width mx-auto py-20 text-center">
|
||||
<p className="text-foreground">Loading posts...</p>
|
||||
</div>
|
||||
) : (
|
||||
<div id="blog" data-section="blog">
|
||||
<BlogCardTwo
|
||||
blogs={posts}
|
||||
title="Latest Insights & Updates"
|
||||
description="Discover expert insights, industry trends, and product updates from our team of specialists"
|
||||
tag="Blog"
|
||||
textboxLayout="default"
|
||||
useInvertedBackground="noInvert"
|
||||
carouselMode="buttons"
|
||||
animationType="slide-up"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseCard
|
||||
logoText="Linear"
|
||||
copyrightText="© 2025 Linear Sales. All rights reserved."
|
||||
columns={[
|
||||
{
|
||||
title: "Product", items: [
|
||||
{ label: "Features", href: "#features-1" },
|
||||
{ label: "Pricing", href: "#pricing" },
|
||||
{ label: "Security", href: "#" },
|
||||
{ label: "Roadmap", href: "#" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Company", items: [
|
||||
{ label: "About", href: "#about" },
|
||||
{ label: "Blog", href: "#" },
|
||||
{ label: "Careers", href: "#" },
|
||||
{ label: "Press", href: "#" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Resources", items: [
|
||||
{ label: "Documentation", href: "#" },
|
||||
{ label: "API Reference", href: "#" },
|
||||
{ label: "Support", href: "#" },
|
||||
{ label: "Community", href: "#" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Legal", items: [
|
||||
{ label: "Privacy Policy", href: "#" },
|
||||
{ label: "Terms of Service", href: "#" },
|
||||
{ label: "Cookie Policy", href: "#" },
|
||||
{ label: "Contact", href: "#contact" }
|
||||
]
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</ReactLenis>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
BIN
src/app/favicon.ico
Normal file
BIN
src/app/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
5
src/app/globals.css
Normal file
5
src/app/globals.css
Normal file
@@ -0,0 +1,5 @@
|
||||
@import "tailwindcss";
|
||||
@import "./styles/variables.css";
|
||||
@import "./styles/theme.css";
|
||||
@import "./styles/utilities.css";
|
||||
@import "./styles/base.css";
|
||||
1262
src/app/layout.tsx
Normal file
1262
src/app/layout.tsx
Normal file
File diff suppressed because it is too large
Load Diff
358
src/app/page.tsx
Normal file
358
src/app/page.tsx
Normal file
@@ -0,0 +1,358 @@
|
||||
"use client"
|
||||
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleFullscreen from '@/components/navbar/NavbarStyleFullscreen/NavbarStyleFullscreen';
|
||||
import HeroBillboardDashboard from '@/components/sections/hero/HeroBillboardDashboard';
|
||||
import FeatureBento from '@/components/sections/feature/FeatureBento';
|
||||
import FeatureHoverPattern from '@/components/sections/feature/featureHoverPattern/FeatureHoverPattern';
|
||||
import MetricSplitMediaAbout from '@/components/sections/about/MetricSplitMediaAbout';
|
||||
import TestimonialCardSix from '@/components/sections/testimonial/TestimonialCardSix';
|
||||
import PricingCardThree from '@/components/sections/pricing/PricingCardThree';
|
||||
import FaqDouble from '@/components/sections/faq/FaqDouble';
|
||||
import ContactCTA from '@/components/sections/contact/ContactCTA';
|
||||
import FooterBaseCard from '@/components/sections/footer/FooterBaseCard';
|
||||
import { LayoutDashboard, TrendingUp, Users, Settings, BarChart3, CheckCircle, Clock, AlertCircle, Zap, Lightbulb, Brain, MessageSquare, Share2, Mail, Phone, FileText, Sparkles, Lock, GitBranch, Globe, Award, Star, DollarSign, HelpCircle, Rocket } from 'lucide-react';
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="icon-arrow"
|
||||
defaultTextAnimation="background-highlight"
|
||||
borderRadius="rounded"
|
||||
contentWidth="medium"
|
||||
sizing="medium"
|
||||
background="none"
|
||||
cardStyle="gradient-bordered"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="layered"
|
||||
headingFontWeight="semibold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleFullscreen
|
||||
navItems={[
|
||||
{ name: "Features", id: "features" },
|
||||
{ name: "Pricing", id: "pricing" },
|
||||
{ name: "Testimonials", id: "testimonials" },
|
||||
{ name: "Blog", id: "blog" },
|
||||
{ name: "Contact", id: "contact" }
|
||||
]}
|
||||
brandName="Linear"
|
||||
bottomLeftText="Global Sales Platform"
|
||||
bottomRightText="sales@linear.io"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="hero" data-section="hero">
|
||||
<HeroBillboardDashboard
|
||||
title="Real-Time Sales Dashboard for Growing Teams"
|
||||
description="Transform your sales pipeline with Linear's advanced analytics, real-time metrics, and intelligent forecasting. Monitor revenue, conversion rates, and team performance from a single unified dashboard."
|
||||
tag="Sales Intelligence"
|
||||
tagIcon={TrendingUp}
|
||||
buttons={[
|
||||
{ text: "Start Free Trial", href: "https://linear.io/signup" },
|
||||
{ text: "View Demo", href: "#" }
|
||||
]}
|
||||
background={{ variant: "radial-gradient" }}
|
||||
dashboard={{
|
||||
title: "Sales Metrics Hub", logoIcon: BarChart3,
|
||||
imageSrc: "https://img.b2bpic.net/free-vector/user-panel-template-infographic-dashboard_23-2148378206.jpg", imageAlt: "Linear Sales Dashboard", searchPlaceholder: "Search deals, contacts, pipeline...", buttons: [
|
||||
{ text: "Export Report", href: "#" },
|
||||
{ text: "Share Dashboard", href: "#" }
|
||||
],
|
||||
sidebarItems: [
|
||||
{ icon: LayoutDashboard, active: true },
|
||||
{ icon: TrendingUp },
|
||||
{ icon: Users },
|
||||
{ icon: Settings }
|
||||
],
|
||||
stats: [
|
||||
{
|
||||
title: "Total Pipeline", values: [850000, 1250000, 1680000],
|
||||
valuePrefix: "$", description: "Potential revenue opportunities"
|
||||
},
|
||||
{
|
||||
title: "Conversion Rate", values: [18.5, 22.3, 26.8],
|
||||
valueSuffix: "%", description: "Deal closure percentage"
|
||||
},
|
||||
{
|
||||
title: "Active Deals", values: [42, 58, 71],
|
||||
description: "Ongoing sales opportunities"
|
||||
}
|
||||
],
|
||||
chartTitle: "Monthly Revenue Trend", chartData: [
|
||||
{ value: 45 },
|
||||
{ value: 62 },
|
||||
{ value: 58 },
|
||||
{ value: 73 },
|
||||
{ value: 89 }
|
||||
],
|
||||
listTitle: "Recent Deals", listItems: [
|
||||
{ icon: CheckCircle, title: "Enterprise License - $125K", status: "Closed Won" },
|
||||
{ icon: Clock, title: "SMB Package - $45K", status: "Negotiation" },
|
||||
{ icon: AlertCircle, title: "Startup Plan - $12K", status: "Proposal" }
|
||||
]
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="features-1" data-section="features-1">
|
||||
<FeatureBento
|
||||
features={[
|
||||
{
|
||||
title: "Real-Time Analytics", description: "Track pipeline health, conversion rates, and revenue forecasts in real-time", bentoComponent: "animated-bar-chart"
|
||||
},
|
||||
{
|
||||
title: "AI-Powered Insights", description: "Get intelligent recommendations to accelerate deal closure and identify risks", bentoComponent: "icon-info-cards", items: [
|
||||
{ icon: Lightbulb, label: "Smart Scoring", value: "ML-Driven" },
|
||||
{ icon: Brain, label: "Predictive", value: "AI-Enhanced" },
|
||||
{ icon: Zap, label: "Automated", value: "Real-Time" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Team Collaboration", description: "Keep your entire sales team aligned with shared dashboards and communications", bentoComponent: "orbiting-icons", centerIcon: Users,
|
||||
items: [
|
||||
{ icon: MessageSquare, ring: 1 },
|
||||
{ icon: Share2, ring: 1 },
|
||||
{ icon: CheckCircle, ring: 2 },
|
||||
{ icon: AlertCircle, ring: 2 }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Pipeline Stages", description: "Visualize your entire sales pipeline with customizable stages and forecasting", bentoComponent: "3d-task-list", title: "Sales Process", items: [
|
||||
{ icon: Mail, label: "Lead Outreach", time: "Day 1" },
|
||||
{ icon: Phone, label: "Discovery Call", time: "Day 3-5" },
|
||||
{ icon: FileText, label: "Proposal", time: "Day 7-10" }
|
||||
]
|
||||
}
|
||||
]}
|
||||
title="Powerful Sales Tools Built for Performance"
|
||||
description="Everything you need to accelerate your sales cycle and close more deals faster"
|
||||
tag="Core Features"
|
||||
tagIcon={Zap}
|
||||
textboxLayout="default"
|
||||
animationType="slide-up"
|
||||
useInvertedBackground="noInvert"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="features-2" data-section="features-2">
|
||||
<FeatureHoverPattern
|
||||
features={[
|
||||
{
|
||||
icon: BarChart3,
|
||||
title: "Custom Reporting", description: "Create unlimited custom reports and automate insights delivery to stakeholders"
|
||||
},
|
||||
{
|
||||
icon: Lock,
|
||||
title: "Enterprise Security", description: "SOC2 compliant with role-based access control and audit logging"
|
||||
},
|
||||
{
|
||||
icon: GitBranch,
|
||||
title: "API Integration", description: "Connect your entire tech stack with powerful REST and webhook APIs"
|
||||
},
|
||||
{
|
||||
icon: Zap,
|
||||
title: "Automation Rules", description: "Automate repetitive tasks and create workflows that save your team hours"
|
||||
},
|
||||
{
|
||||
icon: Globe,
|
||||
title: "Multi-Currency", description: "Support for 150+ currencies with real-time exchange rate conversion"
|
||||
},
|
||||
{
|
||||
icon: Users,
|
||||
title: "Team Management", description: "Manage permissions, territories, and quotas across unlimited team members"
|
||||
}
|
||||
]}
|
||||
title="Advanced Sales Capabilities"
|
||||
description="Unlock deeper insights and control with enterprise-grade features"
|
||||
tag="Advanced Tools"
|
||||
tagIcon={Sparkles}
|
||||
textboxLayout="default"
|
||||
animationType="blur-reveal"
|
||||
useInvertedBackground="invertDefault"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="about" data-section="about">
|
||||
<MetricSplitMediaAbout
|
||||
tag="Our Impact"
|
||||
tagIcon={Award}
|
||||
title="Trusted by Sales Leaders Worldwide"
|
||||
description="Linear powers sales teams at leading companies who want to close deals faster and grow revenue. Our platform has helped thousands of sales professionals streamline their processes, improve forecasting accuracy, and accelerate their pipeline velocity."
|
||||
metrics={[
|
||||
{ value: "500K+", title: "Active Sales Professionals" },
|
||||
{ value: "$2B+", title: "Pipeline Managed Annually" }
|
||||
]}
|
||||
imageSrc="https://img.b2bpic.net/free-photo/team-diverse-coworkers-modern-office-discuss-their-project-together_93675-133516.jpg"
|
||||
imageAlt="Sales Team Collaboration"
|
||||
useInvertedBackground="noInvert"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="testimonials" data-section="testimonials">
|
||||
<TestimonialCardSix
|
||||
testimonials={[
|
||||
{
|
||||
id: "1", name: "Sarah Chen", handle: "VP Sales, TechCorp", testimonial: "Linear transformed how our sales team operates. We went from manual spreadsheets to automated dashboards that save us 10 hours per week.", imageSrc: "https://img.b2bpic.net/free-photo/close-up-portrait-young-handsome-successful-man_1163-5475.jpg", imageAlt: "Sarah Chen"
|
||||
},
|
||||
{
|
||||
id: "2", name: "Michael Rodriguez", handle: "Sales Manager, GrowthCo", testimonial: "The forecasting accuracy has improved dramatically. We can now predict quarterly results with 95% accuracy instead of guessing.", imageSrc: "https://img.b2bpic.net/free-photo/smiling-homosexual-man-official-suit-looking-camera-close-up-shot-happy-gay-getting-dressed-wedding-ceremony-standing-hotel-room-with-his-partner-background-love-emotion-concept_74855-22675.jpg", imageAlt: "Michael Rodriguez"
|
||||
},
|
||||
{
|
||||
id: "3", name: "Emily Watson", handle: "CEO, StartupXYZ", testimonial: "Linear's AI insights helped us identify deal risks early. We prevented three major deal losses by acting on recommendations.", imageSrc: "https://img.b2bpic.net/free-photo/happy-young-professional-posing-office_1262-21170.jpg", imageAlt: "Emily Watson"
|
||||
},
|
||||
{
|
||||
id: "4", name: "David Kim", handle: "Head of Sales, EnterpriseSoft", testimonial: "The team collaboration features are incredible. Everyone is always aligned on pipeline status and next steps.", imageSrc: "https://img.b2bpic.net/free-photo/positive-confident-businessman-posing-outside_74855-1183.jpg", imageAlt: "David Kim"
|
||||
},
|
||||
{
|
||||
id: "5", name: "Jessica Martinez", handle: "Sales Director, CloudFirst", testimonial: "ROI was immediate. We recovered $500K in at-risk deals in our first month using Linear's insights.", imageSrc: "https://img.b2bpic.net/free-photo/close-up-competitive-employee_1098-2870.jpg", imageAlt: "Jessica Martinez"
|
||||
},
|
||||
{
|
||||
id: "6", name: "James Sullivan", handle: "VP Revenue, FinTech Labs", testimonial: "The best investment we've made in our sales stack. Linear pays for itself within weeks through improved productivity.", imageSrc: "https://img.b2bpic.net/free-photo/serene-businessman-with-glasses_1098-719.jpg", imageAlt: "James Sullivan"
|
||||
}
|
||||
]}
|
||||
title="What Sales Leaders Say About Linear"
|
||||
description="Hear from the teams transforming their sales processes with Linear"
|
||||
tag="Testimonials"
|
||||
tagIcon={Star}
|
||||
textboxLayout="default"
|
||||
animationType="slide-up"
|
||||
useInvertedBackground="invertDefault"
|
||||
speed={40}
|
||||
topMarqueeDirection="left"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="pricing" data-section="pricing">
|
||||
<PricingCardThree
|
||||
plans={[
|
||||
{
|
||||
id: "1", price: "$99/mo", name: "Starter", buttons: [
|
||||
{ text: "Get Started", href: "https://linear.io/signup" },
|
||||
{ text: "Contact Sales", href: "#contact" }
|
||||
],
|
||||
features: [
|
||||
"Up to 5 team members", "Basic analytics dashboard", "Pipeline management", "Email support", "Monthly forecasts"
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "2", badge: "Most Popular", badgeIcon: Sparkles,
|
||||
price: "$299/mo", name: "Professional", buttons: [
|
||||
{ text: "Get Started", href: "https://linear.io/signup" },
|
||||
{ text: "Contact Sales", href: "#contact" }
|
||||
],
|
||||
features: [
|
||||
"Up to 20 team members", "Advanced analytics & AI insights", "Custom reporting", "Priority support", "Weekly forecasts", "API access"
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "3", price: "$899/mo", name: "Enterprise", buttons: [
|
||||
{ text: "Get Started", href: "https://linear.io/signup" },
|
||||
{ text: "Contact Sales", href: "#contact" }
|
||||
],
|
||||
features: [
|
||||
"Unlimited team members", "Enterprise-grade analytics", "White-label capabilities", "24/7 dedicated support", "Real-time forecasts", "Advanced integrations", "SSO & advanced security"
|
||||
]
|
||||
}
|
||||
]}
|
||||
title="Transparent Pricing for Every Team Size"
|
||||
description="Choose the plan that fits your sales organization. Upgrade or downgrade anytime."
|
||||
tag="Pricing"
|
||||
tagIcon={DollarSign}
|
||||
textboxLayout="default"
|
||||
animationType="slide-up"
|
||||
useInvertedBackground="noInvert"
|
||||
carouselMode="buttons"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="faq" data-section="faq">
|
||||
<FaqDouble
|
||||
faqs={[
|
||||
{
|
||||
id: "1", title: "How quickly can we implement Linear?", content: "Most teams are up and running within 1-2 weeks. Our onboarding team provides dedicated support including data migration, integration setup, and team training. Enterprise clients typically complete implementation within 4 weeks."
|
||||
},
|
||||
{
|
||||
id: "2", title: "Does Linear integrate with our existing CRM?", content: "Yes! Linear integrates with Salesforce, HubSpot, Pipedrive, and 50+ other tools. We offer REST APIs and webhooks for custom integrations. Contact our team to discuss your specific tech stack."
|
||||
},
|
||||
{
|
||||
id: "3", title: "What about data security and compliance?", content: "Linear is SOC2 Type II certified and GDPR compliant. We offer enterprise features including SSO, role-based access control, audit logging, and encrypted data transmission. Your data is never shared with third parties."
|
||||
},
|
||||
{
|
||||
id: "4", title: "Can we customize the dashboard for our team?", content: "Absolutely. Every dashboard is fully customizable. Build custom reports, set up automated alerts, create team-specific views, and configure permissions. No coding required."
|
||||
},
|
||||
{
|
||||
id: "5", title: "How is customer support handled?", content: "Starter plans get email support during business hours. Professional plans receive priority support with 4-hour response times. Enterprise customers get dedicated account managers and 24/7 support."
|
||||
},
|
||||
{
|
||||
id: "6", title: "What happens to our data if we cancel?", content: "We provide a 30-day data export window after cancellation in standard formats (CSV, JSON). You maintain full access to your data and can migrate to any other platform at any time."
|
||||
}
|
||||
]}
|
||||
title="Frequently Asked Questions"
|
||||
description="Find answers to common questions about Linear's features, pricing, and implementation"
|
||||
tag="Help Center"
|
||||
tagIcon={HelpCircle}
|
||||
textboxLayout="default"
|
||||
useInvertedBackground="invertDefault"
|
||||
animationType="smooth"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="contact" data-section="contact">
|
||||
<ContactCTA
|
||||
tag="Ready to Scale Your Sales?"
|
||||
tagIcon={Rocket}
|
||||
title="Start Your Free Trial Today"
|
||||
description="Join hundreds of sales teams already using Linear to accelerate their pipeline and close more deals. Get instant access to all features. No credit card required."
|
||||
buttons={[
|
||||
{ text: "Start Free Trial", href: "https://linear.io/signup" },
|
||||
{ text: "Schedule Demo", href: "#" }
|
||||
]}
|
||||
background={{ variant: "radial-gradient" }}
|
||||
useInvertedBackground="noInvert"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseCard
|
||||
logoText="Linear"
|
||||
copyrightText="© 2025 Linear Sales. All rights reserved."
|
||||
columns={[
|
||||
{
|
||||
title: "Product", items: [
|
||||
{ label: "Features", href: "#features-1" },
|
||||
{ label: "Pricing", href: "#pricing" },
|
||||
{ label: "Security", href: "#" },
|
||||
{ label: "Roadmap", href: "#" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Company", items: [
|
||||
{ label: "About", href: "#about" },
|
||||
{ label: "Blog", href: "#" },
|
||||
{ label: "Careers", href: "#" },
|
||||
{ label: "Press", href: "#" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Resources", items: [
|
||||
{ label: "Documentation", href: "#" },
|
||||
{ label: "API Reference", href: "#" },
|
||||
{ label: "Support", href: "#" },
|
||||
{ label: "Community", href: "#" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Legal", items: [
|
||||
{ label: "Privacy Policy", href: "#" },
|
||||
{ label: "Terms of Service", href: "#" },
|
||||
{ label: "Cookie Policy", href: "#" },
|
||||
{ label: "Contact", href: "#contact" }
|
||||
]
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
249
src/app/shop/[id]/page.tsx
Normal file
249
src/app/shop/[id]/page.tsx
Normal file
@@ -0,0 +1,249 @@
|
||||
"use client";
|
||||
|
||||
import { use, useCallback, useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import ReactLenis from "lenis/react";
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleFullscreen from '@/components/navbar/NavbarStyleFullscreen/NavbarStyleFullscreen';
|
||||
import FooterBaseCard from '@/components/sections/footer/FooterBaseCard';
|
||||
import ProductDetailCard from "@/components/ecommerce/productDetail/ProductDetailCard";
|
||||
import ProductCart from "@/components/ecommerce/cart/ProductCart";
|
||||
import { useProductDetail } from "@/hooks/useProductDetail";
|
||||
import { useCart } from "@/hooks/useCart";
|
||||
import { useCheckout } from "@/hooks/useCheckout";
|
||||
|
||||
interface ProductPageProps {
|
||||
params: Promise<{ id: string }>;
|
||||
}
|
||||
|
||||
export default function ProductPage({ params }: ProductPageProps) {
|
||||
const { id } = use(params);
|
||||
const router = useRouter();
|
||||
const [cartOpen, setCartOpen] = useState(false);
|
||||
|
||||
const {
|
||||
product,
|
||||
isLoading,
|
||||
images,
|
||||
meta,
|
||||
variants,
|
||||
quantityVariant,
|
||||
selectedQuantity,
|
||||
createCartItem,
|
||||
} = useProductDetail(id);
|
||||
|
||||
const {
|
||||
items: cartItems,
|
||||
isOpen: cartOpenFromHook,
|
||||
setIsOpen: setCartOpenFromHook,
|
||||
addItem,
|
||||
updateQuantity,
|
||||
removeItem,
|
||||
total: cartTotal,
|
||||
getCheckoutItems,
|
||||
} = useCart();
|
||||
|
||||
const { buyNow, checkout, isLoading: isCheckoutLoading } = useCheckout();
|
||||
|
||||
const handleAddToCart = useCallback(() => {
|
||||
const item = createCartItem();
|
||||
if (item) {
|
||||
addItem(item);
|
||||
}
|
||||
}, [createCartItem, addItem]);
|
||||
|
||||
const handleBuyNow = useCallback(() => {
|
||||
if (product) {
|
||||
buyNow(product, selectedQuantity);
|
||||
}
|
||||
}, [product, selectedQuantity, buyNow]);
|
||||
|
||||
const handleCheckout = useCallback(async () => {
|
||||
if (cartItems.length === 0) return;
|
||||
|
||||
const currentUrl = new URL(window.location.href);
|
||||
currentUrl.searchParams.set("success", "true");
|
||||
|
||||
await checkout(getCheckoutItems(), { successUrl: currentUrl.toString() });
|
||||
}, [cartItems, checkout, getCheckoutItems]);
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="icon-arrow"
|
||||
defaultTextAnimation="background-highlight"
|
||||
borderRadius="rounded"
|
||||
contentWidth="medium"
|
||||
sizing="medium"
|
||||
background="none"
|
||||
cardStyle="gradient-bordered"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="layered"
|
||||
headingFontWeight="semibold"
|
||||
>
|
||||
<ReactLenis root>
|
||||
<div id="navbar" data-section="navbar">
|
||||
<NavbarStyleFullscreen
|
||||
navItems={[
|
||||
{"name":"Home","id":"/"},
|
||||
{"name":"Shop","id":"/shop"}
|
||||
]}
|
||||
brandName="Linear"
|
||||
bottomLeftText="Global Sales Platform"
|
||||
bottomRightText="sales@linear.io"
|
||||
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
|
||||
/>
|
||||
</div>
|
||||
<main className="min-h-screen flex items-center justify-center pt-20">
|
||||
<p className="text-foreground">Loading product...</p>
|
||||
</main>
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseCard
|
||||
logoText="Linear"
|
||||
copyrightText="© 2025 Linear Sales. All rights reserved."
|
||||
columns={[
|
||||
{"title":"Product","items":[{"label":"Features","href":"#features-1"},{"label":"Pricing","href":"#pricing"},{"label":"Security","href":"#"},{"label":"Roadmap","href":"#"}]},
|
||||
{"title":"Company","items":[{"label":"About","href":"#about"},{"label":"Blog","href":"#"},{"label":"Careers","href":"#"},{"label":"Press","href":"#"}]},
|
||||
{"title":"Resources","items":[{"label":"Documentation","href":"#"},{"label":"API Reference","href":"#"},{"label":"Support","href":"#"},{"label":"Community","href":"#"}]},
|
||||
{"title":"Legal","items":[{"label":"Privacy Policy","href":"#"},{"label":"Terms of Service","href":"#"},{"label":"Cookie Policy","href":"#"},{"label":"Contact","href":"#contact"}]}
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</ReactLenis>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
if (!product) {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="icon-arrow"
|
||||
defaultTextAnimation="background-highlight"
|
||||
borderRadius="rounded"
|
||||
contentWidth="medium"
|
||||
sizing="medium"
|
||||
background="none"
|
||||
cardStyle="gradient-bordered"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="layered"
|
||||
headingFontWeight="semibold"
|
||||
>
|
||||
<ReactLenis root>
|
||||
<div id="navbar" data-section="navbar">
|
||||
<NavbarStyleFullscreen
|
||||
navItems={[
|
||||
{"name":"Home","id":"/"},
|
||||
{"name":"Shop","id":"/shop"}
|
||||
]}
|
||||
brandName="Linear"
|
||||
bottomLeftText="Global Sales Platform"
|
||||
bottomRightText="sales@linear.io"
|
||||
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
|
||||
/>
|
||||
</div>
|
||||
<main className="min-h-screen flex items-center justify-center pt-20">
|
||||
<div className="text-center">
|
||||
<p className="text-foreground mb-4">Product not found</p>
|
||||
<button
|
||||
onClick={() => router.push("/shop")}
|
||||
className="primary-button px-6 py-2 rounded-theme"
|
||||
>
|
||||
Back to Shop
|
||||
</button>
|
||||
</div>
|
||||
</main>
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseCard
|
||||
logoText="Linear"
|
||||
copyrightText="© 2025 Linear Sales. All rights reserved."
|
||||
columns={[
|
||||
{"title":"Product","items":[{"label":"Features","href":"#features-1"},{"label":"Pricing","href":"#pricing"},{"label":"Security","href":"#"},{"label":"Roadmap","href":"#"}]},
|
||||
{"title":"Company","items":[{"label":"About","href":"#about"},{"label":"Blog","href":"#"},{"label":"Careers","href":"#"},{"label":"Press","href":"#"}]},
|
||||
{"title":"Resources","items":[{"label":"Documentation","href":"#"},{"label":"API Reference","href":"#"},{"label":"Support","href":"#"},{"label":"Community","href":"#"}]},
|
||||
{"title":"Legal","items":[{"label":"Privacy Policy","href":"#"},{"label":"Terms of Service","href":"#"},{"label":"Cookie Policy","href":"#"},{"label":"Contact","href":"#contact"}]}
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</ReactLenis>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="icon-arrow"
|
||||
defaultTextAnimation="background-highlight"
|
||||
borderRadius="rounded"
|
||||
contentWidth="medium"
|
||||
sizing="medium"
|
||||
background="none"
|
||||
cardStyle="gradient-bordered"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="layered"
|
||||
headingFontWeight="semibold"
|
||||
>
|
||||
<ReactLenis root>
|
||||
<div id="navbar" data-section="navbar">
|
||||
<NavbarStyleFullscreen
|
||||
navItems={[
|
||||
{"name":"Home","id":"/"},
|
||||
{"name":"Shop","id":"/shop"}
|
||||
]}
|
||||
brandName="Linear"
|
||||
bottomLeftText="Global Sales Platform"
|
||||
bottomRightText="sales@linear.io"
|
||||
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
|
||||
/>
|
||||
</div>
|
||||
<div id="productDetailCard" data-section="productDetailCard">
|
||||
<ProductDetailCard
|
||||
layout="page"
|
||||
name={product.name}
|
||||
price={product.price}
|
||||
salePrice={meta.salePrice}
|
||||
rating={product.rating || 0}
|
||||
description={product.description}
|
||||
images={images}
|
||||
variants={variants.length > 0 ? variants : undefined}
|
||||
quantity={quantityVariant}
|
||||
ribbon={meta.ribbon}
|
||||
inventoryStatus={meta.inventoryStatus}
|
||||
inventoryQuantity={meta.inventoryQuantity}
|
||||
sku={meta.sku}
|
||||
buttons={[
|
||||
{ text: "Add To Cart", onClick: handleAddToCart },
|
||||
{ text: "Buy Now", onClick: handleBuyNow },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<div id="productCart" data-section="productCart">
|
||||
<ProductCart
|
||||
isOpen={cartOpen}
|
||||
onClose={() => setCartOpen(false)}
|
||||
items={cartItems}
|
||||
onQuantityChange={updateQuantity}
|
||||
onRemove={removeItem}
|
||||
total={`$${cartTotal}`}
|
||||
buttons={[
|
||||
{
|
||||
text: isCheckoutLoading ? "Processing..." : "Check Out", onClick: handleCheckout,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseCard
|
||||
logoText="Linear"
|
||||
copyrightText="© 2025 Linear Sales. All rights reserved."
|
||||
columns={[
|
||||
{"title":"Product","items":[{"label":"Features","href":"#features-1"},{"label":"Pricing","href":"#pricing"},{"label":"Security","href":"#"},{"label":"Roadmap","href":"#"}]},
|
||||
{"title":"Company","items":[{"label":"About","href":"#about"},{"label":"Blog","href":"#"},{"label":"Careers","href":"#"},{"label":"Press","href":"#"}]},
|
||||
{"title":"Resources","items":[{"label":"Documentation","href":"#"},{"label":"API Reference","href":"#"},{"label":"Support","href":"#"},{"label":"Community","href":"#"}]},
|
||||
{"title":"Legal","items":[{"label":"Privacy Policy","href":"#"},{"label":"Terms of Service","href":"#"},{"label":"Cookie Policy","href":"#"},{"label":"Contact","href":"#contact"}]}
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</ReactLenis>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
120
src/app/shop/page.tsx
Normal file
120
src/app/shop/page.tsx
Normal file
@@ -0,0 +1,120 @@
|
||||
"use client";
|
||||
|
||||
import ReactLenis from "lenis/react";
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleFullscreen from '@/components/navbar/NavbarStyleFullscreen/NavbarStyleFullscreen';
|
||||
import FooterBaseCard from '@/components/sections/footer/FooterBaseCard';
|
||||
import ProductCatalog from "@/components/ecommerce/productCatalog/ProductCatalog";
|
||||
import { useProductCatalog } from "@/hooks/useProductCatalog";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function ShopPage() {
|
||||
const [cartOpen, setCartOpen] = useState(false);
|
||||
const {
|
||||
products,
|
||||
isLoading,
|
||||
search,
|
||||
setSearch,
|
||||
filters,
|
||||
} = useProductCatalog({ basePath: "/shop" });
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="icon-arrow"
|
||||
defaultTextAnimation="background-highlight"
|
||||
borderRadius="rounded"
|
||||
contentWidth="medium"
|
||||
sizing="medium"
|
||||
background="none"
|
||||
cardStyle="gradient-bordered"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="layered"
|
||||
headingFontWeight="semibold"
|
||||
>
|
||||
<ReactLenis root>
|
||||
<div id="navbar" data-section="navbar">
|
||||
<NavbarStyleFullscreen
|
||||
navItems={[
|
||||
{"name":"Home","id":"/"},
|
||||
{"name":"Shop","id":"/shop"}
|
||||
]}
|
||||
brandName="Linear"
|
||||
bottomLeftText="Global Sales Platform"
|
||||
bottomRightText="sales@linear.io"
|
||||
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
|
||||
/>
|
||||
</div>
|
||||
<main className="min-h-screen flex items-center justify-center pt-20">
|
||||
<p className="text-foreground">Loading products...</p>
|
||||
</main>
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseCard
|
||||
logoText="Linear"
|
||||
copyrightText="© 2025 Linear Sales. All rights reserved."
|
||||
columns={[
|
||||
{"title":"Product","items":[{"label":"Features","href":"#features-1"},{"label":"Pricing","href":"#pricing"},{"label":"Security","href":"#"},{"label":"Roadmap","href":"#"}]},
|
||||
{"title":"Company","items":[{"label":"About","href":"#about"},{"label":"Blog","href":"#"},{"label":"Careers","href":"#"},{"label":"Press","href":"#"}]},
|
||||
{"title":"Resources","items":[{"label":"Documentation","href":"#"},{"label":"API Reference","href":"#"},{"label":"Support","href":"#"},{"label":"Community","href":"#"}]},
|
||||
{"title":"Legal","items":[{"label":"Privacy Policy","href":"#"},{"label":"Terms of Service","href":"#"},{"label":"Cookie Policy","href":"#"},{"label":"Contact","href":"#contact"}]}
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</ReactLenis>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="icon-arrow"
|
||||
defaultTextAnimation="background-highlight"
|
||||
borderRadius="rounded"
|
||||
contentWidth="medium"
|
||||
sizing="medium"
|
||||
background="none"
|
||||
cardStyle="gradient-bordered"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="layered"
|
||||
headingFontWeight="semibold"
|
||||
>
|
||||
<ReactLenis root>
|
||||
<div id="navbar" data-section="navbar">
|
||||
<NavbarStyleFullscreen
|
||||
navItems={[
|
||||
{"name":"Home","id":"/"},
|
||||
{"name":"Shop","id":"/shop"}
|
||||
]}
|
||||
brandName="Linear"
|
||||
bottomLeftText="Global Sales Platform"
|
||||
bottomRightText="sales@linear.io"
|
||||
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
|
||||
/>
|
||||
</div>
|
||||
<div id="productCatalog" data-section="productCatalog">
|
||||
<ProductCatalog
|
||||
layout="page"
|
||||
products={products}
|
||||
searchValue={search}
|
||||
onSearchChange={setSearch}
|
||||
searchPlaceholder="Search products..."
|
||||
filters={filters}
|
||||
emptyMessage="No products found"
|
||||
/>
|
||||
</div>
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseCard
|
||||
logoText="Linear"
|
||||
copyrightText="© 2025 Linear Sales. All rights reserved."
|
||||
columns={[
|
||||
{"title":"Product","items":[{"label":"Features","href":"#features-1"},{"label":"Pricing","href":"#pricing"},{"label":"Security","href":"#"},{"label":"Roadmap","href":"#"}]},
|
||||
{"title":"Company","items":[{"label":"About","href":"#about"},{"label":"Blog","href":"#"},{"label":"Careers","href":"#"},{"label":"Press","href":"#"}]},
|
||||
{"title":"Resources","items":[{"label":"Documentation","href":"#"},{"label":"API Reference","href":"#"},{"label":"Support","href":"#"},{"label":"Community","href":"#"}]},
|
||||
{"title":"Legal","items":[{"label":"Privacy Policy","href":"#"},{"label":"Terms of Service","href":"#"},{"label":"Cookie Policy","href":"#"},{"label":"Contact","href":"#contact"}]}
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</ReactLenis>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
28
src/app/styles/base.css
Normal file
28
src/app/styles/base.css
Normal file
@@ -0,0 +1,28 @@
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: rgba(255, 255, 255, 1) rgba(255, 255, 255, 0);
|
||||
}
|
||||
|
||||
html {
|
||||
overscroll-behavior: none;
|
||||
overscroll-behavior-y: none;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--background);
|
||||
color: var(--foreground);
|
||||
font-family: var(--font-ibm-plex-sans), sans-serif;
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
overscroll-behavior: none;
|
||||
overscroll-behavior-y: none;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: var(--font-ibm-plex-sans), sans-serif;
|
||||
}
|
||||
174
src/app/styles/theme.css
Normal file
174
src/app/styles/theme.css
Normal file
@@ -0,0 +1,174 @@
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-card: var(--card);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-primary-cta: var(--primary-cta);
|
||||
--color-secondary-cta: var(--secondary-cta);
|
||||
--color-accent: var(--accent);
|
||||
--color-background-accent: var(--background-accent);
|
||||
|
||||
/* theme border radius */
|
||||
--radius-theme: var(--theme-border-radius);
|
||||
--radius-theme-capped: var(--theme-border-radius-capped);
|
||||
|
||||
/* text */
|
||||
--text-2xs: var(--text-2xs);
|
||||
--text-xs: var(--text-xs);
|
||||
--text-sm: var(--text-sm);
|
||||
--text-base: var(--text-base);
|
||||
--text-lg: var(--text-lg);
|
||||
--text-xl: var(--text-xl);
|
||||
--text-2xl: var(--text-2xl);
|
||||
--text-3xl: var(--text-3xl);
|
||||
--text-4xl: var(--text-4xl);
|
||||
--text-5xl: var(--text-5xl);
|
||||
--text-6xl: var(--text-6xl);
|
||||
--text-7xl: var(--text-7xl);
|
||||
--text-8xl: var(--text-8xl);
|
||||
--text-9xl: var(--text-9xl);
|
||||
|
||||
/* height */
|
||||
--height-4: var(--height-4);
|
||||
--height-5: var(--height-5);
|
||||
--height-6: var(--height-6);
|
||||
--height-7: var(--height-7);
|
||||
--height-8: var(--height-8);
|
||||
--height-9: var(--height-9);
|
||||
--height-11: var(--height-11);
|
||||
--height-12: var(--height-12);
|
||||
|
||||
--height-10: var(--height-10);
|
||||
--height-30: var(--height-30);
|
||||
--height-90: var(--height-90);
|
||||
--height-100: var(--height-100);
|
||||
--height-110: var(--height-110);
|
||||
--height-120: var(--height-120);
|
||||
--height-130: var(--height-130);
|
||||
--height-140: var(--height-140);
|
||||
--height-150: var(--height-150);
|
||||
|
||||
--height-page-padding: calc(2.25rem+var(--vw-1_5)+var(--vw-1_5));
|
||||
|
||||
/* width */
|
||||
--width-5: var(--width-5);
|
||||
--width-7_5: var(--width-7_5);
|
||||
--width-10: var(--width-10);
|
||||
--width-12_5: var(--width-12_5);
|
||||
--width-15: var(--width-15);
|
||||
--width-17: var(--width-17);
|
||||
--width-17_5: var(--width-17_5);
|
||||
--width-20: var(--width-20);
|
||||
--width-21: var(--width-21);
|
||||
--width-22_5: var(--width-22_5);
|
||||
--width-25: var(--width-25);
|
||||
--width-26: var(--width-26);
|
||||
--width-27_5: var(--width-27_5);
|
||||
--width-30: var(--width-30);
|
||||
--width-32_5: var(--width-32_5);
|
||||
--width-35: var(--width-35);
|
||||
--width-37_5: var(--width-37_5);
|
||||
--width-40: var(--width-40);
|
||||
--width-42_5: var(--width-42_5);
|
||||
--width-45: var(--width-45);
|
||||
--width-47_5: var(--width-47_5);
|
||||
--width-50: var(--width-50);
|
||||
--width-52_5: var(--width-52_5);
|
||||
--width-55: var(--width-55);
|
||||
--width-57_5: var(--width-57_5);
|
||||
--width-60: var(--width-60);
|
||||
--width-62_5: var(--width-62_5);
|
||||
--width-65: var(--width-65);
|
||||
--width-67_5: var(--width-67_5);
|
||||
--width-70: var(--width-70);
|
||||
--width-72_5: var(--width-72_5);
|
||||
--width-75: var(--width-75);
|
||||
--width-77_5: var(--width-77_5);
|
||||
--width-80: var(--width-80);
|
||||
--width-82_5: var(--width-82_5);
|
||||
--width-85: var(--width-85);
|
||||
--width-87_5: var(--width-87_5);
|
||||
--width-90: var(--width-90);
|
||||
--width-92_5: var(--width-92_5);
|
||||
--width-95: var(--width-95);
|
||||
--width-97_5: var(--width-97_5);
|
||||
--width-100: var(--width-100);
|
||||
--width-content-width: var(--width-content-width);
|
||||
--width-carousel-padding: var(--width-carousel-padding);
|
||||
--width-carousel-padding-controls: var(--width-carousel-padding-controls);
|
||||
--width-carousel-padding-expanded: var(--width-carousel-padding-expanded);
|
||||
--width-carousel-padding-controls-expanded: var(--width-carousel-padding-controls-expanded);
|
||||
--width-carousel-item-3: var(--width-carousel-item-3);
|
||||
--width-carousel-item-4: var(--width-carousel-item-4);
|
||||
--width-x-padding-mask-fade: var(--width-x-padding-mask-fade);
|
||||
--width-content-width-expanded: var(--width-content-width-expanded);
|
||||
|
||||
/* gap */
|
||||
--spacing-1: var(--vw-0_25);
|
||||
--spacing-2: var(--vw-0_5);
|
||||
--spacing-3: var(--vw-0_75);
|
||||
--spacing-4: var(--vw-1);
|
||||
--spacing-5: var(--vw-1_25);
|
||||
--spacing-6: var(--vw-1_5);
|
||||
--spacing-7: var(--vw-1_75);
|
||||
--spacing-8: var(--vw-2);
|
||||
|
||||
--spacing-x-1: var(--vw-0_25);
|
||||
--spacing-x-2: var(--vw-0_5);
|
||||
--spacing-x-3: var(--vw-0_75);
|
||||
--spacing-x-4: var(--vw-1);
|
||||
--spacing-x-5: var(--vw-1_25);
|
||||
--spacing-x-6: var(--vw-1_5);
|
||||
|
||||
/* border radius */
|
||||
--radius-none: 0;
|
||||
--radius-sm: var(--vw-0_5);
|
||||
--radius: var(--vw-0_75);
|
||||
--radius-md: var(--vw-1);
|
||||
--radius-lg: var(--vw-1_25);
|
||||
--radius-xl: var(--vw-1_75);
|
||||
--radius-full: 999px;
|
||||
|
||||
/* padding */
|
||||
--padding-1: var(--vw-0_25);
|
||||
--padding-2: var(--vw-0_5);
|
||||
--padding-2.5: var(--vw-0_625);
|
||||
--padding-3: var(--vw-0_75);
|
||||
--padding-4: var(--vw-1);
|
||||
--padding-5: var(--vw-1_25);
|
||||
--padding-6: var(--vw-1_5);
|
||||
--padding-7: var(--vw-1_75);
|
||||
--padding-8: var(--vw-2);
|
||||
|
||||
--padding-x-1: var(--vw-0_25);
|
||||
--padding-x-2: var(--vw-0_5);
|
||||
--padding-x-3: var(--vw-0_75);
|
||||
--padding-x-4: var(--vw-1);
|
||||
--padding-x-5: var(--vw-1_25);
|
||||
--padding-x-6: var(--vw-1_5);
|
||||
--padding-x-7: var(--vw-1_75);
|
||||
--padding-x-8: var(--vw-2);
|
||||
|
||||
--padding-hero-page-padding-half: var(--padding-hero-page-padding-half);
|
||||
--padding-hero-page-padding: var(--padding-hero-page-padding);
|
||||
--padding-hero-page-padding-1_5: var(--padding-hero-page-padding-1_5);
|
||||
--padding-hero-page-padding-double: var(--padding-hero-page-padding-double);
|
||||
|
||||
/* margin */
|
||||
--margin-1: var(--vw-0_25);
|
||||
--margin-2: var(--vw-0_5);
|
||||
--margin-3: var(--vw-0_75);
|
||||
--margin-4: var(--vw-1);
|
||||
--margin-5: var(--vw-1_25);
|
||||
--margin-6: var(--vw-1_5);
|
||||
--margin-7: var(--vw-1_75);
|
||||
--margin-8: var(--vw-2);
|
||||
|
||||
--margin-x-1: var(--vw-0_25);
|
||||
--margin-x-2: var(--vw-0_5);
|
||||
--margin-x-3: var(--vw-0_75);
|
||||
--margin-x-4: var(--vw-1);
|
||||
--margin-x-5: var(--vw-1_25);
|
||||
--margin-x-6: var(--vw-1_5);
|
||||
--margin-x-7: var(--vw-1_75);
|
||||
--margin-x-8: var(--vw-2);
|
||||
}
|
||||
178
src/app/styles/utilities.css
Normal file
178
src/app/styles/utilities.css
Normal file
@@ -0,0 +1,178 @@
|
||||
@layer components {}
|
||||
|
||||
@layer utilities {
|
||||
|
||||
/* Card, primary-button, and secondary-button styles are now dynamically injected via ThemeProvider */
|
||||
|
||||
/* .card {
|
||||
@apply backdrop-blur-sm bg-gradient-to-br from-card/80 to-card/40 shadow-sm border border-card;
|
||||
}
|
||||
|
||||
.primary-button {
|
||||
@apply bg-gradient-to-b from-primary-cta/83 to-primary-cta;
|
||||
box-shadow:
|
||||
color-mix(in srgb, var(--color-background) 25%, transparent) 0px 1px 1px 0px inset,
|
||||
color-mix(in srgb, var(--color-primary-cta) 15%, transparent) 3px 3px 3px 0px;
|
||||
}
|
||||
|
||||
.secondary-button {
|
||||
@apply backdrop-blur-sm bg-gradient-to-br from-secondary-cta/80 to-secondary-cta shadow-sm border border-secondary-cta;
|
||||
} */
|
||||
|
||||
.tag-card {
|
||||
@apply backdrop-blur-sm bg-gradient-to-br from-card/80 to-card/40 shadow-sm border border-card;
|
||||
}
|
||||
|
||||
.mask-fade-x {
|
||||
-webkit-mask-image: linear-gradient(to right, transparent 0%, transparent calc((100vw - var(--width-content-width)) / 4), black calc((100vw - var(--width-content-width)) / 2 + 5vw), black calc(100% - (100vw - var(--width-content-width)) / 2 - 5vw), transparent calc(100% - (100vw - var(--width-content-width)) / 4), transparent 100%);
|
||||
mask-image: linear-gradient(to right, transparent 0%, transparent calc((100vw - var(--width-content-width)) / 4), black calc((100vw - var(--width-content-width)) / 2 + 5vw), black calc(100% - (100vw - var(--width-content-width)) / 2 - 5vw), transparent calc(100% - (100vw - var(--width-content-width)) / 4), transparent 100%);
|
||||
}
|
||||
|
||||
.mask-padding-x {
|
||||
-webkit-mask-image: linear-gradient(to right, transparent 0%, black var(--width-x-padding-mask-fade), black calc(100% - var(--width-x-padding-mask-fade)), transparent 100%);
|
||||
mask-image: linear-gradient(to right, transparent 0%, black var(--width-x-padding-mask-fade), black calc(100% - var(--width-x-padding-mask-fade)), transparent 100%);
|
||||
}
|
||||
|
||||
.mask-fade-bottom {
|
||||
-webkit-mask-image: linear-gradient(to bottom, black 0%, black 50%, transparent 100%);
|
||||
mask-image: linear-gradient(to bottom, black 0%, black 50%, transparent 100%);
|
||||
}
|
||||
|
||||
.mask-fade-y {
|
||||
mask-image: linear-gradient(to bottom,
|
||||
transparent 0%,
|
||||
black var(--vw-1_5),
|
||||
black calc(100% - var(--vw-1_5)),
|
||||
transparent 100%);
|
||||
}
|
||||
|
||||
.mask-fade-bottom-large {
|
||||
-webkit-mask-image: linear-gradient(to bottom, black 0%, black 50%, transparent 75%, transparent 100%);
|
||||
mask-image: linear-gradient(to bottom, black 0%, black 50%, transparent 75%, transparent 100%);
|
||||
}
|
||||
|
||||
.mask-fade-bottom-long {
|
||||
-webkit-mask-image: linear-gradient(to bottom, black 0%, black 5%, transparent 100%);
|
||||
mask-image: linear-gradient(to bottom, black 0%, black 5%, transparent 100%);
|
||||
}
|
||||
|
||||
.mask-fade-top-long {
|
||||
-webkit-mask-image: linear-gradient(to top, black 0%, black 5%, transparent 100%);
|
||||
mask-image: linear-gradient(to top, black 0%, black 5%, transparent 100%);
|
||||
}
|
||||
|
||||
.mask-fade-xy {
|
||||
-webkit-mask-image:
|
||||
linear-gradient(to right, transparent 0%, black 20%, black 80%, transparent 100%),
|
||||
linear-gradient(to bottom, transparent 0%, black 20%, black 80%, transparent 100%);
|
||||
mask-image:
|
||||
linear-gradient(to right, transparent 0%, black 20%, black 80%, transparent 100%),
|
||||
linear-gradient(to bottom, transparent 0%, black 20%, black 80%, transparent 100%);
|
||||
-webkit-mask-composite: source-in;
|
||||
mask-composite: intersect;
|
||||
}
|
||||
|
||||
/* ANIMATION */
|
||||
|
||||
.animation-container {
|
||||
animation:
|
||||
fadeInOpacity 0.8s ease-in-out forwards,
|
||||
fadeInTranslate 0.6s forwards;
|
||||
}
|
||||
|
||||
.animation-container-fade {
|
||||
animation: fadeInOpacity 0.8s ease-in-out forwards;
|
||||
}
|
||||
|
||||
@keyframes fadeInOpacity {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInTranslate {
|
||||
from {
|
||||
transform: translateY(0.75vh);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translateY(0vh);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes aurora {
|
||||
from {
|
||||
background-position: 50% 50%, 50% 50%;
|
||||
}
|
||||
|
||||
to {
|
||||
background-position: 350% 50%, 350% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin-slow {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin-reverse {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(-360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-spin-slow {
|
||||
animation: spin-slow 15s linear infinite;
|
||||
}
|
||||
|
||||
.animate-spin-reverse {
|
||||
animation: spin-reverse 10s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes marquee-vertical {
|
||||
from {
|
||||
transform: translateY(0);
|
||||
}
|
||||
to {
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-marquee-vertical {
|
||||
animation: marquee-vertical 20s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes orbit {
|
||||
from {
|
||||
transform: rotate(var(--initial-position, 0deg)) translateX(var(--translate-position, 120px)) rotate(calc(-1 * var(--initial-position, 0deg)));
|
||||
}
|
||||
to {
|
||||
transform: rotate(calc(var(--initial-position, 0deg) + 360deg)) translateX(var(--translate-position, 120px)) rotate(calc(-1 * (var(--initial-position, 0deg) + 360deg)));
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes map-dot-pulse {
|
||||
0%, 100% {
|
||||
transform: scale(0.4);
|
||||
opacity: 0.6;
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.4);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
215
src/app/styles/variables.css
Normal file
215
src/app/styles/variables.css
Normal file
@@ -0,0 +1,215 @@
|
||||
:root {
|
||||
/* Base units */
|
||||
/* --vw is set by ThemeProvider */
|
||||
|
||||
/* --background: #0a0a0a;;
|
||||
--card: #1a1a1a;;
|
||||
--foreground: #ffffffe6;;
|
||||
--primary-cta: #0798ff;;
|
||||
--secondary-cta: #1a1a1a;;
|
||||
--accent: #93c7ff;;
|
||||
--background-accent: #004a93;; */
|
||||
|
||||
--background: #0a0a0a;;
|
||||
--card: #1a1a1a;;
|
||||
--foreground: #ffffffe6;;
|
||||
--primary-cta: #0798ff;;
|
||||
--secondary-cta: #1a1a1a;;
|
||||
--accent: #93c7ff;;
|
||||
--background-accent: #004a93;;
|
||||
|
||||
/* text sizing - set by ThemeProvider */
|
||||
/* --text-2xs: clamp(0.465rem, 0.62vw, 0.62rem);
|
||||
--text-xs: clamp(0.54rem, 0.72vw, 0.72rem);
|
||||
--text-sm: clamp(0.615rem, 0.82vw, 0.82rem);
|
||||
--text-base: clamp(0.69rem, 0.92vw, 0.92rem);
|
||||
--text-lg: clamp(0.75rem, 1vw, 1rem);
|
||||
--text-xl: clamp(0.825rem, 1.1vw, 1.1rem);
|
||||
--text-2xl: clamp(0.975rem, 1.3vw, 1.3rem);
|
||||
--text-3xl: clamp(1.2rem, 1.6vw, 1.6rem);
|
||||
--text-4xl: clamp(1.5rem, 2vw, 2rem);
|
||||
--text-5xl: clamp(2.025rem, 2.75vw, 2.75rem);
|
||||
--text-6xl: clamp(2.475rem, 3.3vw, 3.3rem);
|
||||
--text-7xl: clamp(3rem, 4vw, 4rem);
|
||||
--text-8xl: clamp(3.5rem, 4.5vw, 4.5rem);
|
||||
--text-9xl: clamp(5.25rem, 7vw, 7rem); */
|
||||
|
||||
/* Base spacing units */
|
||||
--vw-0_25: calc(var(--vw) * 0.25);
|
||||
--vw-0_5: calc(var(--vw) * 0.5);
|
||||
--vw-0_625: calc(var(--vw) * 0.625);
|
||||
--vw-0_75: calc(var(--vw) * 0.75);
|
||||
--vw-1: calc(var(--vw) * 1);
|
||||
--vw-1_25: calc(var(--vw) * 1.25);
|
||||
--vw-1_5: calc(var(--vw) * 1.5);
|
||||
--vw-1_75: calc(var(--vw) * 1.75);
|
||||
--vw-2: calc(var(--vw) * 2);
|
||||
--vw-2_25: calc(var(--vw) * 2.25);
|
||||
--vw-2_5: calc(var(--vw) * 2.5);
|
||||
--vw-2_75: calc(var(--vw) * 2.75);
|
||||
--vw-3: calc(var(--vw) * 3);
|
||||
|
||||
/* width */
|
||||
--width-5: clamp(4rem, 5vw, 6rem);
|
||||
--width-7_5: clamp(5.625rem, 7.5vw, 7.5rem);
|
||||
--width-10: clamp(7.5rem, 10vw, 10rem);
|
||||
--width-12_5: clamp(9.375rem, 12.5vw, 12.5rem);
|
||||
--width-15: clamp(11.25rem, 15vw, 15rem);
|
||||
--width-17: clamp(12.75rem, 17vw, 17rem);
|
||||
--width-17_5: clamp(13.125rem, 17.5vw, 17.5rem);
|
||||
--width-20: clamp(15rem, 20vw, 20rem);
|
||||
--width-21: clamp(15.75rem, 21vw, 21rem);
|
||||
--width-22_5: clamp(16.875rem, 22.5vw, 22.5rem);
|
||||
--width-25: clamp(18.75rem, 25vw, 25rem);
|
||||
--width-26: clamp(19.5rem, 26vw, 26rem);
|
||||
--width-27_5: clamp(20.625rem, 27.5vw, 27.5rem);
|
||||
--width-30: clamp(22.5rem, 30vw, 30rem);
|
||||
--width-32_5: clamp(24.375rem, 32.5vw, 32.5rem);
|
||||
--width-35: clamp(26.25rem, 35vw, 35rem);
|
||||
--width-37_5: clamp(28.125rem, 37.5vw, 37.5rem);
|
||||
--width-40: clamp(30rem, 40vw, 40rem);
|
||||
--width-42_5: clamp(31.875rem, 42.5vw, 42.5rem);
|
||||
--width-45: clamp(33.75rem, 45vw, 45rem);
|
||||
--width-47_5: clamp(35.625rem, 47.5vw, 47.5rem);
|
||||
--width-50: clamp(37.5rem, 50vw, 50rem);
|
||||
--width-52_5: clamp(39.375rem, 52.5vw, 52.5rem);
|
||||
--width-55: clamp(41.25rem, 55vw, 55rem);
|
||||
--width-57_5: clamp(43.125rem, 57.5vw, 57.5rem);
|
||||
--width-60: clamp(45rem, 60vw, 60rem);
|
||||
--width-62_5: clamp(46.875rem, 62.5vw, 62.5rem);
|
||||
--width-65: clamp(48.75rem, 65vw, 65rem);
|
||||
--width-67_5: clamp(50.625rem, 67.5vw, 67.5rem);
|
||||
--width-70: clamp(52.5rem, 70vw, 70rem);
|
||||
--width-72_5: clamp(54.375rem, 72.5vw, 72.5rem);
|
||||
--width-75: clamp(56.25rem, 75vw, 75rem);
|
||||
--width-77_5: clamp(58.125rem, 77.5vw, 77.5rem);
|
||||
--width-80: clamp(60rem, 80vw, 80rem);
|
||||
--width-82_5: clamp(61.875rem, 82.5vw, 82.5rem);
|
||||
--width-85: clamp(63.75rem, 85vw, 85rem);
|
||||
--width-87_5: clamp(65.625rem, 87.5vw, 87.5rem);
|
||||
--width-90: clamp(67.5rem, 90vw, 90rem);
|
||||
--width-92_5: clamp(69.375rem, 92.5vw, 92.5rem);
|
||||
--width-95: clamp(71.25rem, 95vw, 95rem);
|
||||
--width-97_5: clamp(73.125rem, 97.5vw, 97.5rem);
|
||||
--width-100: clamp(75rem, 100vw, 100rem);
|
||||
/* --width-content-width and --width-content-width-expanded are set by ThemeProvider */
|
||||
--width-carousel-padding: calc((100vw - var(--width-content-width)) / 2 + 1px - var(--vw-1_5));
|
||||
--width-carousel-padding-controls: calc((100vw - var(--width-content-width)) / 2 + 1px);
|
||||
--width-carousel-padding-expanded: calc((var(--width-content-width-expanded) - var(--width-content-width)) / 2 + 1px - var(--vw-1_5));
|
||||
--width-carousel-padding-controls-expanded: calc((var(--width-content-width-expanded) - var(--width-content-width)) / 2 + 1px);
|
||||
--width-carousel-item-3: calc(var(--width-content-width) / 3 - var(--vw-1_5) / 3 * 2);
|
||||
--width-carousel-item-4: calc(var(--width-content-width) / 4 - var(--vw-1_5) / 4 * 3);
|
||||
--width-x-padding-mask-fade: clamp(1.5rem, 4vw, 4rem);
|
||||
|
||||
--height-4: 1rem;
|
||||
--height-5: 1.25rem;
|
||||
--height-6: 1.5rem;
|
||||
--height-7: 1.75rem;
|
||||
--height-8: 2rem;
|
||||
--height-9: 2.25rem;
|
||||
--height-10: 2.5rem;
|
||||
--height-11: 2.75rem;
|
||||
--height-12: 3rem;
|
||||
--height-30: 7.5rem;
|
||||
--height-90: 22.5rem;
|
||||
--height-100: 25rem;
|
||||
--height-110: 27.5rem;
|
||||
--height-120: 30rem;
|
||||
--height-130: 32.5rem;
|
||||
--height-140: 35rem;
|
||||
--height-150: 37.5rem;
|
||||
|
||||
/* hero page padding */
|
||||
--padding-hero-page-padding-half: calc((var(--height-10) + var(--vw-1_5) + var(--vw-1_5) + var(--height-10)) / 2);
|
||||
--padding-hero-page-padding: calc(var(--height-10) + var(--vw-1_5) + var(--vw-1_5) + var(--height-10));
|
||||
--padding-hero-page-padding-1_5: calc(1.5 * (var(--height-10) + var(--vw-1_5) + var(--vw-1_5) + var(--height-10)));
|
||||
--padding-hero-page-padding-double: calc(2 * (var(--height-10) + var(--vw-1_5) + var(--vw-1_5) + var(--height-10)));
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
:root {
|
||||
/* --vw and text sizing are set by ThemeProvider */
|
||||
/* --vw: 3vw;
|
||||
|
||||
--text-2xs: 2.5vw;
|
||||
--text-xs: 2.75vw;
|
||||
--text-sm: 3vw;
|
||||
--text-base: 3.25vw;
|
||||
--text-lg: 3.5vw;
|
||||
--text-xl: 4.25vw;
|
||||
--text-2xl: 5vw;
|
||||
--text-3xl: 6vw;
|
||||
--text-4xl: 7vw;
|
||||
--text-5xl: 7.5vw;
|
||||
--text-6xl: 8.5vw;
|
||||
--text-7xl: 10vw;
|
||||
--text-8xl: 12vw;
|
||||
--text-9xl: 14vw; */
|
||||
|
||||
--width-5: 5vw;
|
||||
--width-7_5: 7.5vw;
|
||||
--width-10: 10vw;
|
||||
--width-12_5: 12.5vw;
|
||||
--width-15: 15vw;
|
||||
--width-17_5: 17.5vw;
|
||||
--width-20: 20vw;
|
||||
--width-22_5: 22.5vw;
|
||||
--width-25: 25vw;
|
||||
--width-27_5: 27.5vw;
|
||||
--width-30: 30vw;
|
||||
--width-32_5: 32.5vw;
|
||||
--width-35: 35vw;
|
||||
--width-37_5: 37.5vw;
|
||||
--width-40: 40vw;
|
||||
--width-42_5: 42.5vw;
|
||||
--width-45: 45vw;
|
||||
--width-47_5: 47.5vw;
|
||||
--width-50: 50vw;
|
||||
--width-52_5: 52.5vw;
|
||||
--width-55: 55vw;
|
||||
--width-57_5: 57.5vw;
|
||||
--width-60: 60vw;
|
||||
--width-62_5: 62.5vw;
|
||||
--width-65: 65vw;
|
||||
--width-67_5: 67.5vw;
|
||||
--width-70: 70vw;
|
||||
--width-72_5: 72.5vw;
|
||||
--width-75: 75vw;
|
||||
--width-77_5: 77.5vw;
|
||||
--width-80: 80vw;
|
||||
--width-82_5: 82.5vw;
|
||||
--width-85: 85vw;
|
||||
--width-87_5: 87.5vw;
|
||||
--width-90: 90vw;
|
||||
--width-92_5: 92.5vw;
|
||||
--width-95: 95vw;
|
||||
--width-97_5: 97.5vw;
|
||||
--width-100: 100vw;
|
||||
/* --width-content-width and --width-content-width-expanded are set by ThemeProvider */
|
||||
--width-carousel-padding: calc((100vw - var(--width-content-width)) / 2 + 1px - var(--vw-1_5));
|
||||
--width-carousel-padding-controls: calc((100vw - var(--width-content-width)) / 2 + 1px);
|
||||
--width-carousel-padding-expanded: calc((var(--width-content-width-expanded) - var(--width-content-width)) / 2 + 1px - var(--vw-1_5));
|
||||
--width-carousel-padding-controls-expanded: calc((var(--width-content-width-expanded) - var(--width-content-width)) / 2 + 1px);
|
||||
--width-carousel-item-3: var(--width-content-width);
|
||||
--width-carousel-item-4: var(--width-content-width);
|
||||
--width-x-padding-mask-fade: 10vw;
|
||||
|
||||
--height-4: 3.5vw;
|
||||
--height-5: 4.5vw;
|
||||
--height-6: 5.5vw;
|
||||
--height-7: 6.5vw;
|
||||
--height-8: 7.5vw;
|
||||
--height-9: 8.5vw;
|
||||
--height-10: 9vw;
|
||||
--height-11: 10vw;
|
||||
--height-12: 11vw;
|
||||
--height-30: 25vw;
|
||||
--height-90: 81vw;
|
||||
--height-100: 90vw;
|
||||
--height-110: 99vw;
|
||||
--height-120: 108vw;
|
||||
--height-130: 117vw;
|
||||
--height-140: 126vw;
|
||||
--height-150: 135vw;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user