@jimmy_harika/websitekit 0.5.3 → 0.5.5

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.
@@ -1,26 +1,54 @@
1
1
  "use client";
2
2
 
3
3
  /**
4
- * Top-level editor. Floating-panel layout: canvas owns the space; left/right
5
- * tools open as on-call glass cards so the live page stays large (Pixieset-style
6
- * preview-first). Host apps theme via [data-websitekit-editor] + CSS vars.
4
+ * Editor shell — canvas-first with ONE consistent right dock for every panel
5
+ * (sections, design, inspect, add block, host tools). Left rail is labeled.
7
6
  */
8
7
  import { useEffect, useMemo, useRef, useState, type ReactNode } from "react";
9
- import { List, Palette, PanelRight, Plus, Sliders, X } from "lucide-react";
8
+ import {
9
+ LayoutTemplate,
10
+ List,
11
+ Palette,
12
+ PanelRight,
13
+ Plus,
14
+ Sliders,
15
+ } from "lucide-react";
10
16
  import type { PageDocument } from "../model";
11
17
  import type { Catalog } from "../registry";
12
18
  import { BuilderProvider, useBuilder, useCreateBuilderStore } from "../store";
13
19
  import { EditorCapsContext } from "./edit-primitives";
14
- import { EditorUiContext, type Device, type EditorUi, type MobilePanel, useEditorUi } from "./ui-context";
20
+ import {
21
+ EditorUiContext,
22
+ type Device,
23
+ type EditorUi,
24
+ type MobilePanel,
25
+ useEditorUi,
26
+ } from "./ui-context";
15
27
  import { Toolbar } from "./Toolbar";
16
28
  import { Canvas } from "./Canvas";
17
29
  import { Inspector } from "./Inspector";
18
- import { BlockLibrary } from "./BlockLibrary";
30
+ import { BlockLibraryBody } from "./BlockLibrary";
19
31
  import { ThemePanel } from "./ThemePanel";
20
32
  import { SectionsPanel } from "./SectionsPanel";
21
33
  import { TemplateGallery, type TemplateMeta } from "./TemplateGallery";
22
34
  import { useEditorShortcuts } from "./shortcuts";
23
- import { cn } from "../lib/cn";
35
+ import { EditorDock, EditorRail } from "./EditorDock";
36
+
37
+ export type DockMode =
38
+ | "sections"
39
+ | "design"
40
+ | "inspector"
41
+ | "library"
42
+ | "host"
43
+ | null;
44
+
45
+ export interface HostRailItem {
46
+ id: string;
47
+ label: string;
48
+ icon: ReactNode;
49
+ active?: boolean;
50
+ onClick: () => void;
51
+ }
24
52
 
25
53
  export interface PageBuilderProps {
26
54
  catalog: Catalog;
@@ -31,15 +59,11 @@ export interface PageBuilderProps {
31
59
  templates?: TemplateMeta[];
32
60
  saving?: "idle" | "saving" | "saved";
33
61
  leading?: ReactNode;
34
- /** Extra tools in the left icon rail (host app: SEO, Domain, …). */
35
- railExtra?: ReactNode;
36
- /** Floating host panel body (when host manages its own panel open state). */
37
- hostPanel?: ReactNode;
62
+ /** Host tools in the labeled left rail (SEO, Domain, …). */
63
+ hostRail?: HostRailItem[];
64
+ /** When set, dock shows this host body (same right dock as all other panels). */
65
+ hostDock?: { title: string; subtitle?: string; body: ReactNode } | null;
38
66
  viewUrl?: string;
39
- /**
40
- * floating (default) = max canvas, panels on-call.
41
- * classic = permanent 3-column rails.
42
- */
43
67
  layout?: "floating" | "classic";
44
68
  }
45
69
 
@@ -55,8 +79,6 @@ export function PageBuilder(props: PageBuilderProps) {
55
79
  );
56
80
  }
57
81
 
