diff --git a/web/.storybook/main.js b/web/.storybook/main.js index bd65d31a6..f694bd4dc 100644 --- a/web/.storybook/main.js +++ b/web/.storybook/main.js @@ -14,7 +14,7 @@ module.exports = { '@storybook/preset-scss', '@storybook/addon-postcss', '@storybook/addon-a11y', - '@storybook/addon-viewport', + 'storybook-addon-designs', 'storybook-dark-mode', 'addon-screen-reader', ], diff --git a/web/components/ui/NotifyReminderPopup/NotifyReminderPopup.tsx b/web/components/ui/NotifyReminderPopup/NotifyReminderPopup.tsx new file mode 100644 index 000000000..59a07aaed --- /dev/null +++ b/web/components/ui/NotifyReminderPopup/NotifyReminderPopup.tsx @@ -0,0 +1,6 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +interface Props {} + +export default function NotifyReminderPopup(props: Props) { + return
Popup reminder goes here
; +} diff --git a/web/package-lock.json b/web/package-lock.json index 52074baa2..ca7abba3c 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -38,6 +38,7 @@ "recoil": "^0.7.2", "slate": "^0.78.0", "slate-react": "^0.79.0", + "storybook-addon-designs": "^6.2.1", "ua-parser-js": "1.0.2", "video.js": "^7.18.1" }, @@ -2224,6 +2225,26 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@figspec/components": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@figspec/components/-/components-1.0.1.tgz", + "integrity": "sha512-UvnEamPEAMh9HExViqpobWmX25g1+soA9kcJu+It3VerMa7CeVyaIbQydNf1Gys5v/rxJVdTDRgQ7OXW2zAAig==", + "dependencies": { + "lit": "^2.1.3" + } + }, + "node_modules/@figspec/react": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@figspec/react/-/react-1.0.1.tgz", + "integrity": "sha512-4TGazTVFG1SJ+mJNzi3HPKnRC8IGBF6J7GR+wXCPTrOhWpRyQOvcyfomiluPUh69lMLs6hsawjz9yVtutyJocQ==", + "dependencies": { + "@figspec/components": "^1.0.0", + "@lit-labs/react": "^1.0.2" + }, + "peerDependencies": { + "react": "^16.14.0 || ^17.0.0" + } + }, "node_modules/@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", @@ -3350,6 +3371,16 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@lit-labs/react": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@lit-labs/react/-/react-1.0.4.tgz", + "integrity": "sha512-Sy4RCxTZpTE2TwByjVac6gC7jzr8bCQC6s9bJhhJDKos4ZlN2cqcuVz63n0mpSSr1zxFh+Z0o0VR223l36Y4Ag==" + }, + "node_modules/@lit/reactive-element": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.3.2.tgz", + "integrity": "sha512-A2e18XzPMrIh35nhIdE4uoqRzoIpEU5vZYuQN4S3Ee1zkGdYC27DP12pewbw/RLgPHzaE4kx/YqxMzebOpm0dA==" + }, "node_modules/@mdx-js/loader": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-1.6.22.tgz", @@ -11047,6 +11078,11 @@ "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz", "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==" }, + "node_modules/@types/trusted-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", + "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" + }, "node_modules/@types/ua-parser-js": { "version": "0.7.36", "resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz", @@ -22767,6 +22803,33 @@ "uc.micro": "^1.0.1" } }, + "node_modules/lit": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/lit/-/lit-2.2.3.tgz", + "integrity": "sha512-5/v+r9dH3Pw/o0rhp/qYk3ERvOUclNF31bWb0FiW6MPgwdQIr+/KCt/p3zcd8aPl8lIGnxdGrVcZA+gWS6oFOQ==", + "dependencies": { + "@lit/reactive-element": "^1.3.0", + "lit-element": "^3.2.0", + "lit-html": "^2.2.0" + } + }, + "node_modules/lit-element": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.2.0.tgz", + "integrity": "sha512-HbE7yt2SnUtg5DCrWt028oaU4D5F4k/1cntAFHTkzY8ZIa8N0Wmu92PxSxucsQSOXlODFrICkQ5x/tEshKi13g==", + "dependencies": { + "@lit/reactive-element": "^1.3.0", + "lit-html": "^2.2.0" + } + }, + "node_modules/lit-html": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.2.3.tgz", + "integrity": "sha512-vI4j3eWwtQaR8q/O63juZVliBIFMio716X719/lSsGH4UWPy2/7Qf377jsNs4cx3gCHgIbx8yxFgXFQ/igZyXQ==", + "dependencies": { + "@types/trusted-types": "^2.0.2" + } + }, "node_modules/loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", @@ -29272,6 +29335,14 @@ "resolved": "https://registry.npmjs.org/store2/-/store2-2.13.2.tgz", "integrity": "sha512-CMtO2Uneg3SAz/d6fZ/6qbqqQHi2ynq6/KzMD/26gTkiEShCcpqFfTHgOxsE0egAq6SX3FmN4CeSqn8BzXQkJg==" }, + "node_modules/storybook-addon-designs": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/storybook-addon-designs/-/storybook-addon-designs-6.2.1.tgz", + "integrity": "sha512-ihsscab8185HnxqTNZlM4TfrCPVsO7AimVA8BapuqT/sfZQF9m5H9C0plT3kbECdIMh2cmzMBF1Tc9ckWRgpWg==", + "dependencies": { + "@figspec/react": "^1.0.0" + } + }, "node_modules/storybook-dark-mode": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/storybook-dark-mode/-/storybook-dark-mode-1.0.9.tgz", @@ -33650,6 +33721,23 @@ "strip-json-comments": "^3.1.1" } }, + "@figspec/components": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@figspec/components/-/components-1.0.1.tgz", + "integrity": "sha512-UvnEamPEAMh9HExViqpobWmX25g1+soA9kcJu+It3VerMa7CeVyaIbQydNf1Gys5v/rxJVdTDRgQ7OXW2zAAig==", + "requires": { + "lit": "^2.1.3" + } + }, + "@figspec/react": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@figspec/react/-/react-1.0.1.tgz", + "integrity": "sha512-4TGazTVFG1SJ+mJNzi3HPKnRC8IGBF6J7GR+wXCPTrOhWpRyQOvcyfomiluPUh69lMLs6hsawjz9yVtutyJocQ==", + "requires": { + "@figspec/components": "^1.0.0", + "@lit-labs/react": "^1.0.2" + } + }, "@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", @@ -34589,6 +34677,16 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "@lit-labs/react": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@lit-labs/react/-/react-1.0.4.tgz", + "integrity": "sha512-Sy4RCxTZpTE2TwByjVac6gC7jzr8bCQC6s9bJhhJDKos4ZlN2cqcuVz63n0mpSSr1zxFh+Z0o0VR223l36Y4Ag==" + }, + "@lit/reactive-element": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.3.2.tgz", + "integrity": "sha512-A2e18XzPMrIh35nhIdE4uoqRzoIpEU5vZYuQN4S3Ee1zkGdYC27DP12pewbw/RLgPHzaE4kx/YqxMzebOpm0dA==" + }, "@mdx-js/loader": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-1.6.22.tgz", @@ -40388,6 +40486,11 @@ "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz", "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==" }, + "@types/trusted-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", + "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" + }, "@types/ua-parser-js": { "version": "0.7.36", "resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz", @@ -49564,6 +49667,33 @@ "uc.micro": "^1.0.1" } }, + "lit": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/lit/-/lit-2.2.3.tgz", + "integrity": "sha512-5/v+r9dH3Pw/o0rhp/qYk3ERvOUclNF31bWb0FiW6MPgwdQIr+/KCt/p3zcd8aPl8lIGnxdGrVcZA+gWS6oFOQ==", + "requires": { + "@lit/reactive-element": "^1.3.0", + "lit-element": "^3.2.0", + "lit-html": "^2.2.0" + } + }, + "lit-element": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.2.0.tgz", + "integrity": "sha512-HbE7yt2SnUtg5DCrWt028oaU4D5F4k/1cntAFHTkzY8ZIa8N0Wmu92PxSxucsQSOXlODFrICkQ5x/tEshKi13g==", + "requires": { + "@lit/reactive-element": "^1.3.0", + "lit-html": "^2.2.0" + } + }, + "lit-html": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.2.3.tgz", + "integrity": "sha512-vI4j3eWwtQaR8q/O63juZVliBIFMio716X719/lSsGH4UWPy2/7Qf377jsNs4cx3gCHgIbx8yxFgXFQ/igZyXQ==", + "requires": { + "@types/trusted-types": "^2.0.2" + } + }, "loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", @@ -54467,6 +54597,14 @@ "resolved": "https://registry.npmjs.org/store2/-/store2-2.13.2.tgz", "integrity": "sha512-CMtO2Uneg3SAz/d6fZ/6qbqqQHi2ynq6/KzMD/26gTkiEShCcpqFfTHgOxsE0egAq6SX3FmN4CeSqn8BzXQkJg==" }, + "storybook-addon-designs": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/storybook-addon-designs/-/storybook-addon-designs-6.2.1.tgz", + "integrity": "sha512-ihsscab8185HnxqTNZlM4TfrCPVsO7AimVA8BapuqT/sfZQF9m5H9C0plT3kbECdIMh2cmzMBF1Tc9ckWRgpWg==", + "requires": { + "@figspec/react": "^1.0.0" + } + }, "storybook-dark-mode": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/storybook-dark-mode/-/storybook-dark-mode-1.0.9.tgz", diff --git a/web/package.json b/web/package.json index e3a3a5ed1..92eb10ac8 100644 --- a/web/package.json +++ b/web/package.json @@ -42,6 +42,7 @@ "recoil": "^0.7.2", "slate": "^0.78.0", "slate-react": "^0.79.0", + "storybook-addon-designs": "^6.2.1", "ua-parser-js": "1.0.2", "video.js": "^7.18.1" }, diff --git a/web/stories/ActionButton.stories.tsx b/web/stories/ActionButton.stories.tsx index 8061d595e..f3dd624cf 100644 --- a/web/stories/ActionButton.stories.tsx +++ b/web/stories/ActionButton.stories.tsx @@ -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; // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/web/stories/ActionButtonRow.stories.tsx b/web/stories/ActionButtonRow.stories.tsx index 8a71400c2..00eb016af 100644 --- a/web/stories/ActionButtonRow.stories.tsx +++ b/web/stories/ActionButtonRow.stories.tsx @@ -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; // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/web/stories/BrowserNotifyModal.stories.tsx b/web/stories/BrowserNotifyModal.stories.tsx index cacefabe9..cddee5598 100644 --- a/web/stories/BrowserNotifyModal.stories.tsx +++ b/web/stories/BrowserNotifyModal.stories.tsx @@ -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 = () => (
@@ -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; // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/web/stories/ChatActionMessage.stories.tsx b/web/stories/ChatActionMessage.stories.tsx index 3c255c51b..cdca8e1e3 100644 --- a/web/stories/ChatActionMessage.stories.tsx +++ b/web/stories/ChatActionMessage.stories.tsx @@ -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; // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/web/stories/ChatSystemMessage.stories.tsx b/web/stories/ChatSystemMessage.stories.tsx index f0a70bf1c..f3902d049 100644 --- a/web/stories/ChatSystemMessage.stories.tsx +++ b/web/stories/ChatSystemMessage.stories.tsx @@ -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; const Template: ComponentStory = args => ; diff --git a/web/stories/ChatTextField.stories.tsx b/web/stories/ChatTextField.stories.tsx index cb9d3d80a..dc7af9485 100644 --- a/web/stories/ChatTextField.stories.tsx +++ b/web/stories/ChatTextField.stories.tsx @@ -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: ` diff --git a/web/stories/ChatUserMessage.stories.tsx b/web/stories/ChatUserMessage.stories.tsx index b3b503d69..afd12a7a3 100644 --- a/web/stories/ChatUserMessage.stories.tsx +++ b/web/stories/ChatUserMessage.stories.tsx @@ -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; const Template: ComponentStory = args => ; diff --git a/web/stories/FediAuthModal.stories.tsx b/web/stories/FediAuthModal.stories.tsx index f342c390e..4b56560f7 100644 --- a/web/stories/FediAuthModal.stories.tsx +++ b/web/stories/FediAuthModal.stories.tsx @@ -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 = () => (
@@ -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; // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/web/stories/FollowModal.stories.tsx b/web/stories/FollowModal.stories.tsx index 07dfa0c47..a959b2207 100644 --- a/web/stories/FollowModal.stories.tsx +++ b/web/stories/FollowModal.stories.tsx @@ -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 = () => (
@@ -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; // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/web/stories/IndieAuthModal.stories.tsx b/web/stories/IndieAuthModal.stories.tsx index 660ea0c4b..6b46d12bd 100644 --- a/web/stories/IndieAuthModal.stories.tsx +++ b/web/stories/IndieAuthModal.stories.tsx @@ -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 = () => (
@@ -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; // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/web/stories/Introduction.stories.mdx b/web/stories/Introduction.stories.mdx index c5ccf1305..3ddec11d7 100644 --- a/web/stories/Introduction.stories.mdx +++ b/web/stories/Introduction.stories.mdx @@ -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!** - diff --git a/web/stories/Modal.stories.tsx b/web/stories/Modal.stories.tsx index 50fd40e97..99d53c593 100644 --- a/web/stories/Modal.stories.tsx +++ b/web/stories/Modal.stories.tsx @@ -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; const Template: ComponentStory = args => { diff --git a/web/stories/NotifyReminder.stories.tsx b/web/stories/NotifyReminder.stories.tsx new file mode 100644 index 000000000..758133068 --- /dev/null +++ b/web/stories/NotifyReminder.stories.tsx @@ -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; + +const Template: ComponentStory = args => ; + +export const Example = Template.bind({}); +Example.args = {}; diff --git a/web/stories/assets/mocks/chatinput-mock.png b/web/stories/assets/mocks/chatinput-mock.png new file mode 100644 index 000000000..09342cf9f Binary files /dev/null and b/web/stories/assets/mocks/chatinput-mock.png differ diff --git a/web/stories/assets/mocks/chatmessage-action.png b/web/stories/assets/mocks/chatmessage-action.png new file mode 100644 index 000000000..95c064dac Binary files /dev/null and b/web/stories/assets/mocks/chatmessage-action.png differ diff --git a/web/stories/assets/mocks/chatmessage-system.png b/web/stories/assets/mocks/chatmessage-system.png new file mode 100644 index 000000000..e5e2ea97d Binary files /dev/null and b/web/stories/assets/mocks/chatmessage-system.png differ diff --git a/web/stories/assets/mocks/chatmessage-user.png b/web/stories/assets/mocks/chatmessage-user.png new file mode 100644 index 000000000..d0a30f384 Binary files /dev/null and b/web/stories/assets/mocks/chatmessage-user.png differ diff --git a/web/stories/assets/mocks/fediauth-modal.png b/web/stories/assets/mocks/fediauth-modal.png new file mode 100644 index 000000000..39188b547 Binary files /dev/null and b/web/stories/assets/mocks/fediauth-modal.png differ diff --git a/web/stories/assets/mocks/follow-modal.png b/web/stories/assets/mocks/follow-modal.png new file mode 100644 index 000000000..4c6a3b26a Binary files /dev/null and b/web/stories/assets/mocks/follow-modal.png differ diff --git a/web/stories/assets/mocks/indieauth-modal.png b/web/stories/assets/mocks/indieauth-modal.png new file mode 100644 index 000000000..b598bdf9b Binary files /dev/null and b/web/stories/assets/mocks/indieauth-modal.png differ diff --git a/web/stories/assets/mocks/notify-modal.png b/web/stories/assets/mocks/notify-modal.png new file mode 100644 index 000000000..6508c1aac Binary files /dev/null and b/web/stories/assets/mocks/notify-modal.png differ diff --git a/web/stories/assets/mocks/notify-popup.png b/web/stories/assets/mocks/notify-popup.png new file mode 100644 index 000000000..e116e8520 Binary files /dev/null and b/web/stories/assets/mocks/notify-popup.png differ