Skip to content

feat(templates): author templates on the note surface - #941

Merged
h4yfans merged 13 commits into
mainfrom
template-editor-note-surface
Aug 4, 2026
Merged

feat(templates): author templates on the note surface#941
h4yfans merged 13 commits into
mainfrom
template-editor-note-surface

Conversation

@h4yfans

@h4yfans h4yfans commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Templates were authored on a bespoke form — its own header, a description textarea, and the note editor boxed inside a card. This replaces that screen with the note editing surface itself, so a template is written exactly the way a note is.

What changes

Authoring. pages/template-editor.tsx is rewritten to compose the primitives the note page already uses — NoteLayout, NoteTitle, TagsRow, InfoSection, GhostAffordanceRow, ContentArea. pages/note.tsx is untouched: what is shared is the components, not the page.

Saving. A new template is an in-memory draft — nothing reaches the database until Create Template (disabled while the name is blank), so a half-typed template never litters the list. After creation the button becomes Update and saving turns continuous: an 800 ms debounce, skipped whenever the serialized payload is byte-identical to the last persisted one, since every write enqueues a sync item. The state machine lives in hooks/use-template-draft.ts, isolated from rendering.

Closing. A dirty draft marks its tab and prompts Save / Don't Save / Cancel on close. The guard registry sits inside the tabs context (contexts/tabs/close-guard.tsx), so the ✕, middle-click, the tab context menu, ⌘W, and close-others/right/all are all covered without patching the six call sites. Tabs that register no guard behave exactly as before. Window close and app quit are deliberately out of scope.

Built-ins. Open read-only with a Duplicate & Edit button that opens the editable copy in a new tab.

Settings. Clicking a row opens the editor tab instead of the inline preview, which is removed.

Bugs fixed along the way

Both pre-existing, both surfaced by rewriting this code:

  • Property types were silently degrading. mapFromTemplatePropertyType had no reverse mapping for select, multiselect, or rating, so they fell through to text. Editing anything in a template holding a select property rewrote that property's type permanently. lib/template-properties.ts fixes it structurally: TemplateProperty stays the stored truth behind a stable id and maps to the UI shape for display only — nothing maps back. Index-derived ids (prop-${index}), which also broke under reorder, are gone with it.
  • The template icon had no setter. It was read from state and never written, so it could not be changed. It now uses the shared IconPickerButton.

Removals

  • pages/templates.tsx and the templates tab type — a 19K list page nothing in the app ever opened. Safe on restore: an unrecognised stored tab lands on the "unknown tab type" branch, not a crash.
  • pages/settings/template-preview.tsx — superseded by the editor tab.
  • phaseF.pagesTemplateEditor and phaseF.pagesTemplates locale keys, orphaned by the two deletions above.

Compatibility

No schema, IPC contract, vault format, or sync protocol change. The description field is no longer edited here but is preserved on disk — updateTemplate treats an omitted description as "keep", so existing values survive untouched and still show in the Settings list.

Verification

  • renderer: 546 files, 6114 tests, green
  • main: 422 files, 4597 tests, green
  • pnpm typecheck (includes contracts, architecture, ipc:check), pnpm lint (0 errors), git diff --check
  • i18n: new strings across all 32 locales; i18n:check and the icu-brace-style / placeholder-parity locale tests green. The literal {{title}} in the content placeholder is ICU-escaped, which the brace test enforces.
  • pnpm docs:impact --base origin/main --strict and pnpm docs:build
  • Both template E2E specs drive window.api.templates.* directly, so the UI rewrite does not touch them.

Not yet done: an interactive smoke pass in a running app.

Spec: docs/superpowers/specs/2026-08-04-template-editor-as-note-page-design.md

Copilot AI lite review requested due to automatic review settings August 4, 2026 05:45

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions github-actions Bot added documentation Improvements or additions to documentation enhancement New feature or request test labels Aug 4, 2026
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit fa0ff2e.

@codecov

codecov Bot commented Aug 4, 2026

Copy link
Copy Markdown

React Doctor flagged six `no-ref-current-in-render` errors: the latest-ref
pattern was assigning during render, which React may replay or discard.
Every one now syncs in an effect, matching the convention already documented
in the tabs context ("must be in useEffect per React rules").

Four real defects fixed alongside it:

- The editor read its tab from `useActiveTab()`, so in a split view it drove
  whichever tab was focused rather than its own. `TabContent` now passes
  `tabId` down.
- Keying the surface off `templateId` remounted the whole editor the moment a
  draft adopted its new id — mid-typing, right after Create. The key is pinned
  to the identity the tab opened with, and the new template seeds the query
  cache so the surface never flips to loading.
- Pending tag colours were stored lower-cased but looked up raw-cased, so a
  tag typed with a capital lost its colour until the notes query caught up.
- The unsaved-changes prompt used `AlertDialogAction`, which is Dialog.Close:
  it fired `onOpenChange(false)` on top of the handler, and the guard read
  that as a Cancel that aborted the close the user had just confirmed. The
  registry now ignores a resolution that lands while one is in flight, and
  drops the Save button when the pending work has no name to save under.

Regression tests cover the remount and the tab-identity fixes; both were
confirmed to fail against the unfixed code.
Copilot AI review requested due to automatic review settings August 4, 2026 06:27

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@h4yfans
h4yfans marked this pull request as ready for review August 4, 2026 06:35
@h4yfans
h4yfans merged commit f59b029 into main Aug 4, 2026
16 checks passed
@h4yfans
h4yfans deleted the template-editor-note-surface branch August 4, 2026 06:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants