Work on Newsroom (#71)

This commit is contained in:
Fede Álvarez 2022-05-23 15:17:31 +02:00 committed by GitHub
parent 40140ee99b
commit 2cce85d0c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 630 additions and 38 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 728 B

View File

@ -0,0 +1,6 @@
<svg width="83" height="83" viewBox="0 0 83 83" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.9">
<rect x="1" y="1" width="81" height="81" rx="3" stroke="#FBFBFB" stroke-width="2"/>
<path d="M57.0075 41.919L27.6641 58.6867L27.6641 25.1514L57.0075 41.919Z" fill="#FBFBFB"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

View File

@ -183,7 +183,7 @@
gap: tovw(30px, 'default', 25px);
&.is_news {
gap: tovw(70px, 'default', 40px);
gap: tovw(60px, 'default', 30px);
}
}

View File

@ -17,9 +17,10 @@ interface CardProps {
className?: string
data?: any
isNews?: boolean
reduced?: boolean
}
const Card = ({ className, data, isNews = false }: CardProps) => {
const Card = ({ className, data, isNews = false, reduced }: CardProps) => {
const [eventDate, setEventDate] = useState<string>()
const [eventTime, setEventTime] = useState<string>()
@ -77,7 +78,7 @@ const Card = ({ className, data, isNews = false }: CardProps) => {
<Heading as="h2" variant="sm" font="tthoves">
{isNews ? data?.title : data?.eventTitle}
</Heading>
<p>{isNews ? getDescription(data) : data?.eventDesc}</p>
{!reduced && <p>{isNews ? getDescription(data) : data?.eventDesc}</p>}
<Link href={isNews ? `/blog/${data?.slug}` : data?.eventLink}>
{isNews ? 'READ ARTICLE' : 'LEARN MORE'}
</Link>

View File

@ -14,21 +14,23 @@ import s from './related.module.scss'
// TODO
export interface Props {
isInPost?: boolean
isFeatured?: boolean
data: any
}
const Related = ({ data, isInPost }: Props) => {
const Related = ({ data, isInPost, isFeatured }: Props) => {
const [sliderRef] = useKeenSlider<HTMLDivElement>({
initial: 0,
loop: true,
mode: 'free-snap',
breakpoints: {
'(min-width: 1141px)': {
'(min-width: 901px)': {
slides: { perView: 3, spacing: 35 },
loop: false
},
'(max-width: 1140px)': {
slides: { perView: 2.9, spacing: 22 }
'(max-width: 1300px)': {
slides: { perView: 3, spacing: 15 },
loop: false
},
'(max-width: 900px)': {
slides: { perView: 1.12, spacing: 12 }
@ -40,16 +42,25 @@ const Related = ({ data, isInPost }: Props) => {
<Section className={s['section']}>
<Container className={clsx(s['heading'], isInPost && s.altheader)}>
<Heading as="h2" variant="lg">
{isInPost ? 'Related articles' : 'Learn More'}
{isInPost && !isFeatured && 'Related articles'}
{isFeatured && !isInPost && 'Featured articles'}
{!isFeatured && !isInPost && 'Learn more'}
</Heading>
</Container>
<div className={s['slider__container']}>
<div className={clsx(s['events'], 'keen-slider')} ref={sliderRef}>
{data.map((item: any, i: Key) => (
<Card key={i} data={item} className="keen-slider__slide" isNews />
<Card
key={i}
data={item}
className="keen-slider__slide"
reduced={true}
isNews
/>
))}
</div>
</div>
{isFeatured && <div className={s['gradient']} />}
</Section>
)
}

View File

@ -20,7 +20,7 @@
margin-left: auto;
width: calc(100% - tovw(205px, 'default', 16px));
@media screen and (min-width: 1141px) {
@media screen and (min-width: 901px) {
margin: 0 auto;
}
}
@ -40,7 +40,7 @@
margin-bottom: tovw(90px, 'default', 64px);
&.altheader {
@media screen and (min-width: 1141px) {
@media screen and (min-width: 901px) {
place-content: center;
}
}
@ -55,30 +55,6 @@
font-family: var(--font-tt-hoves), sans-serif;
font-size: tovw(24px, 'default', 18px);
}
.gradient {
@include respond-to('mobile') {
display: none;
}
position: absolute;
right: 0;
left: 0;
opacity: 0.4;
z-index: -1;
margin-left: 0;
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%
);
width: 100%;
height: tovw(500px, 'default', 250px);
content: '';
pointer-events: none;
user-select: none;
}
}
.events {
@ -88,7 +64,7 @@
padding-left: tovw(100px);
@media screen and (min-width: 1141px) {
@media screen and (min-width: 901px) {
margin: 0 auto;
padding: 0;
width: 100%;
@ -119,7 +95,7 @@
height: 100%;
content: '';
@media screen and (min-width: 1141px) {
@media screen and (min-width: 900px) {
display: none;
}
}
@ -135,4 +111,29 @@
z-index: 5;
}
}
.gradient {
@include respond-to('mobile') {
display: none;
}
position: absolute;
right: 0;
bottom: tovw(80px, 'default', 80px);
left: 0;
margin-left: 0;
background: linear-gradient(
180deg,
rgb(229 229 229 / 0) 0%,
rgb(241 241 241 / 0.5) 48.91%,
rgb(241 241 241 / 0) 89.23%
);
opacity: 0.4;
width: 100%;
height: tovw(960px, 'default', 750px);
content: '';
pointer-events: none;
user-select: none;
z-index: -1;
}
}

View File

@ -0,0 +1,176 @@
@import '~/css/helpers';
.section {
@include respond-to('mobile') {
margin-bottom: tovw(88px, 'mobile');
padding: 0;
width: 100vw;
justify-content: flex-start;
}
display: flex;
flex-direction: column;
justify-content: center;
padding: tovw(100px, 'default', 50px) 0;
max-width: 100%;
min-height: calc(var(--vh) * 100);
.container {
@include respond-to('mobile') {
padding: 0 tovw(56px, 'default', 16px);
}
}
.video_container {
align-self: center;
position: relative;
margin-top: tovw(-165px, 'default');
margin-bottom: tovw(-140px, 'default');
padding-top: tovw(30px, 'default', 20px);
width: 82%;
mix-blend-mode: lighten;
video {
@include respond-to('mobile') {
display: none;
}
width: 100%;
}
&::after {
position: absolute;
top: 0;
left: 0;
z-index: 1;
background: radial-gradient(
ellipse,
rgb(3 3 3 / 0) 60%,
rgb(3 3 3 / 1) 75%,
rgb(3 3 3 / 1) 100%
);
width: 100%;
height: 100%;
content: '';
}
}
.hero__mobile {
@include respond-to('mobile') {
display: flex;
margin: tovw(50px, 'mobile', 130px) 0 tovw(50px, 'mobile', 70px)
tovw(16px, 'mobile', 20px);
width: 200%;
mix-blend-mode: screen;
place-self: center;
mask-image: linear-gradient(
0deg,
rgb(255 255 255 / 0) 0%,
rgb(0 0 0) 25%
);
}
display: none;
}
.body {
@include respond-to('mobile') {
flex-direction: column;
align-items: flex-start;
}
display: flex;
justify-content: space-between;
margin-top: tovw(16px, 'default', 10px);
h1 {
@include respond-to('mobile') {
width: 100%;
font-size: tovw(50px, 'mobile');
}
margin: 0;
font-size: tovw(100px, 'default', 50px);
width: tovw(600px, 'default', 300px);
text-shadow: 0 0 tovw(20px, 'default', 20px) rgb(255 255 255 / 0.4);
}
.text__container {
@include respond-to('mobile') {
margin-top: tovw(25px, 'mobile');
}
display: flex;
align-items: center;
h2 {
@include respond-to('mobile') {
min-width: tovw(75px, 'mobile');
}
line-height: 120%;
padding-top: tovw(15px, 'default', 15px);
width: tovw(600px, 'default', 300px);
}
.line {
@include respond-to('mobile') {
top: unset;
margin: 0;
left: 0;
height: tovw(100px, 'default', 90px);
transform: rotate(0deg) translateY(tovw(8px, 'default', 8px))
scaleX(1.2) scaleY(1.4);
}
margin-top: tovw(8px, 'default', 8px);
height: tovw(90px, 'default', 90px);
transform: scaleX(1.5);
padding-right: tovw(25px, 'default', 15px);
}
}
div:first-child {
@include respond-to('mobile') {
width: 100%;
display: flex;
justify-content: space-between;
}
.arrow {
@include respond-to('mobile') {
display: unset;
position: relative;
align-self: flex-end;
padding-bottom: tovw(10px, 'mobile', 10px);
width: tovw(18px, 'mobile', 18px);
}
display: none;
}
}
a {
margin-top: tovw(50px, 'default', 25px);
}
}
.gradient {
@include respond-to('mobile') {
height: 80%;
}
position: absolute;
top: 0;
left: 0;
z-index: 2;
mix-blend-mode: screen;
background: linear-gradient(
180deg,
rgb(0 0 244 / 0.9) 1.63%,
rgb(0 0 244 / 0) 99.89%
);
width: 100%;
height: tovw(740px, 'default', 740px);
}
}

View File

@ -0,0 +1,70 @@
import { useRef } from 'react'
import { Arrow } from '~/components/icons/arrow'
import Line from '~/components/icons/line'
import { Container } from '~/components/layout/container'
import Section from '~/components/layout/section'
import { ButtonLink } from '~/components/primitives/button'
import Heading from '~/components/primitives/heading'
import s from './hero.module.scss'
// interface Props {
// data: {
// heroHeading: string
// heroLine: string
// }
// }
const Hero = () => {
const heroVideoRef = useRef<HTMLVideoElement>(null)
return (
<Section className={s['section']} disableFadeIn>
<div className={s.gradient} />
<div className={s.video_container}>
<video
autoPlay
ref={heroVideoRef}
controls={false}
loop
muted
playsInline={true}
preload="true"
>
<source src="/videos/banner-products.webm" type="video/webm" />
<source src="/videos/banner-products.mp4" type="video/mp4" />
</video>
</div>
<img
className={s.hero__mobile}
loading="eager"
alt="hero"
src="/images/products/products.jpg"
/>
<Container className={s['container']}>
<div className={s.body}>
<div>
<Heading as="h1" variant="xl">
Newsroom
</Heading>
<Arrow className={s['arrow']} />
</div>
<div>
<div className={s.text__container}>
<Line className={s.line} height={144} />
<Heading as="h2" variant="sm">
Contact press at laconic.com for press inquiries.
</Heading>
</div>
<ButtonLink variant="primary" href="https://google.com">
Get in touch
</ButtonLink>
</div>
</div>
</Container>
</Section>
)
}
export default Hero

View File

@ -0,0 +1,124 @@
import { useKeenSlider } from 'keen-slider/react'
import { Container } from '~/components/layout/container'
import Section from '~/components/layout/section'
import Heading from '~/components/primitives/heading'
import s from './media.module.scss'
// interface Props {
// data: {}
// }
const Media = () => {
const [sliderRef] = useKeenSlider<HTMLDivElement>({
initial: 0,
loop: true,
mode: 'snap',
breakpoints: {
'(max-width: 900px)': {
slides: { perView: 1.12, spacing: 12 }
},
'(min-width: 901px)': {
disabled: true
}
}
})
return (
<Section className={s['section']}>
<Container className={s['container']}>
<div className={s['header']}>
<Heading as="h2" variant="md">
Media
</Heading>
<span>04</span>
</div>
<div className={`${s.media__block} keen-slider`} ref={sliderRef}>
<div className={`${s.item} keen-slider__slide`}>
<div className={s['image__container']}>
<img
alt="image"
loading="lazy"
src="/images/newsroom/prev01.jpg"
/>
<img
alt="play"
loading="lazy"
className={s.play}
src="/images/newsroom/play.svg"
/>
</div>
<div className={s['content']}>
<Heading as="h2" variant="sm" font="tthoves">
Introducing Laconic video
</Heading>
</div>
</div>
<div className={`${s.item} keen-slider__slide`}>
<div className={s['image__container']}>
<img
alt="image"
loading="lazy"
src="/images/newsroom/prev02.jpg"
/>
<img
alt="play"
loading="lazy"
className={s.play}
src="/images/newsroom/play.svg"
/>
</div>
<div className={s['content']}>
<Heading as="h2" variant="sm" font="tthoves">
Introducing Laconic video
</Heading>
</div>
</div>
<div className={`${s.item} keen-slider__slide`}>
<div className={s['image__container']}>
<img
alt="image"
loading="lazy"
src="/images/newsroom/prev03.jpg"
/>
<img
alt="play"
loading="lazy"
className={s.play}
src="/images/newsroom/play.svg"
/>
</div>
<div className={s['content']}>
<Heading as="h2" variant="sm" font="tthoves">
Introducing Laconic video
</Heading>
</div>
</div>
<div className={`${s.item} keen-slider__slide`}>
<div className={s['image__container']}>
<img
alt="image"
loading="lazy"
src="/images/newsroom/prev04.jpg"
/>
<img
alt="play"
loading="lazy"
className={s.play}
src="/images/newsroom/play.svg"
/>
</div>
<div className={s['content']}>
<Heading as="h2" variant="sm" font="tthoves">
Introducing Laconic video
</Heading>
</div>
</div>
</div>
</Container>
</Section>
)
}
export default Media

View File

@ -0,0 +1,134 @@
@import '~/css/helpers';
.section {
@include respond-to('mobile') {
padding-bottom: 0;
}
position: relative;
margin: tovw(140px, 'default', 110px) 0;
padding: tovw(104px, 'default', 90px) 0;
.container {
@include respond-to('mobile') {
padding: 0 tovw(56px, 'default', 16px);
width: 100%;
}
position: relative;
width: tovw(1076px, 'default', 400px);
.header {
@include respond-to('mobile') {
align-items: flex-end;
}
display: flex;
justify-content: space-between;
border-bottom: tovw(1px, 'default', 1px) solid var(--color-white);
padding-bottom: tovw(36px, 'default', 24px);
margin-bottom: tovw(56px, 'default', 40px);
> h2 {
text-shadow: 0 0 tovw(20px, 'default', 20px) rgb(255 255 255 / 0.4);
}
span {
padding-top: tovw(35px, 'default', 14px);
color: var(--color-grey-light);
font-family: var(--font-dm-mono), sans-serif;
font-size: tovw(18px, 'default', 12px);
}
}
.media__block {
// @include respond-to('mobile') {
// }
@include respond-to('mobile') {
display: flex;
gap: unset;
width: calc(100% - tovw(16px, 'mobile'));
}
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: tovw(45px, 'default', 40px) tovw(24px, 'default', 20px);
.item {
display: flex;
flex-direction: column;
padding-bottom: tovw(2px, 'default', 2px);
white-space: normal;
width: 100%;
}
.image__container {
cursor: pointer;
position: relative;
display: flex;
place-content: center;
place-items: center;
width: 100%;
margin: 0 0 tovw(20px, 'default', 16px) 0;
border-top: tovw(1px, 'default', 1px) solid var(--color-white);
border-bottom: tovw(1px, 'default', 1px) solid var(--color-white);
&:hover {
img:first-child {
opacity: 80%;
filter: grayscale(50%);
transition: all 300ms;
}
}
img {
width: 100%;
height: 100%;
object-fit: cover;
@supports (aspect-ratio: 16 / 9) {
aspect-ratio: 16 / 9;
}
}
.play {
position: absolute;
height: tovw(83px, 'default', 60px);
width: tovw(83px, 'default', 60px);
z-index: 3;
}
}
.content {
display: flex;
flex-direction: column;
height: 100%;
text-align: left;
gap: tovw(24px, 'default', 18px);
place-content: space-between;
a {
padding-top: tovw(20px, 'default', 12px);
width: fit-content;
}
h2 {
font-size: tovw(40px, 'default', 24px);
text-transform: none !important;
line-height: 1.2;
}
p {
@include respond-to('mobile') {
line-height: 1.6;
}
margin: 0;
line-height: 1.4;
font-size: tovw(18px, 'default', 15px);
}
}
}
}
}

View File

@ -98,6 +98,7 @@
font-size: tovw(100px, 'default', 70px);
width: tovw(600px, 'default', 300px);
text-shadow: 0 0 tovw(20px, 'default', 20px) rgb(255 255 255 / 0.4);
z-index: 5;
}
.text__container {
@ -110,6 +111,7 @@
display: flex;
flex-direction: column;
width: tovw(645px, 'default', 300px);
z-index: 5;
p {
margin: tovw(25px, 'default', 10px) 0;

View File

@ -38,7 +38,7 @@ const BlogPost = ({
<Hero data={post} />
<Content data={post} />
<Shares url={completeUrl} />
<Related isInPost data={latestPosts} />
{latestPosts?.length > 0 && <Related isInPost data={latestPosts} />}
</PageLayout>
)
}

67
src/pages/newsroom.tsx Normal file
View File

@ -0,0 +1,67 @@
import {
getBlogPosts as serverGetBlogPosts,
getBlogPostsCategories as serverGetBlogPostsCategories
} from 'lib/blog'
import { InferGetStaticPropsType } from 'next'
import { Meta } from '~/components/common/meta'
import { PageLayout } from '~/components/layout/page'
import Related from '~/components/sections/about/related'
import Hero from '~/components/sections/newsroom/hero'
import Media from '~/components/sections/newsroom/media'
// import {
// CareersHero,
// CareersPositions,
// CareersPositionsSection,
// CareersValues,
// CareersWhy
// } from '~/lib/cms/queries/careers'
// import { request } from '../lib/datocms'
export const getStaticProps = async () => {
const [allBlogPosts, categories] = await Promise.all([
serverGetBlogPosts({ page: 1 }),
serverGetBlogPostsCategories()
])
const heroBlogPost = allBlogPosts.data[0]
// const [latestData] = await Promise.all([request(HomeLatest)])
return {
props: {
// heroData: heroData?.careersPage,
// valuesData: valuesData?.careersPage,
// positionsSectData: positionsSectData?.careersPage,
// whyData: whyData?.careersPage,
// positionsData: positionsData?.allPositions,
initialBlogPosts: {
pagination: allBlogPosts.pagination,
data: allBlogPosts.data.slice(0, 3)
},
categories,
page:
{
heroBlogPost
} ?? null
},
revalidate: 60
}
}
const Newsroom = ({
initialBlogPosts
}: InferGetStaticPropsType<typeof getStaticProps>) => {
return (
<PageLayout>
<Meta />
<Hero />
<Related data={initialBlogPosts?.data} isFeatured={true} />
<Media />
<Related data={initialBlogPosts?.data} />
</PageLayout>
)
}
export default Newsroom