Section benefits (#5)

This commit is contained in:
Nazareno Oviedo 2022-03-30 22:47:43 -03:00 committed by GitHub
parent da28e4059b
commit 6243ca87ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 746 additions and 7 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View File

@ -1,19 +1,27 @@
const Line = ({ className, fill }: { className?: string; fill?: string }) => {
const Line = ({
className,
fill,
height = 72
}: {
className?: string
fill?: string
height?: number
}) => {
return (
<svg
className={className}
fill="none"
viewBox="0 0 3 72"
viewBox={`0 0 3 ${height}`}
xmlns="http://www.w3.org/2000/svg"
>
<path stroke="url(#heroline)" strokeWidth="3" d="M1.5 0v72" />
<path stroke="url(#heroline)" strokeWidth="3" d={`M1.5 0v${height}`} />
<defs>
<linearGradient
id="heroline"
x1="0"
y1="0"
x2="0"
y2="72"
y2={height}
gradientUnits="userSpaceOnUse"
>
<stop stopColor={fill || 'var(--color-white)'} stopOpacity="0" />

View File

@ -31,7 +31,7 @@
}
&--sm {
font-size: tovw(40px, 'default', 36px);
font-size: tovw(40px, 'default', 30px);
line-height: 1;
}

View File

@ -0,0 +1,39 @@
@import '~/css/helpers';
.benefit {
display: flex;
p {
margin: 0;
margin-left: tovw(28px, 'default', 28px);
}
}
.icon {
position: relative;
width: tovw(38px, 'default', 38px);
height: tovw(27px, 'default', 27px);
&::before {
position: absolute;
z-index: 1;
top: 0;
left: 0;
width: tovw(38px, 'default', 38px);
height: tovw(27px, 'default', 27px);
content: '';
opacity: 0.5;
background: linear-gradient(
134.38deg,
#fff 4.91%,
rgb(255 255 255 / 0) 108.92%
);
}
svg {
z-index: 5;
width: tovw(32px, 'default', 32px);
height: tovw(32px, 'default', 32px);
transform: translate(50%, -50%);
}
}

View File

@ -0,0 +1,19 @@
import * as React from 'react'
import s from './benefit.module.scss'
type BenefitProps = {
children: React.ReactNode
icon: React.ReactNode
}
const Benefit = ({ children, icon }: BenefitProps) => {
return (
<li className={s['benefit']}>
<div className={s['icon']}>{icon}</div>
<p className={s['text']}>{children}</p>
</li>
)
}
export default Benefit

View File

@ -0,0 +1,173 @@
@import '~/css/helpers';
.section {
position: relative;
padding-top: tovw(280px, 'default', 80px);
padding-bottom: tovw(246px, 'default', 200px);
.grid {
display: grid;
margin-top: tovw(64px, 'default', 44px);
grid-column-gap: tovw(24px, 'default', 24px);
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 1fr;
.icon {
grid-area: 1 / 1 / 2 / 2;
svg {
display: block;
width: tovw(23px, 'default', 23px);
}
}
p {
margin: 0;
line-height: 1.33;
letter-spacing: tovw(-0.3px, 'default', -0.3px);
font-size: tovw(30px, 'default', 18px);
grid-area: 1 / 2 / 2 / 11;
}
}
@media screen and (max-width: 800px) {
.grid {
display: flex;
.icon {
display: none;
}
}
.header {
padding-right: 0;
padding-left: 0;
}
}
ul {
display: grid;
margin: 0;
padding: 0;
list-style-type: none;
grid-gap: tovw(26px, 'default', 26px) tovw(24px, 'default', 24px);
grid-template-columns: repeat(3, auto);
grid-template-rows: repeat(2, 1fr);
@media screen and (max-width: 800px) {
display: flex;
flex-wrap: wrap;
li {
width: 100%;
}
}
}
}
.background {
margin: 0 tovw(-56px, 'default', -56px);
margin-top: tovw(72px, 'default', 60px);
background-image: url('/images/benefit-bg.jpg');
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
height: tovw(1582px, 'default', 900px);
@media screen and (max-width: 800px) {
margin-top: tovw(-60px, 'mobile');
background-image: none;
height: auto;
}
}
.developers,
.users {
margin: 0 0 tovw(305px, 'default', 110px) auto;
padding-top: tovw(138px, 'default', 100px);
padding-right: tovw(69px, 'default', 69px);
width: 100%;
max-width: tovw(1080px, 'default', 730px);
> ul {
margin-top: tovw(88px, 'default', 72px);
}
@media screen and (max-width: 800px) {
padding: 0 tovw(13px, 'mobile');
}
}
.service {
&__header {
position: relative;
padding-left: tovw(8px, 'default');
@media screen and (max-width: 800px) {
padding-left: tovw(32px, 'mobile');
}
.line {
position: absolute;
top: 0;
left: tovw(-24px, 'default', -16px);
width: tovw(3px, 'default', 2px);
height: 100%;
@media screen and (max-width: 800px) {
left: tovw(16px, 'mobile');
}
}
span {
position: absolute;
top: 0;
left: tovw(-62px, 'default', -48px);
text-transform: uppercase;
font-family: var(--font-dm-mono);
font-size: tovw(12px, 'default', 12px);
@media screen and (max-width: 800px) {
top: tovw(4px, 'mobile');
left: tovw(-5px, 'mobile');
}
}
p {
max-width: tovw(557px, 'default', 390px);
color: var(--color-grey-light);
}
}
}
.users {
margin: 0 auto 0 0;
padding-top: tovw(16px, 'default', 16px);
padding-right: 0;
&__container {
@media screen and (max-width: 800px) {
padding-right: 0;
padding-left: 0;
}
}
}
.benefit {
&__image {
display: block;
width: 100%;
&--01 {
transform: translateY(-14%);
z-index: -1;
margin: 0 0 0 tovw(-16px, 'mobile');
width: calc(100% + (tovw(16px, 'mobile') * 2));
pointer-events: none;
user-select: none;
}
&--02 {
margin-bottom: tovw(67px, 'mobile');
}
}
}

View File

@ -0,0 +1,358 @@
const Icon01 = ({ className, fill }: { className?: string; fill?: string }) => {
return (
<svg
className={className}
fill="none"
viewBox="0 0 32 32"
xmlns="http://www.w3.org/2000/svg"
>
<circle
cx="12.5"
cy="12.5"
r="9.5"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
/>
<path
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
strokeLinecap="square"
d="M19.414 20 27 27.586"
/>
<path
d="M8 11.652 12.546 16 23 6"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
strokeLinecap="round"
/>
</svg>
)
}
const Icon02 = ({ className, fill }: { className?: string; fill?: string }) => {
return (
<svg
className={className}
fill="none"
viewBox="0 0 32 32"
xmlns="http://www.w3.org/2000/svg"
>
<circle
cx="16"
cy="16"
r="12"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
/>
<circle
cx="16"
cy="16"
r="6"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
/>
<circle cx="16" cy="16" r="2" fill={fill || 'var(--color-white)'} />
<circle cx="7" cy="24" r="3" fill={fill || 'var(--color-white)'} />
<circle cx="25" cy="8" r="4" fill={fill || 'var(--color-white)'} />
</svg>
)
}
const Icon03 = ({ className, fill }: { className?: string; fill?: string }) => {
return (
<svg
className={className}
fill="none"
viewBox="0 0 32 32"
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#icon03)">
<path
d="M7.515 24.485a12 12 0 1 1 16.97 0"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
strokeLinecap="square"
strokeLinejoin="round"
/>
<path
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
strokeLinecap="round"
d="M5 15h3M16 4v3M7.414 8l2.122 2.121M24 15h3"
/>
<circle cx="16" cy="16" r="2" fill={fill || 'var(--color-white)'} />
<path
d="m21 9-6 6 2 2 4-8Z"
fill={fill || 'var(--color-white)'}
stroke={fill || 'var(--color-white)'}
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
<defs>
<clipPath id="icon03">
<path fill="#fff" d="M0 0h32v32H0z" />
</clipPath>
</defs>
</svg>
)
}
const Icon04 = ({ className, fill }: { className?: string; fill?: string }) => {
return (
<svg
className={className}
fill="none"
viewBox="0 0 32 32"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M14 13.967a5.745 5.745 0 0 1 4.1-1.73c1.538 0 3.012.622 4.1 1.73l4.101 4.18A5.969 5.969 0 0 1 28 22.325a5.97 5.97 0 0 1-1.699 4.18 5.744 5.744 0 0 1-4.1 1.73 5.744 5.744 0 0 1-4.101-1.73l-2.05-2.09"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
strokeLinejoin="round"
/>
<path
d="M18.059 18.27a5.744 5.744 0 0 1-4.1 1.73 5.744 5.744 0 0 1-4.1-1.73l-4.102-4.18A5.97 5.97 0 0 1 4.06 9.91a5.97 5.97 0 0 1 1.698-4.179A5.744 5.744 0 0 1 9.858 4c1.538 0 3.013.623 4.1 1.731l2.05 2.09"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
strokeLinejoin="round"
/>
</svg>
)
}
const Icon05 = ({ className, fill }: { className?: string; fill?: string }) => {
return (
<svg
className={className}
fill="none"
viewBox="0 0 32 32"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M4 22h5l6-6m11-6h-5l-3 3"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
strokeLinecap="square"
/>
<path
d="M4 10h5l12 12h5"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
strokeLinecap="square"
/>
<path
d="m23 6 4 4-4 4M23 18l4 4-4 4"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
strokeLinecap="round"
/>
</svg>
)
}
const Icon06 = ({ className, fill }: { className?: string; fill?: string }) => {
return (
<svg
className={className}
fill="none"
viewBox="0 0 32 32"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M2.293 12.293a1 1 0 1 0 1.414 1.414l-1.414-1.414ZM6 10h1a1 1 0 0 0-1.707-.707L6 10Zm-2.293 3.707 3-3-1.414-1.414-3 3 1.414 1.414ZM5 10v14h2V10H5Z"
fill={fill || 'var(--color-white)'}
/>
<rect
x="9"
y="10"
width="4"
height="13"
rx="2"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
/>
<rect
x="16"
y="10"
width="4"
height="13"
rx="2"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
/>
<path
d="m23 10 6 6M29 10l-6 6"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
/>
</svg>
)
}
const Icon07 = ({ className, fill }: { className?: string; fill?: string }) => {
return (
<svg
className={className}
fill="none"
viewBox="0 0 32 32"
xmlns="http://www.w3.org/2000/svg"
>
<circle
cx="16.001"
cy="14.143"
r="1.857"
fill={fill || 'var(--color-white)'}
/>
<path
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
d="M16.072 14.144v5.571"
/>
<circle
cx="16"
cy="16"
r="12"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
/>
<path
d="M22 16c0 3.457-.757 6.538-1.93 8.718C18.872 26.94 17.388 28 16 28c-1.389 0-2.873-1.06-4.07-3.282C10.758 22.538 10 19.458 10 16c0-3.457.757-6.538 1.93-8.718C13.128 5.06 14.612 4 16 4c1.389 0 2.873 1.06 4.07 3.282C21.242 9.462 22 12.542 22 16ZM4 16h6M22 16h6"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
/>
</svg>
)
}
const Icon08 = ({ className, fill }: { className?: string; fill?: string }) => {
return (
<svg
className={className}
fill="none"
viewBox="0 0 32 32"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M27 8.5c0 .89-.83 2.017-2.931 2.98C22.055 12.403 19.203 13 16 13c-3.204 0-6.055-.597-8.069-1.52C5.831 10.517 5 9.39 5 8.5c0-.89.83-2.017 2.931-2.98C9.945 4.597 12.796 4 16 4c3.203 0 6.055.597 8.069 1.52C26.169 6.483 27 7.61 27 8.5ZM27 16c0 2.761-4.925 5-11 5S5 18.761 5 16"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
/>
<path
d="M5 9v15c0 2.761 4.925 5 11 5s11-2.239 11-5V9"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
strokeLinecap="round"
/>
<circle cx="24" cy="15" r="1" fill={fill || 'var(--color-white)'} />
<circle cx="24" cy="23" r="1" fill={fill || 'var(--color-white)'} />
</svg>
)
}
const Icon09 = ({ className, fill }: { className?: string; fill?: string }) => {
return (
<svg
className={className}
fill="none"
viewBox="0 0 32 32"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M8.222 12h15.556c.462 0 1.222.58 1.222 1.833v11.334C25 26.419 24.24 27 23.778 27H8.222C7.76 27 7 26.42 7 25.167V13.833C7 12.581 7.76 12 8.222 12Z"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M10 12V6.375c0-.895.316-1.754.879-2.386C11.44 3.356 12.204 3 13 3h6c.796 0 1.559.356 2.121.989.563.632.879 1.49.879 2.386V7.5"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
strokeLinecap="square"
strokeLinejoin="round"
/>
</svg>
)
}
const Icon10 = ({ className, fill }: { className?: string; fill?: string }) => {
return (
<svg
className={className}
fill="none"
viewBox="0 0 32 32"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="m12 14.667 4 4L29.333 5.333"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M28 16v9.333A2.667 2.667 0 0 1 25.333 28H6.667A2.667 2.667 0 0 1 4 25.333V6.667A2.667 2.667 0 0 1 6.667 4h14.666"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)
}
const Icon11 = ({ className, fill }: { className?: string; fill?: string }) => {
return (
<svg
className={className}
fill="none"
viewBox="0 0 32 32"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="m16 5.2 3.306 6.478.231.453.503.08 7.183 1.143-5.14 5.146-.36.36.08.502 1.133 7.185-6.483-3.298-.453-.231-.453.23-6.483 3.299 1.133-7.185.08-.502-.36-.36-5.14-5.146 7.183-1.143.503-.08.23-.453L16 5.2Z"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
/>
</svg>
)
}
const Icon12 = ({ className, fill }: { className?: string; fill?: string }) => {
return (
<svg
className={className}
fill="none"
viewBox="0 0 32 32"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M16 25.544 3.386 12.188 9.422 6h13.156l6.036 6.188L16 25.544ZM3 12h25"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
/>
<path
d="m14 6-3 6 5 13M18 6l3 6-5 13"
stroke={fill || 'var(--color-white)'}
strokeWidth="2"
/>
</svg>
)
}
export {
Icon01,
Icon02,
Icon03,
Icon04,
Icon05,
Icon06,
Icon07,
Icon08,
Icon09,
Icon10,
Icon11,
Icon12
}

View File

@ -0,0 +1,140 @@
import clsx from 'clsx'
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 Heading from '~/components/primitives/heading'
import Benefit from './benefit'
import s from './benefits.module.scss'
import {
Icon01,
Icon02,
Icon03,
Icon04,
Icon05,
Icon06,
Icon07,
Icon08,
Icon09,
Icon10,
Icon11,
Icon12
} from './icons'
const Benefits = () => {
return (
<Section className={s['section']}>
<Container className={s['header']}>
<Heading as="h2" variant="lg">
Benefits
</Heading>
<div className={s['grid']}>
<div className={s['icon']}>
<Arrow />
</div>
<p>
For DApp developers and users, Laconic is the only solution that
provides accurate, low-cost, multi-chain verifiable data, by
leveraging cryptographic proofs and cutting edge data caching
engineering. <br />
<br /> Laconic is the only blockchain data querying solution that
provides cross-chain cryptographic proofs.
</p>
</div>
</Container>
<img
className={clsx(
s['benefit__image'],
s['benefit__image--01'],
'hide-on-desktop'
)}
alt="Benefit"
loading="lazy"
src="/images/benefit-mobile-01.png"
/>
<div className={s['background']}>
<Container className={s['developers']}>
<div className={s['service__header']}>
<span>01</span>
<Line className={s['line']} height={144} />
<Heading as="h3" variant="sm">
For DApp Developers
</Heading>
<p>
Quickly and easily build blockchain applications with the fastest,
most accurate, and lowest cost multi-chain verifiable data
solution.
</p>
</div>
<ul>
<Benefit icon={<Icon01 />}>
Only solution providing Cryptographic proof
</Benefit>
<Benefit icon={<Icon02 />}>
Composable, supports broader use cases
</Benefit>
<Benefit icon={<Icon03 />}>
From months to seconds. Quick automated setup.
</Benefit>
<Benefit icon={<Icon04 />}>Broad cross-chain compatibility</Benefit>
<Benefit icon={<Icon05 />}>
Unparalleled flexibility. Supports hash-linked data including
blockchain
</Benefit>
<Benefit icon={<Icon06 />}>
Lower development and data costs. Hundreds of times less than
market
</Benefit>
</ul>
</Container>
<img
className={clsx(
s['benefit__image'],
s['benefit__image--02'],
'hide-on-desktop'
)}
alt="Benefit"
loading="lazy"
src="/images/benefit-mobile-02.png"
/>
<Container className={s['users__container']}>
<Container className={s['users']}>
<div className={s['service__header']}>
<span>02</span>
<Line className={s['line']} height={112} />
<Heading as="h3" variant="sm">
For DApp Users
</Heading>
<p>
Experience a higher quality of service and better uptime with
Laconic.
</p>
</div>
<ul>
<Benefit icon={<Icon07 />}>
Greater data access and control
</Benefit>
<Benefit icon={<Icon08 />}>
In-browser local cache, without need for data avilability layer
</Benefit>
<Benefit icon={<Icon09 />}>
Optimal control of privacy levels
</Benefit>
<Benefit icon={<Icon10 />}>Self-Verify data accuracy</Benefit>
<Benefit icon={<Icon11 />}>
Higher quality of service and uptime
</Benefit>
<Benefit icon={<Icon12 />}>
LNT rewards for network participation
</Benefit>
</ul>
</Container>
</Container>
</div>
</Section>
)
}
export default Benefits

View File

@ -19,7 +19,7 @@ const SeenIn = () => {
return (
<Section className={s['section']}>
<Container>
<Heading as="h2" variant="sm" centered>
<Heading as="h2" variant="lg" centered>
Seen In
</Heading>
<img

View File

@ -18,7 +18,7 @@ const TrustedBy = () => {
return (
<Section className={s['section']}>
<Container>
<Heading as="h2" variant="sm" centered>
<Heading as="h2" variant="md" centered>
Trusted By
</Heading>
<Marquee

View File

@ -1,5 +1,6 @@
import { Meta } from '~/components/common/meta'
import { PageLayout } from '~/components/layout/page'
import Benefits from '~/components/sections/homepage/benefits'
import Hero from '~/components/sections/homepage/hero'
import SeenIn from '~/components/sections/homepage/seen-in'
import TrustedBy from '~/components/sections/homepage/trusted-by'
@ -12,6 +13,7 @@ const HomePage: Page = () => {
<Meta />
<Hero />
<TrustedBy />
<Benefits />
<SeenIn />
</PageLayout>
)