kofi-stack-template-generator 2.1.51 → 2.1.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +6 -6
- package/dist/index.js +1906 -146
- package/package.json +2 -2
- package/src/generator.ts +9 -0
- package/src/templates.generated.ts +51 -5
- package/templates/marketing/astro/astro.config.ts.hbs +12 -0
- package/templates/marketing/astro/package.json.hbs +31 -0
- package/templates/marketing/astro/postcss.config.mjs.hbs +5 -0
- package/templates/marketing/astro/public/favicon.svg +4 -0
- package/templates/marketing/astro/public/media/hero-bg.png +1 -0
- package/templates/marketing/astro/src/components/Footer.astro +167 -0
- package/templates/marketing/astro/src/components/Header.astro +378 -0
- package/templates/marketing/astro/src/components/Logo.astro +30 -0
- package/templates/marketing/astro/src/components/ThemeSelector.astro +64 -0
- package/templates/marketing/astro/src/components/blocks/BentoFeatures.astro +209 -0
- package/templates/marketing/astro/src/components/blocks/FeatureShowcase.astro +102 -0
- package/templates/marketing/astro/src/components/blocks/FinalCTA.astro +82 -0
- package/templates/marketing/astro/src/components/blocks/IndustryTabs.astro +177 -0
- package/templates/marketing/astro/src/components/blocks/LogoBanner.astro +95 -0
- package/templates/marketing/astro/src/components/blocks/PricingTable.astro +176 -0
- package/templates/marketing/astro/src/components/blocks/ProofBanner.astro +56 -0
- package/templates/marketing/astro/src/components/blocks/TestimonialsGrid.astro +106 -0
- package/templates/marketing/astro/src/components/blocks/TrustColumns.astro +88 -0
- package/templates/marketing/astro/src/components/heros/AnimatedMockup.astro +711 -0
- package/templates/marketing/astro/src/components/heros/ProductShowcaseHero.astro +111 -0
- package/templates/marketing/astro/src/layouts/Layout.astro +37 -0
- package/templates/marketing/astro/src/lib/utils.ts +6 -0
- package/templates/marketing/astro/src/pages/index.astro +163 -0
- package/templates/marketing/astro/src/styles/globals.css.hbs +353 -0
- package/templates/marketing/astro/tsconfig.json.hbs +11 -0
- package/templates/marketing/nextjs/package.json.hbs +6 -1
- package/templates/marketing/nextjs/src/app/layout.tsx.hbs +19 -5
- package/templates/marketing/nextjs/src/app/page.tsx.hbs +160 -164
- package/templates/marketing/nextjs/src/components/Footer/index.tsx +188 -0
- package/templates/marketing/nextjs/src/components/Header/MegaMenu.tsx +117 -0
- package/templates/marketing/nextjs/src/components/Header/MobileMenu.tsx +178 -0
- package/templates/marketing/nextjs/src/components/Header/index.tsx +172 -0
- package/templates/marketing/nextjs/src/components/Logo.tsx +46 -0
- package/templates/marketing/nextjs/src/components/ThemeProvider.tsx +8 -0
- package/templates/marketing/nextjs/src/components/ThemeSelector.tsx +69 -0
- package/templates/marketing/nextjs/src/components/blocks/BentoFeatures.tsx +249 -0
- package/templates/marketing/nextjs/src/components/blocks/FeatureShowcase.tsx +110 -0
- package/templates/marketing/nextjs/src/components/blocks/FinalCTA.tsx +91 -0
- package/templates/marketing/nextjs/src/components/blocks/IndustryTabs.tsx +137 -0
- package/templates/marketing/nextjs/src/components/blocks/LogoBanner.tsx +80 -0
- package/templates/marketing/nextjs/src/components/blocks/PricingTable.tsx +210 -0
- package/templates/marketing/nextjs/src/components/blocks/ProofBanner.tsx +72 -0
- package/templates/marketing/nextjs/src/components/blocks/TestimonialsGrid.tsx +119 -0
- package/templates/marketing/nextjs/src/components/blocks/TrustColumns.tsx +110 -0
- package/templates/marketing/nextjs/src/components/blocks/index.ts +9 -0
- package/templates/marketing/nextjs/src/components/heros/AnimatedMockup.tsx +242 -0
- package/templates/marketing/nextjs/src/components/heros/ProductShowcaseHero.tsx +84 -0
- package/templates/marketing/nextjs/src/components/heros/index.ts +2 -0
- package/templates/marketing/nextjs/src/lib/utils.ts +6 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@repo/marketing",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "astro dev --port 3000",
|
|
8
|
+
"build": "astro build",
|
|
9
|
+
"preview": "astro preview",
|
|
10
|
+
"astro": "astro",
|
|
11
|
+
"lint": "biome check .",
|
|
12
|
+
"lint:fix": "biome check --write .",
|
|
13
|
+
"typecheck": "astro check && tsc --noEmit"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"astro": "^5.1.6",
|
|
17
|
+
"lucide-astro": "^0.468.0",
|
|
18
|
+
"clsx": "^2.1.1",
|
|
19
|
+
"tailwind-merge": "^2.6.0"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@astrojs/check": "^0.9.4",
|
|
23
|
+
"@astrojs/tailwind": "^6.0.2",
|
|
24
|
+
"@repo/config-typescript": "workspace:*",
|
|
25
|
+
"@types/node": "^20.0.0",
|
|
26
|
+
"tailwindcss": "^4.0.0",
|
|
27
|
+
"@tailwindcss/postcss": "^4.0.0",
|
|
28
|
+
"postcss": "^8.4.0",
|
|
29
|
+
"typescript": "^5.0.0"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
|
2
|
+
<rect width="32" height="32" rx="6" fill="#0a0a0a"/>
|
|
3
|
+
<path d="M17.33 5L9 18.67h8L16 27l9-12h-8l1-10z" fill="none" stroke="#fafafa" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
4
|
+
</svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
placeholder
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
---
|
|
2
|
+
import Logo from "./Logo.astro"
|
|
3
|
+
import ThemeSelector from "./ThemeSelector.astro"
|
|
4
|
+
|
|
5
|
+
const footerColumns = [
|
|
6
|
+
{
|
|
7
|
+
title: "Product",
|
|
8
|
+
links: [
|
|
9
|
+
{ label: "Home", href: "/" },
|
|
10
|
+
{ label: "Pricing", href: "/pricing" },
|
|
11
|
+
{ label: "Integrations", href: "/features/integrations" },
|
|
12
|
+
],
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
title: "Resources",
|
|
16
|
+
links: [
|
|
17
|
+
{ label: "Blog", href: "/blog" },
|
|
18
|
+
{ label: "Documentation", href: "/docs" },
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
title: "Company",
|
|
23
|
+
links: [
|
|
24
|
+
{ label: "About", href: "/about" },
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
title: "Legal",
|
|
29
|
+
links: [
|
|
30
|
+
{ label: "Privacy", href: "/privacy" },
|
|
31
|
+
{ label: "Terms", href: "/terms" },
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
const socialLinks = {
|
|
37
|
+
twitter: "https://x.com/saasify",
|
|
38
|
+
linkedin: "https://linkedin.com/company/saasify",
|
|
39
|
+
github: "https://github.com/saasify",
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const bottomLinks = [
|
|
43
|
+
{ label: "Contact Support", href: "/support" },
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
const currentYear = new Date().getFullYear()
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
<footer class="mt-auto border-t border-border bg-background">
|
|
50
|
+
<!-- Main Footer Content -->
|
|
51
|
+
<div class="container mx-auto px-4 py-12 lg:py-16">
|
|
52
|
+
<div class="grid grid-cols-2 gap-8 md:grid-cols-3 lg:grid-cols-6">
|
|
53
|
+
<!-- Link Columns -->
|
|
54
|
+
{footerColumns.map((column) => (
|
|
55
|
+
<div class="col-span-1">
|
|
56
|
+
<h3 class="mb-4 text-sm font-medium text-foreground">
|
|
57
|
+
{column.title}
|
|
58
|
+
</h3>
|
|
59
|
+
<ul class="space-y-3">
|
|
60
|
+
{column.links.map((link) => (
|
|
61
|
+
<li>
|
|
62
|
+
<a
|
|
63
|
+
href={link.href}
|
|
64
|
+
class="text-sm text-muted-foreground transition-colors hover:text-foreground"
|
|
65
|
+
>
|
|
66
|
+
{link.label}
|
|
67
|
+
</a>
|
|
68
|
+
</li>
|
|
69
|
+
))}
|
|
70
|
+
</ul>
|
|
71
|
+
</div>
|
|
72
|
+
))}
|
|
73
|
+
|
|
74
|
+
<!-- Newsletter Column -->
|
|
75
|
+
<div class="col-span-2 md:col-span-3 lg:col-span-2">
|
|
76
|
+
<h3 class="mb-4 text-sm font-medium text-foreground">
|
|
77
|
+
Newsletter
|
|
78
|
+
</h3>
|
|
79
|
+
<p class="mb-4 text-sm text-muted-foreground">
|
|
80
|
+
Get product updates, tips, and insights delivered weekly.
|
|
81
|
+
</p>
|
|
82
|
+
<form class="flex gap-2">
|
|
83
|
+
<input
|
|
84
|
+
type="email"
|
|
85
|
+
placeholder="Enter your email"
|
|
86
|
+
class="flex-1 px-3 py-2 text-sm rounded-md border border-input bg-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
87
|
+
/>
|
|
88
|
+
<button
|
|
89
|
+
type="submit"
|
|
90
|
+
class="px-4 py-2 text-sm font-medium rounded-md bg-primary text-primary-foreground hover:bg-primary/90"
|
|
91
|
+
>
|
|
92
|
+
Subscribe
|
|
93
|
+
</button>
|
|
94
|
+
</form>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
<!-- Social Links -->
|
|
99
|
+
<div class="mt-10 flex items-center gap-4 border-t border-border pt-8">
|
|
100
|
+
<a
|
|
101
|
+
href={socialLinks.twitter}
|
|
102
|
+
target="_blank"
|
|
103
|
+
rel="noopener noreferrer"
|
|
104
|
+
class="text-muted-foreground transition-colors hover:text-foreground"
|
|
105
|
+
aria-label="X (Twitter)"
|
|
106
|
+
>
|
|
107
|
+
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
|
108
|
+
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
|
|
109
|
+
</svg>
|
|
110
|
+
</a>
|
|
111
|
+
<a
|
|
112
|
+
href={socialLinks.linkedin}
|
|
113
|
+
target="_blank"
|
|
114
|
+
rel="noopener noreferrer"
|
|
115
|
+
class="text-muted-foreground transition-colors hover:text-foreground"
|
|
116
|
+
aria-label="LinkedIn"
|
|
117
|
+
>
|
|
118
|
+
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
|
119
|
+
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" />
|
|
120
|
+
</svg>
|
|
121
|
+
</a>
|
|
122
|
+
<a
|
|
123
|
+
href={socialLinks.github}
|
|
124
|
+
target="_blank"
|
|
125
|
+
rel="noopener noreferrer"
|
|
126
|
+
class="text-muted-foreground transition-colors hover:text-foreground"
|
|
127
|
+
aria-label="GitHub"
|
|
128
|
+
>
|
|
129
|
+
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
|
130
|
+
<path
|
|
131
|
+
fill-rule="evenodd"
|
|
132
|
+
d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"
|
|
133
|
+
clip-rule="evenodd"
|
|
134
|
+
/>
|
|
135
|
+
</svg>
|
|
136
|
+
</a>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
<!-- Bottom Bar -->
|
|
141
|
+
<div class="border-t border-border">
|
|
142
|
+
<div class="container mx-auto flex flex-col items-center justify-between gap-4 px-4 py-6 sm:flex-row">
|
|
143
|
+
<!-- Logo and Copyright -->
|
|
144
|
+
<div class="flex items-center gap-4">
|
|
145
|
+
<a href="/" class="flex items-center">
|
|
146
|
+
<Logo class="h-6 w-6" />
|
|
147
|
+
</a>
|
|
148
|
+
<p class="text-sm text-muted-foreground">
|
|
149
|
+
© {currentYear} SaaSify
|
|
150
|
+
</p>
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
<!-- Bottom Links and Theme Selector -->
|
|
154
|
+
<div class="flex items-center gap-6">
|
|
155
|
+
{bottomLinks.map((link) => (
|
|
156
|
+
<a
|
|
157
|
+
href={link.href}
|
|
158
|
+
class="text-sm text-muted-foreground transition-colors hover:text-foreground"
|
|
159
|
+
>
|
|
160
|
+
{link.label}
|
|
161
|
+
</a>
|
|
162
|
+
))}
|
|
163
|
+
<ThemeSelector />
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
</footer>
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
---
|
|
2
|
+
import Logo from "./Logo.astro"
|
|
3
|
+
import { ChevronDown, Menu, X, Layout, BarChart3, Shield, Zap, Layers, Target, Rocket, Settings } from "lucide-astro"
|
|
4
|
+
|
|
5
|
+
// Navigation data structure matching SaaSify
|
|
6
|
+
const productMenu = {
|
|
7
|
+
label: "Product",
|
|
8
|
+
columns: [
|
|
9
|
+
{
|
|
10
|
+
title: "Core Features",
|
|
11
|
+
items: [
|
|
12
|
+
{ label: "Integrations", description: "Connect with 100+ tools you already use", href: "/features/integrations", icon: "layout" },
|
|
13
|
+
{ label: "Analytics", description: "Real-time insights and reporting dashboards", href: "/features/analytics", icon: "barChart" },
|
|
14
|
+
{ label: "Security", description: "Enterprise-grade protection and compliance", href: "/features/security", icon: "shield" },
|
|
15
|
+
],
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
title: "Productivity",
|
|
19
|
+
items: [
|
|
20
|
+
{ label: "Dashboard", description: "Unified command center for your team", href: "/features/dashboard", icon: "layout" },
|
|
21
|
+
{ label: "Automation", description: "Streamline repetitive tasks instantly", href: "/features/automation", icon: "zap" },
|
|
22
|
+
{ label: "Workflows", description: "Build custom processes without code", href: "/features/workflows", icon: "layers" },
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const solutionsMenu = {
|
|
29
|
+
label: "Solutions",
|
|
30
|
+
columns: [
|
|
31
|
+
{
|
|
32
|
+
title: "By Team",
|
|
33
|
+
items: [
|
|
34
|
+
{ label: "Sales Teams", description: "Close deals faster with smart tools", href: "/use-cases/sales", icon: "target" },
|
|
35
|
+
{ label: "Marketing Teams", description: "Launch campaigns that convert", href: "/use-cases/marketing", icon: "rocket" },
|
|
36
|
+
{ label: "Product Teams", description: "Ship features users love", href: "/use-cases/product", icon: "layers" },
|
|
37
|
+
{ label: "Operations", description: "Scale without the growing pains", href: "/use-cases/operations", icon: "settings" },
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const navLinks = [
|
|
44
|
+
{ label: "Pricing", href: "/pricing" },
|
|
45
|
+
{ label: "Blog", href: "/blog" },
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
const ctaLinks = [
|
|
49
|
+
{ label: "Sign In", href: "/sign-in", variant: "ghost" },
|
|
50
|
+
{ label: "Get Started", href: "/sign-up", variant: "default" },
|
|
51
|
+
]
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
<header class="sticky top-0 z-50 border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
|
55
|
+
<div class="container mx-auto px-4 h-16 flex justify-between items-center">
|
|
56
|
+
<!-- Left section: Logo + Nav -->
|
|
57
|
+
<div class="flex items-center gap-8">
|
|
58
|
+
<a href="/" class="flex items-center gap-2">
|
|
59
|
+
<Logo />
|
|
60
|
+
<span class="text-xl font-semibold hidden sm:inline">SaaSify</span>
|
|
61
|
+
</a>
|
|
62
|
+
|
|
63
|
+
<!-- Desktop navigation -->
|
|
64
|
+
<nav class="hidden lg:flex items-center gap-1">
|
|
65
|
+
<!-- Product Menu -->
|
|
66
|
+
<div class="mega-menu-trigger relative" data-menu="product">
|
|
67
|
+
<button
|
|
68
|
+
type="button"
|
|
69
|
+
class="flex items-center gap-1 px-4 py-2 text-sm font-medium text-muted-foreground hover:text-foreground transition-colors"
|
|
70
|
+
>
|
|
71
|
+
{productMenu.label}
|
|
72
|
+
<ChevronDown class="h-4 w-4 transition-transform mega-chevron" />
|
|
73
|
+
</button>
|
|
74
|
+
<div class="mega-menu-dropdown absolute left-0 top-full pt-2 opacity-0 -translate-y-2 pointer-events-none transition-all">
|
|
75
|
+
<div class="bg-background border border-border rounded-lg shadow-lg p-6 min-w-[480px]">
|
|
76
|
+
<div class="grid gap-8 grid-cols-2">
|
|
77
|
+
{productMenu.columns.map((column) => (
|
|
78
|
+
<div>
|
|
79
|
+
<h3 class="text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-4">
|
|
80
|
+
{column.title}
|
|
81
|
+
</h3>
|
|
82
|
+
<ul class="space-y-1">
|
|
83
|
+
{column.items.map((item) => (
|
|
84
|
+
<li>
|
|
85
|
+
<a
|
|
86
|
+
href={item.href}
|
|
87
|
+
class="flex items-start gap-3 p-3 rounded-lg hover:bg-muted transition-colors group"
|
|
88
|
+
>
|
|
89
|
+
<div class="flex h-10 w-10 shrink-0 items-center justify-center rounded-md bg-muted group-hover:bg-background">
|
|
90
|
+
{item.icon === "layout" && <Layout class="h-5 w-5 text-primary" />}
|
|
91
|
+
{item.icon === "barChart" && <BarChart3 class="h-5 w-5 text-primary" />}
|
|
92
|
+
{item.icon === "shield" && <Shield class="h-5 w-5 text-primary" />}
|
|
93
|
+
{item.icon === "zap" && <Zap class="h-5 w-5 text-primary" />}
|
|
94
|
+
{item.icon === "layers" && <Layers class="h-5 w-5 text-primary" />}
|
|
95
|
+
</div>
|
|
96
|
+
<div>
|
|
97
|
+
<div class="text-sm font-medium text-foreground">{item.label}</div>
|
|
98
|
+
<div class="text-xs text-muted-foreground mt-0.5">{item.description}</div>
|
|
99
|
+
</div>
|
|
100
|
+
</a>
|
|
101
|
+
</li>
|
|
102
|
+
))}
|
|
103
|
+
</ul>
|
|
104
|
+
</div>
|
|
105
|
+
))}
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<!-- Solutions Menu -->
|
|
112
|
+
<div class="mega-menu-trigger relative" data-menu="solutions">
|
|
113
|
+
<button
|
|
114
|
+
type="button"
|
|
115
|
+
class="flex items-center gap-1 px-4 py-2 text-sm font-medium text-muted-foreground hover:text-foreground transition-colors"
|
|
116
|
+
>
|
|
117
|
+
{solutionsMenu.label}
|
|
118
|
+
<ChevronDown class="h-4 w-4 transition-transform mega-chevron" />
|
|
119
|
+
</button>
|
|
120
|
+
<div class="mega-menu-dropdown absolute left-0 top-full pt-2 opacity-0 -translate-y-2 pointer-events-none transition-all">
|
|
121
|
+
<div class="bg-background border border-border rounded-lg shadow-lg p-6 min-w-[320px]">
|
|
122
|
+
<div class="grid gap-8 grid-cols-1">
|
|
123
|
+
{solutionsMenu.columns.map((column) => (
|
|
124
|
+
<div>
|
|
125
|
+
<h3 class="text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-4">
|
|
126
|
+
{column.title}
|
|
127
|
+
</h3>
|
|
128
|
+
<ul class="space-y-1">
|
|
129
|
+
{column.items.map((item) => (
|
|
130
|
+
<li>
|
|
131
|
+
<a
|
|
132
|
+
href={item.href}
|
|
133
|
+
class="flex items-start gap-3 p-3 rounded-lg hover:bg-muted transition-colors group"
|
|
134
|
+
>
|
|
135
|
+
<div class="flex h-10 w-10 shrink-0 items-center justify-center rounded-md bg-muted group-hover:bg-background">
|
|
136
|
+
{item.icon === "target" && <Target class="h-5 w-5 text-primary" />}
|
|
137
|
+
{item.icon === "rocket" && <Rocket class="h-5 w-5 text-primary" />}
|
|
138
|
+
{item.icon === "layers" && <Layers class="h-5 w-5 text-primary" />}
|
|
139
|
+
{item.icon === "settings" && <Settings class="h-5 w-5 text-primary" />}
|
|
140
|
+
</div>
|
|
141
|
+
<div>
|
|
142
|
+
<div class="text-sm font-medium text-foreground">{item.label}</div>
|
|
143
|
+
<div class="text-xs text-muted-foreground mt-0.5">{item.description}</div>
|
|
144
|
+
</div>
|
|
145
|
+
</a>
|
|
146
|
+
</li>
|
|
147
|
+
))}
|
|
148
|
+
</ul>
|
|
149
|
+
</div>
|
|
150
|
+
))}
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
|
|
156
|
+
{navLinks.map((link) => (
|
|
157
|
+
<a
|
|
158
|
+
href={link.href}
|
|
159
|
+
class="px-4 py-2 text-sm font-medium text-muted-foreground hover:text-foreground transition-colors"
|
|
160
|
+
>
|
|
161
|
+
{link.label}
|
|
162
|
+
</a>
|
|
163
|
+
))}
|
|
164
|
+
</nav>
|
|
165
|
+
</div>
|
|
166
|
+
|
|
167
|
+
<!-- Right section: CTAs -->
|
|
168
|
+
<div class="flex items-center gap-3">
|
|
169
|
+
<!-- Desktop CTAs -->
|
|
170
|
+
<div class="hidden lg:flex items-center gap-3">
|
|
171
|
+
{ctaLinks.map((link) => (
|
|
172
|
+
<a
|
|
173
|
+
href={link.href}
|
|
174
|
+
class:list={[
|
|
175
|
+
"px-4 py-2 text-sm font-medium rounded-md transition-colors",
|
|
176
|
+
link.variant === "default"
|
|
177
|
+
? "bg-primary text-primary-foreground hover:bg-primary/90"
|
|
178
|
+
: "text-muted-foreground hover:text-foreground"
|
|
179
|
+
]}
|
|
180
|
+
>
|
|
181
|
+
{link.label}
|
|
182
|
+
</a>
|
|
183
|
+
))}
|
|
184
|
+
</div>
|
|
185
|
+
|
|
186
|
+
<!-- Mobile: Primary CTA + Hamburger -->
|
|
187
|
+
<a
|
|
188
|
+
href="/sign-up"
|
|
189
|
+
class="lg:hidden px-4 py-2 text-sm font-medium rounded-md bg-primary text-primary-foreground hover:bg-primary/90"
|
|
190
|
+
>
|
|
191
|
+
Get Started
|
|
192
|
+
</a>
|
|
193
|
+
|
|
194
|
+
<button
|
|
195
|
+
type="button"
|
|
196
|
+
id="mobile-menu-toggle"
|
|
197
|
+
class="lg:hidden p-2 text-muted-foreground hover:text-foreground"
|
|
198
|
+
aria-label="Toggle menu"
|
|
199
|
+
>
|
|
200
|
+
<Menu class="h-6 w-6 menu-open-icon" />
|
|
201
|
+
<X class="h-6 w-6 menu-close-icon hidden" />
|
|
202
|
+
</button>
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
</header>
|
|
206
|
+
|
|
207
|
+
<!-- Mobile Menu Overlay -->
|
|
208
|
+
<div id="mobile-menu" class="fixed inset-0 top-16 z-50 bg-background hidden lg:hidden">
|
|
209
|
+
<nav class="overflow-y-auto max-h-[calc(100vh-4rem)]">
|
|
210
|
+
<!-- Product Section -->
|
|
211
|
+
<div class="mobile-section border-b border-border" data-section="product">
|
|
212
|
+
<button
|
|
213
|
+
type="button"
|
|
214
|
+
class="flex items-center justify-between w-full px-4 py-3 text-sm font-medium"
|
|
215
|
+
>
|
|
216
|
+
Product
|
|
217
|
+
<ChevronDown class="h-4 w-4 transition-transform section-chevron" />
|
|
218
|
+
</button>
|
|
219
|
+
<div class="mobile-section-content hidden px-4 pb-4 space-y-4">
|
|
220
|
+
{productMenu.columns.map((column) => (
|
|
221
|
+
<div>
|
|
222
|
+
<h4 class="text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-2">
|
|
223
|
+
{column.title}
|
|
224
|
+
</h4>
|
|
225
|
+
<ul class="space-y-1">
|
|
226
|
+
{column.items.map((item) => (
|
|
227
|
+
<li>
|
|
228
|
+
<a href={item.href} class="flex items-center gap-3 p-2 rounded-lg hover:bg-muted">
|
|
229
|
+
{item.icon === "layout" && <Layout class="h-4 w-4 text-primary" />}
|
|
230
|
+
{item.icon === "barChart" && <BarChart3 class="h-4 w-4 text-primary" />}
|
|
231
|
+
{item.icon === "shield" && <Shield class="h-4 w-4 text-primary" />}
|
|
232
|
+
{item.icon === "zap" && <Zap class="h-4 w-4 text-primary" />}
|
|
233
|
+
{item.icon === "layers" && <Layers class="h-4 w-4 text-primary" />}
|
|
234
|
+
<span class="text-sm">{item.label}</span>
|
|
235
|
+
</a>
|
|
236
|
+
</li>
|
|
237
|
+
))}
|
|
238
|
+
</ul>
|
|
239
|
+
</div>
|
|
240
|
+
))}
|
|
241
|
+
</div>
|
|
242
|
+
</div>
|
|
243
|
+
|
|
244
|
+
<!-- Solutions Section -->
|
|
245
|
+
<div class="mobile-section border-b border-border" data-section="solutions">
|
|
246
|
+
<button
|
|
247
|
+
type="button"
|
|
248
|
+
class="flex items-center justify-between w-full px-4 py-3 text-sm font-medium"
|
|
249
|
+
>
|
|
250
|
+
Solutions
|
|
251
|
+
<ChevronDown class="h-4 w-4 transition-transform section-chevron" />
|
|
252
|
+
</button>
|
|
253
|
+
<div class="mobile-section-content hidden px-4 pb-4 space-y-4">
|
|
254
|
+
{solutionsMenu.columns.map((column) => (
|
|
255
|
+
<div>
|
|
256
|
+
<h4 class="text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-2">
|
|
257
|
+
{column.title}
|
|
258
|
+
</h4>
|
|
259
|
+
<ul class="space-y-1">
|
|
260
|
+
{column.items.map((item) => (
|
|
261
|
+
<li>
|
|
262
|
+
<a href={item.href} class="flex items-center gap-3 p-2 rounded-lg hover:bg-muted">
|
|
263
|
+
{item.icon === "target" && <Target class="h-4 w-4 text-primary" />}
|
|
264
|
+
{item.icon === "rocket" && <Rocket class="h-4 w-4 text-primary" />}
|
|
265
|
+
{item.icon === "layers" && <Layers class="h-4 w-4 text-primary" />}
|
|
266
|
+
{item.icon === "settings" && <Settings class="h-4 w-4 text-primary" />}
|
|
267
|
+
<span class="text-sm">{item.label}</span>
|
|
268
|
+
</a>
|
|
269
|
+
</li>
|
|
270
|
+
))}
|
|
271
|
+
</ul>
|
|
272
|
+
</div>
|
|
273
|
+
))}
|
|
274
|
+
</div>
|
|
275
|
+
</div>
|
|
276
|
+
|
|
277
|
+
<!-- Simple nav links -->
|
|
278
|
+
{navLinks.map((link) => (
|
|
279
|
+
<a
|
|
280
|
+
href={link.href}
|
|
281
|
+
class="flex items-center px-4 py-3 text-sm font-medium border-b border-border hover:bg-muted"
|
|
282
|
+
>
|
|
283
|
+
{link.label}
|
|
284
|
+
</a>
|
|
285
|
+
))}
|
|
286
|
+
|
|
287
|
+
<!-- CTA links -->
|
|
288
|
+
<div class="p-4 space-y-2">
|
|
289
|
+
{ctaLinks.map((link) => (
|
|
290
|
+
<a
|
|
291
|
+
href={link.href}
|
|
292
|
+
class:list={[
|
|
293
|
+
"flex items-center justify-center w-full px-4 py-3 text-sm font-medium rounded-md transition-colors",
|
|
294
|
+
link.variant === "default"
|
|
295
|
+
? "bg-primary text-primary-foreground hover:bg-primary/90"
|
|
296
|
+
: "border border-border hover:bg-muted"
|
|
297
|
+
]}
|
|
298
|
+
>
|
|
299
|
+
{link.label}
|
|
300
|
+
</a>
|
|
301
|
+
))}
|
|
302
|
+
</div>
|
|
303
|
+
</nav>
|
|
304
|
+
</div>
|
|
305
|
+
|
|
306
|
+
<script>
|
|
307
|
+
function initHeader() {
|
|
308
|
+
// Desktop mega menu
|
|
309
|
+
const megaMenuTriggers = document.querySelectorAll('.mega-menu-trigger')
|
|
310
|
+
megaMenuTriggers.forEach((trigger) => {
|
|
311
|
+
const dropdown = trigger.querySelector('.mega-menu-dropdown')
|
|
312
|
+
const chevron = trigger.querySelector('.mega-chevron')
|
|
313
|
+
|
|
314
|
+
trigger.addEventListener('mouseenter', () => {
|
|
315
|
+
dropdown?.classList.remove('opacity-0', '-translate-y-2', 'pointer-events-none')
|
|
316
|
+
dropdown?.classList.add('opacity-100', 'translate-y-0', 'pointer-events-auto')
|
|
317
|
+
chevron?.classList.add('rotate-180')
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
trigger.addEventListener('mouseleave', () => {
|
|
321
|
+
dropdown?.classList.add('opacity-0', '-translate-y-2', 'pointer-events-none')
|
|
322
|
+
dropdown?.classList.remove('opacity-100', 'translate-y-0', 'pointer-events-auto')
|
|
323
|
+
chevron?.classList.remove('rotate-180')
|
|
324
|
+
})
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
// Mobile menu toggle
|
|
328
|
+
const mobileToggle = document.getElementById('mobile-menu-toggle')
|
|
329
|
+
const mobileMenu = document.getElementById('mobile-menu')
|
|
330
|
+
const openIcon = mobileToggle?.querySelector('.menu-open-icon')
|
|
331
|
+
const closeIcon = mobileToggle?.querySelector('.menu-close-icon')
|
|
332
|
+
|
|
333
|
+
mobileToggle?.addEventListener('click', () => {
|
|
334
|
+
const isOpen = !mobileMenu?.classList.contains('hidden')
|
|
335
|
+
if (isOpen) {
|
|
336
|
+
mobileMenu?.classList.add('hidden')
|
|
337
|
+
openIcon?.classList.remove('hidden')
|
|
338
|
+
closeIcon?.classList.add('hidden')
|
|
339
|
+
} else {
|
|
340
|
+
mobileMenu?.classList.remove('hidden')
|
|
341
|
+
openIcon?.classList.add('hidden')
|
|
342
|
+
closeIcon?.classList.remove('hidden')
|
|
343
|
+
}
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
// Mobile sections toggle
|
|
347
|
+
const mobileSections = document.querySelectorAll('.mobile-section')
|
|
348
|
+
mobileSections.forEach((section) => {
|
|
349
|
+
const button = section.querySelector('button')
|
|
350
|
+
const content = section.querySelector('.mobile-section-content')
|
|
351
|
+
const chevron = section.querySelector('.section-chevron')
|
|
352
|
+
|
|
353
|
+
button?.addEventListener('click', () => {
|
|
354
|
+
const isOpen = !content?.classList.contains('hidden')
|
|
355
|
+
if (isOpen) {
|
|
356
|
+
content?.classList.add('hidden')
|
|
357
|
+
chevron?.classList.remove('rotate-180')
|
|
358
|
+
} else {
|
|
359
|
+
content?.classList.remove('hidden')
|
|
360
|
+
chevron?.classList.add('rotate-180')
|
|
361
|
+
}
|
|
362
|
+
})
|
|
363
|
+
})
|
|
364
|
+
|
|
365
|
+
// Close mobile menu on link click
|
|
366
|
+
const mobileLinks = mobileMenu?.querySelectorAll('a')
|
|
367
|
+
mobileLinks?.forEach((link) => {
|
|
368
|
+
link.addEventListener('click', () => {
|
|
369
|
+
mobileMenu?.classList.add('hidden')
|
|
370
|
+
openIcon?.classList.remove('hidden')
|
|
371
|
+
closeIcon?.classList.add('hidden')
|
|
372
|
+
})
|
|
373
|
+
})
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
initHeader()
|
|
377
|
+
document.addEventListener('astro:after-swap', initHeader)
|
|
378
|
+
</script>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
class?: string
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const { class: className } = Astro.props
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<div class:list={["flex h-8 w-8 items-center justify-center rounded-lg bg-foreground logo-container", className]}>
|
|
10
|
+
<svg
|
|
11
|
+
class="h-5 w-5 text-background"
|
|
12
|
+
viewBox="0 0 24 24"
|
|
13
|
+
fill="none"
|
|
14
|
+
stroke="currentColor"
|
|
15
|
+
stroke-width="2"
|
|
16
|
+
stroke-linecap="round"
|
|
17
|
+
stroke-linejoin="round"
|
|
18
|
+
>
|
|
19
|
+
<path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"></path>
|
|
20
|
+
</svg>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<style>
|
|
24
|
+
:global([data-theme="dark"]) .logo-container {
|
|
25
|
+
background-color: white;
|
|
26
|
+
}
|
|
27
|
+
:global([data-theme="dark"]) .logo-container svg {
|
|
28
|
+
color: #0a0a0a;
|
|
29
|
+
}
|
|
30
|
+
</style>
|