Flatten story hierarchy for simple stories (#208)
Many components have a single story. Instead of adding a folder with a single story, the story is now hoisted to an item in the containing folder. Storybook avoids creating the extra folder as long as there is only one named export from the component module, and the name matches the content path for the story.
This commit is contained in:
Родитель
08fc8fbca3
Коммит
427648c23c
|
@ -2,12 +2,14 @@
|
|||
|
||||
import { Meta } from '@storybook/react/types-6-0';
|
||||
import React, { useState } from 'react';
|
||||
import { CommunicationUiErrorSeverity, ErrorBar } from 'react-components';
|
||||
import { CommunicationUiErrorSeverity, ErrorBar as ErrorBarComponent } from 'react-components';
|
||||
import { text, select } from '@storybook/addon-knobs';
|
||||
import { getDocs } from './ErrorBarDocs';
|
||||
import { COMPONENT_FOLDER_PREFIX } from '../constants';
|
||||
|
||||
export const ErrorBarComponent = (): JSX.Element | null => {
|
||||
// This must be the only named export from this module, and must be named to match the storybook path suffix.
|
||||
// This ensures that storybook hoists the story instead of creating a folder with a single entry.
|
||||
export const ErrorBar = (): JSX.Element | null => {
|
||||
const [closed, setClosed] = useState<boolean>(false);
|
||||
const message = text('Message', 'This is a sample error message.');
|
||||
const severity = select<CommunicationUiErrorSeverity>(
|
||||
|
@ -20,15 +22,15 @@ export const ErrorBarComponent = (): JSX.Element | null => {
|
|||
};
|
||||
|
||||
if (!closed) {
|
||||
return <ErrorBar message={message} severity={severity} onClose={onClearError} />;
|
||||
return <ErrorBarComponent message={message} severity={severity} onClose={onClearError} />;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
title: `${COMPONENT_FOLDER_PREFIX}/ErrorBar`,
|
||||
component: ErrorBar,
|
||||
title: `${COMPONENT_FOLDER_PREFIX}/Error Bar`,
|
||||
component: ErrorBarComponent,
|
||||
parameters: {
|
||||
docs: {
|
||||
page: () => getDocs()
|
||||
|
|
|
@ -12,10 +12,12 @@ import {
|
|||
mediaGalleryHeightOptions,
|
||||
COMPONENT_FOLDER_PREFIX
|
||||
} from '../constants';
|
||||
import { GridLayout, VideoTile, StreamMedia } from 'react-components';
|
||||
import { GridLayout as GridLayoutComponent, VideoTile, StreamMedia } from 'react-components';
|
||||
import { renderVideoStream } from '../utils';
|
||||
|
||||
export const GridLayoutComponent: () => JSX.Element = () => {
|
||||
// This must be the only named export from this module, and must be named to match the storybook path suffix.
|
||||
// This ensures that storybook hoists the story instead of creating a folder with a single entry.
|
||||
export const GridLayout: () => JSX.Element = () => {
|
||||
const width = number('Width', mediaGalleryWidthDefault, mediaGalleryWidthOptions);
|
||||
const height = number('Height', mediaGalleryHeightDefault, mediaGalleryHeightOptions);
|
||||
|
||||
|
@ -60,14 +62,14 @@ export const GridLayoutComponent: () => JSX.Element = () => {
|
|||
width: `${width}px`
|
||||
}}
|
||||
>
|
||||
<GridLayout>{participantsComponents}</GridLayout>
|
||||
<GridLayoutComponent>{participantsComponents}</GridLayoutComponent>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default {
|
||||
title: `${COMPONENT_FOLDER_PREFIX}/GridLayout`,
|
||||
component: GridLayout,
|
||||
title: `${COMPONENT_FOLDER_PREFIX}/Grid Layout`,
|
||||
component: GridLayoutComponent,
|
||||
parameters: {
|
||||
docs: {
|
||||
page: () => getDocs()
|
||||
|
|
|
@ -7,7 +7,7 @@ import { text } from '@storybook/addon-knobs';
|
|||
import { v1 as createGUID } from 'uuid';
|
||||
import { CommunicationIdentityClient, CommunicationUserToken } from '@azure/communication-administration';
|
||||
import { getDocs } from './GroupCallCompositeDocs';
|
||||
import { GroupCall } from 'react-composites';
|
||||
import { GroupCall as GroupCallComposite } from 'react-composites';
|
||||
import { COMPOSITE_FOLDER_PREFIX } from '../constants';
|
||||
import {
|
||||
CompositeConnectionParamsErrMessage,
|
||||
|
@ -16,8 +16,8 @@ import {
|
|||
} from '../CompositeStringUtils';
|
||||
|
||||
export default {
|
||||
title: `${COMPOSITE_FOLDER_PREFIX}/GroupCall`,
|
||||
component: GroupCall,
|
||||
title: `${COMPOSITE_FOLDER_PREFIX}/Group Call`,
|
||||
component: GroupCallComposite,
|
||||
parameters: {
|
||||
docs: {
|
||||
page: () => getDocs()
|
||||
|
@ -39,7 +39,9 @@ const createUserToken = async (connectionString: string): Promise<CommunicationU
|
|||
return token;
|
||||
};
|
||||
|
||||
export const GroupCallComposite: () => JSX.Element = () => {
|
||||
// This must be the only named export from this module, and must be named to match the storybook path suffix.
|
||||
// This ensures that storybook hoists the story instead of creating a folder with a single entry.
|
||||
export const GroupCall: () => JSX.Element = () => {
|
||||
const [userId, setUserId] = useState<string>('');
|
||||
const [groupId, setGroupId] = useState<string>('');
|
||||
const [token, setToken] = useState<string>('');
|
||||
|
@ -73,7 +75,7 @@ export const GroupCallComposite: () => JSX.Element = () => {
|
|||
}}
|
||||
>
|
||||
{connectionString && (
|
||||
<GroupCall
|
||||
<GroupCallComposite
|
||||
displayName={`user${Math.ceil(Math.random() * 1000)}`}
|
||||
userId={userId}
|
||||
groupId={groupId}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { text } from '@storybook/addon-knobs';
|
||||
import { getDocs } from './GroupChatCompositeDocs';
|
||||
import { ChatConfig, GroupChat } from 'react-composites';
|
||||
import { ChatConfig, GroupChat as GroupChatComposite } from 'react-composites';
|
||||
import { AzureCommunicationUserCredential } from '@azure/communication-common';
|
||||
import { CommunicationIdentityClient } from '@azure/communication-administration';
|
||||
import { ChatClient } from '@azure/communication-chat';
|
||||
|
@ -17,8 +17,8 @@ import {
|
|||
import { Meta } from '@storybook/react/types-6-0';
|
||||
|
||||
export default {
|
||||
title: `${COMPOSITE_FOLDER_PREFIX}/GroupChat`,
|
||||
component: GroupChat,
|
||||
title: `${COMPOSITE_FOLDER_PREFIX}/Group Chat`,
|
||||
component: GroupChatComposite,
|
||||
parameters: {
|
||||
useMaxHeightParent: true,
|
||||
useMaxWidthParent: true,
|
||||
|
@ -112,7 +112,9 @@ const createChatConfig = async (resourceConnectionString: string): Promise<ChatC
|
|||
};
|
||||
};
|
||||
|
||||
export const GroupChatComposite: () => JSX.Element = () => {
|
||||
// This must be the only named export from this module, and must be named to match the storybook path suffix.
|
||||
// This ensures that storybook hoists the story instead of creating a folder with a single entry.
|
||||
export const GroupChat: () => JSX.Element = () => {
|
||||
const [chatConfig, setChatConfig] = useState<ChatConfig>();
|
||||
|
||||
const connectionString = text(COMPOSITE_STRING_CONNECTIONSTRING, '', 'Server Simulator');
|
||||
|
@ -163,7 +165,7 @@ export const GroupChatComposite: () => JSX.Element = () => {
|
|||
padding: '0 10px'
|
||||
}}
|
||||
>
|
||||
{chatConfig && <GroupChat {...chatConfig} />}
|
||||
{chatConfig && <GroupChatComposite {...chatConfig} />}
|
||||
{!chatConfig && CompositeConnectionParamsErrMessage([emptyConfigTips, emptyConfigParametersTips])}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Meta } from '@storybook/react/types-6-0';
|
|||
import React, { useState } from 'react';
|
||||
import {
|
||||
MessageProps,
|
||||
MessageThread,
|
||||
MessageThread as MessageThreadComponent,
|
||||
ChatMessage,
|
||||
CustomMessage,
|
||||
SystemMessage,
|
||||
|
@ -27,7 +27,9 @@ import {
|
|||
} from './placeholdermessages';
|
||||
import { COMPONENT_FOLDER_PREFIX } from '../constants';
|
||||
|
||||
export const MessageThreadComponent: () => JSX.Element = () => {
|
||||
// This must be the only named export from this module, and must be named to match the storybook path suffix.
|
||||
// This ensures that storybook hoists the story instead of creating a folder with a single entry.
|
||||
export const MessageThread: () => JSX.Element = () => {
|
||||
const [chatMessages, setChatMessages] = useState<(SystemMessage | CustomMessage | ChatMessage)[]>(
|
||||
GenerateMockChatMessages()
|
||||
);
|
||||
|
@ -72,7 +74,7 @@ export const MessageThreadComponent: () => JSX.Element = () => {
|
|||
|
||||
return (
|
||||
<Stack style={MessageThreadContainerStyles}>
|
||||
<MessageThread
|
||||
<MessageThreadComponent
|
||||
styles={MessageThreadStyles}
|
||||
userId={UserOne.senderId}
|
||||
messages={chatMessages}
|
||||
|
@ -94,8 +96,8 @@ export const MessageThreadComponent: () => JSX.Element = () => {
|
|||
};
|
||||
|
||||
export default {
|
||||
title: `${COMPONENT_FOLDER_PREFIX}/MessageThread`,
|
||||
component: MessageThread,
|
||||
title: `${COMPONENT_FOLDER_PREFIX}/Message Thread`,
|
||||
component: MessageThreadComponent,
|
||||
parameters: {
|
||||
docs: {
|
||||
page: () => getDocs()
|
||||
|
|
|
@ -6,7 +6,7 @@ import { Meta } from '@storybook/react/types-6-0';
|
|||
import { text } from '@storybook/addon-knobs';
|
||||
import { CommunicationIdentityClient, CommunicationUserToken } from '@azure/communication-administration';
|
||||
import { getDocs } from './OneToOneCallCompositeDocs';
|
||||
import { OneToOneCall } from 'react-composites';
|
||||
import { OneToOneCall as OneToOneCallComposite } from 'react-composites';
|
||||
import { COMPOSITE_FOLDER_PREFIX } from '../constants';
|
||||
import {
|
||||
CompositeConnectionParamsErrMessage,
|
||||
|
@ -15,8 +15,8 @@ import {
|
|||
} from '../CompositeStringUtils';
|
||||
|
||||
export default {
|
||||
title: `${COMPOSITE_FOLDER_PREFIX}/OneToOneCall`,
|
||||
component: OneToOneCall,
|
||||
title: `${COMPOSITE_FOLDER_PREFIX}/One To One Call`,
|
||||
component: OneToOneCallComposite,
|
||||
parameters: {
|
||||
docs: {
|
||||
page: () => getDocs()
|
||||
|
@ -59,7 +59,7 @@ const OneToOneCallCompositeInstance: (token: string, calleeId?: string) => JSX.E
|
|||
return (
|
||||
<div style={experienceContainerStyle}>
|
||||
{requiredInformationObtained && (
|
||||
<OneToOneCall displayName={randomCallerName()} calleeId={calleeId} token={token} />
|
||||
<OneToOneCallComposite displayName={randomCallerName()} calleeId={calleeId} token={token} />
|
||||
)}
|
||||
{!requiredInformationObtained &&
|
||||
CompositeConnectionParamsErrMessage([
|
||||
|
@ -69,7 +69,9 @@ const OneToOneCallCompositeInstance: (token: string, calleeId?: string) => JSX.E
|
|||
);
|
||||
};
|
||||
|
||||
export const OneToOneCallComposite: () => JSX.Element = () => {
|
||||
// This must be the only named export from this module, and must be named to match the storybook path suffix.
|
||||
// This ensures that storybook hoists the story instead of creating a folder with a single entry.
|
||||
export const OneToOneCall: () => JSX.Element = () => {
|
||||
const [token, setToken] = useState<string>('');
|
||||
const [userId, setUserId] = useState<string>('');
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import React from 'react';
|
|||
// also exported from '@storybook/react' if you can deal with breaking changes in 6.1
|
||||
import { Meta } from '@storybook/react/types-6-0';
|
||||
import { boolean, text } from '@storybook/addon-knobs';
|
||||
import { ParticipantItem } from 'react-components';
|
||||
import { ParticipantItem as ParticipantItemComponent } from 'react-components';
|
||||
import { getDocs } from './ParticipantItemDocs';
|
||||
import { Stack } from '@fluentui/react';
|
||||
import { MicOffIcon, CallControlPresentNewIcon } from '@fluentui/react-northstar';
|
||||
|
@ -14,7 +14,9 @@ const onlyUnique = (value: string, index: number, self: string[]): boolean => {
|
|||
return self.indexOf(value) === index;
|
||||
};
|
||||
|
||||
export const ParticipantItemComponent: () => JSX.Element = () => {
|
||||
// This must be the only named export from this module, and must be named to match the storybook path suffix.
|
||||
// This ensures that storybook hoists the story instead of creating a folder with a single entry.
|
||||
export const ParticipantItem: () => JSX.Element = () => {
|
||||
const name = text('Name', 'Jim');
|
||||
const isScreenSharing = boolean('Is screen sharing', false);
|
||||
const isMuted = boolean('Is muted', false);
|
||||
|
@ -36,7 +38,7 @@ export const ParticipantItemComponent: () => JSX.Element = () => {
|
|||
|
||||
return (
|
||||
<div style={containerStyle}>
|
||||
<ParticipantItem
|
||||
<ParticipantItemComponent
|
||||
name={name}
|
||||
isYou={isYou}
|
||||
menuItems={menuItems}
|
||||
|
@ -52,8 +54,8 @@ export const ParticipantItemComponent: () => JSX.Element = () => {
|
|||
};
|
||||
|
||||
export default {
|
||||
title: `${COMPONENT_FOLDER_PREFIX}/ParticipantItem`,
|
||||
component: ParticipantItem,
|
||||
title: `${COMPONENT_FOLDER_PREFIX}/Participant Item`,
|
||||
component: ParticipantItemComponent,
|
||||
parameters: {
|
||||
docs: {
|
||||
page: () => getDocs()
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
// © Microsoft Corporation. All rights reserved.
|
||||
|
||||
import React from 'react';
|
||||
import { MessageStatus, ReadReceipt } from 'react-components';
|
||||
import { MessageStatus, ReadReceipt as ReadRecieptComponent } from 'react-components';
|
||||
import { select, text } from '@storybook/addon-knobs';
|
||||
import { getDocs } from './ReadReceiptDocs';
|
||||
import { COMPONENT_FOLDER_PREFIX } from '../constants';
|
||||
import { Meta } from '@storybook/react/types-6-0';
|
||||
|
||||
export default {
|
||||
title: `${COMPONENT_FOLDER_PREFIX}/ReadReceipt`,
|
||||
component: ReadReceipt,
|
||||
title: `${COMPONENT_FOLDER_PREFIX}/Read Receipt`,
|
||||
component: ReadRecieptComponent,
|
||||
parameters: {
|
||||
docs: {
|
||||
page: () => getDocs()
|
||||
|
@ -17,9 +17,11 @@ export default {
|
|||
}
|
||||
} as Meta;
|
||||
|
||||
export const ReadRecieptIconComponent = (): JSX.Element => {
|
||||
// This must be the only named export from this module, and must be named to match the storybook path suffix.
|
||||
// This ensures that storybook hoists the story instead of creating a folder with a single entry.
|
||||
export const ReadReceipt = (): JSX.Element => {
|
||||
return (
|
||||
<ReadReceipt
|
||||
<ReadRecieptComponent
|
||||
messageStatus={select<MessageStatus>('Message Status', ['delivered', 'sending', 'seen', 'failed'], 'delivered')}
|
||||
deliveredTooltipText={text('Delivered icon tooltip text', 'Sent')}
|
||||
sendingTooltipText={text('Sending icon tooltip text', 'Sending')}
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
import React from 'react';
|
||||
import { boolean, text } from '@storybook/addon-knobs';
|
||||
import { getDocs } from './SendBoxDocs';
|
||||
import { SendBox } from 'react-components';
|
||||
import { SendBox as SendBoxComponent } from 'react-components';
|
||||
import { COMPONENT_FOLDER_PREFIX } from '../constants';
|
||||
import { Meta } from '@storybook/react/types-6-0';
|
||||
|
||||
export default {
|
||||
title: `${COMPONENT_FOLDER_PREFIX}/SendBox`,
|
||||
component: SendBox,
|
||||
title: `${COMPONENT_FOLDER_PREFIX}/Send Box`,
|
||||
component: SendBoxComponent,
|
||||
parameters: {
|
||||
docs: {
|
||||
page: () => getDocs()
|
||||
|
@ -17,10 +17,12 @@ export default {
|
|||
}
|
||||
} as Meta;
|
||||
|
||||
export const SendBoxComponent = (): JSX.Element => {
|
||||
// This must be the only named export from this module, and must be named to match the storybook path suffix.
|
||||
// This ensures that storybook hoists the story instead of creating a folder with a single entry.
|
||||
export const SendBox = (): JSX.Element => {
|
||||
return (
|
||||
<div style={{ width: '31.25rem' }}>
|
||||
<SendBox
|
||||
<SendBoxComponent
|
||||
disabled={boolean('Block button from sending', false, 'Injected by ACS Context')}
|
||||
onMessageSend={async (message) => alert(`sent message: ${message} `)}
|
||||
onTyping={(): Promise<void> => {
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
// © Microsoft Corporation. All rights reserved.
|
||||
import { object, text, boolean } from '@storybook/addon-knobs';
|
||||
import { Meta } from '@storybook/react/types-6-0';
|
||||
import { TypingIndicator } from 'react-components';
|
||||
import { TypingIndicator as TypingIndicatorComponent } from 'react-components';
|
||||
import React from 'react';
|
||||
import { getDocs } from './TypingIndicatorDocs';
|
||||
import { COMPONENT_FOLDER_PREFIX } from '../constants';
|
||||
|
||||
export const TypingIndicatorComponent: () => JSX.Element = () => {
|
||||
// This must be the only named export from this module, and must be named to match the storybook path suffix.
|
||||
// This ensures that storybook hoists the story instead of creating a folder with a single entry.
|
||||
export const TypingIndicator: () => JSX.Element = () => {
|
||||
const typingUsers = object('Typing Users', [
|
||||
{
|
||||
userId: '1',
|
||||
|
@ -19,12 +21,12 @@ export const TypingIndicatorComponent: () => JSX.Element = () => {
|
|||
]);
|
||||
const overrideTypingString = boolean('Override typing string?', false);
|
||||
const typingString = overrideTypingString ? text('Typing String', ' are typing away...') : undefined;
|
||||
return <TypingIndicator typingUsers={typingUsers} typingString={typingString} />;
|
||||
return <TypingIndicatorComponent typingUsers={typingUsers} typingString={typingString} />;
|
||||
};
|
||||
|
||||
export default {
|
||||
title: `${COMPONENT_FOLDER_PREFIX}/TypingIndicator`,
|
||||
component: TypingIndicator,
|
||||
title: `${COMPONENT_FOLDER_PREFIX}/Typing Indicator`,
|
||||
component: TypingIndicatorComponent,
|
||||
parameters: {
|
||||
docs: {
|
||||
page: () => getDocs()
|
||||
|
|
|
@ -10,14 +10,16 @@ import {
|
|||
MicrophoneButton,
|
||||
OptionsButton,
|
||||
StreamMedia,
|
||||
VideoTile
|
||||
VideoTile as VideoTileComponent
|
||||
} from 'react-components';
|
||||
import { text, boolean, number } from '@storybook/addon-knobs';
|
||||
import { renderVideoStream } from '../utils';
|
||||
import { getDocs } from './VideoTileDocs';
|
||||
import { COMPONENT_FOLDER_PREFIX } from '../constants';
|
||||
|
||||
export const VideoTileComponent: () => JSX.Element = () => {
|
||||
// This must be the only named export from this module, and must be named to match the storybook path suffix.
|
||||
// This ensures that storybook hoists the story instead of creating a folder with a single entry.
|
||||
export const VideoTile: () => JSX.Element = () => {
|
||||
const avatarName = text('Avatar Name', 'John Krasinski');
|
||||
const isVideoReady = boolean('Is Video Ready', false);
|
||||
const showControlBarComponent = boolean('Show Control Bar (Not a part of this component)', false);
|
||||
|
@ -36,7 +38,7 @@ export const VideoTileComponent: () => JSX.Element = () => {
|
|||
});
|
||||
|
||||
return (
|
||||
<VideoTile
|
||||
<VideoTileComponent
|
||||
isVideoReady={isVideoReady}
|
||||
videoProvider={<StreamMedia videoStreamElement={renderVideoStream()} />}
|
||||
avatarName={avatarName}
|
||||
|
@ -55,13 +57,13 @@ export const VideoTileComponent: () => JSX.Element = () => {
|
|||
</ControlBar>
|
||||
</Stack>
|
||||
)}
|
||||
</VideoTile>
|
||||
</VideoTileComponent>
|
||||
);
|
||||
};
|
||||
|
||||
export default {
|
||||
title: `${COMPONENT_FOLDER_PREFIX}/VideoTile`,
|
||||
component: VideoTile,
|
||||
title: `${COMPONENT_FOLDER_PREFIX}/Video Tile`,
|
||||
component: VideoTileComponent,
|
||||
parameters: {
|
||||
docs: {
|
||||
page: () => getDocs()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`storybook snapshot tests Storyshots Composites/GroupCall Group Call Composite 1`] = `
|
||||
exports[`storybook snapshot tests Storyshots Composites/Group Call Group Call 1`] = `
|
||||
<div
|
||||
className="css-75 root-0 body-1"
|
||||
>
|
||||
|
@ -51,7 +51,7 @@ exports[`storybook snapshot tests Storyshots Composites/GroupCall Group Call Com
|
|||
</div>
|
||||
`;
|
||||
|
||||
exports[`storybook snapshot tests Storyshots Composites/GroupChat Group Chat Composite 1`] = `
|
||||
exports[`storybook snapshot tests Storyshots Composites/Group Chat Group Chat 1`] = `
|
||||
<div
|
||||
className="css-75 root-0 body-1"
|
||||
>
|
||||
|
@ -105,7 +105,7 @@ exports[`storybook snapshot tests Storyshots Composites/GroupChat Group Chat Com
|
|||
</div>
|
||||
`;
|
||||
|
||||
exports[`storybook snapshot tests Storyshots Composites/OneToOneCall One To One Call Composite 1`] = `
|
||||
exports[`storybook snapshot tests Storyshots Composites/One To One Call One To One Call 1`] = `
|
||||
<div
|
||||
className="css-75 root-0 body-1"
|
||||
>
|
||||
|
@ -1082,7 +1082,7 @@ exports[`storybook snapshot tests Storyshots Settings/Manage Cookies Manage Cook
|
|||
</div>
|
||||
`;
|
||||
|
||||
exports[`storybook snapshot tests Storyshots UI Components/ReadReceipt Read Reciept Icon Component 1`] = `
|
||||
exports[`storybook snapshot tests Storyshots UI Components/Read Receipt Read Receipt 1`] = `
|
||||
<div
|
||||
className="css-75 root-0 body-1"
|
||||
>
|
||||
|
|
Загрузка…
Ссылка в новой задаче