cards: clamp the web note preview, as Android always has
CI & Build / Build now, or wait for Android? (push) Successful in 3s
CI & Build / Python lint (push) Successful in 3s
CI & Build / TypeScript typecheck (push) Successful in 6s
CI & Build / Python tests (push) Successful in 12s
CI & Build / integration (push) Successful in 13s
CI & Build / Build & push image (push) Successful in 29s
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 2m16s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 4m24s
Desktop (Tauri) / Update manifest (push) Successful in 4s

M13 step 4 asked for no bold first line, and step 3 already delivered that —
removing `note.title` took the card's <h3> and the Android editor's bold field
with it. What step 4 also asked for, and hadn't been done, was the other half:
"be willing to spend something small on legibility that isn't weight on the
first line."

The web card rendered the entire body. Android has always clamped to eight lines
(`MAX_PREVIEW_LINES`), so one long note produced a card taller than the screen on
the web and pushed the rest of the board off it — a real asymmetry between two
surfaces that are supposed to be peers.

It matters more without a title. The first line used to be what your eye caught;
with one weight throughout, an unbounded card is just a wall, and the note beside
it is the one you were actually looking for.

Clamped in the STRING, not with CSS `line-clamp` — that needs a `-webkit-box` and
behaves unreliably around the block elements MarkdownText emits (lists, quotes,
fenced code). Doing it before the parse is deterministic, matches Android's
semantics exactly, and skips parsing a body the card was never going to show.
This commit is contained in:
2026-08-23 01:00:39 -04:00
parent 6f21db85a1
commit c99cbb3e14
+21 -1
View File
@@ -54,6 +54,26 @@ const trashUrgent = computed(() => trashDays.value !== null && trashDays.value <
const firstImage = computed(() => props.note.attachments.find((a) => a.mime.startsWith("image/")));
const otherAttachments = computed(() => props.note.attachments.filter((a) => !a.mime.startsWith("image/")));
// How much of a note the CARD shows. Android has always clamped to 8
// (`MAX_PREVIEW_LINES`); the web rendered the whole body, so one long note could
// produce a card taller than the screen and push everything else off the board.
//
// It matters more now that the title is gone (M13 step 4). The first line used to be
// the thing your eye caught; with one weight throughout, an unbounded card is just a
// wall, and the note next to it is the one you were looking for.
//
// Clamped in the STRING rather than with CSS `line-clamp`, which needs a
// `-webkit-box` and behaves unreliably around the block elements MarkdownText emits
// (lists, quotes, fenced code). This is deterministic, matches Android's semantics
// exactly, and skips parsing a body the card was never going to show.
const PREVIEW_LINES = 8;
const bodyPreview = computed(() => {
const lines = props.note.body.split("\n");
if (lines.length <= PREVIEW_LINES) return props.note.body;
return lines.slice(0, PREVIEW_LINES).join("\n") + "\n…";
});
const root = ref<HTMLElement | null>(null);
// --- Drag-to-reorder. Pointer Events, gated behind an explicit grip handle so a
@@ -222,7 +242,7 @@ onBeforeUnmount(() => document.removeEventListener("mousedown", onDocMousedown))
@keydown.enter="emit('open', note)"
>
<div v-if="note.body" class="text-sm text-neutral-700 dark:text-neutral-300">
<MarkdownText :text="note.body" />
<MarkdownText :text="bodyPreview" />
</div>
<p
v-if="!note.body && !note.items.length && !note.attachments.length"