diff --git a/addons/notes/package.json b/addons/notes/package.json
index ab4c08978991..36280152197c 100644
--- a/addons/notes/package.json
+++ b/addons/notes/package.json
@@ -28,6 +28,7 @@
"@storybook/client-logger": "5.1.0-alpha.34",
"@storybook/components": "5.1.0-alpha.34",
"@storybook/core-events": "5.1.0-alpha.34",
+ "@storybook/router": "5.1.0-alpha.34",
"@storybook/theming": "5.1.0-alpha.34",
"core-js": "^2.6.5",
"global": "^4.3.2",
diff --git a/addons/notes/src/Panel.test.js b/addons/notes/src/Panel.test.js
index 3a6cadb2c70c..13ef69d336c9 100644
--- a/addons/notes/src/Panel.test.js
+++ b/addons/notes/src/Panel.test.js
@@ -1,7 +1,8 @@
import React from 'react';
-import { shallow } from 'enzyme';
+import { shallow, mount } from 'enzyme';
+import { Link } from '@reach/router';
import { SyntaxHighlighter as SyntaxHighlighterBase } from '@storybook/components';
-import { SyntaxHighlighter } from './Panel';
+import { SyntaxHighlighter, NotesLink } from './Panel';
describe('NotesPanel', () => {
describe('SyntaxHighlighter component', () => {
@@ -20,4 +21,25 @@ describe('NotesPanel', () => {
expect(syntaxHighlighterBase.prop('language')).toBe('jsx');
});
});
+
+ describe('NotesLink component', () => {
+ it('should render storybook links with @storybook/router Link', () => {
+ const component = mount(
+
+ Storybook Link
+
+ );
+ expect(component.find(Link).prop('to')).toBe('/?path=/story/addon-notes');
+ expect(component.find(Link).prop('title')).toBe('title');
+ });
+ it('should render absolute links as ', () => {
+ const component = mount(
+
+ Storybook Link
+
+ );
+ expect(component.find('a').prop('href')).toBe('https://example.com');
+ expect(component.find('a').prop('title')).toBe('title');
+ });
+ });
});
diff --git a/addons/notes/src/Panel.tsx b/addons/notes/src/Panel.tsx
index d48f1d4a8394..401e457c03aa 100644
--- a/addons/notes/src/Panel.tsx
+++ b/addons/notes/src/Panel.tsx
@@ -1,6 +1,7 @@
import React, { ReactElement, Fragment, ReactNode } from 'react';
import { types } from '@storybook/addons';
import { API, Consumer, Combo } from '@storybook/api';
+import { Link as RouterLink } from '@storybook/router';
import { styled } from '@storybook/theming';
import {
@@ -66,11 +67,34 @@ export const SyntaxHighlighter = ({ className, children, ...props }: SyntaxHighl
);
};
+interface NotesLinkProps {
+ href: string;
+ children: ReactElement;
+}
+export const NotesLink = ({ href, children, ...props }: NotesLinkProps) => {
+ /* https://github.com/sindresorhus/is-absolute-url/blob/master/index.js */
+ const isAbsoluteUrl = /^[a-z][a-z0-9+.-]*:/.test(href);
+ if (isAbsoluteUrl) {
+ return (
+
+ {children}
+
+ );
+ }
+
+ return (
+
+ {children}
+
+ );
+};
+
// use our SyntaxHighlighter component in place of a element when
// converting markdown to react elements
const defaultOptions = {
overrides: {
code: SyntaxHighlighter,
+ a: NotesLink,
Giphy: {
component: Giphy,
},
diff --git a/examples/svelte-kitchen-sink/src/stories/addon-notes.stories.js b/examples/svelte-kitchen-sink/src/stories/addon-notes.stories.js
index 43228243f0d8..ec8dcb3da0f8 100644
--- a/examples/svelte-kitchen-sink/src/stories/addon-notes.stories.js
+++ b/examples/svelte-kitchen-sink/src/stories/addon-notes.stories.js
@@ -8,7 +8,7 @@ storiesOf('Addon|Notes', module)
() => ({
Component: ButtonView,
}),
- { notes: 'My notes on the ButtonView component' }
+ { notes: 'My notes on the [ButtonView](/story/addon-notes--simple-note) component' }
)
.add(
'Note with HTML',