Mockup: attachment cards round 2, bounce cards like the original, shared context menu (#172, #245) #278

Closed
kayg wants to merge 0 commits from issue/172-attachment-cards-3 into dev
Owner

Round 2 of the attachment mockup, with kayg's iPhone follow-ups (bounce cards matched to the original, no card border, a real grid, one shared context menu with shortcut chips). It replaces #267 and #232 (the forge ignores pushes to an open PR), so it includes round 1 (#172) too, rebased on today's dev. Mockup only.

Live at https://preview.calternal.cloud/#/note/autumn-trip?list=all and https://preview.calternal.cloud/#/note/lake-weekend?list=all

Points from #245

  1. The card whose ⋯ or right-click menu is open stays grown, with its toolbar showing.
  2. Pressing a toolbar button never presses the picture (:has() keeps the press for the card itself).
  3. Not built: three options are posted on #245 for you to choose from.
  4. Nothing in the mockup to change; see the #245 comment.
  5. Hover is scale only: no lift, no photo drift, no map zoom, no PDF tilt.
  6. The name strip sits on the picture: a soft blur that fades in, the name, then dimensions or length and size in small tabular figures.
  7. "Deeplink" is gone from Copy as; Copy link to block is the one link.
  8. Double-click opens the original file (a 2000 px copy) in the viewer. A click shows it 1:1, and you can scroll around.
  9. A real recording plays. Its waveform is decoded from the sound (RMS per bar), and the player is only created on first play.
  10. Layout changes grow the card from its old shape (FLIP on a spring), and the blocks below glide to their new place. Keyboard changes happen at once.
  11. Syntax colours, lib/highlight.ts:
    • The language comes from the fence word or file extension, else from the code itself, and shows as "Plain text" when it can't tell.
    • Python, TS/JS, Rust, Shell, JSON, CSS and SQL.
    • Used by code blocks and code-file embeds.
  12. Embedded notes are drawn by the editor's own block renderer: BlockContent.svelte is now shared by Editor.svelte and NoteCard.svelte, and so is blockview.ts (tree lines and list numbers).
    • No side bar, and Open is in the toolbar.
    • Opening scales the note up out of its card instead of the fade.

Galleries (kayg's markdown decision)

  • Markdown: one image per line stays a single image. Several images on one line, separated by spaces, are a gallery.
  • Stack: our own take on bounce-cards, with no library. A fanned stack of prints bounces in on an elastic spring (WAAPI on scale) when it scrolls into view.
    • Pointing at a print brings it forward and nudges the others aside, as far as the line has room.
    • ← → change the front print with no motion.
    • Reduced motion: no bounce.
  • Grid is the other layout.
  • Building and splitting a gallery:
    • A quiet + beside a single image adds a picture to its line.
    • Dropping one image card on another joins them.
    • "Take out of gallery" moves a picture to its own line below.
  • Fixtures: "Weekend by the lake" shows both forms.

Follow-ups after the iPhone review (#245)

  • Bounce cards: matched to sveltebits' bounce-cards. A side-by-side check against the real GSAP component gives identical card positions, scales and angles at every frame of the entrance and the hover push.
  • Cards: no border.
  • Grid: fills the line in even rows, with the same corners as the cards.
  • Context menu: #155's menu now lives in packages/ui/components/ContextMenu.svelte, and the web app and the mockup both use it (both old copies are deleted). It adds the icon row, plus shortcut chips (warm-tooltip style, right-aligned) shown only when a keyboard is present. The web app's svelte-check passes with 0 errors.

Also

  • ui.svelte.ts: a focused element that unmounts made the focusout listener write state during Svelte's update (state_unsafe_mutation). That write is now deferred with a microtask.

🤖 Generated with Claude Code

https://claude.ai/code/session_018Yyy8fQGxPLkLa8v8NXz7T

Round 2 of the attachment mockup, with kayg's iPhone follow-ups (bounce cards matched to the original, no card border, a real grid, one shared context menu with shortcut chips). It replaces #267 and #232 (the forge ignores pushes to an open PR), so it includes round 1 (#172) too, rebased on today's dev. **Mockup only.** Live at https://preview.calternal.cloud/#/note/autumn-trip?list=all and https://preview.calternal.cloud/#/note/lake-weekend?list=all **Points from #245** 1. The card whose ⋯ or right-click menu is open stays grown, with its toolbar showing. 2. Pressing a toolbar button never presses the picture (`:has()` keeps the press for the card itself). 3. Not built: three options are posted on #245 for you to choose from. 4. Nothing in the mockup to change; see the #245 comment. 5. Hover is scale only: no lift, no photo drift, no map zoom, no PDF tilt. 6. The name strip sits on the picture: a soft blur that fades in, the name, then dimensions or length and size in small tabular figures. 7. "Deeplink" is gone from Copy as; Copy link to block is the one link. 8. Double-click opens the original file (a 2000 px copy) in the viewer. A click shows it 1:1, and you can scroll around. 9. A real recording plays. Its waveform is decoded from the sound (RMS per bar), and the player is only created on first play. 10. Layout changes grow the card from its old shape (FLIP on a spring), and the blocks below glide to their new place. Keyboard changes happen at once. 11. Syntax colours, `lib/highlight.ts`: - The language comes from the fence word or file extension, else from the code itself, and shows as "Plain text" when it can't tell. - Python, TS/JS, Rust, Shell, JSON, CSS and SQL. - Used by code blocks and code-file embeds. 12. Embedded notes are drawn by the editor's own block renderer: `BlockContent.svelte` is now shared by `Editor.svelte` and `NoteCard.svelte`, and so is `blockview.ts` (tree lines and list numbers). - No side bar, and Open is in the toolbar. - Opening scales the note up out of its card instead of the fade. **Galleries (kayg's markdown decision)** - **Markdown:** one image per line stays a single image. Several images on one line, separated by spaces, are a gallery. - **Stack:** our own take on bounce-cards, with no library. A fanned stack of prints bounces in on an elastic spring (WAAPI on `scale`) when it scrolls into view. - Pointing at a print brings it forward and nudges the others aside, as far as the line has room. - ← → change the front print with no motion. - Reduced motion: no bounce. - **Grid** is the other layout. - **Building and splitting a gallery:** - A quiet + beside a single image adds a picture to its line. - Dropping one image card on another joins them. - "Take out of gallery" moves a picture to its own line below. - **Fixtures:** "Weekend by the lake" shows both forms. **Follow-ups after the iPhone review (#245)** - **Bounce cards:** matched to sveltebits' bounce-cards. A side-by-side check against the real GSAP component gives identical card positions, scales and angles at every frame of the entrance and the hover push. - **Cards:** no border. - **Grid:** fills the line in even rows, with the same corners as the cards. - **Context menu:** #155's menu now lives in `packages/ui/components/ContextMenu.svelte`, and the web app and the mockup both use it (both old copies are deleted). It adds the icon row, plus shortcut chips (warm-tooltip style, right-aligned) shown only when a keyboard is present. The web app's `svelte-check` passes with 0 errors. **Also** - `ui.svelte.ts`: a focused element that unmounts made the focusout listener write state during Svelte's update (`state_unsafe_mutation`). That write is now deferred with a microtask. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_018Yyy8fQGxPLkLa8v8NXz7T
Every embed is a floating card with layered depth that lifts and grows a
touch on a spring under the pointer (kayg.org's card feel), and focuses with
a ring and no motion from the keyboard. Each kind gets its own context menu
(layouts as an icon row, the kind's actions, then the shared tail: copy
link to block, copy as, duplicate, move, delete) and a mini toolbar with the
layouts and the one or two actions people reach for most.

Fixture note "Autumn trip": Large and Card photos, a gallery made from
adjacent photos (carousel or grid), HEIC, GIF, video, a recording,
PDF, CSV, code, a plain file, an embedded note, a link card and pill, and a
place from a geo: link. Stacked on #176 (#133's mockup refresh).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Yyy8fQGxPLkLa8v8NXz7T
Mockup round 2 for attachments: kayg's review (#245)
Some checks failed
CI / server (pull_request) Successful in 28s
CI / rust (pull_request) Failing after 2m4s
CI / web (pull_request) Failing after 15s
f8c3632c59
- The card whose menu is open stays grown with its toolbar showing (1).
- Pressing the toolbar never presses the picture (2).
- Hover is scale only: no lift, no photo drifting inside (5).
- Pictures carry their name on a soft blurred strip with size and
  dimensions (6).
- Copy as drops Deeplink; Copy link to block is the one link (7).
- Double-click opens the original at full resolution, click for 1:1 (8).
- Recordings play for real and draw their waveform from the sound (9).
- Layout changes grow from the old shape; text below glides (10).
- Code blocks and code files find their language, say Plain text
  otherwise, and get syntax colours (11).
- Embedded notes are drawn by the editor's own block renderer
  (BlockContent), no side bar, Open in the toolbar, and the note scales up
  out of its card when opened (12).
- Galleries: several images on one line. They bounce in as a fanned
  stack when scrolled into view (our own take on bounce-cards); pointing
  brings a print forward, arrow keys do it at once. A quiet + beside a
  single image adds a picture to its line, dropping one image on another
  joins them, and Take out of gallery moves one to its own line.
- Fixture note "Weekend by the lake" shows both ways to write pictures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Yyy8fQGxPLkLa8v8NXz7T
Bounce cards match the original; grid fills the line; one shared menu (#245)
Some checks failed
CI / server (pull_request) Successful in 27s
CI / web (pull_request) Failing after 27s
CI / rust (pull_request) Successful in 1m59s
5521b92a85
- Galleries: the stack now plays exactly like sveltebits' bounce-cards:
  the same five places, elastic.out(1, 0.8) over 0.5 s, 0.06 s apart
  after 0.5 s, and the hover push (straighten, others 160 px along their
  tilt, back.out(1.4), 0.4 s, 0.05 s per step). GSAP's curves are written
  as CSS linear() easings and its transforms as move-then-turn, so frame
  by frame the numbers match the original's. No border on the cards.
- Grid: square pictures filling the line in even rows with the cards'
  corners; an odd count lets the first one span the row. (The cells had
  picked up the file row's 40 px tile style.)
- Menus: the app's #155 context menu moves to packages/ui and both the
  web app and the mockup use it; the mockup's copy is gone. It gains the
  icon row (layouts) and shortcut chips in the warm tooltip's style,
  right-aligned, shown only with a keyboard (fine hover pointer, or a
  real key pressed this session).

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

Landed in merge train #282.

Landed in merge train #282.
kayg closed this pull request 2026-10-14 13:10:23 +00:00
Some checks failed
CI / server (pull_request) Successful in 27s
CI / web (pull_request) Failing after 27s
CI / rust (pull_request) Successful in 1m59s

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!278
No description provided.