From 33be56dcb12aa1168f42fde811b5c18e94de6c98 Mon Sep 17 00:00:00 2001 From: tolvitty Date: Fri, 13 Feb 2026 15:47:49 +0100 Subject: [PATCH] feat: add side-by-side live preview to form builder Co-Authored-By: Claude Opus 4.6 --- src/ui/form-builder.ts | 57 +++++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/src/ui/form-builder.ts b/src/ui/form-builder.ts index 151596d..cc1d16d 100644 --- a/src/ui/form-builder.ts +++ b/src/ui/form-builder.ts @@ -1,5 +1,6 @@ import { App, Modal, Notice } from 'obsidian'; import { FormDefinition, FormField, FieldType } from '../types'; +import { renderField } from './field-renderers'; const FIELD_TYPES: FieldType[] = [ 'text', @@ -90,10 +91,15 @@ export class FormBuilderModal extends Modal { } }); - // --- General settings --- - contentEl.createEl('h2', { text: 'Form Settings' }); + // --- Two-column layout --- + const layout = contentEl.createDiv({ cls: 'ff-builder-layout' }); - const generalEl = contentEl.createDiv({ cls: 'ff-builder-general' }); + // === LEFT: Editor === + const editorEl = layout.createDiv({ cls: 'ff-builder-editor' }); + + editorEl.createEl('h2', { text: 'Form Settings' }); + + const generalEl = editorEl.createDiv({ cls: 'ff-builder-general' }); // Name this.addTextSetting(generalEl, 'Form Name', this.draft.name, (v) => { @@ -109,7 +115,7 @@ export class FormBuilderModal extends Modal { (v) => { this.pushSnapshot(); this.draft.mode = v as 'create' | 'update'; - this.render(); // Re-render to show mode-specific settings + this.render(); }, ); @@ -151,14 +157,14 @@ export class FormBuilderModal extends Modal { ); } - // --- Fields section --- - contentEl.createEl('h3', { text: 'Fields' }); + // Fields section + editorEl.createEl('h3', { text: 'Fields' }); - const fieldsContainer = contentEl.createDiv({ cls: 'ff-builder-fields' }); + const fieldsContainer = editorEl.createDiv({ cls: 'ff-builder-fields' }); this.renderFields(fieldsContainer); // Add field button - const addBtn = contentEl.createEl('button', { + const addBtn = editorEl.createEl('button', { cls: 'ff-builder-add-btn', text: '+ Add Field', }); @@ -174,7 +180,40 @@ export class FormBuilderModal extends Modal { this.render(); }); - // --- Footer --- + // === RIGHT: Preview === + const previewEl = layout.createDiv({ cls: 'ff-builder-preview' }); + previewEl.createEl('h2', { text: 'Preview' }); + + const previewContent = previewEl.createDiv({ cls: 'ff-builder-preview-content' }); + + if (this.draft.fields.length === 0) { + previewContent.createDiv({ + cls: 'ff-builder-preview-empty', + text: 'Add fields to see a preview.', + }); + } else { + // Form title + previewContent.createEl('h3', { + text: this.draft.name || 'Untitled Form', + cls: 'ff-form-title', + }); + + // Render each field + const previewFields = previewContent.createDiv({ cls: 'ff-fields' }); + for (const field of this.draft.fields) { + renderField(this.app, previewFields, field, field.defaultValue); + } + + // Disabled submit button + const previewFooter = previewContent.createDiv({ cls: 'ff-form-footer' }); + const previewSubmit = previewFooter.createEl('button', { + text: this.draft.mode === 'create' ? 'Create Note' : 'Update Frontmatter', + cls: 'mod-cta ff-submit-btn', + }); + previewSubmit.setAttribute('disabled', ''); + } + + // --- Footer (full width, below grid) --- const footer = contentEl.createDiv({ cls: 'ff-builder-footer' }); // Left side: undo/redo