feat(ui, preview): add loader to canvas's preview (#9143)

feat(ui, preview): add loader to canvas's preview

Co-authored-by: Norbert de Langen <ndelangen@me.com>
This commit is contained in:
Norbert de Langen 2019-12-23 23:40:32 +01:00 committed by GitHub
commit 481fdab55d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 54 additions and 3 deletions

View File

@ -0,0 +1,5 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import { Loader } from './Loader';
storiesOf('Basics/Loader', module).add('infinite state', () => <Loader role="progressbar" />);

View File

@ -0,0 +1,24 @@
import { keyframes, styled } from '@storybook/theming';
const spin = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`;
export const Loader = styled.div(({ theme }) => ({
animation: `${spin} 1s linear infinite`,
borderRadius: '50%',
height: 48,
left: 'calc(50% - 24px)',
position: 'absolute',
top: 'calc(50% - 24px)',
width: 48,
zIndex: 4,
border: `3px solid ${theme.color.secondary}`,
borderTop: '3px solid transparent',
}));

View File

@ -35,3 +35,6 @@ export { StorybookIcon } from './brand/StorybookIcon';
// Doc blocks
export * from './blocks';
// Loader
export { Loader } from './Loader/Loader';

View File

@ -34,8 +34,15 @@ class FakeProvider extends Provider {
}
}
class FakeLoadingProvider extends FakeProvider {
renderPreview() {
return <p>Switch between Desktop and Mobile viewport to see how the loading state behaves.</p>;
}
}
storiesOf('UI/Layout/App', module)
.addParameters({
component: App,
})
.add('default', () => <App provider={new FakeProvider()} />);
.add('default', () => <App provider={new FakeProvider()} />)
.add('loading state', () => <App provider={new FakeLoadingProvider()} />);

View File

@ -5,9 +5,10 @@ import memoize from 'memoizerific';
import copy from 'copy-to-clipboard';
import { styled } from '@storybook/theming';
import { Consumer } from '@storybook/api';
import { SET_CURRENT_STORY } from '@storybook/core-events';
import { types } from '@storybook/addons';
import { Icons, IconButton, TabButton, TabBar, Separator } from '@storybook/components';
import { Icons, IconButton, Loader, TabButton, TabBar, Separator } from '@storybook/components';
import { Helmet } from 'react-helmet-async';
@ -217,6 +218,10 @@ const getDocumentTitle = description => {
return description ? `${description} ⋅ Storybook` : 'Storybook';
};
const mapper = ({ state }) => ({
loading: !state.storiesConfigured,
});
class Preview extends Component {
shouldComponentUpdate({ storyId, viewMode, docsOnly, options, queryParams }) {
const { props } = this;
@ -277,7 +282,14 @@ class Preview extends Component {
customCanvas,
};
return <ActualPreview {...props} />;
return (
<>
<Consumer filter={mapper}>
{state => state.loading && <Loader role="progressbar" />}
</Consumer>
<ActualPreview {...props} />
</>
);
}}
</ZoomConsumer>
),