Mockup: swipe actions on rows, one rowActions registry (#400) #433

Closed
kayg wants to merge 2 commits from issue/400-swipe-mockup into dev
Owner

Mockup for #400: swipe actions on rows, with every route to a row's actions fed by one registry.

Preview: https://preview.calternal.cloud/swipe.html#/note/calternal-rewrite?list=all (on a phone, #/list/all). The Mockup pill has the switches for the questions still open.

What's in it

  • Rows that swipe: the note list, the sidebar (places and tags), search results and the Trash.
  • Left → right: Copy link (a long swipe copies) and Open. Search adds Insert link here while a note is open behind it, and stays open afterwards.
  • Right → left: Archive, Hide and Delete (a long swipe moves the note to the Trash, with Undo). In the Trash, Restore comes from the left. Delete forever is never a long swipe: it asks "Confirm" in place first.
  • Archive and Hide, as kayg decided them (W13, W17–W19, W22):
    • Archive: an Archive place shows once anything is archived, and a long swipe there unarchives.
    • Hide: hidden items leave every list, search and Linked here.
    • In search, the words "archived" and "hidden" bring them back, and each result's ⋯ has Show hidden items.
  • Long press (W10): a card with the row's preview and every action under it.
  • Desktop: ⋯ on hover and focus, the same menu on right-click, and shortcuts on the focused row (⌘↵ insert link, ⌘C copy link, ⌘⌫ delete, ⇧F10 menu).
  • Still open, as switches: W14 (which link action comes first in search), W15 (Pin as a swipe button or only in the menus), W16 (Open as a swipe button).

Code (all in apps/mockup/src/rows/, made to move into #399 and #312 later)

  • swipe-row.ts: the gesture, a Svelte action.
    • The row follows the finger 1:1, then stretches with resistance past the buttons (×0.55).
    • At the long-swipe point the outer button grows into the gap on a spring detent.
    • On release a WAAPI spring keeps the finger's speed (spring-to.ts): it opens past half the buttons or on a flick faster than 0.3 px/ms.
    • It never starts in the left 24 px of the screen. It claims the touch at ≥10 px sideways, more than 2× the vertical movement, within 300 ms by event timestamps. A still hold of 500 ms is a long press.
    • It uses non-passive touch listeners (WebKit 232545) and writes transforms only; the one layout read is the row's width, once per touch.
    • One row is open at a time.
  • row-actions.ts: the rowActions registry. It builds the swipe tray, the ⋯ and right-click menu, the card, the shortcuts and aria-actions.
  • RowActions.svelte wraps any row, and RowCard.svelte is the long-press card.
  • plugins/: the note, search, sidebar and Trash actions.
  • packages/ui gains three icons: archive, hide and show.
  • Search's old long-press popover is no longer used, and the ⋯ menu replaces the hand-written right-click menus for these rows.

Checks

Real touch through CDP in Chromium at 320, 375 and 390, light and dark, plus mouse at 1440. The screenshots and a frame strip are on #400. Emulation can't prove the iPhone gesture, so there's a checklist for kayg on #400.

🤖 Generated with Claude Code

https://claude.ai/code/session_018Yyy8fQGxPLkLa8v8NXz7T

Mockup for #400: swipe actions on rows, with every route to a row's actions fed by one registry. **Preview:** https://preview.calternal.cloud/swipe.html#/note/calternal-rewrite?list=all (on a phone, `#/list/all`). The Mockup pill has the switches for the questions still open. ## What's in it - **Rows that swipe:** the note list, the sidebar (places and tags), search results and the Trash. - **Left → right:** Copy link (a long swipe copies) and Open. Search adds *Insert link here* while a note is open behind it, and stays open afterwards. - **Right → left:** Archive, Hide and Delete (a long swipe moves the note to the Trash, with Undo). In the Trash, Restore comes from the left. *Delete forever* is never a long swipe: it asks "Confirm" in place first. - **Archive and Hide, as kayg decided them (W13, W17–W19, W22):** - Archive: an Archive place shows once anything is archived, and a long swipe there unarchives. - Hide: hidden items leave every list, search and Linked here. - In search, the words "archived" and "hidden" bring them back, and each result's ⋯ has *Show hidden items*. - **Long press (W10):** a card with the row's preview and every action under it. - **Desktop:** ⋯ on hover and focus, the same menu on right-click, and shortcuts on the focused row (⌘↵ insert link, ⌘C copy link, ⌘⌫ delete, ⇧F10 menu). - **Still open, as switches:** W14 (which link action comes first in search), W15 (Pin as a swipe button or only in the menus), W16 (Open as a swipe button). ## Code (all in `apps/mockup/src/rows/`, made to move into #399 and #312 later) - `swipe-row.ts`: the gesture, a Svelte action. - The row follows the finger 1:1, then stretches with resistance past the buttons (×0.55). - At the long-swipe point the outer button grows into the gap on a spring detent. - On release a WAAPI spring keeps the finger's speed (`spring-to.ts`): it opens past half the buttons or on a flick faster than 0.3 px/ms. - It never starts in the left 24 px of the screen. It claims the touch at ≥10 px sideways, more than 2× the vertical movement, within 300 ms by event timestamps. A still hold of 500 ms is a long press. - It uses non-passive touch listeners (WebKit 232545) and writes transforms only; the one layout read is the row's width, once per touch. - One row is open at a time. - `row-actions.ts`: the `rowActions` registry. It builds the swipe tray, the ⋯ and right-click menu, the card, the shortcuts and `aria-actions`. - `RowActions.svelte` wraps any row, and `RowCard.svelte` is the long-press card. - `plugins/`: the note, search, sidebar and Trash actions. - `packages/ui` gains three icons: archive, hide and show. - Search's old long-press popover is no longer used, and the ⋯ menu replaces the hand-written right-click menus for these rows. ## Checks Real touch through CDP in Chromium at 320, 375 and 390, light and dark, plus mouse at 1440. The screenshots and a frame strip are on #400. Emulation can't prove the iPhone gesture, so there's a checklist for kayg on #400. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_018Yyy8fQGxPLkLa8v8NXz7T
Rows swipe in the note list, the sidebar (places and tags), search results and the Trash. Every
route to a row's actions reads one registry (rows/row-actions.ts): the swipe buttons, the ⋯ and
right-click menu, the long-press card, the shortcuts on a focused row and aria-actions.

- rows/swipe-row.ts: the gesture. Follows the finger 1:1, rubber-bands past the buttons (×0.55),
  a long swipe grows the outer button into the gap on a spring detent, release keeps the finger's
  speed (springTo). Never from the left 24 px; claims at ≥10 px sideways, >2× vertical, within
  300 ms of the touch; a still hold is a long press. Non-passive touch listeners (WebKit 232545).
  Transforms only; one width read per touch.
- rows/RowActions.svelte, RowCard.svelte: the tray, the ⋯ on hover/focus, the long-press card
  (preview with every action under it).
- rows/plugins: note, search, sidebar and Trash actions. Archive and Hide as kayg decided them
  (W13, W17–W19): an Archive place once anything is archived, Unarchive on its long swipe; "archived"
  and "hidden" in search, and "Show hidden items" in a result's ⋯.
- Still open, as mockup switches: W14 search's left → right order, W15 Pin, W16 Open as a button.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Yyy8fQGxPLkLa8v8NXz7T
Swipe rows: labels wrap only between words, ⋯ steps aside while a row moves (#400)
Some checks failed
CI / server (pull_request) Successful in 1m6s
CI / rust (pull_request) Successful in 2m39s
CI / web (pull_request) Failing after 44m13s
56313bd51f
"Unarchive" broke mid-word in its 56 px tile; labels now wrap between words only. The ⋯ hid the
tray during a mouse swipe; it now steps aside while the row is moved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Yyy8fQGxPLkLa8v8NXz7T
Author
Owner

Closing: superseded by #510 (named in the PR body or comments). Branch kept.

Closing: superseded by #510 (named in the PR body or comments). Branch kept.
kayg closed this pull request 2026-11-04 13:04:26 +00:00
Some checks failed
CI / server (pull_request) Successful in 1m6s
CI / rust (pull_request) Successful in 2m39s
CI / web (pull_request) Failing after 44m13s

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal!433
No description provided.