Add more placeholder components and some mocks
@@ -5,7 +5,13 @@ import ActionButton from '../components/action-buttons/ActionButton';
|
||||
export default {
|
||||
title: 'owncast/Action Buttons/Single button',
|
||||
component: ActionButton,
|
||||
parameters: {},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: `An **Action Button** or **External Action Button** is a button that is used to trigger either an internal or external action. Many will show a modal, but they can also open a new tab to allow navigating to external pages. They are rendered horizontally within the Action Button Row.`,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof ActionButton>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
|
||||
@@ -4,9 +4,16 @@ import ActionButtonRow from '../components/action-buttons/ActionButtonRow';
|
||||
import ActionButton from '../components/action-buttons/ActionButton';
|
||||
|
||||
export default {
|
||||
title: 'owncast/Action Buttons/Row',
|
||||
title: 'owncast/Action Buttons/Buttons Row',
|
||||
component: ActionButtonRow,
|
||||
parameters: {},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: `This is a horizontal row of buttons that could be statically created by the Owncast application (such as Notify, Follow) or are user-generated external actions (Donate, Learn more, etc).
|
||||
There can be any number of buttons, including zero. They should wrap if needed and handle resizing.`,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof ActionButtonRow>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import BrowserNotifyModal from '../components/modals/BrowserNotifyModal';
|
||||
import BrowserNotifyModalMock from './assets/mocks/notify-modal.png';
|
||||
|
||||
const Example = () => (
|
||||
<div>
|
||||
@@ -11,7 +12,23 @@ const Example = () => (
|
||||
export default {
|
||||
title: 'owncast/Modals/Browser Notifications',
|
||||
component: BrowserNotifyModal,
|
||||
parameters: {},
|
||||
parameters: {
|
||||
design: {
|
||||
type: 'image',
|
||||
url: BrowserNotifyModalMock,
|
||||
scale: 0.5,
|
||||
},
|
||||
docs: {
|
||||
description: {
|
||||
component: `The notify modal allows an end user to get notified when the stream goes live via [Browser Push Notifications](https://developers.google.com/web/ilt/pwa/introduction-to-push-notifications) It must:
|
||||
|
||||
- Verify the browser supports notifications.
|
||||
- Handle errors that come back from the server.
|
||||
- Have an enabled and disabled state with accurate information about each.
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof BrowserNotifyModal>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
import React from 'react';
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import ChatActionMessage from '../components/chat/ChatActionMessage';
|
||||
import Mock from './assets/mocks/chatmessage-action.png';
|
||||
|
||||
export default {
|
||||
title: 'owncast/Chat/Messages/Chat action',
|
||||
component: ChatActionMessage,
|
||||
parameters: {},
|
||||
parameters: {
|
||||
design: {
|
||||
type: 'image',
|
||||
url: Mock,
|
||||
},
|
||||
docs: {
|
||||
description: {
|
||||
component: `This is the message design an action takes place, such as a join or a name change.`,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof ChatActionMessage>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
import React from 'react';
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import ChatSystemMessage from '../components/chat/ChatSystemMessage';
|
||||
import Mock from './assets/mocks/chatmessage-system.png';
|
||||
|
||||
export default {
|
||||
title: 'owncast/Chat/Messages/System',
|
||||
component: ChatSystemMessage,
|
||||
parameters: {},
|
||||
parameters: {
|
||||
design: {
|
||||
type: 'image',
|
||||
url: Mock,
|
||||
},
|
||||
docs: {
|
||||
description: {
|
||||
component: `This is the message design used when the server sends a message to chat.`,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof ChatSystemMessage>;
|
||||
|
||||
const Template: ComponentStory<typeof ChatSystemMessage> = args => <ChatSystemMessage {...args} />;
|
||||
|
||||
@@ -2,11 +2,16 @@ import React from 'react';
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import ChatTextField from '../components/chat/ChatTextField/ChatTextField';
|
||||
import Mock from './assets/mocks/chatinput-mock.png';
|
||||
|
||||
export default {
|
||||
title: 'owncast/Chat/Input text field',
|
||||
component: ChatTextField,
|
||||
parameters: {
|
||||
design: {
|
||||
type: 'image',
|
||||
url: Mock,
|
||||
},
|
||||
docs: {
|
||||
description: {
|
||||
component: `
|
||||
|
||||
@@ -2,11 +2,23 @@ import React from 'react';
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import UserChatMessage from '../components/chat/ChatUserMessage';
|
||||
import { ChatMessage } from '../interfaces/chat-message.model';
|
||||
import Mock from './assets/mocks/chatmessage-user.png';
|
||||
|
||||
export default {
|
||||
title: 'owncast/Chat/Messages/Standard user',
|
||||
component: UserChatMessage,
|
||||
parameters: {},
|
||||
parameters: {
|
||||
design: {
|
||||
type: 'image',
|
||||
url: Mock,
|
||||
scale: 0.5,
|
||||
},
|
||||
docs: {
|
||||
description: {
|
||||
component: `This is the standard text message design that is used when a user sends a message in Owncast chat.`,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof UserChatMessage>;
|
||||
|
||||
const Template: ComponentStory<typeof UserChatMessage> = args => <UserChatMessage {...args} />;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import FediAuthModal from '../components/modals/FediAuthModal';
|
||||
import FediAuthModalMock from './assets/mocks/fediauth-modal.png';
|
||||
|
||||
const Example = () => (
|
||||
<div>
|
||||
@@ -11,7 +12,13 @@ const Example = () => (
|
||||
export default {
|
||||
title: 'owncast/Modals/FediAuth',
|
||||
component: FediAuthModal,
|
||||
parameters: {},
|
||||
parameters: {
|
||||
design: {
|
||||
type: 'image',
|
||||
url: FediAuthModalMock,
|
||||
scale: 0.5,
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof FediAuthModal>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import FollowModal from '../components/modals/FollowModal';
|
||||
import FollowModalMock from './assets/mocks/follow-modal.png';
|
||||
|
||||
const Example = () => (
|
||||
<div>
|
||||
@@ -11,7 +12,23 @@ const Example = () => (
|
||||
export default {
|
||||
title: 'owncast/Modals/Follow',
|
||||
component: FollowModal,
|
||||
parameters: {},
|
||||
parameters: {
|
||||
design: {
|
||||
type: 'image',
|
||||
url: FollowModalMock,
|
||||
scale: 0.5,
|
||||
},
|
||||
docs: {
|
||||
description: {
|
||||
component: `The Follow modal allows an end user to type in their Fediverse account information to follow this Owncast instance. It must:
|
||||
|
||||
- Validate the input to make sure it's a valid looking account.
|
||||
- Handle errors that come back from the server.
|
||||
- Perform the redirect to the remote server when the backend response is received.
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof FollowModal>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import IndieAuthModal from '../components/modals/IndieAuthModal';
|
||||
import Mock from './assets/mocks/indieauth-modal.png';
|
||||
|
||||
const Example = () => (
|
||||
<div>
|
||||
@@ -11,7 +12,13 @@ const Example = () => (
|
||||
export default {
|
||||
title: 'owncast/Modals/IndieAuth',
|
||||
component: IndieAuthModal,
|
||||
parameters: {},
|
||||
parameters: {
|
||||
design: {
|
||||
type: 'image',
|
||||
url: Mock,
|
||||
scale: 0.5,
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof IndieAuthModal>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
|
||||
@@ -16,6 +16,7 @@ Visit the [UIv2 milestone](https://github.com/owncast/owncast/milestone/18) on G
|
||||
- Address feedback from users.
|
||||
- Better accessibility.
|
||||
- Better mobile experience.
|
||||
- Updated [design](https://www.figma.com/file/B6ICOn1J3dyYeoZM5kPM2A/Owncast---Review?node-id=528%3A18).
|
||||
- Standardize styling across the project by using a single design language and style guide.
|
||||
- Allows more people to contribute to the project if we use popular frameworks.
|
||||
|
||||
@@ -25,6 +26,21 @@ Visit the [UIv2 milestone](https://github.com/owncast/owncast/milestone/18) on G
|
||||
- [React](https://reactjs.org/)
|
||||
- [Ant Design](https://ant.design/)
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Find a component that hasn't yet been worked on by looking through the [UIv2 milestone](https://github.com/owncast/owncast/milestone/18)
|
||||
and the sidebar of components to the left.
|
||||
1. See if you can have an example of this functionality in action via the [Owncast Demo Server](https://watch.owncast.online) or [Owncast Nightly Build](https://nightly.owncast.online) so you know how it's supposed to work if it's interactive.
|
||||
1. Visit the `Docs` tab to read any specific documentation that may have been written about how this component works.
|
||||
1. Go to the `Canvas` tab of the component you selected and see if there's a Design attached to it.
|
||||
1. If there is a design, then that's a starting point you can use to start building out the component.
|
||||
1. If there isn't, then visit the [Owncast Demo Server](https://watch.owncast.online), the [Owncast Nightly Build](https://nightly.owncast.online), or the proposed [v2 design](https://www.figma.com/file/B6ICOn1J3dyYeoZM5kPM2A/Owncast---Review?node-id=0%3A1) for some ways to start.
|
||||
1. If no design exists, then you can ask around the Owncast chat for help, for come up with your own ideas!
|
||||
1. No designs are stuck in stone, and we're using this as an opportunity to level up the UI of Owncast, so all ideas are welcome.
|
||||
|
||||
|
||||
|
||||
## How?
|
||||
|
||||
This rewrite is a large project, but like anything else, breaking it into pieces and working on one thing at a time will eventually get us to the finish line.
|
||||
@@ -45,9 +61,3 @@ For example a button may have a disabled state that requires a specific scenario
|
||||
but here we you can just toggle the state to verify things are working as expected.
|
||||
|
||||
This means [new components should have a corresponding story added](https://storybook.js.org/docs/react/get-started/whats-a-story) to make it easier to maintain the project.
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
This is a standard React project so it makes it easy for **anybody to help!**
|
||||
|
||||
|
||||
@@ -5,7 +5,13 @@ import Modal from '../components/ui/Modal/Modal';
|
||||
export default {
|
||||
title: 'owncast/Modals/Container',
|
||||
component: Modal,
|
||||
parameters: {},
|
||||
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 => {
|
||||
|
||||
26
web/stories/NotifyReminder.stories.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import React from 'react';
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import NotifyReminder from '../components/ui/NotifyReminderPopup/NotifyReminderPopup';
|
||||
import Mock from './assets/mocks/notify-popup.png';
|
||||
|
||||
export default {
|
||||
title: 'owncast/Notify Reminder',
|
||||
component: NotifyReminder,
|
||||
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 notificaiton modal display. Clicking the "X" will hide the modal and make it never show again.`,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof NotifyReminder>;
|
||||
|
||||
const Template: ComponentStory<typeof NotifyReminder> = args => <NotifyReminder {...args} />;
|
||||
|
||||
export const Example = Template.bind({});
|
||||
Example.args = {};
|
||||
BIN
web/stories/assets/mocks/chatinput-mock.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
web/stories/assets/mocks/chatmessage-action.png
Normal file
|
After Width: | Height: | Size: 9.8 KiB |
BIN
web/stories/assets/mocks/chatmessage-system.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
web/stories/assets/mocks/chatmessage-user.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
web/stories/assets/mocks/fediauth-modal.png
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
web/stories/assets/mocks/follow-modal.png
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
web/stories/assets/mocks/indieauth-modal.png
Normal file
|
After Width: | Height: | Size: 98 KiB |
BIN
web/stories/assets/mocks/notify-modal.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
web/stories/assets/mocks/notify-popup.png
Normal file
|
After Width: | Height: | Size: 48 KiB |