Skip to content
This repository was archived by the owner on Aug 27, 2025. It is now read-only.

Commit e86b0d4

Browse files
committed
Merge branch 'feat/landing-page'
2 parents 2af7337 + f89e0b5 commit e86b0d4

File tree

105 files changed

+3560
-193
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+3560
-193
lines changed

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,16 @@
1717
"start": "pnpm --filter crossbell.io run start"
1818
},
1919
"dependencies": {
20-
"@crossbell/connect-kit": "0.0.77",
21-
"@crossbell/contract": "0.0.77",
22-
"@crossbell/indexer": "0.0.77",
20+
"@crossbell/connect-kit": "0.0.80",
21+
"@crossbell/contract": "0.0.80",
22+
"@crossbell/indexer": "0.0.80",
2323
"@crossbell/ipfs-gateway": "0.0.18",
2424
"@crossbell/ipfs-react": "0.0.18",
25-
"@crossbell/notification": "0.0.77",
26-
"@crossbell/ui": "0.0.77",
27-
"@crossbell/util-ethers": "0.0.77",
28-
"@crossbell/util-hooks": "0.0.77",
29-
"@crossbell/util-metadata": "0.0.77",
25+
"@crossbell/notification": "0.0.80",
26+
"@crossbell/ui": "0.0.80",
27+
"@crossbell/util-ethers": "0.0.80",
28+
"@crossbell/util-hooks": "0.0.80",
29+
"@crossbell/util-metadata": "0.0.80",
3030
"@ctrl/tinycolor": "3.6.0",
3131
"@emoji-mart/react": "1.1.1",
3232
"@emotion/cache": "11.10.7",

pnpm-lock.yaml

Lines changed: 469 additions & 71 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

shared/providers/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export function MainProvider({ children, urlComposer }: MainProviderProps) {
5454
<ThemeProvider>
5555
<WalletProvider>
5656
<QueryProvider>
57-
<LazyMotion features={loadFeatures} strict>
57+
<LazyMotion features={loadFeatures}>
5858
<ModalsProvider>
5959
<NotificationsProvider>
6060
<RouterTransition />

sites/crossbell.io/components/pages/Index/components/Logo.tsx

Lines changed: 0 additions & 65 deletions
This file was deleted.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import React, { ReactHTML, useEffect, useRef } from "react";
2+
import { HTMLMotionProps, motion, useAnimation } from "framer-motion";
3+
4+
export type AutoShowProps<T extends keyof ReactHTML> = HTMLMotionProps<T> & {
5+
as?: T;
6+
};
7+
8+
export function AutoShow<T extends keyof ReactHTML = "div">({
9+
children,
10+
as,
11+
...props
12+
}: AutoShowProps<T>) {
13+
const controls = useAnimation();
14+
const ref = useRef<HTMLDivElement>(null);
15+
const [isActive, setIsActive] = React.useState(false);
16+
// @ts-expect-error
17+
const MotionComponent = motion[as ?? "div"];
18+
19+
useEffect(() => {
20+
const elm = ref.current;
21+
22+
if (!elm) return;
23+
24+
const observer = new IntersectionObserver(
25+
([entry]) => {
26+
if (entry.isIntersecting) {
27+
setIsActive(true);
28+
observer.disconnect();
29+
}
30+
},
31+
{
32+
root: null,
33+
rootMargin: "0px",
34+
threshold: 0.1,
35+
}
36+
);
37+
38+
observer.observe(elm);
39+
40+
return () => {
41+
observer.disconnect();
42+
};
43+
}, [controls]);
44+
45+
return (
46+
<MotionComponent
47+
ref={ref}
48+
initial={false}
49+
animate={{ opacity: isActive ? 1 : 0, y: isActive ? 0 : 50 }}
50+
transition={{ duration: 0.5, delay: 0.3 }}
51+
{...props}
52+
>
53+
{children}
54+
</MotionComponent>
55+
);
56+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
.flipCard {
2+
background-color: transparent;
3+
perspective: 1000px;
4+
cursor: pointer;
5+
}
6+
7+
.flipped .flipCardInner {
8+
transform: rotateY(180deg);
9+
}
10+
11+
.flipCardInner {
12+
position: relative;
13+
width: 100%;
14+
height: 100%;
15+
text-align: center;
16+
transition: transform 0.8s;
17+
transform-style: preserve-3d;
18+
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.1);
19+
}
20+
21+
.flipCardFront,
22+
.flipCardBack {
23+
position: absolute;
24+
top: 0;
25+
left: 0;
26+
right: 0;
27+
bottom: 0;
28+
display: flex;
29+
justify-content: center;
30+
align-items: center;
31+
backface-visibility: hidden;
32+
}
33+
34+
.flipCardFront {
35+
background-color: transparent;
36+
}
37+
38+
.flipCardBack {
39+
background-color: transparent;
40+
transform: rotateY(180deg);
41+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import React from "react";
2+
3+
import styles from "./index.module.css";
4+
import classNames from "classnames";
5+
6+
export type FlipCardProps = {
7+
front: React.ReactNode;
8+
back: React.ReactNode;
9+
isFlipped: boolean;
10+
width: number;
11+
height: number;
12+
} & React.HTMLAttributes<HTMLDivElement>;
13+
14+
export const FlipCard: React.FC<FlipCardProps> = ({
15+
front,
16+
back,
17+
width,
18+
height,
19+
isFlipped,
20+
...props
21+
}) => {
22+
const className = classNames(
23+
props.className,
24+
styles.flipCard,
25+
isFlipped && styles.flipped
26+
);
27+
28+
const cardStyle = {
29+
...props.style,
30+
width: `${width}px`,
31+
height: `${height}px`,
32+
};
33+
34+
return (
35+
<div {...props} className={className} style={cardStyle}>
36+
<div className={styles.flipCardInner}>
37+
<div className={styles.flipCardFront}>{front}</div>
38+
<div className={styles.flipCardBack}>{back}</div>
39+
</div>
40+
</div>
41+
);
42+
};
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import React from "react";
2+
import Image from "next/image";
3+
import Link from "next/link";
4+
import { Popover } from "@mantine/core";
5+
import { BaseModal } from "@crossbell/ui";
6+
7+
import {
8+
CrossbellLogo,
9+
XFeedLogo,
10+
XCharLogo,
11+
XSyncLogo,
12+
XLogLogo,
13+
breakpoints,
14+
} from "@crossbell/ui";
15+
import { useMediaQuery } from "@mantine/hooks";
16+
import { useDisclosure } from "@crossbell/util-hooks";
17+
18+
import appsImg from "./apps-icon.svg";
19+
20+
export function Header() {
21+
return (
22+
<div className="fixed md:absolute top-0 left-0 w-full bg-[#0D0E0F] md:bg-transparent z-20 px-[24px] pt-[24px] pb-[12px]">
23+
<div className="max-w-[1920px] mx-auto flex justify-between gap-[32px]">
24+
<CrossbellLogo className="w-[90px] h-[24px]" />
25+
<Link href="/products" className="mr-auto hidden md:block">
26+
Products
27+
</Link>
28+
<AppsBtn />
29+
</div>
30+
</div>
31+
);
32+
}
33+
34+
function AppsBtn() {
35+
const isSM = useMediaQuery(`(min-width: ${breakpoints.sm}px)`);
36+
const [isModalOpened, modal] = useDisclosure(false);
37+
38+
const apps = (
39+
<div className="p-24px flex flex-col gap-[20px] items-center">
40+
<div className="flex items-center justify-between w-full">
41+
<a
42+
className="flex flex-col items-center gap-[4px]"
43+
href="https://xfeed.app"
44+
target="_blank"
45+
>
46+
<XFeedLogo className="w-[36px] h-[36px]" />
47+
<div className="text-[#000]">xFeed</div>
48+
</a>
49+
50+
<a
51+
className="flex flex-col items-center gap-[4px]"
52+
href="https://xchar.app"
53+
target="_blank"
54+
>
55+
<XCharLogo className="w-[36px] h-[36px]" />
56+
<div className="text-[#000]">xChar</div>
57+
</a>
58+
59+
<a
60+
className="flex flex-col items-center gap-[4px]"
61+
href="https://xsync.app"
62+
target="_blank"
63+
>
64+
<XSyncLogo className="w-[36px] h-[36px]" />
65+
<div className="text-[#000]">xSync</div>
66+
</a>
67+
68+
<a
69+
className="flex flex-col items-center gap-[4px]"
70+
href="https://xlog.app"
71+
target="_blank"
72+
>
73+
<XLogLogo className="w-[36px] h-[36px] text-[#000]" />
74+
<div className="text-[#000]">xLog</div>
75+
</a>
76+
</div>
77+
</div>
78+
);
79+
80+
const btn = (
81+
<Image
82+
src={appsImg}
83+
alt="Apps"
84+
onClick={isSM ? undefined : modal.open}
85+
className="cursor-pointer"
86+
/>
87+
);
88+
89+
if (isSM) {
90+
return (
91+
<Popover width={320} radius={24} offset={24} position="bottom-end">
92+
<Popover.Target>{btn}</Popover.Target>
93+
94+
<Popover.Dropdown p={0} className="border-[#E1E8F7]">
95+
{apps}
96+
</Popover.Dropdown>
97+
</Popover>
98+
);
99+
} else {
100+
return (
101+
<>
102+
<BaseModal
103+
isActive={isModalOpened}
104+
onClickBg={modal.close}
105+
onClose={modal.close}
106+
zIndex={11}
107+
>
108+
<div className="w-[100vw] px-[24px] max-w-[320px]">
109+
<div className="bg-[#fff] rounded-[24px]">{apps}</div>
110+
</div>
111+
</BaseModal>
112+
{btn}
113+
</>
114+
);
115+
}
116+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import React from "react";
2+
import Image, { ImageProps } from "next/image";
3+
4+
import starImg from "./star.svg";
5+
6+
export function Star(props: Partial<ImageProps>) {
7+
return <Image src={starImg} alt="Star" {...props} />;
8+
}

0 commit comments

Comments
 (0)