landing-site/src/components/PrimaryFeatures.jsx
2022-11-08 12:00:19 +00:00

241 lines
8.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Fragment, useEffect, useId, useRef, useState } from 'react'
import { Tab } from '@headlessui/react'
import clsx from 'clsx'
import { AnimatePresence, motion } from 'framer-motion'
import { useDebouncedCallback } from 'use-debounce'
import Image from 'next/image'
import { AppScreen } from '@/components/AppScreen'
import { CircleBackground } from '@/components/CircleBackground'
import { Container } from '@/components/Container'
import { PhoneFrame } from '@/components/PhoneFrame'
import {
DiageoLogo,
LaravelLogo,
MirageLogo,
ReversableLogo,
StatamicLogo,
StaticKitLogo,
TransistorLogo,
TupleLogo,
} from '@/components/StockLogos'
import exampleApp from '@/images/example-app.png'
const MotionAppScreenHeader = motion(AppScreen.Header)
const MotionAppScreenBody = motion(AppScreen.Body)
const features = [
{
name: 'Invite friends for better returns',
description:
'For every friend you invite to Pocket, you get insider notifications 5 seconds sooner. And its 10 seconds if you invite an insider.',
icon: DeviceUserIcon
},
{
name: 'Notifications on stock dips',
description:
'Get a push notification every time we find out something thats going to lower the share price on your holdings so you can sell before the information hits the public markets.',
icon: DeviceNotificationIcon
},
{
name: 'Invest what you want',
description:
'We hide your stock purchases behind thousands of anonymous trading accounts, so suspicious activity can never be traced back to you.',
icon: DeviceTouchIcon
},
]
function DeviceUserIcon(props) {
return (
<svg viewBox="0 0 32 32" aria-hidden="true" {...props}>
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
<path
fillRule="evenodd"
clipRule="evenodd"
d="M16 23a3 3 0 100-6 3 3 0 000 6zm-1 2a4 4 0 00-4 4v1a2 2 0 002 2h6a2 2 0 002-2v-1a4 4 0 00-4-4h-2z"
fill="#737373"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5 4a4 4 0 014-4h14a4 4 0 014 4v24a4.002 4.002 0 01-3.01 3.877c-.535.136-.99-.325-.99-.877s.474-.98.959-1.244A2 2 0 0025 28V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9a2 2 0 00-2 2v24a2 2 0 001.041 1.756C8.525 30.02 9 30.448 9 31s-.455 1.013-.99.877A4.002 4.002 0 015 28V4z"
fill="#A3A3A3"
/>
</svg>
)
}
function DeviceNotificationIcon(props) {
return (
<svg viewBox="0 0 32 32" aria-hidden="true" {...props}>
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
<path
fillRule="evenodd"
clipRule="evenodd"
d="M9 0a4 4 0 00-4 4v24a4 4 0 004 4h14a4 4 0 004-4V4a4 4 0 00-4-4H9zm0 2a2 2 0 00-2 2v24a2 2 0 002 2h14a2 2 0 002-2V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9z"
fill="#A3A3A3"
/>
<path
d="M9 8a2 2 0 012-2h10a2 2 0 012 2v2a2 2 0 01-2 2H11a2 2 0 01-2-2V8z"
fill="#737373"
/>
</svg>
)
}
function DeviceTouchIcon(props) {
let id = useId()
return (
<svg viewBox="0 0 32 32" fill="none" aria-hidden="true" {...props}>
<defs>
<linearGradient
id={`${id}-gradient`}
x1={14}
y1={14.5}
x2={7}
y2={17}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#737373" />
<stop offset={1} stopColor="#D4D4D4" stopOpacity={0} />
</linearGradient>
</defs>
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5 4a4 4 0 014-4h14a4 4 0 014 4v13h-2V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9a2 2 0 00-2 2v24a2 2 0 002 2h4v2H9a4 4 0 01-4-4V4z"
fill="#A3A3A3"
/>
<path
d="M7 22c0-4.694 3.5-8 8-8"
stroke={`url(#${id}-gradient)`}
strokeWidth={2}
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M21 20l.217-5.513a1.431 1.431 0 00-2.85-.226L17.5 21.5l-1.51-1.51a2.107 2.107 0 00-2.98 0 .024.024 0 00-.005.024l3.083 9.25A4 4 0 0019.883 32H25a4 4 0 004-4v-5a3 3 0 00-3-3h-5z"
fill="#A3A3A3"
/>
</svg>
)
}
const headerAnimation = {
initial: { opacity: 0, transition: { duration: 0.3 } },
animate: { opacity: 1, transition: { duration: 0.3, delay: 0.3 } },
exit: { opacity: 0, transition: { duration: 0.3 } },
}
const maxZIndex = 2147483647
const bodyVariantBackwards = {
opacity: 0.4,
scale: 0.8,
zIndex: 0,
filter: 'blur(4px)',
transition: { duration: 0.4 },
}
const bodyVariantForwards = (custom) => ({
y: '100%',
zIndex: maxZIndex - custom.changeCount,
transition: { duration: 0.4 },
})
const bodyAnimation = {
initial: 'initial',
animate: 'animate',
exit: 'exit',
variants: {
initial: (custom) =>
custom.isForwards ? bodyVariantForwards(custom) : bodyVariantBackwards,
animate: (custom) => ({
y: '0%',
opacity: 1,
scale: 1,
zIndex: maxZIndex / 2 - custom.changeCount,
filter: 'blur(0px)',
transition: { duration: 0.4 },
}),
exit: (custom) =>
custom.isForwards ? bodyVariantBackwards : bodyVariantForwards(custom),
},
}
function InviteScreen({ custom, animated = false }) {
return (
<AppScreen className="w-full">
<MotionAppScreenHeader {...(animated ? headerAnimation : {})}>
<AppScreen.Title>Invite people</AppScreen.Title>
<AppScreen.Subtitle>
Get tips <span className="text-white">5s sooner</span> for every
invite.
</AppScreen.Subtitle>
</MotionAppScreenHeader>
<MotionAppScreenBody {...(animated ? { ...bodyAnimation, custom } : {})}>
<div className="px-4 py-6">
<div className="space-y-6">
{[
{ label: 'Full name', value: 'Albert H. Wiggin' },
{ label: 'Email address', value: 'awiggin@chase.com' },
].map((field) => (
<div key={field.label}>
<div className="text-sm text-gray-500">{field.label}</div>
<div className="mt-2 border-b border-gray-200 pb-2 text-sm text-gray-900">
{field.value}
</div>
</div>
))}
</div>
<div className="mt-6 rounded-lg bg-cyan-500 py-2 px-3 text-center text-sm font-semibold text-white">
Invite person
</div>
</div>
</MotionAppScreenBody>
</AppScreen>
)
}
export function PrimaryFeatures() {
return (
<section
id="features"
aria-label="Features for investing all your money"
className="bg-gray-900 py-20 sm:py-32"
>
<Container>
<div className="mx-auto max-w-2xl lg:mx-0 lg:max-w-3xl">
<h2 className="text-3xl font-medium tracking-tight text-white">
Every way you could possibly want to express yourself and talk with people
</h2>
<p className="mt-2 text-lg text-gray-400">
Akkoma is a part of the &quot;fediverse&quot;; that means it&apos;s a social network with no central
authority. You can follow and talk with anyone else that has an account on any other fediverse
service, and you can even host your own server if you want.
</p>
<p className="mt-2 text-lg text-gray-400">
It implements the <a className={"text-blue-400"} href={"https://www.w3.org/TR/activitypub/"}>ActivityPub protocol</a>, a standard format for sharing data between servers.
This allows us to send text and media to any other service implementing ActivityPub.
</p>
<p className="mt-2 text-lg text-gray-400">
For those more familiar with the fediverse, Akkoma is a specialised fork of Pleroma.
It is faster-paced in development and aligns itself more closely with Misskey than Pleroma mainline.
<br/>
It differentiates itself with a focus on custom expression, for example with custom emoji reactions,
or Misskey-Flavoured Markdown.
</p>
<p className="mt-2 text-lg text-gray-400">
In short: Akkoma is part of a distributed social network. Sorta like the child of twitter and email.
</p>
</div>
<div className={"items-center"}>
<Image src={exampleApp} className={"justify-center align-center rounded-lg pt-10"}/>
</div>
</Container>
</section>
)
}