updated layout on info page, added background image. Work on times/dates
This commit is contained in:
parent
7b9a675e31
commit
90b3a71b2f
1
app.js
1
app.js
@ -52,6 +52,7 @@ export default () => {
|
||||
data={data}
|
||||
loading={loading || !minLoadTimePassed}
|
||||
infoActive={infoActive}
|
||||
// infoActive
|
||||
currentVideo={currentVideo}
|
||||
setInfoActive={setInfoActive}
|
||||
/>
|
||||
|
@ -20,6 +20,7 @@
|
||||
"date-fns": "^2.19.0",
|
||||
"ical": "^0.8.0",
|
||||
"ical.js": "^1.4.0",
|
||||
"markdown-to-jsx": "^7.1.2",
|
||||
"preact": "^10.5.12",
|
||||
"prop-types": "^15.7.2",
|
||||
"styled-components": "^5.2.1"
|
||||
@ -31,6 +32,7 @@
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"eslint": "^4.12.1",
|
||||
"eslint-config-flying-rocket": "^1.1.1",
|
||||
"marked": "^2.0.3",
|
||||
"module-alias": "^2.0.3",
|
||||
"parcel-bundler": "1.12.3",
|
||||
"prettier": "^1.9.1",
|
||||
|
BIN
src/assets/img/hero/1lg.png
Normal file
BIN
src/assets/img/hero/1lg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 906 KiB |
BIN
src/assets/img/hero/1sm.png
Normal file
BIN
src/assets/img/hero/1sm.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 112 KiB |
BIN
src/assets/img/hero/2lg.png
Normal file
BIN
src/assets/img/hero/2lg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 603 KiB |
BIN
src/assets/img/hero/2md.png
Normal file
BIN
src/assets/img/hero/2md.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 178 KiB |
BIN
src/assets/img/hero/2sm.png
Normal file
BIN
src/assets/img/hero/2sm.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 83 KiB |
@ -7,6 +7,7 @@ export const colours = {
|
||||
highlight: '#03a59e',
|
||||
roseDarker: '#FEB9B3',
|
||||
rose: '#F1CFCD',
|
||||
roseLight: '#F8E5E1',
|
||||
}
|
||||
|
||||
colours.text = colours.offwhite
|
||||
|
35
src/components/Button/index.js
Normal file
35
src/components/Button/index.js
Normal file
@ -0,0 +1,35 @@
|
||||
import styled from 'styled-components'
|
||||
import { colours } from '../../assets/theme'
|
||||
|
||||
const Button = styled.button`
|
||||
background-color: transparent;
|
||||
border: 1px solid ${colours.midnightDarker};
|
||||
padding: 0.3em 1em;
|
||||
font-family: Karla;
|
||||
font-weight: inherit;
|
||||
color: ${colours.midnightDarker};
|
||||
opacity: 1;
|
||||
text-decoration: none;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
|
||||
svg {
|
||||
margin-right: 12px;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
:hover {
|
||||
background-color: ${colours.midnightDarker};
|
||||
color: ${colours.roseLight};
|
||||
|
||||
svg {
|
||||
path {
|
||||
stroke: ${colours.roseLight};
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export default Button
|
@ -2,7 +2,8 @@
|
||||
import { h, Fragment } from 'preact'
|
||||
import { isFuture, isPast } from 'date-fns'
|
||||
|
||||
import { P } from '../Text'
|
||||
import { H1 } from '../Text'
|
||||
import Markdown from '../Markdown'
|
||||
import translations from '../../data/strings'
|
||||
import InfoLayout from '../InfoLayout'
|
||||
import {
|
||||
@ -10,8 +11,15 @@ import {
|
||||
Title,
|
||||
InfoContent,
|
||||
PositionedCross as CrossSvg,
|
||||
TopContent,
|
||||
} from './styles'
|
||||
|
||||
import intro from '../../data/intro.md'
|
||||
import credits from '../../data/credits.md'
|
||||
import Button from '../Button'
|
||||
import PlaySvg from '../Svg/Play'
|
||||
import { colours } from '../../assets/theme'
|
||||
|
||||
const Info = ({ data, loading, infoActive, setInfoActive, currentVideo }) => {
|
||||
const pastStreams =
|
||||
data && data.length
|
||||
@ -20,20 +28,34 @@ const Info = ({ data, loading, infoActive, setInfoActive, currentVideo }) => {
|
||||
|
||||
const futureStreams =
|
||||
data && data.length
|
||||
? data.filter(
|
||||
feeditem =>
|
||||
feeditem.id !== (currentVideo && currentVideo.id) &&
|
||||
isFuture(new Date(feeditem.start))
|
||||
)
|
||||
? data
|
||||
.filter(
|
||||
feeditem =>
|
||||
feeditem.id !== (currentVideo && currentVideo.id) &&
|
||||
isFuture(new Date(feeditem.start))
|
||||
)
|
||||
.sort(
|
||||
(a, b) =>
|
||||
// Turn your strings into dates, and then subtract them
|
||||
// to get a value that is either negative, positive, or zero.
|
||||
new Date(a.start) - new Date(b.start)
|
||||
)
|
||||
: []
|
||||
|
||||
console.log({ currentVideo })
|
||||
|
||||
return (
|
||||
<InfoLayout loading={loading}>
|
||||
{infoActive && <CrossSvg onClick={() => setInfoActive(false)} />}
|
||||
{!loading && (
|
||||
<InfoContent>
|
||||
<Fragment>
|
||||
<InfoContent>
|
||||
<H1>The Para-Real:</H1>
|
||||
<H1>Finding the Future in Unexpected Places</H1>
|
||||
<Markdown withLinebreaks>{intro}</Markdown>
|
||||
<Button>
|
||||
<PlaySvg colour={colours.midnightDarker} size="20" />
|
||||
Watch the trailer
|
||||
</Button>
|
||||
</InfoContent>
|
||||
{currentVideo && (
|
||||
<Fragment>
|
||||
<Title>{translations.en.nowPlaying}:</Title>
|
||||
@ -58,7 +80,10 @@ const Info = ({ data, loading, infoActive, setInfoActive, currentVideo }) => {
|
||||
))}
|
||||
</Fragment>
|
||||
) : null}
|
||||
</InfoContent>
|
||||
<InfoContent>
|
||||
<Markdown>{credits}</Markdown>
|
||||
</InfoContent>
|
||||
</Fragment>
|
||||
)}
|
||||
</InfoLayout>
|
||||
)
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { format } from 'date-fns'
|
||||
import { h, Fragment } from 'preact'
|
||||
import styled from 'styled-components'
|
||||
import { colours } from '../../assets/theme'
|
||||
import { colours, textSizes } from '../../assets/theme'
|
||||
import config from '../../data/config'
|
||||
import Logo from '../Logo'
|
||||
import translations from '../../data/strings'
|
||||
@ -10,6 +10,8 @@ import CrossSvg from '../Svg/Cross'
|
||||
import { P, H1, H2, Span, Label } from '../Text'
|
||||
import Link from '../Link'
|
||||
import { bool, instanceOf, string } from 'prop-types'
|
||||
import Markdown from '../Markdown'
|
||||
import Button from '../Button'
|
||||
|
||||
export const Wrapper = styled.div`
|
||||
height: 100vh;
|
||||
@ -34,10 +36,21 @@ export const Wrapper = styled.div`
|
||||
}
|
||||
`
|
||||
|
||||
export const Top = styled.div``
|
||||
|
||||
export const InfoContent = styled.div`
|
||||
max-width: 600px;
|
||||
margin: 0 0 0em 2px;
|
||||
padding-bottom: 1em;
|
||||
|
||||
h1 {
|
||||
display: none;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
@media screen and (max-width: 1000px) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export const PositionedLogo = styled(Logo)`
|
||||
@ -68,18 +81,22 @@ export const PositionedCross = styled(CrossSvg)`
|
||||
}
|
||||
`
|
||||
|
||||
const VCWrapper = styled.div`
|
||||
export const VCWrapper = styled.div`
|
||||
max-width: 600px;
|
||||
margin: 0 0 6em 2px;
|
||||
border-left: 5px solid ${colours.midnightDarker};
|
||||
padding-left: 1em;
|
||||
|
||||
button {
|
||||
margin-top: 16px;
|
||||
}
|
||||
/* border-left: 5px solid ${colours.midnightDarker}; */
|
||||
/* padding-left: 1em; */
|
||||
`
|
||||
|
||||
const VCImg = styled.img`
|
||||
width: 100%;
|
||||
`
|
||||
|
||||
const ItemTitle = styled(H2)`
|
||||
const ItemTitleWrapper = styled.div`
|
||||
margin-bottom: 0.3em;
|
||||
`
|
||||
|
||||
@ -93,46 +110,49 @@ const LinkBlock = styled(Link)`
|
||||
width: 100%;
|
||||
`
|
||||
|
||||
const renderTitles = titles =>
|
||||
titles.split('\\n').map(title => <H2 key={title}>{title}</H2>)
|
||||
|
||||
export const VideoCard = ({
|
||||
title,
|
||||
description,
|
||||
start,
|
||||
end,
|
||||
previewPath,
|
||||
hasPassed,
|
||||
videoUrl,
|
||||
}) => (
|
||||
<VCWrapper>
|
||||
{videoUrl && hasPassed ? (
|
||||
<LinkBlock href={videoUrl}>
|
||||
<ItemTitle>{title}</ItemTitle>
|
||||
<VCImg src={`${config.peertube_root}${previewPath}`} alt="" />
|
||||
</LinkBlock>
|
||||
) : (
|
||||
<Fragment>
|
||||
<ItemTitle>{title}</ItemTitle>
|
||||
<VCImg src={`${config.peertube_root}${previewPath}`} alt="" />
|
||||
</Fragment>
|
||||
)}
|
||||
<DateLabel colour={colours.midnight} size="18">
|
||||
{`${
|
||||
hasPassed
|
||||
? translations.en.streamDatePast
|
||||
: translations.en.streamDateFuture
|
||||
}`}
|
||||
<Span bold colour={colours.midnight}>
|
||||
{format(new Date(start), 'hh:mm dd/MM/yy')}
|
||||
</Span>
|
||||
</DateLabel>
|
||||
<P>{description}</P>
|
||||
</VCWrapper>
|
||||
)
|
||||
}) => {
|
||||
console.log('start', start)
|
||||
return (
|
||||
<VCWrapper>
|
||||
<DateLabel colour={colours.midnight} size={textSizes.lg}>
|
||||
{`${hasPassed ? translations.en.streamDatePast : ''}`}
|
||||
<Span bold colour={colours.midnight}>
|
||||
{hasPassed
|
||||
? format(new Date(start), 'dd/MM/yy')
|
||||
: format(new Date(start), 'do LLLL y // HH:mm')}
|
||||
</Span>
|
||||
</DateLabel>
|
||||
{videoUrl && hasPassed ? (
|
||||
<LinkBlock href={videoUrl}>
|
||||
<ItemTitleWrapper>{renderTitles(title)}</ItemTitleWrapper>
|
||||
<VCImg src={`${config.peertube_root}${previewPath}`} alt="" />
|
||||
</LinkBlock>
|
||||
) : (
|
||||
<Fragment>
|
||||
<ItemTitleWrapper>{renderTitles(title)}</ItemTitleWrapper>
|
||||
<VCImg src={`${config.peertube_root}${previewPath}`} alt="" />
|
||||
</Fragment>
|
||||
)}
|
||||
<P>{description}</P>
|
||||
<Button>Subscribe to this event</Button>
|
||||
</VCWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
VideoCard.propTypes = {
|
||||
title: string,
|
||||
description: string,
|
||||
start: instanceOf(Date),
|
||||
end: instanceOf(Date),
|
||||
previewPath: string,
|
||||
hasPassed: bool,
|
||||
videoUrl: string,
|
||||
|
@ -2,47 +2,58 @@ import { h } from 'preact'
|
||||
import { useEffect, useRef, useState } from 'preact/hooks'
|
||||
import { bool, string } from 'prop-types'
|
||||
|
||||
import { H1, H2 } from '../Text'
|
||||
import { H1, H2, Label, Span } from '../Text'
|
||||
import {
|
||||
Wrapper,
|
||||
PositionedLogo as Logo,
|
||||
TaglineContainer,
|
||||
LoaderWrapper,
|
||||
Content,
|
||||
Fade,
|
||||
Hero,
|
||||
FadeBottom,
|
||||
} from './styles'
|
||||
import translations from '../../data/strings'
|
||||
import { colours } from '../../assets/theme'
|
||||
import Loader from '../Loader'
|
||||
import { useTimeout } from '../../hooks/timerHooks'
|
||||
import { NdcLogo, RFLogo } from '../Logo'
|
||||
|
||||
const InfoLayout = ({ children, loading }) => {
|
||||
return (
|
||||
<Wrapper>
|
||||
<Fade>
|
||||
<Logo active colour={colours.midnightDarker} />
|
||||
</Fade>
|
||||
<Content>
|
||||
{loading ? (
|
||||
<LoaderWrapper>
|
||||
<Loader />
|
||||
</LoaderWrapper>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</Content>
|
||||
|
||||
const InfoLayout = ({ children, loading }) => (
|
||||
<Wrapper>
|
||||
<Content>
|
||||
{loading ? (
|
||||
<LoaderWrapper>
|
||||
<Loader />
|
||||
</LoaderWrapper>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</Content>
|
||||
<Hero>
|
||||
<div>
|
||||
<H1>The</H1>
|
||||
<H1>Para-</H1>
|
||||
<H1>Real</H1>
|
||||
<H1
|
||||
css={`
|
||||
max-width: 50%;
|
||||
`}
|
||||
>
|
||||
Finding the Future in Unexpected Places
|
||||
</H1>
|
||||
</div>
|
||||
<TaglineContainer>
|
||||
{translations &&
|
||||
translations.en.underscoreTagline.map(line => (
|
||||
<H1 align="right" key={line}>
|
||||
{line}
|
||||
</H1>
|
||||
))}
|
||||
<a href="https://newdesigncongress.org/">
|
||||
<NdcLogo active colour={colours.offwhite} />
|
||||
</a>
|
||||
<Label size="24">{'//'}</Label>
|
||||
<a href="https://reclaimfutures.org/">
|
||||
<RFLogo active colour={colours.offwhite} />
|
||||
</a>
|
||||
</TaglineContainer>
|
||||
</Wrapper>
|
||||
)
|
||||
}
|
||||
<FadeBottom />
|
||||
</Hero>
|
||||
</Wrapper>
|
||||
)
|
||||
|
||||
InfoLayout.propTypes = {
|
||||
loading: bool,
|
||||
|
@ -1,25 +1,20 @@
|
||||
import styled from 'styled-components'
|
||||
import { colours } from '../../assets/theme'
|
||||
import bg from '../../assets/img/hero/2md.png'
|
||||
|
||||
import { H1 } from '../Text'
|
||||
|
||||
import Logo from '../Logo'
|
||||
|
||||
const heroWidth = 'calc(100vw - 600px - 4em)'
|
||||
|
||||
export const Wrapper = styled.div`
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
padding: 6em 2em 2em 2em;
|
||||
padding: 2em;
|
||||
display: flex;
|
||||
/* justify-content: space-between; */
|
||||
/* flex-direction: column; */
|
||||
|
||||
background: url(https://images.unsplash.com/photo-1579762715118-a6f1d4b934f1?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=3031&q=80)
|
||||
${colours.rose};
|
||||
background-color: ${colours.roseLight};
|
||||
box-sizing: border-box;
|
||||
background-size: cover;
|
||||
background-position-y: 50%;
|
||||
background-position-x: 23vw;
|
||||
background-blend-mode: soft-light;
|
||||
position: fixed;
|
||||
overflow-y: scroll;
|
||||
|
||||
@ -30,14 +25,10 @@ export const Wrapper = styled.div`
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
padding: 6em 1.5em 1.5em 1.5em;
|
||||
background-size: 150%;
|
||||
background-position-x: 0vw;
|
||||
padding: 1.5em;
|
||||
}
|
||||
@media screen and (max-width: 800px) {
|
||||
padding: 6em 1em 1em 1em;
|
||||
background-size: 250%;
|
||||
background-position-x: -50vw;
|
||||
padding: 1em;
|
||||
}
|
||||
`
|
||||
|
||||
@ -45,9 +36,14 @@ export const Top = styled.div`
|
||||
width: 50%;
|
||||
`
|
||||
|
||||
const gradientColour = '#F8E5E2'
|
||||
const getGradient = direction =>
|
||||
`linear-gradient(to ${direction}, ${gradientColour}ee 0%,${gradientColour}00 100%);`
|
||||
const gradientColourLight = '#F8E5E2'
|
||||
const gradientColourDark = colours.midnightDarker
|
||||
const getGradient = (direction, lightDark) =>
|
||||
`linear-gradient(to ${direction}, ${
|
||||
lightDark === 'dark' ? gradientColourDark : gradientColourLight
|
||||
}ee 0%,${
|
||||
lightDark === 'dark' ? gradientColourDark : gradientColourLight
|
||||
}00 100%);`
|
||||
|
||||
// prettier-ignore
|
||||
export const Fade = styled.div`
|
||||
@ -59,6 +55,44 @@ export const Fade = styled.div`
|
||||
left: 0;
|
||||
background: ${getGradient('bottom')};
|
||||
`
|
||||
|
||||
export const Hero = styled.div`
|
||||
width: ${heroWidth};
|
||||
height: 100vh;
|
||||
background: url(${bg});
|
||||
background-size: cover;
|
||||
background-position-x: right;
|
||||
position: fixed;
|
||||
padding: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
padding: 2em 2em 8px 2em;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
pointer-events: none;
|
||||
h1,
|
||||
h2 {
|
||||
color: ${colours.offwhite};
|
||||
}
|
||||
|
||||
h1:not(:last-of-type) {
|
||||
font-size: 30vh;
|
||||
|
||||
@media screen and (max-height: 600px) {
|
||||
font-size: 20vh;
|
||||
}
|
||||
@media screen and (max-width: 1200px) {
|
||||
font-size: 20vh;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1000px) {
|
||||
display: none;
|
||||
}
|
||||
`
|
||||
|
||||
export const LoaderWrapper = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@ -66,7 +100,7 @@ export const LoaderWrapper = styled.div`
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 50vw;
|
||||
width: 600px;
|
||||
`
|
||||
|
||||
export const Content = styled.div`
|
||||
@ -75,27 +109,37 @@ export const Content = styled.div`
|
||||
|
||||
export const PositionedLogo = styled(Logo)``
|
||||
|
||||
export const TaglineContainer = styled.div`
|
||||
background: ${getGradient('top')};
|
||||
export const FadeBottom = styled.div`
|
||||
background: ${getGradient('top', 'dark')};
|
||||
width: ${heroWidth};
|
||||
position: fixed;
|
||||
bottom: 0em;
|
||||
padding-bottom: 0.5em;
|
||||
right: 1em;
|
||||
right: 0;
|
||||
/* left: 0; */
|
||||
pointer-events: none;
|
||||
min-height: 75px;
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
width: 100vw;
|
||||
right: auto;
|
||||
left: 1.5em;
|
||||
h1 {
|
||||
font-size: 32px;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
/* @media screen and (max-width: 800px) {
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
}
|
||||
} */
|
||||
`
|
||||
|
||||
export const TaglineContainer = styled.div`
|
||||
width: 100%;
|
||||
bottom: 0em;
|
||||
padding-bottom: 0.5em;
|
||||
right: 0;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
a {
|
||||
pointer-events: all;
|
||||
}
|
||||
`
|
||||
|
File diff suppressed because one or more lines are too long
49
src/components/Markdown/index.js
Normal file
49
src/components/Markdown/index.js
Normal file
@ -0,0 +1,49 @@
|
||||
/* eslint-disable jsx-a11y/anchor-has-content */
|
||||
import { h, Fragment } from 'preact'
|
||||
import MarkdownRenderer from 'markdown-to-jsx'
|
||||
import { MarkdownWrapper } from './styles'
|
||||
import { P, A, H1, H2, Span } from '../Text'
|
||||
|
||||
const Markdown = ({ children, withLinebreaks, options, ...rest }) => (
|
||||
<MarkdownWrapper $withLinebreaks={withLinebreaks}>
|
||||
<MarkdownRenderer
|
||||
options={{
|
||||
overrides: {
|
||||
p: {
|
||||
component: P,
|
||||
},
|
||||
span: {
|
||||
component: P,
|
||||
},
|
||||
em: {
|
||||
component: ({ children: spanChildren }) => (
|
||||
<Span fontStyle="italic">{spanChildren}</Span>
|
||||
),
|
||||
},
|
||||
a: {
|
||||
component: props => (
|
||||
<A
|
||||
data-hoverable
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
},
|
||||
h1: {
|
||||
component: H1,
|
||||
},
|
||||
h2: {
|
||||
component: H2,
|
||||
},
|
||||
},
|
||||
...options,
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</MarkdownRenderer>
|
||||
</MarkdownWrapper>
|
||||
)
|
||||
|
||||
export default Markdown
|
40
src/components/Markdown/styles.js
Normal file
40
src/components/Markdown/styles.js
Normal file
@ -0,0 +1,40 @@
|
||||
import { h } from 'preact'
|
||||
import styled from 'styled-components'
|
||||
import { colours } from '../../assets/theme'
|
||||
import { P } from '../Text'
|
||||
|
||||
export const MarkdownWrapper = styled.span`
|
||||
a {
|
||||
color: ${colours.highlight};
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 200px;
|
||||
float: left;
|
||||
padding: 0 12px 6px 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: ${props => (props.$withLinebreaks ? '32px' : '0')};
|
||||
}
|
||||
|
||||
p > p {
|
||||
display: inline;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-left: 1em;
|
||||
}
|
||||
ul {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
`
|
19
src/components/Svg/Play.js
Normal file
19
src/components/Svg/Play.js
Normal file
@ -0,0 +1,19 @@
|
||||
import { h } from 'preact'
|
||||
import { number, string } from 'prop-types'
|
||||
|
||||
const Play = ({ size = '24', colour = 'inherit', ...rest }) => (
|
||||
<svg viewBox="0 0 24 24" height={size} width={size} {...rest}>
|
||||
<path
|
||||
stroke={colour}
|
||||
fill="transparent"
|
||||
d="M2.12436,1.73205 C2.12436,0.96225 2.95769,0.481125 3.62436,0.866025 L21.6244,11.2583 C22.291,11.6432 22.291,12.6055 21.6244,12.9904 L3.62436,23.3827 C2.95769,23.7676 2.12436,23.2865 2.12436,22.5167 L2.12436,1.73205 Z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
|
||||
Play.propTypes = {
|
||||
size: number,
|
||||
colour: string,
|
||||
}
|
||||
|
||||
export default Play
|
@ -13,7 +13,9 @@ const Text = ({
|
||||
fontFamily = 'Karla',
|
||||
children,
|
||||
size,
|
||||
sizeUnit,
|
||||
selectable = true,
|
||||
fontStyle,
|
||||
...rest
|
||||
}) => {
|
||||
const colour = colourProp || colours.text
|
||||
@ -26,6 +28,8 @@ const Text = ({
|
||||
lineHeight={lineHeight}
|
||||
$fontFamily={fontFamily}
|
||||
$size={size}
|
||||
$sizeUnit={sizeUnit}
|
||||
$fontStyle={fontStyle}
|
||||
selectable={selectable}
|
||||
{...rest}
|
||||
>
|
||||
@ -61,20 +65,18 @@ Text.propTypes = {
|
||||
selectable: bool,
|
||||
}
|
||||
|
||||
export const H1 = ({ children, ...rest }) => {
|
||||
return (
|
||||
<Text
|
||||
tag="h1"
|
||||
weight="700"
|
||||
$size="48"
|
||||
lineHeight="0.8"
|
||||
fontFamily="Lunchtype24"
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
export const H1 = ({ children, size, ...rest }) => (
|
||||
<Text
|
||||
tag="h1"
|
||||
weight="700"
|
||||
$size={size || '48'}
|
||||
lineHeight="0.8"
|
||||
fontFamily="Lunchtype24"
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</Text>
|
||||
)
|
||||
|
||||
export const H2 = ({ children, ...rest }) => (
|
||||
<Text
|
||||
@ -102,7 +104,7 @@ export const P = ({ children, ...rest }) => (
|
||||
</Text>
|
||||
)
|
||||
export const Span = ({ children, ...rest }) => (
|
||||
<Text tag="span" $size="inherit" weight="inherit" {...rest}>
|
||||
<Text tag="span" colour="inherit" $size="inherit" weight="inherit" {...rest}>
|
||||
{children}
|
||||
</Text>
|
||||
)
|
||||
|
@ -4,6 +4,7 @@ import { colours } from '../../assets/theme'
|
||||
export const TextBase = styled.span`
|
||||
${({
|
||||
$size,
|
||||
$fontStyle,
|
||||
weight,
|
||||
colour,
|
||||
align,
|
||||
@ -12,6 +13,7 @@ export const TextBase = styled.span`
|
||||
$fontFamily: fontFamily,
|
||||
selectable,
|
||||
underline,
|
||||
$sizeUnit,
|
||||
}) => css`
|
||||
font-family: ${fontFamily};
|
||||
font-weight: ${weight};
|
||||
@ -21,7 +23,8 @@ export const TextBase = styled.span`
|
||||
opacity: ${opacity};
|
||||
user-select: ${selectable ? 'inherit' : 'none'};
|
||||
text-decoration: ${underline ? 'underline' : 'none'};
|
||||
font-size: ${$size}px;
|
||||
font-size: ${`${$size}${$sizeUnit || 'px'}`};
|
||||
font-style: ${$fontStyle};
|
||||
|
||||
::selection {
|
||||
background-color: ${colours.midnightDarker};
|
||||
|
23
src/data/credits.md
Normal file
23
src/data/credits.md
Normal file
@ -0,0 +1,23 @@
|
||||
## Credits
|
||||
|
||||
A [NEW DESIGN CONGRESS](https://newdesigncongress.org) project
|
||||
|
||||
Stream Design by **[BENJAMIN JONES](https://benjaminjon.es)**
|
||||
|
||||
Host & Research by **[CADE DIEHM](https://shiba.computer)**
|
||||
|
||||
Stream Backgrounds by **[IGNATIUS GILFEDDER](https://ignatius.design)**
|
||||
|
||||
Series operated by **[ReclaimFutures](https://reclaimfutures.org)**
|
||||
|
||||
Infrastructure by **[UNDERSCO.RE](https://undersco.re)**
|
||||
|
||||
Music \*\*\*\*by:
|
||||
|
||||
- [♥ GOJII ♥](https://gojii.bandcamp.com/)
|
||||
- [音 LIGHT システム](https://saphronsquares.bandcamp.com/)
|
||||
- [ABELARD](https://abelard.bandcamp.com/)
|
||||
- [Frog of Earth](https://frogoftheearth.bandcamp.com/)
|
||||
- [spatial manufacture ltd.](https://spatialmanufactureltd.bandcamp.com/)\*\*
|
||||
|
||||
Simulcasted at [UNDERSCORE TV](https://stream.undersco.re) and [Twitch](https://twitch.tv/newdesigncongress)
|
7
src/data/intro.md
Normal file
7
src/data/intro.md
Normal file
@ -0,0 +1,7 @@
|
||||
[NEW DESIGN CONGRESS](https://newdesigncongress.org) x [RECLAIMFUTURES](https://reclaimfutures.org) present _The Para-Real: Finding the Future in Unexpected Places,_ a Spring/Summer livestream series about economic subcultures and emergent technology use. Over 12 episodes streamed weekly, we meet filmmakers who have never met their actors, artists building their own networks of value, documentarians exploring digital identity, and members of resilient subcultures. All of these people share a commonality: they have an innate understanding of the _Para-Real,_ and have seized upon it to better their surroundings.
|
||||
|
||||
Between the digital realm and our physical world is a third space, equally material but poorly understood. The _Para-Real_ is a tangible place where class structures, economics and the outcomes of hardware and infrastructure design collide. The Para-Real manifests in many ways — It can be the desire for play that turns young Minecraft players into network administrators, the drive that fosters the resilience of subculture-driven mutually-supportive marketplaces, or the tension of class structures inherent in Virtual Reality's encroachment on living room space.
|
||||
|
||||
_We shape our tools, and thereafter our tools shape us._
|
||||
|
||||
The Para-Real is everywhere. Whether attending a Furcon at the height of pandemic, organising community for resilience, or navigating a commissioned open world, we must consider ourselves as inhabiting not a real or online world, but a bridge between the two, one whose rules are not yet settled. _The future is not a Zoom call_. The digital systems we are confined to today merge protocol with platform to prey on isolation and extract value from labour. That we grapple with this incarnation of the digital realm indicates a dominant cartel in decline. In its place is a vacuum. We must resist the immature groupthink of the 90s’ vision of what the Internet can be — the Para-Real is a contested space*. Never trust someone who says the Internet is boring.* Thanks to the Para-Real, the Internet has never been weirder.
|
@ -1,11 +1,13 @@
|
||||
export default {
|
||||
en: {
|
||||
nextStream: 'Next streams',
|
||||
nextStream: 'Program',
|
||||
pastStream: 'Latest streams',
|
||||
nowPlaying: 'Now playing',
|
||||
noStreams: 'No upcoming streams, check back soon.',
|
||||
underscoreTagline: ['LEAVE THE', 'SURVEILLANCE ECONOMY', '— TOGETHER.'],
|
||||
streamDateFuture: 'Going live at: ',
|
||||
streamDatePast: 'First broadcast: ',
|
||||
main_text:
|
||||
"[NEW DESIGN CONGRESS](https://newdesigncongress.org) x [RECLAIMFUTURES](https://reclaimfutures.org) present *The Para-Real: Finding the Future in Unexpected Places,* a Spring/Summer livestream series about economic subcultures and emergent technology use. Over 12 episodes streamed weekly, we meet filmmakers who have never met their actors, artists building their own networks of value, documentarians exploring digital identity, and members of resilient subcultures. All of these people share a commonality: they have an innate understanding of the *Para-Real,* and have seized upon it to better their surroundings. \nBetween the digital realm and our physical world is a third space, equally material but poorly understood. The *Para-Real* is a tangible place where class structures, economics and the outcomes of hardware and infrastructure design collide. The Para-Real manifests in many ways — It can be the desire for play that turns young Minecraft players into network administrators, the drive that fosters the resilience of subculture-driven mutually-supportive marketplaces, or the tension of class structures inherent in Virtual Reality's encroachment on living room space.\n\nWe shape our tools, and thereafter our tools shape us.* The Para-Real is everywhere. Whether attending a Furcon at the height of pandemic, organising community for resilience, or navigating a commissioned open world, we must consider ourselves as inhabiting not a real or online world, but a bridge between the two, one whose rules are not yet settled. *The future is not a Zoom call*. The digital systems we are confined to today merge protocol with platform to prey on isolation and extract value from labour. That we grapple with this incarnation of the digital realm indicates a dominant cartel in decline. In its place is a vacuum. We must resist the immature groupthink of the 90s’ vision of what the Internet can be — the Para-Real is a contested space*. Never trust someone who says the Internet is boring.* Thanks to the Para-Real, the Internet has never been weirder.",
|
||||
},
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ export const useEventStream = () => {
|
||||
calEvents.map(async calItem => {
|
||||
const url = calItem.component.getAllProperties('url')[0]
|
||||
if (url) {
|
||||
console.log('url', url)
|
||||
const id = url
|
||||
.getFirstValue()
|
||||
.split('/')
|
||||
@ -61,6 +60,14 @@ export const useEventStream = () => {
|
||||
videoUrl: url.getFirstValue(),
|
||||
}
|
||||
setData(arr => [...arr, item])
|
||||
} else {
|
||||
const item = {
|
||||
title: calItem.summary,
|
||||
description: calItem.description,
|
||||
start: calItem.startDate.toJSDate(),
|
||||
end: calItem.endDate.toJSDate(),
|
||||
}
|
||||
setData(arr => [...arr, item])
|
||||
}
|
||||
})
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user