Add mobile-specific tabs+content

This commit is contained in:
Gabe Kangas
2022-09-10 12:08:22 -07:00
parent a2fa754922
commit 0430adc502
5 changed files with 104 additions and 28 deletions

View File

@@ -39,6 +39,7 @@
font-weight: 300; font-weight: 300;
line-height: 1.3; line-height: 1.3;
color: var(--theme-color-background-header); color: var(--theme-color-background-header);
max-width: 900px;
} }
} }

View File

@@ -9,9 +9,13 @@
background-color: var(--theme-color-components-video-background); background-color: var(--theme-color-components-video-background);
} }
.lowerSection { .lowerSection {
padding: 0em 2em; padding: 0em 2%;
margin-bottom: 2em; margin-bottom: 2em;
} }
.lowerSectionMobile {
padding: 0.3em;
}
} }
.leftCol { .leftCol {

View File

@@ -1,10 +1,14 @@
import { useRecoilState, useRecoilValue } from 'recoil'; import { useRecoilState, useRecoilValue } from 'recoil';
import { Layout, Tabs, Spin } from 'antd'; import { Layout, Tabs, Spin } from 'antd';
import { FC, useEffect, useState } from 'react'; import { FC, useEffect, useState } from 'react';
import classNames from 'classnames';
import { LOCAL_STORAGE_KEYS, getLocalStorage, setLocalStorage } from '../../../utils/localStorage'; import { LOCAL_STORAGE_KEYS, getLocalStorage, setLocalStorage } from '../../../utils/localStorage';
import { import {
clientConfigStateAtom, clientConfigStateAtom,
chatMessagesAtom,
chatDisplayNameAtom,
chatUserIdAtom,
isChatVisibleSelector, isChatVisibleSelector,
appStateAtom, appStateAtom,
isOnlineSelector, isOnlineSelector,
@@ -31,19 +35,87 @@ import { BrowserNotifyModal } from '../../modals/BrowserNotifyModal/BrowserNotif
import { ContentHeader } from '../../common/ContentHeader/ContentHeader'; import { ContentHeader } from '../../common/ContentHeader/ContentHeader';
import { ServerStatus } from '../../../interfaces/server-status.model'; import { ServerStatus } from '../../../interfaces/server-status.model';
import { Statusbar } from '../Statusbar/Statusbar'; import { Statusbar } from '../Statusbar/Statusbar';
import { ChatContainer } from '../../chat/ChatContainer/ChatContainer';
import { ChatMessage } from '../../../interfaces/chat-message.model';
const { TabPane } = Tabs; const { TabPane } = Tabs;
const { Content: AntContent } = Layout; const { Content: AntContent } = Layout;
const DesktopContent = ({ name, streamTitle, summary, tags, socialHandles, extraPageContent }) => (
<>
<div className={styles.lowerHalf}>
<ContentHeader
name={name}
title={streamTitle}
summary={summary}
tags={tags}
links={socialHandles}
logo="/logo"
/>
</div>
<div className={styles.lowerSection}>
<Tabs defaultActiveKey="0">
<TabPane tab="About" key="2">
<CustomPageContent content={extraPageContent} />
</TabPane>
<TabPane tab="Followers" key="3">
<FollowerCollection />
</TabPane>
</Tabs>
</div>
</>
);
const MobileContent = ({
name,
streamTitle,
summary,
tags,
socialHandles,
extraPageContent,
messages,
chatDisplayName,
chatUserId,
}) => (
<div className={classNames(styles.lowerSectionMobile)}>
<Tabs defaultActiveKey="0">
<TabPane tab="Chat" key="1">
<ChatContainer
messages={messages}
usernameToHighlight={chatDisplayName}
chatUserId={chatUserId}
isModerator={false}
height="40vh"
/>{' '}
</TabPane>
<TabPane tab="About" key="2">
<ContentHeader
name={name}
title={streamTitle}
summary={summary}
tags={tags}
links={socialHandles}
logo="/logo"
/>
<CustomPageContent content={extraPageContent} />
</TabPane>
<TabPane tab="Followers" key="3">
<FollowerCollection />
</TabPane>
</Tabs>
</div>
);
export const Content: FC = () => { export const Content: FC = () => {
const appState = useRecoilValue<AppStateOptions>(appStateAtom); const appState = useRecoilValue<AppStateOptions>(appStateAtom);
const clientConfig = useRecoilValue<ClientConfig>(clientConfigStateAtom); const clientConfig = useRecoilValue<ClientConfig>(clientConfigStateAtom);
const isChatVisible = useRecoilValue<boolean>(isChatVisibleSelector); const isChatVisible = useRecoilValue<boolean>(isChatVisibleSelector);
const [isMobile, setIsMobile] = useRecoilState<boolean | undefined>(isMobileAtom); const [isMobile, setIsMobile] = useRecoilState<boolean | undefined>(isMobileAtom);
// const messages = useRecoilValue<ChatMessage[]>(chatMessagesAtom); const messages = useRecoilValue<ChatMessage[]>(chatMessagesAtom);
const online = useRecoilValue<boolean>(isOnlineSelector); const online = useRecoilValue<boolean>(isOnlineSelector);
// const chatDisplayName = useRecoilValue<string>(chatDisplayNameAtom); const chatDisplayName = useRecoilValue<string>(chatDisplayNameAtom);
// const chatUserId = useRecoilValue<string>(chatUserIdAtom); const chatUserId = useRecoilValue<string>(chatUserIdAtom);
const { viewerCount, lastConnectTime, lastDisconnectTime, streamTitle } = const { viewerCount, lastConnectTime, lastDisconnectTime, streamTitle } =
useRecoilValue<ServerStatus>(serverStatusState); useRecoilValue<ServerStatus>(serverStatusState);
const { const {
@@ -145,31 +217,32 @@ export const Content: FC = () => {
</Modal> </Modal>
</div> </div>
</div> </div>
<div className={styles.lowerHalf}> {isMobile && isChatVisible ? (
<ContentHeader <MobileContent
name={name} name={name}
title={streamTitle} streamTitle={streamTitle}
summary={summary} summary={summary}
tags={tags} tags={tags}
links={socialHandles} socialHandles={socialHandles}
logo="/logo" extraPageContent={extraPageContent}
messages={messages}
chatDisplayName={chatDisplayName}
chatUserId={chatUserId}
/> />
</div> ) : (
<DesktopContent
<div className={styles.lowerSection}> name={name}
<Tabs defaultActiveKey="0"> streamTitle={streamTitle}
<TabPane tab="About" key="2"> summary={summary}
<CustomPageContent content={extraPageContent} /> tags={tags}
</TabPane> socialHandles={socialHandles}
<TabPane tab="Followers" key="3"> extraPageContent={extraPageContent}
<FollowerCollection /> />
</TabPane> )}
</Tabs>
</div>
</div> </div>
{isChatVisible && !isMobile && <Sidebar />} {isChatVisible && !isMobile && <Sidebar />}
</AntContent> </AntContent>
<Footer version={version} /> {(!isMobile || !isChatVisible) && <Footer version={version} />}
</div> </div>
); );
}; };

View File

@@ -5,15 +5,15 @@
} }
.customPageContent { .customPageContent {
font-size: 16px; font-size: 1.1rem;
line-height: 1.5em; line-height: 1.6em;
margin: 0; margin: 0;
padding: 0; padding: 0;
color: var(--theme-color-palette-0); color: var(--theme-color-palette-0);
background-color: var(--theme-color-palette-4); background-color: var(--theme-color-palette-4);
padding: calc(2 * var(--content-padding)); padding: calc(2 * var(--content-padding));
border-radius: var(--theme-rounded-corners); border-radius: var(--theme-rounded-corners);
width: clamp(300px, 80%, 900px); width: clamp(300px, 80%, 1000px);
// Allow the content to fill the width on narrow screens. // Allow the content to fill the width on narrow screens.
@media only screen and (max-width: 768px) { @media only screen and (max-width: 768px) {

View File

@@ -20,9 +20,7 @@ export const Header: FC<HeaderComponentProps> = ({ name = 'Your stream title', c
{chatAvailable && <UserDropdown />} {chatAvailable && <UserDropdown />}
{!chatAvailable && ( {!chatAvailable && (
<Tooltip title="Chat is available when the stream is live." placement="left"> <Tooltip title="Chat is available when the stream is live." placement="left">
<Tag color="processing" style={{ cursor: 'pointer' }}> <Tag style={{ cursor: 'pointer' }}>Chat offline</Tag>
Chat offline
</Tag>
</Tooltip> </Tooltip>
)} )}
</AntHeader> </AntHeader>