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

CLI: Component-driven React / Vue / Angular / Preact / Svelte templates #11505

Merged
merged 23 commits into from
Jul 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1b2f4ab
CLI: Update React JS template with Header/Page stories
shilman Jul 11, 2020
3282fc1
Merge branch 'next' into 10723-update-cli-template-stories
shilman Jul 11, 2020
f8531a3
CLI: React template Button onClick
shilman Jul 11, 2020
fddc9a1
CLI: React template Button css
shilman Jul 11, 2020
b67c65f
add e2e target
tooppaaa Jul 11, 2020
0f94327
Vue stories
tooppaaa Jul 13, 2020
e0d531b
CLI template: Fix button CSS
shilman Jul 14, 2020
c06b9e9
CLI template: Link to componentdriven.org
shilman Jul 14, 2020
b5e6985
Fix typo
shilman Jul 14, 2020
f6e7ddf
CLI: Ignore import/extensions for framework templates
shilman Jul 14, 2020
1e6a38e
Preact CLI
tooppaaa Jul 14, 2020
25089c1
Angular CLI
tooppaaa Jul 14, 2020
b101f9e
Merge branch 'next' into 10723-update-cli-template-stories
shilman Jul 15, 2020
bfa4926
CLI template: Fix componentdriven.org link
shilman Jul 15, 2020
45f7ec2
CLI template: Use action argType instead of hard-coded action
shilman Jul 15, 2020
fba408c
CLI template: Prettier
shilman Jul 15, 2020
ed2e2ed
CLI: Fix Angular template compodoc settings
shilman Jul 15, 2020
af5337e
Merge branch 'next' into 10723-update-cli-template-stories
shilman Jul 15, 2020
8026f60
Merge branch 'next' into 10723-update-cli-template-stories
shilman Jul 15, 2020
2302d7a
CLI: Fix Vue CLI template props handing
shilman Jul 15, 2020
fec9066
Svelte CLI
tooppaaa Jul 15, 2020
aa1d6ba
Merge branch 'next' into 10723-update-cli-template-stories
shilman Jul 16, 2020
bca9750
Fix capitalization
shilman Jul 16, 2020
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
2 changes: 1 addition & 1 deletion addons/controls/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ Here is the full list of available controls:
| ----------- | ------------ | -------------------------------------------------------------- | -------------- |
| **array** | array | serialize array into a comma-separated string inside a textbox | separator |
| **boolean** | boolean | checkbox input | - |
| **number** | number | a numberic text box input | min, max, step |
| **number** | number | a numeric text box input | min, max, step |
| | range | a range slider input | min, max, step |
| **object** | object | json editor text input | - |
| **enum** | radio | radio buttons input | options |
Expand Down
2 changes: 1 addition & 1 deletion cypress/generated/addon-action.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ describe('addon-action', () => {

it('should trigger an action', () => {
// click on the button
cy.navigateToStory('button', 'text');
cy.navigateToStory('example-button', 'primary');

cy.getStoryElement().contains('Button').click();
cy.viewAddonPanel('Actions');
Expand Down
15 changes: 0 additions & 15 deletions cypress/generated/addon-link.spec.ts

This file was deleted.

76 changes: 67 additions & 9 deletions cypress/generated/basic.spec.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,76 @@
describe('Basic Flow', () => {
describe('Basic CLI', () => {
before(() => {
cy.visitStorybook();
});

it('should load welcome flow', () => {
cy.navigateToStory('example-introduction', 'page');
describe('Welcome story (MDX)', () => {
it('should load and display', () => {
cy.navigateToStory('example-introduction', 'page');
cy.getDocsElement().should('contain.text', 'Welcome to Storybook');
});
});

describe('Button story', () => {
it('should load primary story', () => {
cy.navigateToStory('example-button', 'primary');
cy.getStoryElement()
.find('button')
.should('have.class', 'storybook-button')
.and('have.class', 'storybook-button--primary');
});

it('should load secondary story', () => {
cy.navigateToStory('example-button', 'secondary');
cy.getStoryElement()
.find('button')
.should('have.class', 'storybook-button')
.and('have.class', 'storybook-button--secondary');
});
it('should load small story', () => {
cy.navigateToStory('example-button', 'small');
cy.getStoryElement()
.find('button')
.should('have.class', 'storybook-button')
.and('have.class', 'storybook-button--small');
});
it('should load large story', () => {
cy.navigateToStory('example-button', 'large');
cy.getStoryElement()
.find('button')
.should('have.class', 'storybook-button')
.and('have.class', 'storybook-button--large');
});
});

describe('Header story', () => {
it('should load and display logged in', () => {
cy.navigateToStory('example-header', 'logged-in');
cy.getStoryElement().find('header').should('contain.text', 'Acme');
cy.getStoryElement().find('button').should('contain.text', 'Log out');
});

// assert url changes
cy.url().should('include', 'path=/story/example-introduction--page');
it('should load and display logged out', () => {
cy.navigateToStory('example-header', 'logged-out');
cy.getStoryElement().find('header').should('contain.text', 'Acme');
cy.getStoryElement().find('button').first().should('contain.text', 'Log in');
cy.getStoryElement().find('button').last().should('contain.text', 'Sign up');
});
});

// check for selected element
cy.get('#example-introduction--page').should('have.class', 'selected');
describe('Page story', () => {
it('should load and display logged in', () => {
cy.navigateToStory('example-page', 'logged-in');
cy.getStoryElement().find('header').should('contain.text', 'Acme');
cy.getStoryElement().find('button').should('contain.text', 'Log out');
cy.getStoryElement().should('contain.text', 'Pages in Storybook');
});

// check for content
cy.getDocsElement().should('contain.text', 'Welcome to Storybook');
it('should load and display logged out', () => {
cy.navigateToStory('example-page', 'logged-out');
cy.getStoryElement().should('contain.text', 'Acme');
cy.getStoryElement().find('button').first().should('contain.text', 'Log in');
cy.getStoryElement().find('button').last().should('contain.text', 'Sign up');
cy.getStoryElement().should('contain.text', 'Pages in Storybook');
});
});
});
4 changes: 4 additions & 0 deletions cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ Cypress.Commands.add('navigateToStory', (kind, name) => {
// assert url changes
cy.url().should('include', `path=/story/${kindId}--${storyId}`);
cy.get(storyLinkId).should('have.class', 'selected');

// A pause is good when switching stories
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(50);
});

Cypress.Commands.add('viewAddonPanel', (name) => {
Expand Down
2 changes: 2 additions & 0 deletions lib/cli/src/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ module.exports = {
'react/prop-types': ignore,
'react/react-in-jsx-scope': ignore,
'import/no-extraneous-dependencies': ignore,
'import/extensions': ignore,
'import/named': ignore,
},
},
],
Expand Down
48 changes: 0 additions & 48 deletions lib/cli/src/frameworks/angular/1-Button.stories.ts

This file was deleted.

37 changes: 37 additions & 0 deletions lib/cli/src/frameworks/angular/Button.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Button from './button.component';

export default {
title: 'Example/Button',
component: Button,
argTypes: {
backgroundColor: { control: 'color' },
},
};

const Template = (args: Button) => ({
component: Button,
props: args,
});

export const Primary = Template.bind({});
Primary.args = {
primary: true,
label: 'Button',
};

export const Secondary = Template.bind({});
Secondary.args = {
label: 'Button',
};

export const Large = Template.bind({});
Large.args = {
size: 'large',
label: 'Button',
};

export const Small = Template.bind({});
Small.args = {
size: 'small',
label: 'Button',
};
29 changes: 29 additions & 0 deletions lib/cli/src/frameworks/angular/Header.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { moduleMetadata } from '@storybook/angular';
import { CommonModule } from '@angular/common';

import Button from './button.component';
import Header from './header.component';

export default {
title: 'Example/Header',
component: Header,
decorators: [
moduleMetadata({
declarations: [Button],
imports: [CommonModule],
}),
],
};

const Template = (args: Header) => ({
component: Header,
props: args,
});

export const LoggedIn = Template.bind({});
LoggedIn.args = {
user: {},
};

export const LoggedOut = Template.bind({});
LoggedOut.args = {};
34 changes: 34 additions & 0 deletions lib/cli/src/frameworks/angular/Page.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { moduleMetadata } from '@storybook/angular';
import { CommonModule } from '@angular/common';

import Button from './button.component';
import Header from './header.component';
import Page from './page.component';

import * as HeaderStories from './Header.stories';

export default {
title: 'Example/Page',
component: Header,
decorators: [
moduleMetadata({
declarations: [Button, Header],
imports: [CommonModule],
}),
],
};

const Template = (args: Page) => ({
component: Page,
props: args,
});

export const LoggedIn = Template.bind({});
LoggedIn.args = {
...HeaderStories.LoggedIn.args,
};

export const LoggedOut = Template.bind({});
LoggedOut.args = {
...HeaderStories.LoggedOut.args,
};
61 changes: 44 additions & 17 deletions lib/cli/src/frameworks/angular/button.component.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,53 @@
import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
selector: 'storybook-button-component',
template: ` <button (click)="onClick.emit($event)">{{ text }}</button> `,
styles: [
`
button {
border: 1px solid #eee;
border-radius: 3px;
background-color: #ffffff;
cursor: pointer;
font-size: 15px;
padding: 3px 10px;
margin: 10px;
}
`,
],
selector: 'storybook-button',
template: ` <button
type="button"
(click)="onClick.emit($event)"
[ngClass]="classes"
[ngStyle]="{ 'background-color': backgroundColor }"
>
{{ label }}
</button>`,
styleUrls: ['./button.css'],
})
export default class ButtonComponent {
/**
* Is this the principal call to action on the page?
*/
@Input()
text = '';
primary: boolean;

/**
* What background color to use
*/
@Input()
backgroundColor: string;

/**
* How large should the button be?
*/
@Input()
size: 'small' | 'medium' | 'large' = 'medium';

/**
* Button contents
*
* @required
*/
@Input()
label: string;

/**
* Optional click handler
*/
@Output()
onClick = new EventEmitter<any>();
onClick = new EventEmitter<Event>();

public get classes(): string[] {
const mode = this.primary ? 'storybook-button--primary' : 'storybook-button--secondary';

return ['storybook-button', `storybook-button--${this.size}`, mode];
}
}
Loading