Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Homepage: add "values" section with marquee #13836

Merged
merged 29 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
90cb069
feat: initialize "internet is changing" section
wackerow Sep 10, 2024
dc0bc15
feat: add usePrefersReducedMotion hook
wackerow Sep 10, 2024
71d14a6
patch: name
wackerow Sep 10, 2024
0718f24
feat: initialize motion-reduce preference
wackerow Sep 10, 2024
bdf11e5
chore: mobile adjustments
wackerow Sep 10, 2024
6c27e2e
chore: update colors, extract reusable component
wackerow Sep 11, 2024
768b115
Merge branch 'dev' into internet-is-changing
wackerow Sep 11, 2024
c12efbf
chore: yarn format
wackerow Sep 11, 2024
3c2ffee
style: clean up sizing, add header
wackerow Sep 12, 2024
103326a
fix: motion-reduce styling
wackerow Sep 12, 2024
8a91198
feat: import finalized copy
wackerow Sep 16, 2024
a4fe816
intl: extract strings
wackerow Sep 17, 2024
3672478
chore: rm ring
wackerow Sep 17, 2024
b3c193a
fix: use portal to lift tooltip
wackerow Sep 17, 2024
1af0a5e
chore: add string
wackerow Sep 17, 2024
16ff4d9
refactor: extract useValuesMarquee hook
wackerow Sep 17, 2024
175d6aa
refactor: rename to ValuesMarquee
wackerow Sep 17, 2024
25bfeaf
chore: add ethereum string
wackerow Sep 17, 2024
b6f77f6
feat: add center ethereum/legacy feature
wackerow Sep 17, 2024
360c0f9
chore: update to 15s animation
wackerow Sep 17, 2024
0617db6
set custom container to tooltips inside marquee to keep animation pau…
pettinarip Sep 18, 2024
d97bcff
Merge pull request #13906 from ethereum/marquee-tooltips
wackerow Sep 18, 2024
255a5e3
feat: implement desktop layout details
wackerow Sep 18, 2024
9f614e5
Merge branch 'dev' into internet-is-changing
wackerow Sep 19, 2024
ab43baa
fix: animation timing and mobile pausing
wackerow Sep 19, 2024
de6ed46
chore: increase scroll margin for values marquee
wackerow Sep 19, 2024
752f017
chore: suggestions from design review
wackerow Sep 19, 2024
52db0b9
matomo: "values" event on tooltip open
wackerow Sep 19, 2024
8dc29d7
Merge branch 'staging' into internet-is-changing
wackerow Sep 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/components/BannerGrid/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ export const BannerGridCell = ({ children }: ChildOnlyProp) => {
className={cn(
"px-0 py-8 md:px-12",
"flex-col",
"border-t border-t-search-background",
"md:border-s md:border-s-search-background",
"border-t-search-background border-t",
"md:border-s-search-background md:border-s",
"first:border-t-0",
"lg:[&:first-child]:border-s-0",
"md:[&:nth-child(-n+2)]:border-t-0 lg:[&:nth-child(-n+2)]:border-t lg:[&:nth-child(-n+2)]:border-t-search-background",
"md:[&:nth-child(2n+1)]:border-s-0 lg:[&:nth-child(2n+1)]:border-s lg:[&:nth-child(2n+1)]:border-s-search-background",
"lg:[&:nth-child(-n+2)]:border-t-search-background md:[&:nth-child(-n+2)]:border-t-0 lg:[&:nth-child(-n+2)]:border-t",
"lg:[&:nth-child(2n+1)]:border-s-search-background md:[&:nth-child(2n+1)]:border-s-0 lg:[&:nth-child(2n+1)]:border-s",
"lg:[&:nth-child(-n+3)]:justify-start lg:[&:nth-child(-n+3)]:border-t-0 lg:[&:nth-child(-n+3)]:pt-0",
"lg:[&:nth-child(3n+1)]:border-s-0 lg:[&:nth-child(3n+1)]:ps-0",
"lg:[&:nth-child(n+4)]:justify-start lg:[&:nth-child(n+4)]:pb-0"
Expand Down
2 changes: 1 addition & 1 deletion src/components/Hero/HomeHero/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const HomeHero = ({ heroImg, className }: HomeHeroProps) => {
<Morpher />
<div className="flex flex-col items-center gap-y-5 lg:max-w-2xl">
<h1 className="font-black">{t("page-index:page-index-title")}</h1>
<p className="max-w-96 text-body-medium">
<p className="max-w-96 text-md text-body-medium lg:text-lg">
{t("page-index:page-index-description")}
</p>
</div>
Expand Down
234 changes: 234 additions & 0 deletions src/components/Homepage/ValuesMarquee.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
import { forwardRef, useEffect, useRef, useState } from "react"
import { FaCheck } from "react-icons/fa"
import { MdClose } from "react-icons/md"

import EthGlyphSolid from "@/components/icons/eth-glyph-solid.svg"
import Tooltip from "@/components/Tooltip"

import { cn } from "@/lib/utils/cn"
import { isMobile } from "@/lib/utils/isMobile"
import { trackCustomEvent } from "@/lib/utils/matomo"

import { type Pairing, useValuesMarquee } from "../Homepage/useValuesMarquee"
import { Stack } from "../ui/flex"
import {
Section,
SectionContent,
SectionHeader,
SectionTag,
} from "../ui/section"

import { usePrefersReducedMotion } from "@/hooks/usePrefersReducedMotion"

type ItemProps = React.HTMLAttributes<HTMLButtonElement> & {
pairing: Pairing
separatorClass: string
container?: HTMLElement | null
label: string
}

const Item = ({
children,
className,
pairing,
separatorClass,
container,
label,
}: ItemProps) => (
<>
<Tooltip
container={container}
onBeforeOpen={() => {
trackCustomEvent({
eventCategory: "Homepage",
eventAction: "internet_changing",
eventName: label,
})
}}
content={
<Stack>
<h3 className="text-md text-body-medium dark:text-gray-300">
{label}
</h3>
<div className="flex flex-col gap-4">
<div className="flex gap-2 text-body-medium">
<div className="p-1 text-lg">
<MdClose />
</div>
<div>
{pairing.legacy.content.map((line) => (
<p key={line} className="text-sm">
{line}
</p>
))}
</div>
</div>
<div className="flex gap-2 text-body">
<div className="p-1 text-lg">
<EthGlyphSolid />
</div>
<div className="flex flex-col gap-2">
{pairing.ethereum.content.map((line) => (
<p key={line} className="text-sm">
{line}
</p>
))}
</div>
</div>
</div>
</Stack>
}
>
<div
className={cn(
"flex flex-nowrap items-center text-nowrap rounded-full px-4 py-1 font-bold uppercase",
className
)}
>
{children}
</div>
</Tooltip>
<div
className={cn(
"h-1.5 min-w-1.5 rounded-full motion-reduce:last:hidden",
separatorClass
)}
/>
</>
)

type RowProps = React.HTMLAttributes<HTMLDivElement> & {
toRight?: boolean
}

const Row = forwardRef<HTMLDivElement, RowProps>(
({ className, children, toRight }, ref) => {
const { prefersReducedMotion } = usePrefersReducedMotion()
const fadeEdges = {
mask: `linear-gradient(to right, transparent 1rem, white 15%, white 85%, transparent calc(100% - 1rem))`,
}

return (
<div ref={ref} className={cn("group", className)}>
<div
className="flex max-w-full overflow-hidden motion-reduce:overflow-auto"
style={prefersReducedMotion ? {} : fadeEdges}
>
{Array(prefersReducedMotion ? 1 : 3)
.fill(0)
.map((_, idx) => (
<div
key={idx}
className={cn(
"flex min-w-fit items-center space-x-10 px-6 py-8 motion-reduce:w-full motion-reduce:animate-none motion-reduce:justify-center",
isMobile()
? "group-has-[button:hover]:animate-pause"
: "group-hover:animate-pause",
toRight ? "animate-scroll-right" : "animate-scroll-left"
)}
>
{children}
</div>
))}
</div>
</div>
)
}
)
Row.displayName = "Row"

const ValuesMarquee = () => {
const { t, pairings } = useValuesMarquee()
const containerFirstRef = useRef<HTMLDivElement>(null)
const containerSecondRef = useRef<HTMLDivElement>(null)

const [containerFirst, setContainerFirst] = useState<HTMLDivElement | null>(
null
)
const [containerSecond, setContainerSecond] = useState<HTMLDivElement | null>(
null
)

useEffect(() => {
if (containerFirstRef.current) {
setContainerFirst(containerFirstRef.current)
}
if (containerSecondRef.current) {
setContainerSecond(containerSecondRef.current)
}
}, [])

return (
<Section id="values" className="!sm:my-64 !my-48 scroll-m-48">
<SectionContent className="flex flex-col items-center text-center">
<SectionTag>{t("page-index:page-index-values-tag")}</SectionTag>
<SectionHeader>
{t("page-index:page-index-values-header")}
</SectionHeader>
<p className="text-lg text-body-medium">
{t("page-index:page-index-values-description")}
</p>
</SectionContent>
<div className="relative mt-19 overflow-hidden max-2xl:-mx-4 2xl:rounded-2xl">
<Row
ref={containerFirstRef}
className="border-b border-background bg-blue-50 dark:bg-blue-600"
>
{pairings.map((pairing) => (
<Item
key={pairing.ethereum.label}
label={pairing.ethereum.label}
container={containerFirst}
pairing={pairing}
separatorClass="bg-accent-a"
className="group/item bg-blue-100 text-blue-600 hover:bg-blue-600 hover:text-white dark:hover:bg-blue-700"
>
<FaCheck className="me-1 text-success group-hover/item:text-white" />
{pairing.ethereum.label}
</Item>
))}
</Row>

<Row
ref={containerSecondRef}
className="border-t border-background bg-gray-50 dark:bg-gray-800"
toRight
>
{pairings.map((pairing) => (
<Item
key={pairing.legacy.label}
label={pairing.legacy.label}
container={containerSecond}
pairing={pairing}
className="bg-gray-200/20 text-body-medium hover:bg-gray-600 hover:text-white dark:bg-gray-950 dark:text-body"
separatorClass="bg-gray-200 dark:bg-gray-950"
>
{pairing.legacy.label}
</Item>
))}
</Row>

<div className="absolute start-[50%] top-[50%] flex -translate-x-[50%] -translate-y-[50%] items-center overflow-hidden rounded-lg text-sm font-bold">
<p className="bg-gray-50 px-4 py-1 text-body-medium dark:bg-gray-800 dark:text-gray-200">
{t("page-index-values-legacy")}
</p>

<div
className={cn(
"border-t-[15px] border-t-blue-50 dark:border-t-blue-600",
"border-r-8 border-r-blue-50 dark:border-r-blue-600",
"border-b-[15px] border-b-gray-50 dark:border-b-gray-800",
"border-l-8 border-l-gray-50 dark:border-l-gray-800"
)}
/>

<p className="bg-blue-50 px-4 py-1 text-accent-a dark:bg-blue-600 dark:text-white">
{t("common:ethereum")}
</p>
</div>
</div>
</Section>
)
}

export default ValuesMarquee
98 changes: 98 additions & 0 deletions src/components/Homepage/useValuesMarquee.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { useTranslation } from "next-i18next"

type Item = {
label: string
content: string[]
}

export type Pairing = {
legacy: Item
ethereum: Item
}

export const useValuesMarquee = () => {
const { t } = useTranslation("page-index")
const pairings: Pairing[] = [
{
legacy: {
label: t("page-index-values-ownership-legacy-label"),
content: [
t("page-index-values-ownership-legacy-content-0"),
t("page-index-values-ownership-legacy-content-1"),
],
},
ethereum: {
label: t("page-index-values-ownership-ethereum-label"),
content: [t("page-index-values-ownership-ethereum-content-0")],
},
},
{
legacy: {
label: t("page-index-values-fairness-legacy-label"),
content: [t("page-index-values-fairness-legacy-content-0")],
},
ethereum: {
label: t("page-index-values-fairness-ethereum-label"),
content: [t("page-index-values-fairness-ethereum-content-0")],
},
},
{
legacy: {
label: t("page-index-values-privacy-legacy-label"),
content: [
t("page-index-values-privacy-legacy-content-0"),
t("page-index-values-privacy-legacy-content-1"),
],
},
ethereum: {
label: t("page-index-values-privacy-ethereum-label"),
content: [t("page-index-values-privacy-ethereum-content-0")],
},
},
{
legacy: {
label: t("page-index-values-integration-legacy-label"),
content: [t("page-index-values-integration-legacy-content-0")],
},
ethereum: {
label: t("page-index-values-integration-ethereum-label"),
content: [t("page-index-values-integration-ethereum-content-0")],
},
},
{
legacy: {
label: t("page-index-values-decentralization-legacy-label"),
content: [t("page-index-values-decentralization-legacy-content-0")],
},
ethereum: {
label: t("page-index-values-decentralization-ethereum-label"),
content: [t("page-index-values-decentralization-ethereum-content-0")],
},
},
{
legacy: {
label: t("page-index-values-censorship-legacy-label"),
content: [t("page-index-values-censorship-legacy-content-0")],
},
ethereum: {
label: t("page-index-values-censorship-ethereum-label"),
content: [
t("page-index-values-censorship-ethereum-content-0"),
t("page-index-values-censorship-ethereum-content-1"),
],
},
},
{
legacy: {
label: t("page-index-values-open-legacy-label"),
content: [t("page-index-values-open-legacy-content-0")],
},
ethereum: {
label: t("page-index-values-open-ethereum-label"),
content: [t("page-index-values-open-ethereum-content-0")],
},
},
]

return { t, pairings }
}
Loading
Loading