@etchteam/storybook-addon-marker
Version:
Add a Marker.io feedback button to the storybook UI
88 lines (82 loc) • 2.77 kB
JavaScript
import { addons, types, useGlobals, useChannel } from 'storybook/manager-api';
import markerSDK from '@marker.io/browser';
import { CommentIcon } from '@storybook/icons';
import React, { useState, useCallback, useEffect } from 'react';
import { IconButton } from 'storybook/internal/components';
import { styled } from 'storybook/theming';
// src/manager.js
// src/constants.js
var ADDON_ID = "marker";
var TOOL_ID = `${ADDON_ID}/tool`;
var EVENTS = {
LOADED: `${ADDON_ID}/loaded`,
CAPTURE: `${ADDON_ID}/capture`
};
// src/hideDefaultMarkerButton.js
var hideDefaultMarkerButton = () => {
const markerBtns = [
...document.querySelectorAll(".marker-app #feedback-button")
];
markerBtns.forEach((markerBtn) => markerBtn.style.display = "none");
};
// src/FeedbackButton.jsx
var IconButtonWithLabel = styled(IconButton)(() => ({
display: "inline-flex",
alignItems: "center"
}));
var IconButtonLabel = styled.div(({ theme }) => ({
display: "inline-block",
textDecoration: "none",
padding: "10px 5px",
fontWeight: theme.typography.weight.bold,
fontSize: theme.typography.size.s2 - 1,
lineHeight: "1",
height: 37,
border: "none",
borderTop: "3px solid transparent",
borderBottom: "3px solid transparent",
background: "transparent"
}));
function FeedbackButton() {
const [markerLoaded, setMarkerLoaded] = useState(false);
const [globals] = useGlobals();
const { project, mode, ...config } = globals.marker ?? {};
const emit = useChannel({
// The loaded event will fire when the marker decorator loads
[EVENTS.LOADED]: () => {
if (window.Marker) {
window.Marker.unload();
}
setMarkerLoaded(true);
},
[EVENTS.CAPTURE]: () => {
window.Marker?.capture(mode)?.then(() => {
hideDefaultMarkerButton();
});
}
});
const handleSendFeedback = useCallback(() => {
emit(EVENTS.CAPTURE);
}, [emit]);
useEffect(() => {
clearTimeout(window.markerTimer);
if (project && !markerLoaded && !window.Marker) {
window.markerTimer = setTimeout(() => {
markerSDK.loadWidget({ project, ...config }).then(() => {
hideDefaultMarkerButton();
setMarkerLoaded(true);
});
}, 3e3);
}
}, [project, markerLoaded]);
return markerLoaded ? /* @__PURE__ */ React.createElement(IconButtonWithLabel, { key: TOOL_ID, onClick: handleSendFeedback }, /* @__PURE__ */ React.createElement(CommentIcon, null), /* @__PURE__ */ React.createElement(IconButtonLabel, null, "Feedback")) : null;
}
// src/manager.js
addons.register(ADDON_ID, () => {
addons.add(TOOL_ID, {
type: types.TOOL,
title: "Marker",
match: ({ viewMode }) => !!(viewMode && viewMode.match(/^(story|docs)$/)),
render: FeedbackButton
});
});