Skip to content

Commit

Permalink
support actions addon
Browse files Browse the repository at this point in the history
Basically entirely replacing the actions addon ArgsEnhancers with our own that also add inlineQrl so it works with Qwik.
  • Loading branch information
literalpie committed Feb 18, 2024
1 parent 3e799a8 commit c0ba17f
Show file tree
Hide file tree
Showing 12 changed files with 157 additions and 34 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/preview-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ jobs:
- name: Storybook Test
if: ${{ env.vercel_token != '' }}
run: |
yarn workspace qwik-app test-storybook
yarn workspace qwik-app playwright install && yarn workspace qwik-app test-storybook
env:
TARGET_URL: "${{ steps.deploy.outputs.url }}"
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ You can also add the decorator to individual stories or story files.

Because this framework is shipped only as an ESM module, this may require that you add `"type": "module"` to your `package.json` (or create a package.json inside your .storybook folder to only make this setting apply to storybook).

## Troubleshooting

If you are using `MDX` files and get an error like:

`Failed to resolve import "react/jsx-dev-runtime" `

you may need to install `react` as a dev dependency.

## Demo

There is a simple example Storybook using the latest version of this package [here](https://storybook-framework-qwik.vercel.app/)
Expand Down
1 change: 1 addition & 0 deletions packages/qwik-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"eslint": "8.56.0",
"eslint-plugin-qwik": "1.4.1",
"node-fetch": "3.3.2",
"playwright": "1.41.2",
"prettier": "3.2.5",
"react": "18.2.0",
"react-dom": "18.2.0",
Expand Down
19 changes: 19 additions & 0 deletions packages/qwik-app/src/components/button/button.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { Meta, StoryObj } from "storybook-framework-qwik";
import type { ButtonProps } from "./button";
import { Button } from "./button";

const meta = {
title: "Button",
args: {},
argTypes: {
onClick$: { action: "onClick" },
},
component: Button,
} satisfies Meta<ButtonProps>;

export default meta;

type Story = StoryObj<ButtonProps>;

// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args
export const Primary: Story = {};
21 changes: 21 additions & 0 deletions packages/qwik-app/src/components/button/button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { PropFunction } from "@builder.io/qwik";
import { component$ } from "@builder.io/qwik";

export interface ButtonProps {
/**
* Button contents
*/
label: string;
/**
* Optional click handler
*/
onClick$?: PropFunction<onClickEvent> | undefined;
}

export type onClickEvent = (event: MouseEvent, element: Element) => void;

export const Button = component$<ButtonProps>(
({ label = "click me!", onClick$ }) => {
return <button onClick$={onClick$}>{label}</button>;
},
);
69 changes: 69 additions & 0 deletions packages/storybook-framework-qwik/src/addArgsHelpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// This file is entirely copied from @storybook/addon-actions (changing the action import)

import type { Args, Renderer, ArgsEnhancer } from "@storybook/types";
import { action } from "@storybook/addon-actions";

// interface ActionsParameter {
// disable?: boolean;
// argTypesRegex?: RegExp;
// }

const isInInitialArgs = (name: string, initialArgs: Args) =>
typeof initialArgs[name] === "undefined" && !(name in initialArgs);

/**
* Automatically add action args for argTypes whose name
* matches a regex, such as `^on.*` for react-style `onClick` etc.
*/

export const inferActionsFromArgTypesRegex: ArgsEnhancer<Renderer> = (
context,
) => {
const {
initialArgs,
argTypes,
parameters: { actions },
} = context;
if (!actions || actions.disable || !actions.argTypesRegex || !argTypes) {
return {};
}

const argTypesRegex = new RegExp(actions.argTypesRegex);
const argTypesMatchingRegex = Object.entries(argTypes).filter(
([name]) => !!argTypesRegex.test(name),
);

return argTypesMatchingRegex.reduce((acc, [name, argType]) => {
if (isInInitialArgs(name, initialArgs)) {
acc[name] = action(name);
}
return acc;
}, {} as Args);
};

/**
* Add action args for list of strings.
*/
export const addActionsFromArgTypes: ArgsEnhancer<Renderer> = (context) => {
const {
initialArgs,
argTypes,
parameters: { actions },
} = context;
if (actions?.disable || !argTypes) {
return {};
}

const argTypesWithAction = Object.entries(argTypes).filter(
([name, argType]) => !!argType["action"],
);

return argTypesWithAction.reduce((acc, [name, argType]) => {
if (isInInitialArgs(name, initialArgs)) {
acc[name] = action(
typeof argType["action"] === "string" ? argType["action"] : name,
);
}
return acc;
}, {} as Args);
};
26 changes: 24 additions & 2 deletions packages/storybook-framework-qwik/src/preview.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { render as renderQwik } from "@builder.io/qwik";
import { ArgsStoryFn, RenderContext } from "@storybook/types";
import { inlinedQrl, render as renderQwik } from "@builder.io/qwik";
import { ArgsEnhancer, ArgsStoryFn, RenderContext } from "@storybook/types";
import { QwikRenderer } from "./types.js";
import { componentToJSX } from "./component-to-jsx.js";
import {
addActionsFromArgTypes,
inferActionsFromArgTypesRegex,
} from "./addArgsHelpers.js";
export { parameters, argTypesEnhancers } from "./docs/config.js";

// returns the Qwik component as a JSX element (</MyComponent>)
Expand Down Expand Up @@ -33,3 +37,21 @@ if (viteHotMeta) {
document.location.reload();
});
}

