瀏覽代碼

Add newer version of Storybooks. Create Button stories file

Tatiana Inama 6 年之前
父節點
當前提交
292937b02f

+ 11 - 0
recipes/.storybook/main.js

@@ -0,0 +1,11 @@
+module.exports = {
+  "stories": [
+    "../src/**/*.stories.mdx",
+    "../src/**/*.stories.@(js|jsx|ts|tsx)"
+  ],
+  "addons": [
+    "@storybook/addon-links",
+    "@storybook/addon-essentials",
+    "@storybook/preset-create-react-app"
+  ]
+}

+ 4 - 0
recipes/.storybook/preview.js

@@ -0,0 +1,4 @@
+import '!style-loader!css-loader!sass-loader!../src/styles/app.scss';
+export const parameters = {
+  actions: { argTypesRegex: "^on[A-Z].*" },
+}

File diff suppressed because it is too large
+ 6156 - 68
recipes/package-lock.json


+ 12 - 2
recipes/package.json

@@ -53,7 +53,9 @@
     "start": "react-scripts start",
     "build": "react-scripts build && cd build && tar czf ../frontend.tar.gz .",
     "test": "react-scripts test",
-    "eject": "react-scripts eject"
+    "eject": "react-scripts eject",
+    "storybook": "start-storybook -p 6006 -s public",
+    "build-storybook": "build-storybook -s public"
   },
   "eslintConfig": {
     "extends": "react-app"
@@ -66,7 +68,15 @@
   ],
   "devDependencies": {
     "@babel/core": "^7.5.4",
+    "@storybook/addon-actions": "^6.0.21",
+    "@storybook/addon-essentials": "^6.0.21",
+    "@storybook/addon-links": "^6.0.21",
+    "@storybook/node-logger": "^6.0.21",
+    "@storybook/preset-create-react-app": "^3.1.4",
+    "@storybook/react": "^6.0.21",
     "@types/react-redux": "^7.1.1",
-    "@types/webpack-env": "^1.15.2"
+    "@types/webpack-env": "^1.15.2",
+    "babel-loader": "^8.1.0",
+    "react-is": "^16.13.1"
   }
 }

+ 1 - 1
recipes/src/App.tsx

@@ -3,11 +3,11 @@ import React from 'react';
 import { Provider } from 'react-redux';
 import Toast from 'components/Toast';
 import configureStore from 'store/configureStore';
-import './styles/app.scss';
 import TopBar from 'components/TopAppBar';
 import Routes, { navbarRoutes } from 'route.config';
 import { Display } from "./types/ui";
 
+import './styles/app.scss';
 
 
 const store = configureStore();

+ 46 - 0
recipes/src/components/Button/Button.stories.tsx

@@ -0,0 +1,46 @@
+import React from 'react';
+// also exported from '@storybook/react' if you can deal with breaking changes in 6.1
+import { Story, Meta } from '@storybook/react/types-6-0';
+
+import Button, { CBKButtonProps as ButttonProps } from './index';
+
+export default {
+  title: 'Components/Button',
+  component: Button,
+  argTypes: {
+    backgroundColor: { control: 'color' },
+  },
+  decorators: [
+    story => <div>{story()}</div>
+  ]
+} as Meta;
+
+const Template: (label: string) => Story<ButttonProps> = label => (args) => <Button {...args}>{label}</Button>;
+
+export const Raised = Template('raised').bind({});
+Raised.args = {
+  raised: true,
+};
+
+export const Unelevated = Template('unelevated').bind({});
+Unelevated.args = {
+  unelevated: true,
+};
+
+export const Outlined = Template('outlined').bind({});
+Outlined.args = {
+  outlined: true,
+};
+
+export const Link = Template('link').bind({});
+Link.args = {
+  link: true,
+  active: false,
+};
+
+export const IconButton = Template('').bind({});
+IconButton.args = {
+  icon: 'favorite',
+  onClick: () => {},
+  small: true
+};

+ 1 - 1
recipes/src/components/Button/index.tsx

@@ -8,7 +8,7 @@ import '@rmwc/icon-button/styles';
 
 import './styles.scss';
 
