Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(storybook): 📝 refactor storybook preview #360

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .husky/post-checkout

This file was deleted.

3 changes: 0 additions & 3 deletions .husky/post-commit

This file was deleted.

3 changes: 0 additions & 3 deletions .husky/post-merge

This file was deleted.

3 changes: 0 additions & 3 deletions .husky/pre-push

This file was deleted.

2 changes: 1 addition & 1 deletion .storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module.exports = {
features: { babelModeV7: true },
stories: ["../src/**/*.stories.@(js|jsx|ts|tsx)"],
addons: [
"storybook-addon-preview",
"storybook-addon-preview/register",
"storybook-addon-react-docgen",
"@storybook/addon-essentials",
"@storybook/addon-a11y",
Expand Down
184 changes: 149 additions & 35 deletions .storybook/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable no-new-func */
import { CodeSandboxTemplate } from "storybook-addon-preview";
import outdent from "outdent";

type CreateControlsOptions = {
unions?: string[];
Expand Down Expand Up @@ -29,9 +30,12 @@ export const createControls = (options?: CreateControlsOptions) => {
}
};

interface FilesProp {
[index: string]: string;
}
interface Props {
js?: string;
ts?: string;
js?: { template: string; files?: FilesProp };
ts?: { template: string; files?: FilesProp };
jsUtils?: string;
tsUtils?: string;
css?: string;
Expand All @@ -40,16 +44,18 @@ interface Props {

export function createPreviewTabs(props: Props) {
const { js, ts, jsUtils, tsUtils, css, deps: extraDeps = [] } = props;
const deps = ["@adaptui/react@latest", "reakit@latest", ...extraDeps];
const tabs = [];

if (js) {
tabs.push({
tab: "JSX",
template: js,
template: js.template,
language: "jsx",
copy: true,
codesandbox: REACTJS_CUSTOM_CODESANDBOX(deps),
codesandbox: REACTJS_CUSTOM_CODESANDBOX([...extraDeps], {
"src/components/index.js": js.template,
...(js.files && js.files),
}),
});
}

Expand All @@ -59,17 +65,19 @@ export function createPreviewTabs(props: Props) {
template: jsUtils,
language: "jsx",
copy: true,
codesandbox: REACTJS_CUSTOM_CODESANDBOX(deps),
});
}

if (ts) {
tabs.push({
tab: "TSX",
template: ts,
template: ts.template,
language: "tsx",
copy: true,
codesandbox: REACT_CUSTOM_CODESANDBOX(deps),
codesandbox: REACT_CUSTOM_CODESANDBOX([...extraDeps], {
"src/components/index.tsx": ts.template,
...(ts.files && ts.files),
}),
});
}

Expand All @@ -79,7 +87,6 @@ export function createPreviewTabs(props: Props) {
template: tsUtils,
language: "tsx",
copy: true,
codesandbox: REACT_CUSTOM_CODESANDBOX(deps),
});
}

Expand All @@ -94,33 +101,140 @@ export function createPreviewTabs(props: Props) {

return tabs;
}

const joinStrs = (strs: string[]) => {
return `[${strs.map(str => `"${str}"`).join(", ")}]`;
};

const REACTJS_CUSTOM_CODESANDBOX = (dependencies: string[]) =>
new Function(`
var previews = arguments[0];
return {
framework: "reactjs",
export const REACTJS_CUSTOM_CODESANDBOX: CodeSandboxTemplate = (
userDependencies = [],
files = {},
) => {
return {
template: "create-react-app",
files: {
"src/App.js": previews["JSX"][0],
"src/styles.css": previews["CSS"] ? previews["CSS"][0] : "",
...(previews["UtilsJSX"] ? {"src/Utils.component.js": previews["UtilsJSX"][0]} : {}),
"public/index.html": `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
</body>
</html>
`,
"src/index.js": `
import App from "./App";
import { createRoot } from 'react-dom/client';
const rootElement = document.getElementById('root');
const root = createRoot(rootElement);
root.render(<App />);
`,
"src/App.js": outdent`
import React from "react";
import Component from "./components";

export default function App() {
return <Component />
}
`,
...files,
},
userDependencies: ${joinStrs(dependencies)},
};`) as CodeSandboxTemplate;

const REACT_CUSTOM_CODESANDBOX = (dependencies: string[]) =>
new Function(`
var previews = arguments[0];
return {
framework: "react",
dependencies: {
"@adaptui/react": "latest",
react: "18.0.0",
"react-dom": "18.0.0",
"react-scripts": "latest",
"@internationalized/date": "^3.0.0-rc.0",
},
scripts: {
start: "react-scripts start",
build: "react-scripts build",
test: "react-scripts test --env=jsdom",
eject: "react-scripts eject",
},
main: "src/index.js",
userDependencies,
};
};
export const REACT_CUSTOM_CODESANDBOX: CodeSandboxTemplate = (
userDependencies = [],
files = {},
) => {
return {
template: "create-react-app-typescript",
files: {
"src/App.tsx": previews["TSX"][0],
"src/styles.css": previews["CSS"] ? previews["CSS"][0] : "",
...(previews["UtilsTSX"] ? {"src/Utils.component.tsx": previews["UtilsTSX"][0]} : {}),
"public/index.html": `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
</body>
</html>
`,
"src/index.tsx": `
import * as ReactDOM from "react-dom";
import * as React from "react";
import App from "./App";
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
`,
"src/App.tsx": `import React from \"react\";\n import Component from \"./components\";\n\nexport default function App() {\n return (\n <div>\n <main >\n <Component />\n </main>\n </div>\n );\n}\n`,
...files,
},
userDependencies: ${joinStrs(dependencies)},
};`) as CodeSandboxTemplate;
dependencies: {
"@adaptui/react": "latest",
react: "17.0.2",
"react-dom": "17.0.2",
next: "12.0.7",
},
devDependencies: {
"@types/node": "17.0.5",
"@types/react": "17.0.38",
"@types/react-dom": "17.0.11",
typescript: "4.5.4",
},
scripts: {
dev: "next dev",
build: "next build",
start: "next start",
lint: "next lint",
},
main: "src/index.ts",
userDependencies,
};
};

export const CreateAppTemplate = (props: object | undefined) => {
return outdent`
import React from "react";
import Component from "./components";

