@morphika/andami 0.1.9 → 0.1.10

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 (31) hide show
  1. package/components/admin/nav-builder/NavBuilder.tsx +90 -14
  2. package/components/admin/nav-builder/NavGeneralSettings.tsx +521 -271
  3. package/components/admin/nav-builder/NavItemSettings.tsx +331 -312
  4. package/components/admin/nav-builder/NavMobileSettings.tsx +159 -140
  5. package/components/admin/nav-builder/NavSettingsFields.tsx +287 -21
  6. package/components/admin/nav-builder/NavSettingsPanel.tsx +137 -127
  7. package/components/blocks/TextBlockRenderer.tsx +1 -1
  8. package/components/builder/editors/ButtonBlockEditor.tsx +8 -3
  9. package/components/builder/editors/CoverBlockEditor.tsx +14 -6
  10. package/components/builder/editors/ImageBlockEditor.tsx +8 -3
  11. package/components/builder/editors/ImageGridBlockEditor.tsx +8 -3
  12. package/components/builder/editors/ProjectGridEditor.tsx +7 -46
  13. package/components/builder/editors/SpacerBlockEditor.tsx +4 -1
  14. package/components/builder/editors/StaggerSettings.tsx +2 -1
  15. package/components/builder/editors/TextBlockEditor.tsx +8 -3
  16. package/components/builder/editors/VideoBlockEditor.tsx +10 -4
  17. package/components/builder/editors/section-icons.tsx +492 -0
  18. package/components/builder/editors/shared.tsx +23 -4
  19. package/components/builder/live-preview/LiveTextEditor.tsx +1 -1
  20. package/components/builder/settings-panel/BlockLayoutTab.tsx +13 -58
  21. package/components/builder/settings-panel/ColumnV2Settings.tsx +4 -1
  22. package/components/builder/settings-panel/LayoutTab.tsx +11 -47
  23. package/components/builder/settings-panel/PageSettings.tsx +10 -4
  24. package/components/builder/settings-panel/ParallaxGroupSettings.tsx +6 -2
  25. package/components/builder/settings-panel/ParallaxSlideSettings.tsx +8 -3
  26. package/components/builder/settings-panel/SectionV2LayoutTab.tsx +11 -47
  27. package/components/builder/settings-panel/SectionV2Settings.tsx +6 -27
  28. package/components/ui/Navbar.tsx +151 -30
  29. package/lib/sanity/types.ts +22 -0
  30. package/package.json +5 -2
  31. package/styles/base.css +7 -3
