Skip to content

Commit

Permalink
Experience 8346: Add configuration for local instance of Storybook
Browse files Browse the repository at this point in the history
This changeset adds the initial configuration needed to spin up Storybook locally.  It's incredibly simple right now, but it should include most addons that we need.  Also included are very simple CSF examples for the StaticAlert and USLink components as a proof-of-concept.

There's a known error with React 18 [here](storybookjs/storybook#17831 (comment)), but it shouldn't affect us for the time being.  We could also install the bleeding-edge version of Storybook, but it looks like there are other issues with that as well -- so I recommend just sticking with the latest stable version until the next version is officially out.
  • Loading branch information
Stephen Kao committed Apr 3, 2023
1 parent 161feca commit 93b95b4
Show file tree
Hide file tree
Showing 7 changed files with 6,730 additions and 253 deletions.
1 change: 1 addition & 0 deletions frontend-react/.eslintrc.js
Expand Up @@ -4,6 +4,7 @@ module.exports = {
"plugin:import/recommended",
"plugin:import/typescript",
"prettier",
"plugin:storybook/recommended",
],
plugins: ["testing-library", "unused-imports", "jest-dom", "prettier"],
env: {
Expand Down
22 changes: 22 additions & 0 deletions frontend-react/.storybook/main.js
@@ -0,0 +1,22 @@
module.exports = {
stories: [
"../src/**/*.stories.mdx",
"../src/**/*.stories.@(js|jsx|ts|tsx)",
],
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions",
"@storybook/addon-a11y",
],
framework: "@storybook/react",
core: {
builder: "@storybook/builder-webpack5",
},
refs: {
trussworks: {
title: "Trussworks Storybook",
url: "https://trussworks.github.io/react-uswds/",
},
},
};
59 changes: 59 additions & 0 deletions frontend-react/.storybook/preview.js
@@ -0,0 +1,59 @@
import { initializeWorker, mswDecorator } from "msw-storybook-addon";
import { CacheProvider } from "rest-hooks";
import { BrowserRouter } from "react-router-dom";
import { HelmetProvider } from "react-helmet-async";
import MockDate from "mockdate";

import "../src/content/generated/global.out.css";

// mock all dates in stories to make sure we don't run into date-related inconsistencies
MockDate.set("2023-01-01");

export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
options: {
storySort: {
method: "alphabetical",
order: [],
},
},
};

initializeWorker();

function withRestHooksCacheProvider(Story) {
return (
<CacheProvider>
<Story />
</CacheProvider>
);
}

function withRouter(Story) {
return (
<BrowserRouter>
<Story />
</BrowserRouter>
);
}

function withHelmet(Story) {
return (
<HelmetProvider>
<Story />
</HelmetProvider>
);
}

