@prenta/admin 0.93.0 → 0.94.0

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 (90) hide show
  1. package/CHANGELOG.md +111 -0
  2. package/dist/__tests__/lib/version-diff.test.d.ts +2 -0
  3. package/dist/__tests__/lib/version-diff.test.d.ts.map +1 -0
  4. package/dist/__tests__/lib/version-diff.test.js +230 -0
  5. package/dist/__tests__/lib/version-diff.test.js.map +1 -0
  6. package/dist/__tests__/lib/version-history.test.d.ts +2 -0
  7. package/dist/__tests__/lib/version-history.test.d.ts.map +1 -0
  8. package/dist/__tests__/lib/version-history.test.js +125 -0
  9. package/dist/__tests__/lib/version-history.test.js.map +1 -0
  10. package/dist/__tests__/styles/responsive-layer.test.d.ts +2 -0
  11. package/dist/__tests__/styles/responsive-layer.test.d.ts.map +1 -0
  12. package/dist/__tests__/styles/responsive-layer.test.js +127 -0
  13. package/dist/__tests__/styles/responsive-layer.test.js.map +1 -0
  14. package/dist/__tests__/views/canvas-review-mode.render.test.d.ts +2 -0
  15. package/dist/__tests__/views/canvas-review-mode.render.test.d.ts.map +1 -0
  16. package/dist/__tests__/views/canvas-review-mode.render.test.js +70 -0
  17. package/dist/__tests__/views/canvas-review-mode.render.test.js.map +1 -0
  18. package/dist/__tests__/views/editor-top-bar.render.test.js +29 -0
  19. package/dist/__tests__/views/editor-top-bar.render.test.js.map +1 -1
  20. package/dist/__tests__/views/version-history-panel.render.test.d.ts +2 -0
  21. package/dist/__tests__/views/version-history-panel.render.test.d.ts.map +1 -0
  22. package/dist/__tests__/views/version-history-panel.render.test.js +153 -0
  23. package/dist/__tests__/views/version-history-panel.render.test.js.map +1 -0
  24. package/dist/components/EditorRail.js +3 -3
  25. package/dist/components/EditorRail.js.map +1 -1
  26. package/dist/components/page-tab/DirectiveSwitch.d.ts.map +1 -1
  27. package/dist/components/page-tab/DirectiveSwitch.js +5 -1
  28. package/dist/components/page-tab/DirectiveSwitch.js.map +1 -1
  29. package/dist/layout/primitives/AdminShell.d.ts.map +1 -1
  30. package/dist/layout/primitives/AdminShell.js +2 -2
  31. package/dist/layout/primitives/AdminShell.js.map +1 -1
  32. package/dist/lib/version-diff.d.ts +50 -0
  33. package/dist/lib/version-diff.d.ts.map +1 -0
  34. package/dist/lib/version-diff.js +294 -0
  35. package/dist/lib/version-diff.js.map +1 -0
  36. package/dist/lib/version-history.d.ts +73 -0
  37. package/dist/lib/version-history.d.ts.map +1 -0
  38. package/dist/lib/version-history.js +126 -0
  39. package/dist/lib/version-history.js.map +1 -0
  40. package/dist/prenta-admin.css +1 -1
  41. package/dist/views/page-editor/EditorCanvas.d.ts +14 -1
  42. package/dist/views/page-editor/EditorCanvas.d.ts.map +1 -1
  43. package/dist/views/page-editor/EditorCanvas.js +3 -3
  44. package/dist/views/page-editor/EditorCanvas.js.map +1 -1
  45. package/dist/views/page-editor/EditorTopBar.d.ts +8 -2
  46. package/dist/views/page-editor/EditorTopBar.d.ts.map +1 -1
  47. package/dist/views/page-editor/EditorTopBar.js +8 -6
  48. package/dist/views/page-editor/EditorTopBar.js.map +1 -1
  49. package/dist/views/page-editor/PageSectionEditor.d.ts.map +1 -1
  50. package/dist/views/page-editor/PageSectionEditor.js +115 -32
  51. package/dist/views/page-editor/PageSectionEditor.js.map +1 -1
  52. package/dist/views/page-editor/ReviewBar.d.ts +21 -0
  53. package/dist/views/page-editor/ReviewBar.d.ts.map +1 -0
  54. package/dist/views/page-editor/ReviewBar.js +22 -0
  55. package/dist/views/page-editor/ReviewBar.js.map +1 -0
  56. package/dist/views/page-editor/SectionInspector.d.ts.map +1 -1
  57. package/dist/views/page-editor/SectionInspector.js +1 -1
  58. package/dist/views/page-editor/SectionInspector.js.map +1 -1
  59. package/dist/views/page-editor/SectionsPanel.js +1 -1
  60. package/dist/views/page-editor/SectionsPanel.js.map +1 -1
  61. package/dist/views/page-editor/VersionHistoryPanel.d.ts +29 -0
  62. package/dist/views/page-editor/VersionHistoryPanel.d.ts.map +1 -0
  63. package/dist/views/page-editor/VersionHistoryPanel.js +81 -0
  64. package/dist/views/page-editor/VersionHistoryPanel.js.map +1 -0
  65. package/dist/views/page-editor/sections/SectionRenderer.d.ts +13 -1
  66. package/dist/views/page-editor/sections/SectionRenderer.d.ts.map +1 -1
  67. package/dist/views/page-editor/sections/SectionRenderer.js +23 -8
  68. package/dist/views/page-editor/sections/SectionRenderer.js.map +1 -1
  69. package/package.json +3 -3
  70. package/src/__tests__/lib/version-diff.test.ts +278 -0
  71. package/src/__tests__/lib/version-history.test.ts +166 -0
  72. package/src/__tests__/styles/responsive-layer.test.ts +152 -0
  73. package/src/__tests__/views/canvas-review-mode.render.test.tsx +94 -0
  74. package/src/__tests__/views/editor-top-bar.render.test.tsx +42 -0
  75. package/src/__tests__/views/version-history-panel.render.test.tsx +195 -0
  76. package/src/components/EditorRail.tsx +5 -5
  77. package/src/components/page-tab/DirectiveSwitch.tsx +4 -1
  78. package/src/layout/primitives/AdminShell.tsx +13 -1
  79. package/src/lib/version-diff.ts +376 -0
  80. package/src/lib/version-history.ts +192 -0
  81. package/src/styles/responsive.css +281 -0
  82. package/src/styles/theme.css +8 -0
  83. package/src/views/page-editor/EditorCanvas.tsx +34 -7
  84. package/src/views/page-editor/EditorTopBar.tsx +20 -8
  85. package/src/views/page-editor/PageSectionEditor.tsx +162 -43
  86. package/src/views/page-editor/ReviewBar.tsx +76 -0
  87. package/src/views/page-editor/SectionInspector.tsx +2 -1
  88. package/src/views/page-editor/SectionsPanel.tsx +2 -2
  89. package/src/views/page-editor/VersionHistoryPanel.tsx +302 -0
  90. package/src/views/page-editor/sections/SectionRenderer.tsx +53 -12
