diff --git a/src/index.ts b/src/index.ts
index 278fb3ff..4016ea9e 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -8,6 +8,7 @@ import type { Options } from "@storybook/types";
import { type Configuration, getConfiguration, getGitInfo, type GitInfo } from "chromatic/node";
import {
+ ADDON_ID,
CHROMATIC_BASE_URL,
CONFIG_INFO,
GIT_INFO,
@@ -212,6 +213,8 @@ async function serverChannel(channel: Channel, options: Options & { configFile?:
configInfoState.value = await getConfigInfo(configuration, options);
});
+ setInterval(() => channel.emit(`${ADDON_ID}/heartbeat`), 1000);
+
return channel;
}
diff --git a/src/manager.tsx b/src/manager.tsx
index d5f4c3d1..4a330653 100644
--- a/src/manager.tsx
+++ b/src/manager.tsx
@@ -1,4 +1,6 @@
-import { addons, types } from "@storybook/manager-api";
+import { addons, type API } from "@storybook/manager-api";
+import { color } from "@storybook/theming";
+import { Addon_TypesEnum } from "@storybook/types";
import React from "react";
import { ADDON_ID, PANEL_ID, SIDEBAR_BOTTOM_ID, SIDEBAR_TOP_ID } from "./constants";
@@ -6,21 +8,48 @@ import { Panel } from "./Panel";
import { SidebarBottom } from "./SidebarBottom";
import { SidebarTop } from "./SidebarTop";
+let heartbeatTimeout: NodeJS.Timeout;
+const expectHeartbeat = (api: API) => {
+ heartbeatTimeout = setTimeout(() => expectHeartbeat(api), 30000);
+};
+
addons.register(ADDON_ID, (api) => {
addons.add(PANEL_ID, {
- type: types.PANEL,
+ type: Addon_TypesEnum.PANEL,
title: "Visual Tests",
match: ({ viewMode }) => viewMode === "story",
render: ({ active }) => ,
});
addons.add(SIDEBAR_TOP_ID, {
- type: types.experimental_SIDEBAR_TOP,
+ type: Addon_TypesEnum.experimental_SIDEBAR_TOP,
render: () => ,
});
addons.add(SIDEBAR_BOTTOM_ID, {
- type: types.experimental_SIDEBAR_BOTTOM,
+ type: Addon_TypesEnum.experimental_SIDEBAR_BOTTOM,
render: () => ,
});
+
+ const channel = api.getChannel();
+ if (!channel) return;
+
+ channel.on(`${ADDON_ID}/heartbeat`, () => {
+ clearTimeout(heartbeatTimeout);
+ heartbeatTimeout = setTimeout(() => {
+ api.addNotification({
+ id: `${ADDON_ID}/connection-lost`,
+ content: {
+ headline: "Connection lost",
+ subHeadline: "Lost connection to the Storybook server. Try refreshing the page.",
+ },
+ icon: {
+ name: "failed",
+ color: color.negative,
+ },
+ // @ts-expect-error SB needs a proper API for no link
+ link: undefined,
+ });
+ }, 3000);
+ });
});