obsidian-formfire/docs/plans/2026-02-13-phase1-quick-wins-design.md
tolvitty d48bb1b052 docs: add Phase 1 quick wins design document
Covers new field types (slider, color, time), keyboard navigation,
and form import/export.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 14:40:24 +01:00

4.1 KiB

Phase 1 — Quick Wins Design

Status: Approved Date: 2026-02-13 Scope: New field types, keyboard navigation, form import/export


Overview

Phase 1 adds three categories of improvements to Formfire:

  1. Three new field types (slider, color, time)
  2. Keyboard navigation in the form modal
  3. Form import/export via JSON files

These features extend existing patterns with minimal architectural changes.


1. New Field Types

Type System Changes (types.ts)

Extend FieldType union with 'slider' | 'color' | 'time'.

Add optional properties to FormField:

  • min?: number — slider minimum (default: 0)
  • max?: number — slider maximum (default: 100)
  • step?: number — slider step increment (default: 1)

Renderers (field-renderers.ts)

Type HTML Element getValue() Notes
slider <input type="range"> + value label number Live value display, min/max/step from FormField
color <input type="color"> + hex label string (#hex) Default: #000000
time <input type="time"> string (HH:MM) Mirrors existing date renderer pattern

All three implement the standard RenderedField interface (getValue/setValue/setError).

Builder Changes (form-builder.ts)

  • Add 'slider', 'color', 'time' to FIELD_TYPES array
  • Show Min/Max/Step settings when field type is slider
  • Placeholder support for time (same as date)

Validation (validators.ts)

  • Slider: validate value is within min/max range

2. Keyboard Navigation

Form Modal (form-modal.ts)

Single keydown listener on modal contentEl with event delegation:

  • Ctrl+Enter → Submit form (always)
  • Enter on single-line inputs (text, number, date, time, color, dropdown) → Submit, unless a suggest dropdown is open
  • Enter on textarea → normal line break (no submit)
  • Escape → Close modal (already handled by Obsidian's Modal base class)

Field Renderer Accessibility (field-renderers.ts)

  • Toggle: Add tabindex="0", Space/Enter to toggle
  • Rating: Add tabindex="0", Arrow Left/Right to change value, Enter to confirm
  • Tags: Input already has focus handling, just needs tab-order

Tab order follows field definition order naturally via DOM order.


3. Form Import/Export

New Module: src/utils/form-io.ts

Two pure functions:

exportForms(forms: FormDefinition[]): string

Serializes to JSON with version wrapper: { version: 1, forms: [...] }.

importForms(json: string): FormDefinition[]

Parses JSON, validates structure (forms array, each form has id/name/fields), generates new UUIDs for imported forms to prevent ID collisions.

Settings Tab Changes (settings-tab.ts)

New buttons below "New Form":

  • Export All — Creates JSON blob, triggers browser download as formfire-export.json
  • Import — Opens native file input (<input type="file" accept=".json">), reads file, validates, adds forms to store

Per-form Export button in the form list (alongside Edit/Duplicate/Delete). Exports single form.

Error Handling

  • Invalid JSON → Notice("Invalid JSON file")
  • Missing required fields → Notice("Invalid form format")
  • Success → Notice("Imported X form(s)")

No import preview modal — validation is sufficient. YAGNI.


Files Changed

File Change
src/types.ts Extend FieldType, add min/max/step to FormField
src/ui/field-renderers.ts Add slider, color, time renderers; add tabindex/keyboard to toggle, rating
src/ui/form-modal.ts Add keydown listener for Ctrl+Enter, Enter submit
src/ui/form-builder.ts Extend FIELD_TYPES, add slider-specific settings
src/utils/validators.ts Add slider range validation
src/utils/form-io.ts New — exportForms, importForms
src/ui/settings-tab.ts Add Export All, Import, per-form Export buttons
styles.css Styles for slider, color, time fields

Out of Scope

  • Import preview/diff modal
  • Clipboard-based import/export
  • Cloud sync or sharing
  • Migration logic between form versions