58
- type LeftPanel = "sections" | "design" | null;
59
-
60
82
  function PageBuilderInner({
61
83
  catalog,
62
84
  onChange,
@@ -65,31 +87,53 @@ function PageBuilderInner({
65
87
  saving,
66
88
  leading,
67
89
  viewUrl,
68
- railExtra,
69
- hostPanel,
90
+ hostRail,
91
+ hostDock,
70
92
  layout = "floating",
71
93
  }: PageBuilderProps) {
72
94
  const doc = useBuilder((s) => s.doc);
73
95
  const selectedId = useBuilder((s) => s.selectedId);
96
+ const select = useBuilder((s) => s.select);
74
97
  const [device, setDevice] = useState<Device>("desktop");
75
98
  const [libraryIndex, setLibraryIndex] = useState<number | null>(null);
76
99
  const [inspectorOpen, setInspectorOpen] = useState(false);
77
100
  const [templatesOpen, setTemplatesOpen] = useState(false);
78
- const [leftPanel, setLeftPanel] = useState<LeftPanel>("sections");
101
+ const [dock, setDock] = useState<DockMode>("sections");
79
102
  const [mobilePanel, setMobilePanel] = useState<MobilePanel>(null);
80
103
 
81
- // Open inspector when a section is selected (floating mode); keep open in classic.
104
+ // Library open force library dock. Close library restore sections.
82
105
  useEffect(() => {
83
- if (layout === "floating" && selectedId) setInspectorOpen(true);
84
- }, [selectedId, layout]);
106
+ if (libraryIndex !== null) setDock("library");
107
+ }, [libraryIndex]);
108
+
109
+ // Selecting a section opens inspector in the same dock.
110
+ useEffect(() => {
111
+ if (selectedId && libraryIndex === null && !hostDock) {
112
+ setDock("inspector");
113
+ setInspectorOpen(true);
114
+ }
115
+ }, [selectedId, libraryIndex, hostDock]);
116
+
117
+ // Host dock takes over the unified dock when provided.
118
+ useEffect(() => {
119
+ if (hostDock) setDock("host");
120
+ else if (dock === "host") setDock("sections");
121
+ // eslint-disable-next-line react-hooks/exhaustive-deps
122
+ }, [hostDock]);
85
123
 
86
124
  const ui: EditorUi = useMemo(
87
125
  () => ({
88
126
  device,
89
127
  setDevice,
90
128
  libraryIndex,
91
- openLibrary: setLibraryIndex,
92
- closeLibrary: () => setLibraryIndex(null),
129
+ openLibrary: (index: number | null) => {
130
+ setLibraryIndex(index);
131
+ if (index !== null) setDock("library");
132
+ },
133
+ closeLibrary: () => {
134
+ setLibraryIndex(null);
135
+ setDock((d) => (d === "library" ? "sections" : d));
136
+ },
93
137
  inspectorOpen,
94
138
  setInspectorOpen,
95
139
  templatesOpen,
@@ -111,295 +155,213 @@ function PageBuilderInner({
111
155
  onChangeRef.current?.(doc);
112
156
  }, [doc]);
113
157
 
114
- useEditorShortcuts({ ui, onPublish: onPublish ? () => onPublish(doc) : undefined });
158
+ useEditorShortcuts({
159
+ ui,
160
+ onPublish: onPublish ? () => onPublish(doc) : undefined,
161
+ });
115
162
 
116
- const toggleLeft = (p: LeftPanel) =>
117
- setLeftPanel((cur) => (cur === p ? null : p));
163
+ const openDock = (mode: DockMode) => {
164
+ if (mode === "library") {
165
+ ui.openLibrary(doc.sections.length);
166
+ return;
167
+ }
168
+ // Toggle off if same dock re-clicked
169
+ if (mode !== null && mode === dock) {
170
+ setDock(null);
171
+ return;
172
+ }
173
+ // Leaving library
174
+ if (libraryIndex !== null) {
175
+ setLibraryIndex(null);
176
+ }
177
+ setDock(mode);
178
+ if (mode === "inspector") setInspectorOpen(true);
179
+ };
118
180
 
119
- if (layout === "classic") {
120
- return (
121
- <EditorUiContext.Provider value={ui}>
122
- <div data-websitekit-editor data-layout="classic" className="flex h-full min-h-0 flex-col bg-muted">
123
- <Toolbar
124
- onPublish={onPublish ? () => onPublish(doc) : undefined}
125
- saving={saving}
126
- designOpen={leftPanel === "design"}
127
- onToggleDesign={() => toggleLeft("design")}
128
- hasTemplates={!!templates && templates.length > 0}
129
- leading={leading}
130
- viewUrl={viewUrl}
131
- />
132
- <div className="flex min-h-0 flex-1">
133
- <aside className="hidden w-64 shrink-0 flex-col border-r border-border bg-card md:flex">
134
- {leftPanel === "design" ? (
135
- <>
136
- <div className="border-b border-border px-3 py-2.5 text-xs font-semibold uppercase tracking-wide text-muted-foreground">
137
- Design
138
- </div>
139
- <div className="min-h-0 flex-1 overflow-auto">
140
- <ThemePanel />
141
- </div>
142
- </>
143
- ) : (
144
- <SectionsPanel catalog={catalog} />
145
- )}
146
- </aside>
147
- <Canvas catalog={catalog} />
148
- <aside className="hidden w-80 shrink-0 flex-col border-l border-border bg-card md:flex">
149
- <Inspector catalog={catalog} />
150
- </aside>
151
- </div>
152
- <MobileBar />
153
- <MobileSheet catalog={catalog} />
154
- <BlockLibrary catalog={catalog} />
155
- {templates && templates.length > 0 && <TemplateGallery templates={templates} />}
156
- <EditorStyle />
157
- </div>
158
- </EditorUiContext.Provider>
159
- );
160
- }
181
+ const closeDock = () => {
182
+ if (libraryIndex !== null) ui.closeLibrary();
183
+ setDock(null);
184
+ select(null);
185
+ };
186
+
187
+ const railItems = [
188
+ {
189
+ id: "sections",
190
+ label: "Pages",
191
+ icon: <List />,
192
+ active: dock === "sections",
193
+ onClick: () => openDock("sections"),
194
+ },
195
+ {
196
+ id: "add",
197
+ label: "Add",
198
+ icon: <Plus />,
199
+ active: dock === "library",
200
+ onClick: () => openDock("library"),
201
+ },
202
+ {
203
+ id: "design",
204
+ label: "Design",
205
+ icon: <Palette />,
206
+ active: dock === "design",
207
+ onClick: () => openDock("design"),
208
+ },
209
+ {
210
+ id: "inspect",
211
+ label: "Edit",
212
+ icon: <PanelRight />,
213
+ active: dock === "inspector",
214
+ onClick: () => openDock("inspector"),
215
+ },
216
+ ...(templates && templates.length
217
+ ? [
218
+ {
219
+ id: "templates",
220
+ label: "Looks",
221
+ icon: <LayoutTemplate />,
222
+ active: templatesOpen,
223
+ onClick: () => ui.setTemplatesOpen(true),
224
+ },
225
+ ]
226
+ : []),
227
+ ...(hostRail ?? []).map((h) => ({
228
+ id: h.id,
229
+ label: h.label,
230
+ icon: h.icon,
231
+ active: !!h.active || (dock === "host" && hostDock != null),
232
+ onClick: () => {
233
+ h.onClick();
234
+ },
235
+ })),
236
+ ];
237
+
238
+ const dockTitle =
239
+ dock === "library"
240
+ ? "Add block"
241
+ : dock === "design"
242
+ ? "Design"
243
+ : dock === "inspector"
244
+ ? "Edit section"
245
+ : dock === "host"
246
+ ? (hostDock?.title ?? "Site")
247
+ : dock === "sections"
248
+ ? "Page structure"
249
+ : "";
250
+
251
+ const dockSubtitle =
252
+ dock === "host"
253
+ ? hostDock?.subtitle
254
+ : dock === "inspector"
255
+ ? selectedId
256
+ ? "Selected block"
257
+ : "Select a block on the page"
258
+ : dock === "library"
259
+ ? "Browse layouts"
260
+ : undefined;
261
+
262
+ const showDock = dock !== null;
161
263
 
162
- // ── Floating layout (default): max canvas, panels on-call ──────────────
163
264
  return (
164
265
  <EditorUiContext.Provider value={ui}>
165
266
  <div
166
267
  data-websitekit-editor
167
- data-layout="floating"
268
+ data-layout={layout}
168
269
  className="relative flex h-full min-h-0 flex-col bg-transparent"
169
270
  >
170
271
  <Toolbar
171
272
  onPublish={onPublish ? () => onPublish(doc) : undefined}
172
273
  saving={saving}
173
- designOpen={leftPanel === "design"}
174
- onToggleDesign={() => toggleLeft("design")}
274
+ designOpen={dock === "design"}
275
+ onToggleDesign={() => openDock("design")}
175
276
  hasTemplates={!!templates && templates.length > 0}
176
277
  leading={leading}
177
278
  viewUrl={viewUrl}
178
279
  floating
179
- inspectorOpen={inspectorOpen}
180
- onToggleInspector={() => setInspectorOpen((v) => !v)}
181
- sectionsOpen={leftPanel === "sections"}
182
- onToggleSections={() => toggleLeft("sections")}
280
+ compact
281
+ onAddBlock={() => openDock("library")}
183
282
  />
184
283
 
185
284
  <div className="relative flex min-h-0 flex-1">
186
- {/* Icon rail — always present, thin */}
187
- <nav
188
- className="z-30 hidden w-12 shrink-0 flex-col items-center gap-1 border-r border-border/40 bg-card/40 py-2 backdrop-blur-xl md:flex"
189
- aria-label="Editor tools"
190
- >
191
- <RailBtn
192
- active={leftPanel === "sections"}
193
- onClick={() => toggleLeft("sections")}
194
- title="Sections"
195
- >
196
- <List className="size-4" />
197
- </RailBtn>
198
- <RailBtn
199
- active={leftPanel === "design"}
200
- onClick={() => toggleLeft("design")}
201
- title="Design"
202
- >
203
- <Palette className="size-4" />
204
- </RailBtn>
205
- <RailBtn
206
- active={false}
207
- onClick={() => ui.openLibrary(doc.sections.length)}
208
- title="Add block"
209
- >
210
- <Plus className="size-4" />
211
- </RailBtn>
212
- <RailBtn
213
- active={inspectorOpen}
214
- onClick={() => setInspectorOpen((v) => !v)}
215
- title="Inspector"
216
- >
217
- <PanelRight className="size-4" />
218
- </RailBtn>
219
- {railExtra}
220
- </nav>
285
+ <EditorRail items={railItems} />
221
286
 
222
- {/* Canvas fills everything else */}
223
287
  <div className="relative min-w-0 flex-1">
224
288
  <Canvas catalog={catalog} />
225
-
226
- {/* Floating left panel */}
227
- {leftPanel && (
228
- <FloatingCard side="left" onClose={() => setLeftPanel(null)} title={leftPanel === "design" ? "Design" : "Sections"}>
229
- {leftPanel === "design" ? <ThemePanel /> : <SectionsPanel catalog={catalog} />}
230
- </FloatingCard>
231
- )}
232
-
233
- {/* Host panel (SEO / Domain / …) */}
234
- {hostPanel}
235
-
236
- {/* Floating inspector — only when open */}
237
- {inspectorOpen && (
238
- <FloatingCard
239
- side="right"
240
- onClose={() => setInspectorOpen(false)}
241
- title="Inspector"
242
- wide
289
+ {/* On-canvas Add Block CTA */}
290
+ <div className="pointer-events-none absolute inset-x-0 bottom-4 z-10 flex justify-center">
291
+ <button
292
+ type="button"
293
+ onClick={() => openDock("library")}
294
+ className="pointer-events-auto inline-flex items-center gap-2 rounded-full border border-border/60 bg-card/90 px-4 py-2 text-xs font-semibold uppercase tracking-[0.14em] text-foreground shadow-xl backdrop-blur-xl transition hover:bg-card"
243
295
  >
244
- <Inspector catalog={catalog} />
245
- </FloatingCard>
246
- )}
296
+ <Plus className="size-3.5" />
297
+ Add block
298
+ </button>
299
+ </div>
247
300
  </div>
301
+
302
+ {showDock && (
303
+ <EditorDock
304
+ title={dockTitle}
305
+ subtitle={dockSubtitle}
306
+ onClose={closeDock}
307
+ wide={dock === "library"}
308
+ >
309
+ {dock === "sections" && <SectionsPanel catalog={catalog} embedded />}
310
+ {dock === "design" && <ThemePanel />}
311
+ {dock === "inspector" &&
312
+ (selectedId ? (
313
+ <Inspector catalog={catalog} embedded />
314
+ ) : (
315
+ <p className="p-4 text-sm text-muted-foreground">
316
+ Click a section on the page to edit its content and layout.
317
+ </p>
318
+ ))}
319
+ {dock === "library" && <BlockLibraryBody catalog={catalog} />}
320
+ {dock === "host" && hostDock?.body}
321
+ </EditorDock>
322
+ )}
248
323
  </div>
249
324
 
250
- <MobileBar />
251
- <MobileSheet catalog={catalog} />
252
- <BlockLibrary catalog={catalog} />
253
- {templates && templates.length > 0 && <TemplateGallery templates={templates} />}
254
- <EditorStyle />
325
+ <MobileBar onOpenDock={openDock} />
326
+ {templates && templates.length > 0 && (
327
+ <TemplateGallery templates={templates} />
328
+ )}
329
+ <style>{`[data-websitekit-editor] [data-pb-field]:empty::before{content:attr(data-pb-placeholder);opacity:.4;pointer-events:none;}`}</style>
255
330
  </div>
256
331
  </EditorUiContext.Provider>
257
332
  );
258
333
  }
259
334
 
260
- function RailBtn({
261
- active,
262
- onClick,
263
- title,
264
- children,
335
+ function MobileBar({
336
+ onOpenDock,
265
337
  }: {
266
- active: boolean;
267
- onClick: () => void;
268
- title: string;
269
- children: ReactNode;
270
- }) {
271
- return (
272
- <button
273
- type="button"
274
- title={title}
275
- onClick={onClick}
276
- className={cn(
277
- "flex size-9 items-center justify-center rounded-xl transition",
278
- active
279
- ? "bg-foreground text-background shadow-sm"
280
- : "text-muted-foreground hover:bg-muted hover:text-foreground",
281
- )}
282
- >
283
- {children}
284
- </button>
285
- );
286
- }
287
-
288
- function FloatingCard({
289
- side,
290
- title,
291
- onClose,
292
- children,
293
- wide,
294
- }: {
295
- side: "left" | "right";
296
- title: string;
297
- onClose: () => void;
298
- children: ReactNode;
299
- wide?: boolean;
338
+ onOpenDock: (m: DockMode) => void;
300
339
  }) {
340
+ const ui = useEditorUi();
341
+ const sections = useBuilder((s) => s.doc.sections);
301
342
  return (
302
- <div
303
- className={cn(
304
- "absolute top-3 bottom-3 z-20 flex flex-col overflow-hidden rounded-2xl border border-border/50 bg-card/85 shadow-2xl backdrop-blur-2xl",
305
- wide ? "w-[min(22rem,calc(100%-1.5rem))]" : "w-[min(18rem,calc(100%-1.5rem))]",
306
- side === "left" ? "left-3" : "right-3",
307
- )}
308
- data-floating-panel={side}
309
- >
310
- <div className="flex items-center justify-between border-b border-border/40 px-3 py-2">
311
- <span className="text-[11px] font-semibold uppercase tracking-[0.16em] text-muted-foreground">
312
- {title}
313
- </span>
343
+ <nav className="flex shrink-0 items-stretch border-t border-border/50 bg-card/80 px-1 pb-[env(safe-area-inset-bottom)] backdrop-blur-xl md:hidden">
344
+ {(
345
+ [
346
+ ["sections", "Pages", <List className="size-5" key="l" />],
347
+ ["library", "Add", <Plus className="size-5" key="p" />],
348
+ ["design", "Design", <Palette className="size-5" key="d" />],
349
+ ["inspector", "Edit", <Sliders className="size-5" key="i" />],
350
+ ] as const
351
+ ).map(([mode, label, icon]) => (
314
352
  <button
353
+ key={mode}
315
354
  type="button"
316
- onClick={onClose}
317
- className="rounded-lg p-1 text-muted-foreground transition hover:bg-muted hover:text-foreground"
318
- aria-label="Close panel"
355
+ onClick={() => {
356
+ if (mode === "library") ui.openLibrary(sections.length);
357
+ else onOpenDock(mode);
358
+ }}
359
+ className="flex flex-1 flex-col items-center gap-0.5 py-1.5 text-[10px] text-muted-foreground"
319
360
  >
320
- <X className="size-3.5" />
361
+ {icon}
362
+ <span>{label}</span>
321
363
  </button>
322
- </div>
323
- <div className="min-h-0 flex-1 overflow-auto">{children}</div>
324
- </div>
325
- );
326
- }
327
-
328
- function EditorStyle() {
329
- return (
330
- <style>{`[data-websitekit-editor] [data-pb-field]:empty::before{content:attr(data-pb-placeholder);opacity:.4;pointer-events:none;}`}</style>
331
- );
332
- }
333
-
334
- function MobileBar() {
335
- const ui = useEditorUi();
336
- const sections = useBuilder((s) => s.doc.sections);
337
- const tab = (p: MobilePanel, label: string, icon: ReactNode) => (
338
- <button
339
- type="button"
340
- onClick={() => {
341
- if (p === "inspector") ui.setInspectorOpen(true);
342
- ui.setMobilePanel(ui.mobilePanel === p ? null : p);
343
- }}
344
- className={`flex flex-1 flex-col items-center gap-0.5 py-1.5 text-[10px] ${ui.mobilePanel === p ? "text-foreground" : "text-muted-foreground"}`}
345
- >
346
- {icon}
347
- <span>{label}</span>
348
- </button>
349
- );
350
- return (
351
- <nav className="flex shrink-0 items-stretch border-t border-border/50 bg-card/80 px-1 pb-[env(safe-area-inset-bottom)] backdrop-blur-xl md:hidden">
352
- {tab("sections", "Sections", <List className="size-5" />)}
353
- <button
354
- type="button"
355
- onClick={() => ui.openLibrary(sections.length)}
356
- className="flex flex-1 flex-col items-center gap-0.5 py-1.5 text-[10px] text-muted-foreground"
357
- >
358
- <Plus className="size-5" />
359
- <span>Add</span>
360
- </button>
361
- {tab("design", "Design", <Palette className="size-5" />)}
362
- {tab("inspector", "Section", <Sliders className="size-5" />)}
364
+ ))}
363
365
  </nav>
364
366
  );
365
367
  }
366
-
367
- function MobileSheet({ catalog }: { catalog: Catalog }) {
368
- const ui = useEditorUi();
369
- if (ui.mobilePanel === null) return null;
370
- return (
371
- <div className="fixed inset-0 z-50 flex flex-col justify-end md:hidden">
372
- <button
373
- aria-label="Close panel"
374
- onClick={() => ui.setMobilePanel(null)}
375
- className="absolute inset-0 bg-black/40"
376
- />
377
- <div className="relative max-h-[70vh] overflow-auto rounded-t-2xl border-t border-border bg-card/95 pb-[env(safe-area-inset-bottom)] backdrop-blur-2xl">
378
- <div className="flex items-center justify-between border-b border-border px-4 py-2.5">
379
- <span className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
380
- {ui.mobilePanel === "sections"
381
- ? "Sections"
382
- : ui.mobilePanel === "design"
383
- ? "Design"
384
- : "Section"}
385
- </span>
386
- <button
387
- onClick={() => ui.setMobilePanel(null)}
388
- className="rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground"
389
- >
390
- <X className="size-4" />
391
- </button>
392
- </div>
393
- <div className="min-h-[30vh]">
394
- {ui.mobilePanel === "sections" && <SectionsPanel catalog={catalog} />}
395
- {ui.mobilePanel === "design" && <ThemePanel />}
396
- {ui.mobilePanel === "inspector" && (
397
- <div className="p-4">
398
- <Inspector catalog={catalog} />
399
- </div>
400
- )}
401
- </div>
402
- </div>
403
- </div>
404
- );
405
- }
@@ -61,14 +61,14 @@ export function SectionFrame({
61
61
  className={cn(
62
62
  "pointer-events-none absolute inset-0 z-10 ring-inset transition",
63
63
  selected
64
- ? "ring-2 ring-sky-500"
65
- : "ring-1 ring-transparent group-hover/sec:ring-2 group-hover/sec:ring-sky-300",
66
- over && "ring-2 ring-sky-400",
64
+ ? "ring-2 ring-primary"
65
+ : "ring-1 ring-transparent group-hover/sec:ring-2 group-hover/sec:ring-primary/40",
66
+ over && "ring-2 ring-primary",
67
67
  )}
68
68
  />
69
69
  <div
70
70
  className={cn(
71
- "absolute right-3 top-3 z-20 flex items-center gap-0.5 rounded-lg border border-black/10 bg-background/95 p-1 text-foreground shadow-sm backdrop-blur transition",
71
+ "absolute right-3 top-3 z-20 flex items-center gap-0.5 rounded-lg border border-border bg-card/95 p-1 text-foreground shadow-sm backdrop-blur transition",
72
72
  selected
73
73
  ? "opacity-100"
74
74
  : "pointer-events-none opacity-0 group-hover/sec:pointer-events-auto group-hover/sec:opacity-100",
@@ -103,7 +103,7 @@ export function SectionFrame({
103
103
  <button
104
104
  title="Delete"
105
105
  onClick={stop(() => remove(section.id))}
106
- className="rounded p-1.5 text-red-600 hover:bg-red-50"
106
+ className="rounded p-1.5 text-destructive hover:bg-destructive/10"
107
107
  >
108
108
  <Trash2 className="size-4" />
109
109
  </button>
@@ -111,7 +111,7 @@ export function SectionFrame({
111
111
  {section.hideOn && section.hideOn.length > 0 && (
112
112
  <div
113
113
  title={`Hidden on ${section.hideOn.join(", ")}`}
114
- className="absolute left-3 top-3 z-20 flex items-center gap-1 rounded-md border border-black/10 bg-background/95 px-1.5 py-1 text-foreground/70 shadow-sm backdrop-blur"
114
+ className="absolute left-3 top-3 z-20 flex items-center gap-1 rounded-md border border-border bg-background/95 px-1.5 py-1 text-foreground/70 shadow-sm backdrop-blur"
115
115
  >
116
116
  <EyeOff className="size-3.5" />
117
117
  {section.hideOn.map((bp) => {