Skip to main content

Documentation

No results found.
Features

Canvas Sections

Canvas sections are WebProCMS's bounded free-form layout capability: a section whose pieces — photos, cards, badges, headings — sit on a snap-to 12-column placement grid, can overlap each other, and can be dragged to new positions right on...

Canvas sections are WebProCMS's bounded free-form layout capability: a section whose pieces — photos, cards, badges, headings — sit on a snap-to 12-column placement grid, can overlap each other, and can be dragged to new positions right on the page editor's preview canvas. It brings the Webflow-style collage feel (overlapping photos, floating cards, pinned badges) to the page builder while keeping the guardrails that make non-designer sites stay presentable.


What the editor gets

  • Curated starting points, not a blank canvas. Canvas rows ship in the design library like any other row — Hero Canvas Collage (hero), Feature Canvas Overlap (page content), Canvas Banner + Pinned Badge (below hero). You start from a designed composition and rearrange it; you never start from an empty 12×N grid.
  • Drag tiles on the preview canvas. Hovering a canvas tile adds three controls to the element toolbar: a ✥ place grip (drag the tile to a new grid cell — it snaps to the rendered tracks, with guide lines shown while dragging), and z− / z+ (send backward / bring forward through the stacking order). Handles on the tile's right and bottom edges resize its column / row span the same way.
  • Steppers in the sidebar. Each tile's design tab (paintbrush) has a Placement panel: numeric col/row start + span per breakpoint, an "+ Add breakpoint" disclosure for larger screens, and the stack (z-order) stepper. The drag UI and the steppers write the same values — use whichever is comfortable.
  • Mobile stays sane automatically. Below the tablet breakpoint the canvas renders as a plain stacked flow in source order — no shearing, no hand-tuned phone coordinates. Placement applies from md up (larger-breakpoint overrides are opt-in per tile).
  • Everything else works like a normal row. Tiles are ordinary items: inline text editing, AI image generation (image tiles declare real widths + aspect so generated images match their cells), duplicate/hide/visibility rules, entrance animations, copy/paste styles, translations, and theme capture all behave exactly as they do in any other section.

How it works (for developers)

  • <x-dl.canvas> (resources/views/components/dl/canvas.blade.php) is a container primitive: a fixed grid grid-cols-1 md:grid-cols-12 auto-rows-[minmax(2rem,auto)] grid. The single-column base IS the mobile stack — children need no base placement tokens. Schema: App\Support\DlSchemas\Canvas.
  • Placement is per-child data, not structure: grid-cell utilities (md:col-start-N md:col-span-N md:row-start-N md:row-span-N, unprefixed z-N) stored in the child's own *_classes field like any styling. No new marker grammar, no document-model changes — canvas is one more recurse-into container (the grid-layout precedent) in RowBladeSurgery::wrapRules() + the rowdoc.js twins.
  • One rewrite grammar, two entry points. resources/js/editor/placement.js owns the token rules (per-breakpoint set/clear, the md floor — base/sm writes promote to md: so they can never fight the mobile stack — and decade-scale z stepping that pins at 0/50). The sidebar's placementPicker widget and the preview overlay's cell-snap drag both write through Alpine.store('editor') (setPlacementClass / bumpZOrderClass) → setFieldValue → the normal save pipeline. No new persistence surface.
  • The drag lives in the preview overlay (EditorPreviewOverlay): it measures the canvas's rendered grid tracks (columns, gaps, auto-row unit), snaps the pointer to cells, live-previews via inline grid-column/grid-row, and posts editor-set-placement / editor-set-zorder to the parent — the same message pattern as the spacing drag bars. Handles only appear while the multi-column grid is actually rendering (a stacked mobile preview hides them) and share spacing's support rule ({prefix}_classes must govern the tile's group node).
  • A wrapper opts into the lens with the placement attr: <x-dl.wrapper placement="1" …> registers the {prefix}_placement field (mirrors grid-item's card attr). Curated templates set it on each tile.
  • Node-free installs render everything. All placement utilities are standard Tailwind classes the runtime CSS supplement emits, and auto-rows-[minmax(…)] rides UtilityCssGenerator::SAFE_ARBITRARY (auto-rows → grid-auto-rows). Generatability of every placement family is locked by a dataset test against the real utility map; css:supplement --check stays flagged=0.

Boundaries (deliberate, not gaps)

  • No absolute pixel positioning, ever. Pixel coordinate sets are the ugly-site failure mode and the translate-[…] centering idiom is un-generatable node-free. Bounded percentage nudges (relative top-[-18%], rotate-[-6deg]) are the accent tier — the pinned-badge template shows the pattern.
  • No named grid areas or bespoke coordinate store — placement stays "classes on items" so cascade tools, theme capture, clone/promote, and slug rekeys all work unchanged.
  • The AI site generator does not author canvas sections (RowAuthoringLinter allowlist unchanged) — canvas arrives only through the curated catalog.
  • Curated templates never use fixed row heights — auto-rows-[minmax(min,auto)] lets rows grow, so longer translations can't clip overlapped text.

Adding a new canvas template

Author it like any design-library row (design-library skill): outermost <x-dl.section>, one <x-dl.canvas>, children as <x-dl.wrapper placement="1"> tiles carrying md:-prefixed placement classes + z-* in field-classes. Keep the mobile stack in mind (source order = phone order), give every image tile real widths/sizes/aspect, and run php artisan design-library:index + the screenshot verify.