-type CBKButtonProps = {
+export type CBKButtonProps = {
   children?: string|ReactElement,
   className?: string,
   unelevated?: boolean,

+ 20 - 0
recipes/src/stories/Header.stories.tsx

@@ -0,0 +1,20 @@
+import React from 'react';
+// also exported from '@storybook/react' if you can deal with breaking changes in 6.1
+import { Story, Meta } from '@storybook/react/types-6-0';
+
+import { Header, HeaderProps } from './Header';
+
+export default {
+  title: 'Example/Header',
+  component: Header,
+} as Meta;
+
+const Template: Story<HeaderProps> = (args) => <Header {...args} />;
+
+export const LoggedIn = Template.bind({});
+LoggedIn.args = {
+  user: {},
+};
+
+export const LoggedOut = Template.bind({});
+LoggedOut.args = {};

+ 36 - 0
recipes/src/stories/Header.tsx

@@ -0,0 +1,36 @@
+import React from 'react';
+
+import './header.css';
+
+export interface HeaderProps {
+  user?: {};
+  onLogin: () => void;
+  onLogout: () => void;
+  onCreateAccount: () => void;
+}
+
+export const Header: React.FC<HeaderProps> = ({ user, onLogin, onLogout, onCreateAccount }) => (
+  <header>
+    <div className="wrapper">
+      <div>
+        <svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
+          <g fill="none" fillRule="evenodd">
+            <path
+              d="M10 0h12a10 10 0 0110 10v12a10 10 0 01-10 10H10A10 10 0 010 22V10A10 10 0 0110 0z"
+              fill="#FFF"
+            />
+            <path
+              d="M5.3 10.6l10.4 6v11.1l-10.4-6v-11zm11.4-6.2l9.7 5.5-9.7 5.6V4.4z"
+              fill="#555AB9"
+            />
+            <path
+              d="M27.2 10.6v11.2l-10.5 6V16.5l10.5-6zM15.7 4.4v11L6 10l9.7-5.5z"
+              fill="#91BAF8"
+            />
+          </g>
+        </svg>
+        <h1>Acme</h1>
+      </div>
+    </div>
+  </header>
+);

+ 194 - 0
recipes/src/stories/Introduction.stories.mdx

@@ -0,0 +1,194 @@
+import { Meta } from '@storybook/addon-docs/blocks';
+import Code from './assets/code-brackets.svg';
+import Colors from './assets/colors.svg';
+import Comments from './assets/comments.svg';
+import Direction from './assets/direction.svg';
+import Flow from './assets/flow.svg';
+import Plugin from './assets/plugin.svg';
+import Repo from './assets/repo.svg';
+import StackAlt from './assets/stackalt.svg';
+
+<Meta title="Example/Introduction" />
+
+<style>{`
+  .subheading {
+    --mediumdark: '#999999';
+    font-weight: 900;
+    font-size: 13px;
+    color: #999;
+    letter-spacing: 6px;
+    line-height: 24px;
+    text-transform: uppercase;
+    margin-bottom: 12px;
+    margin-top: 40px;
+  }
+
+  .link-list {
+    display: grid;
+    grid-template-columns: 1fr;
+    grid-template-rows: 1fr 1fr;
+    row-gap: 10px;
+  }
+
+  @media (min-width: 620px) {
+    .link-list {
+      row-gap: 20px;
+      column-gap: 20px;
+      grid-template-columns: 1fr 1fr;
+    }
+  }
+
+  @media all and (-ms-high-contrast:none) {
+  .link-list {
+      display: -ms-grid;
+      -ms-grid-columns: 1fr 1fr;
+      -ms-grid-rows: 1fr 1fr;
+    }
+  }
+
+  .link-item {
+    display: block;
+    padding: 20px 30px 20px 15px;
+    border: 1px solid #00000010;
+    border-radius: 5px;
+    transition: background 150ms ease-out, border 150ms ease-out, transform 150ms ease-out;
+    color: #333333;
+    display: flex;
+    align-items: flex-start;
+  }
+
+  .link-item:hover {
+    border-color: #1EA7FD50;
+    transform: translate3d(0, -3px, 0);
+    box-shadow: rgba(0, 0, 0, 0.08) 0 3px 10px 0;
+  }
+
+  .link-item:active {
+    border-color: #1EA7FD;
+    transform: translate3d(0, 0, 0);
+  }
+
+  .link-item strong {
+    font-weight: 700;
+    display: block;
+    margin-bottom: 2px;
+  }
+  
+  .link-item img {
+    height: 40px;
+    width: 40px;
+    margin-right: 15px;
+    flex: none;
+  }
+
+  .link-item span {
+    font-size: 14px;
+    line-height: 20px;
+  }
+
+  .tip {
+    display: inline-block;
+    border-radius: 1em;
+    font-size: 11px;
+    line-height: 12px;
+    font-weight: 700;
+    background: #E7FDD8;
+    color: #66BF3C;
+    padding: 4px 12px;
+    margin-right: 10px;
+    vertical-align: top;
+  }
+
+  .tip-wrapper {
+    font-size: 13px;
+    line-height: 20px;
+    margin-top: 40px;
+    margin-bottom: 40px;
+  }
+
+  .tip-wrapper code {
+    font-size: 12px;
+    display: inline-block;
+  }
+
+  
+`}</style>
+
+# Welcome to Storybook
+
+Storybook helps you build UI components in isolation from your app's business logic, data, and context.
+That makes it easy to develop hard-to-reach states. Save these UI states as **stories** to revisit during development, testing, or QA.
+
+Browse example stories now by navigating to them in the sidebar.
+View their code in the `src/storybook-examples` directory to learn how they work.
+We recommend building UIs with a [**component-driven**](https://componentdriven.org) process starting with atomic components and ending with pages.
+
+<div class="subheading">Configure</div>
+
+<div class="link-list">
+  <a class="link-item" href="https://storybook.js.org/docs/react/api/presets" target="_blank">
+    <img src={Plugin} alt="plugin" />
+    <span>
+      <strong>Presets for popular tools</strong>
+      Easy setup for TypeScript, SCSS and more.
+    </span>
+  </a>
+  <a class="link-item" href="https://storybook.js.org/docs/react/configure/webpack" target="_blank">
+    <img src={StackAlt} alt="Build" />
+    <span>
+      <strong>Build configuration</strong>
+      How to customize webpack and Babel
+    </span>
+  </a>
+  <a class="link-item" href="https://storybook.js.org/docs/react/configure/styling-and-css" target="_blank">
+    <img src={Colors} alt="colors" />
+    <span>
+      <strong>Styling</strong>
+      How to load and configure CSS libraries
+    </span>
+  </a>
+  <a class="link-item" href="https://storybook.js.org/docs/react/get-started/setup#configure-storybook-for-your-stack" target="_blank">
+    <img src={Flow} alt="flow" />
+    <span>
+      <strong>Data</strong>
+      Providers and mocking for data libraries
+    </span>
+  </a>
+</div>
+
+<div class="subheading">Learn</div>
+
+<div class="link-list">
+  <a class="link-item" href="https://storybook.js.org/docs" target="_blank">
+    <img src={Repo} alt="repo" />
+    <span>
+      <strong>Storybook documentation</strong>
+      Configure, customize, and extend
+    </span>
+  </a>
+  <a class="link-item" href="https://www.learnstorybook.com" target="_blank">
+    <img src={Direction} alt="direction" />
+    <span>
+      <strong>In-depth guides</strong>
+      Best practices from leading teams
+    </span>
+  </a>
+  <a class="link-item" href="https://github.com/storybookjs/storybook" target="_blank">
+    <img src={Code} alt="code" />
+    <span>
+      <strong>GitHub project</strong>
+      View the source and add issues
+    </span>
+  </a>
+  <a class="link-item" href="https://discord.gg/UUt2PJb" target="_blank">
+    <img src={Comments} alt="comments" />
+    <span>
+      <strong>Discord chat</strong>
+      Chat with maintainers and the community
+    </span>
+  </a>
+</div>
+
+<div class="tip-wrapper">
+  <span class="tip">Tip</span>Edit the Markdown in <code>src/storybook-examples/welcome.mdx</code>
+</div>

+ 23 - 0
recipes/src/stories/Page.stories.tsx

@@ -0,0 +1,23 @@
+import React from 'react';
+// also exported from '@storybook/react' if you can deal with breaking changes in 6.1
+import { Story, Meta } from '@storybook/react/types-6-0';
+
+import { Page, PageProps } from './Page';
+import * as HeaderStories from './Header.stories';
+
+export default {
+  title: 'Example/Page',
+  component: Page,
+} as Meta;
+
+const Template: Story<PageProps> = (args) => <Page {...args} />;
+
+export const LoggedIn = Template.bind({});
+LoggedIn.args = {
+  ...HeaderStories.LoggedIn.args,
+};
+
+export const LoggedOut = Template.bind({});
+LoggedOut.args = {
+  ...HeaderStories.LoggedOut.args,
+};

+ 67 - 0
recipes/src/stories/Page.tsx

@@ -0,0 +1,67 @@
+import React from 'react';
+
+import { Header } from './Header';
+import './page.css';
+
+export interface PageProps {
+  user?: {};
+  onLogin: () => void;
+  onLogout: () => void;
+  onCreateAccount: () => void;
+}
+
+export const Page: React.FC<PageProps> = ({ user, onLogin, onLogout, onCreateAccount }) => (
+  <article>
+    <Header user={user} onLogin={onLogin} onLogout={onLogout} onCreateAccount={onCreateAccount} />
+
+    <section>
+      <h2>Pages in Storybook</h2>
+      <p>
+        We recommend building UIs with a{' '}
+        <a href="https://componentdriven.org" target="_blank" rel="noopener noreferrer">
+          <strong>component-driven</strong>
+        </a>{' '}
+        process starting with atomic components and ending with pages.
+      </p>
+      <p>
+        Render pages with mock data. This makes it easy to build and review page states without
+        needing to navigate to them in your app. Here are some handy patterns for managing page data
+        in Storybook:
+      </p>
+      <ul>
+        <li>
+          Use a higher-level connected component. Storybook helps you compose such data from the
+          "args" of child component stories
+        </li>
+        <li>
+          Assemble data in the page component from your services. You can mock these services out
+          using Storybook.
+        </li>
+      </ul>
+      <p>
+        Get a guided tutorial on component-driven development at{' '}
+        <a href="https://www.learnstorybook.com" target="_blank" rel="noopener noreferrer">
+          Learn Storybook
+        </a>
+        . Read more in the{' '}
+        <a href="https://storybook.js.org/docs" target="_blank" rel="noopener noreferrer">
+          docs
+        </a>
+        .
+      </p>
+      <div className="tip-wrapper">
+        <span className="tip">Tip</span> Adjust the width of the canvas with the{' '}
+        <svg width="10" height="10" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
+          <g fill="none" fillRule="evenodd">
+            <path
+              d="M1.5 5.2h4.8c.3 0 .5.2.5.4v5.1c-.1.2-.3.3-.4.3H1.4a.5.5 0 01-.5-.4V5.7c0-.3.2-.5.5-.5zm0-2.1h6.9c.3 0 .5.2.5.4v7a.5.5 0 01-1 0V4H1.5a.5.5 0 010-1zm0-2.1h9c.3 0 .5.2.5.4v9.1a.5.5 0 01-1 0V2H1.5a.5.5 0 010-1zm4.3 5.2H2V10h3.8V6.2z"
+              id="a"
+              fill="#999"
+            />
+          </g>
+        </svg>
+        Viewports addon in the toolbar
+      </div>
+    </section>
+  </article>
+);

File diff suppressed because it is too large
+ 1 - 0
recipes/src/stories/assets/code-brackets.svg


File diff suppressed because it is too large
+ 1 - 0
recipes/src/stories/assets/colors.svg


File diff suppressed because it is too large
+ 1 - 0
recipes/src/stories/assets/comments.svg


File diff suppressed because it is too large
+ 1 - 0
recipes/src/stories/assets/direction.svg


File diff suppressed because it is too large
+ 1 - 0
recipes/src/stories/assets/flow.svg


File diff suppressed because it is too large
+ 1 - 0
recipes/src/stories/assets/plugin.svg


File diff suppressed because it is too large
+ 1 - 0
recipes/src/stories/assets/repo.svg


File diff suppressed because it is too large
+ 1 - 0
recipes/src/stories/assets/stackalt.svg


+ 26 - 0
recipes/src/stories/header.css

@@ -0,0 +1,26 @@
+.wrapper {
+  font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+  padding: 15px 20px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+
+svg {
+  display: inline-block;
+  vertical-align: top;
+}
+
+h1 {
+  font-weight: 900;
+  font-size: 20px;
+  line-height: 1;
+  margin: 6px 0 6px 10px;
+  display: inline-block;
+  vertical-align: top;
+}
+
+button + button {
+  margin-left: 10px;
+}

+ 69 - 0
recipes/src/stories/page.css

@@ -0,0 +1,69 @@
+section {
+  font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+  font-size: 14px;
+  line-height: 24px;
+  padding: 48px 20px;
+  margin: 0 auto;
+  max-width: 600px;
+  color: #333;
+}
+
+h2 {
+  font-weight: 900;
+  font-size: 32px;
+  line-height: 1;
+  margin: 0 0 4px;
+  display: inline-block;
+  vertical-align: top;
+}
+
+p {
+  margin: 1em 0;
+}
+
+a {
+  text-decoration: none;
+  color: #1ea7fd;
+}
+
+ul {
+  padding-left: 30px;
+  margin: 1em 0;
+}
+
+li {
+  margin-bottom: 8px;
+}
+
+.tip {
+  display: inline-block;
+  border-radius: 1em;
+  font-size: 11px;
+  line-height: 12px;
+  font-weight: 700;
+  background: #e7fdd8;
+  color: #66bf3c;
+  padding: 4px 12px;
+  margin-right: 10px;
+  vertical-align: top;
+}
+
+.tip-wrapper {
+  font-size: 13px;
+  line-height: 20px;
+  margin-top: 40px;
+  margin-bottom: 40px;
+}
+
+.tip-wrapper svg {
+  display: inline-block;
+  height: 12px;
+  width: 12px;
+  margin-right: 4px;
+  vertical-align: top;
+  margin-top: 3px;
+}
+
+.tip-wrapper svg path {
+  fill: #1ea7fd;
+}