diff --git a/docs/configure/images-and-assets.md b/docs/configure/images-and-assets.md index 70cda5af159..730669041ce 100644 --- a/docs/configure/images-and-assets.md +++ b/docs/configure/images-and-assets.md @@ -15,7 +15,8 @@ Afterwards you can use any asset in your stories: @@ -43,6 +44,7 @@ Here `./public` is your static directory. Now use it in a component or story lik paths={[ 'react/component-story-static-asset-without-import.js.mdx', 'vue/component-story-static-asset-without-import.js.mdx', + 'angular/component-story-static-asset-without-import.ts.mdx' ]} /> @@ -68,6 +70,7 @@ Upload your files to an online CDN and reference them. In this example we’re u paths={[ 'react/component-story-static-asset-cdn.js.mdx', 'vue/component-story-static-asset-cdn.js.mdx', + 'angular/component-story-static-asset-cdn.ts.mdx' ]} /> diff --git a/docs/essentials/controls.md b/docs/essentials/controls.md index 0fe8a693e0f..91dfec59064 100644 --- a/docs/essentials/controls.md +++ b/docs/essentials/controls.md @@ -93,6 +93,7 @@ Up until now, we only used auto-generated controls based on the component we're 'react/table-story-fully-customize-controls.js.mdx', 'react/table-story-fully-customize-controls.mdx.mdx', 'vue/table-story-fully-customize-controls.js.mdx', + 'angular/table-story-fully-customize-controls.ts.mdx' ]} /> @@ -116,6 +117,7 @@ As they can be complex cases: 'react/component-story-custom-args-complex.ts.mdx', 'react/component-story-custom-args-complex.mdx.mdx', 'vue/component-story-custom-args-complex.js.mdx', + 'angular/component-story-custom-args-complex.ts.mdx' ]} /> @@ -132,6 +134,7 @@ Or even with certain types of elements, such as icons: 'react/component-story-custom-args-icons.ts.mdx', 'react/component-story-custom-args-icons.mdx.mdx', 'vue/component-story-custom-args-icons.js.mdx', + 'angular/component-story-custom-args-icons.ts.mdx' ]} /> diff --git a/docs/essentials/viewport.md b/docs/essentials/viewport.md index b7c37e924f1..bcdf116c881 100644 --- a/docs/essentials/viewport.md +++ b/docs/essentials/viewport.md @@ -122,6 +122,7 @@ You can change your story through [parameters](../writing-stories/parameters.md) 'react/my-component-story-configure-viewports.js.mdx', 'react/my-component-story-configure-viewports.mdx.mdx', 'vue/my-component-story-configure-viewports.js.mdx', + 'angular/my-component-story-configure-viewports.ts.mdx' ]} /> diff --git a/docs/get-started/whats-a-story.md b/docs/get-started/whats-a-story.md index c34429da855..2c46b303b12 100644 --- a/docs/get-started/whats-a-story.md +++ b/docs/get-started/whats-a-story.md @@ -38,7 +38,8 @@ The above story definition can be further improved to take advantage of [Storybo paths={[ 'react/button-story-with-args.js.mdx', 'react/button-story-with-args.ts.mdx', - 'vue/button-story-with-args.js.mdx' + 'vue/button-story-with-args.js.mdx', + 'angular/button-story-with-args.ts.mdx' ]} /> diff --git a/docs/snippets/angular/app-story-with-mock.ts.mdx b/docs/snippets/angular/app-story-with-mock.ts.mdx new file mode 100644 index 00000000000..6261881e8b4 --- /dev/null +++ b/docs/snippets/angular/app-story-with-mock.ts.mdx @@ -0,0 +1,34 @@ +```ts +// App.stories.ts + +import { Story, Meta } from '@storybook/angular/types-6-0'; +import { AppComponent } from './app.component'; + +export default { + component: AppComponent, + title: 'App', +} as Meta; + +const Template: Story = (args: AppComponent) => ({ + component: AppComponent, + props: args, +}); + +export const Success = Template.bind({}); +Success.parameters = { + fetch: { + json: { + JavaScript: 3390991, + 'C++': 44974, + TypeScript: 15530, + CoffeeScript: 12253, + Python: 9383, + C: 5341, + Shell: 5115, + HTML: 3420, + CSS: 3171, + Makefile: 189, + }, + }, +}; +``` diff --git a/docs/snippets/angular/button-group-story.ts.mdx b/docs/snippets/angular/button-group-story.ts.mdx index 5efe19e9cac..2e707e49ad8 100644 --- a/docs/snippets/angular/button-group-story.ts.mdx +++ b/docs/snippets/angular/button-group-story.ts.mdx @@ -14,18 +14,18 @@ export default { decorators: [ moduleMetadata({ declarations: [Button], - imports: [CommonModule], - }), + imports: [CommonModule] + }) ], }; const Template = (args: ButtonGroup) => ({ - props: args, + props: args }); export const Pair = Template.bind({}); Pair.args = { - buttons: [...ButtonStories.Primary.args, ...ButtonStories.Secondary.args], - orientation: 'horizontal', + buttons:[{...ButtonStories.Primary.args},{...ButtonStories.Secondary.args}], + orientation: 'horizontal' }; ``` diff --git a/docs/snippets/angular/button-story-default-docs-code.ts.mdx b/docs/snippets/angular/button-story-default-docs-code.ts.mdx new file mode 100644 index 00000000000..3662412ae9a --- /dev/null +++ b/docs/snippets/angular/button-story-default-docs-code.ts.mdx @@ -0,0 +1,37 @@ +```ts +// Button.stories.ts + +import { Story, Meta } from '@storybook/angular/types-6-0'; +import Button from './button.component'; + +export default { + title: 'Button', + component: Button, + argTypes: { + backgroundColor: { control: 'color' } + } +} as Meta; + +// some function to demonstrate the behavior +const someFunction = (someValue: string) => { + return `i am a ${someValue}`; +}; + +export const ExampleStory: Story = (args: ComplexCase) => { + const { label } = args; + // assigns the function result to a variable and pass it as a prop into the component + const functionResult = someFunction(label); + return { + component: ComplexCase, + props: { + ...args, + label:functionResult + }, + }; +}; +ExampleStory.args = { + primary: true, + size: 'small', + label: 'button', +}; +``` diff --git a/docs/snippets/angular/button-story-with-args.ts.mdx b/docs/snippets/angular/button-story-with-args.ts.mdx index 943a95b0d95..ce0ed38a454 100644 --- a/docs/snippets/angular/button-story-with-args.ts.mdx +++ b/docs/snippets/angular/button-story-with-args.ts.mdx @@ -2,7 +2,8 @@ //Button.stories.ts const Template = (args: Button) => ({ - props: args, + component: Button, + props: args }); export const Primary = Template.bind({}); diff --git a/docs/snippets/angular/button-test.ts.mdx b/docs/snippets/angular/button-test.ts.mdx new file mode 100644 index 00000000000..81e6b9972a6 --- /dev/null +++ b/docs/snippets/angular/button-test.ts.mdx @@ -0,0 +1,15 @@ +```ts +// button.component.spec.ts + +import { render, screen } from '@testing-library/angular'; +import ButtonComponent from './button.component'; + +import { Primary } from './Button.stories'; + +test('renders the button in the primary state ', async () => { + await render(ButtonComponent, { + componentProperties: Primary.args, + }); + expect(screen.getByRole('button').classList.contains('storybook-button--primary')).toBeTruthy(); +}); +``` diff --git a/docs/snippets/angular/component-story-custom-args-complex.ts.mdx b/docs/snippets/angular/component-story-custom-args-complex.ts.mdx new file mode 100644 index 00000000000..a2ac47c1e83 --- /dev/null +++ b/docs/snippets/angular/component-story-custom-args-complex.ts.mdx @@ -0,0 +1,46 @@ +```ts +// YourComponent.stories.ts + +import { Story, Meta } from '@storybook/angular/types-6-0'; +import YourComponent from './your.component'; + +// a function to apply some computations +const someFunction = (valuePropertyA: string, valuePropertyB: string) => { + // makes some computations and returns something +}; + +export default { + component: YourComponent, + title: 'A complex case with a function', + // creates specific argTypes with options + argTypes: { + propertyA: { + control: { + type: 'select', + options: ['Item One', 'Item Two', 'Item Three'] + }, + }, + propertyB: { + control: { + type: 'select', + options: ['Another Item One', 'Another Item Two', 'Another Item Three'] + }, + }, + }, +} as Meta; + +const Template: Story = (args: YourComponent) => { + const { propertyA, propertyB } = args; + + const someFunctionResult = someFunction(propertyA, propertyB); + + args.someProperty = someFunctionResult; + return { + component: YourComponent, + props: { + ...args, + someProperty:someFunctionResult + }, + }; +}; +``` diff --git a/docs/snippets/angular/component-story-custom-args-icons.ts.mdx b/docs/snippets/angular/component-story-custom-args-icons.ts.mdx new file mode 100644 index 00000000000..7d651d9a41c --- /dev/null +++ b/docs/snippets/angular/component-story-custom-args-icons.ts.mdx @@ -0,0 +1,37 @@ +```ts +// YourComponent.stories.ts + +import { Story, Meta } from '@storybook/angular/types-6-0'; +import Icon from './icon.component'; + +import { IconA, IconB, IconC, IconD, IconE } from './icons'; + +// Maps the icons to a JSON serializable object to be safely used with the argTypes +const iconMap = { IconA, IconB, IconC, IconD, IconE }; + +export default { + title: 'My Story with Icons', + component: YourComponent, + argTypes: { + icon: { + control: { + type: 'select', + options: Object.keys(iconMap), + }, + }, + }, +} as Meta; + +const Template: Story = (args: Icon) => { + // retrieves the appropriate icon passes it as a component prop + const { icon } = args; + const selectedIcon = iconMap[icon]; + return { + component: Icon, + props: { + ...args, + icon:selectedIcon + }, + }; +}; +``` diff --git a/docs/snippets/angular/component-story-static-asset-cdn.ts.mdx b/docs/snippets/angular/component-story-static-asset-cdn.ts.mdx new file mode 100644 index 00000000000..3232f11c2f3 --- /dev/null +++ b/docs/snippets/angular/component-story-static-asset-cdn.ts.mdx @@ -0,0 +1,13 @@ +```ts +// MyComponent.stories.ts + +import { Meta } from '@storybook/angular/types-6-0'; + +export default { + title: 'img', +} as Meta; + +export const withAnImage = () => ({ + template: `My CDN placeholder` +}); +``` \ No newline at end of file diff --git a/docs/snippets/angular/component-story-static-asset-with-import.ts.mdx b/docs/snippets/angular/component-story-static-asset-with-import.ts.mdx new file mode 100644 index 00000000000..42cd7eec223 --- /dev/null +++ b/docs/snippets/angular/component-story-static-asset-with-import.ts.mdx @@ -0,0 +1,24 @@ +```ts +// MyComponent.stories.ts + +import { Meta } from '@storybook/angular/types-6-0'; + +import imageFile from './static/image.png'; + +export default { + title: 'img', +} as Meta; + +const image = { + src: imageFile, + alt: 'my image', +}; + +export const withAnImage = () => ({ + template: `{{alt}}`, + props: { + src: image.src, + alt: image.alt, + }, +}); +``` diff --git a/docs/snippets/angular/component-story-static-asset-without-import.ts.mdx b/docs/snippets/angular/component-story-static-asset-without-import.ts.mdx new file mode 100644 index 00000000000..ab263522323 --- /dev/null +++ b/docs/snippets/angular/component-story-static-asset-without-import.ts.mdx @@ -0,0 +1,13 @@ +```ts +// MyComponent.stories.ts + +import { Meta } from '@storybook/angular/types-6-0'; + +export default { + title: 'img', +} as Meta; + +export const withAnImage = () => ({ + template: `my image` +}); +``` \ No newline at end of file diff --git a/docs/snippets/angular/list-story-reuse-data.ts.mdx b/docs/snippets/angular/list-story-reuse-data.ts.mdx index 43a7707ce4b..00f868c7dc3 100644 --- a/docs/snippets/angular/list-story-reuse-data.ts.mdx +++ b/docs/snippets/angular/list-story-reuse-data.ts.mdx @@ -6,9 +6,9 @@ import * as ListItemStories from './ListItem.stories'; export const ManyItems = Template.bind({}); ManyItems.args = { items: [ - ...ListItemStories.Selected.args, - ...ListItemStories.Unselected.args, - ...ListItemStoriesUnselected.args, + { ...ListItemStories.Selected.args }, + { ...ListItemStories.Unselected.args }, + { ...ListItemStories.Unselected.args }, ], }; ``` diff --git a/docs/snippets/angular/list-story-template.ts.mdx b/docs/snippets/angular/list-story-template.ts.mdx new file mode 100644 index 00000000000..a8afbe9a5af --- /dev/null +++ b/docs/snippets/angular/list-story-template.ts.mdx @@ -0,0 +1,31 @@ +```ts +// List.stories.ts + +import { Story } from '@storybook/angular/types-6-0'; + +import ListComponent from './List.component'; +import ListItemComponent from './ListItem.component'; + +import { Unchecked } from './ListItem.stories'; + +const ListTemplate: Story = (args: ListComponent) => ({ + component: ListComponent, + moduleMetadata: { + declarations: [ListComponent, ListItemComponent], + }, + props: args, + template: ` + +
+ +
+
`, +}); + +export const EmptyWithTemplate = ListTemplate.bind({}); +Empty.args = { items: [] }; + + +export const OneItemWithTemplate = ListTemplate.bind({}); +OneItemWithTemplate.args = { items: [Unchecked.args.item] }; +``` \ No newline at end of file diff --git a/docs/snippets/angular/list-story-unchecked.ts.mdx b/docs/snippets/angular/list-story-unchecked.ts.mdx new file mode 100644 index 00000000000..589df98f587 --- /dev/null +++ b/docs/snippets/angular/list-story-unchecked.ts.mdx @@ -0,0 +1,26 @@ +```ts +// List.stories.ts + +import { Story } from '@storybook/angular/types-6-0'; + +import ListComponent from './List.component'; +import ListItemComponent from './ListItem.component'; +import { Unchecked } from './ListItem.stories'; + +export const OneItem: Story = (args: ListComponent) => ({ + component: ListComponent, + moduleMetadata: { + declarations: [ListComponent, ListItemComponent], + }, + props: args, + template: ` + + + + `, +}); + +OneItem.args = { + ...Unchecked.args, +}; +``` diff --git a/docs/snippets/angular/my-component-story-configure-viewports.ts.mdx b/docs/snippets/angular/my-component-story-configure-viewports.ts.mdx new file mode 100644 index 00000000000..9c2622fccae --- /dev/null +++ b/docs/snippets/angular/my-component-story-configure-viewports.ts.mdx @@ -0,0 +1,31 @@ +```ts +// MyComponent.stories.ts + +import { Story, Meta } from '@storybook/angular/types-6-0'; +import { INITIAL_VIEWPORTS } from '@storybook/addon-viewport'; +import MyComponent from './MyComponent.component'; + +export default { + title: 'Stories', + component: MyComponent, + parameters: { + // the viewports object from the Essentials addon + viewport: { + // the viewports you want to use + viewports: INITIAL_VIEWPORTS, + // your own default viewport + defaultViewport: 'iphone6', + } + }, +} as Meta; + +export const myStory: Story = () => ({ + component: MyComponent, + template: '
' +}); +myStory.parameters = { + viewport: { + defaultViewport: 'iphonex' + } +}; +``` \ No newline at end of file diff --git a/docs/snippets/angular/page-story-with-args-composition.ts.mdx b/docs/snippets/angular/page-story-with-args-composition.ts.mdx new file mode 100644 index 00000000000..6556b609ed7 --- /dev/null +++ b/docs/snippets/angular/page-story-with-args-composition.ts.mdx @@ -0,0 +1,42 @@ +```ts +// YourPage.stories.ts + +import { moduleMetadata } from '@storybook/angular' +import { Story, Meta } from '@storybook/angular/types-6-0'; + +import { CommonModule } from '@angular/common'; + +import DocumentScreen from './YourPage.component'; +import DocumentList from './DocumentList.component'; +import DocumentHeader from './DocumentHeader.component'; +import PageLayout from './PageLayout.component'; + + +import * as PageLayoutStories from './PageLayout.stories'; +import * as DocumentHeaderStories from './DocumentHeader.stories'; +import * as DocumentListStories from './DocumentList.stories'; + +export default { + component: DocumentScreen, + title: 'DocumentScreen', + decorators: [ + moduleMetadata({ + // imports components to allow component composition with Storybook + declarations: [DocumentList, DocumentHeader,PageLayout], + imports: [CommonModule], + }), + ], +} as Meta; + +const Template: Story = (args: DocumentScreen) => ({ + component: DocumentScreen, + props: args, +}); + +export const Simple = Template.bind({}); +Simple.args = { + user: PageLayoutStories.PageLayoutSimple.args.user, + document: DocumentHeaderStories.DocumentHeaderSimple.args.document, + subdocuments: DocumentListStories.DocumentListSimple.args.documents +}; +``` \ No newline at end of file diff --git a/docs/snippets/angular/simple-page-implementation.ts.mdx b/docs/snippets/angular/simple-page-implementation.ts.mdx new file mode 100644 index 00000000000..ff6b7517644 --- /dev/null +++ b/docs/snippets/angular/simple-page-implementation.ts.mdx @@ -0,0 +1,26 @@ +```ts +// YourPage.component.ts + +import { Component, Input } from '@angular/core'; + +@Component({ + selector: 'document-screen', + template: ` + + + + + `, +}) +export default class DocumentScreen { + @Input() + user: any = { id: 0, name: 'Some User' }; + + @Input() + document: any = { id: 0, title: 'Some Title' }; + + @Input() + subdocuments: any = []; +} + +``` \ No newline at end of file diff --git a/docs/snippets/angular/table-story-fully-customize-controls.ts.mdx b/docs/snippets/angular/table-story-fully-customize-controls.ts.mdx new file mode 100644 index 00000000000..b5f9737c481 --- /dev/null +++ b/docs/snippets/angular/table-story-fully-customize-controls.ts.mdx @@ -0,0 +1,30 @@ +```ts +// Table.stories.ts + +const TableStory: Story = (args: TableComponent) => ({ + component: TableComponent, + props: args, + template: ` + + + + + + +
+ {{data[i][j]}} +
+ ` +}); + +export const Numeric = TableStory.bind({}); +Numeric.args = { + // This arg is for the story component + data: [ + [1, 2, 3], + [4, 5, 6], + ], + // The remaining args get passed to the `Table` component + size: 'large', +}; +``` diff --git a/docs/snippets/angular/your-component.ts.mdx b/docs/snippets/angular/your-component.ts.mdx index 7cfb697feac..24727f2edb6 100644 --- a/docs/snippets/angular/your-component.ts.mdx +++ b/docs/snippets/angular/your-component.ts.mdx @@ -1,6 +1,7 @@ ```ts -// YourComponent.stories.tsx -import { Meta, moduleMetadata, Story } from '@storybook/angular'; +// YourComponent.stories.ts + +import { Meta, Story } from '@storybook/angular'; import { YourComponent } from './your.component'; @@ -10,7 +11,8 @@ export default { component: YourComponent, } as Meta; -const Template: Story = (args) => ({ +const Template: Story = (args:YourComponent) => ({ + component:YourComponent, props: args, }); diff --git a/docs/workflows/build-pages-with-storybook.md b/docs/workflows/build-pages-with-storybook.md index 13ac64da2aa..986379e61e6 100644 --- a/docs/workflows/build-pages-with-storybook.md +++ b/docs/workflows/build-pages-with-storybook.md @@ -38,7 +38,8 @@ When you are building screens in this way, it is typical that the inputs of a co paths={[ 'react/simple-page-implementation.js.mdx', 'react/simple-page-implementation.ts.mdx', - 'vue/simple-page-implementation.vue.mdx' + 'vue/simple-page-implementation.vue.mdx', + 'angular/simple-page-implementation.ts.mdx' ]} /> @@ -52,7 +53,8 @@ In such cases it is natural to use [args composition](../writing-stories/args.md paths={[ 'react/page-story-with-args-composition.js.mdx', 'react/page-story-with-args-composition.ts.mdx', - 'vue/page-story-with-args-composition.js.mdx' + 'vue/page-story-with-args-composition.js.mdx', + 'angular/page-story-with-args-composition.ts.mdx' ]} /> @@ -131,7 +133,8 @@ Once that configuration is complete, we can set the mock values in a specific st diff --git a/docs/workflows/stories-for-multiple-components.md b/docs/workflows/stories-for-multiple-components.md index 18e9e7d4e6a..4dddcae9cfc 100644 --- a/docs/workflows/stories-for-multiple-components.md +++ b/docs/workflows/stories-for-multiple-components.md @@ -38,7 +38,8 @@ The simplest change we can make to the above is to reuse the stories of the `Lis paths={[ 'react/list-story-unchecked.js.mdx', 'react/list-story-unchecked.ts.mdx', - 'vue/list-story-unchecked.js.mdx' + 'vue/list-story-unchecked.js.mdx', + 'angular/list-story-unchecked.ts.mdx' ]} /> @@ -81,7 +82,8 @@ Another option that is more “data”-based is to create a special “story-gen paths={[ 'react/list-story-template.js.mdx', 'react/list-story-template.ts.mdx', - 'vue/list-story-template.js.mdx' + 'vue/list-story-template.js.mdx', + 'angular/list-story-template.ts.mdx' ]} /> diff --git a/docs/workflows/unit-testing.md b/docs/workflows/unit-testing.md index 481f6162d0e..ff179db0d9a 100644 --- a/docs/workflows/unit-testing.md +++ b/docs/workflows/unit-testing.md @@ -15,7 +15,8 @@ Here is an example of how you can use it in a testing library: diff --git a/docs/writing-docs/doc-blocks.md b/docs/writing-docs/doc-blocks.md index 908cc9166ed..e9c61ebad54 100644 --- a/docs/writing-docs/doc-blocks.md +++ b/docs/writing-docs/doc-blocks.md @@ -242,7 +242,8 @@ As an example, if you had the following story: paths={[ 'react/button-story-default-docs-code.js.mdx', 'react/button-story-default-docs-code.ts.mdx', - 'vue/button-story-default-docs-code.js.mdx' + 'vue/button-story-default-docs-code.js.mdx', + 'angular/button-story-default-docs-code.ts.mdx' ]} />