@@ -10,7 +10,14 @@ import { SeoEditorPane } from '../../components/seo/SeoEditorPane.js'
10
10
  import { EditorRail, RailHeader } from '../../components/EditorRail.js'
11
11
  import { EditorRailTabs, type RailTab, type RailTabId } from '../../components/EditorRailTabs.js'
12
12
  import { ErrorBoundary } from '../../components/ErrorBoundary.js'
13
- import { VersionHistory } from '../../components/VersionHistory.js'
13
+ import { VersionHistoryPanel } from './VersionHistoryPanel.js'
14
+ import { ReviewBar } from './ReviewBar.js'
15
+ import {
16
+ fetchPageVersions,
17
+ restorePageVersion,
18
+ type PageVersion,
19
+ } from '../../lib/version-history.js'
20
+ import { changedSectionIds, diffVersions } from '../../lib/version-diff.js'
14
21
  import {
15
22
  emptyPage,
16
23
  fetchPageForEditor,
@@ -221,6 +228,12 @@ export function PageSectionEditor({
221
228
  /** Active rail tab. Replaces the old boolean `seoOpen` right-hand aside. */
222
229
  const [railTab, setRailTab] = useState<RailTabId>('sections')
223
230
  const [historyOpen, setHistoryOpen] = useState(false)
231
+ const [versions, setVersions] = useState<PageVersion[]>([])
232
+ const [versionsLoading, setVersionsLoading] = useState(false)
233
+ const [versionsError, setVersionsError] = useState<string | null>(null)
234
+ /** Index into `versions`; 0 is the newest, which is the current content. */
235
+ const [versionIndex, setVersionIndex] = useState(0)
236
+ const [restoring, setRestoring] = useState(false)
224
237
  const [confirmPublish, setConfirmPublish] = useState(false)
225
238
  const [scheduleOpen, setScheduleOpen] = useState(false)
226
239
  const [leaveTarget, setLeaveTarget] = useState<string | null>(null)
@@ -325,6 +338,105 @@ export function PageSectionEditor({
325
338
 
326
339
  const activeRailTab = railTabs.find((tab) => tab.id === railTab) ?? railTabs[0]!
327
340
 
341
+ // ─── Version history ─────────────────────────────────────────────────
342
+ // History is a MODE, not a dialog: it overlays the rail and drives the
343
+ // canvas, so the version being reviewed is editor state rather than
344
+ // something owned by a panel that can be unmounted.
345
+
346
+ const loadVersions = useCallback(async (pageId: string) => {
347
+ setVersionsLoading(true)
348
+ setVersionsError(null)
349
+ try {
350
+ setVersions(await fetchPageVersions(PAGES_COLLECTION, pageId))
351
+ } catch (err) {
352
+ setVersions([])
353
+ setVersionsError(err instanceof Error ? err.message : 'Failed to load version history')
354
+ } finally {
355
+ setVersionsLoading(false)
356
+ }
357
+ }, [])
358
+
359
+ const openHistory = useCallback(() => {
360
+ if (!page?.id) return
361
+ setHistoryOpen(true)
362
+ // Always land on "current" so opening history never silently swaps the
363
+ // canvas out from under the editor.
364
+ setVersionIndex(0)
365
+ void loadVersions(page.id)
366
+ }, [page?.id, loadVersions])
367
+
368
+ const closeHistory = useCallback(() => {
369
+ setHistoryOpen(false)
370
+ setVersionIndex(0)
371
+ }, [])
372
+
373
+ /**
374
+ * Index 0 is the current content, which the canvas is already showing — so
375
+ * selecting it is "back to current", not a review. Only an older index puts
376
+ * the editor into review mode.
377
+ */
378
+ const reviewing = historyOpen && versionIndex > 0
379
+ const reviewVersion = reviewing ? (versions[versionIndex] ?? null) : null
380
+
381
+ // What that version's save CHANGED — diffed against the one before it, which
382
+ // is the question the outlines on the canvas answer.
383
+ const reviewChanges = useMemo(
384
+ () =>
385
+ reviewVersion
386
+ ? diffVersions(reviewVersion.sections, versions[versionIndex + 1]?.sections)
387
+ : [],
388
+ [reviewVersion, versions, versionIndex],
389
+ )
390
+ const reviewChangedIds = useMemo(() => changedSectionIds(reviewChanges), [reviewChanges])
391
+
392
+ const handleRestoreVersion = useCallback(
393
+ async (version: PageVersion) => {
394
+ if (!page?.id) return
395
+ setRestoring(true)
396
+ try {
397
+ await restorePageVersion(PAGES_COLLECTION, page.id, version.id)
398
+ // Re-read rather than trusting the snapshot we already hold: the
399
+ // restore goes through the normal update path, so hooks and derived
400
+ // fields may have altered what actually landed.
401
+ const restored = await fetchPageForEditor(page.id)
402
+ acceptPage(restored)
403
+ setSelectedId(null)
404
+ setDirty(false)
405
+ setSaveState('idle')
406
+ setValidation(null)
407
+ closeHistory()
408
+ void loadVersions(page.id)
409
+ toast.success('Version restored')
410
+ } catch (err) {
411
+ toast.error(err instanceof Error ? err.message : 'Failed to restore version')
412
+ } finally {
413
+ setRestoring(false)
414
+ }
415
+ },
416
+ [page?.id, acceptPage, closeHistory, loadVersions],
417
+ )
418
+
419
+ // ─── Edit permission ─────────────────────────────────────────────────
420
+ /**
421
+ * ADR 0002: a Page-Builder-owned page (it has a `_layout`) compiles its
422
+ * sections from the builder layout on every save, so editing them here would
423
+ * be overwritten. The server independently refuses such edits with 409.
424
+ */
425
+ const readOnly = page?.builderOwned ?? false
426
+ /**
427
+ * The single gate every writing surface reads.
428
+ *
429
+ * Hoisted above the callbacks rather than derived at render time, because
430
+ * the two that were left behind were the ones that mattered: the site
431
+ * preview's in-place edit handlers close over `canEdit` (the raw role) and
432
+ * so kept accepting edits while a past version was under review — and while
433
+ * a builder-owned page was supposedly read-only. The iframe is a second
434
+ * editing surface, and a lock that only covers the rail is not a lock.
435
+ */
436
+ const effectiveCanEdit = canEdit && !readOnly && !reviewing
437
+ /** Restoring is not editing: it is allowed precisely while reviewing. */
438
+ const canRestoreVersion = canEdit && !readOnly
439
+
328
440
  // ─── Load ──────────────────────────────────────────────────────────
329
441
  useEffect(() => {
330
442
  let cancelled = false
@@ -610,24 +722,6 @@ export function PageSectionEditor({
610
722
  onNavigate('/pages')
611
723
  }, [page?.id, onNavigate])
612
724
 
613
- // After a version restore the server has already written the restored
614
- // data — refetch so the editor reflects it instead of the stale state.
615
- const handleRestored = useCallback(() => {
616
- if (!page?.id) return
617
- fetchPageForEditor(page.id)
618
- .then((p) => {
619
- acceptPage(p)
620
- setSelectedId(null)
621
- setRailTab('sections')
622
- setDirty(false)
623
- setSaveState('idle')
624
- setValidation(null)
625
- })
626
- .catch(() => {
627
- toast.error('Version restored — refresh the page to see it.')
628
- })
629
- }, [page?.id])
630
-
631
725
  const handleSeoSaved = useCallback(() => {
632
726
  reloadAudit()
633
727
  if (!page?.id) return
@@ -656,25 +750,28 @@ export function PageSectionEditor({
656
750
  setPendingFocusPath(fieldPath ?? null)
657
751
  }, [])
658
752
 
753
+ // `effectiveCanEdit`, not `canEdit`: the site preview is a second editing
754
+ // surface, so a role check alone let it write through both the version-review
755
+ // lock and the builder-owned lock the rest of the editor honours.
659
756
  const handleCanvasEdit = useCallback(
660
757
  (edit: { sectionId: string; fieldPath: string; value: string }) => {
661
- if (!canEdit) return
758
+ if (!effectiveCanEdit) return
662
759
  setSuppressSectionsEcho((n) => n + 1)
663
760
  mutateSections((s) =>
664
761
  updateSectionContentAtPath(s, edit.sectionId, edit.fieldPath, edit.value),
665
762
  )
666
763
  setSelectedId(edit.sectionId)
667
764
  },
668
- [canEdit, mutateSections],
765
+ [effectiveCanEdit, mutateSections],
669
766
  )
670
767
 
671
768
  const handleCanvasRequestMedia = useCallback(
672
769
  (request: { sectionId: string; fieldPath: string }) => {
673
- if (!canEdit) return
770
+ if (!effectiveCanEdit) return
674
771
  setSelectedId(request.sectionId)
675
772
  setCanvasMediaTarget(request)
676
773
  },
677
- [canEdit],
774
+ [effectiveCanEdit],
678
775
  )
679
776
 
680
777
  // After a canvas field click, focus the matching inspector input once painted.
@@ -807,12 +904,12 @@ export function PageSectionEditor({
807
904
 
808
905
  const selected = page.sections.find((s) => s.id === selectedId) ?? null
809
906
 
810
- // ADR 0002: a Page-Builder-owned page (it has a `_layout`) compiles its
811
- // sections from the builder layout on every save, so editing them here would
812
- // be overwritten. Open this editor read-only and route the user to the
813
- // builder. The server independently refuses such edits with 409.
814
- const readOnly = page.builderOwned
815
- const effectiveCanEdit = canEdit && !readOnly
907
+ // `readOnly` / `effectiveCanEdit` / `canRestoreVersion` are computed above,
908
+ // with the hooks, so the callbacks defined there share this one gate.
909
+
910
+ // The canvas shows the reviewed snapshot, but `page.sections` stays the
911
+ // editor's own content throughout — nothing about review mode writes to it.
912
+ const canvasSections = reviewVersion ? reviewVersion.sections : page.sections
816
913
 
817
914
  // Sections whose type has no registered definition (seed/code-owned, e.g.
818
915
  // `opal-*`). They are preserved verbatim on save but can't be edited here.
@@ -857,7 +954,8 @@ export function PageSectionEditor({
857
954
  onViewOnSite={page.id ? handleViewOnSite : undefined}
858
955
  sitePreview={sitePreview.active}
859
956
  onToggleSitePreview={page.id && page.slug ? sitePreview.toggle : undefined}
860
- onHistory={page.id ? () => setHistoryOpen(true) : undefined}
957
+ historyOpen={historyOpen}
958
+ onHistory={page.id ? () => (historyOpen ? closeHistory() : openHistory()) : undefined}
861
959
  onOpenSettings={() => setSettingsOpen(true)}
862
960
  onOpenSeo={handleToggleSeo}
863
961
  seoOpen={railTab === 'seo'}
@@ -926,7 +1024,7 @@ export function PageSectionEditor({
926
1024
  )}
927
1025
 
928
1026
  <ReflowContext.Provider value={reflowContext}>
929
- <div className="relative flex flex-1 overflow-hidden">
1027
+ <div className="prenta-editor-body relative flex flex-1 overflow-hidden">
930
1028
  <EditorRail collapsedLabel={activeRailTab.label}>
931
1029
  {({ width, dragging, collapse }) => (
932
1030
  <>
@@ -992,6 +1090,23 @@ export function PageSectionEditor({
992
1090
  />
993
1091
  )}
994
1092
  </div>
1093
+
1094
+ {/* Overlays the rail rather than replacing its contents, so
1095
+ closing history returns to exactly the tab and scroll
1096
+ position it was opened from. */}
1097
+ {historyOpen && (
1098
+ <VersionHistoryPanel
1099
+ versions={versions}
1100
+ loading={versionsLoading}
1101
+ error={versionsError}
1102
+ selectedIndex={versionIndex}
1103
+ onSelect={setVersionIndex}
1104
+ onClose={closeHistory}
1105
+ onRestore={handleRestoreVersion}
1106
+ restoring={restoring}
1107
+ canRestore={canRestoreVersion}
1108
+ />
1109
+ )}
995
1110
  </>
996
1111
  )}
997
1112
  </EditorRail>
@@ -1012,7 +1127,7 @@ export function PageSectionEditor({
1012
1127
  />
1013
1128
  ) : (
1014
1129
  <EditorCanvas
1015
- sections={page.sections}
1130
+ sections={canvasSections}
1016
1131
  selectedId={selectedId}
1017
1132
  breakpoint={viewport}
1018
1133
  zoom={zoom}
@@ -1021,11 +1136,25 @@ export function PageSectionEditor({
1021
1136
  onSelect={handleSelectSection}
1022
1137
  structuralTypes={structuralTypes}
1023
1138
  sitePreviewAvailable={sitePreviewAvailable && !sitePreview.active}
1139
+ reviewing={reviewing}
1140
+ changedSectionIds={reviewChangedIds}
1141
+ reviewBar={
1142
+ reviewVersion ? (
1143
+ <ReviewBar
1144
+ version={reviewVersion}
1145
+ changedCount={reviewChangedIds.size}
1146
+ onRestore={() => void handleRestoreVersion(reviewVersion)}
1147
+ onBackToCurrent={() => setVersionIndex(0)}
1148
+ restoring={restoring}
1149
+ canRestore={canRestoreVersion}
1150
+ />
1151
+ ) : null
1152
+ }
1024
1153
  />
1025
1154
  )}
1026
1155
  </div>
1027
1156
 
1028
- {selected && railTab === 'sections' && (
1157
+ {selected && railTab === 'sections' && !reviewing && (
1029
1158
  <SectionInspector
1030
1159
  section={selected}
1031
1160
  canEdit={effectiveCanEdit}
@@ -1040,16 +1169,6 @@ export function PageSectionEditor({
1040
1169
  </ReflowContext.Provider>
1041
1170
  </div>
1042
1171
 
1043
- {page.id && (
1044
- <VersionHistory
1045
- collectionSlug="pages"
1046
- documentId={page.id}
1047
- open={historyOpen}
1048
- onClose={() => setHistoryOpen(false)}
1049
- onRestore={handleRestored}
1050
- />
1051
- )}
1052
-
1053
1172
  <PageSettingsModal
1054
1173
  open={settingsOpen}
1055
1174
  page={page}
@@ -0,0 +1,76 @@
1
+ 'use client'
2
+
3
+ import { History, Loader2 } from 'lucide-react'
4
+ import { dayLabel, timeLabel, type PageVersion } from '../../lib/version-history.js'
5
+
6
+ export interface ReviewBarProps {
7
+ version: PageVersion
8
+ changedCount: number
9
+ onRestore: () => void
10
+ onBackToCurrent: () => void
11
+ restoring: boolean
12
+ canRestore: boolean
13
+ }
14
+
15
+ /**
16
+ * The strip above the canvas while a past version is on it.
17
+ *
18
+ * Occupies the same slot as the editing tip and the structure notice, and
19
+ * replaces both rather than stacking with them: everything that slot normally
20
+ * says is about editing the current page, which is precisely what you cannot
21
+ * do here. It also has to be unmissable — the canvas below looks like a
22
+ * perfectly ordinary editable page, and the only thing separating "reviewing
23
+ * history" from "editing" is this bar.
24
+ */
25
+ export function ReviewBar({
26
+ version,
27
+ changedCount,
28
+ onRestore,
29
+ onBackToCurrent,
30
+ restoring,
31
+ canRestore,
32
+ }: ReviewBarProps) {
33
+ return (
34
+ <div
35
+ // `status`, not a bare div: entering review mode is a change of what the
36
+ // whole canvas means, and a screen-reader user gets no equivalent of the
37
+ // amber colour that announces it to everyone else.
38
+ role="status"
39
+ className="border-warning/35 bg-warning/10 text-foreground mx-auto mb-3 flex w-fit max-w-full flex-wrap items-center gap-2.5 rounded-full border py-1.5 pr-1.5 pl-3.5 text-[11.5px]"
40
+ >
41
+ <History className="text-warning h-3.5 w-3.5 shrink-0" aria-hidden />
42
+ <span className="min-w-0">
43
+ Viewing{' '}
44
+ <strong className="font-semibold">
45
+ {dayLabel(version.createdAt)} {timeLabel(version.createdAt)}
46
+ </strong>{' '}
47
+ by <strong className="font-semibold">{version.author.name}</strong>
48
+ {changedCount > 0 && (
49
+ <>
50
+ {' · '}
51
+ {changedCount} section{changedCount === 1 ? '' : 's'} changed
52
+ </>
53
+ )}
54
+ </span>
55
+
56
+ {canRestore && (
57
+ <button
58
+ type="button"
59
+ onClick={onRestore}
60
+ disabled={restoring}
61
+ className="border-border bg-card text-foreground hover:bg-accent inline-flex shrink-0 items-center gap-1.5 rounded-full border px-2.5 py-1 text-[11px] font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50"
62
+ >
63
+ {restoring && <Loader2 className="h-3 w-3 animate-spin" aria-hidden />}
64
+ Restore
65
+ </button>
66
+ )}
67
+ <button
68
+ type="button"
69
+ onClick={onBackToCurrent}
70
+ className="border-border bg-card text-foreground hover:bg-accent shrink-0 rounded-full border px-2.5 py-1 text-[11px] font-medium transition-colors"
71
+ >
72
+ Back to current
73
+ </button>
74
+ </div>
75
+ )
76
+ }
@@ -51,7 +51,8 @@ interface SectionInspectorProps {
51
51
  const LABEL = 'text-foreground mb-1 block text-xs font-medium'
52
52
  const INPUT =
53
53
  'border-input bg-input-background text-foreground focus-visible:ring-ring w-full rounded-md border px-2.5 py-1.5 text-sm focus-visible:ring-2 focus-visible:outline-none'
54
- const INSPECTOR_SHELL = 'bg-card border-border flex h-full flex-col border-l'
54
+ const INSPECTOR_SHELL =
55
+ 'prenta-editor-inspector bg-card border-border flex h-full flex-col border-l'
55
56
 
56
57
  function InspectorHeaderActions({
57
58
  onClose,
@@ -305,7 +305,7 @@ function SectionRow({
305
305
  disabled={!canEdit}
306
306
  aria-pressed={!section.visible}
307
307
  aria-label={section.visible ? `Hide ${section.name}` : `Show ${section.name}`}
308
- className="text-muted-foreground hover:text-foreground shrink-0 rounded p-1 disabled:opacity-40"
308
+ className="prenta-touch-target text-muted-foreground hover:text-foreground shrink-0 rounded p-1 disabled:opacity-40"
309
309
  >
310
310
  {section.visible ? (
311
311
  <Eye className="h-4 w-4" aria-hidden />
@@ -321,7 +321,7 @@ function SectionRow({
321
321
  type="button"
322
322
  disabled={!canEdit}
323
323
  aria-label={`More actions for ${section.name}`}
324
- className="text-muted-foreground hover:text-foreground shrink-0 rounded p-1 disabled:opacity-40"
324
+ className="prenta-touch-target text-muted-foreground hover:text-foreground shrink-0 rounded p-1 disabled:opacity-40"
325
325
  >
326
326
  <MoreVertical className="h-4 w-4" aria-hidden />
327
327
  </button>