reworked slightly main layout
This commit is contained in:
@@ -17,11 +17,9 @@ export default function ChatContainer(props: Props) {
|
|||||||
const chatContainerRef = useRef(null);
|
const chatContainerRef = useRef(null);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div style={{ height: 'calc(100vh - 104.5px)' }}>
|
||||||
<Spin spinning={loading} />
|
<Spin spinning={loading} />
|
||||||
|
|
||||||
<Virtuoso
|
<Virtuoso
|
||||||
style={{ height: '400px' }}
|
|
||||||
ref={chatContainerRef}
|
ref={chatContainerRef}
|
||||||
initialTopMostItemIndex={999}
|
initialTopMostItemIndex={999}
|
||||||
data={messages}
|
data={messages}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
.root {
|
||||||
|
height: 2rem;
|
||||||
|
color: var(--black);
|
||||||
|
}
|
||||||
38
web/components/chat/ChatTextField/ChatTextField.tsx
Normal file
38
web/components/chat/ChatTextField/ChatTextField.tsx
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { MoreOutlined } from '@ant-design/icons';
|
||||||
|
import { Input, Button } from 'antd';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import s from './ChatTextField.module.scss';
|
||||||
|
|
||||||
|
interface Props {}
|
||||||
|
|
||||||
|
export default function ChatTextField(props: Props) {
|
||||||
|
const [value, setValue] = useState('');
|
||||||
|
const [showEmojis, setShowEmojis] = useState(false);
|
||||||
|
// large is 40px
|
||||||
|
const size = 'large';
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log({ value });
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Input.Group compact style={{ display: 'flex' }}>
|
||||||
|
<Input
|
||||||
|
onChange={e => setValue(e.target.value)}
|
||||||
|
size={size}
|
||||||
|
placeholder="Enter text and hit enter!"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
size={size}
|
||||||
|
icon={<MoreOutlined />}
|
||||||
|
type="default"
|
||||||
|
onClick={() => setShowEmojis(!showEmojis)}
|
||||||
|
/>
|
||||||
|
<Button size={size} type="primary">
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
</Input.Group>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Layout } from 'antd';
|
import { Layout } from 'antd';
|
||||||
import { ServerStatusStore } from '../stores/ServerStatusStore';
|
import { ServerStatusStore } from '../stores/ServerStatusStore';
|
||||||
import { ClientConfigStore } from '../stores/ClientConfigStore';
|
import { ClientConfigStore } from '../stores/ClientConfigStore';
|
||||||
import { Content, Footer, Header, Sidebar } from '../ui';
|
import { Content, Header } from '../ui';
|
||||||
|
|
||||||
function Main() {
|
function Main() {
|
||||||
return (
|
return (
|
||||||
@@ -9,12 +9,8 @@ function Main() {
|
|||||||
<ServerStatusStore />
|
<ServerStatusStore />
|
||||||
<ClientConfigStore />
|
<ClientConfigStore />
|
||||||
<Layout>
|
<Layout>
|
||||||
<Sidebar />
|
|
||||||
<Header />
|
<Header />
|
||||||
<Layout className="site-layout" style={{ marginRight: 200 }}>
|
<Content />
|
||||||
<Content />
|
|
||||||
<Footer />
|
|
||||||
</Layout>
|
|
||||||
</Layout>
|
</Layout>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
14
web/components/ui/Content/Content.module.scss
Normal file
14
web/components/ui/Content/Content.module.scss
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
.root {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 8fr 4fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leftCol {
|
||||||
|
display: grid;
|
||||||
|
// -64px, which is the header
|
||||||
|
grid-template-rows: 50vh calc(50vh - 64px);
|
||||||
|
}
|
||||||
|
.lowerRow {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: 1fr 64px;
|
||||||
|
}
|
||||||
@@ -1,10 +1,15 @@
|
|||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { Layout, Row, Col, Tabs } from 'antd';
|
import { Layout, Row, Col, Tabs } from 'antd';
|
||||||
import { clientConfigStateAtom } from '../../stores/ClientConfigStore';
|
import { chatVisibilityAtom, clientConfigStateAtom } from '../../stores/ClientConfigStore';
|
||||||
import { ClientConfig } from '../../../interfaces/client-config.model';
|
import { ClientConfig } from '../../../interfaces/client-config.model';
|
||||||
import CustomPageContent from '../../CustomPageContent';
|
import CustomPageContent from '../../CustomPageContent';
|
||||||
import OwncastPlayer from '../../video/OwncastPlayer';
|
import OwncastPlayer from '../../video/OwncastPlayer';
|
||||||
import FollowerCollection from '../../FollowersCollection';
|
import FollowerCollection from '../../FollowersCollection';
|
||||||
|
import s from './Content.module.scss';
|
||||||
|
import Sidebar from '../Sidebar';
|
||||||
|
import { ChatVisibilityState } from '../../../interfaces/application-state';
|
||||||
|
import Footer from '../Footer';
|
||||||
|
import Grid from 'antd/lib/card/Grid';
|
||||||
|
|
||||||
const { TabPane } = Tabs;
|
const { TabPane } = Tabs;
|
||||||
|
|
||||||
@@ -12,29 +17,30 @@ const { Content } = Layout;
|
|||||||
|
|
||||||
export default function FooterComponent() {
|
export default function FooterComponent() {
|
||||||
const clientConfig = useRecoilValue<ClientConfig>(clientConfigStateAtom);
|
const clientConfig = useRecoilValue<ClientConfig>(clientConfigStateAtom);
|
||||||
|
const chatOpen = useRecoilValue<ChatVisibilityState>(chatVisibilityAtom);
|
||||||
const { extraPageContent } = clientConfig;
|
const { extraPageContent } = clientConfig;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Content style={{ margin: '80px 16px 0', overflow: 'initial' }}>
|
<Content className={`${s.root}`}>
|
||||||
<div>
|
<Col className={`${s.leftCol}`}>
|
||||||
<Row>
|
<OwncastPlayer source="https://watch.owncast.online" />
|
||||||
<Col span={24}>
|
<div className={`${s.lowerRow}`}>
|
||||||
<OwncastPlayer source="https://watch.owncast.online" />
|
<Tabs defaultActiveKey="1" type="card">
|
||||||
</Col>
|
<TabPane tab="About" key="1">
|
||||||
</Row>
|
<CustomPageContent content={extraPageContent} />
|
||||||
<Row>
|
</TabPane>
|
||||||
<Col span={24}>
|
<TabPane tab="Followers" key="2">
|
||||||
<Tabs defaultActiveKey="1" type="card">
|
<FollowerCollection />
|
||||||
<TabPane tab="About" key="1">
|
</TabPane>
|
||||||
<CustomPageContent content={extraPageContent} />
|
</Tabs>
|
||||||
</TabPane>
|
<Footer />
|
||||||
<TabPane tab="Followers" key="2">
|
</div>
|
||||||
<FollowerCollection />
|
</Col>
|
||||||
</TabPane>
|
{chatOpen && (
|
||||||
</Tabs>
|
<Col>
|
||||||
</Col>
|
<Sidebar />
|
||||||
</Row>
|
</Col>
|
||||||
</div>
|
)}
|
||||||
</Content>
|
</Content>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ const { Footer } = Layout;
|
|||||||
export default function FooterComponent(props) {
|
export default function FooterComponent(props) {
|
||||||
const { version } = props;
|
const { version } = props;
|
||||||
|
|
||||||
return <Footer style={{ textAlign: 'center' }}>Footer: Owncast {version}</Footer>;
|
return <Footer style={{ textAlign: 'center', height: '64px' }}>Footer: Owncast {version}</Footer>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
chatStateAtom,
|
chatStateAtom,
|
||||||
} from '../../stores/ClientConfigStore';
|
} from '../../stores/ClientConfigStore';
|
||||||
import { ChatState, ChatVisibilityState } from '../../../interfaces/application-state';
|
import { ChatState, ChatVisibilityState } from '../../../interfaces/application-state';
|
||||||
import ChatTextField from '../../chat/ChatTextField';
|
import ChatTextField from '../../chat/ChatTextField/ChatTextField';
|
||||||
|
|
||||||
export default function Sidebar() {
|
export default function Sidebar() {
|
||||||
const messages = useRecoilValue<ChatMessage[]>(chatMessagesAtom);
|
const messages = useRecoilValue<ChatMessage[]>(chatMessagesAtom);
|
||||||
@@ -20,13 +20,7 @@ export default function Sidebar() {
|
|||||||
<Sider
|
<Sider
|
||||||
collapsed={chatVisibility === ChatVisibilityState.Hidden}
|
collapsed={chatVisibility === ChatVisibilityState.Hidden}
|
||||||
collapsedWidth={0}
|
collapsedWidth={0}
|
||||||
width={300}
|
width="100%"
|
||||||
style={{
|
|
||||||
position: 'fixed',
|
|
||||||
right: 0,
|
|
||||||
top: 0,
|
|
||||||
bottom: 0,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<ChatContainer messages={messages} state={chatState} />
|
<ChatContainer messages={messages} state={chatState} />
|
||||||
<ChatTextField />
|
<ChatTextField />
|
||||||
|
|||||||
@@ -47,7 +47,11 @@ export function VideoJS(props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-vjs-player>
|
<div data-vjs-player>
|
||||||
<video ref={videoRef} className="video-js vjs-big-play-centered" />
|
<video
|
||||||
|
ref={videoRef}
|
||||||
|
className="video-js vjs-big-play-centered"
|
||||||
|
style={{ width: '100%', height: '100%' }}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||||
import ChatTextField from '../components/chat/ChatTextField';
|
import ChatTextField from '../components/chat/ChatTextField/ChatTextField';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'owncast/Chat/Input text field',
|
title: 'owncast/Chat/Input text field',
|
||||||
|
|||||||
Reference in New Issue
Block a user