export default function App() {
return <Component ${props && `{...${JSON.stringify(props)}}`} />
}
`;
};
3 changes: 2 additions & 1 deletion scripts/builds/create-previews.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ const transpileTs = require("../utils/transpile-ts");
const addPackageName = string =>
string
.replace("../../index", "@adaptui/react")
.replace("../../../index", "@adaptui/react");
.replace("../../../index", "@adaptui/react")
.replace(/(\.\.\/\.\.\/).*(\/)/g, "./");

function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
Expand Down
2 changes: 1 addition & 1 deletion src/accordion/stories/AccordionBasic.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default {
component: AccordionBasic,
parameters: {
layout: "centered",
preview: createPreviewTabs({ js, ts }),
preview: createPreviewTabs({ js: { template: js }, ts: { template: ts } }),
},
} as Meta;

Expand Down
2 changes: 1 addition & 1 deletion src/accordion/stories/AccordionMultiple.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default {
component: AccordionMultiple,
parameters: {
layout: "centered",
preview: createPreviewTabs({ js, ts }),
preview: createPreviewTabs({ js: { template: js }, ts: { template: ts } }),
},
} as Meta;

Expand Down
6 changes: 5 additions & 1 deletion src/accordion/stories/AccordionStyled.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ export default {
title: "Accordion/Styled",
parameters: {
layout: "centered",
preview: createPreviewTabs({ js, ts, css }),
preview: createPreviewTabs({
js: { template: js },
ts: { template: ts },
css,
}),
},
} as Meta;

Expand Down
2 changes: 2 additions & 0 deletions src/breadcrumbs/stories/BreadcrumbsBasic.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import * as React from "react";

import { BreadcrumbLink, Breadcrumbs, BreadcrumbsProps } from "../../index";

import "./BreadcrumbsBasic.css";

export type BreadcrumbsBasicProps = BreadcrumbsProps & {};

export const BreadcrumbsBasic: React.FC<BreadcrumbsBasicProps> = props => {
Expand Down
14 changes: 11 additions & 3 deletions src/breadcrumbs/stories/BreadcrumbsBasic.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import { ComponentMeta, ComponentStoryObj } from "@storybook/react";

import { createPreviewTabs } from "../../../.storybook/utils";

import css from "./templates/BreadcrumbsBasicCss";
import js from "./templates/BreadcrumbsBasicJsx";
import ts from "./templates/BreadcrumbsBasicTsx";
import { BreadcrumbsBasic } from "./BreadcrumbsBasic.component";

import "./BreadcrumbsBasic.css";

type Meta = ComponentMeta<typeof BreadcrumbsBasic>;
type Story = ComponentStoryObj<typeof BreadcrumbsBasic>;

Expand All @@ -16,7 +15,16 @@ export default {
component: BreadcrumbsBasic,
parameters: {
layout: "centered",
preview: createPreviewTabs({ js, ts }),
preview: createPreviewTabs({
js: {
template: js,
files: { "src/components/BreadcrumbsBasic.css": css },
},
ts: {
template: ts,
files: { "src/components/BreadcrumbsBasic.css": css },
},
}),
},
} as Meta;

Expand Down
17 changes: 14 additions & 3 deletions src/calendar/stories/CalendarBasic.component.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import * as React from "react";
import { VisuallyHidden } from "ariakit";
import { getWeeksInMonth, startOfWeek } from "@internationalized/date";
import {
createCalendar,
getWeeksInMonth,
startOfWeek,
} from "@internationalized/date";
import { useLocale } from "@react-aria/i18n";

import {
Expand All @@ -22,10 +26,17 @@ import {

import { ChevronLeft, ChevronRight } from "./Utils.component";

export type CalendarBasicProps = CalendarBaseStateProps & {};
import "./CalendarBasic.css";

/** Omiting locale and createCalendar */
export type CalendarBasicProps = Omit<
CalendarBaseStateProps,
"locale" | "createCalendar"
> & {};

export const CalendarBasic: React.FC<CalendarBasicProps> = props => {
const state = useCalendarBaseState(props);
const { locale } = useLocale();
const state = useCalendarBaseState({ ...props, locale, createCalendar });
const calendar = useCalendarState({ ...props, state });

return (
Expand Down
Loading