export const decorators = [
withHelmet,
withRouter,
withRestHooksCacheProvider,
mswDecorator,
];
22 changes: 21 additions & 1 deletion frontend-react/package.json
Expand Up @@ -79,7 +79,9 @@
"lint:eslint": "cross-env NODE_ENV=production eslint \"src/**/*.{js,ts,jsx,tsx}\"",
"lint:eslint:write": "cross-env NODE_ENV=production eslint --fix \"src/**/*.{js,ts,jsx,tsx}\"",
"yarn:show-outdated-packages": "yarn outdated",
"run-build-dir": "yarn build:localdev:csp && yarn global add serve && serve -s build"
"run-build-dir": "yarn build:localdev:csp && yarn global add serve && serve -s build",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
},
"browserslist": {
"production": [
Expand All @@ -102,6 +104,20 @@
"@jest/globals": "^29.5.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
"@rest-hooks/test": "^7.3.1",
"@storybook/addon-a11y": "^6.5.16",
"@storybook/addon-actions": "^6.5.16",
"@storybook/addon-essentials": "^6.5.16",
"@storybook/addon-interactions": "^6.5.16",
"@storybook/addon-links": "^6.5.16",
"@storybook/addons": "^6.5.16",
"@storybook/api": "^6.5.16",
"@storybook/builder-webpack5": "^6.5.16",
"@storybook/components": "^6.5.16",
"@storybook/core-events": "^6.5.16",
"@storybook/manager-webpack5": "^6.5.16",
"@storybook/react": "^6.5.16",
"@storybook/testing-library": "^0.0.13",
"@storybook/theming": "^6.5.16",
"@svgr/webpack": "^6.5.1",
"@testing-library/cypress": "^9.0.0",
"@testing-library/dom": "^9.0.0",
Expand Down Expand Up @@ -147,6 +163,7 @@
"eslint-plugin-cypress": "^2.12.1",
"eslint-plugin-jest-dom": "^4.0.3",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-storybook": "^0.6.11",
"eslint-plugin-testing-library": "^5.10.2",
"eslint-plugin-unused-imports": "2.0.0",
"eslint-webpack-plugin": "^4.0.0",
Expand All @@ -160,7 +177,9 @@
"jest-watch-typeahead": "^2.2.2",
"loader-utils": "3.2.1",
"mini-css-extract-plugin": "^2.7.5",
"mockdate": "^3.0.5",
"msw": "^1.1.0",
"msw-storybook-addon": "^1.8.0",
"npm-run-all": "^4.1.5",
"otplib": "^12.0.1",
"postcss": "^8.4.21",
Expand All @@ -181,6 +200,7 @@
"sass-loader": "^13.2.1",
"semver": "^7.3.8",
"source-map-loader": "^4.0.1",
"storybook-addon-react-router-v6": "^0.3.1",
"style-loader": "^3.3.1",
"tailwindcss": "^3.2.7",
"terser-webpack-plugin": "^5.3.6",
Expand Down
27 changes: 27 additions & 0 deletions frontend-react/src/components/StaticAlert.stories.tsx
@@ -0,0 +1,27 @@
import React from "react";
import { ComponentMeta, ComponentStory } from "@storybook/react";

import { StaticAlert, StaticAlertType } from "./StaticAlert";

export default {
title: "components/StaticAlert",
component: StaticAlert,
argTypes: {
type: {
control: {
type: "radio",
options: Object.values(StaticAlertType),
},
},
},
} as ComponentMeta<typeof StaticAlert>;

export const Default: ComponentStory<typeof StaticAlert> = (args) => (
<StaticAlert {...args} />
);
Default.args = {
type: StaticAlertType.Success,
heading: "StaticAlert Heading",
message: "This is the message of the StaticAlert",
children: "Children are optional! (Try clearing me out)",
};
50 changes: 50 additions & 0 deletions frontend-react/src/components/USLink.stories.tsx
@@ -0,0 +1,50 @@
import React from "react";
import { ComponentMeta, ComponentStory } from "@storybook/react";

import { USExtLink, USLink, USLinkButton } from "./USLink";

export default {
title: "components/USLink",
component: USLink,
} as ComponentMeta<typeof USLink>;

export const Default: ComponentStory<typeof USLink> = (args) => (
<USLink {...args} />
);
Default.args = {
className: "",
children: "This is a link",
};

export const Button: ComponentStory<typeof USLinkButton> = (args) => (
<USLinkButton {...args} />
);
Button.args = {
children: "This is a link styled as a button",
secondary: false,
base: false,
inverse: false,
unstyled: false,
};
Button.argTypes = {
accentStyle: {
control: {
type: "radio",
options: ["", "cool", "warm"],
},
},
size: {
control: {
type: "radio",
options: ["", "big"],
},
},
};

export const ExtLink: ComponentStory<typeof USExtLink> = (args) => (
<USExtLink {...args} />
);
ExtLink.args = {
className: "",
children: "This is an external link",
};

0 comments on commit 93b95b4

Please sign in to comment.