@@ -0,0 +1,492 @@
1
+ /**
2
+ * section-icons.tsx — Centralized colored section header icons.
3
+ *
4
+ * Single source of truth for ALL SettingsSection icons across the builder.
5
+ * Each concept (Spacing, Background, Border, etc.) has one icon + one color,
6
+ * used consistently everywhere it appears (blocks, sections, pages, etc.).
7
+ *
8
+ * Color palette (semantic grouping):
9
+ * Amber #d97706 / #fef3c7 — Spacing, Style
10
+ * Rose #e11d48 / #ffe4e6 — Offset
11
+ * Indigo #6366f1 / #e0e7ff — Background, Cover Background
12
+ * Slate #475569 / #f1f5f9 — Border
13
+ * Blue #2563eb / #dbeafe — Typography, Grid, Grid Gaps, Column Size
14
+ * Cyan #0891b2 / #cffafe — Content, Source, Images, Projects
15
+ * Green #059669 / #d1fae5 — Animation, Stagger, Transition
16
+ * Purple #7c3aed / #ede9fe — Position, Link, Alignment
17
+ * Orange #ea580c / #ffedd5 — Appearance, Cover Effects
18
+ * Teal #0d9488 / #ccfbf1 — Layout, Layout Preset
19
+ * Sky #0284c7 / #e0f2fe — Playback, Video, Height
20
+ * Pink #db2777 / #fce7f3 — Options, CTA Button
21
+ * Neutral #525252 / #f5f5f5 — General, Info, SEO
22
+ * Violet #8b5cf6 / #ede9fe — Navigation, Navbar Color
23
+ * Red #dc2626 / #fee2e2 — Overlay
24
+ *
25
+ * Session 163: Created — unified icon system for the entire builder.
26
+ */
27
+
28
+ import type { ReactNode } from "react";
29
+
30
+ // ============================================
31
+ // Icon + color definitions
32
+ // ============================================
33
+
34
+ export interface SectionIconDef {
35
+ icon: ReactNode;
36
+ color: string; // stroke/fill color for the SVG
37
+ bg: string; // background pill color
38
+ }
39
+
40
+ // ── Spacing (Amber) ──
41
+ export function SpacingIcon() {
42
+ return (
43
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#d97706" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
44
+ <rect x="3" y="3" width="18" height="18" rx="2" strokeDasharray="4 2" />
45
+ <rect x="7" y="7" width="10" height="10" rx="1" />
46
+ </svg>
47
+ );
48
+ }
49
+ SpacingIcon.bg = "#fef3c7";
50
+
51
+ // ── Offset (Rose) ──
52
+ export function OffsetIcon() {
53
+ return (
54
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#e11d48" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
55
+ <rect x="3" y="3" width="14" height="14" rx="2" strokeDasharray="4 2" opacity="0.5" />
56
+ <rect x="7" y="7" width="14" height="14" rx="2" />
57
+ <path d="M5 5 L7 7" strokeWidth="1.5" />
58
+ </svg>
59
+ );
60
+ }
61
+ OffsetIcon.bg = "#ffe4e6";
62
+
63
+ // ── Background (Indigo) ──
64
+ export function BackgroundIcon() {
65
+ return (
66
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#6366f1" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
67
+ <rect x="3" y="3" width="18" height="18" rx="2" />
68
+ <circle cx="8.5" cy="8.5" r="1.5" />
69
+ <polyline points="21 15 16 10 5 21" />
70
+ </svg>
71
+ );
72
+ }
73
+ BackgroundIcon.bg = "#e0e7ff";
74
+
75
+ // ── Border (Slate) ──
76
+ export function BorderIcon() {
77
+ return (
78
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#475569" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
79
+ <rect x="3" y="3" width="18" height="18" rx="3" />
80
+ <path d="M3 9 L21 9" strokeWidth="1.5" opacity="0.5" />
81
+ </svg>
82
+ );
83
+ }
84
+ BorderIcon.bg = "#f1f5f9";
85
+
86
+ // ── Alignment (Purple) ──
87
+ export function AlignmentIcon() {
88
+ return (
89
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#7c3aed" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
90
+ <line x1="18" y1="10" x2="6" y2="10" />
91
+ <line x1="21" y1="6" x2="3" y2="6" />
92
+ <line x1="15" y1="14" x2="9" y2="14" />
93
+ <line x1="18" y1="18" x2="6" y2="18" />
94
+ </svg>
95
+ );
96
+ }
97
+ AlignmentIcon.bg = "#ede9fe";
98
+
99
+ // ── Typography (Blue) ──
100
+ export function TypographyIcon() {
101
+ return (
102
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#2563eb" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
103
+ <polyline points="4 7 4 4 20 4 20 7" />
104
+ <line x1="9" y1="20" x2="15" y2="20" />
105
+ <line x1="12" y1="4" x2="12" y2="20" />
106
+ </svg>
107
+ );
108
+ }
109
+ TypographyIcon.bg = "#dbeafe";
110
+
111
+ // ── Grid / Grid Gaps (Blue) ──
112
+ export function GridIcon() {
113
+ return (
114
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#2563eb" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
115
+ <rect x="3" y="3" width="7" height="7" />
116
+ <rect x="14" y="3" width="7" height="7" />
117
+ <rect x="14" y="14" width="7" height="7" />
118
+ <rect x="3" y="14" width="7" height="7" />
119
+ </svg>
120
+ );
121
+ }
122
+ GridIcon.bg = "#dbeafe";
123
+
124
+ // ── Grid Gaps (Blue — slightly different icon) ──
125
+ export function GridGapsIcon() {
126
+ return (
127
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#2563eb" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
128
+ <rect x="3" y="3" width="7" height="7" rx="1" />
129
+ <rect x="14" y="3" width="7" height="7" rx="1" />
130
+ <rect x="3" y="14" width="7" height="7" rx="1" />
131
+ <rect x="14" y="14" width="7" height="7" rx="1" />
132
+ <line x1="12" y1="3" x2="12" y2="21" strokeDasharray="2 2" opacity="0.5" />
133
+ <line x1="3" y1="12" x2="21" y2="12" strokeDasharray="2 2" opacity="0.5" />
134
+ </svg>
135
+ );
136
+ }
137
+ GridGapsIcon.bg = "#dbeafe";
138
+
139
+ // ── Column Size (Blue) ──
140
+ export function ColumnSizeIcon() {
141
+ return (
142
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#2563eb" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
143
+ <rect x="3" y="4" width="18" height="16" rx="2" />
144
+ <line x1="9" y1="4" x2="9" y2="20" />
145
+ <path d="M4 12 L7 12" />
146
+ <path d="M11 12 L20 12" />
147
+ </svg>
148
+ );
149
+ }
150
+ ColumnSizeIcon.bg = "#dbeafe";
151
+
152
+ // ── Layout Preset (Teal) ──
153
+ export function LayoutPresetIcon() {
154
+ return (
155
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0d9488" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
156
+ <rect x="3" y="3" width="18" height="18" rx="2" />
157
+ <line x1="9" y1="3" x2="9" y2="21" />
158
+ <line x1="3" y1="12" x2="9" y2="12" />
159
+ </svg>
160
+ );
161
+ }
162
+ LayoutPresetIcon.bg = "#ccfbf1";
163
+
164
+ // ── Layout (Teal) ──
165
+ export function LayoutIcon() {
166
+ return (
167
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0d9488" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
168
+ <rect x="3" y="3" width="18" height="18" rx="2" />
169
+ <line x1="3" y1="9" x2="21" y2="9" />
170
+ <line x1="9" y1="9" x2="9" y2="21" />
171
+ </svg>
172
+ );
173
+ }
174
+ LayoutIcon.bg = "#ccfbf1";
175
+
176
+ // ── Content / Source (Cyan) ──
177
+ export function ContentIcon() {
178
+ return (
179
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0891b2" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
180
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
181
+ <polyline points="14 2 14 8 20 8" />
182
+ <line x1="16" y1="13" x2="8" y2="13" />
183
+ <line x1="16" y1="17" x2="8" y2="17" />
184
+ </svg>
185
+ );
186
+ }
187
+ ContentIcon.bg = "#cffafe";
188
+
189
+ // ── Source (Cyan) ──
190
+ export function SourceIcon() {
191
+ return (
192
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0891b2" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
193
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
194
+ <polyline points="7 10 12 15 17 10" />
195
+ <line x1="12" y1="15" x2="12" y2="3" />
196
+ </svg>
197
+ );
198
+ }
199
+ SourceIcon.bg = "#cffafe";
200
+
201
+ // ── Images (Cyan) ──
202
+ export function ImagesIcon() {
203
+ return (
204
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0891b2" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
205
+ <rect x="3" y="3" width="18" height="18" rx="2" />
206
+ <circle cx="8.5" cy="8.5" r="1.5" />
207
+ <polyline points="21 15 16 10 5 21" />
208
+ </svg>
209
+ );
210
+ }
211
+ ImagesIcon.bg = "#cffafe";
212
+
213
+ // ── Projects (Cyan) ──
214
+ export function ProjectsIcon() {
215
+ return (
216
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0891b2" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
217
+ <rect x="3" y="3" width="18" height="7" rx="2" />
218
+ <rect x="3" y="14" width="18" height="7" rx="2" />
219
+ <circle cx="7" cy="6.5" r="1" />
220
+ <circle cx="7" cy="17.5" r="1" />
221
+ <line x1="10" y1="6.5" x2="17" y2="6.5" />
222
+ <line x1="10" y1="17.5" x2="17" y2="17.5" />
223
+ </svg>
224
+ );
225
+ }
226
+ ProjectsIcon.bg = "#cffafe";
227
+
228
+ // ── Text (Cyan) ──
229
+ export function TextIcon() {
230
+ return (
231
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0891b2" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
232
+ <line x1="17" y1="10" x2="3" y2="10" />
233
+ <line x1="21" y1="6" x2="3" y2="6" />
234
+ <line x1="21" y1="14" x2="3" y2="14" />
235
+ <line x1="17" y1="18" x2="3" y2="18" />
236
+ </svg>
237
+ );
238
+ }
239
+ TextIcon.bg = "#cffafe";
240
+
241
+ // ── Columns (Blue) ──
242
+ export function ColumnsIcon() {
243
+ return (
244
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#2563eb" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
245
+ <rect x="3" y="3" width="18" height="18" rx="2" />
246
+ <line x1="9" y1="3" x2="9" y2="21" />
247
+ <line x1="15" y1="3" x2="15" y2="21" />
248
+ </svg>
249
+ );
250
+ }
251
+ ColumnsIcon.bg = "#dbeafe";
252
+
253
+ // ── Appearance (Orange) ──
254
+ export function AppearanceIcon() {
255
+ return (
256
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#ea580c" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
257
+ <circle cx="12" cy="12" r="9" />
258
+ <path d="M12 3 A9 9 0 0 1 12 21 Z" fill="#ea580c" opacity="0.2" />
259
+ <circle cx="12" cy="12" r="3" />
260
+ </svg>
261
+ );
262
+ }
263
+ AppearanceIcon.bg = "#ffedd5";
264
+
265
+ // ── Style (Amber) ──
266
+ export function StyleIcon() {
267
+ return (
268
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#d97706" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
269
+ <circle cx="13.5" cy="6.5" r="2.5" />
270
+ <path d="M17 2H7a5 5 0 0 0-5 5v10a5 5 0 0 0 5 5h10a5 5 0 0 0 5-5V7a5 5 0 0 0-5-5z" />
271
+ </svg>
272
+ );
273
+ }
274
+ StyleIcon.bg = "#fef3c7";
275
+
276
+ // ── Animation / Entrance (Green) ──
277
+ export function AnimationIcon() {
278
+ return (
279
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#059669" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
280
+ <path d="M5 12h14" />
281
+ <path d="M12 5l7 7-7 7" />
282
+ </svg>
283
+ );
284
+ }
285
+ AnimationIcon.bg = "#d1fae5";
286
+
287
+ // ── Stagger Children (Green) ──
288
+ export function StaggerIcon() {
289
+ return (
290
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#059669" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
291
+ <line x1="4" y1="6" x2="14" y2="6" />
292
+ <line x1="7" y1="12" x2="17" y2="12" />
293
+ <line x1="10" y1="18" x2="20" y2="18" />
294
+ </svg>
295
+ );
296
+ }
297
+ StaggerIcon.bg = "#d1fae5";
298
+
299
+ // ── Transition Effect (Green) ──
300
+ export function TransitionIcon() {
301
+ return (
302
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#059669" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
303
+ <rect x="2" y="7" width="8" height="10" rx="2" opacity="0.5" />
304
+ <rect x="14" y="7" width="8" height="10" rx="2" />
305
+ <path d="M10 12 L14 12" />
306
+ <path d="M12 10 L14 12 L12 14" />
307
+ </svg>
308
+ );
309
+ }
310
+ TransitionIcon.bg = "#d1fae5";
311
+
312
+ // ── Position (Purple) ──
313
+ export function PositionIcon() {
314
+ return (
315
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#7c3aed" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
316
+ <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" />
317
+ <circle cx="12" cy="10" r="3" />
318
+ </svg>
319
+ );
320
+ }
321
+ PositionIcon.bg = "#ede9fe";
322
+
323
+ // ── Link (Purple) ──
324
+ export function LinkIcon() {
325
+ return (
326
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#7c3aed" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
327
+ <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" />
328
+ <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" />
329
+ </svg>
330
+ );
331
+ }
332
+ LinkIcon.bg = "#ede9fe";
333
+
334
+ // ── Video (Sky) ──
335
+ export function VideoIcon() {
336
+ return (
337
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0284c7" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
338
+ <rect x="2" y="4" width="14" height="16" rx="2" />
339
+ <path d="M16 10 L22 7 L22 17 L16 14 Z" />
340
+ </svg>
341
+ );
342
+ }
343
+ VideoIcon.bg = "#e0f2fe";
344
+
345
+ // ── Playback (Sky) ──
346
+ export function PlaybackIcon() {
347
+ return (
348
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0284c7" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
349
+ <circle cx="12" cy="12" r="9" />
350
+ <polygon points="10 8 16 12 10 16" fill="#0284c7" opacity="0.3" />
351
+ </svg>
352
+ );
353
+ }
354
+ PlaybackIcon.bg = "#e0f2fe";
355
+
356
+ // ── Height (Sky) ──
357
+ export function HeightIcon() {
358
+ return (
359
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0284c7" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
360
+ <path d="M12 4 L12 20" />
361
+ <path d="M8 8 L12 4 L16 8" />
362
+ <path d="M8 16 L12 20 L16 16" />
363
+ </svg>
364
+ );
365
+ }
366
+ HeightIcon.bg = "#e0f2fe";
367
+
368
+ // ── Options / CTA Button (Pink) ──
369
+ export function OptionsIcon() {
370
+ return (
371
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#db2777" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
372
+ <circle cx="12" cy="12" r="1" />
373
+ <circle cx="19" cy="12" r="1" />
374
+ <circle cx="5" cy="12" r="1" />
375
+ </svg>
376
+ );
377
+ }
378
+ OptionsIcon.bg = "#fce7f3";
379
+
380
+ // ── CTA Button (Pink) ──
381
+ export function CTAButtonIcon() {
382
+ return (
383
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#db2777" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
384
+ <rect x="3" y="8" width="18" height="8" rx="3" />
385
+ <line x1="8" y1="12" x2="16" y2="12" />
386
+ </svg>
387
+ );
388
+ }
389
+ CTAButtonIcon.bg = "#fce7f3";
390
+
391
+ // ── Settings (Amber) — generic ──
392
+ export function SettingsIcon() {
393
+ return (
394
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#d97706" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
395
+ <circle cx="12" cy="12" r="3" />
396
+ <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
397
+ </svg>
398
+ );
399
+ }
400
+ SettingsIcon.bg = "#fef3c7";
401
+
402
+ // ── General / Info (Neutral) ──
403
+ export function GeneralIcon() {
404
+ return (
405
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#525252" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
406
+ <circle cx="12" cy="12" r="9" />
407
+ <line x1="12" y1="16" x2="12" y2="12" />
408
+ <line x1="12" y1="8" x2="12.01" y2="8" />
409
+ </svg>
410
+ );
411
+ }
412
+ GeneralIcon.bg = "#f5f5f5";
413
+
414
+ // ── Info (Neutral) ──
415
+ export function InfoIcon() {
416
+ return (
417
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#525252" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
418
+ <circle cx="12" cy="12" r="9" />
419
+ <line x1="12" y1="16" x2="12" y2="12" />
420
+ <line x1="12" y1="8" x2="12.01" y2="8" />
421
+ </svg>
422
+ );
423
+ }
424
+ InfoIcon.bg = "#f5f5f5";
425
+
426
+ // ── SEO (Neutral) ──
427
+ export function SEOIcon() {
428
+ return (
429
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#525252" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
430
+ <circle cx="11" cy="11" r="8" />
431
+ <line x1="21" y1="21" x2="16.65" y2="16.65" />
432
+ </svg>
433
+ );
434
+ }
435
+ SEOIcon.bg = "#f5f5f5";
436
+
437
+ // ── Navigation (Violet) ──
438
+ export function NavigationIcon() {
439
+ return (
440
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#8b5cf6" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
441
+ <line x1="3" y1="12" x2="21" y2="12" />
442
+ <line x1="3" y1="6" x2="21" y2="6" />
443
+ <line x1="3" y1="18" x2="21" y2="18" />
444
+ </svg>
445
+ );
446
+ }
447
+ NavigationIcon.bg = "#ede9fe";
448
+
449
+ // ── Navbar Color (Violet) ──
450
+ export function NavbarColorIcon() {
451
+ return (
452
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#8b5cf6" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
453
+ <rect x="3" y="3" width="18" height="6" rx="2" />
454
+ <circle cx="7" cy="6" r="1.5" fill="#8b5cf6" opacity="0.3" />
455
+ <line x1="11" y1="6" x2="17" y2="6" />
456
+ </svg>
457
+ );
458
+ }
459
+ NavbarColorIcon.bg = "#ede9fe";
460
+
461
+ // ── Overlay (Red) ──
462
+ export function OverlayIcon() {
463
+ return (
464
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#dc2626" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
465
+ <rect x="3" y="3" width="18" height="18" rx="2" />
466
+ <rect x="3" y="3" width="18" height="18" rx="2" fill="#dc2626" opacity="0.15" />
467
+ </svg>
468
+ );
469
+ }
470
+ OverlayIcon.bg = "#fee2e2";
471
+
472
+ // ── Cover Background (Indigo) ──
473
+ export function CoverBackgroundIcon() {
474
+ return (
475
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#6366f1" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
476
+ <rect x="3" y="3" width="18" height="18" rx="2" />
477
+ <path d="M3 3 L21 21" opacity="0.4" />
478
+ <path d="M21 3 L3 21" opacity="0.4" />
479
+ </svg>
480
+ );
481
+ }
482
+ CoverBackgroundIcon.bg = "#e0e7ff";
483
+
484
+ // ── Cover Effects (Orange) ──
485
+ export function CoverEffectsIcon() {
486
+ return (
487
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#ea580c" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
488
+ <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" />
489
+ </svg>
490
+ );
491
+ }
492
+ CoverEffectsIcon.bg = "#ffedd5";
@@ -153,8 +153,13 @@ export function SettingsField({
153
153
  // ============================================
154
154
 
155
155
  /**
156
- * Collapsible section: clean text header + thin border separator.
157
- * No gray background, no uppercase.
156
+ * Collapsible section with optional colored icon pill.
157
+ *
158
+ * When an `icon` is provided with a `bg` static property (from section-icons.tsx),
159
+ * it renders as a colored pill (26×26px rounded square with tinted background).
160
+ * Without `bg`, the icon renders inline in neutral gray (legacy behavior).
161
+ *
162
+ * Session 163: Upgraded to colored icon pills for visual consistency with nav builder.
158
163
  */
159
164
  export function SettingsSection({
160
165
  title,
@@ -169,14 +174,28 @@ export function SettingsSection({
169
174
  }) {
170
175
  const [isOpen, setIsOpen] = useState(defaultOpen);
171
176
 
177
+ // Check if icon component has a `.bg` property (colored icon from section-icons.tsx)
178
+ const iconBg = icon && typeof icon === "object"
179
+ ? ((icon as unknown as { type?: { bg?: string } }).type?.bg ?? null)
180
+ : null;
181
+
172
182
  return (
173
183
  <div className="border-b border-[#f0f0f0] last:border-b-0">
174
184
  <button
175
185
  onClick={() => setIsOpen(!isOpen)}
176
186
  className="w-full flex items-center justify-between px-4 py-3 transition-colors hover:bg-[#fafafa] group"
177
187
  >
178
- <span className="flex items-center gap-1.5 text-xs font-medium text-neutral-900">
179
- {icon && <span className="text-neutral-400 flex-shrink-0">{icon}</span>}
188
+ <span className="flex items-center gap-2 text-xs font-medium text-neutral-900">
189
+ {icon && iconBg ? (
190
+ <span
191
+ className="w-[26px] h-[26px] rounded-[7px] flex items-center justify-center shrink-0"
192
+ style={{ background: iconBg }}
193
+ >
194
+ {icon}
195
+ </span>
196
+ ) : icon ? (
197
+ <span className="text-neutral-400 flex-shrink-0">{icon}</span>
198
+ ) : null}
180
199
  {title}
181
200
  </span>
182
201
  <span className="text-base text-neutral-300 font-light leading-none transition-colors group-hover:text-neutral-500">
@@ -149,7 +149,7 @@ export default function LiveTextEditor({ block, editable = false }: { block: Tex
149
149
  fontFamily: "inherit",
150
150
  outline: "none",
151
151
  whiteSpace: "pre-wrap",
152
- wordBreak: "break-word",
152
+ wordBreak: "normal",
153
153
  minHeight: "1em",
154
154
  // Multi-column layout: gap inherits global grid gutter
155
155
  ...(cols ? {
@@ -145,59 +145,14 @@ function AlignmentButtons<T extends string>({
145
145
  );
146
146
  }
147
147
 
148
- // ── Section title icons (small, inline) ──
149
-
150
- function AlignmentSectionIcon() {
151
- return (
152
- <svg width={14} height={14} viewBox="0 0 14 14" fill="none">
153
- <rect x="1" y="2" width="9" height="2" rx="0.5" fill="currentColor" opacity="0.7" />
154
- <rect x="3" y="6" width="8" height="2" rx="0.5" fill="currentColor" opacity="0.5" />
155
- <rect x="2" y="10" width="10" height="2" rx="0.5" fill="currentColor" opacity="0.7" />
156
- </svg>
157
- );
158
- }
159
-
160
- function SpacingSectionIcon() {
161
- return (
162
- <svg width={14} height={14} viewBox="0 0 14 14" fill="none">
163
- <rect x="4" y="4" width="6" height="6" rx="1" stroke="currentColor" strokeWidth="1" fill="none" opacity="0.5" />
164
- <path d="M7 1 L7 3.5" stroke="currentColor" strokeWidth="0.8" opacity="0.7" />
165
- <path d="M7 10.5 L7 13" stroke="currentColor" strokeWidth="0.8" opacity="0.7" />
166
- <path d="M1 7 L3.5 7" stroke="currentColor" strokeWidth="0.8" opacity="0.7" />
167
- <path d="M10.5 7 L13 7" stroke="currentColor" strokeWidth="0.8" opacity="0.7" />
168
- </svg>
169
- );
170
- }
171
-
172
- function OffsetSectionIcon() {
173
- return (
174
- <svg width={14} height={14} viewBox="0 0 14 14" fill="none">
175
- <rect x="3" y="3" width="8" height="8" rx="1" stroke="currentColor" strokeWidth="0.8" strokeDasharray="2 1" fill="none" opacity="0.35" />
176
- <rect x="5" y="5" width="6" height="6" rx="1" stroke="currentColor" strokeWidth="1" fill="none" opacity="0.7" />
177
- <path d="M4 4 L5 5" stroke="currentColor" strokeWidth="0.6" opacity="0.5" />
178
- </svg>
179
- );
180
- }
181
-
182
- function BackgroundSectionIcon() {
183
- return (
184
- <svg width={14} height={14} viewBox="0 0 14 14" fill="none">
185
- <rect x="1.5" y="1.5" width="11" height="11" rx="2" fill="currentColor" opacity="0.15" />
186
- <rect x="1.5" y="1.5" width="11" height="11" rx="2" stroke="currentColor" strokeWidth="0.8" opacity="0.5" fill="none" />
187
- <circle cx="5" cy="5" r="1.5" fill="currentColor" opacity="0.5" />
188
- <path d="M1.5 10 L5 7 L8 9 L10.5 6.5 L12.5 8.5 L12.5 11 C12.5 11.8 11.8 12.5 11 12.5 L3 12.5 C2.2 12.5 1.5 11.8 1.5 11 Z" fill="currentColor" opacity="0.3" />
189
- </svg>
190
- );
191
- }
192
-
193
- function BorderSectionIcon() {
194
- return (
195
- <svg width={14} height={14} viewBox="0 0 14 14" fill="none">
196
- <rect x="2" y="2" width="10" height="10" rx="2" stroke="currentColor" strokeWidth="1.2" fill="none" opacity="0.6" />
197
- <rect x="2" y="2" width="10" height="1.2" rx="0.5" fill="currentColor" opacity="0.7" />
198
- </svg>
199
- );
200
- }
148
+ // ── Section title icons (centralized colored icons — Session 163) ──
149
+ import {
150
+ AlignmentIcon,
151
+ SpacingIcon,
152
+ OffsetIcon,
153
+ BackgroundIcon,
154
+ BorderIcon,
155
+ } from "../editors/section-icons";
201
156
 
202
157
  // ── Override indicator badge ──
203
158
 
@@ -287,7 +242,7 @@ export function BlockLayoutTab({ block }: { block: ContentBlock }) {
287
242
  )}
288
243
 
289
244
  {/* Alignment */}
290
- <SettingsSection title="Alignment" defaultOpen icon={<AlignmentSectionIcon />}>
245
+ <SettingsSection title="Alignment" defaultOpen icon={<AlignmentIcon />}>
291
246
  <SettingsField label="Horizontal">
292
247
  <AlignmentButtons<AlignH>
293
248
  options={[
@@ -329,7 +284,7 @@ export function BlockLayoutTab({ block }: { block: ContentBlock }) {
329
284
  </SettingsSection>
330
285
 
331
286
  {/* Spacing (Padding) */}
332
- <SettingsSection title="Spacing" defaultOpen icon={<SpacingSectionIcon />}>
287
+ <SettingsSection title="Spacing" defaultOpen icon={<SpacingIcon />}>
333
288
  <TRBLInputs
334
289
  top={getBlockLayoutValue<string>(block, activeViewport, "spacing_top", "0")}
335
290
  right={getBlockLayoutValue<string>(block, activeViewport, "spacing_right", "0")}
@@ -348,7 +303,7 @@ export function BlockLayoutTab({ block }: { block: ContentBlock }) {
348
303
  </SettingsSection>
349
304
 
350
305
  {/* Offset (Margin) */}
351
- <SettingsSection title="Offset" icon={<OffsetSectionIcon />}>
306
+ <SettingsSection title="Offset" icon={<OffsetIcon />}>
352
307
  <TRBLInputs
353
308
  top={getBlockLayoutValue<string>(block, activeViewport, "offset_top", "0")}
354
309
  right={getBlockLayoutValue<string>(block, activeViewport, "offset_right", "0")}
@@ -367,7 +322,7 @@ export function BlockLayoutTab({ block }: { block: ContentBlock }) {
367
322
  </SettingsSection>
368
323
 
369
324
  {/* Background */}
370
- <SettingsSection title="Background" defaultOpen icon={<BackgroundSectionIcon />}>
325
+ <SettingsSection title="Background" defaultOpen icon={<BackgroundIcon />}>
371
326
  <SettingsField label="Color">
372
327
  <ColorSwatchPicker
373
328
  value={parseColorField(getBlockLayoutValue<string>(block, activeViewport, "background_color", ""))}
@@ -466,7 +421,7 @@ export function BlockLayoutTab({ block }: { block: ContentBlock }) {
466
421
  </SettingsSection>
467
422
 
468
423
  {/* Border */}
469
- <SettingsSection title="Border" icon={<BorderSectionIcon />}>
424
+ <SettingsSection title="Border" icon={<BorderIcon />}>
470
425
  <SettingsField label="Color">
471
426
  <ColorSwatchPicker
472
427
  value={parseColorField(getBlockLayoutValue<string>(block, activeViewport, "border_color", ""))}