const actionsArgsEnhancers: ArgsEnhancer[] = [
addActionsFromArgTypes,
inferActionsFromArgTypesRegex,
];

export const argsEnhancers: ArgsEnhancer[] =
// use the argsEnhancers from addon-actions, then wrap the actions in Qwik's inlinedQrl function so things work.
actionsArgsEnhancers.map((actionsEnhancer: ArgsEnhancer) => {
return ((context) => {
const argsWithActions = actionsEnhancer(context);
let finalArgs: any = {};
Object.keys(argsWithActions).forEach((key) => {
finalArgs[key] = inlinedQrl(argsWithActions[key], key);
});
return finalArgs;
}) as ArgsEnhancer;
});
14 changes: 3 additions & 11 deletions packages/storybook-framework-qwik/template/cli/button.stories.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
import { action } from "@storybook/addon-actions";
import { $ } from "@builder.io/qwik";
import type { Meta, StoryObj } from "storybook-framework-qwik";
import type { ButtonProps, onClickEvent } from "./button";
import type { ButtonProps } from "./button";
import { Button } from "./button";

const meta = {
title: "Button",
args: {
// automatic actions are not yet supported.
// See https://github.com/literalpie/storybook-framework-qwik/issues/16
// For now, use the legacy addon-actions API wrapped in a $ to make your own QRL action.
onClick$: $<onClickEvent>((event, element) => {
action("click action")({ event, element });
}),
},
args: { },
argTypes: {
onClick$: { action: 'onClick'},
backgroundColor: { control: "color" },
},
component: Button,
Expand Down
4 changes: 2 additions & 2 deletions packages/storybook-framework-qwik/template/cli/button.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { PropFunction, QwikMouseEvent } from "@builder.io/qwik";
import type { PropFunction } from "@builder.io/qwik";
import { component$, useStylesScoped$ } from "@builder.io/qwik";
import buttonStyles from "./button.css?inline";

Expand Down Expand Up @@ -37,7 +37,7 @@ export const getClassForSize = (size: "small" | "medium" | "large") => {
};

export type onClickEvent = (
event: QwikMouseEvent<HTMLButtonElement, MouseEvent>,
event: MouseEvent,
element: Element
) => void;

Expand Down
22 changes: 6 additions & 16 deletions packages/storybook-framework-qwik/template/cli/header.stories.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import type { Meta, StoryObj } from "storybook-framework-qwik";
import type { HeaderProps } from "./header";
import { Header } from "./header";
import { $ } from "@builder.io/qwik";
import { action } from "@storybook/addon-actions";

const meta = {
title: "Example/Header",
Expand All @@ -13,20 +11,12 @@ const meta = {
// More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout
layout: "fullscreen",
},
args: {
// automatic actions are not yet supported.
// See https://github.com/literalpie/storybook-framework-qwik/issues/16
// For now, use the legacy addon-actions API wrapped in a $ to make your own QRL action.
onCreateAccount$: $<() => void>(() => {
action("Create Account Action")();
}),
onLogin$: $<() => void>(() => {
action("Login Action")();
}),
onLogout$: $<() => void>(() => {
action("Logout Action")();
}),
},
args: { },
argTypes: {
onCreateAccount$: { action: 'onCreateAccount' },
onLogin$: { action: 'onLogin' },
onLogout$: { action: 'onLogout' },
}
} satisfies Meta<HeaderProps>;

export default meta;
Expand Down
2 changes: 1 addition & 1 deletion packages/storybook-framework-qwik/template/cli/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const Header = component$(
viewBox="0 0 32 32"
xmlns="http://www.w3.org/2000/svg"
>
<g fill="none" fillRule="evenodd">
<g fill="none" fill-rule="evenodd">
<path
d="M10 0h12a10 10 0 0110 10v12a10 10 0 01-10 10H10A10 10 0 010 22V10A10 10 0 0110 0z"
fill="#FFF"
Expand Down
3 changes: 2 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -16095,7 +16095,7 @@ __metadata:
languageName: node
linkType: hard

"playwright@npm:^1.14.0":
"playwright@npm:1.41.2, playwright@npm:^1.14.0":
version: 1.41.2
resolution: "playwright@npm:1.41.2"
dependencies:
Expand Down Expand Up @@ -16472,6 +16472,7 @@ __metadata:
eslint: 8.56.0
eslint-plugin-qwik: 1.4.1
node-fetch: 3.3.2
playwright: 1.41.2
prettier: 3.2.5
react: 18.2.0
react-dom: 18.2.0
Expand Down

0 comments on commit c0ba17f

Please sign in to comment.