mirror of
https://github.com/layer-systems/website.git
synced 2026-09-13 14:14:07 +02:00
* feat: highlight text in the Reader (NIP-84) Adds NIP-84 highlights (kind 9802) to the article reader: - Selecting text in an article shows a floating "Highlight" button (src/apps/articles/HighlightLayer.tsx), publishing the selected plain text tagged to the article (`a`) and its author (`p`, role "author"). - Existing highlights for the article are listed underneath it, with the highlighter's identity and timestamp. Closes #23 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BYiUtZMQeA5RHggQw73wto * fix: harden selection handling and clamp the highlight button Per review: - Guard sel.rangeCount === 0 before calling getRangeAt(0), which throws otherwise. - Scope containment by the range's commonAncestorContainer instead of just anchorNode, so a selection that starts inside the article but is dragged out past its boundary is correctly rejected. - Clamp the floating button's top so a selection near the top of the viewport doesn't push it off-screen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BYiUtZMQeA5RHggQw73wto * fix: don't highlight against a malformed address, gate the listener Per a "needs a closer look" review pass: - articles/index.tsx now passes an empty string, not a malformed "kind:pubkey:" address, when an article has no d tag. HighlightLayer treats a falsy address as "highlighting isn't available here." - The selectionchange listener is only registered when both user and address are present (in the effect's deps), instead of always running selection tracking regardless of whether a highlight could ever be published. - handleHighlight and the floating button both guard on address too, not just selection, so stale selection state from before a prop change went missing can't still trigger a publish. - docs/apps.md corrected: the saved text comes from Selection.toString() (window.getSelection()), not Range.toString(). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BYiUtZMQeA5RHggQw73wto --------- Co-authored-by: highperfocused <highperfocused@pm.me> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>