@thorprovider/storefront 0.4.0-mvp.0 → 0.4.0-mvp.2

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.
Files changed (166) hide show
  1. package/README.md +173 -153
  2. package/VENDOR.md +69 -0
  3. package/assets/openspec/config.yaml +38 -0
  4. package/assets/templates/AGENTS.md +76 -0
  5. package/assets/templates/app/app/[[...slug]]/page.tsx +42 -1
  6. package/assets/templates/app/app/[[...slug]]/renderer.tsx +13 -2
  7. package/assets/templates/app/app/globals.css +5 -8
  8. package/assets/templates/app/app/layout.tsx +1 -5
  9. package/assets/templates/app/app/robots.ts +9 -3
  10. package/assets/templates/app/app/sitemap.ts +64 -5
  11. package/assets/templates/app/lib/__STOREFRONT__/actions.ts +70 -0
  12. package/assets/templates/app/lib/__STOREFRONT__/catalog.ts +15 -5
  13. package/assets/templates/app/lib/__STOREFRONT__/commerce.ts +71 -0
  14. package/assets/templates/app/lib/__STOREFRONT__/composition.ts +26 -0
  15. package/assets/templates/app/lib/__STOREFRONT__/handlers.core.ts +36 -4
  16. package/assets/templates/app/lib/__STOREFRONT__/registry.tsx +82 -50
  17. package/assets/templates/app/lib/__STOREFRONT__/runtime.ts +3 -0
  18. package/assets/templates/app/lib/__STOREFRONT__/schema.ts +29 -14
  19. package/assets/templates/app/lib/__STOREFRONT__/section-observation.ts +182 -0
  20. package/assets/templates/app/lib/__STOREFRONT__/section-sources.ts +130 -0
  21. package/assets/templates/app/lib/__STOREFRONT__/shell/content.ts +31 -7
  22. package/assets/templates/app/lib/__STOREFRONT__/shell/props.ts +4 -0
  23. package/assets/templates/app/lib/__STOREFRONT__/spec/index.ts +56 -26
  24. package/assets/templates/app/lib/__STOREFRONT__/spec/seo.ts +165 -0
  25. package/assets/templates/app/lib/__STOREFRONT__/store-context.ts +26 -7
  26. package/assets/templates/app/lib/__STOREFRONT__/views/sections/index.ts +2 -1
  27. package/assets/templates/app/lib/__STOREFRONT__/views/sections/products.client.tsx +100 -0
  28. package/assets/templates/app/lib/__STOREFRONT__/views/sections/products.tsx +19 -0
  29. package/assets/templates/app/lib/__STOREFRONT__/views/sections/schema.products.ts +39 -0
  30. package/assets/templates/features/checkout/handlers.ts +6 -0
  31. package/assets/templates/features/customer-auth/state.ts +10 -1
  32. package/assets/templates/views/account/index.tsx +1 -1
  33. package/assets/templates/views/account/registry.tsx +80 -19
  34. package/assets/templates/views/account/schema.ts +1 -0
  35. package/assets/templates/views/cart/content.ts +11 -0
  36. package/assets/templates/views/cart/data.ts +23 -0
  37. package/assets/templates/views/cart/index.tsx +53 -0
  38. package/assets/templates/views/cart/props.ts +12 -0
  39. package/assets/templates/views/cart/registry.tsx +81 -0
  40. package/assets/templates/views/cart/schema.ts +52 -0
  41. package/assets/templates/views/category/assembly/assembly.json +1 -0
  42. package/assets/templates/views/category/assembly/index.skeleton.tsx +64 -6
  43. package/assets/templates/views/category/assembly/registry.skeleton.tsx +2 -1
  44. package/assets/templates/views/category/assembly/slots/breadcrumb/Breadcrumb/binding.json +5 -0
  45. package/assets/templates/views/category/assembly/slots/breadcrumb/Breadcrumb/catalog.part +4 -0
  46. package/assets/templates/views/category/assembly/slots/breadcrumb/Breadcrumb/element.part +7 -0
  47. package/assets/templates/views/category/assembly/slots/breadcrumb/Breadcrumb/registry.part +18 -0
  48. package/assets/templates/views/category/index.tsx +76 -7
  49. package/assets/templates/views/category/props.ts +7 -0
  50. package/assets/templates/views/category/registry.tsx +19 -0
  51. package/assets/templates/views/category/schema.ts +13 -0
  52. package/assets/templates/views/home/assembly/assembly.json +9 -0
  53. package/assets/templates/views/home/assembly/index.skeleton.tsx +22 -4
  54. package/assets/templates/views/home/assembly/slots/hero/StorefrontHero1/element.part +1 -1
  55. package/assets/templates/views/home/assembly/slots/hero/StorefrontHero1/registry.part +2 -2
  56. package/assets/templates/views/home/data.ts +9 -0
  57. package/assets/templates/views/home/index.tsx +23 -5
  58. package/assets/templates/views/home/registry.tsx +2 -2
  59. package/assets/templates/views/product/data.ts +4 -2
  60. package/assets/templates/views/product/index.tsx +49 -5
  61. package/assets/templates/views/product/props.ts +7 -0
  62. package/assets/templates/views/product/registry.tsx +25 -0
  63. package/assets/templates/views/product/schema.ts +13 -0
  64. package/assets/templates/views/static/content.ts +4 -4
  65. package/assets/templates/views/static/index.tsx +1 -1
  66. package/bin/storefront.js +1231 -154
  67. package/examples/merchandising/category-led.json +37 -0
  68. package/examples/merchandising/collection-led.json +37 -0
  69. package/package.json +11 -7
  70. package/recipes/archetypes.json +9 -22
  71. package/recipes/catalog.json +40 -1
  72. package/recipes/features.json +25 -2
  73. package/recipes/recipe.schema.json +1 -1
  74. package/recipes/recipes.json +32 -30
  75. package/recipes/sections.json +10 -0
  76. package/recipes/validate.mjs +54 -0
  77. package/scripts/candidate.mjs +4 -4
  78. package/scripts/composers.mjs +25 -5
  79. package/scripts/env-file.mjs +86 -0
  80. package/scripts/file-classes.mjs +5 -0
  81. package/scripts/migrate-english-routes.mjs +276 -0
  82. package/scripts/pinning.mjs +74 -5
  83. package/scripts/plan-apply.mjs +149 -5
  84. package/scripts/reconcile.mjs +49 -11
  85. package/scripts/render-templates.mjs +97 -44
  86. package/scripts/section-config.mjs +253 -0
  87. package/scripts/starter.mjs +17 -0
  88. package/scripts/theme/color.mjs +185 -0
  89. package/scripts/theme/css-theme.mjs +233 -0
  90. package/scripts/theme/fonts.mjs +123 -0
  91. package/scripts/theme/import-export.mjs +125 -0
  92. package/scripts/theme/preset.mjs +93 -0
  93. package/scripts/theme/theme-plan.mjs +292 -0
  94. package/scripts/theme/tokens.mjs +137 -0
  95. package/scripts/view-assembly.mjs +47 -1
  96. package/skills/sf-feature/SKILL.md +32 -19
  97. package/skills/sf-setup/SKILL.md +79 -0
  98. package/skills/sf-theme-gen/SKILL.md +99 -36
  99. package/skills/sf-theme-gen/references/shadcn-theming.md +87 -0
  100. package/skills/{shadcn-theming/references/templates → sf-theme-gen/references}/theme-setup.md +15 -19
  101. package/skills/{shadcn-theming → sf-theme-gen}/references/theming-guide.md +6 -11
  102. package/skills/sf-view-gen/SKILL.md +63 -40
  103. package/skills/sf-view-gen/assets/recipes/archetypes.json +9 -22
  104. package/skills/sf-view-gen/assets/recipes/catalog.json +40 -1
  105. package/skills/sf-view-gen/assets/recipes/features.json +25 -2
  106. package/skills/sf-view-gen/assets/recipes/recipes.json +32 -30
  107. package/skills/sf-view-gen/assets/recipes/sections.json +10 -0
  108. package/skills/sf-view-gen/assets/templates/views/sections/products.client.tsx +100 -0
  109. package/skills/sf-view-gen/assets/templates/views/sections/products.tsx +19 -0
  110. package/skills/sf-view-gen/assets/templates/views/sections/schema.products.ts +39 -0
  111. package/skills/{json-render-core/SKILL.md → sf-view-gen/references/json-render-core.md} +4 -27
  112. package/skills/{json-render-next/SKILL.md → sf-view-gen/references/json-render-next.md} +5 -8
  113. package/skills/{json-render-react/SKILL.md → sf-view-gen/references/json-render-react.md} +3 -5
  114. package/skills/{json-render-shadcn/SKILL.md → sf-view-gen/references/json-render-shadcn.md} +3 -5
  115. package/skills/sf-view-gen/references/views.md +28 -37
  116. package/skills/sf-view-gen/scripts/validate.mjs +54 -0
  117. package/skills/storefront-workflow/SKILL.md +94 -31
  118. package/skills/{storefront-best-practices/reference/design.md → storefront-workflow/references/design-consistency.md} +13 -29
  119. package/CHANGELOG.md +0 -84
  120. package/assets/templates/views/user-panel/index.tsx +0 -106
  121. package/assets/templates/views/user-panel/registry.tsx +0 -54
  122. package/assets/templates/views/user-panel/schema.ts +0 -79
  123. package/commands/sf-add-view.md +0 -57
  124. package/commands/sf-feature.md +0 -28
  125. package/commands/sf-theme.md +0 -26
  126. package/commands/sf-view.md +0 -67
  127. package/skills/building-storefronts/SKILL.md +0 -178
  128. package/skills/building-storefronts/references/frontend-integration.md +0 -229
  129. package/skills/json-render-remotion/SKILL.md +0 -111
  130. package/skills/json-render-solid/SKILL.md +0 -204
  131. package/skills/nextjs-shadcn/SKILL.md +0 -367
  132. package/skills/nextjs-shadcn/references/architecture.md +0 -499
  133. package/skills/nextjs-shadcn/references/project-setup.md +0 -162
  134. package/skills/nextjs-shadcn/references/shadcn-platform.md +0 -261
  135. package/skills/nextjs-shadcn/references/sidebar.md +0 -274
  136. package/skills/nextjs-shadcn/references/styling.md +0 -555
  137. package/skills/shadcn-component-discovery/SKILL.md +0 -273
  138. package/skills/shadcn-component-discovery/references/registries.md +0 -226
  139. package/skills/shadcn-theming/SKILL.md +0 -104
  140. package/skills/storefront-best-practices/SKILL.md +0 -421
  141. package/skills/storefront-best-practices/reference/components/breadcrumbs.md +0 -123
  142. package/skills/storefront-best-practices/reference/components/cart-popup.md +0 -189
  143. package/skills/storefront-best-practices/reference/components/country-selector.md +0 -298
  144. package/skills/storefront-best-practices/reference/components/footer.md +0 -112
  145. package/skills/storefront-best-practices/reference/components/hero.md +0 -241
  146. package/skills/storefront-best-practices/reference/components/megamenu.md +0 -239
  147. package/skills/storefront-best-practices/reference/components/navbar.md +0 -397
  148. package/skills/storefront-best-practices/reference/components/popups.md +0 -221
  149. package/skills/storefront-best-practices/reference/components/product-card.md +0 -125
  150. package/skills/storefront-best-practices/reference/components/product-reviews.md +0 -217
  151. package/skills/storefront-best-practices/reference/components/product-slider.md +0 -174
  152. package/skills/storefront-best-practices/reference/components/search.md +0 -101
  153. package/skills/storefront-best-practices/reference/connecting-to-backend.md +0 -391
  154. package/skills/storefront-best-practices/reference/features/promotions.md +0 -307
  155. package/skills/storefront-best-practices/reference/features/wishlist.md +0 -230
  156. package/skills/storefront-best-practices/reference/layouts/account.md +0 -380
  157. package/skills/storefront-best-practices/reference/layouts/cart.md +0 -316
  158. package/skills/storefront-best-practices/reference/layouts/checkout.md +0 -486
  159. package/skills/storefront-best-practices/reference/layouts/home-page.md +0 -264
  160. package/skills/storefront-best-practices/reference/layouts/order-confirmation.md +0 -231
  161. package/skills/storefront-best-practices/reference/layouts/product-details.md +0 -527
  162. package/skills/storefront-best-practices/reference/layouts/product-listing.md +0 -520
  163. package/skills/storefront-best-practices/reference/layouts/static-pages.md +0 -356
  164. package/skills/storefront-best-practices/reference/medusa.md +0 -307
  165. /package/skills/{storefront-best-practices/reference → storefront-workflow/references}/mobile-responsiveness.md +0 -0
  166. /package/skills/{storefront-best-practices/reference → storefront-workflow/references}/seo.md +0 -0
