diff --git a/.changeset/hot-lobsters-yell.md b/.changeset/hot-lobsters-yell.md new file mode 100644 index 0000000000..1fdc923a82 --- /dev/null +++ b/.changeset/hot-lobsters-yell.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Adds support for opening internal Techdocs links in a new tab with CTRL+Click or CMD+Click diff --git a/plugins/techdocs/src/reader/components/Reader.tsx b/plugins/techdocs/src/reader/components/Reader.tsx index a8b8067d96..eb8f4d39e9 100644 --- a/plugins/techdocs/src/reader/components/Reader.tsx +++ b/plugins/techdocs/src/reader/components/Reader.tsx @@ -358,21 +358,32 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { scrollIntoAnchor(), addLinkClickListener({ baseUrl: window.location.origin, - onClick: (_: MouseEvent, url: string) => { + onClick: (event: MouseEvent, url: string) => { + // detect if CTRL or META keys are pressed so that links can be opened in a new tab with `window.open` + const modifierActive = event.ctrlKey || event.metaKey; const parsedUrl = new URL(url); + // hash exists when anchor is clicked on secondary sidebar if (parsedUrl.hash) { - navigate(`${parsedUrl.pathname}${parsedUrl.hash}`); - // Scroll to hash if it's on the current page - transformedElement - ?.querySelector(`#${parsedUrl.hash.slice(1)}`) - ?.scrollIntoView(); + if (modifierActive) { + window.open(`${parsedUrl.pathname}${parsedUrl.hash}`, '_blank'); + } else { + navigate(`${parsedUrl.pathname}${parsedUrl.hash}`); + // Scroll to hash if it's on the current page + transformedElement + ?.querySelector(`#${parsedUrl.hash.slice(1)}`) + ?.scrollIntoView(); + } } else { - navigate(parsedUrl.pathname); - // Scroll to top of reader if primary sidebar link is clicked - transformedElement - ?.querySelector('.md-content__inner') - ?.scrollIntoView(); + if (modifierActive) { + window.open(parsedUrl.pathname, '_blank'); + } else { + navigate(parsedUrl.pathname); + // Scroll to top of reader if primary sidebar link is clicked + transformedElement + ?.querySelector('.md-content__inner') + ?.scrollIntoView(); + } } }, }),