refactor(stories): co-locate stories with components (#2078)
* refactor: move ActionButton component * refactor: move BanUserButton component * refactor: move ChatActionMessage component * refactor: move ChatContainer component * refactor: move AuthModal component * refactor: move BrowserNotifyModal component * refactor: move ChatUserMessage component * refactor: move ChatJoinMessage component * refactor: move ChatTextField component * refactor: move ChatUserBadge component * refactor: move FollowerCollection and SingleFollower components * fix: bad import path * refactor: move FollowModal component * refactor: move Modal component * refactor: move ContentHeader component * refactor: move ChatSystemMessage component * refactor: move Header component * refactor: move Footer component * refactor: move StatusBar component * refactor: move OfflineBanner component * refactor: move OwncastPlayer component * refactor: move IndieAuthModal component * refactor: move SocialLinks component * refactor: move VideoPoster component * refactor: move FollowModal component * refactor: move FediAuthModal.tsx component * refactor: move UserDropdown component * refactor: move ChatSocialMessage component * refactor: move Logo component * refactor: move NotifyReminderPopup component * refactor: move NameChangeModal component * refactor: move FatalErrorStateModal component * refactor: move ChatModeratorNotification component * refactor: move ChatModerationActionMenu and ChatModerationDetailsModal components * refactor: move CustomPageContent component * refactor: move storybook Introduction file * refactor: update storybook story import path * refactor: move storybook preview styles * refactor: move storybook doc pages * refactor: move Color and ImageAsset components * fix: bad import path * fix: bad import path in story file
This commit is contained in:
@@ -18,23 +18,23 @@ import {
|
||||
} from '../../stores/ClientConfigStore';
|
||||
import { ClientConfig } from '../../../interfaces/client-config.model';
|
||||
import CustomPageContent from '../CustomPageContent/CustomPageContent';
|
||||
import OwncastPlayer from '../../video/OwncastPlayer';
|
||||
import FollowerCollection from '../Followers/FollowersCollection';
|
||||
import OwncastPlayer from '../../video/OwncastPlayer/OwncastPlayer';
|
||||
import FollowerCollection from '../followers/FollowerCollection/FollowerCollection';
|
||||
import s from './Content.module.scss';
|
||||
import Sidebar from '../Sidebar';
|
||||
import Footer from '../Footer';
|
||||
// import ChatContainer from '../../chat/ChatContainer';
|
||||
// import { ChatMessage } from '../../../interfaces/chat-message.model';
|
||||
// import ChatTextField from '../../chat/ChatTextField/ChatTextField';
|
||||
import ActionButtonRow from '../../action-buttons/ActionButtonRow';
|
||||
import ActionButton from '../../action-buttons/ActionButton';
|
||||
import ActionButtonRow from '../../action-buttons/ActionButtonRow/ActionButtonRow';
|
||||
import ActionButton from '../../action-buttons/ActionButton/ActionButton';
|
||||
import NotifyReminderPopup from '../NotifyReminderPopup/NotifyReminderPopup';
|
||||
import OfflineBanner from '../OfflineBanner/OfflineBanner';
|
||||
import { AppStateOptions } from '../../stores/application-state';
|
||||
import FollowButton from '../../action-buttons/FollowButton';
|
||||
import NotifyButton from '../../action-buttons/NotifyButton';
|
||||
import Modal from '../Modal/Modal';
|
||||
import BrowserNotifyModal from '../../modals/BrowserNotify/BrowserNotifyModal';
|
||||
import BrowserNotifyModal from '../../modals/BrowserNotifyModal/BrowserNotifyModal';
|
||||
import ContentHeader from '../../common/ContentHeader';
|
||||
import { ServerStatus } from '../../../interfaces/server-status.model';
|
||||
import { StatusBar } from '..';
|
||||
|
||||
File diff suppressed because one or more lines are too long
17
web/components/ui/Footer/Footer.stories.tsx
Normal file
17
web/components/ui/Footer/Footer.stories.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import Footer from './Footer';
|
||||
|
||||
export default {
|
||||
title: 'owncast/Layout/Footer',
|
||||
component: Footer,
|
||||
parameters: {},
|
||||
} as ComponentMeta<typeof Footer>;
|
||||
|
||||
const Template: ComponentStory<typeof Footer> = args => <Footer {...args} />;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export const Example = Template.bind({});
|
||||
Example.args = {
|
||||
version: 'v1.2.3',
|
||||
};
|
||||
28
web/components/ui/Header/Header.stories.tsx
Normal file
28
web/components/ui/Header/Header.stories.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import Header from './Header';
|
||||
|
||||
export default {
|
||||
title: 'owncast/Layout/Header',
|
||||
component: Header,
|
||||
parameters: {},
|
||||
} as ComponentMeta<typeof Header>;
|
||||
|
||||
const Template: ComponentStory<typeof Header> = args => (
|
||||
<RecoilRoot>
|
||||
<Header {...args} />
|
||||
</RecoilRoot>
|
||||
);
|
||||
|
||||
export const ChatAvailable = Template.bind({});
|
||||
ChatAvailable.args = {
|
||||
name: 'Example Stream Name',
|
||||
chatAvailable: true,
|
||||
};
|
||||
|
||||
export const ChatNotAvailable = Template.bind({});
|
||||
ChatNotAvailable.args = {
|
||||
name: 'Example Stream Name',
|
||||
chatAvailable: false,
|
||||
};
|
||||
34
web/components/ui/Modal/Modal.stories.tsx
Normal file
34
web/components/ui/Modal/Modal.stories.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import React from 'react';
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import Modal from './Modal';
|
||||
|
||||
export default {
|
||||
title: 'owncast/Modals/Container',
|
||||
component: Modal,
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: `This is the popup modal container that all modal content is rendered inside. It can be passed content nodes to render, or a URL to show an iframe.`,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof Modal>;
|
||||
|
||||
const Template: ComponentStory<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 UrlExample = Template.bind({});
|
||||
UrlExample.args = {
|
||||
title: 'Modal example with URL',
|
||||
visible: true,
|
||||
url: 'https://owncast.online',
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
/* eslint-disable no-alert */
|
||||
import React from 'react';
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import NotifyReminderPopup from './NotifyReminderPopup';
|
||||
import Mock from '../../../stories/assets/mocks/notify-popup.png';
|
||||
|
||||
const Example = args => (
|
||||
<div style={{ margin: '20px', marginTop: '130px' }}>
|
||||
<NotifyReminderPopup {...args}>
|
||||
<button type="button">notify button</button>
|
||||
</NotifyReminderPopup>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default {
|
||||
title: 'owncast/Components/Notify Reminder',
|
||||
component: NotifyReminderPopup,
|
||||
parameters: {
|
||||
design: {
|
||||
type: 'image',
|
||||
url: Mock,
|
||||
},
|
||||
docs: {
|
||||
description: {
|
||||
component: `After visiting the page three times this popup reminding you that you can register for live stream notifications shows up.
|
||||
Clicking it will make the notification modal display. Clicking the "X" will hide the modal and make it never show again.`,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof NotifyReminderPopup>;
|
||||
|
||||
const Template: ComponentStory<typeof NotifyReminderPopup> = args => <Example {...args} />;
|
||||
|
||||
export const Active = Template.bind({});
|
||||
Active.args = {
|
||||
visible: true,
|
||||
notificationClicked: () => {
|
||||
alert('notification clicked');
|
||||
},
|
||||
notificationClosed: () => {
|
||||
alert('notification closed');
|
||||
},
|
||||
};
|
||||
|
||||
export const InActive = Template.bind({});
|
||||
InActive.args = {
|
||||
visible: false,
|
||||
};
|
||||
35
web/components/ui/OfflineBanner/OfflineBanner.stories.tsx
Normal file
35
web/components/ui/OfflineBanner/OfflineBanner.stories.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import React from 'react';
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import OfflineBanner from './OfflineBanner';
|
||||
import OfflineState from '../../../stories/assets/mocks/offline-state.png';
|
||||
|
||||
export default {
|
||||
title: 'owncast/Layout/Offline Banner',
|
||||
component: OfflineBanner,
|
||||
parameters: {
|
||||
design: {
|
||||
type: 'image',
|
||||
url: OfflineState,
|
||||
scale: 0.5,
|
||||
},
|
||||
docs: {
|
||||
description: {
|
||||
component: `When the stream is offline the player should be replaced by this banner that can support custom text and notify actions.`,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof OfflineBanner>;
|
||||
|
||||
const Template: ComponentStory<typeof OfflineBanner> = args => <OfflineBanner {...args} />;
|
||||
|
||||
export const ExampleDefault = Template.bind({});
|
||||
ExampleDefault.args = {
|
||||
name: 'Cool stream 42',
|
||||
text: 'To get notifications when <server name> is back online you can follow or ask for notifications.',
|
||||
};
|
||||
|
||||
export const ExampleCustom = Template.bind({});
|
||||
ExampleCustom.args = {
|
||||
name: 'Dull stream 31337',
|
||||
text: 'This is some example offline text that a streamer can leave for a visitor of the page.',
|
||||
};
|
||||
39
web/components/ui/SocialLinks/SocialLinks.stories.tsx
Normal file
39
web/components/ui/SocialLinks/SocialLinks.stories.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import React from 'react';
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import SocialLinks from './SocialLinks';
|
||||
|
||||
export default {
|
||||
title: 'owncast/Components/Social links',
|
||||
component: SocialLinks,
|
||||
parameters: {},
|
||||
} as ComponentMeta<typeof SocialLinks>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const Template: ComponentStory<typeof SocialLinks> = args => <SocialLinks {...args} />;
|
||||
|
||||
// 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 Empty = Template.bind({});
|
||||
Empty.args = {
|
||||
links: [],
|
||||
};
|
||||
25
web/components/ui/Statusbar/StatusBar.stories.tsx
Normal file
25
web/components/ui/Statusbar/StatusBar.stories.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import React from 'react';
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import { subHours } from 'date-fns';
|
||||
import Statusbar from './Statusbar';
|
||||
|
||||
export default {
|
||||
title: 'owncast/Player/Status bar',
|
||||
component: Statusbar,
|
||||
parameters: {},
|
||||
} as ComponentMeta<typeof Statusbar>;
|
||||
|
||||
const Template: ComponentStory<typeof Statusbar> = args => <Statusbar {...args} />;
|
||||
|
||||
export const Online = Template.bind({});
|
||||
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),
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
.followers {
|
||||
width: 100%;
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
import React from 'react';
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import FollowerCollection from './FollowerCollection';
|
||||
|
||||
export default {
|
||||
title: 'owncast/Components/Followers/Followers collection',
|
||||
component: FollowerCollection,
|
||||
parameters: {},
|
||||
} as ComponentMeta<typeof FollowerCollection>;
|
||||
|
||||
const Template: ComponentStory<typeof FollowerCollection> = (args: object) => (
|
||||
<FollowerCollection {...args} />
|
||||
);
|
||||
|
||||
export const NoFollowers = Template.bind({});
|
||||
NoFollowers.args = { followers: [] };
|
||||
|
||||
export const Example = Template.bind({});
|
||||
Example.args = {
|
||||
followers: [
|
||||
{
|
||||
link: 'https://sun.minuscule.space/users/mardijker',
|
||||
name: 'mardijker',
|
||||
username: 'mardijker@sun.minuscule.space',
|
||||
image:
|
||||
'https://sun.minuscule.space/media/336af7ae5a2bcb508308eddb30b661ee2b2e15004a50795ee3ba0653ab190a93.jpg',
|
||||
timestamp: '2022-04-27T12:12:50Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://mastodon.online/users/Kallegro',
|
||||
name: '',
|
||||
username: 'Kallegro@mastodon.online',
|
||||
image: '',
|
||||
timestamp: '2022-04-26T15:24:09Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://mastodon.online/users/kerfuffle',
|
||||
name: 'Kerfuffle',
|
||||
username: 'kerfuffle@mastodon.online',
|
||||
image:
|
||||
'https://files.mastodon.online/accounts/avatars/000/133/698/original/6aa73caa898b2d36.gif',
|
||||
timestamp: '2022-04-25T21:32:41Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://mastodon.uno/users/informapirata',
|
||||
name: 'informapirata :privacypride:',
|
||||
username: 'informapirata@mastodon.uno',
|
||||
image:
|
||||
'https://cdn.masto.host/mastodonuno/accounts/avatars/000/060/227/original/da4c44c716a339b8.png',
|
||||
timestamp: '2022-04-25T11:38:23Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://gamethattune.club/users/Raeanus',
|
||||
name: 'Raeanus',
|
||||
username: 'Raeanus@gamethattune.club',
|
||||
image:
|
||||
'https://gamethattune.club/media/a6e6ccea-34f8-4c2e-b9dc-ad8cca7fafd3/DD14E3BF-1358-4961-A900-42F3495F6BE2.jpeg',
|
||||
timestamp: '2022-04-23T00:46:56Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://mastodon.ml/users/latte',
|
||||
name: 'Даниил',
|
||||
username: 'latte@mastodon.ml',
|
||||
image:
|
||||
'https://mastodon.ml/system/accounts/avatars/107/837/409/059/601/386/original/c45ec2676489e363.png',
|
||||
timestamp: '2022-04-19T13:06:09Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://wienermobile.rentals/users/jprjr',
|
||||
name: 'Johnny',
|
||||
username: 'jprjr@wienermobile.rentals',
|
||||
image: '',
|
||||
timestamp: '2022-04-14T14:48:11Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://gamethattune.club/users/johnny',
|
||||
name: 'John Regan',
|
||||
username: 'johnny@gamethattune.club',
|
||||
image:
|
||||
'https://gamethattune.club/media/3c10cd89-866b-4604-ae40-39387fe17061/profile_large.jpg',
|
||||
timestamp: '2022-04-14T14:42:48Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://mastodon.social/users/MightyOwlbear',
|
||||
name: 'Haunted Owlbear',
|
||||
username: 'MightyOwlbear@mastodon.social',
|
||||
image:
|
||||
'https://files.mastodon.social/accounts/avatars/107/246/961/007/605/352/original/a86fc3db97a6de04.jpg',
|
||||
timestamp: '2022-04-14T13:33:03Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://gamethattune.club/users/thelinkfloyd',
|
||||
name: 'thelinkfloyd',
|
||||
username: 'thelinkfloyd@gamethattune.club',
|
||||
image: '',
|
||||
timestamp: '2022-04-05T12:23:32Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://gamethattune.club/users/TheBaffler',
|
||||
name: 'TheBaffler',
|
||||
username: 'TheBaffler@gamethattune.club',
|
||||
image: '',
|
||||
timestamp: '2022-04-04T19:50:08Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://gamethattune.club/users/Gttjessie',
|
||||
name: 'Gttjessie',
|
||||
username: 'Gttjessie@gamethattune.club',
|
||||
image: '',
|
||||
timestamp: '2022-03-30T20:18:47Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://cybre.space/users/fractal',
|
||||
name: 'Le fractal',
|
||||
username: 'fractal@cybre.space',
|
||||
image:
|
||||
'https://cybre.ams3.digitaloceanspaces.com/accounts/avatars/000/405/126/original/f1f2832a7bf1a967.png',
|
||||
timestamp: '2022-03-30T19:46:17Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://fosstodon.org/users/jumboshrimp',
|
||||
name: 'alex 👑🦐',
|
||||
username: 'jumboshrimp@fosstodon.org',
|
||||
image: 'https://cdn.fosstodon.org/accounts/avatars/000/320/316/original/de43cda8653ade7f.jpg',
|
||||
timestamp: '2022-03-30T18:09:54Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://gamethattune.club/users/nvrslep303',
|
||||
name: 'Tay',
|
||||
username: 'nvrslep303@gamethattune.club',
|
||||
image: 'https://gamethattune.club/media/5cf9bc27-8821-445a-86ce-8aa3704acf2d/pfp.jpg',
|
||||
timestamp: '2022-03-30T15:27:49Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://gamethattune.club/users/anKerrigan',
|
||||
name: 'anKerrigan',
|
||||
username: 'anKerrigan@gamethattune.club',
|
||||
image: '',
|
||||
timestamp: '2022-03-30T14:47:04Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://gamethattune.club/users/jgangsta187',
|
||||
name: 'jgangsta187',
|
||||
username: 'jgangsta187@gamethattune.club',
|
||||
image: '',
|
||||
timestamp: '2022-03-30T14:42:52Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://gamethattune.club/users/aekre',
|
||||
name: 'aekre',
|
||||
username: 'aekre@gamethattune.club',
|
||||
image: '',
|
||||
timestamp: '2022-03-30T14:41:32Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://gamethattune.club/users/mork',
|
||||
name: 'mork',
|
||||
username: 'mork@gamethattune.club',
|
||||
image: '',
|
||||
timestamp: '2022-03-30T14:37:10Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://fosstodon.org/users/owncast',
|
||||
name: 'Owncast',
|
||||
username: 'owncast@fosstodon.org',
|
||||
image:
|
||||
'https://cdn.fosstodon.org/accounts/avatars/107/017/218/425/829/465/original/f98ba4cd61f483ab.png',
|
||||
timestamp: '2022-03-29T21:38:02Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://cybre.space/users/wklew',
|
||||
name: 'wally',
|
||||
username: 'wklew@cybre.space',
|
||||
image:
|
||||
'https://cybre.ams3.digitaloceanspaces.com/accounts/avatars/000/308/727/original/7453e74f3e09b27b.jpg',
|
||||
timestamp: '2022-03-29T18:24:29Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://mastodon.social/users/nvrslep303',
|
||||
name: 'Tay',
|
||||
username: 'nvrslep303@mastodon.social',
|
||||
image:
|
||||
'https://files.mastodon.social/accounts/avatars/108/041/196/166/285/851/original/fc444dd6096381af.jpg',
|
||||
timestamp: '2022-03-29T18:19:31Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://mastodon.social/users/morky',
|
||||
name: '',
|
||||
username: 'morky@mastodon.social',
|
||||
image: '',
|
||||
timestamp: '2022-03-29T18:17:59Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://mastodon.social/users/jgangsta187',
|
||||
name: 'John H.',
|
||||
username: 'jgangsta187@mastodon.social',
|
||||
image: '',
|
||||
timestamp: '2022-03-29T18:15:48Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
{
|
||||
link: 'https://fosstodon.org/users/meisam',
|
||||
name: 'Meisam 🇪🇺:archlinux:',
|
||||
username: 'meisam@fosstodon.org',
|
||||
image: 'https://cdn.fosstodon.org/accounts/avatars/000/264/096/original/54b4e6db97206bda.jpg',
|
||||
timestamp: '2022-03-29T18:12:21Z',
|
||||
disabledAt: null,
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Col, Pagination, Row } from 'antd';
|
||||
import { Follower } from '../../../interfaces/follower';
|
||||
import SingleFollower from './Follower';
|
||||
import s from './Followers.module.scss';
|
||||
import { Follower } from '../../../../interfaces/follower';
|
||||
import SingleFollower from '../SingleFollower/SingleFollower';
|
||||
import s from '../SingleFollower/SingleFollower.module.scss';
|
||||
|
||||
export default function FollowerCollection() {
|
||||
const ENDPOINT = '/api/followers';
|
||||
@@ -31,7 +31,3 @@
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.followers {
|
||||
width: 100%;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import React from 'react';
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import SingleFollower from './SingleFollower';
|
||||
import SingleFollowerMock from '../../../../stories/assets/mocks/single-follower.png';
|
||||
|
||||
export default {
|
||||
title: 'owncast/Components/Followers/Single Follower',
|
||||
component: SingleFollower,
|
||||
parameters: {
|
||||
design: {
|
||||
type: 'image',
|
||||
url: SingleFollowerMock,
|
||||
},
|
||||
docs: {
|
||||
description: {
|
||||
component: `Represents a single follower.`,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof SingleFollower>;
|
||||
|
||||
const Template: ComponentStory<typeof SingleFollower> = args => <SingleFollower {...args} />;
|
||||
|
||||
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',
|
||||
},
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Avatar, Col, Row } from 'antd';
|
||||
import React from 'react';
|
||||
import { Follower } from '../../../interfaces/follower';
|
||||
import s from './Followers.module.scss';
|
||||
import { Follower } from '../../../../interfaces/follower';
|
||||
import s from './SingleFollower.module.scss';
|
||||
|
||||
interface Props {
|
||||
follower: Follower;
|
||||
Reference in New Issue
Block a user