UNPKG

@etchteam/storybook-addon-marker

Version:

Add a Marker.io feedback button to the storybook UI

88 lines (82 loc) 2.77 kB
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 }); });