Skip to content

Visual Editor

The Visual Editor (VISEDITOR epic, #958) adds direct-manipulation editing capabilities to the section preview pane in Smackz-Websites. Instead of adjusting properties through form fields in the 7-step wizard, users can click, drag, and edit elements visually in the preview.

Scope: the visual editor operates inside the section preview pane (SectionPreviewPane within PageSectionWizard). The full-page preview remains read-only.

Feature Set

Selection Overlay (VISEDITOR-01)

A click-to-select interaction layer on top of the section preview. When a user clicks an element (heading, button, media, etc.), it highlights with a Figma-style blue outline, 8 resize handles, and a role label badge.

How it works:

  • page-renderer components are annotated with data-role attributes (e.g., data-role="heading", data-role="button-primary", data-role="text-container"). These attributes are inert and do not affect rendering.
  • A transparent SelectionOverlay component intercepts clicks and walks the DOM upward to find the nearest data-role, identifying the element type and parent section.
  • SelectionHighlight positions a blue outline (#3b82f6) using getBoundingClientRect() relative to the preview container. CSS zoom scaling is handled automatically since the overlay is a sibling within the same container.
  • Hover shows a dashed blue indicator. Click shows a solid outline with handles and label. Escape or clicking outside deselects.

Key files: Smackz-Websites/src/pages/pages/components/visual-editor/ (new directory), plus data-role attributes added across page-renderer layout and content components.

Floating Toolbar (VISEDITOR-02)

When an element is selected, a contextual floating toolbar appears above it with the most relevant editing controls. This provides shortcuts for common property changes without navigating the wizard.

Controls by element type:

Element Available Controls
Text (heading, subheading, body) Font size, color, alignment, font family, bold, italic
Primary/secondary button Color, text color, variant (filled/outline/text), size
Buttons container Alignment, "Edit in wizard" link
Media Border radius, layout selector (carousel/grid/list/row)
Text container Background color, opacity, "Edit in wizard" link
Section Background color, "Edit in wizard" link

The toolbar uses a dark glassmorphic style (rgba(15, 23, 42, 0.85) with blur(16px)) and flips below the element when there is not enough space above. All changes flow through the same onFieldChange callback used by the wizard forms, so the preview updates in real time.

Drag-to-Position Text Container (VISEDITOR-03)

On hero sections with background media, the selection handles on the text container become draggable. Users can reposition and resize the text container by dragging instead of adjusting the four percentage sliders (textStartPercent, textEndPercent, textTopPercent, textBottomPercent).

Features:

  • All 8 handles support resize (corners resize two axes, midpoints resize one axis)
  • Dragging the body moves the entire container
  • Snap guides appear at 25%, 50%, 75% positions with 2% snap threshold
  • A live tooltip near the cursor shows current percentage values during drag
  • Zoom compensation ensures accurate coordinate math at all preview scales
  • Minimum 10% width and height enforced

Phone Preview Parity (VISEDITOR-15)

The portrait device preview now matches what the SMACKZ-MOBILE React Native app renders on the selected phone model.

The problem: Non-hero section heights used browser vh units instead of the selected device's viewport height. A section set to 50% height would render at 450px in a 900px browser window instead of the correct 395px for an iPhone 14.

Three-phase fix:

  • Phase 1 (shipped): Non-hero section heights now use getSectionHeight(heightPercent, navHeight, viewportHeight) instead of ${heightPercent}vh. When iPhone 14 is selected, heights calculate from 844px minus 55px nav = 789px available.
  • Phase 2 (planned): Render the preview frame at full device dimensions with a CSS transform: scale() to fit. This removes the PORTRAIT_SCALE = 0.55 font hack and achieves 1:1 proportional parity.
  • Phase 3 (planned): Fix RN-side inconsistencies where NativeHeroSection and NativeFeaturedMenuSection skip nav height subtraction. Add screenshot parity testing.

Architecture

All visual editor code lives under Smackz-Websites/src/pages/pages/components/visual-editor/. The page-renderer changes are limited to adding data-role attributes -- no structural or behavioral changes.

visual-editor/
  SelectionOverlay.tsx       -- Click capture + hover/selection rendering
  SelectionHighlight.tsx     -- Blue outline + 8 handles
  ElementLabel.tsx           -- Role label badge
  FloatingToolbar.tsx        -- Contextual toolbar with positioning
  DragHandles.tsx            -- Draggable handles for text container
  SnapGuides.tsx             -- Snap guide lines during drag
  useSelectionState.ts       -- Selection state + coordinate math
  useDragHandle.ts           -- Drag state + zoom compensation
  toolbar-controls/          -- Compact control components