Skip to content

Commit de98fac

Browse files
funbunchDevinCLane
authored andcommitted
chore: add storybook
1 parent 1345d9a commit de98fac

9 files changed

Lines changed: 1261 additions & 24 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ coverage
1010
cypress/screenshots
1111
cypress/videos
1212
cypress/downloads/downloads.htm
13+
14+
*storybook.log
15+
storybook-static

client/.storybook/main.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { join, dirname } from "path";
2+
3+
/**
4+
* This function is used to resolve the absolute path of a package.
5+
* It is needed in projects that use Yarn PnP or are set up within a monorepo.
6+
*/
7+
function getAbsolutePath(value) {
8+
return dirname(require.resolve(join(value, "package.json")));
9+
}
10+
11+
/** @type { import('@storybook/react-vite').StorybookConfig } */
12+
const config = {
13+
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
14+
addons: [],
15+
framework: {
16+
name: getAbsolutePath("@storybook/react-vite"),
17+
options: {},
18+
},
19+
};
20+
export default config;

client/.storybook/preview.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/** @type { import('@storybook/react-vite').Preview } */
2+
const preview = {
3+
parameters: {
4+
controls: {
5+
matchers: {
6+
color: /(background|color)$/i,
7+
date: /Date$/i,
8+
},
9+
},
10+
},
11+
};
12+
13+
export default preview;

client/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"scripts": {
88
"start": "vite",
99
"dev": "vite",
10-
"build": "vite build"
10+
"build": "vite build",
11+
"storybook": "storybook dev -p 6006"
1112
},
1213
"dependencies": {
1314
"date-fns": "^2.29.3",
@@ -18,11 +19,14 @@
1819
"react-router-dom": "^6.13.0"
1920
},
2021
"devDependencies": {
22+
"@storybook/react-vite": "^9.0.12",
2123
"@vitejs/plugin-react": "^4.4.1",
2224
"autoprefixer": "^10.4.13",
2325
"axios": "^1.1.3",
2426
"http-proxy-middleware": "^2.0.6",
2527
"postcss": "^8.4.18",
28+
"prop-types": "^15.8.1",
29+
"storybook": "^9.0.12",
2630
"tailwindcss": "^3.2.2",
2731
"vite": "^6.3.5",
2832
"vite-plugin-istanbul": "^7.0.0"

client/src/stories/Button.jsx

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import React from "react";
2+
3+
import PropTypes from "prop-types";
4+
5+
import "./button.css";
6+
7+
/** Primary UI component for user interaction */
8+
export const Button = ({
9+
primary = false,
10+
backgroundColor = null,
11+
size = "medium",
12+
label,
13+
...props
14+
}) => {
15+
const mode = primary
16+
? "storybook-button--primary"
17+
: "storybook-button--secondary";
18+
return (
19+
<button
20+
type="button"
21+
className={["storybook-button", `storybook-button--${size}`, mode].join(
22+
" "
23+
)}
24+
style={backgroundColor && { backgroundColor }}
25+
{...props}
26+
>
27+
{label}
28+
</button>
29+
);
30+
};
31+
32+
Button.propTypes = {
33+
/** Is this the principal call to action on the page? */
34+
primary: PropTypes.bool,
35+
/** What background color to use */
36+
backgroundColor: PropTypes.string,
37+
/** How large should the button be? */
38+
size: PropTypes.oneOf(["small", "medium", "large"]),
39+
/** Button contents */
40+
label: PropTypes.string.isRequired,
41+
/** Optional click handler */
42+
onClick: PropTypes.func,
43+
};
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { fn } from "storybook/test";
2+
3+
import { Button } from "./Button";
4+
5+
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
6+
export default {
7+
title: "Example/Button",
8+
component: Button,
9+
parameters: {
10+
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
11+
layout: "centered",
12+
},
13+
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
14+
tags: ["autodocs"],
15+
// More on argTypes: https://storybook.js.org/docs/api/argtypes
16+
argTypes: {
17+
backgroundColor: { control: "color" },
18+
},
19+
// Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args
20+
args: { onClick: fn() },
21+
};
22+
23+
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
24+
export const Primary = {
25+
args: {
26+
primary: true,
27+
label: "Button",
28+
},
29+
};
30+
31+
export const Secondary = {
32+
args: {
33+
label: "Button",
34+
},
35+
};
36+
37+
export const Large = {
38+
args: {
39+
size: "large",
40+
label: "Button",
41+
},
42+
};
43+
44+
export const Small = {
45+
args: {
46+
size: "small",
47+
label: "Button",
48+
},
49+
};

client/src/stories/button.css

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
.storybook-button {
2+
display: inline-block;
3+
cursor: pointer;
4+
border: 0;
5+
border-radius: 3em;
6+
font-weight: 700;
7+
line-height: 1;
8+
font-family: "Nunito Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
9+
}
10+
.storybook-button--primary {
11+
background-color: #555ab9;
12+
color: white;
13+
}
14+
.storybook-button--secondary {
15+
box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset;
16+
background-color: transparent;
17+
color: #333;
18+
}
19+
.storybook-button--small {
20+
padding: 10px 16px;
21+
font-size: 12px;
22+
}
23+
.storybook-button--medium {
24+
padding: 11px 20px;
25+
font-size: 14px;
26+
}
27+
.storybook-button--large {
28+
padding: 12px 24px;
29+
font-size: 16px;
30+
}

0 commit comments

Comments
 (0)