10 changed files with 197 additions and 167 deletions
@ -0,0 +1,57 @@ |
|||||||
|
.root { |
||||||
|
position: relative; |
||||||
|
display: grid; |
||||||
|
} |
||||||
|
|
||||||
|
.buttonsLogoTitleSection { |
||||||
|
// margin-left: 1.5vw; |
||||||
|
// margin-right: 1.5vw; |
||||||
|
} |
||||||
|
|
||||||
|
.row { |
||||||
|
margin-bottom: 7px; |
||||||
|
} |
||||||
|
|
||||||
|
.logoTitleSection { |
||||||
|
display: flex; |
||||||
|
@media (max-width: 768px) { |
||||||
|
flex-direction: column; |
||||||
|
.logo { |
||||||
|
margin-left: auto; |
||||||
|
margin-right: auto; |
||||||
|
margin-bottom: 10px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.titleSection { |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
|
||||||
|
.title { |
||||||
|
font-size: 32px; |
||||||
|
font-weight: bold; |
||||||
|
color: black; |
||||||
|
text-transform: uppercase; |
||||||
|
line-height: 30px; |
||||||
|
} |
||||||
|
|
||||||
|
.subtitle { |
||||||
|
font-size: 24px; |
||||||
|
font-weight: 400; |
||||||
|
line-height: 22px; |
||||||
|
color: var(--theme-text-secondary); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.tagList { |
||||||
|
font-family: var(--theme-text-display-font-family); |
||||||
|
color: var(--theme-text-primary); |
||||||
|
|
||||||
|
span { |
||||||
|
display: inline-block; |
||||||
|
margin-right: 8px; |
||||||
|
font-size: 14px; |
||||||
|
font-weight: 300; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,36 @@ |
|||||||
|
import cn from 'classnames'; |
||||||
|
|
||||||
|
import { ServerLogo } from '../../ui'; |
||||||
|
import SocialLinks from '../../ui/SocialLinks/SocialLinks'; |
||||||
|
import { SocialLink } from '../../../interfaces/social-link.model'; |
||||||
|
import s from './ContentHeader.module.scss'; |
||||||
|
|
||||||
|
interface Props { |
||||||
|
name: string; |
||||||
|
title: string; |
||||||
|
summary: string; |
||||||
|
tags: string[]; |
||||||
|
links: SocialLink[]; |
||||||
|
logo: string; |
||||||
|
} |
||||||
|
export default function ContentHeader({ name, title, summary, logo, tags, links }: Props) { |
||||||
|
return ( |
||||||
|
<div className={s.root}> |
||||||
|
<div className={s.logoTitleSection}> |
||||||
|
<div className={s.logo}> |
||||||
|
<ServerLogo src={logo} /> |
||||||
|
</div> |
||||||
|
<div className={s.titleSection}> |
||||||
|
<div className={cn(s.title, s.row)}>{name}</div> |
||||||
|
<div className={cn(s.subtitle, s.row)}>{title || summary}</div> |
||||||
|
<div className={cn(s.tagList, s.row)}> |
||||||
|
{tags.length > 0 && tags.map(tag => <span key={tag}>#{tag} </span>)} |
||||||
|
</div> |
||||||
|
<div className={cn(s.socialLinks, s.row)}> |
||||||
|
<SocialLinks links={links} /> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
@ -0,0 +1 @@ |
|||||||
|
export { default } from './ContentHeader'; |
||||||
@ -1,89 +0,0 @@ |
|||||||
.root { |
|
||||||
position: relative; |
|
||||||
display: grid; |
|
||||||
} |
|
||||||
|
|
||||||
.buttonsLogoTitleSection { |
|
||||||
margin-left: 1.5vw; |
|
||||||
margin-right: 1.5vw; |
|
||||||
} |
|
||||||
|
|
||||||
.logoTitleSection { |
|
||||||
display: flex; |
|
||||||
align-items: center; |
|
||||||
} |
|
||||||
|
|
||||||
.titleSection { |
|
||||||
display: flex; |
|
||||||
flex-direction: column; |
|
||||||
|
|
||||||
.title { |
|
||||||
font-size: 1.5rem; |
|
||||||
font-weight: bold; |
|
||||||
color: var(--theme-text-primary); |
|
||||||
} |
|
||||||
|
|
||||||
.subtitle { |
|
||||||
margin-top: 0.35em; |
|
||||||
font-size: 1.5em; |
|
||||||
font-weight: 300; |
|
||||||
color: var(--theme-text-secondary); |
|
||||||
text-transform: uppercase; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
.mobile { |
|
||||||
&.root { |
|
||||||
position: relative; |
|
||||||
display: flex; |
|
||||||
padding: 0 0.3rem; |
|
||||||
align-items: center; |
|
||||||
justify-content: space-between; |
|
||||||
.mobileInfo { |
|
||||||
display: flex; |
|
||||||
align-items: center; |
|
||||||
.title { |
|
||||||
font-size: 1.2rem; |
|
||||||
font-weight: 600; |
|
||||||
} |
|
||||||
} |
|
||||||
.mobileStatus { |
|
||||||
display: flex; |
|
||||||
font-weight: 600; |
|
||||||
.viewerCount { |
|
||||||
display: flex; |
|
||||||
align-items: center; |
|
||||||
gap: 4px; |
|
||||||
} |
|
||||||
.liveStatus { |
|
||||||
display: flex; |
|
||||||
align-items: center; |
|
||||||
margin-left: 0.5rem; |
|
||||||
font-size: 0.8rem; |
|
||||||
gap: 4px; |
|
||||||
.liveCircle { |
|
||||||
border-radius: 50%; |
|
||||||
background-color: red; |
|
||||||
width: 0.5rem; |
|
||||||
height: 0.5rem; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
.tagList { |
|
||||||
font-family: var(--theme-text-display-font-family); |
|
||||||
color: var(--theme-text-secondary); |
|
||||||
|
|
||||||
ul { |
|
||||||
margin: 0; |
|
||||||
padding: 0; |
|
||||||
} |
|
||||||
|
|
||||||
li { |
|
||||||
display: inline-block; |
|
||||||
margin: 0 0.7em 0 0; |
|
||||||
font-weight: 600; |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,65 +0,0 @@ |
|||||||
import { useRecoilValue } from 'recoil'; |
|
||||||
import cn from 'classnames'; |
|
||||||
import { EyeFilled } from '@ant-design/icons'; |
|
||||||
import { useEffect } from 'react'; |
|
||||||
import { ClientConfig } from '../../../interfaces/client-config.model'; |
|
||||||
import { |
|
||||||
clientConfigStateAtom, |
|
||||||
isOnlineSelector, |
|
||||||
serverStatusState, |
|
||||||
} from '../../stores/ClientConfigStore'; |
|
||||||
import { ServerLogo } from '../../ui'; |
|
||||||
import SocialLinks from '../../ui/SocialLinks/SocialLinks'; |
|
||||||
import s from './StreamInfo.module.scss'; |
|
||||||
import { ServerStatus } from '../../../interfaces/server-status.model'; |
|
||||||
|
|
||||||
interface Props { |
|
||||||
isMobile: boolean; |
|
||||||
} |
|
||||||
export default function StreamInfo({ isMobile }: Props) { |
|
||||||
const { socialHandles, name, title, tags, summary } = |
|
||||||
useRecoilValue<ClientConfig>(clientConfigStateAtom); |
|
||||||
const { viewerCount } = useRecoilValue<ServerStatus>(serverStatusState); |
|
||||||
const online = useRecoilValue<boolean>(isOnlineSelector); |
|
||||||
|
|
||||||
useEffect(() => { |
|
||||||
console.log({ online }); |
|
||||||
}, [online]); |
|
||||||
|
|
||||||
return isMobile ? ( |
|
||||||
<div className={cn(s.root, s.mobile)}> |
|
||||||
<div className={s.mobileInfo}> |
|
||||||
<ServerLogo src="/logo" /> |
|
||||||
<div className={s.title}>{name}</div> |
|
||||||
</div> |
|
||||||
<div className={s.mobileStatus}> |
|
||||||
<div className={s.viewerCount}> |
|
||||||
{online && ( |
|
||||||
<> |
|
||||||
<span>{viewerCount}</span> |
|
||||||
<EyeFilled /> |
|
||||||
</> |
|
||||||
)} |
|
||||||
</div> |
|
||||||
<div className={s.liveStatus}> |
|
||||||
{online && <div className={s.liveCircle} />} |
|
||||||
<span>{online ? 'LIVE' : 'OFFLINE'}</span> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
) : ( |
|
||||||
<div className={s.root}> |
|
||||||
<div className={s.logoTitleSection}> |
|
||||||
<ServerLogo src="/logo" /> |
|
||||||
<div className={s.titleSection}> |
|
||||||
<div className={s.title}>{name}</div> |
|
||||||
<div className={s.subtitle}>{title || summary}</div> |
|
||||||
<div className={s.tagList}> |
|
||||||
{tags.length > 0 && tags.map(tag => <span key={tag}>#{tag} </span>)} |
|
||||||
</div> |
|
||||||
<SocialLinks links={socialHandles} /> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
); |
|
||||||
} |
|
||||||
@ -1 +0,0 @@ |
|||||||
export { default } from './StreamInfo'; |
|
||||||
@ -0,0 +1,76 @@ |
|||||||
|
import React from 'react'; |
||||||
|
import { ComponentStory, ComponentMeta } from '@storybook/react'; |
||||||
|
import ContentHeader from '../components/common/ContentHeader/ContentHeader'; |
||||||
|
|
||||||
|
export default { |
||||||
|
title: 'owncast/Components/Content Header', |
||||||
|
component: ContentHeader, |
||||||
|
parameters: {}, |
||||||
|
} as ComponentMeta<typeof ContentHeader>; |
||||||
|
|
||||||
|
const Template: ComponentStory<typeof ContentHeader> = args => <ContentHeader {...args} />; |
||||||
|
|
||||||
|
export const Example = Template.bind({}); |
||||||
|
Example.args = { |
||||||
|
name: 'My Awesome Owncast Stream', |
||||||
|
summary: 'A calvacade of glorious sights and sounds', |
||||||
|
tags: ['word', 'tag with spaces', 'music'], |
||||||
|
logo: 'https://watch.owncast.online/logo', |
||||||
|
links: [ |
||||||
|
{ |
||||||
|
platform: 'github', |
||||||
|
url: 'https://github.com/owncast/owncast', |
||||||
|
icon: 'https://watch.owncast.online/img/platformlogos/github.svg', |
||||||
|
}, |
||||||
|
{ |
||||||
|
platform: 'Documentation', |
||||||
|
url: 'https://owncast.online', |
||||||
|
icon: 'https://watch.owncast.online/img/platformlogos/link.svg', |
||||||
|
}, |
||||||
|
{ |
||||||
|
platform: 'mastodon', |
||||||
|
url: 'https://fosstodon.org/users/owncast', |
||||||
|
icon: 'https://watch.owncast.online/img/platformlogos/mastodon.svg', |
||||||
|
}, |
||||||
|
], |
||||||
|
}; |
||||||
|
|
||||||
|
export const LongContent = Template.bind({}); |
||||||
|
LongContent.args = { |
||||||
|
name: 'My Awesome Owncast Stream, streaming the best of streams and some lorem ipsum too', |
||||||
|
summary: |
||||||
|
'A calvacade of glorious sights and sounds. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.', |
||||||
|
tags: [ |
||||||
|
'word', |
||||||
|
'tag with spaces', |
||||||
|
'music', |
||||||
|
'more tags', |
||||||
|
'a bunch', |
||||||
|
'keep going', |
||||||
|
'and more', |
||||||
|
'just a few more', |
||||||
|
'video games', |
||||||
|
'things', |
||||||
|
'stuff', |
||||||
|
'ok some more', |
||||||
|
'this should do it', |
||||||
|
], |
||||||
|
logo: 'https://watch.owncast.online/logo', |
||||||
|
links: [ |
||||||
|
{ |
||||||
|
platform: 'github', |
||||||
|
url: 'https://github.com/owncast/owncast', |
||||||
|
icon: 'https://watch.owncast.online/img/platformlogos/github.svg', |
||||||
|
}, |
||||||
|
{ |
||||||
|
platform: 'Documentation', |
||||||
|
url: 'https://owncast.online', |
||||||
|
icon: 'https://watch.owncast.online/img/platformlogos/link.svg', |
||||||
|
}, |
||||||
|
{ |
||||||
|
platform: 'mastodon', |
||||||
|
url: 'https://fosstodon.org/users/owncast', |
||||||
|
icon: 'https://watch.owncast.online/img/platformlogos/mastodon.svg', |
||||||
|
}, |
||||||
|
], |
||||||
|
}; |
||||||
Loading…
Reference in new issue