Skip to content

hover-key-figure: presentation-ready key-figure preview for discourse nodes - #18

Open
mattakamatsu wants to merge 4 commits into
mainfrom
hover-key-figure
Open

hover-key-figure: presentation-ready key-figure preview for discourse nodes#18
mattakamatsu wants to merge 4 commits into
mainfrom
hover-key-figure

Conversation

@mattakamatsu

Copy link
Copy Markdown

What this is

A new prototype for presenting discourse nodes in the outliner during a live discussion (journal club, lab meeting). Hover a discourse-node reference and a small "Figure" chip appears next to it. Click the chip to open a pinned card showing the node's key figure. Click the image to expand it to a full-screen lightbox. Esc unwinds one layer at a time. Nothing is added to the page at rest.

This executes the outline half of PRO-50 (Node info hover preview) and DES-85 (the May 2025 mockup). The full request inventory and Linear state live in the dg-prototypes dossier (roam-discourse-hover-metadata/CONTEXT.md); the design is in this prototype's SPEC.md, with Matt's three product decisions marked FIRM: hover-then-click trigger designed for presentation, key figure only in v1, and click-to-expand in v1.

How the key figure is found

  1. Manual key image first: the page's Roam props at discourse-graph.keyImage, which is where ENG-2123 decided manual key images will be stored. The plugin has not shipped that yet, so this read is forward-compatibility, not a dependency.
  2. Otherwise the first image on the page, using the same semantics as the plugin's findFirstImage: images reached through ((block refs)) and {{[[embed]]: ((uid))}} trees count, children are walked in document order, and cycles are guarded. Results are cached for 5 minutes and prefetched on hover so the click answers instantly.

Node references are recognized using the graph's own discourse-graph/nodes/* Format pages (matcher ported from copy-for-latex), with a fallback pattern when the plugin is not configured, plus a settings field for an extra pattern.

Testing

  • 34 vitest tests, including a smoke test that imports the built dist/extension.js with host globals stubbed and loads it the way a roam/js block does (extensionAPI undefined), which is the path that has silently eaten load errors before.
  • A source-text test enforces the no-default-imports-from-roamjs-components rule.
  • Opt-in strict typecheck passes: pnpm exec tsc -p tsconfig.check.json.
  • pnpm build and pnpm prepare:artifacts succeed; the bundle carries its own CSS so the roam/js preview path is styled.

How to try it

Wait for the Roam prototype previews comment below, paste its URL into Roam under Settings, Extensions, Developer, Load from URL, then hover any [[RES]] or [[EVD]] style reference on a page whose node has a figure.

🤖 Generated with Claude Code

… nodes

Hover a discourse-node reference in the outliner, click the Figure chip,
see the node's key figure in a pinned card; click the image for a
full-viewport lightbox. Nothing on the page at rest.

- Eligibility from the graph's discourse-graph/nodes/* formats (ported
  from copy-for-latex), [[XXX]] - fallback, extra-pattern setting.
- Key-figure resolution: manual discourse-graph.keyImage prop
  (ENG-2123 forward-compat) over automatic first-image walk with
  embed + block-ref traversal and cycle guard; 5-min cache; prefetch
  on hover.
- 34 tests incl. a dist smoke test on the roam/js load path
  (extensionAPI undefined); opt-in strict typecheck.

Executes the outline half of PRO-50/DES-85; spec in SPEC.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown

Roam prototype previews

The preview deployment is ready. Paste a URL below into Load Developer Extensions from URL in Roam:

View publishing details

mattakamatsu and others added 3 commits August 20, 2026 14:51
Long node titles put the reference's right edge a full line-width away
from the cursor, so the old placement forced mouse travel to reach the
affordance (first live-test feedback). The chip now shows centered 14px
below the pointer position captured when the hover dwell fires, clamped
to the viewport, and the figure card anchors to the chip instead of the
reference.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
An EVD titled '[[EVD]] - ... clustering.  -' (bare trailing dash, no
Source) fails the '[[EVD]] - {content} - {Source}' format regex because
the separator needs a space after the dash — the plugin itself does not
recognize that page as a node. The chip is read-only, so it now also
accepts any '[[XXX]] - ' prefixed title alongside the configured
formats, instead of only when zero formats load.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Long node titles wrap, and a chip placed at the pointer's own y lands
between the wrapped lines, on top of the text (second live-test
feedback). The chip now uses the reference's union bounding rect:
pointer x (clamped to the link's horizontal extent), y just below
rect.bottom, flipping above the block when the viewport runs out below.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant