Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Commit

Permalink
add guided tour example
Browse files Browse the repository at this point in the history
  • Loading branch information
yannbf committed May 25, 2023
1 parent 50f6507 commit 5d4ec86
Show file tree
Hide file tree
Showing 7 changed files with 302 additions and 18 deletions.
5 changes: 5 additions & 0 deletions .storybook/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import type { Preview } from "@storybook/react";

const preview: Preview = {
parameters: {
options: {
storySort: {
order: ["Example", ["Introduction"]],
},
},
backgrounds: {
default: "light",
},
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,8 @@
"url": "https://github.com/storybookjs/addon-onboarding/issues"
},
"readme": "ERROR: No README data found!",
"homepage": "https://github.com/storybookjs/addon-onboarding#readme"
"homepage": "https://github.com/storybookjs/addon-onboarding#readme",
"dependencies": {
"react-joyride": "^2.5.4"
}
}
201 changes: 201 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
import React, { useEffect, useState } from "react";
import Joyride, { Step } from "react-joyride";
import {
STORY_CHANGED,
STORY_ARGS_UPDATED,
SELECT_STORY,
} from "@storybook/core-events";

const TitleBody = ({
prefix,
title,
body,
}: {
prefix?: React.ReactNode;
title: React.ReactNode;
body: React.ReactNode;
}) => {
return (
<div>
{prefix}
<strong style={{ fontSize: 14 }}>{title}</strong>
<p style={{ fontSize: 14, color: "#798186", margin: 0, marginTop: 10 }}>{body}</p>
</div>
);
};

let INTERACTIONS_COUNT = 0;
export const App = () => {
const [shouldRun, setShouldRun] = useState<boolean>(true);
const [channel, setChannel] = useState<any>();
const [stepIndex, setStepIndex] = useState<number>();

useEffect(() => {
// TODO: Only get the channel once Storybook is available
setTimeout(() => {
// @ts-ignore
const channelInstance = window?.__STORYBOOK_ADDONS_MANAGER?.getChannel();

setChannel(channelInstance);
channelInstance.emit(SELECT_STORY, {
storyId: "example-button--primary",
});

// @ts-ignore
document.querySelector("#tabbutton-addon-controls")?.click();
}, 2000);
}, []);

useEffect(() => {
if (channel) {
channel.on(STORY_CHANGED, (storyId: string) => {
if(storyId === 'introduction-configure-your-project--docs') {
setShouldRun(false);
}
});

channel.on(STORY_ARGS_UPDATED, () => {
console.log("STORY_ARGS_UPDATED", { INTERACTIONS_COUNT });
INTERACTIONS_COUNT = INTERACTIONS_COUNT + 1;
if (INTERACTIONS_COUNT === 2) {
setStepIndex(4);
}
});
}
}, [channel]);

// Challenges
// Do we need to remove autodocs from button component?
// What if the addon panel is not open/visible?
// What if the addon panel is in a bad placement?
// HMR when testing the onboarding component
// Setting up Storybook to the right state as it can be in different stories, addons, etc.
// Defining proper selectors to the Storybook components (task in the monorepo)
// Deal with Storybook channel updates
// Detect new story (apparently there is no event for that!)

const steps: Step[] = [
{
content: (
<div style={{ width: '80%' }}>
<h2>Welcome to Storybook</h2>
<p>
Storybook helps you develop UI components. Let's learn the basics in
a few simple steps. It shouldn't take more than 3 minutes. Enjoy!
</p>
</div>
),
locale: { skip: <span aria-label="skip">Skip onboarding</span> },
placement: "center",
target: "body",
styles: {
tooltip: {
maxWidth: '100%',
width: 500,
height: 300
},

}
},
{
target: ".sto-1qwztpk",
content: (
<TitleBody
title="Your stories"
body="A story is a key state of your UI component. This Button component
has four stories."
/>
),
placement: "right",
},
{
target: "#storybook-preview-iframe",
content: (
<TitleBody
title="Interactive story preview"
body="Preview your stories here. Each time you modify a story, the changes will live update here."
/>
),
placement: "bottom",
},
{
target: "#control-primary",
content: (
<TitleBody
title="Interactive story update"
body="Update your story without having to change the code. Modify this boolean input a couple times to see how it changes the story."
/>
),
placement: "right",
spotlightPadding: 5,
spotlightClicks: true,
disableOverlay: true,
styles: {
buttonNext: {
display: "none",
},
spotlight: {
borderRadius: 200,
},
},
},
{
target: "#control-primary",
content: (
<TitleBody
prefix={<div style={{ fontSize: "50px" }}>🙌</div>}
title="Great progress!"
body="Now that you know how to control your stories interactively, let's dive deeper into how to create a story."
/>
),
placement: "right",
disableOverlay: true,
},
{
target: "#introduction-configure-your-project--docs",
content: (
<TitleBody title="Configure the rest of your project"
body="Click on your story to see the result." />
),
placement: "right",
disableOverlay: true,
styles: {
buttonNext: {
display: "none",
},
}
},
];

return (
<Joyride
steps={steps}
continuous
run={shouldRun}
stepIndex={stepIndex}
spotlightPadding={0}
hideBackButton
callback={(data) => console.log(data)}
styles={{
spotlight: {
border: "solid 2px #004c7c",
},
tooltip: {
maxWidth: 260
},
buttonNext: {
backgroundColor: "#029CFD",
width: "100%",
padding: "12px 9px",
margin: 0,
},
tooltipContent: {
paddingBottom: 0
},
options: {
zIndex: 10000,
},
}}
/>
);
};
19 changes: 10 additions & 9 deletions src/manager.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import ReactDOM from "react-dom";
import React from "react";
import { App } from "./App";

// Add a new DOM element to document.body, where we will bootstrap our React app
const domNode = document.createElement("div");

domNode.id = "addon-onboarding";
domNode.style.position = "absolute";
domNode.style.top = "0";
domNode.style.left = "0";
domNode.style.width = "0";
domNode.style.height = "0";
domNode.style.overflow = "hidden";
domNode.style.opacity = "0";
domNode.style.visibility = "hidden";
// domNode.style.position = "absolute";
// domNode.style.top = "0";
// domNode.style.left = "0";
// domNode.style.width = "0";
// domNode.style.height = "0";
// domNode.style.overflow = "hidden";
// domNode.style.opacity = "0";
// domNode.style.visibility = "hidden";

// Append the new DOM element to document.body
document.body.appendChild(domNode);

// Render the React app
ReactDOM.render(<div>Hello World</div>, domNode);
ReactDOM.render(<App />, domNode);
7 changes: 0 additions & 7 deletions src/stories/Button.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,6 @@ const meta: Meta<typeof Button> = {
backgroundColor: { control: "color" },
},
tags: ["autodocs"],
parameters: {
myAddonParameter: `
<MyComponent boolProp scalarProp={1} complexProp={{ foo: 1, bar: '2' }}>
<SomeOtherComponent funcProp={(a) => a.id} />
</MyComponent>
`,
},
};

export default meta;
Expand Down
2 changes: 1 addition & 1 deletion src/stories/Introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Plugin from './assets/plugin.svg';
import Repo from './assets/repo.svg';
import StackAlt from './assets/stackalt.svg';

<Meta title="Example/Introduction" />
<Meta title="Introduction/Configure Your Project" />

<style>
{`
Expand Down
Loading

0 comments on commit 5d4ec86

Please sign in to comment.