@cimplify/sdk 0.40.0 → 0.40.1
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/dist/mock/cli.mjs +30 -6
- package/dist/mock/library.js +30 -6
- package/dist/mock/library.mjs +30 -6
- package/dist/mock/msw.js +30 -6
- package/dist/mock/msw.mjs +30 -6
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/templates/storefront-retail/app/categories/[slug]/page.tsx +49 -37
- package/templates/storefront-retail/app/collections/[slug]/page.tsx +48 -36
- package/templates/storefront-retail/app/page.tsx +166 -24
- package/templates/storefront-retail/app/shop/page.tsx +36 -3
- package/templates/storefront-retail/app/shop/shop-client.tsx +6 -1
- package/templates/storefront-retail/components/brand-marquee.tsx +36 -0
- package/templates/storefront-retail/components/category-tiles.tsx +104 -0
- package/templates/storefront-retail/components/feature-hero.tsx +83 -0
- package/templates/storefront-retail/components/newsletter.tsx +52 -0
- package/templates/storefront-retail/components/promo-banner.tsx +44 -0
- package/templates/storefront-retail/components/section-heading.tsx +37 -0
- package/templates/storefront-retail/components/trade-in-cta.tsx +60 -0
- package/templates/storefront-retail/components/trust-bar.tsx +26 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
|
|
5
|
+
export function Newsletter() {
|
|
6
|
+
const [email, setEmail] = useState("");
|
|
7
|
+
const [submitted, setSubmitted] = useState(false);
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<section className="max-w-7xl mx-auto px-6 sm:px-8 py-14 sm:py-20">
|
|
11
|
+
<div className="rounded-3xl border border-border bg-card p-8 sm:p-12 grid grid-cols-1 lg:grid-cols-2 gap-8 items-center">
|
|
12
|
+
<div>
|
|
13
|
+
<p className="text-[11px] font-mono uppercase tracking-[0.16em] text-primary mb-2">
|
|
14
|
+
The shortlist
|
|
15
|
+
</p>
|
|
16
|
+
<h2 className="text-[clamp(1.5rem,3vw,2rem)] font-bold m-0 mb-3 -tracking-[0.025em]">
|
|
17
|
+
New drops, real prices, in your inbox.
|
|
18
|
+
</h2>
|
|
19
|
+
<p className="text-muted-foreground leading-relaxed">
|
|
20
|
+
One email a week. Curated launches, our actual price (not the
|
|
21
|
+
launch price), and the deals worth knowing about. No newsletter
|
|
22
|
+
chaff.
|
|
23
|
+
</p>
|
|
24
|
+
</div>
|
|
25
|
+
<form
|
|
26
|
+
onSubmit={(e) => {
|
|
27
|
+
e.preventDefault();
|
|
28
|
+
setSubmitted(true);
|
|
29
|
+
}}
|
|
30
|
+
className="flex flex-col sm:flex-row gap-2"
|
|
31
|
+
>
|
|
32
|
+
<input
|
|
33
|
+
type="email"
|
|
34
|
+
required
|
|
35
|
+
value={email}
|
|
36
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
37
|
+
placeholder="you@email.com"
|
|
38
|
+
disabled={submitted}
|
|
39
|
+
className="flex-1 px-4 py-3 rounded-md bg-background border border-border focus:border-primary focus:ring-2 focus:ring-primary/20 outline-none transition-shadow text-sm disabled:opacity-50"
|
|
40
|
+
/>
|
|
41
|
+
<button
|
|
42
|
+
type="submit"
|
|
43
|
+
disabled={submitted}
|
|
44
|
+
className="inline-flex items-center justify-center gap-2 px-5 py-3 rounded-md bg-foreground text-background font-semibold text-sm hover:bg-primary transition-colors disabled:opacity-50"
|
|
45
|
+
>
|
|
46
|
+
{submitted ? "Subscribed ✓" : "Subscribe"}
|
|
47
|
+
</button>
|
|
48
|
+
</form>
|
|
49
|
+
</div>
|
|
50
|
+
</section>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import Link from "next/link";
|
|
2
|
+
|
|
3
|
+
interface PromoBannerProps {
|
|
4
|
+
badge: string;
|
|
5
|
+
title: string;
|
|
6
|
+
body: string;
|
|
7
|
+
cta: { label: string; href: string };
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Full-width promo banner — featured deal / launch / season campaign.
|
|
12
|
+
* Bold geometric background, mono-spaced detail labels.
|
|
13
|
+
*/
|
|
14
|
+
export function PromoBanner({ badge, title, body, cta }: PromoBannerProps) {
|
|
15
|
+
return (
|
|
16
|
+
<section className="max-w-7xl mx-auto px-6 sm:px-8 py-6">
|
|
17
|
+
<div className="relative overflow-hidden rounded-3xl bg-gradient-to-br from-primary via-primary to-foreground text-primary-foreground p-8 sm:p-12 lg:p-16">
|
|
18
|
+
<div className="absolute -top-20 -right-20 w-72 h-72 rounded-full bg-background/10 blur-3xl pointer-events-none" />
|
|
19
|
+
<div className="absolute -bottom-32 -left-20 w-96 h-96 rounded-full bg-foreground/30 blur-3xl pointer-events-none" />
|
|
20
|
+
<div className="relative grid grid-cols-1 lg:grid-cols-[1fr_auto] gap-8 items-center">
|
|
21
|
+
<div className="max-w-2xl">
|
|
22
|
+
<span className="inline-flex items-center gap-2 mb-4 px-3 py-1 rounded-full bg-background/15 border border-background/25 text-[11px] font-mono uppercase tracking-[0.16em]">
|
|
23
|
+
<span className="w-1.5 h-1.5 rounded-full bg-background animate-pulse" />
|
|
24
|
+
{badge}
|
|
25
|
+
</span>
|
|
26
|
+
<h2 className="text-[clamp(1.75rem,3.5vw,2.75rem)] font-bold m-0 mb-3 -tracking-[0.025em] leading-[1.1]">
|
|
27
|
+
{title}
|
|
28
|
+
</h2>
|
|
29
|
+
<p className="text-base sm:text-lg opacity-90 leading-relaxed">{body}</p>
|
|
30
|
+
</div>
|
|
31
|
+
<Link
|
|
32
|
+
href={cta.href}
|
|
33
|
+
className="inline-flex items-center gap-2 px-5 py-3 rounded-md bg-background text-foreground font-semibold text-sm hover:bg-background/90 transition-colors whitespace-nowrap"
|
|
34
|
+
>
|
|
35
|
+
{cta.label}
|
|
36
|
+
<svg viewBox="0 0 12 12" className="w-3 h-3" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden>
|
|
37
|
+
<path d="M3 6h7m0 0L7 3m3 3L7 9" strokeLinecap="round" strokeLinejoin="round" />
|
|
38
|
+
</svg>
|
|
39
|
+
</Link>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</section>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import Link from "next/link";
|
|
2
|
+
|
|
3
|
+
interface SectionHeadingProps {
|
|
4
|
+
eyebrow: string;
|
|
5
|
+
title: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
link?: { label: string; href: string };
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function SectionHeading({ eyebrow, title, description, link }: SectionHeadingProps) {
|
|
11
|
+
return (
|
|
12
|
+
<div className="flex items-end justify-between gap-6 mb-8">
|
|
13
|
+
<div className="max-w-2xl">
|
|
14
|
+
<p className="text-[11px] font-mono uppercase tracking-[0.16em] text-primary mb-2">
|
|
15
|
+
{eyebrow}
|
|
16
|
+
</p>
|
|
17
|
+
<h2 className="text-[clamp(1.75rem,3vw,2.25rem)] font-bold m-0 -tracking-[0.025em]">
|
|
18
|
+
{title}
|
|
19
|
+
</h2>
|
|
20
|
+
{description && (
|
|
21
|
+
<p className="mt-2 text-muted-foreground">{description}</p>
|
|
22
|
+
)}
|
|
23
|
+
</div>
|
|
24
|
+
{link && (
|
|
25
|
+
<Link
|
|
26
|
+
href={link.href}
|
|
27
|
+
className="text-sm font-semibold text-primary hover:underline whitespace-nowrap hidden sm:inline-flex items-center gap-1"
|
|
28
|
+
>
|
|
29
|
+
{link.label}
|
|
30
|
+
<svg viewBox="0 0 12 12" className="w-3 h-3" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden>
|
|
31
|
+
<path d="M3 6h7m0 0L7 3m3 3L7 9" strokeLinecap="round" strokeLinejoin="round" />
|
|
32
|
+
</svg>
|
|
33
|
+
</Link>
|
|
34
|
+
)}
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import Link from "next/link";
|
|
2
|
+
|
|
3
|
+
export function TradeInCta() {
|
|
4
|
+
return (
|
|
5
|
+
<section className="max-w-7xl mx-auto px-6 sm:px-8 py-14 sm:py-20">
|
|
6
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 items-center bg-foreground text-background rounded-3xl p-8 sm:p-12 lg:p-14 overflow-hidden relative">
|
|
7
|
+
<div className="absolute top-0 right-0 w-1/2 h-full opacity-[0.04] [background-image:linear-gradient(135deg,white_1px,transparent_1px)] [background-size:24px_24px] pointer-events-none" />
|
|
8
|
+
<div>
|
|
9
|
+
<p className="text-[11px] font-mono uppercase tracking-[0.16em] text-primary-foreground/70 mb-3">
|
|
10
|
+
Trade-in programme
|
|
11
|
+
</p>
|
|
12
|
+
<h2 className="text-[clamp(1.75rem,3.5vw,2.5rem)] font-bold m-0 mb-4 -tracking-[0.025em] leading-[1.1]">
|
|
13
|
+
Last year's phone, this year's discount.
|
|
14
|
+
</h2>
|
|
15
|
+
<p className="text-background/75 leading-relaxed mb-6">
|
|
16
|
+
Send us your iPhone, Galaxy, or MacBook. We'll quote within
|
|
17
|
+
48 hours and credit the value toward your next purchase. Devices
|
|
18
|
+
head to certified refurbishers across the continent — yours stays
|
|
19
|
+
in service for years more.
|
|
20
|
+
</p>
|
|
21
|
+
<div className="flex flex-wrap items-center gap-3">
|
|
22
|
+
<Link
|
|
23
|
+
href="/about"
|
|
24
|
+
className="inline-flex items-center gap-2 px-5 py-2.5 rounded-md bg-primary text-primary-foreground font-semibold text-sm hover:bg-primary/90 transition-colors"
|
|
25
|
+
>
|
|
26
|
+
Get a quote
|
|
27
|
+
<svg viewBox="0 0 12 12" className="w-3 h-3" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden>
|
|
28
|
+
<path d="M3 6h7m0 0L7 3m3 3L7 9" strokeLinecap="round" strokeLinejoin="round" />
|
|
29
|
+
</svg>
|
|
30
|
+
</Link>
|
|
31
|
+
<Link
|
|
32
|
+
href="/faq"
|
|
33
|
+
className="inline-flex items-center gap-2 px-5 py-2.5 rounded-md border border-background/25 hover:bg-background/10 transition-colors text-sm font-medium"
|
|
34
|
+
>
|
|
35
|
+
How it works
|
|
36
|
+
</Link>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
<div className="grid grid-cols-3 gap-3">
|
|
40
|
+
{[
|
|
41
|
+
{ step: "01", title: "Tell us what you have", body: "Model + condition + photos. 2 minutes." },
|
|
42
|
+
{ step: "02", title: "Ship it free", body: "Drop at our store or book a free pickup." },
|
|
43
|
+
{ step: "03", title: "Get credited", body: "Within 48 hours, in store credit or Mobile Money." },
|
|
44
|
+
].map((s) => (
|
|
45
|
+
<div
|
|
46
|
+
key={s.step}
|
|
47
|
+
className="rounded-2xl p-4 sm:p-5 bg-background/5 border border-background/10"
|
|
48
|
+
>
|
|
49
|
+
<p className="text-[10px] font-mono text-primary tabular-nums mb-3">{s.step}</p>
|
|
50
|
+
<p className="text-[13px] sm:text-sm font-semibold mb-1.5 -tracking-[0.015em]">
|
|
51
|
+
{s.title}
|
|
52
|
+
</p>
|
|
53
|
+
<p className="text-[11px] sm:text-xs text-background/65 leading-snug">{s.body}</p>
|
|
54
|
+
</div>
|
|
55
|
+
))}
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</section>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
interface TrustBarProps {
|
|
2
|
+
items: { label: string; value: string; description: string; icon: React.ReactNode }[];
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function TrustBar({ items }: TrustBarProps) {
|
|
6
|
+
return (
|
|
7
|
+
<section className="border-y border-border bg-card">
|
|
8
|
+
<div className="max-w-7xl mx-auto px-6 sm:px-8 py-10 grid grid-cols-2 md:grid-cols-4 gap-x-6 gap-y-8">
|
|
9
|
+
{items.map((it) => (
|
|
10
|
+
<div key={it.label} className="flex items-start gap-3">
|
|
11
|
+
<div className="grid place-items-center w-10 h-10 rounded-lg bg-primary/10 text-primary shrink-0">
|
|
12
|
+
{it.icon}
|
|
13
|
+
</div>
|
|
14
|
+
<div className="min-w-0">
|
|
15
|
+
<p className="text-[10px] font-mono uppercase tracking-[0.16em] text-muted-foreground mb-0.5">
|
|
16
|
+
{it.label}
|
|
17
|
+
</p>
|
|
18
|
+
<p className="text-base font-semibold -tracking-[0.015em] mb-0.5">{it.value}</p>
|
|
19
|
+
<p className="text-xs text-muted-foreground leading-snug">{it.description}</p>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
))}
|
|
23
|
+
</div>
|
|
24
|
+
</section>
|
|
25
|
+
);
|
|
26
|
+
}
|