Community Page (#9)

This commit is contained in:
Fede Álvarez 2022-04-04 16:21:00 +02:00 committed by GitHub
parent 9815117da5
commit c9278a1075
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 871 additions and 3 deletions

View File

@ -70,7 +70,7 @@
"typescript": "^4.6.3"
},
"engines": {
"node": "14.x",
"node": ">=14.x",
"yarn": "1.x"
},
"browserslist": [

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

View File

@ -0,0 +1,3 @@
<svg width="23" height="23" viewBox="0 0 23 23" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.75817 23H23L23 3.75817L20.4767 3.74743L20.4874 18.6835L1.80392 0L0 1.80392L18.6835 20.4874L3.74743 20.4767L3.75817 23Z" fill="#FBFBFB"/>
</svg>

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 785 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

View File

@ -0,0 +1,72 @@
@import '~/css/helpers';
.cardContainer {
width: 100%;
display: flex;
flex-direction: column;
.eventHeader {
display: flex;
flex-direction: column;
gap: tovw(14px, 'default', 8px);
font-size: tovw(18px, 'default', 12px);
font-family: var(--font-dm-mono), sans-serif;
font-weight: 400;
line-height: 1.2;
letter-spacing: -0.02rem;
.date,
.hour {
display: flex;
align-items: center;
gap: tovw(10px, 'default', 6px);
svg {
height: tovw(18px, 'default', 12px);
margin-bottom: tovw(1px, 'default', 1px);
}
}
div {
display: flex;
gap: tovw(30px, 'default', 25px);
color: var(--color-grey-light);
}
}
.imageContainer {
margin: tovw(25px, 'default', 16px) 0;
width: 100%;
height: tovw(232px, 'default', 200px);
border-top: tovw(1px, 'default', 1px) solid var(--color-white);
border-bottom: tovw(1px, 'default', 1px) solid var(--color-white);
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.body {
display: flex;
flex-direction: column;
gap: tovw(24px, 'default', 18px);
a {
padding-top: tovw(20px, 'default', 12px);
width: fit-content;
}
p {
margin: 0;
font-weight: 400;
line-height: 1.4;
font-size: tovw(18px, 'default', 15px);
@media screen and (max-width: 800px) {
line-height: 1.6;
}
}
}
}

View File

@ -0,0 +1,42 @@
import { Calendar, Clock } from '~/components/icons/events'
import Heading from '~/components/primitives/heading'
import Link from '~/components/primitives/link'
import s from './card.module.scss'
interface Props {
className?: string
data?: any
}
function Card({ className, data }: Props) {
return (
<div className={`${s.cardContainer} ${className}`}>
<div className={s.eventHeader}>
<span className={s.location}>{data?.location?.toUpperCase()}</span>
<div>
<span className={s.date}>
<Calendar />
{data?.date}
</span>
<span className={s.hour}>
<Clock />
{data?.time} HS
</span>
</div>
</div>
<div className={s.imageContainer}>
<img src={data?.imgSrc} alt="preview" />
</div>
<div className={s.body}>
<Heading as="h2" variant="sm" font="tthoves">
{data?.title}
</Heading>
<p>{data?.preview}</p>
<Link href={data?.link}>LEARN MORE</Link>
</div>
</div>
)
}
export default Card

View File

@ -65,4 +65,37 @@ const ArrowLink = ({
)
}
export { Arrow, ArrowDotted, ArrowLink }
const ArrowSlider = ({
className,
fill,
onClick,
disabled
}: {
className?: string
fill?: string
onClick?: any
disabled?: any
}) => {
return (
<svg
onClick={onClick}
className={className}
fill="none"
viewBox="0 0 50 18"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M40 17L48 9L40 1"
stroke={fill || (!disabled ? 'var(--color-white)' : 'grey')}
strokeWidth="1.5"
/>
<path
d="M48 9H0"
stroke={fill || (!disabled ? 'var(--color-white)' : 'grey')}
strokeWidth="1.5"
/>
</svg>
)
}
export { Arrow, ArrowDotted, ArrowLink, ArrowSlider }

View File

@ -0,0 +1,28 @@
const Calendar = ({ className }: { className?: string }) => {
return (
<svg
className={className}
viewBox="0 0 18 20"
fill="#8E8E8E"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M6 9H4V11H6V9ZM10 9H8V11H10V9ZM14 9H12V11H14V9ZM16 2H15V0H13V2H5V0H3V2H2C0.89 2 0.00999999 2.9 0.00999999 4L0 18C0 18.5304 0.210714 19.0391 0.585786 19.4142C0.960859 19.7893 1.46957 20 2 20H16C17.1 20 18 19.1 18 18V4C18 2.9 17.1 2 16 2ZM16 18H2V7H16V18Z" />
</svg>
)
}
const Clock = ({ className }: { className?: string }) => {
return (
<svg
className={className}
viewBox="0 0 20 20"
fill="#8E8E8E"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M10 0C4.486 0 0 4.486 0 10C0 15.514 4.486 20 10 20C15.514 20 20 15.514 20 10C20 4.486 15.514 0 10 0ZM10 18C5.589 18 2 14.411 2 10C2 5.589 5.589 2 10 2C14.411 2 18 5.589 18 10C18 14.411 14.411 18 10 18Z" />
<path d="M11 5H9V10.414L12.293 13.707L13.707 12.293L11 9.586V5Z" />
</svg>
)
}
export { Calendar, Clock }

View File

@ -225,4 +225,28 @@ const Instagram = ({
)
}
export { Facebook, Instagram, Linkedin, Reddit, Telegram, Twitter }
const Discourse = ({
className,
fill
}: {
className?: string
fill?: string
}) => {
return (
<svg
className={className}
viewBox="0 0 30 30"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M15.123 0.375C7.11867 0.375 0.375 6.80599 0.375 14.7451C0.375 14.9994 0.381592 29.625 0.381592 29.625L15.123 29.6118C23.1342 29.6118 29.625 22.9325 29.625 14.9934C29.625 7.05428 23.1342 0.375 15.123 0.375ZM15 6C19.9703 6 24 10.0297 24 15C24 19.9703 19.9703 24 15 24C13.4025 24 11.9038 23.5788 10.6033 22.8486L6 24L7.26123 19.5791C6.46473 18.237 6 16.6751 6 15C6 10.0297 10.0297 6 15 6Z"
fill={fill || 'var(--color-white)'}
/>
</svg>
)
}
export { Discourse, Facebook, Instagram, Linkedin, Reddit, Telegram, Twitter }

View File

@ -0,0 +1,123 @@
@import '~/css/helpers';
.section {
display: flex;
place-content: center;
align-items: center;
margin-top: tovw(55px, 'default', 20px);
padding: tovw(220px, 'default', 72px) 0;
.heading {
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: tovw(1px, 'default', 1px) solid #fbfbfb;
padding-bottom: tovw(60px, 'default', 30px);
margin-bottom: tovw(80px, 'default', 64px);
@media screen and (max-width: 800px) {
flex-direction: column;
align-items: flex-start;
border-bottom: unset;
padding-bottom: unset;
gap: tovw(16px, 'mobile');
}
h2 {
text-shadow: 0px 0px tovw(20px, 'default', 20px) rgb(255 255 255 / 0.4);
}
span {
line-height: 1.32;
font-size: tovw(24px, 'default', 18px);
font-family: var(--font-tt-hoves), sans-serif;
width: tovw(350px, 'default', 265px);
}
.gradient {
position: absolute;
z-index: -1;
left: 0;
right: 0;
width: 100vw;
margin-left: 0;
height: tovw(500px, 'default', 250px);
content: '';
user-select: none;
pointer-events: none;
opacity: 0.4;
background: linear-gradient(
180deg,
rgb(229 229 229 / 0) 0%,
rgb(241 241 241 / 0.4) 48.91%,
rgb(241 241 241 / 0) 89.23%
);
@media screen and (max-width: 800px) {
display: none;
}
}
}
.eventsContainer {
display: grid;
grid-auto-flow: column;
&::after,
&::before {
position: absolute;
content: '';
height: 100%;
width: tovw(280px, 'default', 150px);
right: 0;
background: linear-gradient(
90deg,
rgb(3 3 3 / 0) 0%,
rgb(3 3 3 / 0.95) 35%,
rgb(3 3 3 / 1) 65%
);
@media screen and (max-width: 800px) {
background: linear-gradient(
90deg,
rgb(3 3 3 / 0) 0%,
rgb(3 3 3 / 0.55) 35%,
rgb(3 3 3 / 1) 95%
);
width: tovw(20px, 'default', 20px);
}
}
&::before {
left: 0;
z-index: 1;
background: linear-gradient(
270deg,
rgb(3 3 3 / 0) 0%,
rgb(3 3 3 / 0.95) 35%,
rgb(3 3 3 / 1) 65%
);
}
}
.navigation {
display: flex;
place-content: center;
width: 100%;
gap: tovw(25px, 'default', 15px);
padding-top: tovw(75px, 'default', 45px);
@media screen and (max-width: 800px) {
display: none;
}
.arrow {
cursor: pointer;
width: tovw(50px, 'default', 30px);
&:first-child {
transform: rotate(180deg);
}
}
}
}

View File

@ -0,0 +1,42 @@
export const events = [
{
location: 'California, US',
date: '01.31.22',
time: '20:30',
imgSrc: '/images/community/events/card01.png',
title: 'ETH Denver',
preview:
'Sit sed dolor felis quis. Porttitor semper enim placerat luctus purus aliquam. Diam eu varius donec sit urna feugiat libero diam augue.',
link: 'https://google.com'
},
{
location: 'San Francisco, US',
date: '04.25.22',
time: '19:30',
imgSrc: '/images/community/events/card02.png',
title: 'Devconnect',
preview:
'Sit sed dolor felis quis. Porttitor semper enim placerat luctus purus aliquam. Diam eu varius donec sit urna feugiat libero diam augue.',
link: 'https://google.com'
},
{
location: 'Paris, FR',
date: '06.25.22',
time: '19:30',
imgSrc: '/images/community/events/card03.png',
title: 'Paris Blockchain Week',
preview:
'Sit sed dolor felis quis. Porttitor semper enim placerat luctus purus aliquam. Diam eu varius donec sit urna feugiat libero diam augue.',
link: 'https://google.com'
},
{
location: 'Amsterdam, NL',
date: '08.25.22',
time: '19:30',
imgSrc: '/images/community/events/card04.png',
title: 'ETHCC',
preview:
'Sit sed dolor felis quis. Porttitor semper enim placerat luctus purus aliquam. Diam eu varius donec sit urna feugiat libero diam augue.',
link: 'https://google.com'
}
]

View File

@ -0,0 +1,83 @@
import { useKeenSlider } from 'keen-slider/react'
import { useState } from 'react'
import Card from '~/components/common/card'
import { ArrowSlider } from '~/components/icons/arrow'
import { Container } from '~/components/layout/container'
import Section from '~/components/layout/section'
import Heading from '~/components/primitives/heading'
import { events } from './events'
import s from './events.module.scss'
const Events = () => {
const [currentSlide, setCurrentSlide] = useState(0)
const [loaded, setLoaded] = useState(false)
const [slideHasEnded, setSlideHasEnded] = useState(false)
const [sliderRef, slider] = useKeenSlider<HTMLDivElement>({
initial: 0,
loop: false,
slideChanged(slider) {
setCurrentSlide(slider.track.details.rel)
},
detailsChanged: (slider) => {
setSlideHasEnded(slider.track.details.progress >= 1 ? true : false)
},
created() {
setLoaded(true)
},
breakpoints: {
'(max-width: 1050px)': {
slides: { perView: 1, spacing: 12 }
},
'(min-width: 1050px)': {
slides: { perView: 2, spacing: 22 }
},
'(min-width: 1600px)': {
slides: { perView: 3, spacing: 26 }
}
}
})
return (
<Section className={s['section']}>
<Container className={s.container}>
<div className={s.heading}>
<Heading as="h2" variant="lg">
Events
</Heading>
<span>
Wed love to meet you in person. Find us at a conference near you:
</span>
<div className={s.gradient} />
</div>
<div className={`${s.eventsContainer} keen-slider`} ref={sliderRef}>
{events.map((event, i) => (
<Card key={i} data={event} className={`keen-slider__slide`} />
))}
</div>
{loaded && slider.current && (
<div className={s.navigation}>
<ArrowSlider
onClick={(e: any) =>
e.stopPropagation() || slider.current?.prev()
}
disabled={currentSlide === 0}
className={s['arrow']}
/>
<ArrowSlider
onClick={(e: any) =>
e.stopPropagation() || slider.current?.next()
}
disabled={slideHasEnded}
className={s['arrow']}
/>
</div>
)}
</Container>
</Section>
)
}
export default Events

View File

@ -0,0 +1,135 @@
@import '~/css/helpers';
.section {
display: grid;
align-items: center;
gap: tovw(140px, 'default', 80px) tovw(130px, 'default', 30px);
justify-content: center;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(2, 1fr);
min-height: calc(var(--vh) * 100);
max-width: 100%;
@media screen and (max-width: 800px) {
display: flex;
flex-direction: column;
width: 100vw;
padding: 0 tovw(27px, 'tablet', 27px);
padding-bottom: tovw(18px, 'mobile');
min-height: 100vh;
}
img {
position: absolute;
z-index: -2;
width: tovw(1050px, 'default', 400px);
padding-top: tovw(150px, 'default', 90px);
@media screen and (max-width: 800px) {
position: unset;
width: 110vw;
padding-top: tovw(55px, 'mobile');
margin-bottom: tovw(-85px, 'mobile');
}
}
.headingContainer {
justify-self: end;
align-self: end;
width: tovw(580px, 'default', 80px);
@media screen and (max-width: 800px) {
display: flex;
align-self: flex-start;
align-items: flex-end;
justify-content: space-between;
width: 100%;
}
h1 {
margin: 0;
text-shadow: 0px 0px tovw(20px, 'default', 20px) rgb(255 255 255 / 0.4);
@media screen and (max-width: 800px) {
font-size: tovw(50px, 'mobile');
}
}
}
.textContainer {
display: flex;
flex-direction: column;
gap: tovw(60px, 'default', 20px);
align-self: start;
grid-area: 2 / 2 / 3 / 3;
@media screen and (max-width: 800px) {
width: 100%;
gap: tovw(120px, 'default', 30px);
}
p {
margin: 0;
width: tovw(500px, 'default', 370px);
line-height: 1.3;
@media screen and (max-width: 800px) {
width: tovw(150px, 'mobile', 320px);
}
}
a {
width: fit-content;
}
}
.buttonsContainer {
display: flex;
gap: tovw(24px, 'default', 20px);
@media screen and (max-width: 800px) {
width: 100%;
flex-direction: column;
gap: tovw(20px, 'mobile');
}
}
.gradient {
position: absolute;
top: 0;
width: 100%;
height: 55%;
background: linear-gradient(
180deg,
rgb(0 0 244 / 0.9) 1.63%,
rgb(0 0 244 / 0) 99.89%
);
z-index: -1;
@media screen and (max-width: 800px) {
height: 75%;
mix-blend-mode: screen;
}
}
.arrow {
position: absolute;
margin-left: tovw(-58px, 'default', -58px);
width: tovw(22px, 'default', 15px);
height: tovw(22px, 'default', 15px);
@media screen and (max-width: 800px) {
display: none;
}
}
.arrowMobile {
width: tovw(25px, 'default', 25px);
height: tovw(25px, 'default', 25px);
margin-bottom: tovw(8px, 'default', 7px);
@media screen and (min-width: 801px) {
display: none;
}
}
}

View File

@ -0,0 +1,38 @@
import { Arrow } from '~/components/icons/arrow'
import Section from '~/components/layout/section'
import { Button } from '~/components/primitives/button'
import Heading from '~/components/primitives/heading'
import Link from '~/components/primitives/link'
import s from './hero.module.scss'
const Hero = () => {
return (
<Section className={s['section']}>
<div className={s.gradient}></div>
<img src="/images/community/hero/hero2.png" alt="hero" />
<div className={s.headingContainer}>
<Heading as="h1" variant="xl">
Laconic Community
</Heading>
<Arrow className={s.arrowMobile} />
</div>
<div className={s.textContainer}>
<Arrow className={s.arrow} />
<p>
Join us as we accelerate blockchain development and interoperability
by expanding access to verifiable data.
</p>
<Link href="https://google.com">LEARN MORE</Link>
<div className={s.buttonsContainer}>
<Button size="large">CHAT WITH US</Button>
<Button size="large" variant="primary">
Get Started
</Button>
</div>
</div>
</Section>
)
}
export default Hero

View File

@ -0,0 +1,68 @@
import Line from '~/components/icons/line'
import {
Discourse,
Facebook,
Instagram,
Linkedin,
Reddit,
Telegram,
Twitter
} from '~/components/icons/socials'
import { Container } from '~/components/layout/container'
import Section from '~/components/layout/section'
import Heading from '~/components/primitives/heading'
import s from './socials.module.scss'
const Socials = () => {
return (
<Section className={s['section']}>
<Container className={s.container}>
<img
className={s.planetImage}
src="/images/community/socials/planet.png"
alt="planet figure"
/>
<div>
<div className={s.headingContainer}>
<Heading as="h2" variant="xl" centered={false}>
Socials
</Heading>
<Heading as="h2" variant="xl" centered={false}>
Connect With Us
</Heading>
</div>
<Line className={s['line']} height={144} />
</div>
<div className={s.socialIconsContainer}>
<span>GET IN TOUCH</span>
<div className={s.iconsGrid}>
<button aria-label="instagram">
<Instagram />
</button>
<button aria-label="facebook">
<Facebook />
</button>
<button aria-label="linkedin">
<Linkedin />
</button>
<button aria-label="reddit">
<Reddit />
</button>
<button aria-label="telegram">
<Telegram />
</button>
<button aria-label="twitter">
<Twitter />
</button>
<button aria-label="discourse">
<Discourse />
</button>
</div>
</div>
</Container>
</Section>
)
}
export default Socials

View File

@ -0,0 +1,157 @@
@import '~/css/helpers';
.section {
position: relative;
padding: tovw(124px, 'default', 100px) 0;
@media screen and (max-width: 800px) {
margin-top: 0;
}
.container {
display: grid;
grid-template-columns: 1.7fr 1fr;
grid-template-rows: repeat(2, 1fr);
gap: tovw(70px, 'default', 20px) 0;
@media screen and (max-width: 800px) {
display: flex;
flex-direction: column;
gap: tovw(5px, 'mobile', 15px);
}
}
.headingContainer {
display: flex;
flex-direction: column;
width: 100%;
@media screen and (max-width: 800px) {
margin-top: tovw(-135px, 'mobile', -150px);
}
h2 {
margin: 0;
text-shadow: 0px 0px tovw(20px, 'default', 20px) rgb(255 255 255 / 0.4);
@media screen and (max-width: 800px) {
font-size: tovw(42px, 'default', 36px);
text-align: center;
}
&:nth-child(1) {
padding-left: tovw(125px, 'default', 60px);
@media screen and (max-width: 800px) {
padding-left: unset;
}
}
&:nth-child(2) {
align-self: end;
width: tovw(465px, 'default', 80px);
@media screen and (max-width: 800px) {
width: 100%;
}
}
}
}
.line {
position: absolute;
left: tovw(770px, 'default', 300px);
top: tovw(170px, 'default', 120px);
transform: rotate(270deg) scale(1.6);
width: tovw(173px, 'default', 120px);
height: tovw(72px, 'default', 40px);
@media screen and (max-width: 800px) {
transform: rotate(0deg) translateY(35%) scaleX(1.6);
height: tovw(80px, 'default', 38px);
left: 0;
right: 0;
margin: auto;
top: unset;
}
}
.socialIconsContainer {
grid-area: 2 / 2 / 3 / 3;
@media screen and (max-width: 800px) {
display: flex;
flex-direction: column;
}
span {
font-family: var(--font-dm-mono), sans-serif;
font-size: tovw(18px, 'default', 12px);
letter-spacing: -0.02rem;
&::before {
position: absolute;
transform: translate(-220%, -50%);
display: block;
content: '';
width: tovw(24px, 'default', 15px);
height: tovw(18px, 'default', 15px);
border-bottom: tovw(2px, 'default', 2px) solid blue;
@media screen and (max-width: 800px) {
display: none;
}
}
@media screen and (max-width: 800px) {
text-align: center;
}
}
.iconsGrid {
width: tovw(400px, 'default', 255px);
padding-top: tovw(30px, 'default', 15px);
display: flex;
flex-wrap: wrap;
gap: tovw(20px, 'default', 12px);
@media screen and (max-width: 800px) {
place-self: center;
place-content: center;
}
button {
cursor: pointer;
display: flex;
place-content: center;
padding: tovw(13px, 'default', 8px);
height: tovw(55px, 'default', 38px);
width: tovw(72px, 'default', 54px);
border: tovw(1px, 'default', 1px) solid #fff;
border-radius: tovw(30px, 'default', 20px);
background-color: var(--color-black);
transition: filter 200ms;
&:hover {
filter: invert(1);
}
}
svg {
width: tovw(27px, 'default', 20px);
}
}
}
.planetImage {
position: absolute;
padding-top: tovw(160px, 'default', 80px);
width: tovw(725px, 'default', 320px);
@media screen and (max-width: 800px) {
padding-top: unset;
width: 100%;
position: relative;
}
}
}

20
src/pages/community.tsx Normal file
View File

@ -0,0 +1,20 @@
import { Meta } from '~/components/common/meta'
import { PageLayout } from '~/components/layout/page'
import Events from '~/components/sections/community/events'
import Hero from '~/components/sections/community/hero'
import Socials from '~/components/sections/community/socials'
import { Page } from './_app'
const Community: Page = () => {
return (
<PageLayout>
<Meta />
<Hero />
<Events />
<Socials />
</PageLayout>
)
}
export default Community