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

Storybook/Export to CodeSandbox #19583

Merged
Merged
Show file tree
Hide file tree
Changes from 60 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
43b340d
QuickStart: fix closing tag
PeterDraex Jul 2, 2021
61ba427
Merge branch 'microsoft:master' into master
PeterDraex Jul 7, 2021
442f248
Merge branch 'microsoft:master' into master
PeterDraex Jul 14, 2021
0efe6ab
Merge branch 'microsoft:master' into master
PeterDraex Jul 21, 2021
5ec023d
Merge branch 'microsoft:master' into master
PeterDraex Jul 26, 2021
3da0b4f
Merge branch 'microsoft:master' into master
PeterDraex Jul 30, 2021
c9d5c7d
Update RFC/authoring stories
PeterDraex Jul 30, 2021
5d74494
polish RFC for authoring stories
PeterDraex Jul 30, 2021
8034742
fix toc
PeterDraex Jul 30, 2021
7a27b0b
fix stylization
PeterDraex Jul 30, 2021
1394163
fix config example
PeterDraex Jul 30, 2021
074908e
remove lists with one bullet
PeterDraex Jul 30, 2021
685ea4d
Merge branch 'microsoft:master' into master
PeterDraex Aug 3, 2021
2536d86
Update rfcs/convergence/authoring-stories.md
PeterDraex Aug 3, 2021
7eb2523
.story.tsx -> .stories.tsx
PeterDraex Aug 3, 2021
080702e
Update rfcs/convergence/authoring-stories.md
PeterDraex Aug 3, 2021
97c00aa
Update authoring-stories.md
PeterDraex Aug 3, 2021
dd8ed8c
Update authoring-stories.md
PeterDraex Aug 3, 2021
a6e25a9
Update authoring-stories.md
PeterDraex Aug 3, 2021
d0c3fbb
Update rfcs/convergence/authoring-stories.md
PeterDraex Aug 3, 2021
b3b1c50
Update rfcs/convergence/authoring-stories.md
PeterDraex Aug 4, 2021
cedc49c
Update rfcs/convergence/authoring-stories.md
PeterDraex Aug 4, 2021
0e5187f
Update rfcs/convergence/authoring-stories.md
PeterDraex Aug 4, 2021
ddc13de
Update authoring-stories.md
PeterDraex Aug 4, 2021
f05c67f
Update authoring-stories.md
PeterDraex Aug 5, 2021
b20e6d5
Update authoring-stories.md
PeterDraex Aug 5, 2021
d209ba6
Update authoring-stories.md
PeterDraex Aug 5, 2021
7e52408
formatting
PeterDraex Aug 9, 2021
494981a
heading to bold text
PeterDraex Aug 9, 2021
3d7a839
use @filename pragma
PeterDraex Aug 9, 2021
f3d5ec2
add component to imports
PeterDraex Aug 9, 2021
754d075
make "first" more explicit
PeterDraex Aug 9, 2021
e982e55
add bad example
PeterDraex Aug 9, 2021
e820ea0
code style
PeterDraex Aug 9, 2021
3649556
Merge branch 'microsoft:master' into master
PeterDraex Aug 10, 2021
d34b67d
Merge branch 'microsoft:master' into master
PeterDraex Aug 24, 2021
a5d7507
Merge branch 'microsoft:master' into master
PeterDraex Aug 25, 2021
e9af531
Merge branch 'microsoft:master' into master
PeterDraex Sep 1, 2021
cb8fac9
export to codesandbox
PeterDraex Aug 31, 2021
375a1a7
simplify story names
PeterDraex Aug 31, 2021
cb323af
Change files
PeterDraex Aug 31, 2021
d178b4c
fix pipeline
PeterDraex Sep 1, 2021
9b91353
fix pipeline
PeterDraex Sep 1, 2021
6a36221
update package.json
PeterDraex Sep 1, 2021
f05fc75
Update change/@fluentui-react-components-ac6ea616-3cc3-4a01-ae02-aa2f…
PeterDraex Sep 1, 2021
18686f6
Update change/@fluentui-react-button-d1f817e2-ff90-495f-bdc9-27c91f79…
PeterDraex Sep 1, 2021
4397531
remove stories exclusion from tsconfig.base.json
PeterDraex Sep 1, 2021
b7d863e
update to version without bundled codesandbox
PeterDraex Sep 1, 2021
1a8d42e
use makeStyles
PeterDraex Sep 1, 2021
54a95b8
use babel plugin to get story source
PeterDraex Sep 14, 2021
7d2536a
remove decorator
PeterDraex Sep 14, 2021
66b00f1
add comments to babel plugin
PeterDraex Sep 14, 2021
4ed4048
ignore ts errors
PeterDraex Sep 14, 2021
e422879
change make-styles import
PeterDraex Sep 14, 2021
9c4a533
style stories
PeterDraex Sep 15, 2021
2ea8ee0
update addon version
PeterDraex Sep 15, 2021
bec2094
remove relative import
PeterDraex Sep 15, 2021
f4b5fc5
minor update of package
PeterDraex Sep 16, 2021
ddc0d31
remove unnecessary ts-ignores
PeterDraex Sep 16, 2021
bdf0c54
delete invalid change files
PeterDraex Sep 16, 2021
3874ce0
update yarn.lock
PeterDraex Sep 16, 2021
eccd640
add ts-ignore to babel.plugin.js
PeterDraex Sep 16, 2021
c5182fc
Revert "delete invalid change files"
PeterDraex Sep 17, 2021
16d079a
show full source code
PeterDraex Sep 17, 2021
9f048b9
workaround for ts-ignore
PeterDraex Sep 17, 2021
8bad95c
Change files
PeterDraex Sep 17, 2021
f5644ab
dont break menu story
PeterDraex Sep 20, 2021
d7572e0
fix order of stories
PeterDraex Sep 20, 2021
07e461a
Merge branch 'microsoft:master' into storybook/export-to-codesandbox
PeterDraex Sep 21, 2021
a1e0402
update addon to 0.4.0
PeterDraex Sep 24, 2021
439617d
fix types for babel plugin
PeterDraex Sep 24, 2021
80a0b6c
Button.stories.tsx - revert disscet, update
PeterDraex Sep 24, 2021
1d8c1ae
update to 0.5.1
PeterDraex Sep 29, 2021
cb3da40
Merge branch 'microsoft:master' into storybook/export-to-codesandbox
PeterDraex Sep 29, 2021
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
32 changes: 32 additions & 0 deletions .storybook/babel.plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// This Babel plugin adds context.parameters.fullSource property to Storybook stories,
// which contains source of of the file where story is present.
// It’s utilized by Export to CodeSandbox.

