diff --git a/packages/react/src/generators/component-story/component-story.spec.ts b/packages/react/src/generators/component-story/component-story.spec.ts
index d0d14a1971..97a631537c 100644
--- a/packages/react/src/generators/component-story/component-story.spec.ts
+++ b/packages/react/src/generators/component-story/component-story.spec.ts
@@ -217,6 +217,67 @@ describe('react:component-story', () => {
});
});
+ describe('component with props and actions', () => {
+ beforeEach(async () => {
+ appTree.write(
+ cmpPath,
+ `import React from 'react';
+
+ import './test.scss';
+
+ export type ButtonStyle = 'default' | 'primary' | 'warning';
+
+ export interface TestProps {
+ name: string;
+ displayAge: boolean;
+ someAction: (e: unknown) => void;
+ style: ButtonStyle;
+ }
+
+ export const Test = (props: TestProps) => {
+ return (
+
+
Welcome to test component, {props.name}
+
+
+ );
+ };
+
+ export default Test;
+ `
+ );
+
+ await componentStoryGenerator(appTree, {
+ componentPath: 'lib/test-ui-lib.tsx',
+ project: 'test-ui-lib',
+ });
+ });
+
+ it('should setup controls based on the component props', () => {
+ expect(formatFile`${appTree.read(storyFilePath, 'utf-8')}`)
+ .toContain(formatFile`
+ import { Story, Meta } from '@storybook/react';
+ import { Test, TestProps } from './test-ui-lib';
+
+ export default {
+ component: Test,
+ title: 'Test',
+ argTypes: {
+ someAction: { action: 'someAction executed!' },
+ },
+ } as Meta;
+
+ const Template: Story = (args) => ;
+
+ export const Primary = Template.bind({});
+ Primary.args = {
+ name: '',
+ displayAge: false,
+ };
+ `);
+ });
+ });
+
[
{
name: 'default export function',
diff --git a/packages/react/src/generators/component-story/component-story.ts b/packages/react/src/generators/component-story/component-story.ts
index c8482ecebc..edb962df62 100644
--- a/packages/react/src/generators/component-story/component-story.ts
+++ b/packages/react/src/generators/component-story/component-story.ts
@@ -36,11 +36,7 @@ export function getArgsDefaultValue(property: ts.SyntaxKind): string {
export function createComponentStoriesFile(
host: Tree,
- {
- // name,
- project,
- componentPath,
- }: CreateComponentStoriesFileSchema
+ { project, componentPath }: CreateComponentStoriesFileSchema
) {
const proj = getProjects(host).get(project);
const sourceRoot = proj.sourceRoot;
@@ -98,16 +94,29 @@ export function createComponentStoriesFile(
name: string;
defaultValue: any;
}[] = [];
+ let argTypes: {
+ name: string;
+ type: string;
+ actionText: string;
+ }[] = [];
if (propsInterface) {
propsTypeName = propsInterface.name.text;
-
props = propsInterface.members.map((member: ts.PropertySignature) => {
- return {
- name: (member.name as ts.Identifier).text,
- defaultValue: getArgsDefaultValue(member.type.kind),
- };
+ if (member.type.kind === ts.SyntaxKind.FunctionType) {
+ argTypes.push({
+ name: (member.name as ts.Identifier).text,
+ type: 'action',
+ actionText: `${(member.name as ts.Identifier).text} executed!`,
+ });
+ } else {
+ return {
+ name: (member.name as ts.Identifier).text,
+ defaultValue: getArgsDefaultValue(member.type.kind),
+ };
+ }
});
+ props = props.filter((p) => p && p.defaultValue !== undefined);
}
generateFiles(
@@ -118,6 +127,7 @@ export function createComponentStoriesFile(
componentFileName: name,
propsTypeName,
props,
+ argTypes,
componentName: (cmpDeclaration as any).name.text,
isPlainJs,
fileExt,
diff --git a/packages/react/src/generators/component-story/files/__componentFileName__.stories.__fileExt__ b/packages/react/src/generators/component-story/files/__componentFileName__.stories.__fileExt__
index 2154ac7d7a..f232d83f6b 100644
--- a/packages/react/src/generators/component-story/files/__componentFileName__.stories.__fileExt__
+++ b/packages/react/src/generators/component-story/files/__componentFileName__.stories.__fileExt__
@@ -3,7 +3,11 @@ import<% if ( !isPlainJs ) { %> { <% } %> <%= componentName %><% if ( propsTypeN
export default {
component: <%= componentName %>,
- title: '<%= componentName %>'
+ title: '<%= componentName %>',<% if ( argTypes && argTypes.length > 0 ) { %>
+ argTypes: {<% for (let argType of argTypes) { %>
+ <%= argType.name %>: { <%- argType.type %> : "<%- argType.actionText %>" },<% } %>
+}
+ <% } %>
}<% if ( !isPlainJs ) { %> as Meta <% } %>;
const Template<% if ( !isPlainJs ) { %>: Story<<%= propsTypeName %>><% } %> = (args) => <<%= componentName %> {...args} />;