Browse Source

Migrated Storybook notation from CSF2 to CSF3 (#3412)

* Migrate web action-buttons directory to CSF3 notation

* Migrate web chat directory to CSF3 notation

* Migrate web common directory to CSF3 notation

* Migrate web layout directory to CSF3 notation

* Migrate web modals directory to CSF3 notation

* Migrate web ui directory to CSF3 notation

* Migrate web video directory to CSF3 notation

* Migrate web stories directory to CSF3 notation
pull/3414/head
kame 2 years ago committed by GitHub
parent
commit
4f078e1ee4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 54
      web/components/action-buttons/ActionButton/ActionButton.stories.tsx
  2. 55
      web/components/action-buttons/ActionButtonMenu/ActionButtonMenu.stories.tsx
  3. 23
      web/components/action-buttons/ActionButtonRow/ActionButtonRow.stories.tsx
  4. 16
      web/components/chat/ChatActionMessage/ChatActionMessage.stories.tsx
  5. 75
      web/components/chat/ChatContainer/ChatContainer.stories.tsx
  6. 31
      web/components/chat/ChatJoinMessage/ChatJoinMessage.stories.tsx
  7. 17
      web/components/chat/ChatModerationActionMenu/ChatModerationActionMenu.stories.tsx
  8. 17
      web/components/chat/ChatModerationDetailsModal/ChatModerationDetailsModal.stories.tsx
  9. 15
      web/components/chat/ChatModeratorNotification/ChatModeratorNotification.stories.tsx
  10. 26
      web/components/chat/ChatNameChangeMessage/ChatNameChangeMessage.stories.tsx
  11. 31
      web/components/chat/ChatPartMessage/ChatPartMessage.stories.tsx
  12. 94
      web/components/chat/ChatSocialMessage/ChatSocialMessage.stories.tsx
  13. 26
      web/components/chat/ChatSystemMessage/ChatSystemMessage.stories.tsx
  14. 62
      web/components/chat/ChatTextField/ChatTextField.stories.tsx
  15. 56
      web/components/chat/ChatUserBadge/ChatUserBadge.stories.tsx
  16. 96
      web/components/chat/ChatUserMessage/ChatUserMessage.stories.tsx
  17. 133
      web/components/common/ContentHeader/ContentHeader.stories.tsx
  18. 25
      web/components/common/OwncastLogo/OwncastLogo.stories.tsx
  19. 21
      web/components/common/UserDropdown/UserDropdown.stories.tsx
  20. 106
      web/components/layouts/Main/Main.stories.tsx
  21. 17
      web/components/modals/AuthModal/AuthModal.stories.tsx
  22. 17
      web/components/modals/BrowserNotifyModal/BrowserNotifyModal.stories.tsx
  23. 41
      web/components/modals/ChatModal/ChatModal.stories.tsx
  24. 22
      web/components/modals/FatalErrorStateModal/FatalErrorStateModal.stories.tsx
  25. 31
      web/components/modals/FediAuthModal/FediAuthModal.stories.tsx
  26. 17
      web/components/modals/FollowModal/FollowModal.stories.tsx
  27. 17
      web/components/modals/IndieAuthModal/IndieAuthModal.stories.tsx
  28. 16
      web/components/modals/NameChangeModal/NameChangeModal.stories.tsx
  29. 47
      web/components/ui/ComponentError/ComponentError.stories.tsx
  30. 38
      web/components/ui/CustomPageContent/CustomPageContent.stories.tsx
  31. 21
      web/components/ui/Footer/Footer.stories.tsx
  32. 33
      web/components/ui/Header/Header.stories.tsx
  33. 37
      web/components/ui/Modal/Modal.stories.tsx
  34. 39
      web/components/ui/NotifyReminderPopup/NotifyReminderPopup.stories.tsx
  35. 97
      web/components/ui/OfflineBanner/OfflineBanner.stories.tsx
  36. 57
      web/components/ui/SocialLinks/SocialLinks.stories.tsx
  37. 29
      web/components/ui/Statusbar/StatusBar.stories.tsx
  38. 29
      web/components/ui/followers/FollowerCollection/FollowerCollection.stories.tsx
  39. 26
      web/components/ui/followers/SingleFollower/SingleFollower.stories.tsx
  40. 24
      web/components/video/OwncastPlayer/OwncastPlayer.stories.tsx
  41. 44
      web/components/video/VideoPoster/VideoPoster.stories.tsx
  42. 32
      web/stories/PageLogo.stories.tsx
  43. 18
      web/stories/ReadonlyChat.stories.tsx
  44. 18
      web/stories/ReadwriteChat.stories.tsx

54
web/components/action-buttons/ActionButton/ActionButton.stories.tsx

@ -1,9 +1,8 @@ @@ -1,9 +1,8 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { StoryFn, Meta } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { ActionButton } from './ActionButton';
export default {
const meta = {
title: 'owncast/Components/Action Buttons/Single button',
component: ActionButton,
parameters: {
@ -13,38 +12,45 @@ export default { @@ -13,38 +12,45 @@ export default {
},
},
},
} as ComponentMeta<typeof ActionButton>;
} satisfies Meta<typeof ActionButton>;
export default meta;
const itemSelected = a => {
console.log('itemSelected', a);
action(a.title);
};
const Template: ComponentStory<typeof ActionButton> = args => (
const Template: StoryFn<typeof ActionButton> = args => (
<ActionButton externalActionSelected={itemSelected} {...args} />
);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const Example1 = Template.bind({});
Example1.args = {
action: {
url: 'https://owncast.online/docs',
title: 'Documentation',
description: 'Owncast Documentation',
icon: 'https://owncast.online/images/logo.svg',
color: '#5232c8',
openExternally: false,
export const Example1 = {
render: Template,
args: {
action: {
url: 'https://owncast.online/docs',
title: 'Documentation',
description: 'Owncast Documentation',
icon: 'https://owncast.online/images/logo.svg',
color: '#5232c8',
openExternally: false,
},
},
};
export const Example2 = Template.bind({});
Example2.args = {
action: {
url: 'https://opencollective.com/embed/owncast/donate',
title: 'Support Owncast',
description: 'Contribute to Owncast',
icon: 'https://opencollective.com/static/images/opencollective-icon.svg',
color: '#2b4863',
openExternally: false,
export const Example2 = {
render: Template,
args: {
action: {
url: 'https://opencollective.com/embed/owncast/donate',
title: 'Support Owncast',
description: 'Contribute to Owncast',
icon: 'https://opencollective.com/static/images/opencollective-icon.svg',
color: '#2b4863',
openExternally: false,
},
},
};

55
web/components/action-buttons/ActionButtonMenu/ActionButtonMenu.stories.tsx

@ -1,20 +1,21 @@ @@ -1,20 +1,21 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { StoryFn, Meta } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { ActionButtonMenu } from './ActionButtonMenu';
export default {
const meta = {
title: 'owncast/Components/Action Buttons/Action Menu',
component: ActionButtonMenu,
parameters: {},
} as ComponentMeta<typeof ActionButtonMenu>;
} satisfies Meta<typeof ActionButtonMenu>;
export default meta;
const itemSelected = a => {
console.log('itemSelected', a);
action(a.title);
};
const Template: ComponentStory<typeof ActionButtonMenu> = args => (
const Template: StoryFn<typeof ActionButtonMenu> = args => (
<ActionButtonMenu {...args} externalActionSelected={a => itemSelected(a)} />
);
@ -37,26 +38,38 @@ const actions = [ @@ -37,26 +38,38 @@ const actions = [
},
];
export const Example = Template.bind({});
Example.args = {
actions,
export const Example = {
render: Template,
args: {
actions,
},
};
export const ShowFollowExample = Template.bind({});
ShowFollowExample.args = {
actions,
showFollowItem: true,
export const ShowFollowExample = {
render: Template,
args: {
actions,
showFollowItem: true,
},
};
export const ShowNotifyExample = Template.bind({});
ShowNotifyExample.args = {
actions,
showNotifyItem: true,
export const ShowNotifyExample = {
render: Template,
args: {
actions,
showNotifyItem: true,
},
};
export const ShowNotifyAndFollowExample = Template.bind({});
ShowNotifyAndFollowExample.args = {
actions,
showNotifyItem: true,
showFollowItem: true,
export const ShowNotifyAndFollowExample = {
render: Template,
args: {
actions,
showNotifyItem: true,
showFollowItem: true,
},
};

23
web/components/action-buttons/ActionButtonRow/ActionButtonRow.stories.tsx

@ -1,10 +1,9 @@ @@ -1,10 +1,9 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { StoryFn, Meta } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { ActionButtonRow } from './ActionButtonRow';
import { ActionButton } from '../ActionButton/ActionButton';
export default {
const meta = {
title: 'owncast/Components/Action Buttons/Buttons Row',
component: ActionButtonRow,
parameters: {
@ -15,15 +14,15 @@ export default { @@ -15,15 +14,15 @@ export default {
},
},
},
} as ComponentMeta<typeof ActionButtonRow>;
} satisfies Meta<typeof ActionButtonRow>;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const Template: ComponentStory<typeof ActionButtonRow> = args => {
export default meta;
const Template: StoryFn<typeof ActionButtonRow> = args => {
const { buttons } = args as any;
return <ActionButtonRow>{buttons}</ActionButtonRow>;
};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const actions = [
{
url: 'https://owncast.online/docs',
@ -49,7 +48,11 @@ const itemSelected = a => { @@ -49,7 +48,11 @@ const itemSelected = a => {
};
const buttons = actions.map(a => <ActionButton externalActionSelected={itemSelected} action={a} />);
export const Example1 = Template.bind({});
Example1.args = {
buttons,
export const Example1 = {
render: Template,
args: {
buttons,
},
};

16
web/components/chat/ChatActionMessage/ChatActionMessage.stories.tsx

@ -1,9 +1,8 @@ @@ -1,9 +1,8 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Meta } from '@storybook/react';
import { ChatActionMessage } from './ChatActionMessage';
import Mock from '../../../stories/assets/mocks/chatmessage-action.png';
export default {
const meta = {
title: 'owncast/Chat/Messages/Chat action',
component: ChatActionMessage,
parameters: {
@ -17,11 +16,12 @@ export default { @@ -17,11 +16,12 @@ export default {
},
},
},
} as ComponentMeta<typeof ChatActionMessage>;
} satisfies Meta<typeof ChatActionMessage>;
const Template: ComponentStory<typeof ChatActionMessage> = args => <ChatActionMessage {...args} />;
export default meta;
export const Basic = Template.bind({});
Basic.args = {
body: 'This is a basic action message.',
export const Basic = {
args: {
body: 'This is a basic action message.',
},
};

75
web/components/chat/ChatContainer/ChatContainer.stories.tsx

@ -1,10 +1,10 @@ @@ -1,10 +1,10 @@
import React, { useState } from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { useState } from 'react';
import { StoryFn, Meta } from '@storybook/react';
import { RecoilRoot } from 'recoil';
import { ChatContainer } from './ChatContainer';
import { ChatMessage } from '../../../interfaces/chat-message.model';
export default {
const meta = {
title: 'owncast/Chat/Chat messages container',
component: ChatContainer,
parameters: {
@ -19,7 +19,9 @@ export default { @@ -19,7 +19,9 @@ export default {
},
},
},
} as ComponentMeta<typeof ChatContainer>;
} satisfies Meta<typeof ChatContainer>;
export default meta;
const testMessages = `[
{
@ -586,37 +588,46 @@ const AddMessagesChatExample = args => { @@ -586,37 +588,46 @@ const AddMessagesChatExample = args => {
);
};
const Template: ComponentStory<typeof ChatContainer> = args => <AddMessagesChatExample {...args} />;
const Template: StoryFn<typeof ChatContainer> = args => <AddMessagesChatExample {...args} />;
export const Example = {
render: Template,
export const Example = Template.bind({});
Example.args = {
loading: false,
messages,
usernameToHighlight: 'testuser',
chatUserId: 'testuser',
isModerator: true,
showInput: true,
chatAvailable: true,
args: {
loading: false,
messages,
usernameToHighlight: 'testuser',
chatUserId: 'testuser',
isModerator: true,
showInput: true,
chatAvailable: true,
},
};
export const ChatDisabled = Template.bind({});
ChatDisabled.args = {
loading: false,
messages,
usernameToHighlight: 'testuser',
chatUserId: 'testuser',
isModerator: true,
showInput: true,
chatAvailable: false,
export const ChatDisabled = {
render: Template,
args: {
loading: false,
messages,
usernameToHighlight: 'testuser',
chatUserId: 'testuser',
isModerator: true,
showInput: true,
chatAvailable: false,
},
};
export const SingleMessage = Template.bind({});
SingleMessage.args = {
loading: false,
messages: [messages[0]],
usernameToHighlight: 'testuser',
chatUserId: 'testuser',
isModerator: true,
showInput: true,
chatAvailable: true,
export const SingleMessage = {
render: Template,
args: {
loading: false,
messages: [messages[0]],
usernameToHighlight: 'testuser',
chatUserId: 'testuser',
isModerator: true,
showInput: true,
chatAvailable: true,
},
};

31
web/components/chat/ChatJoinMessage/ChatJoinMessage.stories.tsx

@ -1,9 +1,8 @@ @@ -1,9 +1,8 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Meta } from '@storybook/react';
import { ChatJoinMessage } from './ChatJoinMessage';
import Mock from '../../../stories/assets/mocks/chatmessage-action.png';
export default {
const meta = {
title: 'owncast/Chat/Messages/Chat Join',
component: ChatJoinMessage,
argTypes: {
@ -23,20 +22,22 @@ export default { @@ -23,20 +22,22 @@ export default {
},
},
},
} as ComponentMeta<typeof ChatJoinMessage>;
} satisfies Meta<typeof ChatJoinMessage>;
const Template: ComponentStory<typeof ChatJoinMessage> = args => <ChatJoinMessage {...args} />;
export default meta;
export const Regular = Template.bind({});
Regular.args = {
displayName: 'RandomChatter',
isAuthorModerator: false,
userColor: 3,
export const Regular = {
args: {
displayName: 'RandomChatter',
isAuthorModerator: false,
userColor: 3,
},
};
export const Moderator = Template.bind({});
Moderator.args = {
displayName: 'RandomChatter',
isAuthorModerator: true,
userColor: 2,
export const Moderator = {
args: {
displayName: 'RandomChatter',
isAuthorModerator: true,
userColor: 2,
},
};

17
web/components/chat/ChatModerationActionMenu/ChatModerationActionMenu.stories.tsx

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { StoryFn, Meta } from '@storybook/react';
import { RecoilRoot } from 'recoil';
import { ChatModerationActionMenu } from './ChatModerationActionMenu';
@ -64,7 +63,7 @@ const mocks = { @@ -64,7 +63,7 @@ const mocks = {
],
};
export default {
const meta = {
title: 'owncast/Chat/Moderation menu',
component: ChatModerationActionMenu,
parameters: {
@ -79,10 +78,11 @@ export default { @@ -79,10 +78,11 @@ export default {
},
},
},
} as ComponentMeta<typeof ChatModerationActionMenu>;
} satisfies Meta<typeof ChatModerationActionMenu>;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const Template: ComponentStory<typeof ChatModerationActionMenu> = () => (
export default meta;
const Template: StoryFn<typeof ChatModerationActionMenu> = () => (
<RecoilRoot>
<ChatModerationActionMenu
accessToken="abc123"
@ -93,5 +93,6 @@ const Template: ComponentStory<typeof ChatModerationActionMenu> = () => ( @@ -93,5 +93,6 @@ const Template: ComponentStory<typeof ChatModerationActionMenu> = () => (
</RecoilRoot>
);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const Basic = Template.bind({});
export const Basic = {
render: Template,
};

17
web/components/chat/ChatModerationDetailsModal/ChatModerationDetailsModal.stories.tsx

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { StoryFn, Meta } from '@storybook/react';
import { RecoilRoot } from 'recoil';
import { ChatModerationDetailsModal } from './ChatModerationDetailsModal';
@ -64,7 +63,7 @@ const mocks = { @@ -64,7 +63,7 @@ const mocks = {
],
};
export default {
const meta = {
title: 'owncast/Chat/Moderation modal',
component: ChatModerationDetailsModal,
parameters: {
@ -79,14 +78,16 @@ export default { @@ -79,14 +78,16 @@ export default {
},
},
},
} as ComponentMeta<typeof ChatModerationDetailsModal>;
} satisfies Meta<typeof ChatModerationDetailsModal>;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const Template: ComponentStory<typeof ChatModerationDetailsModal> = () => (
export default meta;
const Template: StoryFn<typeof ChatModerationDetailsModal> = () => (
<RecoilRoot>
<ChatModerationDetailsModal userId="testuser123" accessToken="fakeaccesstoken4839" />
</RecoilRoot>
);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const Example = Template.bind({});
export const Example = {
render: Template,
};

15
web/components/chat/ChatModeratorNotification/ChatModeratorNotification.stories.tsx

@ -1,17 +1,12 @@ @@ -1,17 +1,12 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Meta } from '@storybook/react';
import { ChatModeratorNotification } from './ChatModeratorNotification';
export default {
const meta = {
title: 'owncast/Chat/Messages/Moderation Role Notification',
component: ChatModeratorNotification,
parameters: {},
} as ComponentMeta<typeof ChatModeratorNotification>;
} satisfies Meta<typeof ChatModeratorNotification>;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const Template: ComponentStory<typeof ChatModeratorNotification> = (args: object) => (
<ChatModeratorNotification {...args} />
);
export default meta;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const Basic = Template.bind({});
export const Basic = {};

26
web/components/chat/ChatNameChangeMessage/ChatNameChangeMessage.stories.tsx

@ -1,23 +1,21 @@ @@ -1,23 +1,21 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Meta } from '@storybook/react';
import { ChatNameChangeMessage } from './ChatNameChangeMessage';
export default {
const meta = {
title: 'owncast/Chat/Messages/Chat name change',
component: ChatNameChangeMessage,
} as ComponentMeta<typeof ChatNameChangeMessage>;
} satisfies Meta<typeof ChatNameChangeMessage>;
const Template: ComponentStory<typeof ChatNameChangeMessage> = args => (
<ChatNameChangeMessage {...args} />
);
export default meta;
export const Basic = Template.bind({});
Basic.args = {
message: {
oldName: 'JohnnyOldName',
user: {
displayName: 'JohnnyNewName',
displayColor: '3',
export const Basic = {
args: {
message: {
oldName: 'JohnnyOldName',
user: {
displayName: 'JohnnyNewName',
displayColor: '3',
},
},
},
};

31
web/components/chat/ChatPartMessage/ChatPartMessage.stories.tsx

@ -1,9 +1,8 @@ @@ -1,9 +1,8 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Meta } from '@storybook/react';
import { ChatPartMessage } from './ChatPartMessage';
import Mock from '../../../stories/assets/mocks/chatmessage-action.png';
export default {
const meta = {
title: 'owncast/Chat/Messages/Chat Part',
component: ChatPartMessage,
argTypes: {
@ -23,20 +22,22 @@ export default { @@ -23,20 +22,22 @@ export default {
},
},
},
} as ComponentMeta<typeof ChatPartMessage>;
} satisfies Meta<typeof ChatPartMessage>;
const Template: ComponentStory<typeof ChatPartMessage> = args => <ChatPartMessage {...args} />;
export default meta;
export const Regular = Template.bind({});
Regular.args = {
displayName: 'RandomChatter',
isAuthorModerator: false,
userColor: 3,
export const Regular = {
args: {
displayName: 'RandomChatter',
isAuthorModerator: false,
userColor: 3,
},
};
export const Moderator = Template.bind({});
Moderator.args = {
displayName: 'RandomChatter',
isAuthorModerator: true,
userColor: 2,
export const Moderator = {
args: {
displayName: 'RandomChatter',
isAuthorModerator: true,
userColor: 2,
},
};

94
web/components/chat/ChatSocialMessage/ChatSocialMessage.stories.tsx

@ -1,66 +1,70 @@ @@ -1,66 +1,70 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Meta } from '@storybook/react';
import { ChatSocialMessage } from './ChatSocialMessage';
export default {
const meta = {
title: 'owncast/Chat/Messages/Social-fediverse event',
component: ChatSocialMessage,
parameters: {},
} as ComponentMeta<typeof ChatSocialMessage>;
} satisfies Meta<typeof ChatSocialMessage>;
const Template: ComponentStory<typeof ChatSocialMessage> = args => <ChatSocialMessage {...args} />;
export default meta;
export const Follow = Template.bind({});
Follow.args = {
message: {
type: 'FEDIVERSE_ENGAGEMENT_FOLLOW',
body: '<p>james followed this live stream.</p>',
title: 'james@mastodon.social',
image: 'https://mastodon.social/avatars/original/missing.png',
link: 'https://mastodon.social/@james',
export const Follow = {
args: {
message: {
type: 'FEDIVERSE_ENGAGEMENT_FOLLOW',
body: '<p>james followed this live stream.</p>',
title: 'james@mastodon.social',
image: 'https://mastodon.social/avatars/original/missing.png',
link: 'https://mastodon.social/@james',
},
},
};
export const Like = Template.bind({});
Like.args = {
message: {
type: 'FEDIVERSE_ENGAGEMENT_LIKE',
body: '<p>james liked that this stream went live.</p>',
title: 'james@mastodon.social',
image: 'https://mastodon.social/avatars/original/missing.png',
link: 'https://mastodon.social/@james',
export const Like = {
args: {
message: {
type: 'FEDIVERSE_ENGAGEMENT_LIKE',
body: '<p>james liked that this stream went live.</p>',
title: 'james@mastodon.social',
image: 'https://mastodon.social/avatars/original/missing.png',
link: 'https://mastodon.social/@james',
},
},
};
export const Repost = Template.bind({});
Repost.args = {
message: {
type: 'FEDIVERSE_ENGAGEMENT_REPOST',
body: '<p>james shared this stream with their followers.</p>',
title: 'james@mastodon.social',
image: 'https://mastodon.social/avatars/original/missing.png',
link: 'https://mastodon.social/@james',
export const Repost = {
args: {
message: {
type: 'FEDIVERSE_ENGAGEMENT_REPOST',
body: '<p>james shared this stream with their followers.</p>',
title: 'james@mastodon.social',
image: 'https://mastodon.social/avatars/original/missing.png',
link: 'https://mastodon.social/@james',
},
},
};
export const LongAccountName = Template.bind({});
LongAccountName.args = {
message: {
type: 'FEDIVERSE_ENGAGEMENT_REPOST',
body: '<p>james shared this stream with their followers.</p>',
title: 'littlejimmywilliams@technology.biz.net.org.technology.gov',
image: 'https://mastodon.social/avatars/original/missing.png',
link: 'https://mastodon.social/@james',
export const LongAccountName = {
args: {
message: {
type: 'FEDIVERSE_ENGAGEMENT_REPOST',
body: '<p>james shared this stream with their followers.</p>',
title: 'littlejimmywilliams@technology.biz.net.org.technology.gov',
image: 'https://mastodon.social/avatars/original/missing.png',
link: 'https://mastodon.social/@james',
},
},
};
export const InvalidAvatarImage = Template.bind({});
InvalidAvatarImage.args = {
message: {
type: 'FEDIVERSE_ENGAGEMENT_REPOST',
body: '<p>james shared this stream with their followers.</p>',
title: 'james@mastodon.social',
image: 'https://xx.xx/avatars/original/missing.png',
link: 'https://mastodon.social/@james',
export const InvalidAvatarImage = {
args: {
message: {
type: 'FEDIVERSE_ENGAGEMENT_REPOST',
body: '<p>james shared this stream with their followers.</p>',
title: 'james@mastodon.social',
image: 'https://xx.xx/avatars/original/missing.png',
link: 'https://mastodon.social/@james',
},
},
};

26
web/components/chat/ChatSystemMessage/ChatSystemMessage.stories.tsx

@ -1,10 +1,9 @@ @@ -1,10 +1,9 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Meta } from '@storybook/react';
import { ChatSystemMessage } from './ChatSystemMessage';
import Mock from '../../../stories/assets/mocks/chatmessage-system.png';
import { ChatMessage } from '../../../interfaces/chat-message.model';
export default {
const meta = {
title: 'owncast/Chat/Messages/System',
component: ChatSystemMessage,
parameters: {
@ -18,9 +17,9 @@ export default { @@ -18,9 +17,9 @@ export default {
},
},
},
} as ComponentMeta<typeof ChatSystemMessage>;
} satisfies Meta<typeof ChatSystemMessage>;
const Template: ComponentStory<typeof ChatSystemMessage> = args => <ChatSystemMessage {...args} />;
export default meta;
const message: ChatMessage = JSON.parse(`{
"type": "SYSTEM",
@ -34,14 +33,15 @@ const message: ChatMessage = JSON.parse(`{ @@ -34,14 +33,15 @@ const message: ChatMessage = JSON.parse(`{
},
"body": "Test system message from the chat server."}`);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const Basic = Template.bind({});
Basic.args = {
message,
export const Basic = {
args: {
message,
},
};
export const HighlightExample = Template.bind({});
HighlightExample.args = {
message,
highlightString: 'chat',
export const HighlightExample = {
args: {
message,
highlightString: 'chat',
},
};

62
web/components/chat/ChatTextField/ChatTextField.stories.tsx

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { StoryFn, Meta } from '@storybook/react';
import { RecoilRoot } from 'recoil';
import { ChatTextField } from './ChatTextField';
import Mockup from '../../../stories/assets/mocks/chatinput-mock.png';
@ -28,7 +27,7 @@ const mocks = { @@ -28,7 +27,7 @@ const mocks = {
],
};
export default {
const meta = {
title: 'owncast/Chat/Input text field',
component: ChatTextField,
parameters: {
@ -48,43 +47,54 @@ export default { @@ -48,43 +47,54 @@ export default {
},
},
},
} as ComponentMeta<typeof ChatTextField>;
} satisfies Meta<typeof ChatTextField>;
const Template: ComponentStory<typeof ChatTextField> = args => (
export default meta;
const Template: StoryFn<typeof ChatTextField> = args => (
<RecoilRoot>
<ChatTextField {...args} />
</RecoilRoot>
);
export const Example = Template.bind({});
Example.args = {
enabled: true,
};
export const Example = {
render: Template,
export const LongerMessage = Template.bind({});
LongerMessage.args = {
enabled: true,
defaultText:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
args: {
enabled: true,
},
};
LongerMessage.parameters = {
docs: {
description: {
story: 'Should display two lines of text and scroll to display more.',
export const LongerMessage = {
render: Template,
args: {
enabled: true,
defaultText:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
},
parameters: {
docs: {
description: {
story: 'Should display two lines of text and scroll to display more.',
},
},
},
};
export const DisabledChat = Template.bind({});
DisabledChat.args = {
enabled: false,
};
export const DisabledChat = {
render: Template,
args: {
enabled: false,
},
DisabledChat.parameters = {
docs: {
description: {
story: 'Should not allow you to type anything and should state that chat is disabled.',
parameters: {
docs: {
description: {
story: 'Should not allow you to type anything and should state that chat is disabled.',
},
},
},
};

56
web/components/chat/ChatUserBadge/ChatUserBadge.stories.tsx

@ -1,11 +1,10 @@ @@ -1,11 +1,10 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { StoryFn, Meta } from '@storybook/react';
import { ChatUserBadge } from './ChatUserBadge';
import { ModerationBadge } from './ModerationBadge';
import { AuthedUserBadge } from './AuthedUserBadge';
import { BotUserBadge } from './BotUserBadge';
export default {
const meta = {
title: 'owncast/Chat/Messages/User Flag',
component: ChatUserBadge,
argTypes: {
@ -14,36 +13,43 @@ export default { @@ -14,36 +13,43 @@ export default {
control: { type: 'select' },
},
},
} as ComponentMeta<typeof ChatUserBadge>;
} satisfies Meta<typeof ChatUserBadge>;
const Template: ComponentStory<typeof ChatUserBadge> = args => <ChatUserBadge {...args} />;
const ModerationTemplate: ComponentStory<typeof ModerationBadge> = args => (
<ModerationBadge {...args} />
);
export default meta;
const AuthedTemplate: ComponentStory<typeof ModerationBadge> = args => (
<AuthedUserBadge {...args} />
);
const ModerationTemplate: StoryFn<typeof ModerationBadge> = args => <ModerationBadge {...args} />;
const BotTemplate: ComponentStory<typeof BotUserBadge> = args => <BotUserBadge {...args} />;
const AuthedTemplate: StoryFn<typeof ModerationBadge> = args => <AuthedUserBadge {...args} />;
export const Authenticated = AuthedTemplate.bind({});
Authenticated.args = {
userColor: '3',
const BotTemplate: StoryFn<typeof BotUserBadge> = args => <BotUserBadge {...args} />;
export const Authenticated = {
render: AuthedTemplate,
args: {
userColor: '3',
},
};
export const Moderator = ModerationTemplate.bind({});
Moderator.args = {
userColor: '5',
export const Moderator = {
render: ModerationTemplate,
args: {
userColor: '5',
},
};
export const Bot = BotTemplate.bind({});
Bot.args = {
userColor: '7',
export const Bot = {
render: BotTemplate,
args: {
userColor: '7',
},
};
export const Generic = Template.bind({});
Generic.args = {
badge: '?',
userColor: '6',
export const Generic = {
args: {
badge: '?',
userColor: '6',
},
};

96
web/components/chat/ChatUserMessage/ChatUserMessage.stories.tsx

@ -1,11 +1,10 @@ @@ -1,11 +1,10 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { StoryFn, Meta } from '@storybook/react';
import { RecoilRoot } from 'recoil';
import { ChatUserMessage } from './ChatUserMessage';
import { ChatMessage } from '../../../interfaces/chat-message.model';
import Mock from '../../../stories/assets/mocks/chatmessage-user.png';
export default {
const meta = {
title: 'owncast/Chat/Messages/Standard user',
component: ChatUserMessage,
parameters: {
@ -20,9 +19,11 @@ export default { @@ -20,9 +19,11 @@ export default {
},
},
},
} as ComponentMeta<typeof ChatUserMessage>;
} satisfies Meta<typeof ChatUserMessage>;
const Template: ComponentStory<typeof ChatUserMessage> = args => (
export default meta;
const Template: StoryFn<typeof ChatUserMessage> = args => (
<RecoilRoot>
<ChatUserMessage {...args} />
</RecoilRoot>
@ -105,48 +106,69 @@ const botUserMessage: ChatMessage = JSON.parse(`{ @@ -105,48 +106,69 @@ const botUserMessage: ChatMessage = JSON.parse(`{
},
"body": "I am a bot."}`);
export const WithoutModeratorMenu = Template.bind({});
WithoutModeratorMenu.args = {
message: standardMessage,
showModeratorMenu: false,
export const WithoutModeratorMenu = {
render: Template,
args: {
message: standardMessage,
showModeratorMenu: false,
},
};
export const WithLinkAndCustomEmoji = Template.bind({});
WithLinkAndCustomEmoji.args = {
message: messageWithLinkAndCustomEmoji,
showModeratorMenu: false,
export const WithLinkAndCustomEmoji = {
render: Template,
args: {
message: messageWithLinkAndCustomEmoji,
showModeratorMenu: false,
},
};
export const WithModeratorMenu = Template.bind({});
WithModeratorMenu.args = {
message: standardMessage,
showModeratorMenu: true,
export const WithModeratorMenu = {
render: Template,
args: {
message: standardMessage,
showModeratorMenu: true,
},
};
export const FromModeratorUser = Template.bind({});
FromModeratorUser.args = {
message: moderatorMessage,
showModeratorMenu: false,
isAuthorModerator: true,
export const FromModeratorUser = {
render: Template,
args: {
message: moderatorMessage,
showModeratorMenu: false,
isAuthorModerator: true,
},
};
export const FromAuthenticatedUser = Template.bind({});
FromAuthenticatedUser.args = {
message: authenticatedUserMessage,
showModeratorMenu: false,
isAuthorAuthenticated: true,
export const FromAuthenticatedUser = {
render: Template,
args: {
message: authenticatedUserMessage,
showModeratorMenu: false,
isAuthorAuthenticated: true,
},
};
export const FromBotUser = Template.bind({});
FromBotUser.args = {
message: botUserMessage,
showModeratorMenu: false,
isAuthorBot: true,
export const FromBotUser = {
render: Template,
args: {
message: botUserMessage,
showModeratorMenu: false,
isAuthorBot: true,
},
};
export const WithStringHighlighted = Template.bind({});
WithStringHighlighted.args = {
message: standardMessage,
showModeratorMenu: false,
highlightString: 'message',
export const WithStringHighlighted = {
render: Template,
args: {
message: standardMessage,
showModeratorMenu: false,
highlightString: 'message',
},
};

133
web/components/common/ContentHeader/ContentHeader.stories.tsx

@ -1,76 +1,77 @@ @@ -1,76 +1,77 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Meta } from '@storybook/react';
import { ContentHeader } from './ContentHeader';
export default {
const meta = {
title: 'owncast/Components/Content Header',
component: ContentHeader,
parameters: {},
} as ComponentMeta<typeof ContentHeader>;
} satisfies Meta<typeof ContentHeader>;
const Template: ComponentStory<typeof ContentHeader> = args => <ContentHeader {...args} />;
export default meta;
export const Example = Template.bind({});
Example.args = {
name: 'My Awesome Owncast Stream',
summary: 'A calvacade of glorious sights and sounds',
tags: ['word', 'tag with spaces', 'music'],
logo: 'https://watch.owncast.online/logo',
links: [
{
platform: 'github',
url: 'https://github.com/owncast/owncast',
icon: 'https://watch.owncast.online/img/platformlogos/github.svg',
},
{
platform: 'Documentation',
url: 'https://owncast.online',
icon: 'https://watch.owncast.online/img/platformlogos/link.svg',
},
{
platform: 'mastodon',
url: 'https://fosstodon.org/users/owncast',
icon: 'https://watch.owncast.online/img/platformlogos/mastodon.svg',
},
],
export const Example = {
args: {
name: 'My Awesome Owncast Stream',
summary: 'A calvacade of glorious sights and sounds',
tags: ['word', 'tag with spaces', 'music'],
logo: 'https://watch.owncast.online/logo',
links: [
{
platform: 'github',
url: 'https://github.com/owncast/owncast',
icon: 'https://watch.owncast.online/img/platformlogos/github.svg',
},
{
platform: 'Documentation',
url: 'https://owncast.online',
icon: 'https://watch.owncast.online/img/platformlogos/link.svg',
},
{
platform: 'mastodon',
url: 'https://fosstodon.org/users/owncast',
icon: 'https://watch.owncast.online/img/platformlogos/mastodon.svg',
},
],
},
};
export const LongContent = Template.bind({});
LongContent.args = {
name: 'My Awesome Owncast Stream, streaming the best of streams and some lorem ipsum too',
summary:
'A calvacade of glorious sights and sounds. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
tags: [
'word',
'tag with spaces',
'music',
'more tags',
'a bunch',
'keep going',
'and more',
'just a few more',
'video games',
'things',
'stuff',
'ok some more',
'this should do it',
],
logo: 'https://watch.owncast.online/logo',
links: [
{
platform: 'github',
url: 'https://github.com/owncast/owncast',
icon: 'https://watch.owncast.online/img/platformlogos/github.svg',
},
{
platform: 'Documentation',
url: 'https://owncast.online',
icon: 'https://watch.owncast.online/img/platformlogos/link.svg',
},
{
platform: 'mastodon',
url: 'https://fosstodon.org/users/owncast',
icon: 'https://watch.owncast.online/img/platformlogos/mastodon.svg',
},
],
export const LongContent = {
args: {
name: 'My Awesome Owncast Stream, streaming the best of streams and some lorem ipsum too',
summary:
'A calvacade of glorious sights and sounds. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
tags: [
'word',
'tag with spaces',
'music',
'more tags',
'a bunch',
'keep going',
'and more',
'just a few more',
'video games',
'things',
'stuff',
'ok some more',
'this should do it',
],
logo: 'https://watch.owncast.online/logo',
links: [
{
platform: 'github',
url: 'https://github.com/owncast/owncast',
icon: 'https://watch.owncast.online/img/platformlogos/github.svg',
},
{
platform: 'Documentation',
url: 'https://owncast.online',
icon: 'https://watch.owncast.online/img/platformlogos/link.svg',
},
{
platform: 'mastodon',
url: 'https://fosstodon.org/users/owncast',
icon: 'https://watch.owncast.online/img/platformlogos/mastodon.svg',
},
],
},
};

25
web/components/common/OwncastLogo/OwncastLogo.stories.tsx

@ -1,25 +1,24 @@ @@ -1,25 +1,24 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Meta } from '@storybook/react';
import { OwncastLogo } from './OwncastLogo';
export default {
const meta = {
title: 'owncast/Components/Header Logo',
component: OwncastLogo,
parameters: {
chromatic: { diffThreshold: 0.8 },
},
} as ComponentMeta<typeof OwncastLogo>;
} satisfies Meta<typeof OwncastLogo>;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const Template: ComponentStory<typeof OwncastLogo> = args => <OwncastLogo {...args} />;
export default meta;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const Logo = Template.bind({});
Logo.args = {
url: '/logo',
export const Logo = {
args: {
url: '/logo',
},
};
export const DemoServer = Template.bind({});
DemoServer.args = {
url: 'https://watch.owncast.online/logo',
export const DemoServer = {
args: {
url: 'https://watch.owncast.online/logo',
},
};

21
web/components/common/UserDropdown/UserDropdown.stories.tsx

@ -1,15 +1,17 @@ @@ -1,15 +1,17 @@
import React, { useEffect } from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { useEffect } from 'react';
import { StoryFn, Meta } from '@storybook/react';
import { RecoilRoot, useSetRecoilState } from 'recoil';
import { UserDropdown } from './UserDropdown';
import { CurrentUser } from '../../../interfaces/current-user';
import { currentUserAtom } from '../../stores/ClientConfigStore';
export default {
const meta = {
title: 'owncast/Components/User settings menu',
component: UserDropdown,
parameters: {},
} as ComponentMeta<typeof UserDropdown>;
} satisfies Meta<typeof UserDropdown>;
export default meta;
// This component uses Recoil internally so wrap it in a RecoilRoot.
const Example = args => {
@ -29,13 +31,16 @@ const Example = args => { @@ -29,13 +31,16 @@ const Example = args => {
return <UserDropdown id="user-menu" {...args} />;
};
const Template: ComponentStory<typeof UserDropdown> = args => (
const Template: StoryFn<typeof UserDropdown> = args => (
<RecoilRoot>
<Example {...args} />
</RecoilRoot>
);
export const ChatEnabled = Template.bind({});
ChatEnabled.args = {
username: 'test-user',
export const ChatEnabled = {
render: Template,
args: {
username: 'test-user',
},
};

106
web/components/layouts/Main/Main.stories.tsx

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
import { ComponentMeta, ComponentStory } from '@storybook/react';
import { Meta, StoryFn, StoryObj } from '@storybook/react';
import { MutableSnapshot, RecoilRoot } from 'recoil';
import { makeEmptyClientConfig } from '../../../interfaces/client-config.model';
import { ServerStatus, makeEmptyServerStatus } from '../../../interfaces/server-status.model';
@ -30,12 +30,14 @@ import videoSettingsServiceMockOf from '../../../services/video-settings-service @@ -30,12 +30,14 @@ import videoSettingsServiceMockOf from '../../../services/video-settings-service
import { spidermanUser } from '../../../interfaces/user.fixture';
import { exampleChatHistory } from '../../../interfaces/chat-message.fixture';
export default {
const meta = {
title: 'owncast/Layout/Main',
parameters: {
layout: 'fullscreen',
},
} satisfies ComponentMeta<typeof Main>;
} satisfies Meta<typeof Main>;
export default meta;
// mock the Websocket to prevent ani webhook calls from being made in storybook
// @ts-ignore
@ -92,7 +94,7 @@ const DefaultServerStatusServiceMock = serverStatusServiceMockOf(defaultServerSt @@ -92,7 +94,7 @@ const DefaultServerStatusServiceMock = serverStatusServiceMockOf(defaultServerSt
const OnlineServerStatusServiceMock = serverStatusServiceMockOf(onlineServerStatus);
const VideoSettingsServiceMock = videoSettingsServiceMockOf([]);
const Template: ComponentStory<typeof Main> = ({
const Template: StoryFn<typeof Main> = ({
initializeState,
ServerStatusServiceMock = DefaultServerStatusServiceMock,
...args
@ -113,57 +115,79 @@ const Template: ComponentStory<typeof Main> = ({ @@ -113,57 +115,79 @@ const Template: ComponentStory<typeof Main> = ({
</RecoilRoot>
);
export const OfflineDesktop: typeof Template = Template.bind({});
OfflineDesktop.parameters = {
chromatic: { diffThreshold: 0.88 },
};
export const OfflineDesktop: StoryObj<typeof Template> = {
render: Template,
export const OfflineMobile: typeof Template = Template.bind({});
OfflineMobile.args = {
initializeState: (mutableState: MutableSnapshot) => {
mutableState.set(isMobileAtom, true);
parameters: {
chromatic: { diffThreshold: 0.88 },
},
};
OfflineMobile.parameters = {
viewport: {
defaultViewport: 'mobile1',
export const OfflineMobile: StoryObj<typeof Template> = {
render: Template,
args: {
initializeState: (mutableState: MutableSnapshot) => {
mutableState.set(isMobileAtom, true);
},
},
};
export const OfflineTablet: typeof Template = Template.bind({});
OfflineTablet.parameters = {
viewport: {
defaultViewport: 'tablet',
parameters: {
viewport: {
defaultViewport: 'mobile1',
},
},
};
export const Online: typeof Template = Template.bind({});
Online.args = {
ServerStatusServiceMock: OnlineServerStatusServiceMock,
};
Online.parameters = {
chromatic: { diffThreshold: 0.88 },
};
export const OfflineTablet: StoryObj<typeof Template> = {
render: Template,
export const OnlineMobile: typeof Template = Online.bind({});
OnlineMobile.args = {
ServerStatusServiceMock: OnlineServerStatusServiceMock,
initializeState: (mutableState: MutableSnapshot) => {
mutableState.set(isMobileAtom, true);
parameters: {
viewport: {
defaultViewport: 'tablet',
},
},
};
OnlineMobile.parameters = {
viewport: {
defaultViewport: 'mobile1',
export const Online: StoryObj<typeof Template> = {
render: Template,
args: {
ServerStatusServiceMock: OnlineServerStatusServiceMock,
},
parameters: {
chromatic: { diffThreshold: 0.88 },
},
};
export const OnlineTablet: typeof Template = Online.bind({});
OnlineTablet.args = {
ServerStatusServiceMock: OnlineServerStatusServiceMock,
export const OnlineMobile: StoryObj<typeof Template> = {
render: Template,
args: {
ServerStatusServiceMock: OnlineServerStatusServiceMock,
initializeState: (mutableState: MutableSnapshot) => {
mutableState.set(isMobileAtom, true);
},
},
parameters: {
viewport: {
defaultViewport: 'mobile1',
},
},
};
OnlineTablet.parameters = {
viewport: {
defaultViewport: 'tablet',
export const OnlineTablet: StoryObj<typeof Template> = {
render: Template,
args: {
ServerStatusServiceMock: OnlineServerStatusServiceMock,
},
parameters: {
viewport: {
defaultViewport: 'tablet',
},
},
};

17
web/components/modals/AuthModal/AuthModal.stories.tsx

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
import React, { useEffect } from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { useEffect } from 'react';
import { StoryFn, Meta } from '@storybook/react';
import { RecoilRoot, useSetRecoilState } from 'recoil';
import { AuthModal } from './AuthModal';
import { currentUserAtom } from '../../stores/ClientConfigStore';
@ -26,17 +26,20 @@ const Example = () => { @@ -26,17 +26,20 @@ const Example = () => {
);
};
export default {
const meta = {
title: 'owncast/Modals/Auth',
component: AuthModal,
parameters: {},
} as ComponentMeta<typeof AuthModal>;
} satisfies Meta<typeof AuthModal>;
const Template: ComponentStory<typeof AuthModal> = () => (
export default meta;
const Template: StoryFn<typeof AuthModal> = () => (
<RecoilRoot>
<Example />
</RecoilRoot>
);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const Basic = Template.bind({});
export const Basic = {
render: Template,
};

17
web/components/modals/BrowserNotifyModal/BrowserNotifyModal.stories.tsx

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { StoryFn, Meta } from '@storybook/react';
import { RecoilRoot } from 'recoil';
import { BrowserNotifyModal } from './BrowserNotifyModal';
import BrowserNotifyModalMock from '../../../stories/assets/mocks/notify-modal.png';
@ -10,7 +9,7 @@ const Example = () => ( @@ -10,7 +9,7 @@ const Example = () => (
</div>
);
export default {
const meta = {
title: 'owncast/Modals/Browser Notifications',
component: BrowserNotifyModal,
parameters: {
@ -31,14 +30,16 @@ export default { @@ -31,14 +30,16 @@ export default {
},
},
},
} as ComponentMeta<typeof BrowserNotifyModal>;
} satisfies Meta<typeof BrowserNotifyModal>;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const Template: ComponentStory<typeof BrowserNotifyModal> = () => (
export default meta;
const Template: StoryFn<typeof BrowserNotifyModal> = () => (
<RecoilRoot>
<Example />
</RecoilRoot>
);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const Basic = Template.bind({});
export const Basic = {
render: Template,
};

41
web/components/modals/ChatModal/ChatModal.stories.tsx

@ -1,21 +1,21 @@ @@ -1,21 +1,21 @@
/* eslint-disable object-shorthand */
import React, { useEffect } from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { useEffect } from 'react';
import { StoryFn, Meta } from '@storybook/react';
import { RecoilRoot, useSetRecoilState } from 'recoil';
import { ChatModal, ChatModalProps } from './ChatModal';
import { ChatMessage } from '../../../interfaces/chat-message.model';
import { CurrentUser } from '../../../interfaces/current-user';
import { currentUserAtom } from '../../stores/ClientConfigStore';
export default {
const meta = {
title: 'owncast/Chat/Chat modal',
component: ChatModal,
parameters: {
chromatic: { diffThreshold: 0.8 },
docs: {},
},
} as ComponentMeta<typeof ChatModal>;
} satisfies Meta<typeof ChatModal>;
export default meta;
const testMessages = `[
{
@ -578,21 +578,24 @@ const Component = args => { @@ -578,21 +578,24 @@ const Component = args => {
return <ChatModal {...args} />;
};
const Template: ComponentStory<typeof ChatModal> = args => (
const Template: StoryFn<typeof ChatModal> = args => (
<RecoilRoot>
<Component {...args} />
</RecoilRoot>
);
export const Example = Template.bind({});
Example.args = {
loading: false,
messages: messages,
usernameToHighlight: 'testuser',
chatUserId: 'testuser',
isModerator: true,
showInput: true,
chatAvailable: true,
handleClose: () => {},
currentUser: currentUser,
} as ChatModalProps;
export const Example = {
render: Template,
args: {
loading: false,
messages,
usernameToHighlight: 'testuser',
chatUserId: 'testuser',
isModerator: true,
showInput: true,
chatAvailable: true,
handleClose: () => {},
currentUser,
} as ChatModalProps,
};

22
web/components/modals/FatalErrorStateModal/FatalErrorStateModal.stories.tsx

@ -1,21 +1,17 @@ @@ -1,21 +1,17 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Meta } from '@storybook/react';
import { FatalErrorStateModal } from './FatalErrorStateModal';
export default {
const meta = {
title: 'owncast/Modals/Global error state',
component: FatalErrorStateModal,
parameters: {},
} as ComponentMeta<typeof FatalErrorStateModal>;
} satisfies Meta<typeof FatalErrorStateModal>;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const Template: ComponentStory<typeof FatalErrorStateModal> = args => (
<FatalErrorStateModal {...args} />
);
export default meta;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const Example = Template.bind({});
Example.args = {
title: 'Example error title',
message: 'Example error message',
export const Example = {
args: {
title: 'Example error title',
message: 'Example error message',
},
};

31
web/components/modals/FediAuthModal/FediAuthModal.stories.tsx

@ -1,9 +1,8 @@ @@ -1,9 +1,8 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Meta } from '@storybook/react';
import { FediAuthModal } from './FediAuthModal';
import FediAuthModalMock from '../../../stories/assets/mocks/fediauth-modal.png';
export default {
const meta = {
title: 'owncast/Modals/FediAuth',
component: FediAuthModal,
parameters: {
@ -13,20 +12,22 @@ export default { @@ -13,20 +12,22 @@ export default {
scale: 0.5,
},
},
} as ComponentMeta<typeof FediAuthModal>;
} satisfies Meta<typeof FediAuthModal>;
const Template: ComponentStory<typeof FediAuthModal> = args => <FediAuthModal {...args} />;
export default meta;
export const NotYetAuthenticated = Template.bind({});
NotYetAuthenticated.args = {
displayName: 'fake-user',
authenticated: false,
accessToken: '',
export const NotYetAuthenticated = {
args: {
displayName: 'fake-user',
authenticated: false,
accessToken: '',
},
};
export const Authenticated = Template.bind({});
Authenticated.args = {
displayName: 'fake-user',
authenticated: true,
accessToken: '',
export const Authenticated = {
args: {
displayName: 'fake-user',
authenticated: true,
accessToken: '',
},
};

17
web/components/modals/FollowModal/FollowModal.stories.tsx

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { StoryFn, Meta } from '@storybook/react';
import { FollowModal } from './FollowModal';
import FollowModalMock from '../../../stories/assets/mocks/follow-modal.png';
@ -9,7 +8,7 @@ const Example = () => ( @@ -9,7 +8,7 @@ const Example = () => (
</div>
);
export default {
const meta = {
title: 'owncast/Modals/Follow',
component: FollowModal,
parameters: {
@ -29,10 +28,12 @@ export default { @@ -29,10 +28,12 @@ export default {
},
},
},
} as ComponentMeta<typeof FollowModal>;
} satisfies Meta<typeof FollowModal>;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const Template: ComponentStory<typeof FollowModal> = () => <Example />;
export default meta;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const Basic = Template.bind({});
const Template: StoryFn<typeof FollowModal> = () => <Example />;
export const Basic = {
render: Template,
};

17
web/components/modals/IndieAuthModal/IndieAuthModal.stories.tsx

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { StoryFn, Meta } from '@storybook/react';
import { IndieAuthModal } from './IndieAuthModal';
import Mock from '../../../stories/assets/mocks/indieauth-modal.png';
@ -9,7 +8,7 @@ const Example = () => ( @@ -9,7 +8,7 @@ const Example = () => (
</div>
);
export default {
const meta = {
title: 'owncast/Modals/IndieAuth',
component: IndieAuthModal,
parameters: {
@ -19,10 +18,12 @@ export default { @@ -19,10 +18,12 @@ export default {
scale: 0.5,
},
},
} as ComponentMeta<typeof IndieAuthModal>;
} satisfies Meta<typeof IndieAuthModal>;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const Template: ComponentStory<typeof IndieAuthModal> = () => <Example />;
export default meta;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const Basic = Template.bind({});
const Template: StoryFn<typeof IndieAuthModal> = () => <Example />;
export const Basic = {
render: Template,
};

16
web/components/modals/NameChangeModal/NameChangeModal.stories.tsx

@ -1,15 +1,17 @@ @@ -1,15 +1,17 @@
import React, { useEffect } from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { useEffect } from 'react';
import { StoryFn, Meta } from '@storybook/react';
import { RecoilRoot, useSetRecoilState } from 'recoil';
import { NameChangeModal } from './NameChangeModal';
import { CurrentUser } from '../../../interfaces/current-user';
import { currentUserAtom } from '../../stores/ClientConfigStore';
export default {
const meta = {
title: 'owncast/Modals/Name Change',
component: NameChangeModal,
parameters: {},
} as ComponentMeta<typeof NameChangeModal>;
} satisfies Meta<typeof NameChangeModal>;
export default meta;
const Example = () => {
const setCurrentUser = useSetRecoilState<CurrentUser>(currentUserAtom);
@ -32,10 +34,12 @@ const Example = () => { @@ -32,10 +34,12 @@ const Example = () => {
);
};
const Template: ComponentStory<typeof NameChangeModal> = () => (
const Template: StoryFn<typeof NameChangeModal> = () => (
<RecoilRoot>
<Example />
</RecoilRoot>
);
export const Basic = Template.bind({});
export const Basic = {
render: Template,
};

47
web/components/ui/ComponentError/ComponentError.stories.tsx

@ -1,8 +1,7 @@ @@ -1,8 +1,7 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Meta } from '@storybook/react';
import { ComponentError } from './ComponentError';
export default {
const meta = {
title: 'owncast/Components/Component Error',
component: ComponentError,
parameters: {
@ -12,31 +11,35 @@ export default { @@ -12,31 +11,35 @@ export default {
},
},
},
} as ComponentMeta<typeof ComponentError>;
} satisfies Meta<typeof ComponentError>;
const Template: ComponentStory<typeof ComponentError> = args => <ComponentError {...args} />;
export default meta;
export const DefaultMessage = Template.bind({});
DefaultMessage.args = {
componentName: 'Test Component',
export const DefaultMessage = {
args: {
componentName: 'Test Component',
},
};
export const Error1 = Template.bind({});
Error1.args = { message: 'This is a test error message.', componentName: 'Test Component' };
export const Error1 = {
args: { message: 'This is a test error message.', componentName: 'Test Component' },
};
export const WithDetails = Template.bind({});
WithDetails.args = {
message: 'This is a test error message.',
componentName: 'Test Component',
details: 'Here are some additional details about the error.',
export const WithDetails = {
args: {
message: 'This is a test error message.',
componentName: 'Test Component',
details: 'Here are some additional details about the error.',
},
};
export const CanRetry = Template.bind({});
CanRetry.args = {
message: 'This is a test error message.',
componentName: 'Test Component',
details: 'Here are some additional details about the error.',
retryFunction: () => {
console.log('retrying');
export const CanRetry = {
args: {
message: 'This is a test error message.',
componentName: 'Test Component',
details: 'Here are some additional details about the error.',
retryFunction: () => {
console.log('retrying');
},
},
};

38
web/components/ui/CustomPageContent/CustomPageContent.stories.tsx

File diff suppressed because one or more lines are too long

21
web/components/ui/Footer/Footer.stories.tsx

@ -1,22 +1,25 @@ @@ -1,22 +1,25 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { StoryFn, Meta } from '@storybook/react';
import { RecoilRoot } from 'recoil';
import { Footer } from './Footer';
export default {
const meta = {
title: 'owncast/Layout/Footer',
component: Footer,
parameters: {},
} as ComponentMeta<typeof Footer>;
} satisfies Meta<typeof Footer>;
const Template: ComponentStory<typeof Footer> = args => (
export default meta;
const Template: StoryFn<typeof Footer> = args => (
<RecoilRoot>
<Footer {...args} />
</RecoilRoot>
);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const Example = Template.bind({});
Example.args = {
version: 'v1.2.3',
export const Example = {
render: Template,
args: {
version: 'v1.2.3',
},
};

33
web/components/ui/Header/Header.stories.tsx

@ -1,30 +1,37 @@ @@ -1,30 +1,37 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { StoryFn, Meta } from '@storybook/react';
import { RecoilRoot } from 'recoil';
import { Header } from './Header';
export default {
const meta = {
title: 'owncast/Layout/Header',
component: Header,
parameters: {
chromatic: { diffThreshold: 0.75 },
},
} as ComponentMeta<typeof Header>;
} satisfies Meta<typeof Header>;
const Template: ComponentStory<typeof Header> = args => (
export default meta;
const Template: StoryFn<typeof Header> = args => (
<RecoilRoot>
<Header {...args} />
</RecoilRoot>
);
export const ChatAvailable = Template.bind({});
ChatAvailable.args = {
name: 'Example Stream Name',
chatAvailable: true,
export const ChatAvailable = {
render: Template,
args: {
name: 'Example Stream Name',
chatAvailable: true,
},
};
export const ChatNotAvailable = Template.bind({});
ChatNotAvailable.args = {
name: 'Example Stream Name',
chatAvailable: false,
export const ChatNotAvailable = {
render: Template,
args: {
name: 'Example Stream Name',
chatAvailable: false,
},
};

37
web/components/ui/Modal/Modal.stories.tsx

@ -1,8 +1,7 @@ @@ -1,8 +1,7 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { StoryFn, Meta } from '@storybook/react';
import { Modal } from './Modal';
export default {
const meta = {
title: 'owncast/Modals/Container',
component: Modal,
parameters: {
@ -12,23 +11,31 @@ export default { @@ -12,23 +11,31 @@ export default {
},
},
},
} as ComponentMeta<typeof Modal>;
} satisfies Meta<typeof Modal>;
const Template: ComponentStory<typeof Modal> = args => {
export default meta;
const Template: StoryFn<typeof Modal> = args => {
const { children } = args;
return <Modal {...args}>{children}</Modal>;
};
export const Example = Template.bind({});
Example.args = {
title: 'Modal example with content nodes',
visible: true,
children: <div>Test 123</div>,
export const Example = {
render: Template,
args: {
title: 'Modal example with content nodes',
visible: true,
children: <div>Test 123</div>,
},
};
export const UrlExample = Template.bind({});
UrlExample.args = {
title: 'Modal example with URL',
visible: true,
url: 'https://owncast.online',
export const UrlExample = {
render: Template,
args: {
title: 'Modal example with URL',
visible: true,
url: 'https://owncast.online',
},
};

39
web/components/ui/NotifyReminderPopup/NotifyReminderPopup.stories.tsx

@ -1,6 +1,5 @@ @@ -1,6 +1,5 @@
/* eslint-disable no-alert */
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { StoryFn, Meta } from '@storybook/react';
import { NotifyReminderPopup } from './NotifyReminderPopup';
import Mock from '../../../stories/assets/mocks/notify-popup.png';
@ -12,7 +11,7 @@ const Example = args => ( @@ -12,7 +11,7 @@ const Example = args => (
</div>
);
export default {
const meta = {
title: 'owncast/Components/Notify Reminder',
component: NotifyReminderPopup,
parameters: {
@ -27,22 +26,30 @@ Clicking it will make the notification modal display. Clicking the "X" will hide @@ -27,22 +26,30 @@ Clicking it will make the notification modal display. Clicking the "X" will hide
},
},
},
} as ComponentMeta<typeof NotifyReminderPopup>;
} satisfies Meta<typeof NotifyReminderPopup>;
const Template: ComponentStory<typeof NotifyReminderPopup> = args => <Example {...args} />;
export default meta;
export const Active = Template.bind({});
Active.args = {
open: true,
notificationClicked: () => {
alert('notification clicked');
},
notificationClosed: () => {
alert('notification closed');
const Template: StoryFn<typeof NotifyReminderPopup> = args => <Example {...args} />;
export const Active = {
render: Template,
args: {
open: true,
notificationClicked: () => {
alert('notification clicked');
},
notificationClosed: () => {
alert('notification closed');
},
},
};
export const InActive = Template.bind({});
InActive.args = {
open: false,
export const InActive = {
render: Template,
args: {
open: false,
},
};

97
web/components/ui/OfflineBanner/OfflineBanner.stories.tsx

@ -1,10 +1,9 @@ @@ -1,10 +1,9 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { StoryFn, Meta } from '@storybook/react';
import { RecoilRoot } from 'recoil';
import { OfflineBanner } from './OfflineBanner';
import OfflineState from '../../../stories/assets/mocks/offline-state.png';
export default {
const meta = {
title: 'owncast/Layout/Offline Banner',
component: OfflineBanner,
parameters: {
@ -19,56 +18,76 @@ export default { @@ -19,56 +18,76 @@ export default {
},
},
},
} as ComponentMeta<typeof OfflineBanner>;
} satisfies Meta<typeof OfflineBanner>;
const Template: ComponentStory<typeof OfflineBanner> = args => (
export default meta;
const Template: StoryFn<typeof OfflineBanner> = args => (
<RecoilRoot>
<OfflineBanner {...args} />
</RecoilRoot>
);
export const ExampleDefaultWithNotifications = Template.bind({});
ExampleDefaultWithNotifications.args = {
streamName: 'Cool stream 42',
notificationsEnabled: true,
lastLive: new Date(),
export const ExampleDefaultWithNotifications = {
render: Template,
args: {
streamName: 'Cool stream 42',
notificationsEnabled: true,
lastLive: new Date(),
},
};
export const ExampleDefaultWithDateAndFediverse = Template.bind({});
ExampleDefaultWithDateAndFediverse.args = {
streamName: 'Dull stream 31337',
lastLive: new Date(),
notificationsEnabled: false,
fediverseAccount: 'streamer@coolstream.biz',
export const ExampleDefaultWithDateAndFediverse = {
render: Template,
args: {
streamName: 'Dull stream 31337',
lastLive: new Date(),
notificationsEnabled: false,
fediverseAccount: 'streamer@coolstream.biz',
},
};
export const ExampleCustomWithDateAndNotifications = Template.bind({});
ExampleCustomWithDateAndNotifications.args = {
streamName: 'Dull stream 31337',
customText:
'This is some example offline text that a streamer can leave for a visitor of the page.',
lastLive: new Date(),
notificationsEnabled: true,
export const ExampleCustomWithDateAndNotifications = {
render: Template,
args: {
streamName: 'Dull stream 31337',
customText:
'This is some example offline text that a streamer can leave for a visitor of the page.',
lastLive: new Date(),
notificationsEnabled: true,
},
};
export const ExampleDefaultWithNotificationsAndFediverse = Template.bind({});
ExampleDefaultWithNotificationsAndFediverse.args = {
streamName: 'Cool stream 42',
notificationsEnabled: true,
fediverseAccount: 'streamer@coolstream.biz',
lastLive: new Date(),
export const ExampleDefaultWithNotificationsAndFediverse = {
render: Template,
args: {
streamName: 'Cool stream 42',
notificationsEnabled: true,
fediverseAccount: 'streamer@coolstream.biz',
lastLive: new Date(),
},
};
export const ExampleDefaultWithoutNotifications = Template.bind({});
ExampleDefaultWithoutNotifications.args = {
streamName: 'Cool stream 42',
notificationsEnabled: false,
lastLive: new Date(),
export const ExampleDefaultWithoutNotifications = {
render: Template,
args: {
streamName: 'Cool stream 42',
notificationsEnabled: false,
lastLive: new Date(),
},
};
export const ExampleCustomTextWithoutNotifications = Template.bind({});
ExampleCustomTextWithoutNotifications.args = {
streamName: 'Dull stream 31337',
customText:
'This is some example offline text that a streamer can leave for a visitor of the page.',
export const ExampleCustomTextWithoutNotifications = {
render: Template,
args: {
streamName: 'Dull stream 31337',
customText:
'This is some example offline text that a streamer can leave for a visitor of the page.',
},
};

57
web/components/ui/SocialLinks/SocialLinks.stories.tsx

@ -1,39 +1,38 @@ @@ -1,39 +1,38 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Meta } from '@storybook/react';
import { SocialLinks } from './SocialLinks';
export default {
const meta = {
title: 'owncast/Components/Social links',
component: SocialLinks,
parameters: {},
} as ComponentMeta<typeof SocialLinks>;
} satisfies Meta<typeof SocialLinks>;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const Template: ComponentStory<typeof SocialLinks> = args => <SocialLinks {...args} />;
export default meta;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const Populated = Template.bind({});
Populated.args = {
links: [
{
platform: 'github',
url: 'https://github.com/owncast/owncast',
icon: '/img/platformlogos/github.svg',
},
{
platform: 'Documentation',
url: 'https://owncast.online',
icon: '/img/platformlogos/link.svg',
},
{
platform: 'mastodon',
url: 'https://fosstodon.org/users/owncast',
icon: '/img/platformlogos/mastodon.svg',
},
],
export const Populated = {
args: {
links: [
{
platform: 'github',
url: 'https://github.com/owncast/owncast',
icon: '/img/platformlogos/github.svg',
},
{
platform: 'Documentation',
url: 'https://owncast.online',
icon: '/img/platformlogos/link.svg',
},
{
platform: 'mastodon',
url: 'https://fosstodon.org/users/owncast',
icon: '/img/platformlogos/mastodon.svg',
},
],
},
};
export const Empty = Template.bind({});
Empty.args = {
links: [],
export const Empty = {
args: {
links: [],
},
};

29
web/components/ui/Statusbar/StatusBar.stories.tsx

@ -1,25 +1,26 @@ @@ -1,25 +1,26 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Meta } from '@storybook/react';
import { subHours } from 'date-fns';
import { Statusbar } from './Statusbar';
export default {
const meta = {
title: 'owncast/Player/Status bar',
component: Statusbar,
parameters: {},
} as ComponentMeta<typeof Statusbar>;
} satisfies Meta<typeof Statusbar>;
const Template: ComponentStory<typeof Statusbar> = args => <Statusbar {...args} />;
export default meta;
export const Online = Template.bind({});
Online.args = {
online: true,
viewerCount: 42,
lastConnectTime: subHours(new Date(), 3),
export const Online = {
args: {
online: true,
viewerCount: 42,
lastConnectTime: subHours(new Date(), 3),
},
};
export const Offline = Template.bind({});
Offline.args = {
online: false,
lastDisconnectTime: subHours(new Date(), 3),
export const Offline = {
args: {
online: false,
lastDisconnectTime: subHours(new Date(), 3),
},
};

29
web/components/ui/followers/FollowerCollection/FollowerCollection.stories.tsx

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { StoryFn, Meta } from '@storybook/react';
import { RecoilRoot } from 'recoil';
import { action } from '@storybook/addon-actions';
import { FollowerCollection } from './FollowerCollection';
@ -258,15 +257,17 @@ const noFollowersMock = { @@ -258,15 +257,17 @@ const noFollowersMock = {
],
};
export default {
const meta = {
title: 'owncast/Components/Followers/Followers collection',
component: FollowerCollection,
parameters: {
chromatic: { diffThreshold: 0.86 },
},
} as ComponentMeta<typeof FollowerCollection>;
} satisfies Meta<typeof FollowerCollection>;
const Template: ComponentStory<typeof FollowerCollection> = (args: object) => (
export default meta;
const Template: StoryFn<typeof FollowerCollection> = (args: object) => (
<RecoilRoot>
<FollowerCollection
onFollowButtonClick={() => {
@ -278,12 +279,18 @@ const Template: ComponentStory<typeof FollowerCollection> = (args: object) => ( @@ -278,12 +279,18 @@ const Template: ComponentStory<typeof FollowerCollection> = (args: object) => (
</RecoilRoot>
);
export const NoFollowers = Template.bind({});
NoFollowers.parameters = {
fetchMock: noFollowersMock,
export const NoFollowers = {
render: Template,
parameters: {
fetchMock: noFollowersMock,
},
};
export const Example = Template.bind({});
Example.parameters = {
fetchMock: mocks,
export const Example = {
render: Template,
parameters: {
fetchMock: mocks,
},
};

26
web/components/ui/followers/SingleFollower/SingleFollower.stories.tsx

@ -1,9 +1,8 @@ @@ -1,9 +1,8 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Meta } from '@storybook/react';
import { SingleFollower } from './SingleFollower';
import SingleFollowerMock from '../../../../stories/assets/mocks/single-follower.png';
export default {
const meta = {
title: 'owncast/Components/Followers/Single Follower',
component: SingleFollower,
parameters: {
@ -17,17 +16,18 @@ export default { @@ -17,17 +16,18 @@ export default {
},
},
},
} as ComponentMeta<typeof SingleFollower>;
} satisfies Meta<typeof SingleFollower>;
const Template: ComponentStory<typeof SingleFollower> = args => <SingleFollower {...args} />;
export default meta;
export const Example = Template.bind({});
Example.args = {
follower: {
name: 'John Doe',
description: 'User',
username: '@account@domain.tld',
image: 'https://avatars0.githubusercontent.com/u/1234?s=460&v=4',
link: 'https://yahoo.com',
export const Example = {
args: {
follower: {
name: 'John Doe',
description: 'User',
username: '@account@domain.tld',
image: 'https://avatars0.githubusercontent.com/u/1234?s=460&v=4',
link: 'https://yahoo.com',
},
},
};

24
web/components/video/OwncastPlayer/OwncastPlayer.stories.tsx

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { StoryFn, Meta } from '@storybook/react';
import { RecoilRoot } from 'recoil';
import { OwncastPlayer } from './OwncastPlayer';
@ -9,7 +8,7 @@ const streams = { @@ -9,7 +8,7 @@ const streams = {
localhost: `http://localhost:8080/hls/stream.m3u8`,
};
export default {
const meta = {
title: 'owncast/Player/Player',
component: OwncastPlayer,
argTypes: {
@ -22,17 +21,22 @@ export default { @@ -22,17 +21,22 @@ export default {
},
},
parameters: {},
} as ComponentMeta<typeof OwncastPlayer>;
} satisfies Meta<typeof OwncastPlayer>;
const Template: ComponentStory<typeof OwncastPlayer> = args => (
export default meta;
const Template: StoryFn<typeof OwncastPlayer> = args => (
<RecoilRoot>
<OwncastPlayer {...args} />
</RecoilRoot>
);
export const LiveDemo = Template.bind({});
LiveDemo.args = {
online: true,
source: 'https://watch.owncast.online/hls/stream.m3u8',
title: 'Stream title',
export const LiveDemo = {
render: Template,
args: {
online: true,
source: 'https://watch.owncast.online/hls/stream.m3u8',
title: 'Stream title',
},
};

44
web/components/video/VideoPoster/VideoPoster.stories.tsx

@ -1,8 +1,7 @@ @@ -1,8 +1,7 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Meta } from '@storybook/react';
import { VideoPoster } from './VideoPoster';
export default {
const meta = {
title: 'owncast/Player/Video poster',
component: VideoPoster,
parameters: {
@ -17,29 +16,30 @@ export default { @@ -17,29 +16,30 @@ export default {
},
},
},
} as ComponentMeta<typeof VideoPoster>;
} satisfies Meta<typeof VideoPoster>;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const Template: ComponentStory<typeof VideoPoster> = args => <VideoPoster {...args} />;
export default meta;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const Example1 = Template.bind({});
Example1.args = {
initialSrc: 'https://watch.owncast.online/logo',
src: 'https://watch.owncast.online/thumbnail.jpg',
online: true,
export const Example1 = {
args: {
initialSrc: 'https://watch.owncast.online/logo',
src: 'https://watch.owncast.online/thumbnail.jpg',
online: true,
},
};
export const Example2 = Template.bind({});
Example2.args = {
initialSrc: 'https://listen.batstationrad.io/logo',
src: 'https://listen.batstationrad.io//thumbnail.jpg',
online: true,
export const Example2 = {
args: {
initialSrc: 'https://listen.batstationrad.io/logo',
src: 'https://listen.batstationrad.io//thumbnail.jpg',
online: true,
},
};
export const Offline = Template.bind({});
Offline.args = {
initialSrc: 'https://watch.owncast.online/logo',
src: 'https://watch.owncast.online/thumbnail.jpg',
online: false,
export const Offline = {
args: {
initialSrc: 'https://watch.owncast.online/logo',
src: 'https://watch.owncast.online/thumbnail.jpg',
online: false,
},
};

32
web/stories/PageLogo.stories.tsx

@ -1,30 +1,30 @@ @@ -1,30 +1,30 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Meta } from '@storybook/react';
import { Logo } from '../components/ui/Logo/Logo';
export default {
const meta = {
title: 'owncast/Components/Page Logo',
component: Logo,
parameters: {
chromatic: { diffThreshold: 0.8 },
},
} as ComponentMeta<typeof Logo>;
} satisfies Meta<typeof Logo>;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const Template: ComponentStory<typeof Logo> = args => <Logo {...args} />;
export default meta;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const LocalServer = Template.bind({});
LocalServer.args = {
src: 'http://localhost:8080/logo',
export const LocalServer = {
args: {
src: 'http://localhost:8080/logo',
},
};
export const DemoServer = Template.bind({});
DemoServer.args = {
src: 'https://watch.owncast.online/logo',
export const DemoServer = {
args: {
src: 'https://watch.owncast.online/logo',
},
};
export const NotSquare = Template.bind({});
NotSquare.args = {
src: 'https://via.placeholder.com/150x325/FF0000/FFFFFF?text=Rectangle',
export const NotSquare = {
args: {
src: 'https://via.placeholder.com/150x325/FF0000/FFFFFF?text=Rectangle',
},
};

18
web/stories/ReadonlyChat.stories.tsx

File diff suppressed because one or more lines are too long

18
web/stories/ReadwriteChat.stories.tsx

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save