nextworks 0.2.0-alpha.2 → 0.2.0-alpha.21
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/README.md +280 -228
- package/dist/cli_manifests/blocks_manifest.json +193 -194
- package/dist/commands/blocks.d.ts +3 -0
- package/dist/commands/blocks.d.ts.map +1 -1
- package/dist/commands/blocks.js +128 -19
- package/dist/commands/blocks.js.map +1 -1
- package/dist/commands/doctor.d.ts +136 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +696 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/remove-blocks.d.ts +4 -1
- package/dist/commands/remove-blocks.d.ts.map +1 -1
- package/dist/commands/remove-blocks.js +24 -6
- package/dist/commands/remove-blocks.js.map +1 -1
- package/dist/index.js +125 -4
- package/dist/index.js.map +1 -1
- package/dist/kits/blocks/.nextworks/docs/BLOCKS_QUICKSTART.md +104 -194
- package/dist/kits/blocks/.nextworks/docs/BLOCKS_README.md +115 -75
- package/dist/kits/blocks/.nextworks/docs/THEME_GUIDE.md +269 -251
- package/dist/kits/blocks/app/templates/digitalagency/PresetThemeVars.tsx +80 -80
- package/dist/kits/blocks/app/templates/digitalagency/README.md +42 -36
- package/dist/kits/blocks/app/templates/digitalagency/components/About.tsx +71 -99
- package/dist/kits/blocks/app/templates/digitalagency/components/CTA.tsx +40 -74
- package/dist/kits/blocks/app/templates/digitalagency/components/Contact.tsx +123 -227
- package/dist/kits/blocks/app/templates/digitalagency/components/Footer.tsx +89 -89
- package/dist/kits/blocks/app/templates/digitalagency/components/Hero.tsx +83 -90
- package/dist/kits/blocks/app/templates/digitalagency/components/Navbar.tsx +121 -168
- package/dist/kits/blocks/app/templates/digitalagency/components/NetworkPattern.tsx +288 -297
- package/dist/kits/blocks/app/templates/digitalagency/components/Portfolio.tsx +157 -157
- package/dist/kits/blocks/app/templates/digitalagency/components/Pricing.tsx +114 -114
- package/dist/kits/blocks/app/templates/digitalagency/components/Process.tsx +59 -59
- package/dist/kits/blocks/app/templates/digitalagency/components/Services.tsx +55 -55
- package/dist/kits/blocks/app/templates/digitalagency/components/Team.tsx +28 -28
- package/dist/kits/blocks/app/templates/digitalagency/components/Testimonials.tsx +65 -65
- package/dist/kits/blocks/app/templates/digitalagency/page.tsx +38 -38
- package/dist/kits/blocks/app/templates/gallery/PresetThemeVars.tsx +130 -85
- package/dist/kits/blocks/app/templates/gallery/page.tsx +357 -303
- package/dist/kits/blocks/app/templates/productlaunch/PresetThemeVars.tsx +75 -74
- package/dist/kits/blocks/app/templates/productlaunch/README.md +62 -55
- package/dist/kits/blocks/app/templates/productlaunch/components/About.tsx +84 -178
- package/dist/kits/blocks/app/templates/productlaunch/components/CTA.tsx +50 -93
- package/dist/kits/blocks/app/templates/productlaunch/components/Contact.tsx +231 -231
- package/dist/kits/blocks/app/templates/productlaunch/components/FAQ.tsx +86 -93
- package/dist/kits/blocks/app/templates/productlaunch/components/Features.tsx +83 -84
- package/dist/kits/blocks/app/templates/productlaunch/components/Footer.tsx +132 -132
- package/dist/kits/blocks/app/templates/productlaunch/components/Hero.tsx +88 -89
- package/dist/kits/blocks/app/templates/productlaunch/components/Navbar.tsx +116 -162
- package/dist/kits/blocks/app/templates/productlaunch/components/Pricing.tsx +106 -106
- package/dist/kits/blocks/app/templates/productlaunch/components/ProcessTimeline.tsx +110 -110
- package/dist/kits/blocks/app/templates/productlaunch/components/ServicesGrid.tsx +68 -68
- package/dist/kits/blocks/app/templates/productlaunch/components/Team.tsx +104 -104
- package/dist/kits/blocks/app/templates/productlaunch/components/Testimonials.tsx +90 -89
- package/dist/kits/blocks/app/templates/productlaunch/components/TrustBadges.tsx +76 -76
- package/dist/kits/blocks/app/templates/productlaunch/page.tsx +43 -43
- package/dist/kits/blocks/app/templates/saasdashboard/PresetThemeVars.tsx +80 -80
- package/dist/kits/blocks/app/templates/saasdashboard/README.md +44 -38
- package/dist/kits/blocks/app/templates/saasdashboard/components/Contact.tsx +129 -176
- package/dist/kits/blocks/app/templates/saasdashboard/components/Dashboard.tsx +293 -293
- package/dist/kits/blocks/app/templates/saasdashboard/components/FAQ.tsx +55 -55
- package/dist/kits/blocks/app/templates/saasdashboard/components/Features.tsx +90 -91
- package/dist/kits/blocks/app/templates/saasdashboard/components/Footer.tsx +77 -77
- package/dist/kits/blocks/app/templates/saasdashboard/components/Hero.tsx +104 -105
- package/dist/kits/blocks/app/templates/saasdashboard/components/Hero_mask.tsx +126 -127
- package/dist/kits/blocks/app/templates/saasdashboard/components/Navbar.tsx +117 -159
- package/dist/kits/blocks/app/templates/saasdashboard/components/Pricing.tsx +90 -90
- package/dist/kits/blocks/app/templates/saasdashboard/components/SmoothScroll.tsx +96 -97
- package/dist/kits/blocks/app/templates/saasdashboard/components/Testimonials.tsx +72 -72
- package/dist/kits/blocks/app/templates/saasdashboard/components/TrustBadges.tsx +53 -53
- package/dist/kits/blocks/app/templates/saasdashboard/page.tsx +39 -39
- package/dist/kits/blocks/components/enhanced-theme-provider.tsx +195 -183
- package/dist/kits/blocks/components/providers/BlocksAppProviders.tsx +27 -27
- package/dist/kits/blocks/components/sections/About.tsx +291 -291
- package/dist/kits/blocks/components/sections/CTA.tsx +257 -258
- package/dist/kits/blocks/components/sections/CommandShowcase.tsx +517 -0
- package/dist/kits/blocks/components/sections/Contact.tsx +267 -267
- package/dist/kits/blocks/components/sections/FAQ.tsx +214 -225
- package/dist/kits/blocks/components/sections/FeaturedProjectShowcase.tsx +687 -0
- package/dist/kits/blocks/components/sections/Features.tsx +268 -270
- package/dist/kits/blocks/components/sections/Footer.tsx +302 -302
- package/dist/kits/blocks/components/sections/HeroMotion.tsx +308 -308
- package/dist/kits/blocks/components/sections/HeroOverlay.tsx +358 -358
- package/dist/kits/blocks/components/sections/HeroProductDemo.tsx +246 -0
- package/dist/kits/blocks/components/sections/HeroSplit.tsx +352 -352
- package/dist/kits/blocks/components/sections/HeroWithVideo.tsx +495 -0
- package/dist/kits/blocks/components/sections/Navbar.tsx +352 -353
- package/dist/kits/blocks/components/sections/PortfolioSimple.tsx +549 -550
- package/dist/kits/blocks/components/sections/Pricing.tsx +264 -264
- package/dist/kits/blocks/components/sections/ProcessTimeline.tsx +325 -325
- package/dist/kits/blocks/components/sections/ProjectDeepDive.tsx +805 -0
- package/dist/kits/blocks/components/sections/SelectedWorkRail.tsx +485 -0
- package/dist/kits/blocks/components/sections/ServicesGrid.tsx +210 -210
- package/dist/kits/blocks/components/sections/Team.tsx +309 -309
- package/dist/kits/blocks/components/sections/Testimonials.tsx +158 -158
- package/dist/kits/blocks/components/sections/TrustBadges.tsx +162 -162
- package/dist/kits/blocks/components/sections/product-demo/ApprovalInboxPanel.tsx +128 -0
- package/dist/kits/blocks/components/sections/product-demo/DemoStage.tsx +519 -0
- package/dist/kits/blocks/components/sections/product-demo/DemoWindow.tsx +140 -0
- package/dist/kits/blocks/components/sections/product-demo/KnowledgePanel.tsx +130 -0
- package/dist/kits/blocks/components/sections/product-demo/RunConsolePanel.tsx +430 -0
- package/dist/kits/blocks/components/sections/product-demo/TaskListPanel.tsx +302 -0
- package/dist/kits/blocks/components/sections/product-demo/WorkflowStudioPanel.tsx +744 -0
- package/dist/kits/blocks/components/sections/product-demo/types.ts +262 -0
- package/dist/kits/blocks/components/theme-provider.tsx +1 -34
- package/dist/kits/blocks/components/ui/alert-dialog.tsx +134 -134
- package/dist/kits/blocks/components/ui/brand-node.tsx +121 -121
- package/dist/kits/blocks/components/ui/button.tsx +122 -122
- package/dist/kits/blocks/components/ui/card.tsx +95 -95
- package/dist/kits/blocks/components/ui/checkbox.tsx +30 -30
- package/dist/kits/blocks/components/ui/cta-button.tsx +125 -125
- package/dist/kits/blocks/components/ui/dropdown-menu.tsx +201 -201
- package/dist/kits/blocks/components/ui/feature-card.tsx +91 -91
- package/dist/kits/blocks/components/ui/input.tsx +27 -27
- package/dist/kits/blocks/components/ui/label.tsx +29 -29
- package/dist/kits/blocks/components/ui/pricing-card.tsx +120 -120
- package/dist/kits/blocks/components/ui/select.tsx +25 -25
- package/dist/kits/blocks/components/ui/skeleton.tsx +13 -13
- package/dist/kits/blocks/components/ui/table.tsx +98 -98
- package/dist/kits/blocks/components/ui/testimonial-card.tsx +108 -108
- package/dist/kits/blocks/components/ui/textarea.tsx +26 -26
- package/dist/kits/blocks/components/ui/theme-selector.tsx +243 -247
- package/dist/kits/blocks/components/ui/theme-toggle.tsx +74 -74
- package/dist/kits/blocks/components/ui/toaster.tsx +7 -7
- package/dist/kits/blocks/lib/themes.ts +400 -400
- package/dist/kits/blocks/lib/utils.ts +6 -9
- package/dist/kits/blocks/package-deps.json +40 -28
- package/dist/kits/blocks/tsconfig.json +11 -0
- package/dist/kits/blocks/tsconfig.tsbuildinfo +1 -0
- package/dist/utils/file-operations.d.ts +3 -1
- package/dist/utils/file-operations.d.ts.map +1 -1
- package/dist/utils/file-operations.js +84 -12
- package/dist/utils/file-operations.js.map +1 -1
- package/dist/utils/installation-tracker.d.ts +2 -2
- package/dist/utils/installation-tracker.d.ts.map +1 -1
- package/dist/utils/installation-tracker.js +11 -11
- package/dist/utils/installation-tracker.js.map +1 -1
- package/dist/utils/package-manager.d.ts +6 -0
- package/dist/utils/package-manager.d.ts.map +1 -0
- package/dist/utils/package-manager.js +58 -0
- package/dist/utils/package-manager.js.map +1 -0
- package/dist/utils/yarn-pnp.d.ts +6 -0
- package/dist/utils/yarn-pnp.d.ts.map +1 -0
- package/dist/utils/yarn-pnp.js +39 -0
- package/dist/utils/yarn-pnp.js.map +1 -0
- package/package.json +5 -2
- package/dist/kits/blocks/notes/THEME_GUIDE.md +0 -29
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import Image from "next/image";
|
|
3
|
+
import Link from "next/link";
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
|
|
6
|
+
export type SelectedWorkRailLayout = "grid" | "rail";
|
|
7
|
+
|
|
8
|
+
export interface SelectedWorkRailImage {
|
|
9
|
+
src: string;
|
|
10
|
+
alt?: string;
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface SelectedWorkRailVideo {
|
|
15
|
+
src: string;
|
|
16
|
+
poster?: string;
|
|
17
|
+
title?: string;
|
|
18
|
+
ariaLabel?: string;
|
|
19
|
+
className?: string;
|
|
20
|
+
autoPlay?: boolean;
|
|
21
|
+
muted?: boolean;
|
|
22
|
+
loop?: boolean;
|
|
23
|
+
playsInline?: boolean;
|
|
24
|
+
controls?: boolean;
|
|
25
|
+
preload?: "none" | "metadata" | "auto";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface SelectedWorkRailTag {
|
|
29
|
+
label: string;
|
|
30
|
+
className?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface SelectedWorkRailItem {
|
|
34
|
+
id?: string;
|
|
35
|
+
title: React.ReactNode;
|
|
36
|
+
label?: React.ReactNode;
|
|
37
|
+
description?: React.ReactNode;
|
|
38
|
+
href?: string;
|
|
39
|
+
ariaLabel?: string;
|
|
40
|
+
image?: string | SelectedWorkRailImage;
|
|
41
|
+
video?: string | SelectedWorkRailVideo;
|
|
42
|
+
poster?: string;
|
|
43
|
+
tags?: Array<string | SelectedWorkRailTag>;
|
|
44
|
+
visual?: React.ReactNode;
|
|
45
|
+
className?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface SelectedWorkRailClassNames {
|
|
49
|
+
section?: string;
|
|
50
|
+
backgroundGlow?: string;
|
|
51
|
+
container?: string;
|
|
52
|
+
header?: string;
|
|
53
|
+
eyebrow?: string;
|
|
54
|
+
title?: string;
|
|
55
|
+
description?: string;
|
|
56
|
+
rail?: string;
|
|
57
|
+
item?: string;
|
|
58
|
+
featuredItem?: string;
|
|
59
|
+
itemInner?: string;
|
|
60
|
+
itemLink?: string;
|
|
61
|
+
media?: string;
|
|
62
|
+
image?: string;
|
|
63
|
+
video?: string;
|
|
64
|
+
placeholder?: string;
|
|
65
|
+
content?: string;
|
|
66
|
+
label?: string;
|
|
67
|
+
itemTitle?: string;
|
|
68
|
+
itemDescription?: string;
|
|
69
|
+
tags?: string;
|
|
70
|
+
tag?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface SelectedWorkRailProps {
|
|
74
|
+
id?: string;
|
|
75
|
+
className?: string;
|
|
76
|
+
eyebrow?: React.ReactNode;
|
|
77
|
+
title?: React.ReactNode;
|
|
78
|
+
description?: React.ReactNode;
|
|
79
|
+
items?: SelectedWorkRailItem[];
|
|
80
|
+
layout?: SelectedWorkRailLayout;
|
|
81
|
+
featuredIndex?: number;
|
|
82
|
+
ariaLabel?: string;
|
|
83
|
+
titleId?: string;
|
|
84
|
+
enableMotion?: boolean;
|
|
85
|
+
classNames?: SelectedWorkRailClassNames;
|
|
86
|
+
section?: { className?: string };
|
|
87
|
+
container?: { className?: string };
|
|
88
|
+
header?: { className?: string };
|
|
89
|
+
railSlot?: { className?: string };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const defaultItems: SelectedWorkRailItem[] = [
|
|
93
|
+
{
|
|
94
|
+
title: "Product launch",
|
|
95
|
+
label: "Launch page",
|
|
96
|
+
description: "A focused launch story with space for benefits, proof, and a clear next step.",
|
|
97
|
+
tags: ["Hero", "Proof", "CTA"],
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
title: "Dashboard preview",
|
|
101
|
+
label: "Product UI",
|
|
102
|
+
description: "A visual product tile for showing interface direction or feature depth.",
|
|
103
|
+
tags: ["Dashboard", "Preview"],
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
title: "Marketing site",
|
|
107
|
+
label: "Website",
|
|
108
|
+
description: "A services or company page with room for work, process, and credibility.",
|
|
109
|
+
tags: ["Services", "Portfolio"],
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
title: "Workflow demo",
|
|
113
|
+
label: "Product story",
|
|
114
|
+
description: "A short walkthrough-style item for explaining a process or automation flow.",
|
|
115
|
+
tags: ["Workflow", "Demo"],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
title: "Template gallery",
|
|
119
|
+
label: "Showcase",
|
|
120
|
+
description: "A compact gallery item for grouping related examples or visual variants.",
|
|
121
|
+
tags: ["Gallery", "Sections"],
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
title: "Developer tool",
|
|
125
|
+
label: "Project",
|
|
126
|
+
description: "A technical project tile for showing setup flow, docs, or implementation notes.",
|
|
127
|
+
tags: ["Tooling", "Docs"],
|
|
128
|
+
},
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
function normalizeMediaImage(
|
|
132
|
+
image: SelectedWorkRailItem["image"],
|
|
133
|
+
): SelectedWorkRailImage | undefined {
|
|
134
|
+
if (!image) {
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return typeof image === "string" ? { src: image } : image;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function normalizeMediaVideo(
|
|
142
|
+
video: SelectedWorkRailItem["video"],
|
|
143
|
+
poster?: string,
|
|
144
|
+
): SelectedWorkRailVideo | undefined {
|
|
145
|
+
if (!video) {
|
|
146
|
+
return undefined;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return typeof video === "string" ? { src: video, poster } : { ...video, poster: video.poster ?? poster };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function normalizeTag(tag: string | SelectedWorkRailTag): SelectedWorkRailTag {
|
|
153
|
+
return typeof tag === "string" ? { label: tag } : tag;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function renderVisual(
|
|
157
|
+
item: SelectedWorkRailItem,
|
|
158
|
+
classNames?: SelectedWorkRailClassNames,
|
|
159
|
+
) {
|
|
160
|
+
if (item.visual) {
|
|
161
|
+
return item.visual;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const video = normalizeMediaVideo(item.video, item.poster);
|
|
165
|
+
|
|
166
|
+
if (video?.src) {
|
|
167
|
+
return (
|
|
168
|
+
<video
|
|
169
|
+
src={video.src}
|
|
170
|
+
poster={video.poster}
|
|
171
|
+
title={video.title ?? video.ariaLabel ?? "Selected work preview video"}
|
|
172
|
+
aria-label={video.ariaLabel ?? video.title ?? "Selected work preview video"}
|
|
173
|
+
className={cn("size-full object-cover", classNames?.video, video.className)}
|
|
174
|
+
autoPlay={video.autoPlay ?? true}
|
|
175
|
+
muted={video.muted ?? true}
|
|
176
|
+
loop={video.loop ?? true}
|
|
177
|
+
playsInline={video.playsInline ?? true}
|
|
178
|
+
controls={video.controls ?? false}
|
|
179
|
+
preload={video.preload ?? "metadata"}
|
|
180
|
+
/>
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const image = normalizeMediaImage(item.image);
|
|
185
|
+
|
|
186
|
+
if (image?.src) {
|
|
187
|
+
return (
|
|
188
|
+
<Image
|
|
189
|
+
src={image.src}
|
|
190
|
+
alt={image.alt ?? (typeof item.title === "string" ? item.title : "Selected work preview")}
|
|
191
|
+
fill
|
|
192
|
+
sizes="(max-width: 768px) 100vw, (max-width: 1280px) 50vw, 33vw"
|
|
193
|
+
className={cn("object-cover", classNames?.image, image.className)}
|
|
194
|
+
unoptimized
|
|
195
|
+
/>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<div
|
|
201
|
+
className={cn(
|
|
202
|
+
"flex size-full flex-col justify-between bg-[radial-gradient(circle_at_top,rgba(0,0,0,0.08),rgba(0,0,0,0.03)_32%,rgba(0,0,0,0)_72%)] p-5 sm:p-6 dark:bg-[radial-gradient(circle_at_top,rgba(255,255,255,0.12),rgba(255,255,255,0.04)_32%,rgba(0,0,0,0.96)_72%)]",
|
|
203
|
+
|
|
204
|
+
classNames?.placeholder,
|
|
205
|
+
)}
|
|
206
|
+
aria-hidden="true"
|
|
207
|
+
>
|
|
208
|
+
<div className="h-10 w-28 rounded-full border border-border bg-muted/60" />
|
|
209
|
+
|
|
210
|
+
<div className="space-y-2">
|
|
211
|
+
<div className="h-3 w-24 rounded-full bg-foreground/10" />
|
|
212
|
+
<div className="h-3 w-40 rounded-full bg-foreground/7" />
|
|
213
|
+
<div className="h-20 rounded-[1.25rem] border border-border bg-muted/60" />
|
|
214
|
+
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function renderItemBody(
|
|
221
|
+
item: SelectedWorkRailItem,
|
|
222
|
+
isFeatured: boolean,
|
|
223
|
+
classNames?: SelectedWorkRailClassNames,
|
|
224
|
+
) {
|
|
225
|
+
return (
|
|
226
|
+
<>
|
|
227
|
+
<div
|
|
228
|
+
className={cn(
|
|
229
|
+
"relative aspect-[16/11] overflow-hidden rounded-[1.4rem] border border-border bg-muted",
|
|
230
|
+
|
|
231
|
+
isFeatured && "aspect-[16/9]",
|
|
232
|
+
classNames?.media,
|
|
233
|
+
)}
|
|
234
|
+
>
|
|
235
|
+
{renderVisual(item, classNames)}
|
|
236
|
+
</div>
|
|
237
|
+
|
|
238
|
+
<div className={cn("mt-5 flex flex-col gap-3", classNames?.content)}>
|
|
239
|
+
{item.label ? (
|
|
240
|
+
<p
|
|
241
|
+
className={cn(
|
|
242
|
+
"text-[0.7rem] font-medium uppercase tracking-[0.24em] text-muted-foreground",
|
|
243
|
+
|
|
244
|
+
classNames?.label,
|
|
245
|
+
)}
|
|
246
|
+
>
|
|
247
|
+
{item.label}
|
|
248
|
+
</p>
|
|
249
|
+
) : null}
|
|
250
|
+
|
|
251
|
+
<div>
|
|
252
|
+
<h3
|
|
253
|
+
className={cn(
|
|
254
|
+
"text-xl font-medium tracking-[-0.035em] text-foreground sm:text-2xl",
|
|
255
|
+
|
|
256
|
+
classNames?.itemTitle,
|
|
257
|
+
)}
|
|
258
|
+
>
|
|
259
|
+
{item.title}
|
|
260
|
+
</h3>
|
|
261
|
+
|
|
262
|
+
{item.description ? (
|
|
263
|
+
<p
|
|
264
|
+
className={cn(
|
|
265
|
+
"mt-2 max-w-2xl text-sm leading-6 text-muted-foreground sm:text-[0.95rem]",
|
|
266
|
+
|
|
267
|
+
classNames?.itemDescription,
|
|
268
|
+
)}
|
|
269
|
+
>
|
|
270
|
+
{item.description}
|
|
271
|
+
</p>
|
|
272
|
+
) : null}
|
|
273
|
+
</div>
|
|
274
|
+
|
|
275
|
+
{item.tags?.length ? (
|
|
276
|
+
<div className={cn("flex flex-wrap gap-2", classNames?.tags)}>
|
|
277
|
+
{item.tags.map((tag) => {
|
|
278
|
+
const normalizedTag = normalizeTag(tag);
|
|
279
|
+
|
|
280
|
+
return (
|
|
281
|
+
<span
|
|
282
|
+
key={normalizedTag.label}
|
|
283
|
+
className={cn(
|
|
284
|
+
"rounded-full border border-border bg-muted/60 px-3 py-1 text-xs text-muted-foreground",
|
|
285
|
+
|
|
286
|
+
classNames?.tag,
|
|
287
|
+
normalizedTag.className,
|
|
288
|
+
)}
|
|
289
|
+
>
|
|
290
|
+
{normalizedTag.label}
|
|
291
|
+
</span>
|
|
292
|
+
);
|
|
293
|
+
})}
|
|
294
|
+
</div>
|
|
295
|
+
) : null}
|
|
296
|
+
</div>
|
|
297
|
+
</>
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export function SelectedWorkRail({
|
|
302
|
+
id,
|
|
303
|
+
className,
|
|
304
|
+
eyebrow = "Selected work",
|
|
305
|
+
title = "A visual rail for selected work and project highlights.",
|
|
306
|
+
description =
|
|
307
|
+
"Use this section to show a few polished examples with minimal copy and stronger visuals.",
|
|
308
|
+
items = defaultItems,
|
|
309
|
+
layout = "grid",
|
|
310
|
+
featuredIndex = 0,
|
|
311
|
+
ariaLabel = "Selected work showcase section",
|
|
312
|
+
titleId,
|
|
313
|
+
enableMotion = true,
|
|
314
|
+
classNames,
|
|
315
|
+
section,
|
|
316
|
+
container,
|
|
317
|
+
header,
|
|
318
|
+
railSlot,
|
|
319
|
+
}: SelectedWorkRailProps) {
|
|
320
|
+
const motionClasses = enableMotion
|
|
321
|
+
? "transition-all duration-300 hover:-translate-y-1"
|
|
322
|
+
: "transition-none hover:!translate-y-0";
|
|
323
|
+
|
|
324
|
+
return (
|
|
325
|
+
<section
|
|
326
|
+
id={id}
|
|
327
|
+
className={cn(
|
|
328
|
+
"relative overflow-hidden bg-background px-4 py-20 text-foreground sm:px-6 lg:px-8 lg:py-24",
|
|
329
|
+
|
|
330
|
+
section?.className,
|
|
331
|
+
classNames?.section,
|
|
332
|
+
className,
|
|
333
|
+
)}
|
|
334
|
+
aria-label={ariaLabel}
|
|
335
|
+
aria-labelledby={titleId}
|
|
336
|
+
>
|
|
337
|
+
<div
|
|
338
|
+
className={cn(
|
|
339
|
+
"pointer-events-none absolute left-1/2 top-28 h-[36rem] w-[52rem] -translate-x-1/2 rounded-full bg-[radial-gradient(circle_at_center,rgba(0,0,0,0.08),rgba(0,0,0,0.03)_38%,transparent_74%)] blur-3xl dark:bg-[radial-gradient(circle_at_center,rgba(255,255,255,0.11),rgba(255,255,255,0.04)_38%,transparent_74%)]",
|
|
340
|
+
|
|
341
|
+
classNames?.backgroundGlow,
|
|
342
|
+
)}
|
|
343
|
+
aria-hidden="true"
|
|
344
|
+
/>
|
|
345
|
+
|
|
346
|
+
<div
|
|
347
|
+
className={cn(
|
|
348
|
+
"relative z-10 mx-auto max-w-7xl",
|
|
349
|
+
container?.className,
|
|
350
|
+
classNames?.container,
|
|
351
|
+
)}
|
|
352
|
+
>
|
|
353
|
+
<div
|
|
354
|
+
className={cn(
|
|
355
|
+
"mx-auto max-w-3xl text-center",
|
|
356
|
+
header?.className,
|
|
357
|
+
classNames?.header,
|
|
358
|
+
)}
|
|
359
|
+
>
|
|
360
|
+
{eyebrow ? (
|
|
361
|
+
<p
|
|
362
|
+
className={cn(
|
|
363
|
+
"text-xs font-medium uppercase tracking-[0.28em] text-muted-foreground",
|
|
364
|
+
|
|
365
|
+
classNames?.eyebrow,
|
|
366
|
+
)}
|
|
367
|
+
>
|
|
368
|
+
{eyebrow}
|
|
369
|
+
</p>
|
|
370
|
+
) : null}
|
|
371
|
+
|
|
372
|
+
<h2
|
|
373
|
+
id={titleId}
|
|
374
|
+
className={cn(
|
|
375
|
+
"mt-5 text-balance text-4xl font-semibold tracking-[-0.055em] text-foreground sm:text-5xl lg:text-6xl",
|
|
376
|
+
|
|
377
|
+
classNames?.title,
|
|
378
|
+
)}
|
|
379
|
+
>
|
|
380
|
+
{title}
|
|
381
|
+
</h2>
|
|
382
|
+
|
|
383
|
+
{description ? (
|
|
384
|
+
<p
|
|
385
|
+
className={cn(
|
|
386
|
+
"mx-auto mt-5 max-w-2xl text-pretty text-base leading-7 text-muted-foreground sm:text-lg",
|
|
387
|
+
|
|
388
|
+
classNames?.description,
|
|
389
|
+
)}
|
|
390
|
+
>
|
|
391
|
+
{description}
|
|
392
|
+
</p>
|
|
393
|
+
) : null}
|
|
394
|
+
</div>
|
|
395
|
+
|
|
396
|
+
{layout === "rail" ? (
|
|
397
|
+
<div
|
|
398
|
+
className={cn(
|
|
399
|
+
"mt-12 flex snap-x snap-mandatory gap-5 overflow-x-auto pb-2",
|
|
400
|
+
railSlot?.className,
|
|
401
|
+
classNames?.rail,
|
|
402
|
+
)}
|
|
403
|
+
>
|
|
404
|
+
{items.map((item, index) => {
|
|
405
|
+
const isFeatured = index === featuredIndex;
|
|
406
|
+
const itemBody = renderItemBody(item, isFeatured, classNames);
|
|
407
|
+
|
|
408
|
+
return item.href ? (
|
|
409
|
+
<Link
|
|
410
|
+
key={item.id ?? `${String(item.title)}-${index}`}
|
|
411
|
+
href={item.href}
|
|
412
|
+
aria-label={item.ariaLabel ?? (typeof item.title === "string" ? item.title : "Selected work item")}
|
|
413
|
+
className={cn(
|
|
414
|
+
"group min-w-[18rem] max-w-[26rem] flex-1 snap-start rounded-[2rem] border border-border bg-card/80 p-4 shadow-[0_20px_80px_rgba(0,0,0,0.12)] backdrop-blur dark:shadow-[0_20px_80px_rgba(0,0,0,0.46)] sm:min-w-[22rem] sm:p-5",
|
|
415
|
+
|
|
416
|
+
isFeatured && "min-w-[22rem] max-w-[32rem]",
|
|
417
|
+
motionClasses,
|
|
418
|
+
classNames?.item,
|
|
419
|
+
classNames?.itemLink,
|
|
420
|
+
isFeatured && classNames?.featuredItem,
|
|
421
|
+
item.className,
|
|
422
|
+
)}
|
|
423
|
+
>
|
|
424
|
+
<div className={cn("flex h-full flex-col", classNames?.itemInner)}>{itemBody}</div>
|
|
425
|
+
</Link>
|
|
426
|
+
) : (
|
|
427
|
+
<div
|
|
428
|
+
key={item.id ?? `${String(item.title)}-${index}`}
|
|
429
|
+
className={cn(
|
|
430
|
+
"min-w-[18rem] max-w-[26rem] flex-1 snap-start rounded-[2rem] border border-border bg-card/80 p-4 shadow-[0_20px_80px_rgba(0,0,0,0.12)] backdrop-blur dark:shadow-[0_20px_80px_rgba(0,0,0,0.46)] sm:min-w-[22rem] sm:p-5",
|
|
431
|
+
|
|
432
|
+
isFeatured && "min-w-[22rem] max-w-[32rem]",
|
|
433
|
+
motionClasses,
|
|
434
|
+
classNames?.item,
|
|
435
|
+
isFeatured && classNames?.featuredItem,
|
|
436
|
+
item.className,
|
|
437
|
+
)}
|
|
438
|
+
>
|
|
439
|
+
<div className={cn("flex h-full flex-col", classNames?.itemInner)}>{itemBody}</div>
|
|
440
|
+
</div>
|
|
441
|
+
);
|
|
442
|
+
})}
|
|
443
|
+
</div>
|
|
444
|
+
) : (
|
|
445
|
+
<div
|
|
446
|
+
className={cn(
|
|
447
|
+
"mt-12 grid gap-5 md:grid-cols-2 xl:grid-cols-3",
|
|
448
|
+
railSlot?.className,
|
|
449
|
+
classNames?.rail,
|
|
450
|
+
)}
|
|
451
|
+
>
|
|
452
|
+
{items.map((item, index) => {
|
|
453
|
+
const isFeatured = index === featuredIndex;
|
|
454
|
+
const itemBody = renderItemBody(item, isFeatured, classNames);
|
|
455
|
+
const sharedClassName = cn(
|
|
456
|
+
"rounded-[2rem] border border-border bg-card/80 p-4 shadow-[0_20px_80px_rgba(0,0,0,0.12)] backdrop-blur dark:shadow-[0_20px_80px_rgba(0,0,0,0.46)] sm:p-5",
|
|
457
|
+
|
|
458
|
+
isFeatured && "md:col-span-2 xl:col-span-2",
|
|
459
|
+
motionClasses,
|
|
460
|
+
classNames?.item,
|
|
461
|
+
isFeatured && classNames?.featuredItem,
|
|
462
|
+
item.className,
|
|
463
|
+
);
|
|
464
|
+
|
|
465
|
+
return item.href ? (
|
|
466
|
+
<Link
|
|
467
|
+
key={item.id ?? `${String(item.title)}-${index}`}
|
|
468
|
+
href={item.href}
|
|
469
|
+
aria-label={item.ariaLabel ?? (typeof item.title === "string" ? item.title : "Selected work item")}
|
|
470
|
+
className={cn(sharedClassName, classNames?.itemLink)}
|
|
471
|
+
>
|
|
472
|
+
<div className={cn("flex h-full flex-col", classNames?.itemInner)}>{itemBody}</div>
|
|
473
|
+
</Link>
|
|
474
|
+
) : (
|
|
475
|
+
<div key={item.id ?? `${String(item.title)}-${index}`} className={sharedClassName}>
|
|
476
|
+
<div className={cn("flex h-full flex-col", classNames?.itemInner)}>{itemBody}</div>
|
|
477
|
+
</div>
|
|
478
|
+
);
|
|
479
|
+
})}
|
|
480
|
+
</div>
|
|
481
|
+
)}
|
|
482
|
+
</div>
|
|
483
|
+
</section>
|
|
484
|
+
);
|
|
485
|
+
}
|