From a7dd5e3b186f31d4beb7e4abbb160fc59dde462f Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Wed, 31 May 2023 13:09:15 +0200 Subject: [PATCH] introduce feature components --- README.md | 3 +- src/App.tsx | 153 +++++----------- src/components/Button/Button.tsx | 22 +++ src/components/GuidedTour/GuidedTour.tsx | 140 --------------- src/components/Modal/Modal.styled.tsx | 2 +- src/features/GuidedTour/GuidedTour.tsx | 166 ++++++++++++++++++ .../WelcomeModal/WelcomeModal.stories.tsx | 19 ++ src/features/WelcomeModal/WelcomeModal.tsx | 98 +++++++++++ .../WriteStoriesModal.stories.tsx | 19 ++ .../WriteStoriesModal/WriteStoriesModal.tsx | 29 +++ 10 files changed, 403 insertions(+), 248 deletions(-) create mode 100644 src/components/Button/Button.tsx delete mode 100644 src/components/GuidedTour/GuidedTour.tsx create mode 100644 src/features/GuidedTour/GuidedTour.tsx create mode 100644 src/features/WelcomeModal/WelcomeModal.stories.tsx create mode 100644 src/features/WelcomeModal/WelcomeModal.tsx create mode 100644 src/features/WriteStoriesModal/WriteStoriesModal.stories.tsx create mode 100644 src/features/WriteStoriesModal/WriteStoriesModal.tsx diff --git a/README.md b/README.md index d4ac3cb..97c578d 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,9 @@ Storybook Addon Onboarding - Introduces a new onboarding experience ### Development scripts -- `yarn start` runs babel in watch mode and starts Storybook +- `yarn start` runs tsup in watch mode and starts Storybook - `yarn build` build and package your addon code +- `yarn storybook:watch` runs nodemon in watch mode so it reruns Storybook on changes. This is useful when testing the actual addon (as we cannot have HMR for addon changes) rather than just stories in Storybook ## Release Management diff --git a/src/App.tsx b/src/App.tsx index 14b5238..d46ffc2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,89 +1,22 @@ -import { - ThemeProvider, - ensure, - themes, - styled, - keyframes, -} from "@storybook/theming"; -import { Button } from "@storybook/components"; +import { ThemeProvider, ensure, themes } from "@storybook/theming"; import { type API } from "@storybook/manager-api"; const theme = ensure(themes.light); -import React, { useEffect, useState } from "react"; +import React, { useCallback, useEffect, useState } from "react"; import { STORY_CHANGED, CURRENT_STORY_WAS_SET } from "@storybook/core-events"; -import { GuidedTour } from "./components/GuidedTour/GuidedTour"; -import { Modal } from "./components/Modal/Modal"; -import { StorybookLogo } from "./components/Icons/StorybookLogo"; - -const rainbowAnimation = keyframes` - 0% { - background-position: 0% 50%; - } - 50% { - background-position: 100% 50%; - } - 100% { - background-position: 0% 50%; - } -`; - -// Styled component for the card -const ModalContentWrapper = styled.div` - background: radial-gradient( - circle at left, - #ffccd2, - #ffdbcb, - #ffe9c5, - #fff8c0, - #f2ffd8, - #d2f8e5, - #b3f0f1, - #a1e6f0, - #9fd8df - ) - left, - radial-gradient( - circle at right, - #ffccd2, - #ffdbcb, - #ffe9c5, - #fff8c0, - #f2ffd8, - #d2f8e5, - #b3f0f1, - #a1e6f0, - #9fd8df - ) - right, - linear-gradient( - 45deg, - #ffccd2, - #ffdbcb, - #ffe9c5, - #fff8c0, - #f2ffd8, - #d2f8e5, - #b3f0f1, - #a1e6f0, - #9fd8df - ); - background-size: 300% 300%; - background-repeat: no-repeat; - animation: ${rainbowAnimation} 10s linear infinite; - border-radius: 5px; - display: flex; - flex-direction: column; - align-items: center; - padding-top: 100px; - padding-bottom: 20px; -`; +import { GuidedTour } from "./features/GuidedTour/GuidedTour"; +import { WelcomeModal } from "./features/WelcomeModal/WelcomeModal"; +import { WriteStoriesModal } from "./features/WriteStoriesModal/WriteStoriesModal"; export const App = ({ api }: { api: API }) => { - const [enabled, setEnabled] = useState(true); - const [showGuidedTour, setShowGuidedTour] = useState(false); + const [enabled, setEnabled] = useState(true); + const [showGuidedTour, setShowGuidedTour] = useState(false); + const [showWriteStoriesModal, setShowWriteStoriesModal] = useState(false); + const [showWelcomeModal, setShowWelcomeModal] = useState(true); + const [isFinalStep, setIsFinalStep] = useState(false); - const skipTour = () => { + const skipTour = useCallback(() => { // remove onboarding query parameter from current url const url = new URL(window.location.href); url.searchParams.delete("onboarding"); @@ -91,7 +24,7 @@ export const App = ({ api }: { api: API }) => { url.search = `?path=${path}`; history.replaceState({}, "", url.href); setEnabled(false); - }; + }, [setEnabled]); useEffect(() => { api.once(CURRENT_STORY_WAS_SET, ({ storyId }) => { @@ -110,11 +43,17 @@ export const App = ({ api }: { api: API }) => { }, []); useEffect(() => { - api.on(STORY_CHANGED, (storyId: string) => { + const onStoryChanged = (storyId: string) => { if (storyId === "introduction-configure-your-project--docs") { setEnabled(false); } - }); + }; + + api.on(STORY_CHANGED, onStoryChanged); + + return () => { + api.off(STORY_CHANGED, onStoryChanged); + }; }, []); if (!enabled) { @@ -123,32 +62,34 @@ export const App = ({ api }: { api: API }) => { return ( - {!showGuidedTour && ( - - {({ Title, Description, Close }) => ( - - - Welcome to Storybook - - Storybook helps you develop UI components. -
- Learn the basics in a few simple steps. -
- - - Skip tour - -
- )} -
+ {showGuidedTour && ( + { + setShowWriteStoriesModal(true); + setShowGuidedTour(false); + }} + /> + )} + {showWelcomeModal && ( + { + setShowWelcomeModal(false); + setShowGuidedTour(true); + }} + onSkip={skipTour} + /> + )} + {showWriteStoriesModal && ( + { + setShowWriteStoriesModal(false); + setIsFinalStep(true); + setShowGuidedTour(true); + }} + /> )} - {showGuidedTour && }
); }; diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx new file mode 100644 index 0000000..263d01d --- /dev/null +++ b/src/components/Button/Button.tsx @@ -0,0 +1,22 @@ +import React from "react"; + +export const buttonStyles: React.ComponentProps<"button">["style"] = { + border: 0, + cursor: "pointer", + fontSize: 13, + lineHeight: 1, + padding: "9px 12px", + backgroundColor: "#029CFD", + borderRadius: 4, + color: "#fff", + fontWeight: 700, +}; + +export function Button(props: React.ComponentProps<"button">) { + const style = { + ...buttonStyles, + ...(props.style || {}), + }; + + return + + Skip tour + + + )} + + ); +}; diff --git a/src/features/WriteStoriesModal/WriteStoriesModal.stories.tsx b/src/features/WriteStoriesModal/WriteStoriesModal.stories.tsx new file mode 100644 index 0000000..90af238 --- /dev/null +++ b/src/features/WriteStoriesModal/WriteStoriesModal.stories.tsx @@ -0,0 +1,19 @@ +import React from "react"; +import { Meta, StoryObj } from "@storybook/react"; + +import { WriteStoriesModal } from "./WriteStoriesModal"; + +const meta: Meta = { + component: WriteStoriesModal, + decorators: [ + (storyFn) => ( +
{storyFn()}
+ ), + ], +}; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = {}; diff --git a/src/features/WriteStoriesModal/WriteStoriesModal.tsx b/src/features/WriteStoriesModal/WriteStoriesModal.tsx new file mode 100644 index 0000000..c940947 --- /dev/null +++ b/src/features/WriteStoriesModal/WriteStoriesModal.tsx @@ -0,0 +1,29 @@ +import React from "react"; +import { Button } from "../../components/Button/Button"; + +import { Modal } from "../../components/Modal/Modal"; +import { StorybookLogo } from "../../components/Icons/StorybookLogo"; +import { ModalContentWrapper } from "../WelcomeModal/WelcomeModal"; + +export function WriteStoriesModal({ onFinish }: { onFinish: () => void }) { + return ( + + {({ Title, Description }) => ( + + + + Create your first story (WORK IN PROGRESS) + + + Now it's your turn.
+ See how easy it is to create your first story by following these + steps below. +
+ +
+ )} +
+ ); +}