Unify compose + edit onto one surface (modal-only editor)
CI & Build / Python lint (push) Successful in 3s
CI & Build / TypeScript typecheck (push) Successful in 6s
CI & Build / Python tests (push) Successful in 9s
CI & Build / Build & push image (push) Successful in 30s

Live-pass feedback: compose and edit still felt like different surfaces.
They already shared one component (task 1920), but rendered as two frames —
an inline in-flow box (compose) vs a modal overlay (edit) — which read as
two designs. Per operator choice, make BOTH the modal.

NoteEditor is now modal-only (rule 22 — the inline frame is fully removed):
dropped the `inline`/`autofocus` props, the collapsed "Take a note" frame,
`expanded`, `open()`, `commitInline`, `autoGrow`, and the outside-click
commit. Compose vs edit is purely note=null vs a note. Esc / Ctrl+Enter /
backdrop / Done all commit-and-close (create in compose, save in edit);
Shift+Enter still saves & starts a fresh note in compose (now gated on
isCreate, not the frame). Edit-only sections gate on !isCreate.

BoardView: the always-expanded inline composer becomes a slim "Take a
note…" trigger bar that opens the SAME modal with an empty note; the `c`
shortcut does likewise. One surface for capture and editing — and the
seam the card→editor grow animation (1914) will hook into.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRgehjoz7Yv8LkUfADxACm
This commit is contained in:
2026-07-23 12:57:03 -04:00
co-authored by Claude Opus 4.8
parent d1bc91a54a
commit f9f1b77d37
2 changed files with 47 additions and 111 deletions
+14 -6
View File
@@ -14,14 +14,14 @@ const ui = useUiStore();
const router = useRouter();
const editing = ref<Note | null>(null);
const composer = ref<InstanceType<typeof NoteEditor> | null>(null);
const composing = ref(false); // compose modal open (a new, empty note)
const loadError = ref("");
// The global `c` shortcut bumps composeTick; reopen the composer when we're
// already on the board (a fresh navigation autofocuses it via the prop).
// Compose and edit are ONE surface: the "Take a note…" bar and the global `c`
// shortcut both open the same modal editor with an empty note (editing = null).
watch(
() => ui.composeTick,
() => composer.value?.open(),
() => (composing.value = true),
);
// The command palette opens a note by navigating here with ?open=<id>.
@@ -146,6 +146,7 @@ function openEditor(note: Note) {
}
function closeEditor() {
editing.value = null;
composing.value = false;
}
async function onNavigate(id: string) {
@@ -182,7 +183,14 @@ async function onDrop(target: Note) {
<template>
<div class="mx-auto w-full max-w-6xl px-4 py-6">
<NoteEditor v-if="isMainBoard" ref="composer" inline autofocus class="mb-6" />
<button
v-if="isMainBoard"
type="button"
class="mx-auto mb-6 block w-full max-w-xl rounded-xl border border-neutral-200 bg-white px-4 py-3 text-left text-sm text-neutral-500 shadow-sm transition hover:shadow-md focus:outline-none focus-visible:ring-2 focus-visible:ring-brand dark:border-neutral-700 dark:bg-neutral-900 dark:text-neutral-400"
@click="composing = true"
>
Take a note
</button>
<FilterBar v-if="isMainBoard" />
<div v-if="notes.loading" class="py-24 text-center text-sm text-neutral-400">Loading</div>
@@ -258,7 +266,7 @@ async function onDrop(target: Note) {
</template>
</div>
<template v-if="editing">
<template v-if="composing || editing">
<NoteEditor :note="editing" @close="closeEditor" @navigate="onNavigate" />
</template>
</template>