init: lab project bootstrapped from isletmem-kovakcrm

- CRM domain modules removed (customers, services, software, calendar, tasks, invoices, leads, finance, etc.)
- DLS branding: package name=lab, logo wordmark, sidebar nav, header CTA
- Tenant layer extended with kind dimension (lab|clinic) + requireTenantKind helper
- Schema rewritten for DLS domain: jobs, job_files, job_status_history, prosthetics, connections, finance_entries, notifications
- Onboarding form: clinic/lab account-type selection + auto-generated memberNumber
- Placeholder routes for jobs/{inbound,outbound,new}, products, finance, connections
- PDF spec + spec.md under belgeler/
- db: lab database + 13 collections + indexes + storage bucket (job-files) provisioned via Appwrite MCP

Ref: belgeler/dls-ui-tasarim.pdf
This commit is contained in:
kovakmedya
2026-05-21 18:28:38 +03:00
commit cb150f7a24
215 changed files with 54262 additions and 0 deletions
@@ -0,0 +1,89 @@
"use client"
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Card, CardContent } from '@/components/ui/card'
import { CardDecorator } from '@/components/ui/card-decorator'
import { Github, Code, Palette, Layout, Crown } from 'lucide-react'
const values = [
{
icon: Code,
title: 'Developer First',
description: 'Every component is built with the developer experience in mind, ensuring clean code and easy integration.'
},
{
icon: Palette,
title: 'Design Excellence',
description: 'We maintain the highest design standards, following shadcn/ui principles and modern UI patterns.'
},
{
icon: Layout,
title: 'Production Ready',
description: 'Battle-tested components used in real applications with proven performance and reliability across different environments.'
},
{
icon: Crown,
title: 'Premium Quality',
description: 'Hand-crafted with attention to detail and performance optimization, ensuring exceptional user experience and accessibility.'
}
]
export function AboutSection() {
return (
<section id="about" className="py-24 sm:py-32">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
{/* Section Header */}
<div className="mx-auto max-w-4xl text-center mb-16">
<Badge variant="outline" className="mb-4">
About ShadcnStore
</Badge>
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl mb-6">
Built for developers, by developers
</h2>
<p className="text-lg text-muted-foreground mb-8">
We&apos;re passionate about creating the best marketplace for shadcn/ui components and templates.
Our mission is to accelerate development and help developers build beautiful admin interfaces faster.
</p>
</div>
{/* Modern Values Grid with Enhanced Design */}
<div className="grid grid-cols-1 gap-x-8 gap-y-12 sm:grid-cols-2 xl:grid-cols-4 mb-12">
{values.map((value, index) => (
<Card key={index} className='group shadow-xs py-2'>
<CardContent className='p-8'>
<div className='flex flex-col items-center text-center'>
<CardDecorator>
<value.icon className='h-6 w-6' aria-hidden />
</CardDecorator>
<h3 className='mt-6 font-medium text-balance'>{value.title}</h3>
<p className='text-muted-foreground mt-3 text-sm'>{value.description}</p>
</div>
</CardContent>
</Card>
))}
</div>
{/* Call to Action */}
<div className="mt-16 text-center">
<div className="flex items-center justify-center gap-2 mb-6">
<span className="text-muted-foreground"> Made with love for the developer community</span>
</div>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Button size="lg" className="cursor-pointer" asChild>
<a href="https://github.com/silicondeck/shadcn-dashboard-landing-template" target="_blank" rel="noopener noreferrer">
<Github className="mr-2 h-4 w-4" />
Star on GitHub
</a>
</Button>
<Button size="lg" variant="outline" className="cursor-pointer" asChild>
<a href="https://discord.com/invite/XEQhPc9a6p" target="_blank" rel="noopener noreferrer">
Join Discord Community
</a>
</Button>
</div>
</div>
</div>
</section>
)
}
@@ -0,0 +1,93 @@
"use client"
import Image from 'next/image'
import { ArrowRight } from 'lucide-react'
import { Card, CardContent } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge'
const blogs = [
{
id: 1,
image: 'https://ui.shadcn.com/placeholder.svg',
category: 'Technology',
title: 'AI Development Catalysts',
description:
'Exploring how AI-driven tools are transforming software development workflows and accelerating innovation.',
},
{
id: 2,
image: 'https://ui.shadcn.com/placeholder.svg',
category: 'Lifestyle',
title: 'Minimalist Living Guide',
description:
'Minimalist living approaches that can help reduce stress and create more meaningful daily experiences.',
},
{
id: 3,
image: 'https://ui.shadcn.com/placeholder.svg',
category: 'Design',
title: 'Accessible UI Trends',
description:
'How modern UI trends are embracing accessibility while maintaining sleek, intuitive user experiences.',
},
]
export function BlogSection() {
return (
<section id="blog" className="py-24 sm:py-32 bg-muted/50">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
{/* Section Header */}
<div className="mx-auto max-w-2xl text-center mb-16">
<Badge variant="outline" className="mb-4">Latest Insights</Badge>
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl mb-4">
From our blog
</h2>
<p className="text-lg text-muted-foreground">
Stay updated with the latest trends, best practices, and insights from our team of experts.
</p>
</div>
{/* Blog Grid */}
<div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
{blogs.map(blog => (
<Card key={blog.id} className="overflow-hidden py-0">
<CardContent className="px-0">
<div className="aspect-video">
<Image
src={blog.image}
alt={blog.title}
width={400}
height={225}
className="size-full object-cover dark:invert dark:brightness-[0.95]"
loading="lazy"
/>
</div>
<div className="space-y-3 p-6">
<p className="text-muted-foreground text-xs tracking-widest uppercase">
{blog.category}
</p>
<a
href="#"
onClick={e => e.preventDefault()}
className="cursor-pointer"
>
<h3 className="text-xl font-bold hover:text-primary transition-colors">{blog.title}</h3>
</a>
<p className="text-muted-foreground">{blog.description}</p>
<a
href="#"
onClick={e => e.preventDefault()}
className="inline-flex items-center gap-2 text-primary hover:underline cursor-pointer"
>
Learn More
<ArrowRight className="size-4" />
</a>
</div>
</CardContent>
</Card>
))}
</div>
</div>
</section>
)
}
@@ -0,0 +1,228 @@
"use client"
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Input } from '@/components/ui/input'
import { Textarea } from '@/components/ui/textarea'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form"
import { Mail, MessageCircle, Github, BookOpen } from 'lucide-react'
const contactFormSchema = z.object({
firstName: z.string().min(2, {
message: "First name must be at least 2 characters.",
}),
lastName: z.string().min(2, {
message: "Last name must be at least 2 characters.",
}),
email: z.string().email({
message: "Please enter a valid email address.",
}),
subject: z.string().min(5, {
message: "Subject must be at least 5 characters.",
}),
message: z.string().min(10, {
message: "Message must be at least 10 characters.",
}),
})
export function ContactSection() {
const form = useForm<z.infer<typeof contactFormSchema>>({
resolver: zodResolver(contactFormSchema),
defaultValues: {
firstName: "",
lastName: "",
email: "",
subject: "",
message: "",
},
})
function onSubmit(values: z.infer<typeof contactFormSchema>) {
// Here you would typically send the form data to your backend
console.log(values)
// You could also show a success message or redirect
form.reset()
}
return (
<section id="contact" className="py-24 sm:py-32">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="mx-auto max-w-2xl text-center mb-16">
<Badge variant="outline" className="mb-4">Get In Touch</Badge>
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl mb-4">
Need help or have questions?
</h2>
<p className="text-lg text-muted-foreground">
Our team is here to help you get the most out of ShadcnStore. Choose the best way to reach out to us.
</p>
</div>
<div className="grid gap-8 lg:grid-cols-3">
{/* Contact Options */}
<div className="space-y-6 order-2 lg:order-1">
<Card className="hover:shadow-md transition-shadow cursor-pointer">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<MessageCircle className="h-5 w-5 text-primary" />
Discord Community
</CardTitle>
</CardHeader>
<CardContent>
<p className="text-muted-foreground mb-3">
Join our active community for quick help and discussions with other developers.
</p>
<Button variant="outline" size="sm" className="cursor-pointer" asChild>
<a href="https://discord.com/invite/XEQhPc9a6p" target="_blank" rel="noopener noreferrer">
Join Discord
</a>
</Button>
</CardContent>
</Card>
<Card className="hover:shadow-md transition-shadow cursor-pointer">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Github className="h-5 w-5 text-primary" />
GitHub Issues
</CardTitle>
</CardHeader>
<CardContent>
<p className="text-muted-foreground mb-3">
Report bugs, request features, or contribute to our open source repository.
</p>
<Button variant="outline" size="sm" className="cursor-pointer" asChild>
<a href="https://github.com/silicondeck/shadcn-dashboard-landing-template/issues" target="_blank" rel="noopener noreferrer">
View on GitHub
</a>
</Button>
</CardContent>
</Card>
<Card className="hover:shadow-md transition-shadow cursor-pointer">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<BookOpen className="h-5 w-5 text-primary" />
Documentation
</CardTitle>
</CardHeader>
<CardContent>
<p className="text-muted-foreground mb-3">
Browse our comprehensive guides, tutorials, and component documentation.
</p>
<Button variant="outline" size="sm" className="cursor-pointer" asChild>
<a href="#">
View Docs
</a>
</Button>
</CardContent>
</Card>
</div>
{/* Contact Form */}
<div className="lg:col-span-2 order-1 lg:order-2">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Mail className="h-5 w-5" />
Send us a message
</CardTitle>
</CardHeader>
<CardContent>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
<div className="grid gap-4 sm:grid-cols-2">
<FormField
control={form.control}
name="firstName"
render={({ field }) => (
<FormItem>
<FormLabel>First name</FormLabel>
<FormControl>
<Input placeholder="John" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="lastName"
render={({ field }) => (
<FormItem>
<FormLabel>Last name</FormLabel>
<FormControl>
<Input placeholder="Doe" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input type="email" placeholder="john@example.com" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="subject"
render={({ field }) => (
<FormItem>
<FormLabel>Subject</FormLabel>
<FormControl>
<Input placeholder="Component request, bug report, general inquiry..." {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="message"
render={({ field }) => (
<FormItem>
<FormLabel>Message</FormLabel>
<FormControl>
<Textarea
placeholder="Tell us how we can help you with ShadcnStore components..."
rows={10}
className="min-h-50"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit" className="w-full cursor-pointer">
Send Message
</Button>
</form>
</Form>
</CardContent>
</Card>
</div>
</div>
</div>
</section>
)
}
@@ -0,0 +1,96 @@
"use client"
import { ArrowRight, TrendingUp, Package, Github } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Separator } from '@/components/ui/separator'
export function CTASection() {
return (
<section className='py-16 lg:py-24 bg-muted/80'>
<div className='container mx-auto px-4 lg:px-8'>
<div className='mx-auto max-w-4xl'>
<div className='text-center'>
<div className='space-y-8'>
{/* Badge and Stats */}
<div className='flex flex-col items-center gap-4'>
<Badge variant='outline' className='flex items-center gap-2'>
<TrendingUp className='size-3' />
Productivity Suite
</Badge>
<div className='text-muted-foreground flex items-center gap-4 text-sm'>
<span className='flex items-center gap-1'>
<div className='size-2 rounded-full bg-green-500' />
150+ Blocks
</span>
<Separator orientation='vertical' className='!h-4' />
<span>25K+ Downloads</span>
<Separator orientation='vertical' className='!h-4' />
<span>4.9 Rating</span>
</div>
</div>
{/* Main Content */}
<div className='space-y-6'>
<h1 className='text-4xl font-bold tracking-tight text-balance sm:text-5xl lg:text-6xl'>
Supercharge your team&apos;s
<span className='flex sm:inline-flex justify-center'>
<span className='relative mx-2'>
<span className='bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent'>
performance
</span>
<div className='absolute start-0 -bottom-2 h-1 w-full bg-gradient-to-r from-primary/30 to-secondary/30' />
</span>
today
</span>
</h1>
<p className='text-muted-foreground mx-auto max-w-2xl text-balance lg:text-xl'>
Stop building from scratch. Get production-ready components, templates and dashboards
that integrate seamlessly with your shadcn/ui projects.
</p>
</div>
{/* CTA Buttons */}
<div className='flex flex-col justify-center gap-4 sm:flex-row sm:gap-6'>
<Button size='lg' className='cursor-pointer px-8 py-6 text-lg font-medium' asChild>
<a href='https://shadcnstore.com/blocks' target='_blank' rel='noopener noreferrer'>
<Package className='me-2 size-5' />
Browse Components
</a>
</Button>
<Button variant='outline' size='lg' className='cursor-pointer px-8 py-6 text-lg font-medium group' asChild>
<a href='https://github.com/silicondeck/shadcn-dashboard-landing-template' target='_blank' rel='noopener noreferrer'>
<Github className='me-2 size-5' />
View on GitHub
<ArrowRight className='ms-2 size-4 transition-transform group-hover:translate-x-1' />
</a>
</Button>
</div>
{/* Trust Indicators */}
<div className='text-muted-foreground flex flex-wrap items-center justify-center gap-6 text-sm'>
<div className='flex items-center gap-2'>
<div className='size-2 rounded-full bg-green-600 dark:bg-green-400 me-1' />
<span>Free components available</span>
</div>
<div className='flex items-center gap-2'>
<div className='size-2 rounded-full bg-blue-600 dark:bg-blue-400 me-1' />
<span>Commercial license included</span>
</div>
<div className='flex items-center gap-2'>
<div className='size-2 rounded-full bg-purple-600 dark:bg-purple-400 me-1' />
<span>Regular updates & support</span>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
)
}
+107
View File
@@ -0,0 +1,107 @@
"use client"
import { CircleHelp } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion'
import { Badge } from '@/components/ui/badge'
type FaqItem = {
value: string
question: string
answer: string
}
const faqItems: FaqItem[] = [
{
value: 'item-1',
question: 'How do I integrate ShadcnStore components into my project?',
answer:
'Integration is simple! All our components are built with shadcn/ui and work with React, Next.js, and Vite. Just copy the component code, install any required dependencies, and paste it into your project. Each component comes with detailed installation instructions and examples.',
},
{
value: 'item-2',
question: 'What\'s the difference between free and premium components?',
answer:
'Free components include essential UI elements like buttons, forms, and basic layouts. Premium components offer advanced features like complex data tables, analytics dashboards, authentication flows, and complete admin templates. Premium also includes Figma files, priority support, and commercial licenses.',
},
{
value: 'item-3',
question: 'Can I use these components in commercial projects?',
answer:
'Yes! Free components come with an MIT license for unlimited use. Premium components include a commercial license that allows usage in client projects, SaaS applications, and commercial products without attribution requirements.',
},
{
value: 'item-4',
question: 'Do you provide support and updates?',
answer:
'Absolutely! We provide community support for free components through our Discord server and GitHub issues. Premium subscribers get priority email support, regular component updates, and early access to new releases. We also maintain compatibility with the latest shadcn/ui versions.',
},
{
value: 'item-5',
question: 'What frameworks and tools do you support?',
answer:
'Our components work with React 18+, Next.js 13+, and Vite. We use TypeScript, Tailwind CSS, and follow shadcn/ui conventions. Components are tested with popular tools like React Hook Form, TanStack Query, and Zustand for state management.',
},
{
value: 'item-6',
question: 'How often do you release new components?',
answer:
'We release new components and templates weekly. Premium subscribers get early access to new releases, while free components are updated regularly based on community feedback. You can track our roadmap and request specific components through our GitHub repository.',
},
]
const FaqSection = () => {
return (
<section id="faq" className="py-24 sm:py-32">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
{/* Section Header */}
<div className="mx-auto max-w-2xl text-center mb-16">
<Badge variant="outline" className="mb-4">FAQ</Badge>
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl mb-4">
Frequently Asked Questions
</h2>
<p className="text-lg text-muted-foreground">
Everything you need to know about ShadcnStore components, licensing, and integration. Still have questions? We&apos;re here to help!
</p>
</div>
{/* FAQ Content */}
<div className="max-w-4xl mx-auto">
<div className='bg-transparent'>
<div className='p-0'>
<Accordion type='single' collapsible className='space-y-5'>
{faqItems.map(item => (
<AccordionItem key={item.value} value={item.value} className='rounded-md !border bg-transparent'>
<AccordionTrigger className='cursor-pointer items-center gap-4 rounded-none bg-transparent py-2 ps-3 pe-4 hover:no-underline data-[state=open]:border-b'>
<div className='flex items-center gap-4'>
<div className='bg-primary/10 text-primary flex size-9 shrink-0 items-center justify-center rounded-full'>
<CircleHelp className='size-5' />
</div>
<span className='text-start font-semibold'>{item.question}</span>
</div>
</AccordionTrigger>
<AccordionContent className='p-4 bg-transparent'>{item.answer}</AccordionContent>
</AccordionItem>
))}
</Accordion>
</div>
</div>
{/* Contact Support CTA */}
<div className="text-center mt-12">
<p className="text-muted-foreground mb-4">
Still have questions? We&apos;re here to help.
</p>
<Button className='cursor-pointer' asChild>
<a href="#contact">
Contact Support
</a>
</Button>
</div>
</div>
</div>
</section>
)
}
export { FaqSection }
@@ -0,0 +1,183 @@
"use client"
import {
BarChart3,
Zap,
Users,
ArrowRight,
Database,
Package,
Crown,
Layout,
Palette
} from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Image3D } from '@/components/image-3d'
const mainFeatures = [
{
icon: Package,
title: 'Curated Component Library',
description: 'Hand-picked blocks and templates for quality and reliability.'
},
{
icon: Crown,
title: 'Free & Premium Options',
description: 'Start free, upgrade to premium collections when you need more.'
},
{
icon: Layout,
title: 'Ready-to-Use Templates',
description: 'Copy-paste components that just work out of the box.'
},
{
icon: Zap,
title: 'Regular Updates',
description: 'New blocks and templates added weekly to keep you current.'
}
]
const secondaryFeatures = [
{
icon: BarChart3,
title: 'Multiple Frameworks',
description: 'React, Next.js, and Vite compatibility for flexible development.'
},
{
icon: Palette,
title: 'Modern Tech Stack',
description: 'Built with shadcn/ui, Tailwind CSS, and TypeScript.'
},
{
icon: Users,
title: 'Responsive Design',
description: 'Mobile-first components for all screen sizes and devices.'
},
{
icon: Database,
title: 'Developer-Friendly',
description: 'Clean code, well-documented, easy integration and customization.'
}
]
export function FeaturesSection() {
return (
<section id="features" className="py-24 sm:py-32 bg-muted/30">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
{/* Section Header */}
<div className="mx-auto max-w-2xl text-center mb-16">
<Badge variant="outline" className="mb-4">Marketplace Features</Badge>
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl mb-4">
Everything you need to build amazing web applications
</h2>
<p className="text-lg text-muted-foreground">
Our marketplace provides curated blocks, templates, landing pages, and admin dashboards to help you build professional applications faster than ever.
</p>
</div>
{/* First Feature Section */}
<div className="grid items-center gap-12 lg:grid-cols-2 lg:gap-8 xl:gap-16 mb-24">
{/* Left Image */}
<Image3D
lightSrc="/feature-1-light.png"
darkSrc="/feature-1-dark.png"
alt="Analytics dashboard"
direction="left"
/>
{/* Right Content */}
<div className="space-y-6">
<div className="space-y-4">
<h3 className="text-2xl font-semibold tracking-tight text-balance sm:text-3xl">
Components that accelerate development
</h3>
<p className="text-muted-foreground text-base text-pretty">
Our curated marketplace offers premium blocks and templates designed to save time and ensure consistency across your admin projects.
</p>
</div>
<ul className="grid gap-4 sm:grid-cols-2">
{mainFeatures.map((feature, index) => (
<li key={index} className="group hover:bg-accent/5 flex items-start gap-3 p-2 rounded-lg transition-colors">
<div className="mt-0.5 flex shrink-0 items-center justify-center">
<feature.icon className="size-5 text-primary" aria-hidden="true" />
</div>
<div>
<h3 className="text-foreground font-medium">{feature.title}</h3>
<p className="text-muted-foreground mt-1 text-sm">{feature.description}</p>
</div>
</li>
))}
</ul>
<div className="flex flex-col sm:flex-row gap-4 pe-4 pt-2">
<Button size="lg" className="cursor-pointer">
<a href="https://shadcnstore.com/templates" className='flex items-center'>
Browse Templates
<ArrowRight className="ms-2 size-4" aria-hidden="true" />
</a>
</Button>
<Button size="lg" variant="outline" className="cursor-pointer">
<a href="https://shadcnstore.com/blocks">
View Components
</a>
</Button>
</div>
</div>
</div>
{/* Second Feature Section - Flipped Layout */}
<div className="grid items-center gap-12 lg:grid-cols-2 lg:gap-8 xl:gap-16">
{/* Left Content */}
<div className="space-y-6 order-2 lg:order-1">
<div className="space-y-4">
<h3 className="text-2xl font-semibold tracking-tight text-balance sm:text-3xl">
Built for modern development workflows
</h3>
<p className="text-muted-foreground text-base text-pretty">
Every component follows best practices with TypeScript, responsive design, and clean code architecture that integrates seamlessly into your projects.
</p>
</div>
<ul className="grid gap-4 sm:grid-cols-2">
{secondaryFeatures.map((feature, index) => (
<li key={index} className="group hover:bg-accent/5 flex items-start gap-3 p-2 rounded-lg transition-colors">
<div className="mt-0.5 flex shrink-0 items-center justify-center">
<feature.icon className="size-5 text-primary" aria-hidden="true" />
</div>
<div>
<h3 className="text-foreground font-medium">{feature.title}</h3>
<p className="text-muted-foreground mt-1 text-sm">{feature.description}</p>
</div>
</li>
))}
</ul>
<div className="flex flex-col sm:flex-row gap-4 pe-4 pt-2">
<Button size="lg" className="cursor-pointer">
<a href="#" className='flex items-center'>
View Documentation
<ArrowRight className="ms-2 size-4" aria-hidden="true" />
</a>
</Button>
<Button size="lg" variant="outline" className="cursor-pointer">
<a href="https://github.com/silicondeck/shadcn-dashboard-landing-template" target="_blank" rel="noopener noreferrer">
GitHub Repository
</a>
</Button>
</div>
</div>
{/* Right Image */}
<Image3D
lightSrc="/feature-2-light.png"
darkSrc="/feature-2-dark.png"
alt="Performance dashboard"
direction="right"
className="order-1 lg:order-2"
/>
</div>
</div>
</section>
)
}
+234
View File
@@ -0,0 +1,234 @@
"use client"
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
import { Separator } from '@/components/ui/separator'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import {
Form,
FormControl,
FormField,
FormItem,
FormMessage,
} from "@/components/ui/form"
import { Logo } from '@/components/logo'
import { Github, Twitter, Linkedin, Youtube, Heart } from 'lucide-react'
const newsletterSchema = z.object({
email: z.string().email({
message: "Please enter a valid email address.",
}),
})
const footerLinks = {
product: [
{ name: 'Features', href: '#features' },
{ name: 'Pricing', href: '#pricing' },
{ name: 'API', href: '#api' },
{ name: 'Documentation', href: '#docs' },
],
company: [
{ name: 'About', href: '#about' },
{ name: 'Blog', href: '#blog' },
{ name: 'Careers', href: '#careers' },
{ name: 'Press', href: '#press' },
],
resources: [
{ name: 'Help Center', href: '#help' },
{ name: 'Community', href: '#community' },
{ name: 'Guides', href: '#guides' },
{ name: 'Webinars', href: '#webinars' },
],
legal: [
{ name: 'Privacy', href: '#privacy' },
{ name: 'Terms', href: '#terms' },
{ name: 'Security', href: '#security' },
{ name: 'Status', href: '#status' },
],
}
const socialLinks = [
{ name: 'Twitter', href: '#', icon: Twitter },
{ name: 'GitHub', href: 'https://github.com/silicondeck/shadcn-dashboard-landing-template', icon: Github },
{ name: 'LinkedIn', href: '#', icon: Linkedin },
{ name: 'YouTube', href: '#', icon: Youtube },
]
export function LandingFooter() {
const form = useForm<z.infer<typeof newsletterSchema>>({
resolver: zodResolver(newsletterSchema),
defaultValues: {
email: "",
},
})
function onSubmit(values: z.infer<typeof newsletterSchema>) {
// Here you would typically send the email to your newsletter service
console.log(values)
// Show success message and reset form
form.reset()
}
return (
<footer className="border-t bg-background">
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-16">
{/* Newsletter Section */}
<div className="mb-16">
<div className="mx-auto max-w-2xl text-center">
<h3 className="text-2xl font-bold mb-4">Stay updated</h3>
<p className="text-muted-foreground mb-6">
Get the latest updates, articles, and resources sent to your inbox weekly.
</p>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col gap-2 max-w-md mx-auto sm:flex-row">
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem className="flex-1">
<FormControl>
<Input
type="email"
placeholder="Enter your email"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit" className="cursor-pointer">Subscribe</Button>
</form>
</Form>
</div>
</div>
{/* Main Footer Content */}
<div className="grid gap-8 grid-cols-4 lg:grid-cols-6">
{/* Brand Column */}
<div className="col-span-4 lg:col-span-2 max-w-2xl">
<div className="flex items-center space-x-2 mb-4 max-lg:justify-center">
<a href="https://shadcnstore.com" target='_blank' className="flex items-center space-x-2 cursor-pointer">
<Logo size={32} />
<span className="font-bold text-xl">ShadcnStore</span>
</a>
</div>
<p className="text-muted-foreground mb-6 max-lg:text-center max-lg:flex max-lg:justify-center">
Accelerating web development with curated blocks, templates, landing pages, and admin dashboards designed for modern developers.
</p>
<div className="flex space-x-4 max-lg:justify-center">
{socialLinks.map((social) => (
<Button key={social.name} variant="ghost" size="icon" asChild>
<a
href={social.href}
aria-label={social.name}
target="_blank"
rel="noopener noreferrer"
>
<social.icon className="h-4 w-4" />
</a>
</Button>
))}
</div>
</div>
{/* Links Columns */}
<div className='max-md:col-span-2 lg:col-span-1'>
<h4 className="font-semibold mb-4">Product</h4>
<ul className="space-y-3">
{footerLinks.product.map((link) => (
<li key={link.name}>
<a
href={link.href}
className="text-muted-foreground hover:text-foreground transition-colors"
>
{link.name}
</a>
</li>
))}
</ul>
</div>
<div className='max-md:col-span-2 lg:col-span-1'>
<h4 className="font-semibold mb-4">Company</h4>
<ul className="space-y-3">
{footerLinks.company.map((link) => (
<li key={link.name}>
<a
href={link.href}
className="text-muted-foreground hover:text-foreground transition-colors"
>
{link.name}
</a>
</li>
))}
</ul>
</div>
<div className='max-md:col-span-2 lg:col-span-1'>
<h4 className="font-semibold mb-4">Resources</h4>
<ul className="space-y-3">
{footerLinks.resources.map((link) => (
<li key={link.name}>
<a
href={link.href}
className="text-muted-foreground hover:text-foreground transition-colors"
>
{link.name}
</a>
</li>
))}
</ul>
</div>
<div className='max-md:col-span-2 lg:col-span-1'>
<h4 className="font-semibold mb-4">Legal</h4>
<ul className="space-y-3">
{footerLinks.legal.map((link) => (
<li key={link.name}>
<a
href={link.href}
className="text-muted-foreground hover:text-foreground transition-colors"
>
{link.name}
</a>
</li>
))}
</ul>
</div>
</div>
<Separator className="my-8" />
{/* Bottom Footer */}
<div className="flex flex-col lg:flex-row justify-between items-center gap-2">
<div className="flex flex-col sm:flex-row items-center gap-2 text-muted-foreground text-sm">
<div className="flex items-center gap-1">
<span>Made with</span>
<Heart className="h-4 w-4 text-red-500 fill-current" />
<span>by</span>
<a href="https://shadcnstore.com" target='_blank' className="font-semibold text-foreground hover:text-primary transition-colors cursor-pointer">
ShadcnStore
</a>
</div>
<span className="hidden sm:inline"></span>
<span>© {new Date().getFullYear()} for the developer community</span>
</div>
<div className="flex items-center space-x-4 text-sm text-muted-foreground mt-4 md:mt-0">
<a href="#privacy" className="hover:text-foreground transition-colors">
Privacy Policy
</a>
<a href="#terms" className="hover:text-foreground transition-colors">
Terms of Service
</a>
<a href="#cookies" className="hover:text-foreground transition-colors">
Cookie Policy
</a>
</div>
</div>
</div>
</footer>
)
}
+110
View File
@@ -0,0 +1,110 @@
"use client"
import Link from 'next/link'
import Image from 'next/image'
import { ArrowRight, Play, Star } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { DotPattern } from '@/components/dot-pattern'
export function HeroSection() {
return (
<section id="hero" className="relative overflow-hidden bg-gradient-to-b from-background to-background/80 pt-16 sm:pt-20 pb-16">
{/* Background Pattern */}
<div className="absolute inset-0">
{/* Dot pattern overlay using reusable component */}
<DotPattern className="opacity-100" size="md" fadeStyle="ellipse" />
</div>
<div className="container mx-auto px-4 sm:px-6 lg:px-8 relative">
<div className="mx-auto max-w-4xl text-center">
{/* Announcement Badge */}
<div className="mb-8 flex justify-center">
<Badge variant="outline" className="px-4 py-2 border-foreground">
<Star className="w-3 h-3 mr-2 fill-current" />
New: Premium Template Collection
<ArrowRight className="w-3 h-3 ml-2" />
</Badge>
</div>
{/* Main Headline */}
<h1 className="mb-6 text-4xl font-bold tracking-tight sm:text-6xl lg:text-7xl">
Build Better
<span className="bg-gradient-to-r from-primary to-primary/60 bg-clip-text text-transparent">
{" "}Web Applications{" "}
</span>
with Ready-Made Components
</h1>
{/* Subheading */}
<p className="mx-auto mb-10 max-w-2xl text-lg text-muted-foreground sm:text-xl">
Accelerate your development with our curated collection of blocks, templates, landing pages,
and admin dashboards. From free components to complete solutions, built with shadcn/ui.
</p>
{/* CTA Buttons */}
<div className="flex flex-col gap-4 sm:flex-row sm:justify-center">
<Button size="lg" className="text-base cursor-pointer" asChild>
<Link href="/auth/sign-up">
Get Started Free
<ArrowRight className="ml-2 h-4 w-4" />
</Link>
</Button>
<Button variant="outline" size="lg" className="text-base cursor-pointer" asChild>
<a href="#">
<Play className="mr-2 h-4 w-4" />
Watch Demo
</a>
</Button>
</div>
</div>
{/* Hero Image/Visual */}
<div className="mx-auto mt-20 max-w-6xl">
<div className="relative group">
{/* Top background glow effect - positioned above the image */}
<div className="absolute top-2 lg:-top-8 left-1/2 transform -translate-x-1/2 w-[90%] mx-auto h-24 lg:h-80 bg-primary/50 rounded-full blur-3xl"></div>
<div className="relative rounded-xl border bg-card shadow-2xl">
{/* Light mode dashboard image */}
<Image
src="/dashboard-light.png"
alt="Dashboard Preview - Light Mode"
width={1200}
height={800}
className="w-full rounded-xl object-cover block dark:hidden"
priority
/>
{/* Dark mode dashboard image */}
<Image
src="/dashboard-dark.png"
alt="Dashboard Preview - Dark Mode"
width={1200}
height={800}
className="w-full rounded-xl object-cover hidden dark:block"
priority
/>
{/* Bottom fade effect - gradient overlay that fades the image to background */}
<div className="absolute bottom-0 left-0 w-full h-32 md:h-40 lg:h-48 bg-gradient-to-b from-background/0 via-background/70 to-background rounded-b-xl"></div>
{/* Overlay play button for demo */}
<div className="absolute inset-0 flex items-center justify-center">
<Button
size="lg"
className="rounded-full h-16 w-16 p-0 cursor-pointer hover:scale-105 transition-transform"
asChild
>
<a href="#" aria-label="Watch demo video">
<Play className="h-6 w-6 fill-current" />
</a>
</Button>
</div>
</div>
</div>
</div>
</div>
</section>
)
}
@@ -0,0 +1,406 @@
"use client"
import React from 'react'
import { Palette, RotateCcw, Settings, X, Dices, Upload, ExternalLink, Sun, Moon } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from '@/components/ui/sheet'
import { Label } from '@/components/ui/label'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import { Separator } from '@/components/ui/separator'
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion'
import { useThemeManager } from '@/hooks/use-theme-manager'
import { useCircularTransition } from '@/hooks/use-circular-transition'
import { colorThemes, tweakcnThemes } from '@/config/theme-data'
import { radiusOptions, baseColors } from '@/config/theme-customizer-constants'
import { ColorPicker } from '@/components/color-picker'
import { ImportModal } from '@/components/theme-customizer/import-modal'
import { cn } from '@/lib/utils'
import type { ImportedTheme } from '@/types/theme-customizer'
import "@/components/theme-customizer/circular-transition.css"
interface LandingThemeCustomizerProps {
open: boolean
onOpenChange: (open: boolean) => void
}
export function LandingThemeCustomizer({ open, onOpenChange }: LandingThemeCustomizerProps) {
const {
applyImportedTheme,
isDarkMode,
resetTheme,
applyRadius,
setBrandColorsValues,
applyTheme,
applyTweakcnTheme,
brandColorsValues,
handleColorChange
} = useThemeManager()
const { toggleTheme } = useCircularTransition()
const [selectedTheme, setSelectedTheme] = React.useState("default")
const [selectedTweakcnTheme, setSelectedTweakcnTheme] = React.useState("")
const [selectedRadius, setSelectedRadius] = React.useState("0.5rem")
const [importModalOpen, setImportModalOpen] = React.useState(false)
const [importedTheme, setImportedTheme] = React.useState<ImportedTheme | null>(null)
const handleReset = () => {
// Reset all state variables to initial values
setSelectedTheme("")
setSelectedTweakcnTheme("")
setSelectedRadius("0.5rem")
setImportedTheme(null)
setBrandColorsValues({})
// Reset theme and radius to defaults
resetTheme()
applyRadius("0.5rem")
}
const handleImport = (themeData: ImportedTheme) => {
setImportedTheme(themeData)
// Clear other selections to indicate custom import is active
setSelectedTheme("")
setSelectedTweakcnTheme("")
// Apply the imported theme
applyImportedTheme(themeData, isDarkMode)
}
const handleImportClick = () => {
setImportModalOpen(true)
}
const handleRandomShadcn = () => {
// Apply a random shadcn theme
const randomTheme = colorThemes[Math.floor(Math.random() * colorThemes.length)]
setSelectedTheme(randomTheme.value)
setSelectedTweakcnTheme("")
setBrandColorsValues({})
setImportedTheme(null)
applyTheme(randomTheme.value, isDarkMode)
}
const handleRandomTweakcn = () => {
// Apply a random tweakcn theme
const randomTheme = tweakcnThemes[Math.floor(Math.random() * tweakcnThemes.length)]
setSelectedTweakcnTheme(randomTheme.value)
setSelectedTheme("")
setBrandColorsValues({})
setImportedTheme(null)
applyTweakcnTheme(randomTheme.preset, isDarkMode)
}
const handleRadiusSelect = (radius: string) => {
setSelectedRadius(radius)
applyRadius(radius)
}
const handleLightMode = (event: React.MouseEvent<HTMLButtonElement>) => {
if (isDarkMode === false) return
toggleTheme(event)
}
const handleDarkMode = (event: React.MouseEvent<HTMLButtonElement>) => {
if (isDarkMode === true) return
toggleTheme(event)
}
// Re-apply themes when theme mode changes
React.useEffect(() => {
if (importedTheme) {
applyImportedTheme(importedTheme, isDarkMode)
} else if (selectedTheme) {
applyTheme(selectedTheme, isDarkMode)
} else if (selectedTweakcnTheme) {
const selectedPreset = tweakcnThemes.find(t => t.value === selectedTweakcnTheme)?.preset
if (selectedPreset) {
applyTweakcnTheme(selectedPreset, isDarkMode)
}
}
}, [isDarkMode, importedTheme, selectedTheme, selectedTweakcnTheme, applyImportedTheme, applyTheme, applyTweakcnTheme])
return (
<>
<Sheet open={open} onOpenChange={onOpenChange} modal={false}>
<SheetContent
side="right"
className="w-[400px] p-0 gap-0 pointer-events-auto [&>button]:hidden overflow-hidden flex flex-col"
onInteractOutside={(e) => {
// Prevent the sheet from closing when dialog is open
if (importModalOpen) {
e.preventDefault()
}
}}
>
<SheetHeader className="space-y-0 p-4 pb-2">
<div className="flex items-center gap-2">
<div className="p-2 bg-primary/10 rounded-lg">
<Settings className="h-4 w-4" />
</div>
<SheetTitle className="text-lg font-semibold">Theme Customizer</SheetTitle>
<div className="ml-auto flex items-center gap-2">
<Button variant="outline" size="icon" onClick={handleReset} className="cursor-pointer h-8 w-8">
<RotateCcw className="h-4 w-4" />
</Button>
<Button variant="outline" size="icon" onClick={() => onOpenChange(false)} className="cursor-pointer h-8 w-8">
<X className="h-4 w-4" />
</Button>
</div>
</div>
<SheetDescription className="text-sm text-muted-foreground">
Customize the theme and colors of your landing page.
</SheetDescription>
</SheetHeader>
<div className="flex-1 overflow-y-auto p-4 space-y-6">
{/* Mode Section */}
<div className="space-y-3">
<Label className="text-sm font-medium">Mode</Label>
<div className="grid grid-cols-2 gap-2">
<Button
variant={!isDarkMode ? "secondary" : "outline"}
size="sm"
onClick={handleLightMode}
className="cursor-pointer mode-toggle-button relative overflow-hidden"
>
<Sun className="h-4 w-4 mr-1 transition-transform duration-300" />
Light
</Button>
<Button
variant={isDarkMode ? "secondary" : "outline"}
size="sm"
onClick={handleDarkMode}
className="cursor-pointer mode-toggle-button relative overflow-hidden"
>
<Moon className="h-4 w-4 mr-1 transition-transform duration-300" />
Dark
</Button>
</div>
</div>
<Separator />
{/* Shadcn UI Theme Presets */}
<div className="space-y-3">
<div className="flex items-center justify-between">
<Label className="text-sm font-medium">Shadcn UI Theme Presets</Label>
<Button variant="outline" size="sm" onClick={handleRandomShadcn} className="cursor-pointer">
<Dices className="h-3.5 w-3.5 mr-1.5" />
Random
</Button>
</div>
<Select value={selectedTheme} onValueChange={(value) => {
setSelectedTheme(value)
setSelectedTweakcnTheme("")
setBrandColorsValues({})
setImportedTheme(null)
applyTheme(value, isDarkMode)
}}>
<SelectTrigger className="w-full cursor-pointer">
<SelectValue placeholder="Choose Shadcn Theme" />
</SelectTrigger>
<SelectContent className="max-h-60">
<div className="p-2">
{colorThemes.map((theme) => (
<SelectItem key={theme.value} value={theme.value} className="cursor-pointer">
<div className="flex items-center gap-2">
<div className="flex gap-1">
<div
className="w-3 h-3 rounded-full border border-border/20"
style={{ backgroundColor: theme.preset.styles.light.primary }}
/>
<div
className="w-3 h-3 rounded-full border border-border/20"
style={{ backgroundColor: theme.preset.styles.light.secondary }}
/>
<div
className="w-3 h-3 rounded-full border border-border/20"
style={{ backgroundColor: theme.preset.styles.light.accent }}
/>
<div
className="w-3 h-3 rounded-full border border-border/20"
style={{ backgroundColor: theme.preset.styles.light.muted }}
/>
</div>
<span>{theme.name}</span>
</div>
</SelectItem>
))}
</div>
</SelectContent>
</Select>
</div>
<Separator />
{/* Tweakcn Theme Presets */}
<div className="space-y-3">
<div className="flex items-center justify-between">
<Label className="text-sm font-medium">Tweakcn Theme Presets</Label>
<Button variant="outline" size="sm" onClick={handleRandomTweakcn} className="cursor-pointer">
<Dices className="h-3.5 w-3.5 mr-1.5" />
Random
</Button>
</div>
<Select value={selectedTweakcnTheme} onValueChange={(value) => {
setSelectedTweakcnTheme(value)
setSelectedTheme("")
setBrandColorsValues({})
setImportedTheme(null)
const selectedPreset = tweakcnThemes.find(t => t.value === value)?.preset
if (selectedPreset) {
applyTweakcnTheme(selectedPreset, isDarkMode)
}
}}>
<SelectTrigger className="w-full cursor-pointer">
<SelectValue placeholder="Choose Tweakcn Theme" />
</SelectTrigger>
<SelectContent className="max-h-60">
<div className="p-2">
{tweakcnThemes.map((theme) => (
<SelectItem key={theme.value} value={theme.value} className="cursor-pointer">
<div className="flex items-center gap-2">
<div className="flex gap-1">
<div
className="w-3 h-3 rounded-full border border-border/20"
style={{ backgroundColor: theme.preset.styles.light.primary }}
/>
<div
className="w-3 h-3 rounded-full border border-border/20"
style={{ backgroundColor: theme.preset.styles.light.secondary }}
/>
<div
className="w-3 h-3 rounded-full border border-border/20"
style={{ backgroundColor: theme.preset.styles.light.accent }}
/>
<div
className="w-3 h-3 rounded-full border border-border/20"
style={{ backgroundColor: theme.preset.styles.light.muted }}
/>
</div>
<span>{theme.name}</span>
</div>
</SelectItem>
))}
</div>
</SelectContent>
</Select>
</div>
<Separator />
{/* Radius Selection */}
<div className="space-y-3">
<Label className="text-sm font-medium">Radius</Label>
<div className="grid grid-cols-5 gap-2">
{radiusOptions.map((option) => (
<div
key={option.value}
className={`relative cursor-pointer rounded-md p-3 border transition-colors ${
selectedRadius === option.value
? "border-primary"
: "border-border hover:border-border/60"
}`}
onClick={() => handleRadiusSelect(option.value)}
>
<div className="text-center">
<div className="text-xs font-medium">{option.name}</div>
</div>
</div>
))}
</div>
</div>
<Separator />
{/* Import Theme Button */}
<div className="space-y-3">
<Button
variant="outline"
size="lg"
onClick={handleImportClick}
className="w-full cursor-pointer"
>
<Upload className="h-3.5 w-3.5 mr-1.5" />
Import Theme
</Button>
</div>
{/* Brand Colors Section */}
<Accordion type="single" collapsible className="w-full border-b rounded-lg">
<AccordionItem value="brand-colors" className="border border-border rounded-lg overflow-hidden">
<AccordionTrigger className="px-4 py-3 hover:no-underline hover:bg-muted/50 transition-colors">
<Label className="text-sm font-medium cursor-pointer">Brand Colors</Label>
</AccordionTrigger>
<AccordionContent className="px-4 pb-4 pt-2 space-y-3 border-t border-border bg-muted/20">
{baseColors.map((color) => (
<div key={color.cssVar} className="flex items-center justify-between">
<ColorPicker
label={color.name}
cssVar={color.cssVar}
value={brandColorsValues[color.cssVar] || ""}
onChange={handleColorChange}
/>
</div>
))}
</AccordionContent>
</AccordionItem>
</Accordion>
{/* Tweakcn */}
<div className="p-4 bg-muted rounded-lg space-y-3">
<div className="flex items-center gap-2">
<Palette className="h-4 w-4 text-primary" />
<span className="text-sm font-medium">Advanced Customization</span>
</div>
<p className="text-xs text-muted-foreground">
For advanced theme customization with real-time preview, visual color picker, and hundreds of prebuilt themes, visit{" "}
<a
href="https://tweakcn.com/editor/theme"
target="_blank"
rel="noopener noreferrer"
className="text-primary hover:underline font-medium cursor-pointer"
>
tweakcn.com
</a>
</p>
<Button
variant="outline"
size="sm"
className="w-full cursor-pointer"
onClick={() => window.open('https://tweakcn.com/editor/theme', '_blank')}
>
<ExternalLink className="h-3.5 w-3.5 mr-1.5" />
Open Tweakcn
</Button>
</div>
</div>
</SheetContent>
</Sheet>
<ImportModal
open={importModalOpen}
onOpenChange={setImportModalOpen}
onImport={handleImport}
/>
</>
)
}
// Floating trigger button for landing page
export function LandingThemeCustomizerTrigger({ onClick }: { onClick: () => void }) {
return (
<Button
onClick={onClick}
size="icon"
className={cn(
"fixed top-1/2 -translate-y-1/2 h-12 w-12 rounded-full shadow-lg z-50 bg-primary hover:bg-primary/90 text-primary-foreground cursor-pointer right-4"
)}
>
<Settings className="h-5 w-5" />
</Button>
)
}
@@ -0,0 +1,117 @@
"use client"
import { Card } from '@/components/ui/card'
// Simple icon component for company logos
const SimpleIcon = ({ iconSlug, size = 24 }: { iconSlug: string; size?: number }) => {
const iconMap = {
shopify:
'M15.337 23.979l7.216-1.561s-2.604-17.613-2.625-17.73c-.018-.116-.114-.192-.211-.192s-1.929-.136-1.929-.136-1.275-1.274-1.439-1.411c-.045-.037-.075-.057-.121-.074l-.914 21.104h.023zM11.71 11.305s-.81-.424-1.774-.424c-1.447 0-1.504.906-1.504 1.141 0 1.232 3.24 1.715 3.24 4.629 0 2.295-1.44 3.76-3.406 3.76-2.354 0-3.54-1.465-3.54-1.465l.646-2.086s1.245 1.066 2.28 1.066c.675 0 .975-.545.975-.932 0-1.619-2.654-1.694-2.654-4.359-.034-2.237 1.571-4.416 4.827-4.416 1.257 0 1.875.361 1.875.361l-.945 2.715-.02.01zM11.17.83c.136 0 .271.038.405.135-.984.465-2.064 1.639-2.508 3.992-.656.213-1.293.405-1.889.578C7.697 3.75 8.951.84 11.17.84V.83zm1.235 2.949v.135c-.754.232-1.583.484-2.394.736.466-1.777 1.333-2.645 2.085-2.971.193.501.309 1.176.309 2.1zm.539-2.234c.694.074 1.141.867 1.429 1.755-.349.114-.735.231-1.158.366v-.252c0-.752-.096-1.371-.271-1.871v.002zm2.992 1.289c-.02 0-.06.021-.078.021s-.289.075-.714.21c-.423-1.233-1.176-2.37-2.508-2.37h-.115C12.135.209 11.669 0 11.265 0 8.159 0 6.675 3.877 6.21 5.846c-1.194.365-2.063.636-2.16.674-.675.213-.694.232-.772.87-.075.462-1.83 14.063-1.83 14.063L15.009 24l.927-21.166z',
netflix:
'm5.398 0 8.348 23.602c2.346.059 4.856.398 4.856.398L10.113 0H5.398zm8.489 0v9.172l4.715 13.33V0h-4.715zM5.398 1.5V24c1.873-.225 2.81-.312 4.715-.398V14.83L5.398 1.5z',
spotify:
'M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.66 0 12 0zm5.521 17.34c-.24.359-.66.48-1.021.24-2.82-1.74-6.36-2.101-10.561-1.141-.418.122-.779-.179-.899-.539-.12-.421.18-.78.54-.9 4.56-1.021 8.52-.6 11.64 1.32.42.18.479.659.301 1.02zm1.44-3.3c-.301.42-.841.6-1.262.3-3.239-1.98-8.159-2.58-11.939-1.38-.479.12-1.02-.12-1.14-.6-.12-.48.12-1.021.6-1.141C9.6 9.9 15 10.561 18.72 12.84c.361.181.54.78.241 1.2zm.12-3.36C15.24 8.4 8.82 8.16 5.16 9.301c-.6.179-1.2-.181-1.38-.721-.18-.601.18-1.2.72-1.381 4.26-1.26 11.28-1.02 15.721 1.621.539.3.719 1.02.419 1.56-.299.421-1.02.599-1.559.3z',
airbnb:
'M12.001 18.275c-1.353-1.697-2.148-3.184-2.413-4.457-.263-1.027-.16-1.848.291-2.465.477-.71 1.188-1.056 2.121-1.056s1.643.345 2.12 1.063c.446.61.558 1.432.286 2.465-.291 1.298-1.085 2.785-2.412 4.458zm9.601 1.14c-.185 1.246-1.034 2.28-2.2 2.783-2.253.98-4.483-.583-6.392-2.704 3.157-3.951 3.74-7.028 2.385-9.018-.795-1.14-1.933-1.695-3.394-1.695-2.944 0-4.563 2.49-3.927 5.382.37 1.565 1.352 3.343 2.917 5.332-.98 1.085-1.91 1.856-2.732 2.333-.636.344-1.245.558-1.828.609-2.679.399-4.778-2.2-3.825-4.88.132-.345.395-.98.845-1.961l.025-.053c1.464-3.178 3.242-6.79 5.285-10.795l.053-.132.58-1.116c.45-.822.635-1.19 1.351-1.643.346-.21.77-.315 1.246-.315.954 0 1.698.558 2.016 1.007.158.239.345.557.582.953l.558 1.089.08.159c2.041 4.004 3.821 7.608 5.279 10.794l.026.025.533 1.22.318.764c.243.613.294 1.222.213 1.858zm1.22-2.39c-.186-.583-.505-1.271-.9-2.094v-.03c-1.889-4.006-3.642-7.608-5.307-10.844l-.111-.163C15.317 1.461 14.468 0 12.001 0c-2.44 0-3.476 1.695-4.535 3.898l-.081.16c-1.669 3.236-3.421 6.843-5.303 10.847v.053l-.559 1.22c-.21.504-.317.768-.345.847C-.172 20.74 2.611 24 5.98 24c.027 0 .132 0 .265-.027h.372c1.75-.213 3.554-1.325 5.384-3.317 1.829 1.989 3.635 3.104 5.382 3.317h.372c.133.027.239.027.265.027 3.37.003 6.152-3.261 4.802-6.975z',
dropbox:
'M6 1.807L0 5.629l6 3.822 6.001-3.822L6 1.807zM18 1.807l-6 3.822 6 3.822 6-3.822-6-3.822zM0 13.274l6 3.822 6.001-3.822L6 9.452l-6 3.822zM18 9.452l-6 3.822 6 3.822 6-3.822-6-3.822zM6 18.371l6.001 3.822 6-3.822-6-3.822L6 18.371z',
stripe:
'M13.976 9.15c-2.172-.806-3.356-1.426-3.356-2.409 0-.831.683-1.305 1.901-1.305 2.227 0 4.515.858 6.09 1.631l.89-5.494C18.252.975 15.697 0 12.165 0 9.667 0 7.589.654 6.104 1.872 4.56 3.147 3.757 4.992 3.757 7.218c0 4.039 2.467 5.76 6.476 7.219 2.585.92 3.445 1.574 3.445 2.583 0 .98-.84 1.545-2.354 1.545-1.875 0-4.965-.921-6.99-2.109l-.9 5.555C5.175 22.99 8.385 24 11.714 24c2.641 0 4.843-.624 6.328-1.813 1.664-1.305 2.525-3.236 2.525-5.732 0-4.128-2.524-5.851-6.594-7.305h.003z',
google:
'M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z',
apple:
'M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701',
meta: 'M6.915 4.03c-1.968 0-3.683 1.28-4.871 3.113C.704 9.208 0 11.883 0 14.449c0 .706.07 1.369.21 1.973a6.624 6.624 0 0 0 .265.86 5.297 5.297 0 0 0 .371.761c.696 1.159 1.818 1.927 3.593 1.927 1.497 0 2.633-.671 3.965-2.444.76-1.012 1.144-1.626 2.663-4.32l.756-1.339.186-.325c.061.1.121.196.183.3l2.152 3.595c.724 1.21 1.665 2.556 2.47 3.314 1.046.987 1.992 1.22 3.06 1.22 1.075 0 1.876-.355 2.455-.843a3.743 3.743 0 0 0 .81-.973c.542-.939.861-2.127.861-3.745 0-2.72-.681-5.357-2.084-7.45-1.282-1.912-2.957-2.93-4.716-2.93-1.047 0-2.088.467-3.053 1.308-.652.57-1.257 1.29-1.82 2.05-.69-.875-1.335-1.547-1.958-2.056-1.182-.966-2.315-1.303-3.454-1.303zm10.16 2.053c1.147 0 2.188.758 2.992 1.999 1.132 1.748 1.647 4.195 1.647 6.4 0 1.548-.368 2.9-1.839 2.9-.58 0-1.027-.23-1.664-1.004-.496-.601-1.343-1.878-2.832-4.358l-.617-1.028a44.908 44.908 0 0 0-1.255-1.98c.07-.109.141-.224.211-.327 1.12-1.667 2.118-2.602 3.358-2.602zm-10.201.553c1.265 0 2.058.791 2.675 1.446.307.327.737.871 1.234 1.579l-1.02 1.566c-.757 1.163-1.882 3.017-2.837 4.338-1.191 1.649-1.81 1.817-2.486 1.817-.524 0-1.038-.237-1.383-.794-.263-.426-.464-1.13-.464-2.046 0-2.221.63-4.535 1.66-6.088.454-.687.964-1.226 1.533-1.533a2.264 2.264 0 0 1 1.088-.285z',
tesla:
'M12 5.362l2.475-3.026s4.245.09 8.471 2.054c-1.082 1.636-3.231 2.438-3.231 2.438-.146-1.439-1.154-1.79-4.354-1.79L12 24 8.619 5.034c-3.18 0-4.188.354-4.335 1.792 0 0-2.146-.795-3.229-2.43C5.28 2.431 9.525 2.34 9.525 2.34L12 5.362l-.004.002H12v-.002zm0-3.899c3.415-.03 7.326.528 11.328 2.28.535-.968.672-1.395.672-1.395C19.625.612 15.528.015 12 0 8.472.015 4.375.61 0 2.349c0 0 .195.525.672 1.396C4.674 1.989 8.585 1.435 12 1.46v.003z',
salesforce:
'M10.006 5.415a4.195 4.195 0 013.045-1.306c1.56 0 2.954.9 3.69 2.205.63-.3 1.35-.45 2.1-.45 2.85 0 5.159 2.34 5.159 5.22s-2.31 5.22-5.176 5.22c-.345 0-.69-.044-1.02-.104a3.75 3.75 0 01-3.3 1.95c-.6 0-1.155-.15-1.65-.375A4.314 4.314 0 018.88 20.4a4.302 4.302 0 01-4.05-2.82c-.27.062-.54.076-.825.076-2.204 0-4.005-1.8-4.005-4.05 0-1.5.811-2.805 2.01-3.51-.255-.57-.39-1.2-.39-1.846 0-2.58 2.1-4.65 4.65-4.65 1.53 0 2.85.705 3.72 1.8',
github:
'M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12',
} as const
const iconPath = iconMap[iconSlug as keyof typeof iconMap]
if (!iconPath) {
return <div className='bg-muted animate-pulse rounded-sm' style={{ width: size, height: size }} />
}
return (
<svg role='img' viewBox='0 0 24 24' className='fill-black dark:fill-white' style={{ width: size, height: size }}>
<path d={iconPath} />
</svg>
)
}
// Tech companies data
const techCompanies = [
{ name: 'Shopify', id: 'shopify' },
{ name: 'Netflix', id: 'netflix' },
{ name: 'Spotify', id: 'spotify' },
{ name: 'Airbnb', id: 'airbnb' },
{ name: 'Dropbox', id: 'dropbox' },
{ name: 'Stripe', id: 'stripe' },
{ name: 'Google', id: 'google' },
{ name: 'Apple', id: 'apple' },
{ name: 'Meta', id: 'meta' },
{ name: 'Tesla', id: 'tesla' },
{ name: 'Salesforce', id: 'salesforce' },
{ name: 'GitHub', id: 'github' },
] as const
export function LogoCarousel() {
return (
<section className="pb-12 sm:pb-16 lg:pb-20 pt-12">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center">
<p className="text-sm font-medium text-muted-foreground mb-8">
Trusted by leading companies worldwide
</p>
{/* Logo Carousel with Fade Effect */}
<div className="relative">
{/* Left Fade */}
<div className="absolute left-0 top-0 bottom-0 w-20 bg-gradient-to-r from-background to-transparent z-10 pointer-events-none" />
{/* Right Fade */}
<div className="absolute right-0 top-0 bottom-0 w-20 bg-gradient-to-l from-background to-transparent z-10 pointer-events-none" />
{/* Logo Container */}
<div className="overflow-hidden">
<div className="flex animate-logo-scroll space-x-8 sm:space-x-12">
{/* First set of logos */}
{techCompanies.map((company, index) => (
<Card
key={`first-${index}`}
className="flex-shrink-0 flex items-center justify-center h-16 w-40 opacity-60 hover:opacity-100 transition-opacity duration-300 border-0 shadow-none bg-transparent"
>
<div className="flex items-center gap-3">
<SimpleIcon iconSlug={company.id} size={28} />
<span className="text-foreground text-lg font-semibold whitespace-nowrap">
{company.name}
</span>
</div>
</Card>
))}
{/* Second set for seamless loop - identical to first */}
{techCompanies.map((company, index) => (
<Card
key={`second-${index}`}
className="flex-shrink-0 flex items-center justify-center h-16 w-40 opacity-60 hover:opacity-100 transition-opacity duration-300 border-0 shadow-none bg-transparent"
>
<div className="flex items-center gap-3">
<SimpleIcon iconSlug={company.id} size={28} />
<span className="text-foreground text-lg font-semibold whitespace-nowrap">
{company.name}
</span>
</div>
</Card>
))}
</div>
</div>
</div>
</div>
</div>
</section>
)
}
+274
View File
@@ -0,0 +1,274 @@
"use client"
import { useState } from 'react'
import Link from 'next/link'
import { Menu, Github, LayoutDashboard, ChevronDown, X, Moon, Sun } from 'lucide-react'
import { Button } from '@/components/ui/button'
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
} from '@/components/ui/navigation-menu'
import {
Sheet,
SheetContent,
SheetTrigger,
SheetHeader,
SheetTitle
} from '@/components/ui/sheet'
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from '@/components/ui/collapsible'
import { Logo } from '@/components/logo'
import { MegaMenu } from '@/components/landing/mega-menu'
import { ModeToggle } from '@/components/mode-toggle'
import { useTheme } from '@/hooks/use-theme'
const navigationItems = [
{ name: 'Home', href: '#hero' },
{ name: 'Features', href: '#features' },
{ name: 'Solutions', href: '#features', hasMegaMenu: true },
{ name: 'Team', href: '#team' },
{ name: 'Pricing', href: '#pricing' },
{ name: 'FAQ', href: '#faq' },
{ name: 'Contact', href: '#contact' },
]
// Solutions menu items for mobile
const solutionsItems = [
{ title: 'Browse Products' },
{ name: 'Free Blocks', href: '#free-blocks' },
{ name: 'Premium Templates', href: '#premium-templates' },
{ name: 'Admin Dashboards', href: '#admin-dashboards' },
{ name: 'Landing Pages', href: '#landing-pages' },
{ title: 'Categories' },
{ name: 'E-commerce', href: '#ecommerce' },
{ name: 'SaaS Dashboards', href: '#saas-dashboards' },
{ name: 'Analytics', href: '#analytics' },
{ name: 'Authentication', href: '#authentication' },
{ title: 'Resources' },
{ name: 'Documentation', href: '#docs' },
{ name: 'Component Showcase', href: '#showcase' },
{ name: 'GitHub Repository', href: '#github' },
{ name: 'Design System', href: '#design-system' }
]
// Smooth scroll function
const smoothScrollTo = (targetId: string) => {
if (targetId.startsWith('#')) {
const element = document.querySelector(targetId)
if (element) {
element.scrollIntoView({
behavior: 'smooth',
block: 'start',
})
}
}
}
export function LandingNavbar() {
const [isOpen, setIsOpen] = useState(false)
const [solutionsOpen, setSolutionsOpen] = useState(false)
const { setTheme, theme } = useTheme()
return (
<header className="sticky top-0 z-50 w-full border-b bg-background/80 backdrop-blur-xl supports-[backdrop-filter]:bg-background/60">
<div className="container mx-auto px-4 sm:px-6 lg:px-8 flex h-16 items-center justify-between">
{/* Logo */}
<div className="flex items-center space-x-2">
<Link href="https://shadcnstore.com" className="flex items-center space-x-2 cursor-pointer" target='_blank' rel="noopener noreferrer">
<Logo size={32} />
<span className="font-bold">
ShadcnStore
</span>
</Link>
</div>
{/* Desktop Navigation */}
<NavigationMenu className="hidden xl:flex">
<NavigationMenuList>
{navigationItems.map((item) => (
<NavigationMenuItem key={item.name}>
{item.hasMegaMenu ? (
<>
<NavigationMenuTrigger className="bg-transparent hover:bg-transparent focus:bg-transparent data-[active]:bg-transparent data-[state=open]:bg-transparent px-4 py-2 text-sm font-medium transition-colors hover:text-primary focus:text-primary cursor-pointer">
{item.name}
</NavigationMenuTrigger>
<NavigationMenuContent>
<MegaMenu />
</NavigationMenuContent>
</>
) : (
<NavigationMenuLink
className="group inline-flex h-10 w-max items-center justify-center px-4 py-2 text-sm font-medium transition-colors hover:text-primary focus:text-primary focus:outline-none cursor-pointer"
onClick={(e: React.MouseEvent) => {
e.preventDefault()
if (item.href.startsWith('#')) {
smoothScrollTo(item.href)
} else {
window.location.href = item.href
}
}}
>
{item.name}
</NavigationMenuLink>
)}
</NavigationMenuItem>
))}
</NavigationMenuList>
</NavigationMenu>
{/* Desktop CTA */}
<div className="hidden xl:flex items-center space-x-2">
<ModeToggle variant="ghost" />
<Button variant="ghost" size="icon" asChild className="cursor-pointer">
<a href="https://github.com/silicondeck/shadcn-dashboard-landing-template" target="_blank" rel="noopener noreferrer" aria-label="GitHub Repository">
<Github className="h-5 w-5" />
</a>
</Button>
<Button variant="outline" asChild className="cursor-pointer">
<Link href="/dashboard" target="_blank" rel="noopener noreferrer">
<LayoutDashboard className="h-4 w-4 mr-2" />
Dashboard
</Link>
</Button>
<Button variant="ghost" asChild className="cursor-pointer">
<Link href="/auth/sign-in">Sign In</Link>
</Button>
<Button asChild className="cursor-pointer">
<Link href="/auth/sign-up">Get Started</Link>
</Button>
</div>
{/* Mobile Menu */}
<Sheet open={isOpen} onOpenChange={setIsOpen}>
<SheetTrigger asChild className="xl:hidden">
<Button variant="ghost" size="icon" className="cursor-pointer">
<Menu className="h-5 w-5" />
<span className="sr-only">Toggle menu</span>
</Button>
</SheetTrigger>
<SheetContent side="right" className="w-full sm:w-[400px] p-0 gap-0 [&>button]:hidden overflow-hidden flex flex-col">
<div className="flex flex-col h-full">
{/* Header */}
<SheetHeader className="space-y-0 p-4 pb-2 border-b">
<div className="flex items-center gap-2">
<div className="p-2 bg-primary/10 rounded-lg">
<Logo size={16} />
</div>
<SheetTitle className="text-lg font-semibold">ShadcnStore</SheetTitle>
<div className="ml-auto flex items-center gap-2">
<Button
variant="ghost"
size="icon"
onClick={() => setTheme(theme === "light" ? "dark" : "light")}
className="cursor-pointer h-8 w-8"
>
<Moon className="h-4 w-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Sun className="absolute h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
</Button>
<Button variant="ghost" size="icon" asChild className="cursor-pointer h-8 w-8">
<a href="https://github.com/silicondeck/shadcn-dashboard-landing-template" target="_blank" rel="noopener noreferrer" aria-label="GitHub Repository">
<Github className="h-4 w-4" />
</a>
</Button>
<Button variant="ghost" size="icon" onClick={() => setIsOpen(false)} className="cursor-pointer h-8 w-8">
<X className="h-4 w-4" />
</Button>
</div>
</div>
</SheetHeader>
{/* Navigation Links */}
<div className="flex-1 overflow-y-auto">
<nav className="p-6 space-y-1">
{navigationItems.map((item) => (
<div key={item.name}>
{item.hasMegaMenu ? (
<Collapsible open={solutionsOpen} onOpenChange={setSolutionsOpen}>
<CollapsibleTrigger className="flex items-center justify-between w-full px-4 py-3 text-base font-medium rounded-lg transition-colors hover:bg-accent hover:text-accent-foreground cursor-pointer">
{item.name}
<ChevronDown className={`h-4 w-4 transition-transform ${solutionsOpen ? 'rotate-180' : ''}`} />
</CollapsibleTrigger>
<CollapsibleContent className="pl-4 space-y-1">
{solutionsItems.map((solution, index) => (
solution.title ? (
<div
key={`title-${index}`}
className="px-4 mt-5 py-2 text-xs font-semibold text-muted-foreground/50 uppercase tracking-wider"
>
{solution.title}
</div>
) : (
<a
key={solution.name}
href={solution.href}
className="flex items-center px-4 py-2 text-sm rounded-lg transition-colors hover:bg-accent hover:text-accent-foreground cursor-pointer"
onClick={(e) => {
setIsOpen(false)
if (solution.href?.startsWith('#')) {
e.preventDefault()
setTimeout(() => smoothScrollTo(solution.href), 100)
}
}}
>
{solution.name}
</a>
)
))}
</CollapsibleContent>
</Collapsible>
) : (
<a
href={item.href}
className="flex items-center px-4 py-3 text-base font-medium rounded-lg transition-colors hover:bg-accent hover:text-accent-foreground cursor-pointer"
onClick={(e) => {
setIsOpen(false)
if (item.href.startsWith('#')) {
e.preventDefault()
setTimeout(() => smoothScrollTo(item.href), 100)
}
}}
>
{item.name}
</a>
)}
</div>
))}
</nav>
</div>
{/* Footer Actions */}
<div className="border-t p-6 space-y-4">
{/* Primary Actions */}
<div className="space-y-3">
<Button variant="outline" size="lg" asChild className="w-full cursor-pointer">
<Link href="/dashboard">
<LayoutDashboard className="size-4" />
Dashboard
</Link>
</Button>
<div className="grid grid-cols-2 gap-3">
<Button variant="outline" size="lg" asChild className="cursor-pointer">
<Link href="/auth/sign-in">Sign In</Link>
</Button>
<Button asChild size="lg" className="cursor-pointer" >
<Link href="/auth/sign-up">Get Started</Link>
</Button>
</div>
</div>
</div>
</div>
</SheetContent>
</Sheet>
</div>
</header>
)
}
@@ -0,0 +1,75 @@
"use client"
import {
Package,
Download,
Users,
Star
} from 'lucide-react'
import { Card, CardContent } from '@/components/ui/card'
import { DotPattern } from '@/components/dot-pattern'
const stats = [
{
icon: Package,
value: '500+',
label: 'Components',
description: 'Ready-to-use blocks'
},
{
icon: Download,
value: '25K+',
label: 'Downloads',
description: 'Trusted worldwide'
},
{
icon: Users,
value: '10K+',
label: 'Developers',
description: 'Active community'
},
{
icon: Star,
value: '4.9',
label: 'Rating',
description: 'User satisfaction'
}
]
export function StatsSection() {
return (
<section className="py-12 sm:py-16 relative">
{/* Background with transparency */}
<div className="absolute inset-0 bg-gradient-to-r from-primary/8 via-transparent to-secondary/20" />
<DotPattern className="opacity-75" size="md" fadeStyle="circle" />
<div className="container mx-auto px-4 sm:px-6 lg:px-8 relative">
{/* Stats Grid */}
<div className="grid grid-cols-2 lg:grid-cols-4 gap-6 md:gap-8">
{stats.map((stat, index) => (
<Card
key={index}
className="text-center bg-background/60 backdrop-blur-sm border-border/50 py-0"
>
<CardContent className="p-6">
<div className="flex justify-center mb-4">
<div className="p-3 bg-primary/10 rounded-xl">
<stat.icon className="h-6 w-6 text-primary" />
</div>
</div>
<div className="space-y-1">
<h3 className="text-2xl sm:text-3xl font-bold text-foreground">
{stat.value}
</h3>
<p className="font-semibold text-foreground">{stat.label}</p>
<p className="text-sm text-muted-foreground">{stat.description}</p>
</div>
</CardContent>
</Card>
))}
</div>
</div>
</section>
)
}
+226
View File
@@ -0,0 +1,226 @@
"use client"
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Card, CardContent } from '@/components/ui/card'
import { CardDecorator } from '@/components/ui/card-decorator'
import { Github, Linkedin, Globe } from 'lucide-react'
const team = [
{
id: 1,
name: 'Alexandra Chen',
role: 'Founder & CEO',
description: 'Former co-founder of TechFlow. Early staff at Microsoft and Google.',
image: 'https://images.unsplash.com/photo-1494790108755-2616b612b786?q=60&w=150&auto=format&fit=crop',
fallback: 'AC',
social: {
linkedin: '#',
github: '#',
website: '#'
}
},
{
id: 2,
name: 'Marcus Rodriguez',
role: 'Engineering Manager',
description: 'Lead engineering teams at Stripe, Discord, and Meta Labs.',
image: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?q=60&w=150&auto=format&fit=crop',
fallback: 'MR',
social: {
linkedin: '#',
github: '#',
website: '#'
}
},
{
id: 3,
name: 'Sophie Laurent',
role: 'Product Manager',
description: 'Former PM for Linear, Lambda School, and On Deck.',
image: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?q=60&w=150&auto=format&fit=crop',
fallback: 'SL',
social: {
linkedin: '#',
github: '#',
website: '#'
}
},
{
id: 4,
name: 'David Kim',
role: 'Frontend Developer',
description: 'Former frontend dev for Linear, Coinbase, and PostScript.',
image: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?q=60&w=150&auto=format&fit=crop',
fallback: 'DK',
social: {
linkedin: '#',
github: '#',
website: '#'
}
},
{
id: 5,
name: 'Emma Thompson',
role: 'Backend Developer',
description: 'Lead backend dev at Clearbit. Former Clearbit and Loom.',
image: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?q=60&w=150&auto=format&fit=crop',
fallback: 'ET',
social: {
linkedin: '#',
github: '#',
website: '#'
}
},
{
id: 6,
name: 'Ryan Mitchell',
role: 'Product Designer',
description: 'Founding design team at Figma. Former Pleo, Stripe, and Tile.',
image: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?q=60&w=150&auto=format&fit=crop',
fallback: 'RM',
social: {
linkedin: '#',
github: '#',
website: '#'
}
},
{
id: 7,
name: 'James Anderson',
role: 'UX Researcher',
description: 'Lead user research for Slack. Contractor for Netflix and Udacity.',
image: 'https://images.unsplash.com/photo-1566492031773-4f4e44671d66?q=60&w=150&auto=format&fit=crop',
fallback: 'JA',
social: {
linkedin: '#',
github: '#',
website: '#'
}
},
{
id: 8,
name: 'Isabella Garcia',
role: 'Customer Success',
description: 'Lead CX at Wealthsimple. Former PagerDuty and Squreen.',
image: 'https://images.unsplash.com/photo-1580489944761-15a19d654956?q=60&w=150&auto=format&fit=crop',
fallback: 'IG',
social: {
linkedin: '#',
github: '#',
website: '#'
}
}
]
export function TeamSection() {
return (
<section id="team" className="py-24 sm:py-32">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
{/* Section Header */}
<div className="mx-auto max-w-4xl text-center mb-16">
<Badge variant="outline" className="mb-4">
Our Team
</Badge>
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl mb-6">
Meet our team
</h2>
<p className="text-lg text-muted-foreground mb-8">
We are a passionate team of innovators, builders, and problem-solvers dedicated to creating exceptional digital experiences that make a difference.
</p>
</div>
{/* Team Grid */}
<div className="grid grid-cols-1 gap-x-8 gap-y-12 sm:grid-cols-2 xl:grid-cols-4">
{team.map((member) => (
<Card key={member.id} className="shadow-xs py-2">
<CardContent className="p-4">
<div className="text-center">
{/* Avatar */}
<div className="flex justify-center mb-4">
<CardDecorator>
<Avatar className="h-24 w-24 border shadow-lg">
<AvatarImage
src={member.image}
alt={member.name}
className="object-cover"
/>
<AvatarFallback className="text-lg font-semibold">
{member.fallback}
</AvatarFallback>
</Avatar>
</CardDecorator>
</div>
{/* Name and Role */}
<h3 className="text-lg font-semibold text-foreground mb-1">
{member.name}
</h3>
<p className="text-sm font-medium text-primary mb-3">
{member.role}
</p>
{/* Description */}
<p className="text-sm text-muted-foreground mb-4 leading-relaxed">
{member.description}
</p>
{/* Social Links */}
<div className="flex items-center justify-center gap-3">
<Button
variant="ghost"
size="icon"
className="h-8 w-8 cursor-pointer hover:text-primary"
asChild
>
<a
href={member.social.linkedin}
target="_blank"
rel="noopener noreferrer"
aria-label={`${member.name} LinkedIn`}
>
<Linkedin className="h-4 w-4" />
</a>
</Button>
<Button
variant="ghost"
size="icon"
className="h-8 w-8 cursor-pointer hover:text-primary"
asChild
>
<a
href={member.social.github}
target="_blank"
rel="noopener noreferrer"
aria-label={`${member.name} GitHub`}
>
<Github className="h-4 w-4" />
</a>
</Button>
<Button
variant="ghost"
size="icon"
className="h-8 w-8 cursor-pointer hover:text-primary"
asChild
>
<a
href={member.social.website}
target="_blank"
rel="noopener noreferrer"
aria-label={`${member.name} Website`}
>
<Globe className="h-4 w-4" />
</a>
</Button>
</div>
</div>
</CardContent>
</Card>
))}
</div>
</div>
</section>
)
}
@@ -0,0 +1,153 @@
"use client"
import { Card, CardContent } from '@/components/ui/card'
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Badge } from '@/components/ui/badge'
type Testimonial = {
name: string
role: string
image: string
quote: string
}
const testimonials: Testimonial[] = [
{
name: 'Alexandra Mitchell',
role: 'Senior Frontend Developer',
image: 'https://notion-avatars.netlify.app/api/avatar?preset=female-1',
quote:
'This platform has completely transformed our development workflow. The component system is so well-architected that even complex applications feel simple to build.',
},
{
name: 'James Thompson',
role: 'Technical Lead',
image: 'https://notion-avatars.netlify.app/api/avatar?preset=male-1',
quote: 'After trying countless frameworks, this is the one that finally clicked. The documentation is exceptional.',
},
{
name: 'Priya Sharma',
role: 'Product Designer',
image: 'https://notion-avatars.netlify.app/api/avatar?preset=female-2',
quote:
'The design system is beautiful and consistent. I can prototype ideas quickly and hand them off to developers with confidence that the implementation will match perfectly.',
},
{
name: 'Robert Kim',
role: 'Engineering Manager',
image: 'https://notion-avatars.netlify.app/api/avatar?preset=male-2',
quote:
'We migrated our entire application to this platform in just two weeks. The performance improvements were immediate.',
},
{
name: 'Maria Santos',
role: 'Full Stack Engineer',
image: 'https://notion-avatars.netlify.app/api/avatar?preset=female-3',
quote:
'The accessibility features are top-notch. Building inclusive applications has never been easier. Every component follows best practices out of the box, and the automated testing suite ensures we maintain high accessibility standards throughout our development process.',
},
{
name: 'Thomas Anderson',
role: 'Solutions Architect',
image: 'https://notion-avatars.netlify.app/api/avatar?preset=male-3',
quote: 'Scalability was our biggest concern, but this platform handles enterprise-level complexity with ease.',
},
{
name: 'Lisa Chang',
role: 'UX Researcher',
image: 'https://notion-avatars.netlify.app/api/avatar?preset=female-4',
quote:
'User testing results have been consistently positive since we adopted this platform. The user experience is intuitive and the performance is stellar. Our user satisfaction scores have increased by 40% since the migration.',
},
{
name: 'Michael Foster',
role: 'DevOps Engineer',
image: 'https://notion-avatars.netlify.app/api/avatar?preset=male-4',
quote: 'Deployment and maintenance are a breeze. The platform integrates seamlessly with our CI/CD pipeline.',
},
{
name: 'Sophie Laurent',
role: 'Creative Director',
image: 'https://notion-avatars.netlify.app/api/avatar?preset=female-5',
quote:
'The creative possibilities are endless. We can bring any design concept to life without compromising on technical quality or user experience.',
},
{
name: 'Daniel Wilson',
role: 'Backend Developer',
image: 'https://notion-avatars.netlify.app/api/avatar?preset=male-5',
quote: 'The API design is exceptional. Clean, intuitive, and well-documented.',
},
{
name: 'Natasha Petrov',
role: 'Mobile App Developer',
image: 'https://notion-avatars.netlify.app/api/avatar?preset=female-6',
quote:
'Cross-platform development has never been this efficient. One codebase, multiple platforms, consistent user experience. This is the future. The responsive design system ensures our apps look perfect on every device.',
},
{
name: 'Carlos Rivera',
role: 'Startup Founder',
image: 'https://notion-avatars.netlify.app/api/avatar?preset=male-6',
quote: 'As a non-technical founder, this platform gave me the confidence to build our MVP quickly.',
},
]
export function TestimonialsSection() {
return (
<section id="testimonials" className="py-24 sm:py-32">
<div className="container mx-auto px-8 sm:px-6">
{/* Section Header */}
<div className="mx-auto max-w-2xl text-center mb-16">
<Badge variant="outline" className="mb-4">Testimonials</Badge>
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl mb-4">
Empowering Innovation Worldwide
</h2>
<p className="text-lg text-muted-foreground">
Join thousands of developers and teams who trust our platform to build exceptional digital experiences.
</p>
</div>
{/* Testimonials Masonry Grid */}
<div className="columns-1 gap-4 md:columns-2 md:gap-6 lg:columns-3 lg:gap-4">
{testimonials.map((testimonial, index) => (
<Card key={index} className="mb-6 break-inside-avoid shadow-none lg:mb-4">
<CardContent>
<div className="flex items-start gap-4">
<Avatar className="bg-muted size-12 shrink-0">
<AvatarImage
alt={testimonial.name}
src={testimonial.image}
loading="lazy"
width="120"
height="120"
/>
<AvatarFallback>
{testimonial.name
.split(' ')
.map(n => n[0])
.join('')}
</AvatarFallback>
</Avatar>
<div className="min-w-0 flex-1">
<a href="#" onClick={e => e.preventDefault()} className="cursor-pointer">
<h3 className="font-medium hover:text-primary transition-colors">{testimonial.name}</h3>
</a>
<span className="text-muted-foreground block text-sm tracking-wide">
{testimonial.role}
</span>
</div>
</div>
<blockquote className="mt-4">
<p className="text-sm leading-relaxed text-balance">{testimonial.quote}</p>
</blockquote>
</CardContent>
</Card>
))}
</div>
</div>
</section>
)
}