diff options
| author | 2023-04-22 19:52:26 +0800 | |
|---|---|---|
| committer | 2023-04-22 19:52:26 +0800 | |
| commit | 4838df315931bb883f704ec3e1abe2685f296cdf (patch) | |
| tree | 57a8550c4cd5338f1126364bb518c6cde8d96e7d /docs/components/pages/home-shared | |
| parent | db74ade0234a40c2120ad5f2a41bee50ce13de02 (diff) | |
| download | HydroRoll-4838df315931bb883f704ec3e1abe2685f296cdf.tar.gz HydroRoll-4838df315931bb883f704ec3e1abe2685f296cdf.zip | |
😀
Diffstat (limited to 'docs/components/pages/home-shared')
| -rw-r--r-- | docs/components/pages/home-shared/CTAButton.tsx | 43 | ||||
| -rw-r--r-- | docs/components/pages/home-shared/FadeIn.tsx | 50 | ||||
| -rw-r--r-- | docs/components/pages/home-shared/FeatureBox.tsx | 42 | ||||
| -rw-r--r-- | docs/components/pages/home-shared/FeaturesBento.tsx | 38 | ||||
| -rw-r--r-- | docs/components/pages/home-shared/GlobalStyles.tsx | 20 | ||||
| -rw-r--r-- | docs/components/pages/home-shared/Gradient.tsx | 47 | ||||
| -rw-r--r-- | docs/components/pages/home-shared/GradientSectionBorder.tsx | 37 | ||||
| -rw-r--r-- | docs/components/pages/home-shared/Headings.tsx | 56 | ||||
| -rw-r--r-- | docs/components/pages/home-shared/gradients.module.css | 231 |
9 files changed, 564 insertions, 0 deletions
diff --git a/docs/components/pages/home-shared/CTAButton.tsx b/docs/components/pages/home-shared/CTAButton.tsx new file mode 100644 index 0000000..57da227 --- /dev/null +++ b/docs/components/pages/home-shared/CTAButton.tsx @@ -0,0 +1,43 @@ +import cn from "classnames"; +import { MouseEventHandler } from "react"; +import gradients from "./gradients.module.css"; + +export function CTAButton({ + children, + outline, + onClick, + monospace, +}: { + outline?: boolean; + children: React.ReactNode; + onClick?: MouseEventHandler<HTMLButtonElement>; + monospace?: boolean; +}) { + const outlineClasses = + "border dark:border-neutral-400 dark:text-neutral-200 dark:hover:border-white dark:hover:text-white border-[#EAEAEA] text-neutral-800 hover:border-black hover:text-black"; + const filledClasses = + "dark:text-black text-white border-transparent bg-black dark:bg-white"; + + return ( + <div className="relative w-full group"> + <button + onClick={onClick} + className={`w-full min-w-[120px] text-base font-medium no-underline ${ + outline ? outlineClasses : filledClasses + } rounded md:leading-6 transition-all duration-300 ${ + monospace ? "font-mono" : "" + }`} + > + {children} + </button> + {!outline && ( + <div + className={cn( + "absolute bg-red-100 w-full h-full top-0 -z-10 rounded-full transition-all duration-300 blur-xl group-hover:opacity-70 opacity-0", + gradients.translatingGlow + )} + /> + )} + </div> + ); +} diff --git a/docs/components/pages/home-shared/FadeIn.tsx b/docs/components/pages/home-shared/FadeIn.tsx new file mode 100644 index 0000000..826a078 --- /dev/null +++ b/docs/components/pages/home-shared/FadeIn.tsx @@ -0,0 +1,50 @@ +import { motion, useInView } from "framer-motion"; +import { useRef } from "react"; + +export function FadeIn({ + children, + className, + noVertical, + delay, + viewTriggerOffset, +}: { + children: React.ReactNode; + className?: string; + noVertical?: boolean; + delay?: number; + viewTriggerOffset?: boolean; +}) { + const ref = useRef(null); + const inView = useInView(ref, { + once: true, + margin: viewTriggerOffset ? "-128px" : "0px", + }); + + const fadeUpVariants = { + initial: { + opacity: 0, + y: noVertical ? 0 : 24, + }, + animate: { + opacity: 1, + y: 0, + }, + }; + + return ( + <motion.div + ref={ref} + animate={inView ? "animate" : "initial"} + variants={fadeUpVariants} + className={className} + initial={false} + transition={{ + duration: 1, + delay: delay || 0, + ease: [0.21, 0.47, 0.32, 0.98], + }} + > + {children} + </motion.div> + ); +} diff --git a/docs/components/pages/home-shared/FeatureBox.tsx b/docs/components/pages/home-shared/FeatureBox.tsx new file mode 100644 index 0000000..c9d46c1 --- /dev/null +++ b/docs/components/pages/home-shared/FeatureBox.tsx @@ -0,0 +1,42 @@ +import Image from "next/image"; +import type { ReactNode } from "react"; + +export function FeatureBox({ + name, + description, + iconDark, + iconLight, +}: { + iconDark: Parameters<typeof Image>[0]["src"]; + iconLight: Parameters<typeof Image>[0]["src"]; + name: string; + description: ReactNode; +}) { + return ( + <div className="box-border relative flex flex-col gap-5 p-8 overflow-hidden text-black no-underline border dark:text-white rounded-xl dark:border-neutral-800"> + <Image + src={iconDark} + width={64} + height={64} + aria-hidden="true" + alt="" + className="hidden dark:block" + /> + <Image + src={iconLight} + width={64} + height={64} + aria-hidden="true" + alt="" + className="block dark:hidden" + /> + <div className="flex flex-col gap-2"> + <h3 className="m-0 font-bold leading-5 text-gray-900 font-space-grotesk dark:text-white"> + {name} + </h3> + + <p className="m-0 leading-6 opacity-70">{description}</p> + </div> + </div> + ); +} diff --git a/docs/components/pages/home-shared/FeaturesBento.tsx b/docs/components/pages/home-shared/FeaturesBento.tsx new file mode 100644 index 0000000..f2664db --- /dev/null +++ b/docs/components/pages/home-shared/FeaturesBento.tsx @@ -0,0 +1,38 @@ +import type { Features } from "../../../content/features"; +import { FadeIn } from "./FadeIn"; +import { SectionHeader, SectionSubtext } from "./Headings"; +import { FeatureBox } from "./FeatureBox"; + +export function FeaturesBento({ + header, + body, + features, +}: { + header: string; + body: string; + features: Features; +}) { + return ( + <section className="relative flex flex-col items-center px-6 pb-16 font-sans md:pb-24 lg:pb-32 gap-9 lg:gap-14"> + <FadeIn className="flex flex-col items-center gap-5 md:gap-6"> + <SectionHeader>{header}</SectionHeader> + <SectionSubtext>{body}</SectionSubtext> + </FadeIn> + <div className="grid grid-cols-1 gap-x-4 gap-y-4 sm:grid-cols-2 lg:grid-cols-3 lg:gap-x-6 lg:gap-y-6 max-w-[1200px]"> + {features.map((feature) => ( + <FadeIn + className="flex" + key={feature.name.replace(/\s+/g, "-").toLowerCase()} + > + <FeatureBox + name={feature.name} + description={feature.description} + iconDark={feature.iconDark} + iconLight={feature.iconLight} + /> + </FadeIn> + ))} + </div> + </section> + ); +} diff --git a/docs/components/pages/home-shared/GlobalStyles.tsx b/docs/components/pages/home-shared/GlobalStyles.tsx new file mode 100644 index 0000000..5f695f3 --- /dev/null +++ b/docs/components/pages/home-shared/GlobalStyles.tsx @@ -0,0 +1,20 @@ +import Head from "next/head"; + +export function LandingPageGlobalStyles() { + return ( + <Head> + <style> + {` + .dark footer, + .dark body { + background-color: black !important; + } + + .dark .nextra-nav-container .nextra-nav-container-blur { + background-color: rgba(0,0,0,.5) !important; + } + `} + </style> + </Head> + ); +} diff --git a/docs/components/pages/home-shared/Gradient.tsx b/docs/components/pages/home-shared/Gradient.tsx new file mode 100644 index 0000000..9a03a99 --- /dev/null +++ b/docs/components/pages/home-shared/Gradient.tsx @@ -0,0 +1,47 @@ +import cn from "classnames"; +import gradients from "./gradients.module.css"; + +export function Gradient({ + width = 1000, + height = 200, + opacity, + pink, + blue, + conic, + gray, + className, + small, +}: { + width?: number | string; + height?: number | string; + opacity?: number; + pink?: boolean; + blue?: boolean; + conic?: boolean; + gray?: boolean; + className?: string; + small?: boolean; +}) { + return ( + <span + className={cn( + "absolute", + gradients.glow, + { + [gradients.glowPink]: pink, + [gradients.glowBlue]: blue, + [gradients.glowConic]: conic, + [gradients.glowSmall]: small, + [gradients.glowGray]: gray, + }, + className + )} + style={{ + width, + height, + opacity, + borderRadius: "100%", + }} + /> + ); +} diff --git a/docs/components/pages/home-shared/GradientSectionBorder.tsx b/docs/components/pages/home-shared/GradientSectionBorder.tsx new file mode 100644 index 0000000..ef1e824 --- /dev/null +++ b/docs/components/pages/home-shared/GradientSectionBorder.tsx @@ -0,0 +1,37 @@ +import cn from "classnames"; +import { FadeIn } from "./FadeIn"; +import gradients from "../home-shared/gradients.module.css"; + +export function GradientSectionBorder({ + children, +}: { + children: React.ReactNode; +}) { + return ( + <section className={cn("relative overflow-hidden")}> + <FadeIn noVertical viewTriggerOffset> + <span + className={cn( + "w-full absolute white h-[1px] top-0 opacity-25", + gradients.gradientSectionBorderDivider + )} + /> + <span + className={cn( + gradients.gradientSectionBorder, + gradients.gradientSectionBorderLeft, + "dark:opacity-35 opacity-[0.15]" + )} + /> + <span + className={cn( + gradients.gradientSectionBorder, + gradients.gradientSectionBorderRight, + "dark:opacity-35 opacity-[0.15]" + )} + /> + </FadeIn> + {children} + </section> + ); +} diff --git a/docs/components/pages/home-shared/Headings.tsx b/docs/components/pages/home-shared/Headings.tsx new file mode 100644 index 0000000..43a5e52 --- /dev/null +++ b/docs/components/pages/home-shared/Headings.tsx @@ -0,0 +1,56 @@ +import cn from "classnames"; +import gradients from "./gradients.module.css"; + +export function HeroText({ + children, + className, + h1, +}: { + children: React.ReactNode; + className?: string; + h1?: boolean; +}) { + const combinedClassname = cn( + gradients.heroHeading, + "font-extrabold tracking-[-0.04em] leading-none text-[40px] md:text-5xl lg:text-[80px] max-w-lg md:max-w-xl lg:max-w-4xl text-center text-transparent", + className + ); + + if (h1) { + return <h1 className={combinedClassname}>{children}</h1>; + } + return <h2 className={combinedClassname}>{children}</h2>; +} + +export function SectionHeader({ children }: { children: React.ReactNode }) { + return ( + <h2 + className={cn( + gradients.heroHeading, + "font-bold tracking-[-0.01em] pb-1 text-[32px] md:text-4xl lg:text-[40px] max-w-sm md:max-w-md lg:max-w-2xl text-center text-transparent" + )} + > + {children} + </h2> + ); +} + +export function SectionSubtext({ + hero, + children, +}: { + hero?: boolean; + children: React.ReactNode; +}) { + const textClasses = hero + ? "text-[20px] lg:text-xl" + : "text-[16px] lg:text-[20px]"; + + return ( + <p + className={`font-space-grotesk leading-snug dark:text-[#FFFFFFB2] text-[#00000080] ${textClasses} max-w-md md:max-w-xl lg:max-w-[640px] text-center`} + > + {children} + </p> + ); +} diff --git a/docs/components/pages/home-shared/gradients.module.css b/docs/components/pages/home-shared/gradients.module.css new file mode 100644 index 0000000..b9c50a9 --- /dev/null +++ b/docs/components/pages/home-shared/gradients.module.css @@ -0,0 +1,231 @@ +.benchmarkTurbo { + background: linear-gradient(288.43deg, #ff1e56 28.29%, #9c51a1 78.78%); + box-shadow: 0px 0px 16px #f02662; + :global(.light) & { + background: linear-gradient( + 268.86deg, + #ff1e56 -5.68%, + #d67fdc 107.63%, + #9c51a1 107.64% + ); + box-shadow: none; + } +} + +.benchmarkActiveTab { + background: radial-gradient( + 50% 50% at 50% 100%, + rgba(255, 255, 255, 0.2) 0%, + rgba(255, 255, 255, 0) 100% + ), + linear-gradient(0deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.12)), + radial-gradient( + 128.57% 128.57% at 50% 0%, + rgba(255, 255, 255, 0.1) 0%, + rgba(255, 255, 255, 0) 100% + ), + radial-gradient( + 100% 427.04% at 100% 0%, + rgba(255, 255, 255, 0.1) 0%, + rgba(255, 255, 255, 0) 100% + ), + radial-gradient( + 100% 462.63% at 0% 0%, + rgba(255, 255, 255, 0.1) 0%, + rgba(255, 255, 255, 0) 100% + ); + :global(.light) & { + background: linear-gradient( + 0deg, + rgba(255, 255, 255, 0.8), + rgba(255, 255, 255, 0.8) + ), + radial-gradient( + 50% 50% at 49.66% 0%, + rgba(255, 255, 255, 0.1) 0%, + rgba(255, 255, 255, 0) 100% + ); + } +} + +.benchmarkTurboLabel { + background: linear-gradient(288.43deg, #ff1e56 28.29%, #9c51a1 78.78%); + color: transparent; + background-clip: text; + :global(.light) & { + background: linear-gradient( + 268.86deg, + #ff1e56 -5.68%, + #d67fdc 107.63%, + #9c51a1 107.64% + ), + linear-gradient(288.43deg, #ff1e56 28.29%, #9c51a1 78.78%); + color: transparent; + background-clip: text; + } +} + +.benchmark { + background: linear-gradient(270deg, #5c5c5c 0%, #1f1f1f 100%); + :global(.light) & { + background: linear-gradient(89.98deg, #e0e0e0 0.01%, #9c9c9c 99.49%); + } +} + +.barBorder { + border: rgba(255, 255, 255, 0.4) 1px solid; + :global(.light) & { + border: rgba(0, 0, 0, 0.6) 1px solid; + } +} + +.tooltipArrow { + display: block; + border-left: 8px solid transparent; + border-bottom: 8px solid #333333; + border-right: 8px solid transparent; + :global(.light) & { + border-bottom: 8px solid #f5f5f5; + } +} +.translatingGlow { + background: linear-gradient(32deg, #2a8af6 0%, #a853ba 50%, #e92a67 100%); + background-size: 200% 200%; + animation: translateGlow 7s linear infinite; + will-change: filter; +} + +@keyframes translateGlow { + 0% { + background-position: -20% -20%; + } + 25% { + background-position: 30% 80%; + } + 50% { + background-position: 110% 110%; + } + 75% { + background-position: 80% 30%; + } + 100% { + background-position: -20% -20%; + } +} + +.turbopackHeaderText { + background: linear-gradient( + 90deg, + rgba(200, 221, 255, 0.75) 0%, + rgba(255, 202, 222, 0.75) 100% + ), + linear-gradient(0deg, #ffffff, #ffffff); + + :global(.light) & { + background: linear-gradient( + 90deg, + rgba(200, 221, 255, 0.1) 0%, + rgba(255, 202, 222, 0.1) 100% + ), + #000000; + background-clip: text; + } + background-clip: text; +} + +.heroHeading { + background: linear-gradient(180deg, #ffffff 0%, #aaaaaa 100%), #ffffff; + :global(.light) & { + background: linear-gradient(180deg, rgba(0, 0, 0, 0.8) 0%, #000000 100%); + background-clip: text; + } + background-clip: text; +} + +.letterLine { + opacity: 0.2; + background: linear-gradient( + 90deg, + #000000 0%, + #ffffff 20%, + #ffffff 80%, + #000000 100% + ); + :global(.light) & { + background: linear-gradient( + 90deg, + #ffffff 0%, + #000000 20%, + #000000 80%, + #ffffff 100% + ); + } +} + +.glow { + mix-blend-mode: normal; + filter: blur(75px); + will-change: filter; +} + +.glowSmall { + filter: blur(32px); +} + +.glowBlue { + background: linear-gradient(180deg, #58a5ff 0%, #a67af4 100%); +} + +.glowPink { + background: linear-gradient(180deg, #ff3358 0%, #ff4fd8 100%); +} + +.glowConic { + background: conic-gradient( + from 180deg at 50% 50%, + #2a8af6 0deg, + #a853ba 180deg, + #e92a67 360deg + ); +} + +.glowGray { + background: rgba(255, 255, 255, 0.15); +} + +.gradientSectionBorder { + --gradient-y-offset: -200px; + --gradient-x-offset: -200px; + --height: 255px; + position: relative; + overflow: hidden; + will-change: filter; +} + +.gradientSectionBorderLeft { + position: absolute; + width: 60vw; + height: var(--height); + left: var(--gradient-x-offset); + top: var(--gradient-y-offset); + background: linear-gradient(180deg, #58a5ff 0%, #a67af4 100%); + border-radius: 100%; + mix-blend-mode: normal; + filter: blur(50px); +} + +.gradientSectionBorderRight { + width: 60vw; + position: absolute; + height: var(--height); + right: var(--gradient-x-offset); + top: var(--gradient-y-offset); + background: linear-gradient(180deg, #ff3358 0%, #ff4fd8 100%); + border-radius: 100%; + mix-blend-mode: normal; + filter: blur(50px); +} + +.gradientSectionBorderDivider { + background: linear-gradient(90deg, #288cf9 0%, #e32c6b 100%); +} |
