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

fix(#1216): storybook config #2310

Merged
merged 10 commits into from
Jul 24, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
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 .eslintrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"extends": ["airbnb", "prettier"],
"extends": ["airbnb", "prettier", "plugin:storybook/recommended"],
"parser": "@babel/eslint-parser",
"env": {
"browser": true,
Expand Down
44 changes: 25 additions & 19 deletions .storybook/main.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,35 @@
const path = require('path');

module.exports = {
/** @type { import('@storybook/react-webpack5').StorybookConfig } */
const config = {
stories: ['../client/**/*.stories.(jsx|mdx)'],
addons: [
'@storybook/addon-actions',
'@storybook/addon-docs',
'@storybook/addon-knobs',
'@storybook/addon-links',
Copy link
Collaborator

Choose a reason for hiding this comment

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

I noticed that you removed some packages from the addons array here but kept them in the package.json. Do they need to be kept as dependencies or should they be removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

They should be removed now. They've been deprecated https://www.npmjs.com/package/@storybook/addon-knobs

Actions are built in by default. And knobs have been replaced with args and argTypes where you can configure controls to play with. I've updated Buttons and Icons stories to use these rather than the knobs that were there.

'storybook-addon-theme-playground/dist/register'
'@storybook/addon-essentials',
'@storybook/addon-interactions'
],
webpackFinal: async config => {
// do mutation to the config

const rules = config.module.rules;

// modify storybook's file-loader rule to avoid conflicts with svgr
const fileLoaderRule = rules.find(rule => rule.test.test('.svg'));
fileLoaderRule.exclude = path.resolve(__dirname, '../client');
framework: {
name: '@storybook/react-webpack5',
options: {}
},
docs: {
autodocs: 'tag'
},
async webpackFinal(config) {
// https://storybook.js.org/docs/react/builders/webpack
// this modifies the existing image rule to exclude .svg files
// since we want to handle those files with @svgr/webpack
const imageRule = config.module.rules.find(rule => rule.test.test('.svg'))
imageRule.exclude = /\.svg$/

// use svgr for svg files
rules.push({
// configure .svg files to be loaded with @svgr/webpack
config.module.rules.push({
test: /\.svg$/,
use: ["@svgr/webpack"],
use: ['@svgr/webpack']
})

return config;
return config
},
};

export default config;


40 changes: 15 additions & 25 deletions .storybook/preview.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,21 @@
import React from 'react';
import { addDecorator, addParameters } from '@storybook/react';
import { withKnobs } from "@storybook/addon-knobs";
import { withThemePlayground } from 'storybook-addon-theme-playground';
import { ThemeProvider } from "styled-components";
import { Provider } from 'react-redux';

import theme, { Theme } from '../client/theme';
import ThemeProvider from '../client/modules/App/components/ThemeProvider';
import configureStore from '../client/store';
import '../client/styles/build/css/main.css'

addDecorator(withKnobs);
const initialState = window.__INITIAL_STATE__;

const themeConfigs = Object.values(Theme).map(
name => {
return { name, theme: theme[name] };
}
);
const store = configureStore(initialState);

addDecorator(withThemePlayground({
theme: themeConfigs,
provider: ThemeProvider
}));
export const decorators = [
(Story) => (
<Provider store={store}>
<ThemeProvider>
<Story />
</ThemeProvider>
</Provider>
),
]

addParameters({
options: {
/**
* display the top-level grouping as a "root" in the sidebar
*/
showRoots: true,
},
})

// addDecorator(storyFn => <ThemeProvider theme={theme}>{storyFn()}</ThemeProvider>);
18 changes: 9 additions & 9 deletions client/common/Button.stories.jsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import React from 'react';
import { action } from '@storybook/addon-actions';
import { boolean, text } from '@storybook/addon-knobs';

import Button from './Button';
import { GithubIcon, DropdownArrowIcon, PlusIcon } from './icons';

export default {
title: 'Common/Button',
component: Button
component: Button,
args: {
children: 'this is the button',
label: 'submit',
disabled: false
}
};

export const AllFeatures = () => (
<Button
disabled={boolean('disabled', false)}
type="submit"
label={text('label', 'submit')}
>
{text('children', 'this is the button')}
export const AllFeatures = (args) => (
Copy link
Collaborator

Choose a reason for hiding this comment

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

The controls on this story don't seem to do anything because we aren't passing down all of the args. Looks like we can write the story as an object with the new "Component Story Format 3". Very cool.

export default {
  title: 'Common/Button',
  component: Button
}

export const AllFeatures = {
  args: {
    children: 'this is the button'
  }
};

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for investigating linting... I mistakenly thought these were linting issues on the main branch. I wasn't giving them much thought. I'll try your suggestion later today and see if I can revert them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah with stories you can set some defaults for all stories. Customise default args per story. Or present them with fixed values too if you like.

Previously this AllFeatures story had dynamic args as knobs and all the reset were fixed.

This is a button story from a personal project where args were overridden.

const Template: Story<ButtonProps> = (args) => <Button {...args} />;

export const FullWidth = Template.bind({});
FullWidth.args = {
  primary: true,
  children: 'Button',
  fullWidth: true
};

<Button disabled={args.disabled} type="submit" label={args.label}>
{args.children}
</Button>
);

Expand Down
16 changes: 10 additions & 6 deletions client/common/icons.stories.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import React from 'react';
import { select } from '@storybook/addon-knobs';

import * as icons from './icons';

export default {
title: 'Common/Icons',
component: icons
component: icons,
argTypes: {
variant: {
options: Object.keys(icons),
control: { type: 'select' },
default: icons.CircleFolderIcon
}
}
};

export const AllIcons = () => {
const names = Object.keys(icons);

const SelectedIcon = icons[select('name', names, names[0])];
export const Icons = (args) => {
const SelectedIcon = icons[args.variant || 'CircleInfoIcon'];
return <SelectedIcon />;
};
8 changes: 4 additions & 4 deletions client/components/Nav/NavDropdownMenu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ function NavDropdownMenu({ id, title, children }) {

const { createDropdownHandlers } = useContext(NavBarContext);

const handlers = useMemo(() => createDropdownHandlers(id), [
createDropdownHandlers,
id
]);
const handlers = useMemo(
() => createDropdownHandlers(id),
[createDropdownHandlers, id]
);

return (
<li className={classNames('nav__item', isOpen && 'nav__item--open')}>
Expand Down
8 changes: 4 additions & 4 deletions client/components/Nav/NavMenuItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ function NavMenuItem({ hideIf, ...rest }) {

const { createMenuItemHandlers } = useContext(NavBarContext);

const handlers = useMemo(() => createMenuItemHandlers(parent), [
createMenuItemHandlers,
parent
]);
const handlers = useMemo(
() => createMenuItemHandlers(parent),
[createMenuItemHandlers, parent]
);

if (hideIf) {
return null;
Expand Down
5 changes: 2 additions & 3 deletions client/components/createRedirectWithUsername.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ function mapStateToProps(state) {

const ConnectedRedirectToUser = connect(mapStateToProps)(RedirectToUser);

const createRedirectWithUsername = (url) => (props) => (
<ConnectedRedirectToUser {...props} url={url} />
);
const createRedirectWithUsername = (url) => (props) =>
<ConnectedRedirectToUser {...props} url={url} />;

export default createRedirectWithUsername;
8 changes: 2 additions & 6 deletions client/modules/IDE/components/Console.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -206,12 +206,8 @@ const Console = () => {
const isExpanded = useSelector((state) => state.ide.consoleIsExpanded);
const isPlaying = useSelector((state) => state.ide.isPlaying);
const { theme, fontSize } = useSelector((state) => state.preferences);
const {
collapseConsole,
expandConsole,
clearConsole,
dispatchConsoleEvent
} = bindActionCreators({ ...IDEActions, ...ConsoleActions }, useDispatch());
const { collapseConsole, expandConsole, clearConsole, dispatchConsoleEvent } =
bindActionCreators({ ...IDEActions, ...ConsoleActions }, useDispatch());

const cm = useRef({});

Expand Down
9 changes: 2 additions & 7 deletions client/modules/IDE/components/FileNode.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,8 @@ function parseFileName(name) {
}

function FileName({ name }) {
const {
baseName,
firstLetter,
lastLetter,
middleText,
extension
} = parseFileName(name);
const { baseName, firstLetter, lastLetter, middleText, extension } =
parseFileName(name);
return (
<span className="sidebar__file-item-name-text">
<span>{firstLetter}</span>
Expand Down
4 changes: 2 additions & 2 deletions client/modules/IDE/components/Toolbar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ class Toolbar extends React.Component {
});
const nameContainerClass = classNames({
'toolbar__project-name-container': true,
'toolbar__project-name-container--editing': this.props.project
.isEditingName
'toolbar__project-name-container--editing':
this.props.project.isEditingName
});

const canEditProjectName = this.canEditProjectName();
Expand Down
62 changes: 32 additions & 30 deletions client/modules/IDE/pages/MobileIDEView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -210,41 +210,43 @@ const handleGlobalKeydown = (props, cmController) => (e) => {
}
};

const autosave = (autosaveInterval, setAutosaveInterval) => (
props,
prevProps
) => {
const {
autosaveProject,
preferences,
ide,
selectedFile: file,
project,
isUserOwner
} = props;

const { selectedFile: oldFile } = prevProps;

const doAutosave = () => autosaveProject(true);

if (isUserOwner && project.id) {
if (preferences.autosave && ide.unsavedChanges && !ide.justOpenedProject) {
if (file.name === oldFile.name && file.content !== oldFile.content) {
if (autosaveInterval) {
clearTimeout(autosaveInterval);
const autosave =
(autosaveInterval, setAutosaveInterval) => (props, prevProps) => {
const {
autosaveProject,
preferences,
ide,
selectedFile: file,
project,
isUserOwner
} = props;

const { selectedFile: oldFile } = prevProps;

const doAutosave = () => autosaveProject(true);

if (isUserOwner && project.id) {
if (
preferences.autosave &&
ide.unsavedChanges &&
!ide.justOpenedProject
) {
if (file.name === oldFile.name && file.content !== oldFile.content) {
if (autosaveInterval) {
clearTimeout(autosaveInterval);
}
console.log('will save project in 20 seconds');
setAutosaveInterval(setTimeout(doAutosave, 20000));
}
console.log('will save project in 20 seconds');
setAutosaveInterval(setTimeout(doAutosave, 20000));
} else if (autosaveInterval && !preferences.autosave) {
clearTimeout(autosaveInterval);
setAutosaveInterval(null);
}
} else if (autosaveInterval && !preferences.autosave) {
} else if (autosaveInterval) {
clearTimeout(autosaveInterval);
setAutosaveInterval(null);
}
} else if (autosaveInterval) {
clearTimeout(autosaveInterval);
setAutosaveInterval(null);
}
};
};

// ide, preferences, project, selectedFile, user, params, unsavedChanges, expandConsole, collapseConsole,
// stopSketch, startSketch, getProject, clearPersistedState, autosaveProject, saveProject, files
Expand Down
11 changes: 6 additions & 5 deletions client/utils/responsive.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ export const mobileFirst = (MobileComponent, Fallback) => (props) => {
);
};

export const responsiveForm = (DesktopComponent) => (props) => (
<ResponsiveForm>
<DesktopComponent {...props} />
</ResponsiveForm>
);
export const responsiveForm = (DesktopComponent) => (props) =>
(
<ResponsiveForm>
<DesktopComponent {...props} />
</ResponsiveForm>
);
Loading
Loading