зеркало из
1
0
Форкнуть 0

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:
Prathmesh Prabhu 2021-05-05 11:50:59 -07:00 коммит произвёл GitHub
Родитель 08fc8fbca3
Коммит 427648c23c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
12 изменённых файлов: 82 добавлений и 60 удалений

Просмотреть файл

@ -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"
>