diff --git a/apps/admin/src/components/page-builder/AddSectionModal.tsx b/apps/admin/src/components/page-builder/AddSectionModal.tsx index 38b5ba9..154a41a 100644 --- a/apps/admin/src/components/page-builder/AddSectionModal.tsx +++ b/apps/admin/src/components/page-builder/AddSectionModal.tsx @@ -165,6 +165,105 @@ export default function AddSectionModal({ isOpen, onClose, onSelectBlock }: AddS ) }, + // 5.1 HERO_MINIMAL + { + type: 'HERO_MINIMAL', + category: 'hero', + title: 'HERO MINIMAL (Zen Cover)', + description: 'Fullscreen mood cover with micro-tagline and statement typography (Pure visual, No CTA buttons).', + badge: 'Minimal', + renderPreview: () => ( +
+
+ AUTUMN EQUINOX +

The scent of damp earth & cedar

+
+
+ ) + }, + // 5.2 HERO_SPLIT_MINIMAL + { + type: 'HERO_SPLIT_MINIMAL', + category: 'hero', + title: 'HERO SPLIT MINIMAL (Editorial)', + description: 'Magazine-style asymmetric layout with quiet philosophical copy and vertical editorial image.', + badge: 'Minimal', + renderPreview: () => ( +
+
+
Formulated in silence, crafted for peace.
+

Pure organic distillates.

+
+
+ editorial +
+
+ ) + }, + // 5.3 HERO_VIDEO_MINIMAL + { + type: 'HERO_VIDEO_MINIMAL', + category: 'hero', + title: 'HERO VIDEO MINIMAL (Motion)', + description: 'Atmospheric slow-moving ambient video background with floating quiet typography.', + badge: 'Minimal', + renderPreview: () => ( +
+
+ motion +
+ LIVING ARTWORK +
Breathe with Intention
+
+
+ ) + }, + // 5.4 BANNER_MINIMAL + { + type: 'BANNER_MINIMAL', + category: 'hero', + title: 'BANNER MINIMAL (Quiet Divider)', + description: 'Slim horizontal divider with single statement copy. Ideal for mood transitions between grids.', + badge: 'Minimal', + renderPreview: () => ( +
+
100% pure botanical distillates, harvested with intention.
+

Carbon-neutral delivery on all orders

+
+ ) + }, + // 5.5 ANNOUNCEMENT_BAR_MINIMAL + { + type: 'ANNOUNCEMENT_BAR_MINIMAL', + category: 'hero', + title: 'ANNOUNCEMENT MINIMAL', + description: 'Ultra-thin, gentle top announcement ticker without emojis or loud badges.', + badge: 'Minimal', + renderPreview: () => ( +
+ COMPLIMENTARY BOTANICAL SAMPLE WITH EVERY ORDER +
+ ) + }, + // 5.6 USP_MINIMAL + { + type: 'USP_MINIMAL', + category: 'hero', + title: 'USP MINIMAL (Typography)', + description: 'Pure typographic pillars separated by clean dots or lines. Sophisticated and icon-free.', + badge: 'Minimal', + renderPreview: () => ( +
+

+ Ethically Sourced · No Synthetics · Hand-Poured · Cruelty-Free +

+
+ ) + }, // 6. PRODUCTS { type: 'PRODUCTS', diff --git a/apps/admin/src/components/page-builder/MinimalSectionForms.tsx b/apps/admin/src/components/page-builder/MinimalSectionForms.tsx new file mode 100644 index 0000000..6516408 --- /dev/null +++ b/apps/admin/src/components/page-builder/MinimalSectionForms.tsx @@ -0,0 +1,692 @@ +import React from 'react'; +import { UploadCloud, Image as ImageIcon, Plus, Trash2, Sparkles, Video } from 'lucide-react'; +import { type PageSection } from '@homaroma/types'; +import FocalPointPicker from './FocalPointPicker'; + +interface CommonProps { + editingSection: Partial; + setEditingSection?: React.Dispatch | null>>; + editingLang: string; + getLocalizedValue: (payload: any, field: string) => string; + updateLocalizedValue: (field: string, value: string) => void; + updatePayloadValue: (field: string, value: any) => void; + setUploadTarget?: (target: { type: 'main' | 'slide'; index?: number } | null) => void; + setIsMediaModalOpen?: (open: boolean) => void; +} + +// 1. HERO_MINIMAL FORM +export function HeroMinimalForm({ + editingSection, + getLocalizedValue, + updateLocalizedValue, + updatePayloadValue, + setUploadTarget, + setIsMediaModalOpen, +}: CommonProps) { + return ( +
+
+ + Minimal Mode: Full-screen atmospheric cover with pure typography (No CTA buttons). +
+ +
+
+ +
{ + setUploadTarget?.({ type: 'main' }); + setIsMediaModalOpen?.(true); + }} + > + {editingSection.payload?.imageUrl ? ( + <> + Hero +
+ +
+ + ) : ( +
+ +

Select Cover Image

+
+ )} +
+
+ + {editingSection.payload?.imageUrl && ( +
+ updatePayloadValue('focalPoint', focalPoint)} + /> +
+ )} + +
+ + updateLocalizedValue('tagline', e.target.value)} + className="admin-input w-full" + placeholder="e.g. AUTUMN EQUINOX · BOTANICAL ESSENCE" + /> +
+ +
+ + +
+ +
+ + updateLocalizedValue('title', e.target.value)} + className="admin-input w-full" + placeholder="e.g. The scent of damp earth and cedar [sanctuary]" + /> +

Tip: Use [brackets] to highlight words in accent color.

+
+ +
+ + updatePayloadValue('overlayOpacity', Number(e.target.value))} + className="admin-input w-full" + /> +
+
+
+ ); +} + +// 2. HERO_SPLIT_MINIMAL FORM +export function HeroSplitMinimalForm({ + editingSection, + getLocalizedValue, + updateLocalizedValue, + updatePayloadValue, + setUploadTarget, + setIsMediaModalOpen, +}: CommonProps) { + return ( +
+
+ + Minimal Split: Magazine-style layout with asymmetric whitespace and statement copy. +
+ +
+
+ +
{ + setUploadTarget?.({ type: 'main' }); + setIsMediaModalOpen?.(true); + }} + > + {editingSection.payload?.imageUrl ? ( + <> + Split +
+ +
+ + ) : ( +
+ +

Select Editorial Image

+
+ )} +
+
+ + {editingSection.payload?.imageUrl && ( +
+ updatePayloadValue('focalPoint', focalPoint)} + /> +
+ )} + +
+ + +
+ +
+ + updatePayloadValue('backgroundColor', e.target.value)} + className="admin-input w-full" + placeholder="e.g. #F8F9F5 or empty for default" + /> +
+ +
+ +