public: improve headline on hero
This commit is contained in:
@@ -38,6 +38,7 @@
|
||||
"react-animate-height": "^3.2.3",
|
||||
"react-dom": "18.2.0",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"react-type-animation": "^3.2.0",
|
||||
"tailwind-merge": "^1.14.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"zod": "^3.22.4"
|
||||
|
||||
46
apps/public/src/app/animated-text.tsx
Normal file
46
apps/public/src/app/animated-text.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
'use client';
|
||||
|
||||
import { useMemo, useState } from 'react';
|
||||
import { TypeAnimation } from 'react-type-animation';
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
texts: { text: string; color: string }[];
|
||||
};
|
||||
|
||||
const AnimatedText = ({ texts }: Props) => {
|
||||
const [currIndex, setCurrIndex] = useState(0);
|
||||
const sequence = useMemo(() => {
|
||||
return texts.reduce((acc, { text }, index) => {
|
||||
return [
|
||||
...acc,
|
||||
() => setCurrIndex(index),
|
||||
text,
|
||||
index === 0 ? 3000 : 2000,
|
||||
];
|
||||
}, [] as any[]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<span
|
||||
style={{
|
||||
color: texts[currIndex]?.color,
|
||||
height: 60,
|
||||
display: 'block',
|
||||
whiteSpace: 'nowrap',
|
||||
}}
|
||||
>
|
||||
<TypeAnimation
|
||||
cursor={false}
|
||||
preRenderFirstString={true}
|
||||
sequence={sequence}
|
||||
wrapper="span"
|
||||
repeat={Infinity}
|
||||
omitDeletionAnimation
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
export default AnimatedText;
|
||||
@@ -2,6 +2,7 @@ import { ALink } from '@/components/ui/button';
|
||||
|
||||
import { chQuery } from '@openpanel/db';
|
||||
|
||||
import AnimatedText from './animated-text';
|
||||
import { Heading1, Lead2 } from './copy';
|
||||
|
||||
function shortNumber(num: number) {
|
||||
@@ -31,7 +32,23 @@ export async function Hero() {
|
||||
<Heading1 className="mb-4 text-slate-950">
|
||||
An open-source
|
||||
<br />
|
||||
alternative to Mixpanel
|
||||
alternative to{' '}
|
||||
<AnimatedText
|
||||
texts={[
|
||||
{
|
||||
text: 'Mixpanel',
|
||||
color: '#5028C0',
|
||||
},
|
||||
{
|
||||
text: 'Google Analytics',
|
||||
color: '#FAAE17',
|
||||
},
|
||||
{
|
||||
text: 'Plausible',
|
||||
color: '#5850EC',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Heading1>
|
||||
<Lead2 className="mb-12">
|
||||
The power of Mixpanel, the ease of Plausible and nothing from Google
|
||||
@@ -47,7 +64,7 @@ export async function Hero() {
|
||||
Get started
|
||||
</ALink>
|
||||
</div>
|
||||
<div className="mt-8 flex gap-8">
|
||||
<div className="mt-8 flex justify-center gap-8 md:justify-start">
|
||||
<div>
|
||||
<div className="text-sm uppercase text-muted-foreground">
|
||||
Collected events
|
||||
@@ -66,7 +83,7 @@ export async function Hero() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative mt-12 h-[max(90vh,650px)] w-full md:mt-24">
|
||||
<div className="relative mt-12 h-[max(90vh,650px)] w-full md:mt-36">
|
||||
<div className="absolute inset-0 flex rounded-2xl ring-8 ring-slate-300">
|
||||
<div className="absolute inset-0 w-full animate-pulse overflow-hidden rounded-2xl bg-slate-100" />
|
||||
<iframe
|
||||
|
||||
@@ -16,7 +16,7 @@ export function Navbar({ darkText = false, className }: Props) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'fixed left-0 right-0 top-0 z-10 flex h-20 items-center border-b border-border bg-white',
|
||||
'fixed left-0 right-0 top-0 z-10 z-50 flex h-20 items-center border-b border-border bg-white',
|
||||
textColor,
|
||||
className
|
||||
)}
|
||||
|
||||
16
pnpm-lock.yaml
generated
16
pnpm-lock.yaml
generated
@@ -632,6 +632,9 @@ importers:
|
||||
react-syntax-highlighter:
|
||||
specifier: ^15.5.0
|
||||
version: 15.5.0(react@18.2.0)
|
||||
react-type-animation:
|
||||
specifier: ^3.2.0
|
||||
version: 3.2.0(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0)
|
||||
tailwind-merge:
|
||||
specifier: ^1.14.0
|
||||
version: 1.14.0
|
||||
@@ -14959,6 +14962,7 @@ packages:
|
||||
|
||||
/osenv@0.1.5:
|
||||
resolution: {integrity: sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==}
|
||||
deprecated: This package is no longer supported.
|
||||
dependencies:
|
||||
os-homedir: 1.0.2
|
||||
os-tmpdir: 1.0.2
|
||||
@@ -15995,6 +15999,18 @@ packages:
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/react-type-animation@3.2.0(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-WXTe0i3rRNKjmggPvT5ntye1QBt0ATGbijeW6V3cQe2W0jaMABXXlPPEdtofnS9tM7wSRHchEvI9SUw+0kUohw==}
|
||||
peerDependencies:
|
||||
prop-types: ^15.5.4
|
||||
react: '>= 15.0.0'
|
||||
react-dom: '>= 15.0.0'
|
||||
dependencies:
|
||||
prop-types: 15.8.1
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/react-use-websocket@4.7.0(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-YjR62jB7vB94IZy5UPBGZSR3c0hxu796q9IuJ0vbNg7InJ7Z84NHOd/LHzVI5nAKtaGy1oqvf8EmjKxX+cNz4A==}
|
||||
peerDependencies:
|
||||
|
||||
Reference in New Issue
Block a user