Skip to content

feat(markdown): add copiable anchor links to headings#167

Open
adrianschmidt-bot wants to merge 3 commits intojgroth:mainfrom
adrianschmidt-bot:feat/anchor-links-on-headings
Open

feat(markdown): add copiable anchor links to headings#167
adrianschmidt-bot wants to merge 3 commits intojgroth:mainfrom
adrianschmidt-bot:feat/anchor-links-on-headings

Conversation

@adrianschmidt-bot
Copy link
Contributor

@adrianschmidt-bot adrianschmidt-bot commented Feb 11, 2026

Summary

Adds clickable anchor links that appear on hover next to all headings (h1-h6) in markdown content.

Anchor link example

Behavior

When hovering over a heading with an ID, a # link appears. Clicking it:

  1. Updates the URL with the anchor fragment
  2. Copies the full URL to clipboard

This makes it easy to share direct links to specific sections in documentation.

Implementation

  • Uses the existing rehype-slug plugin (from PR Add support for cross-page anchor links #160) which already adds IDs to headings
  • After markdown renders, addAnchorLinks() appends anchor elements to each heading
  • CSS shows the link on hover with a smooth fade transition
  • Click handler updates URL and copies to clipboard

Styling

  • Anchor link positioned to the left of the heading
  • Fades in on hover (0.15s transition)
  • Uses theme color on hover (--kompendium-color-turquoise)

Closes #145

Summary by CodeRabbit

  • New Features
    • Added shareable, route-aware anchor links to markdown headings (h1–h6). Anchors appear on hover/focus, update the browser URL when clicked, and attempt to copy the full heading URL to the clipboard for easy sharing. Anchors integrate with existing in-page navigation and skip headings that already include links.

Adds clickable anchor links (#) that appear on hover next to all headings
(h1-h6) in markdown content. Clicking the link:
- Updates the URL with the anchor
- Copies the full URL to clipboard

This makes it easy to share direct links to specific sections in documentation.

Closes jgroth#145
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 11, 2026

📝 Walkthrough

Walkthrough

Adds copiable anchor links to rendered markdown headings (h1–h6). After render the component inserts anchor elements for headings with IDs; clicking an anchor updates history with a route-aware hash and attempts to copy the full URL to the clipboard. Styling reveals anchors on heading hover/focus.

Changes

Cohort / File(s) Summary
Anchor Link Styling
src/components/markdown/markdown.scss
Adds .anchor-link styles to position a hidden anchor left of headings, reveal it on heading hover/focus, and apply hover/focus color and accessibility styles.
Anchor Link Implementation
src/components/markdown/markdown.tsx
Imports getRoute; adds addAnchorLinks() to attach/wrap anchors for headed elements with IDs, getAnchorHref(id) to build route-aware hrefs, and handleAnchorClick(event, id) to pushState and attempt to copy the full URL. Integrates augmentation into post-render flow before anchor scrolling.

Sequence Diagram

sequenceDiagram
    participant User
    participant Component as Markdown Component
    participant DOM
    participant URLState as URL/History
    participant Clipboard

    Component->>DOM: render markdown HTML
    Component->>Component: addAnchorLinks() — scan headings, append anchors
    User->>DOM: click anchor link
    DOM->>Component: handleAnchorClick(event, id)
    Component->>Component: getAnchorHref(id)
    Component->>URLState: history.pushState(...) with route-aware `#id`
    Component->>Clipboard: try navigator.clipboard.writeText(fullUrl)
    URLState->>User: browser URL updates (hash)
    Clipboard->>User: copy success/failure (best-effort)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • jgroth
  • adrianschmidt

Poem

🐰
Anchors peek out when headings say hi,
Click and the URL hops, ready to fly.
Copied with care, a turquoise small wink,
Share the exact line in less time than you think.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding copiable anchor links to headings in markdown components.
Linked Issues check ✅ Passed The PR implements all primary objectives from issue #145: anchor links on headings (h1-h6), hover visibility, URL updates with anchor fragments, clipboard copy functionality, and integration with heading IDs.
Out of Scope Changes check ✅ Passed All changes are directly related to the anchor links feature: CSS styling for .anchor-link, JavaScript logic for addAnchorLinks(), anchor href computation, and click handling with URL/clipboard updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

No actionable comments were generated in the recent review. 🎉


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/components/markdown/markdown.tsx`:
- Around line 106-118: The handleAnchorClick function builds fullUrl without
window.location.search and calls navigator.clipboard.writeText without
feature-detection; update handleAnchorClick (and its use of getAnchorHref) to
append window.location.search when constructing the fullUrl (and when updating
history if you want the URL in the address bar to keep query params), and guard
clipboard access by checking if navigator.clipboard and
navigator.clipboard.writeText exist before calling them (fall back to no-op or a
safe alternative if unavailable) so that no exception is thrown before the
.catch() can run.

preserve query params and guard clipboard access
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/components/markdown/markdown.tsx`:
- Around line 99-104: getAnchorHref currently builds fragments like "##id" when
getRoute() returns an empty string; update the getAnchorHref(id: string)
implementation to check the route (obtained via getRoute()) and if
routeWithoutAnchor is empty return `#${id}`, otherwise return
`#${routeWithoutAnchor}#${id}` so you don't produce double-hash fragments;
modify the getAnchorHref method accordingly.

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