Layout Editor

Overview

QuickUIDesign's Layout Editor is a visual drag-and-drop tool for designing UI layouts that run inside Unreal Engine 5. It follows a WYSIWYG approach — drag components, adjust positions and sizes, edit properties, and auto-save layouts to the project's local config storage.

The Editor works alongside Preview and Runtime modes:

  • Editor — visually compose and edit layouts with auto-save and publish workflow
  • Preview — preview in the browser (interactive config selector or ?layout= URL param)
  • Runtime — production build, single HTML for UE5 embedding (--layout=<name>)

Getting Started

Start the Editor

pnpm dev:editor

The browser opens at http://localhost:3000 showing a startup dialog.

Startup Dialog

On first launch, the startup dialog offers three options:

OptionDescription
New LayoutCreate a blank layout from scratch
Open ConfigBrowse published configs and drafts from configs/ directory
Recent FilesQuickly continue editing a recently used layout

If recent files exist, the dialog automatically navigates to the Recent Files page.

Basic Workflow

Startup Dialog ──→ Editor ──auto-save──→ .drafts/ ──publish──→ configs/ ──→ Preview / Build

Interface Layout

The editor uses a classic three-column layout:

┌──────────────────────────────────────────────────────────────────┐
│  Toolbar (filename + save status | Import / Copy / Save / Publish)│
├────────┬──────────────────────────────┬──────────────────────────┤
│  Panel  │                              │  Properties              │
│         │       Grid Canvas            │  - Info                  │
│ Button  │                              │  - Position              │
│ Card    │   ┌──────┐  ┌───────┐       │  - Props                 │
│ Input   │   │Button│  │ Input │       │                          │
│ Label   │   └──────┘  └───────┘       │  Select a                │
│ Alert   │                              │  component               │
├────────┴──────────────────────────────┴──────────────────────────┤
│  Select a component to edit properties                            │
└──────────────────────────────────────────────────────────────────┘

Left Panel: Component Panel

Components are grouped by category:

CategoryComponents
FormButton, Input, Label
LayoutCard
FeedbackAlert

Each component is draggable — just drag it onto the canvas.

Center: Canvas

Powered by react-grid-layout, the canvas provides:

  • Drag to move — drag the title bar (⋮⋮ handle)
  • Resize — drag the bottom-right corner to adjust size
  • Select — click to highlight with a focus ring
  • Context menu — right-click for operations

Right: Property Panel

When a component is selected, the property panel shows:

  • Component info — type name and instance ID
  • Position — X/Y coordinates and width/height (read-only, updated live)
  • Props — auto-generated form based on the component registry

Property Editing Examples

Button props:

PropTypeDescription
childrenstringButton text
variantselectdefault / secondary / ghost / link / outline / destructive
sizeselectsm / default / lg

Input props:

PropTypeDescription
placeholderstringInput placeholder text
typeselecttext / password / number
disabledbooleanWhether input is disabled

Context Menu

Right-click a component on the canvas for:

ActionDescription
Edit PropertiesActivates the right-side property panel
ReplaceHover to open submenu, choose replacement type (keeps position, resets props to defaults)
DuplicateCreates a new instance at the bottom of the canvas
DeleteRemoves from canvas and component list

Save & Export

The editor uses a hybrid save strategy: changes are auto-saved to drafts, and you manually publish when ready.

Auto-Save (Drafts)

Every edit operation (drag, resize, property change) triggers an auto-save after a 500ms debounce. Drafts are stored in configs/.drafts/{name}.layout.json and are not visible to Preview or Build modes.

The toolbar shows the current save status:

IndicatorStatus
🟡 保存中...Saving in progress
🟢 已保存Last save successful
🔴 保存失败Save error occurred

Publish

Click "发布" (Publish) to promote the current draft to configs/{name}.layout.json. Published configs are available for Preview and Build.

Save (Manual)

Click "保存" (Save) to trigger an immediate manual save to drafts (same as auto-save but on-demand).

Copy JSON

Click "复制 JSON" (Copy JSON) to copy the layout JSON string to clipboard — useful for passing directly as a URL parameter to preview.

Import JSON

Click "导入" (Import) to select a previously saved .json file and restore the editing state.

Note: Importing overwrites the current layout. Save first if needed.


End-to-End Workflow

Step 1: Start Editor

pnpm dev:editor

The startup dialog appears. Choose New Layout, enter a name (e.g. dashboard), and click Create.

Step 2: Compose Layout

  1. Drag a Button from the panel onto the canvas
  2. Drag a Card below it
  3. Select the Button, change its text to "Submit" and variant to "destructive"
  4. Resize the Card to 6 columns wide
  5. Right-click the Button → Duplicate

The auto-save indicator shows 🟢 已保存 after each change.

Step 3: Publish

Click "发布" (Publish) in the toolbar to publish your draft. The config is now available at configs/dashboard.layout.json.

Step 4: Preview

pnpm dev:preview

A config selector appears — click your layout to preview it. Alternatively, pass it directly via URL:

http://localhost:3000?layout=dashboard

Step 5: Production Build

pnpm build --layout=dashboard

Output: dist/merged/index.html — a standalone HTML file ready for UE5's Web Browser widget.


Extending Components

Register new components in src/layout/registry.ts:

import { YourComponent } from '@/components/ui/your-component'

const registry: ComponentMeta[] = [
  {
    type: 'YourComponent',
    component: YourComponent,
    defaultProps: { foo: 'bar' },
    propsSchema: [
      { name: 'foo', type: 'string', label: 'Property Label', defaultValue: 'bar' },
    ],
    category: 'Custom',
  },
]

PropDef Reference

interface PropDef {
  name: string
  type: 'string' | 'number' | 'boolean' | 'select'
  label: string
  options?: { label: string; value: any }[]
  defaultValue?: any
}

Built-in Components

Five shadcn/ui components are pre-registered: Button, Card, Input, Label, Alert. Any React component can be added the same way.


FAQ

Can't drag?

Click the title bar (⋮⋮ handle area). dragConfig.handle: '.drag-handle' restricts dragging to handle elements only.

Unresponsive layout?

The editor currently targets the lg breakpoint (≥1200px). Responsive breakpoints are stored in the layout JSON but the editor UI only edits lg layouts.

Build errors?

Use pnpm build --layout=<name> to specify which published config to use. The layout name must match a file in configs/ (e.g. configs/dashboard.layout.json--layout=dashboard). If no layout is specified and no recent file is found, the build fails with a helpful error message.

Auto-save not working?

Auto-save requires a layout to be opened or created via the startup dialog. The currentFileName must be set for drafts to be saved. Check the toolbar for the save status indicator.