From 0f787c6363659e6ec7789b759b47e37f88d70bb1 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Fri, 30 Oct 2026 09:56:58 -0400 Subject: [PATCH] The board places each card in the shortest column, instead of leaving it to CSS columns CSS multi-column decides placement by balancing column heights, so the same notes could land differently at the same width: an edit left two cards alone in the fourth column with the middle two empty, and a refresh left the fourth empty beside a stack of three in the first. Cards now go, in board order, into the shortest column, leftmost on a tie, so the same notes at the same width always land the same way and every column fills before any stacks. This changes the reading order to match Android: the second note sits top-right rather than under the first. useMasonry measures the cards and watches them for height changes. Placement is a pure function, tested in notes/masonry.test.ts. Cards are absolutely placed, so TransitionGroup's move animation carries on working unchanged. Issue #6709. Co-Authored-By: Claude Opus 5.5 --- .../com/fabledsword/inkwell/ui/BoardScreen.kt | 2 +- frontend/src/components/NoteCard.vue | 2 +- frontend/src/components/NoteGrid.vue | 12 ++- frontend/src/composables/useCardDrag.ts | 4 +- frontend/src/composables/useMasonry.ts | 91 +++++++++++++++++++ frontend/src/notes/masonry.test.ts | 38 ++++++++ frontend/src/notes/masonry.ts | 33 +++++++ frontend/src/style.css | 6 +- 8 files changed, 177 insertions(+), 11 deletions(-) create mode 100644 frontend/src/composables/useMasonry.ts create mode 100644 frontend/src/notes/masonry.test.ts create mode 100644 frontend/src/notes/masonry.ts diff --git a/android/app/src/main/java/com/fabledsword/inkwell/ui/BoardScreen.kt b/android/app/src/main/java/com/fabledsword/inkwell/ui/BoardScreen.kt index 5f59453..7d49435 100644 --- a/android/app/src/main/java/com/fabledsword/inkwell/ui/BoardScreen.kt +++ b/android/app/src/main/java/com/fabledsword/inkwell/ui/BoardScreen.kt @@ -530,7 +530,7 @@ private fun DrawerRow( * Staggered rather than a uniform grid because notes are wildly different heights * — a one-line thought beside a twelve-item checklist — and forcing them to a * common height either clips the long ones or strands whitespace under the short - * ones. This is the Compose equivalent of the CSS multi-column `NoteGrid.vue` uses. + * ones. `NoteGrid.vue` places cards the same way, each into the shortest column. */ @Composable private fun NoteBoard( diff --git a/frontend/src/components/NoteCard.vue b/frontend/src/components/NoteCard.vue index 28c1cb4..820e26f 100644 --- a/frontend/src/components/NoteCard.vue +++ b/frontend/src/components/NoteCard.vue @@ -206,7 +206,7 @@ const tagColors = computed>(() => {