@@ -1,555 +0,0 @@
1
- # Styling
2
-
3
- ## Theme System
4
-
5
- ### globals.css Structure
6
-
7
- shadcn generates base variables automatically based on your chosen preset. Customize for your project:
8
-
9
- ```css
10
- @import "tailwindcss";
11
-
12
- /* Note: Tailwind v3 projects use @tailwind base; @tailwind components; @tailwind utilities; instead */
13
-
14
- /* :root and .dark live OUTSIDE @layer base and hold full color values (OKLCH preferred) */
15
- :root {
16
- /* shadcn base variables come from preset */
17
- --background: ...;
18
- --foreground: ...;
19
- --primary: ...;
20
- --secondary: ...;
21
- /* etc. */
22
-
23
- /* Add your own variables as needed */
24
- --brand: oklch(0.55 0.2 260);
25
- }
26
-
27
- .dark {
28
- --brand: oklch(0.7 0.18 260);
29
- }
30
-
31
- @theme inline {
32
- --color-brand: var(--brand);
33
- }
34
- ```
35
-
36
- The `@theme inline` mapping is what makes the `bg-brand` / `text-brand` utilities work — a variable without it generates no utility.
37
-
38
- **Choose preset**: Use [ui.shadcn.com/create](https://ui.shadcn.com/create) to select named style (vega, nova, maia, lyra, mira, luma, sera, rhea), base color, font, icon library, and radius. The customizer outputs a single preset code that encodes all choices.
39
-
40
- ### Theme Customization
41
-
42
- Quick customizations in `globals.css`:
43
-
44
- ```css
45
- :root {
46
- /* Typography - change fonts */
47
- --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
48
- --font-serif: Georgia, serif;
49
- --font-mono: "Fira Code", ui-monospace, monospace;
50
-
51
- /* Border radius - affects all rounded corners */
52
- --radius: 0.5rem; /* Default */
53
- /* --radius: 0.25rem; /* Sharp */
54
- /* --radius: 0.75rem; /* More rounded */
55
- /* --radius: 1rem; /* Very rounded */
56
- /* --radius: 1.3rem; /* Pill-like buttons */
57
- }
58
- ```
59
-
60
- | Variable | Effect |
61
- |----------|--------|
62
- | `--font-sans` | Body text, buttons, inputs |
63
- | `--font-mono` | Code blocks, technical content |
64
- | `--radius` | All rounded corners (buttons, cards, inputs) |
65
-
66
- **Tip**: Larger `--radius` values (1rem+) give a softer, more modern look. Smaller values (0.25rem) feel sharper and technical.
67
-
68
- ### Using Theme Colors
69
-
70
- ```tsx
71
- // ✅ Use CSS variables
72
- <div className="bg-primary text-primary-foreground" />
73
- <div className="border-border" />
74
- <div className="text-muted-foreground" />
75
-
76
- // ❌ Never hardcode colors
77
- <div className="bg-blue-500" />
78
- <div className="text-[#1a1a1a]" />
79
- ```
80
-
81
- ## shadcn/ui Presets
82
-
83
- Available styles at ui.shadcn.com/create:
84
-
85
- | Preset | Character |
86
- |--------|-----------|
87
- | vega | Classic shadcn/ui look. Clean, neutral, familiar |
88
- | nova | Reduced padding and margins for compact layouts |
89
- | maia | Soft and rounded, with generous spacing |
90
- | lyra | Boxy and sharp. Pairs well with mono fonts |
91
- | mira | Compact. Made for dense interfaces |
92
- | luma | Newer official style — see ui.shadcn.com/create |
93
- | sera | Newer official style — see ui.shadcn.com/create |
94
- | rhea | A more compact Luma. Tighter spacing, smaller controls, denser surfaces — built for focused product interfaces |
95
-
96
- ### Fonts
97
-
98
- Body/mono fonts the preset builder offers (these ids are what the preset code
99
- encodes — `shadcn preset decode <code>` prints them back):
100
-
101
- | Font | Type | Character |
102
- |------|------|-----------|
103
- | geist | Sans | Vercel's modern geometric sans |
104
- | inter | Sans | Clean, versatile (classic default) |
105
- | figtree | Sans | Friendly, geometric |
106
- | dm-sans | Sans | Compact geometric with character |
107
- | outfit | Sans | Modern, soft |
108
- | noto-sans | Sans | Universal language support |
109
- | nunito-sans | Sans | Rounded, approachable |
110
- | roboto | Sans | Google's versatile sans |
111
- | raleway | Sans | Elegant, thin-weight display |
112
- | public-sans | Sans | US government standard, neutral |
113
- | jetbrains-mono | Mono | Developer-focused monospace |
114
- | geist-mono | Mono | Vercel's monospace |
115
-
116
- Heading fonts (`fontHeading`) are a separate, longer list — lora, merriweather,
117
- playfair-display, noto-serif, roboto-slab, oxanium, manrope, space-grotesk,
118
- montserrat, ibm-plex-sans, source-sans-3, instrument-sans, eb-garamond,
119
- instrument-serif. It defaults to `inherit` (same face as the body).
120
-
121
- ## Icon Libraries
122
-
123
- Priority order (use first available). The names below are the CLI's library ids —
124
- pass them verbatim to `shadcn migrate icons --from <id> --to <id>`:
125
-
126
- 1. **lucide** (default) - `yarn add lucide-react`
127
- 2. **tabler** - `yarn add @tabler/icons-react`
128
- 3. **hugeicons** - `yarn add @hugeicons/react @hugeicons/core-free-icons` (the old `hugeicons-react` package is deprecated)
129
- 4. **phosphor** - `yarn add @phosphor-icons/react`
130
- 5. **remixicon** - `yarn add @remixicon/react`
131
-
132
- ```tsx
133
- // lucide example
134
- import { ChevronRight, Menu, X } from "lucide-react"
135
-
136
- <Button>
137
- Next <ChevronRight data-icon="inline-end" />
138
- </Button>
139
- ```
140
-
141
- ## Animations
142
-
143
- ### CSS Page Transitions
144
-
145
- Add to `globals.css`:
146
-
147
- ```css
148
- @keyframes page-in {
149
- from {
150
- opacity: 0;
151
- transform: translateY(8px);
152
- }
153
- to {
154
- opacity: 1;
155
- transform: translateY(0);
156
- }
157
- }
158
-
159
- @layer utilities {
160
- .animate-page-in {
161
- animation: page-in 0.6s ease-out both;
162
- }
163
- }
164
- ```
165
-
166
- Usage in layout or template:
167
-
168
- ```tsx
169
- // template.tsx - animates on every navigation
170
- export default function Template({ children }: { children: React.ReactNode }) {
171
- return <main className="animate-page-in">{children}</main>
172
- }
173
- ```
174
-
175
- ### View Transitions API
176
-
177
- No config needed. View transitions work in the App Router out of the box — it
178
- runs React canary releases, which ship `ViewTransition`. The old
179
- `experimental.viewTransition` flag is gone from Next.js 16's config type; adding
180
- it now is a type error, not a no-op.
181
-
182
- Wrap what should animate in React's `<ViewTransition>` — no extra install.
183
- Without browser support it degrades gracefully: no animation, app still works.
184
-
185
- ```tsx
186
- import { ViewTransition } from "react"
187
- ```
188
-
189
- `<ViewTransition>` animations fire on Transitions, `<Suspense>`, and
190
- `useDeferredValue`. Route navigations are Transitions, so they activate
191
- automatically on navigation; plain `setState` does not trigger them.
192
-
193
- | Pattern | Communicates | Key API |
194
- |---------|--------------|---------|
195
- | Shared-element morph | "Same thing, going deeper" | Same `name` on both elements |
196
- | Suspense reveal | "Data loaded" | `enter`/`exit` on fallback + content, `default="none"` |
197
- | Directional slide | "Forward / back" | `<Link transitionTypes={["nav-forward"]}>` + `enter`/`exit` keyed by type |
198
- | Same-route crossfade | "Same place, different content" | `key={slug}` + `share="auto"` `enter="auto"` |
199
-
200
- Shared-element morph is the most common and works with zero CSS — wrap both the
201
- source and destination element with the same `name`:
202
-
203
- ```tsx
204
- // grid thumbnail
205
- <ViewTransition name={`photo-${photo.id}`}>
206
- <Image src={photo.src} alt={photo.title} />
207
- </ViewTransition>
208
-
209
- // detail page hero — same name
210
- <ViewTransition name={`photo-${photo.id}`}>
211
- <Image src={photo.src} alt={photo.title} fill />
212
- </ViewTransition>
213
- ```
214
-
215
- React matches the names across the old/new route and animates size and
216
- position. Customize with `share="morph"` and `::view-transition-group(.morph)`
217
- CSS. Respect `prefers-reduced-motion` by zeroing animation durations on the
218
- `::view-transition-*` pseudo-elements.
219
-
220
- Patterns 2–4 (CSS keyframes, directional/Suspense examples):
221
- [Designing view transitions](https://nextjs.org/docs/app/guides/view-transitions).
222
-
223
- ### Motion Library
224
-
225
- For complex animations:
226
-
227
- ```bash
228
- yarn add motion
229
- ```
230
-
231
- ```tsx
232
- "use client"
233
-
234
- import { motion, HTMLMotionProps } from "motion/react"
235
-
236
- interface FadeInProps extends HTMLMotionProps<"div"> {
237
- delay?: number
238
- duration?: number
239
- direction?: "up" | "down" | "left" | "right" | "none"
240
- }
241
-
242
- export function FadeIn({
243
- children,
244
- className,
245
- delay = 0,
246
- duration = 0.5,
247
- direction = "up",
248
- ...props
249
- }: FadeInProps) {
250
- const directions = {
251
- up: { y: 20, x: 0 },
252
- down: { y: -20, x: 0 },
253
- left: { x: 20, y: 0 },
254
- right: { x: -20, y: 0 },
255
- none: { x: 0, y: 0 },
256
- }
257
-
258
- return (
259
- <motion.div
260
- initial={{ opacity: 0, ...directions[direction] }}
261
- whileInView={{ opacity: 1, x: 0, y: 0 }}
262
- viewport={{ once: true, margin: "-50px" }}
263
- transition={{ duration, delay, ease: "easeOut" }}
264
- className={className}
265
- {...props}
266
- >
267
- {children}
268
- </motion.div>
269
- )
270
- }
271
- ```
272
-
273
- ### GSAP
274
-
275
- For scroll-triggered and complex sequences:
276
-
277
- ```bash
278
- yarn add gsap @gsap/react
279
- ```
280
-
281
- ```tsx
282
- "use client"
283
-
284
- import { useRef } from "react"
285
- import { useGSAP } from "@gsap/react"
286
- import gsap from "gsap"
287
- import { ScrollTrigger } from "gsap/ScrollTrigger"
288
-
289
- gsap.registerPlugin(ScrollTrigger)
290
-
291
- export function ScrollReveal({ children }) {
292
- const containerRef = useRef<HTMLDivElement>(null)
293
-
294
- useGSAP(() => {
295
- gsap.from(containerRef.current, {
296
- opacity: 0,
297
- y: 50,
298
- scrollTrigger: {
299
- trigger: containerRef.current,
300
- start: "top 80%",
301
- },
302
- })
303
- }, [])
304
-
305
- return <div ref={containerRef}>{children}</div>
306
- }
307
- ```
308
-
309
- ## Animation Decision Tree
310
-
311
- ```text
312
- Simple fade/slide on mount?
313
- ├── Yes → CSS animation in globals.css
314
- └── No ↓
315
-
316
- Page/route transitions?
317
- ├── Yes → View Transitions API or template.tsx
318
- └── No ↓
319
-
320
- Interactive hover/tap states?
321
- ├── Yes → Tailwind transitions + Motion
322
- └── No ↓
323
-
324
- Scroll-triggered sequences?
325
- ├── Yes → GSAP + ScrollTrigger
326
- └── No → Evaluate if animation needed
327
- ```
328
-
329
- ## Performance Tips
330
-
331
- 1. **Prefer CSS** - GPU-accelerated, no JS bundle
332
- 2. **Use `will-change` sparingly** - Only for known animations
333
- 3. **Avoid layout thrashing** - Animate `transform` and `opacity`
334
- 4. **Lazy load Motion/GSAP** - Dynamic imports for non-critical animations
335
-
336
- ```tsx
337
- // Lazy load animation library
338
- const MotionDiv = dynamic(
339
- () => import("motion/react").then((mod) => mod.motion.div),
340
- { ssr: false }
341
- )
342
- ```
343
-
344
- ## Decorative Backgrounds
345
-
346
- Reusable patterns for visual atmosphere and section hierarchy.
347
-
348
- ### Grid Pattern
349
-
350
- ```tsx
351
- import { cn } from "@/lib/utils"
352
-
353
- export function GridBackground({
354
- children,
355
- className,
356
- size = 20
357
- }: {
358
- children: React.ReactNode
359
- className?: string
360
- size?: number
361
- }) {
362
- return (
363
- <div className={cn("relative", className)}>
364
- <div
365
- className={cn(
366
- "absolute inset-0 -z-10",
367
- "[background-image:linear-gradient(to_right,var(--border)_1px,transparent_1px),linear-gradient(to_bottom,var(--border)_1px,transparent_1px)]"
368
- )}
369
- style={{ backgroundSize: `${size}px ${size}px` }}
370
- />
371
- {children}
372
- </div>
373
- )
374
- }
375
- ```
376
-
377
- ### Dot Pattern
378
-
379
- ```tsx
380
- export function DotBackground({
381
- children,
382
- className
383
- }: {
384
- children: React.ReactNode
385
- className?: string
386
- }) {
387
- return (
388
- <div className={cn("relative", className)}>
389
- <div
390
- className={cn(
391
- "absolute inset-0 -z-10",
392
- "[background-size:20px_20px]",
393
- "[background-image:radial-gradient(color-mix(in_oklab,var(--muted-foreground)_30%,transparent)_1px,transparent_1px)]"
394
- )}
395
- />
396
- {children}
397
- </div>
398
- )
399
- }
400
- ```
401
-
402
- ### Radial Gradient Hero
403
-
404
- ```tsx
405
- export function GradientHero({ children }: { children: React.ReactNode }) {
406
- return (
407
- <div className="relative min-h-screen">
408
- <div
409
- aria-hidden
410
- className="fixed inset-0 -z-10"
411
- style={{
412
- background: "radial-gradient(125% 125% at 50% 10%, var(--background) 40%, var(--primary) 100%)"
413
- }}
414
- />
415
- {children}
416
- </div>
417
- )
418
- }
419
- ```
420
-
421
- ### Faded Edge Effect
422
-
423
- Combine with grid/dot for vignette:
424
-
425
- ```tsx
426
- <div className="relative">
427
- <GridBackground className="absolute inset-0" />
428
- <div className="pointer-events-none absolute inset-0 bg-background [mask-image:radial-gradient(ellipse_at_center,transparent_20%,black)]" />
429
- {/* Content */}
430
- </div>
431
- ```
432
-
433
- ### Animated Spotlight
434
-
435
- For premium hero sections. Requires `motion`:
436
-
437
- ```tsx
438
- "use client"
439
-
440
- import { motion } from "motion/react"
441
- import { cn } from "@/lib/utils"
442
-
443
- export function Spotlight({ className }: { className?: string }) {
444
- return (
445
- <motion.div
446
- className={cn(
447
- "pointer-events-none fixed inset-0 -z-10 overflow-hidden",
448
- className
449
- )}
450
- aria-hidden
451
- >
452
- <motion.div
453
- className="absolute top-0 left-1/2 h-[60vh] w-[80vw] -translate-x-1/2 rounded-full opacity-20 blur-3xl"
454
- style={{
455
- background:
456
- "radial-gradient(ellipse, color-mix(in oklab, var(--primary) 30%, transparent), transparent 70%)",
457
- }}
458
- animate={{ x: ["-10%", "10%", "-10%"] }}
459
- transition={{ duration: 8, repeat: Infinity, ease: "easeInOut" }}
460
- />
461
- </motion.div>
462
- )
463
- }
464
- ```
465
-
466
- Combine with DotBackground for depth:
467
-
468
- ```tsx
469
- <div className="relative min-h-screen bg-background dark:bg-black">
470
- <Spotlight />
471
- <DotBackground className="absolute inset-0 opacity-30" />
472
- <div className="relative z-10">{children}</div>
473
- </div>
474
- ```
475
-
476
- For more creative direction (custom textures, particles, dramatic effects), apply `/frontend-design` thinking.
477
-
478
- ### Section Wrapper
479
-
480
- For sections that need different theme context:
481
-
482
- ```tsx
483
- type SectionProps = {
484
- children: React.ReactNode
485
- variant?: "default" | "muted" | "inverted"
486
- className?: string
487
- }
488
-
489
- export function Section({ children, variant = "default", className }: SectionProps) {
490
- return (
491
- <section
492
- className={cn(
493
- "relative py-24",
494
- variant === "muted" && "bg-muted",
495
- variant === "inverted" && "bg-foreground text-background [&_*]:border-background/20",
496
- className
497
- )}
498
- >
499
- {children}
500
- </section>
501
- )
502
- }
503
- ```
504
-
505
- ### Background Decision Tree
506
-
507
- ```text
508
- Full-page ambient effect?
509
- ├── Static → Fixed radial gradient (GradientHero)
510
- ├── Animated → Spotlight + DotBackground
511
- ├── Premium → Apply /frontend-design thinking
512
- └── No ↓
513
-
514
- Subtle texture for depth?
515
- ├── Grid → Technical/dashboard feel
516
- ├── Dots → Softer/organic feel
517
- └── No ↓
518
-
519
- Section contrast needed?
520
- ├── Yes → Section wrapper with variant
521
- └── No → Standard bg-background
522
- ```
523
-
524
- ### File Organization
525
-
526
- ```text
527
- components/
528
- ├── ui/ # shadcn primitives
529
- ├── backgrounds/ # Grid, Dot, Gradient patterns
530
- └── animations/ # FadeIn, ScrollReveal
531
- ```
532
-
533
- ## Optional Utilities
534
-
535
- ### Scrollbar Hide
536
-
537
- `shadcn/tailwind.css` already ships a `no-scrollbar` utility, so a shadcn project
538
- needs no extra package:
539
-
540
- ```tsx
541
- <div className="overflow-y-auto no-scrollbar">
542
- {/* Scrollable content without visible scrollbar */}
543
- </div>
544
- ```
545
-
546
- Only reach for a package in a project that doesn't import `shadcn/tailwind.css`:
547
-
548
- ```bash
549
- yarn add tailwind-scrollbar-hide
550
- ```
551
-
552
- ```css
553
- /* globals.css (Tailwind v4 — no config file needed) */
554
- @import "tailwind-scrollbar-hide/v4";
555
- ```