// @ts-ignore
module.exports = function (babel) {
const { types: t } = babel;
return {
name: 'literal-replacer',
visitor: {
// @ts-ignore
PeterDraex marked this conversation as resolved.
Show resolved Hide resolved
MemberExpression(path) {
if (path.node.property.name === 'parameters' && path.parentPath.isAssignmentExpression()) {
const storyName = path.node.object.name;
const expression = t.expressionStatement(
t.assignmentExpression(
'=',
t.memberExpression(
t.memberExpression(t.identifier(storyName), t.identifier('parameters')),
t.identifier('fullSource'),
),
t.identifier('__STORY__'),
),
);
const expressionStatement = path.findParent(p => p.isExpressionStatement());
expressionStatement.insertAfter(expression);
path.stop();
}
},
},
};
};
12 changes: 12 additions & 0 deletions .storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ module.exports = /** @type {Omit<StorybookConfig,'typescript'|'babel'>} */ ({
'@storybook/addon-a11y',
'@storybook/addon-knobs/preset',
'storybook-addon-performance',
'storybook-addon-export-to-codesandbox',
],
webpackFinal: config => {
const tsPaths = new TsconfigPathsPlugin({
Expand All @@ -51,6 +52,17 @@ module.exports = /** @type {Omit<StorybookConfig,'typescript'|'babel'>} */ ({

if (config.module && config.module.rules) {
overrideDefaultBabelLoader(/** @type {import("webpack").RuleSetRule[]} */ (config.module.rules));

config.module.rules.unshift({
test: /\.stories\.tsx$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
plugins: [require('./babel.plugin')],
},
},
});
}

return config;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "update stories structure to make them exportable to CodeSandbox",
"packageName": "@fluentui/react-button",
"email": "[email protected]",
"dependentChangeType": "none"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Add export to CodeSandbox for stories",
"packageName": "@fluentui/react-components",
"email": "[email protected]",
"dependentChangeType": "none"
}

This file was deleted.

This file was deleted.

This file was deleted.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,8 @@
"webpack-merge": "5.7.3",
"workspace-tools": "0.12.3",
"yargs": "13.3.2",
"yargs-parser": "13.1.2"
"yargs-parser": "13.1.2",
"storybook-addon-export-to-codesandbox": "0.2.3"
},
"license": "MIT",
"workspaces": {
Expand Down
179 changes: 12 additions & 167 deletions packages/react-button/src/components/Button/Button.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,168 +1,20 @@
import * as React from 'react';
import { Button, ButtonProps } from '../../Button';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - add link to this comment please (see https://github.com/microsoft/fluentui/pull/18695)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will break any type checking related to the component, which is probably not a good idea for maintainability or our internal dev experience. What was the reason you had to it this way? Then maybe we can come up with an alternative.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a general principle, we should optimize for the primary scenario (local dev experience and ensuring types stay in sync), and if that doesn't work with some secondary scenario (export to codesandbox), any workarounds/hacks should be done in the secondary scenario's code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main reason for this is that we build storybook code along with other code. During the build process, we no longer use ts path aliases, which means that without this ts-ignore, the build will always fail. We want to use aliases here because we want to avoid circular dependencies between packages.

As long as we use ts path aliases, the only long term solution for this is to use separate ts configs which is proposed in #19044

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to make the codesandbox export addon convert relative imports within the same package to absolute imports? That would at least get rid of some of the ts-ignores.

Especially if we end up renaming slots to be named with a Slot suffix, having type checking disabled all over the place is a huge risk.

Copy link
Contributor Author

@PeterDraex PeterDraex Sep 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only easy solution I could think of is specifying the dependency package and it’s version manually, on the import line:

import { Button } from '../../Button'; // codesandbox-dependency: @fluentui/react-button ^9.0.0-alpha

Then, in export to CodeSandbox, we’d replace it with regex:

const dependencyRegex = / from '.*?'; \/\/ codesandbox-dependency: (.*?) (.*)/g;
const dependencySubs = " from '$1';";
storyFile.replaceAll(dependencyRegex, dependencySubs);

What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any way the addon could access package.json to read the package name and version? Or could they be read and passed in when configuring the addon?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that would require more time than I can commit to this. I can create a GitHub issue about it if you think it’s worth it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's definitely worth doing something to avoid using a sledgehammer that so significantly detracts from maintainability. I did something sort of similar with packages/react-examples/.storybook/preview-loader.js, which is solving a different problem but the approach might be generally applicable. I'll check out your branch and see if I can come up with anything.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ecraig12345 I’ll merge this now without changing Button stories. Let’s address automatic version detection / absolute imports in other PRs.

import { Button } from '@fluentui/react-button';
import { Meta } from '@storybook/react';
import { CalendarMonth24Regular } from '@fluentui/react-icons';

import descriptionMd from './ButtonDescription.md';
import bestPracticesMd from './ButtonBestPractices.md';

export const Default = (props: ButtonProps) => <Button {...props}>Button</Button>;

export const Emphasis = () => (
<>
<Button primary>Primary button</Button>
<Button>Default button</Button>
<Button outline>Outline button</Button>
<Button subtle>Subtle button</Button>
<Button transparent>Transparent button</Button>
</>
);
Emphasis.parameters = {
docs: {
description: {
story:
'- `primary` button is used for the most important action on the page or in a view\n' +
'- `default` button is used for subordinate actions\n' +
'- `outline` has no background styling and is emphasized through the styling of its content and borders\n' +
'- `transparent` has no background or border styling and is just emphasized through its content styling\n' +
'- `subtle` button blends into its background and becomes less emphasized\n',
},
},
};

export const ButtonWithIcon = () => (
<>
<Button icon={<CalendarMonth24Regular />}>Text</Button>
<Button icon={<CalendarMonth24Regular />} iconPosition="after">
Text
</Button>
<Button icon={<CalendarMonth24Regular />} />
</>
);
ButtonWithIcon.parameters = {
docs: {
description: {
story:
'Button has an `icon` slot that, if specified, renders an icon either `before` or `after` the children, ' +
'as specified by the `iconPosition` prop.',
},
},
};

export const CircularButton = () => (
<>
<Button circular>Button</Button>
<Button circular outline icon={<CalendarMonth24Regular />} />
<Button circular subtle icon={<CalendarMonth24Regular />} />
<Button circular transparent icon={<CalendarMonth24Regular />} />
</>
);
CircularButton.parameters = {
docs: {
description: {
story: 'A button can have completely rounded corners.',
},
},
};

export const ButtonSize = () => {
const groupStyles: React.CSSProperties = { display: 'flex', flexWrap: 'wrap', gap: '0.5em' };
const headerStyles: React.CSSProperties = { width: '100%', margin: 0 };
return (
<>
<div style={groupStyles}>
<h4 style={headerStyles}>small</h4>
<Button size="small">Text</Button>
<Button size="small" icon={<CalendarMonth24Regular />}>
Text
</Button>
<Button size="small" icon={<CalendarMonth24Regular />} />
</div>
<div style={groupStyles}>
<h4 style={headerStyles}>medium</h4>
<Button>Text</Button>
<Button icon={<CalendarMonth24Regular />}>Text</Button>
<Button icon={<CalendarMonth24Regular />} />
</div>
<div style={groupStyles}>
<h4 style={headerStyles}>large</h4>
<Button size="large">Text</Button>
<Button size="large" icon={<CalendarMonth24Regular />}>
Text
</Button>
<Button size="large" icon={<CalendarMonth24Regular />} />
</div>
</>
);
};
ButtonSize.parameters = {
docs: {
description: {
story: 'A button supports `small`, `medium` and `large` size. Default size is `medium`.',
},
},
};

export const BlockButton = () => (
<>
<Button block>Block button</Button>
</>
);
BlockButton.parameters = {
docs: {
description: {
story: 'A button can fill the width of its container.',
},
},
};

export const DisabledButton = () => {
const groupStyles: React.CSSProperties = { display: 'flex', flexWrap: 'wrap', gap: '0.5em' };
export { Emphasis } from './ButtonEmphasis.stories';
export { Default } from './ButtonDefault.stories';
export { Disabled } from './ButtonDisabled.stories';

return (
<>
<div style={groupStyles}>
<Button>Default</Button>
<Button disabled>Disabled</Button>
<Button disabledFocusable>Disabled focusable</Button>
</div>
<div style={groupStyles}>
<Button primary icon={<CalendarMonth24Regular />}>
Primary
</Button>
<Button primary disabled icon={<CalendarMonth24Regular />}>
Primary disabled
</Button>
<Button primary disabledFocusable>
Primary disabled focusable
</Button>
</div>
</>
);
};
DisabledButton.parameters = {
docs: {
description: {
story: `A button can be \`disabled\` or \`disabledFocusable\`.
\`disabledFocusable\` is used in scenarios where it is important to keep a consistent tab order
for screen reader and keyboard users. The primary example of this pattern is when
the disabled button is in a menu or a commandbar and is seldom used for standalone buttons.`,
},
},
};

export const ButtonWithLongText = () => (
<>
<Button>Text</Button>
<Button>Text truncates after it hits the max width token value</Button>
</>
);
ButtonWithLongText.parameters = {
docs: {
description: {
story: 'Text truncates after it hits the max width theme token value.',
},
},
};
export { WithIcon } from './ButtonWithIcon.stories';
export { Circular } from './ButtonCircular.stories';
export { Size } from './ButtonSize.stories';
export { Block } from './ButtonBlock.stories';
export { WithLongText } from './ButtonWithLongText.stories';

export default {
title: 'Components/Button',
Expand All @@ -174,11 +26,4 @@ export default {
},
},
},
decorators: [
Story => (
<div style={{ display: 'flex', justifyContent: 'space-evenly' }}>
<Story />
</div>
),
],
} as Meta;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as React from 'react';

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - add link to this comment please (see https://github.com/microsoft/fluentui/pull/18695)
import { Button } from '@fluentui/react-button';

export const Block = () => (
<div style={{ display: 'flex', justifyContent: 'space-evenly' }}>
<Button block>Block button</Button>
</div>
);
Block.parameters = {
docs: {
description: {
story: 'A button can fill the width of its container.',
},
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as React from 'react';

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - add link to this comment please (see https://github.com/microsoft/fluentui/pull/18695)
import { Button } from '@fluentui/react-button';
import { CalendarMonth24Regular } from '@fluentui/react-icons';

export const Circular = () => (
<div style={{ display: 'flex', justifyContent: 'space-evenly' }}>
<Button circular>Button</Button>
<Button circular outline icon={<CalendarMonth24Regular />} />
<Button circular subtle icon={<CalendarMonth24Regular />} />
<Button circular transparent icon={<CalendarMonth24Regular />} />
</div>
);
Circular.parameters = {
docs: {
description: {
story: 'A button can have completely rounded corners.',
},
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as React from 'react';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - add link to this comment please (see https://github.com/microsoft/fluentui/pull/18695)
import { Button, ButtonProps } from '@fluentui/react-button';

export const Default = (props: ButtonProps) => (
<div style={{ display: 'flex', justifyContent: 'space-evenly' }}>
<Button {...props}>Button</Button>
</div>
);
Loading