Skip to content

fix(ui): persist active resource tab in url, fix internal markdown links#3925

Open
TheodoreSpeaks wants to merge 5 commits intostagingfrom
feat/file-resource-links
Open

fix(ui): persist active resource tab in url, fix internal markdown links#3925
TheodoreSpeaks wants to merge 5 commits intostagingfrom
feat/file-resource-links

Conversation

@TheodoreSpeaks
Copy link
Copy Markdown
Collaborator

@TheodoreSpeaks TheodoreSpeaks commented Apr 4, 2026

Summary

Currently refreshing a mothership task defaults to the last resource tab opened. This can be confusing for a user who just refreshed. Instead, persist the resource id to the url so on refresh the same resource is opened.

File resources can have internal links to different sections. Previously this would reopen the whole page. Instead, we should navigate to the appropriate section of that resource. This scrolls the webview to the correct location.

Intercepts all link clicks to markdown files and checks if link is internal, starting with "#". If so, attempt to scroll the container to that header.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • Other: ___________

Testing

Validated that file resources can have internal link and external links that both behave appropriately.
Validated that downloaded file still uses correct link formatting.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

Screenshots/Videos

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Apr 4, 2026 8:52pm

Request Review

@TheodoreSpeaks
Copy link
Copy Markdown
Collaborator Author

@BugBot review @cursor review

@cursor
Copy link
Copy Markdown

cursor bot commented Apr 4, 2026

PR Summary

Medium Risk
Moderate UI/navigation changes that alter URL state and intercept markdown link clicks; risk is mainly regressions in routing/scroll behavior and unexpected link handling.

Overview
Persists the currently selected mothership resource tab in the URL via a resource query param, restoring that tab on refresh by threading initialActiveResourceId through HomeuseChat and preferring it when hydrating persisted resources.

Improves markdown file previews by adding heading ids (via rehype-slug) and a custom anchor renderer that distinguishes internal /workspace/... and #hash links: internal links use Next router navigation or smooth-scroll within the preview container, while external links continue to open in a new tab.

Reviewed by Cursor Bugbot for commit 865d7d7. Bugbot is set up for automated code reviews on this repo. Configure here.

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 0f95d73. Configure here.

@TheodoreSpeaks TheodoreSpeaks marked this pull request as ready for review April 4, 2026 17:35
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 4, 2026

Greptile Summary

This PR fixes internal markdown anchor link handling in the file viewer's PreviewPanel. Previously, clicking any link would either open it externally (full page reload) or not navigate correctly. Now, hash-only links (#section) scroll smoothly within the preview container, same-origin path links use Next.js client-side routing, and external links continue to open in a new tab.

The key changes are:

  • rehype-slug is added as a rehype plugin to automatically generate id attributes on all heading elements based on their text content
  • h1h4 custom components are updated to forward the id prop so the slug IDs are present on the DOM nodes
  • The static a component is replaced by a dynamic AnchorRenderer that classifies each link with isInternalHref, intercepts clicks, and dispatches smooth scroll or Next.js router navigation accordingly
  • A NavigateCtx React context threads router.push from MarkdownPreview down to AnchorRenderer, avoiding prop drilling through the static components map
  • rehypePlugins={REHYPE_PLUGINS} is added to every <ReactMarkdown> instance (committed, incoming, and checkbox branches)

Confidence Score: 4/5

Safe to merge with minor fixes — the core navigation logic is correct but two edge cases need attention: scroll target precision within overflow containers, and the silent no-op when NavigateCtx is null for internal path links.

Both P1 findings are real defects on the changed path: (1) scrollIntoView can misalign headings relative to the overflow container's viewport; (2) e.preventDefault is called unconditionally before the null-guard on navigate, making internal non-hash links silently dead if the context is ever absent. Neither causes data loss or a security issue, but both affect the primary user path (navigating via markdown links) described in this very fix.

apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-panel.tsx — specifically the AnchorRenderer handleClick and the NavigateCtx null-guard logic

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-panel.tsx Adds internal anchor navigation via rehype-slug + NavigateCtx + AnchorRenderer; logic is correct for hash-only and same-origin path links, though silently swallows clicks on internal non-hash links when NavigateCtx is null

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User clicks anchor in MarkdownPreview] --> B{href provided?}
    B -- No --> Z[No-op]
    B -- Yes --> C[isInternalHref called]
    C --> D{href starts with '#'?}
    D -- Yes --> E[pathname='', hash=href]
    D -- No --> F{new URL parseable?}
    F -- Yes --> G{same origin?}
    G -- Yes --> H[pathname + hash extracted]
    G -- No --> I[return null = external]
    F -- No --> J{starts with '/'?}
    J -- Yes --> K[pathname + hash extracted from string]
    J -- No --> I
    E --> L[parsed = internal]
    H --> L
    K --> L
    L --> M[handleClick fires]
    I --> N[AnchorRenderer renders with target=_blank]
    M --> O{modifier key held?}
    O -- Yes --> P[browser default = new tab]
    O -- No --> Q[e.preventDefault]
    Q --> R{pathname === '' AND hash?}
    R -- Yes --> S[document.getElementById hash.slice 1]
    S --> T[el?.scrollIntoView smooth]
    R -- No --> U{navigate context non-null?}
    U -- Yes --> V[router.push pathname + hash]
    U -- No --> W[⚠️ click silently dropped]
Loading

Reviews (1): Last reviewed commit: "Fix lint" | Re-trigger Greptile

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ec14b30. Configure here.

@TheodoreSpeaks TheodoreSpeaks changed the title fix(ui): handle markdown internal links fix(ui): persist active resource tab in url, fix internal markdown links Apr 4, 2026
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