chore: Update ThemePage component to include padding for mobile view

This commit is contained in:
Mauro Balades 2024-08-17 22:15:27 +02:00
parent 57b43c6ad2
commit fa36454e77
22 changed files with 223 additions and 50 deletions

BIN
public/color-preview.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

BIN
public/compact-mode.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

BIN
public/logos/zen-black.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
public/logos/zen-blue.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
public/logos/zen-brown.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
public/logos/zen-buff.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
public/logos/zen-indigo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
public/logos/zen-mantis.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
public/logos/zen-orchid.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
public/logos/zen-pink.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
public/logos/zen-white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
public/logos/zen-yellow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View file

@ -29,6 +29,8 @@ import {
import ShineBorder from "./ui/shine-border"; import ShineBorder from "./ui/shine-border";
import SparklesText from "./ui/sparkles-text"; import SparklesText from "./ui/sparkles-text";
import Image from "next/image"; import Image from "next/image";
import OrbitingCircles from "./ui/orbiting-circles";
import { ny } from "@/lib/utils";
function Checkmark() { function Checkmark() {
return ( return (
@ -49,23 +51,81 @@ function Question() {
} }
export default function Features() { export default function Features() {
const [feature, setFeature] = useState(0);
useEffect(() => {
setInterval(() => {
setFeature((feature) => (feature + 1) % 3);
}, 10000);
}, []);
return ( return (
<div className="relative"> <div className="relative w-full mb-52 p-5 lg:p-0">
<div className="w-full lg:w-1/2 p-5 lg:p-0 mx-auto grid mt-52 lg:grid-cols-2 relative lg:border-2 lg:rounded-xl lg:shadow hover:border-blue-500 transition-all duration-200 hover:scale-105">
<div className="flex flex-col lg:p-20 justify-center">
<h1 className="text-3xl font-bold">The only limit is your</h1>
<SparklesText className="!text-3xl" text="Imagination" />
<p className="text-muted-foreground mt-3">
Zen{''}s Compact Mode offers a streamlined browsing experience that maximizes your screen space, perfect for smaller screens.
</p>
<Button className="mt-8" onClick={() => window.location.href = "/download"}>Try it now</Button>
</div>
<div className="relative hidden lg:block flex h-[500px] w-full max-w-lg items-center justify-center overflow-hidden">
<span className="pointer-events-none whitespace-pre-wrap bg-gradient-to-b from-black to-gray-300/80 bg-clip-text text-center text-8xl font-semibold leading-none text-transparent dark:from-white dark:to-slate-900/10">
<Image src="/logos/zen-black.png" width={100} height={100} alt="Zen Logo" />
</span>
{/* Inner Circles */}
<OrbitingCircles
className="size-[30px] border-none bg-transparent"
duration={20}
delay={20}
radius={80}
>
<Image src="/logos/zen-indigo.png" width={30} height={30} alt="Zen Logo" />
</OrbitingCircles>
<OrbitingCircles
className="size-[30px] border-none bg-transparent"
duration={20}
delay={10}
radius={80}
>
<Image src="/logos/zen-yellow.png" width={30} height={30} alt="Zen Logo" />
</OrbitingCircles>
{/* Outer Circles (reverse) */}
<OrbitingCircles
className="size-[50px] border-none bg-transparent"
radius={190}
duration={20}
reverse
>
<Image src="/logos/zen-blue.png" width={50} height={50} alt="Zen Logo" />
</OrbitingCircles>
<OrbitingCircles
className="size-[50px] border-none bg-transparent"
radius={190}
duration={20}
delay={20}
reverse
>
<Image src="/logos/zen-pink.png" width={50} height={50} alt="Zen Logo" />
</OrbitingCircles>
</div>
</div>
{/*<TextReveal text="Zen will change the way you browse the web. 🌟" />*/} {/*<TextReveal text="Zen will change the way you browse the web. 🌟" />*/}
<h1 className="text-5xl font-bold mt-2 text-center p-5 md:p-0 flex flex-col md:flex-row justify-center items-center mb-2">What does Zen offer to <SparklesText className="mx-2" text="YOU" />?</h1> <h1 className="text-5xl font-bold mt-56 text-center p-5 md:p-0 flex flex-col md:flex-row justify-center items-center mb-2">What does Zen offer to <SparklesText className="mx-2" text="YOU" />?</h1>
<p className="text-muted-foreground text-center mx-auto w-3/4 md:w-full p-5 lg:p-0 mb-24"> <p className="text-muted-foreground text-center mx-auto w-3/4 md:w-full p-5 lg:p-0 mb-24">
Discover how Zen Browser can transform your web experience with powerful features that keep you ahead. Discover how Zen Browser can transform your web experience with powerful features that keep you ahead.
Here are<br className="hidden md:block"/> some of the features that Zen offers.</p> Here are<br className="hidden md:block"/> some of the features that Zen offers.</p>
<div className="flex flex-col lg:flex-row w-full mt-4 p-5 lg:p-0"> <div className="w-full lg:w-1/2 mx-auto flex flex-col lg:flex-row w-full mt-4 p-5 lg:p-0">
<div className="w-full flex mx-auto lg:mr-8 flex-col lg:mb-24 lg:ml-4 lg:mt-24"> <div className="w-full flex mx-auto lg:mr-8 flex-col lg:mb-24 lg:ml-4 lg:mt-10">
<div className="hover:border-blue-500 transition-all duration-100 bg-background relative mx-auto lg:mx-0 flex flex-col max-w-lg justify-center rounded-xl md:border-2 p-20 md:shadow-xl"> <div className="hover:border-blue-500 transition-all duration-100 bg-background relative mx-auto lg:mx-0 flex flex-col max-w-lg justify-center rounded-xl md:border-2 lg:p-20 md:shadow-xl hover:scale-105">
<h1 className="text-5xl font-bold">Split views</h1> <h1 className="text-5xl font-bold">Split views</h1>
<p className="text-muted-foreground mt-3"> <p className="text-muted-foreground mt-3">
Multitask effortlessly by splitting your browser into multiple views, so you can browse several sites at once. Multitask effortlessly by splitting your browser into multiple views, so you can browse several sites at once.
</p> </p>
<img src="/split-view.png" className="mt-8 w-full h-full h-auto" /> <img src="/split-view.png" className="mt-8 w-full h-full h-auto" />
</div> </div>
<div className="hover:border-blue-500 transition-all duration-100 bg-background mx-auto lg:mx-0 relative flex flex-col mt-8 max-w-lg justify-center rounded-xl md:border-2 p-20 md:shadow-xl"> <div className="hover:border-blue-500 transition-all duration-100 bg-background mx-auto lg:mx-0 relative flex flex-col mt-8 max-w-lg justify-center rounded-xl md:border-2 lg:p-20 pt-24 lg:pt-0 md:shadow-xl hover:scale-105">
<h1 className="text-5xl font-bold">Workspaces</h1> <h1 className="text-5xl font-bold">Workspaces</h1>
<p className="text-muted-foreground mt-3"> <p className="text-muted-foreground mt-3">
Stay organized and clutter-free by creating workspaces tailored to your browsing needs. Stay organized and clutter-free by creating workspaces tailored to your browsing needs.
@ -80,7 +140,7 @@ export default function Features() {
</div> </div>
</div> </div>
<div className="w-full lg:mr-4 flex flex-col"> <div className="w-full lg:mr-4 flex flex-col">
<div className="hover:border-blue-500 transition-all duration-100 bg-background relative mx-auto lg:mx-0 mt-8 lg:mt-0 flex-col flex max-w-lg justify-center rounded-xl md:border-2 p-20 md:shadow-xl"> <div className="hover:border-blue-500 transition-all duration-100 bg-background relative mx-auto lg:mx-0 mt-8 lg:mt-0 flex-col flex max-w-lg justify-center rounded-xl md:border-2 lg:p-20 pt-24 lg:pt-0 md:shadow-xl hover:scale-105">
<h1 className="text-5xl font-bold">Profile switching</h1> <h1 className="text-5xl font-bold">Profile switching</h1>
<p className="text-muted-foreground mt-3"> <p className="text-muted-foreground mt-3">
Seamlessly switch between work and personal profiles for a focused browsing experience. Seamlessly switch between work and personal profiles for a focused browsing experience.
@ -93,7 +153,7 @@ export default function Features() {
alt="" alt=""
/> />
</div> </div>
<div className="hover:border-blue-500 transition-all duration-100 bg-background relative mx-auto lg:mx-0 mt-8 flex-col flex max-w-lg justify-center rounded-xl md:border-2 p-20 md:shadow-xl"> <div className="hover:border-blue-500 transition-all duration-100 bg-background relative mx-auto lg:mx-0 mt-8 flex-col flex max-w-lg justify-center rounded-xl md:border-2 lg:p-20 pt-24 lg:pt-0 md:shadow-xl hover:scale-105">
<h1 className="text-5xl font-bold">Side web panels</h1> <h1 className="text-5xl font-bold">Side web panels</h1>
<p className="text-muted-foreground mt-3"> <p className="text-muted-foreground mt-3">
Access favorite sites and services instantly, without leaving your current page. Access favorite sites and services instantly, without leaving your current page.
@ -112,9 +172,9 @@ export default function Features() {
borderWidth={2} borderWidth={2}
borderRadius={12} borderRadius={12}
color={["#A07CFE", "#FE8FB5", "#FFBE7B"]} color={["#A07CFE", "#FE8FB5", "#FFBE7B"]}
className="mt-52 flex relative flex-col items-start justify-start w-full bg-background p-12 rounded-lg md:shadow-xl" className="w-full lg:w-1/2 mx-auto mt-52 flex relative flex-col items-start justify-start w-full bg-background lg:p-12 rounded-lg md:shadow-xl"
> >
<div className="w-full p-16"> <div className="w-full lg:p-16">
<Table> <Table>
<TableHeader> <TableHeader>
<TableRow className="!border-none" style={{ pointerEvents: 'none'}}> <TableRow className="!border-none" style={{ pointerEvents: 'none'}}>
@ -216,36 +276,65 @@ export default function Features() {
</Table> </Table>
</div> </div>
</ShineBorder> </ShineBorder>
<div className="flex flex-col items-center justify-center w-full my-48"> <div className="grid grid-cols-1 lg:grid-cols-2 mx-auto justify-center w-full lg:w-2/3 my-80">
<div className="flex flex-col lg:flex-row w-full mt-4 p-5 justify-between items-center"> <div className="relative w-full flex items-center">
<div className="flex flex-col max-w-lg text-center md:text-start"> <div className={ny("flex flex-col lg:flex-row w-full mt-4 p-5 justify-between items-center w-fit transition-all duration-500 absolute", feature === 0 ? "translate-x-0 opacity-100" : "translate-x-[-100%] opacity-0")}>
<h1 className="text-5xl font-bold flex items-center flex-col md:flex-row">Built for <SparklesText className="md:mx-2" text="speed" /></h1> <div className="flex flex-col max-w-lg text-center md:text-start">
<p className="text-muted-foreground mt-3"> <h1 className="text-5xl lg:text-8xl font-bold">Built for</h1>
Zen is engineered for speed, consistently outperforming competitors with every release, ensuring a faster browsing experience. <SparklesText className="!text-5xl lg:!text-8xl" text="speed" />
</p> <p className="text-muted-foreground mt-3">
Zen is engineered for speed, consistently outperforming competitors with every release, ensuring a faster browsing experience.
</p>
<Button className="mt-8 w-fit mx-auto lg:mx-0" onClick={() => window.location.href = "/download"}>Download Zen Browser</Button>
</div>
</div> </div>
<RabbitIcon className="mx-auto hidden md:block w-32 h-32" /> <div className={ny("flex flex-col lg:flex-row w-full mt-4 p-5 justify-between items-center w-fit transition-all duration-500 absolute", feature === 1 ? "translate-x-0 opacity-100" : "translate-x-[-100%] opacity-0")}>
</div> <div className="flex flex-col max-w-lg text-center md:text-start">
<div className="flex flex-col lg:flex-row w-full mt-48 p-5 justify-between items-center"> <h1 className="text-5xl lg:text-8xl font-bold">Privacy is</h1>
<div className="flex flex-col max-w-lg text-center md:text-start"> <SparklesText className="!text-5xl lg:!text-8xl" text="key" />
<h1 className="text-5xl font-bold flex flex-col md:flex-row items-center">Privacy is <SparklesText className="md:mx-2" text="key" /></h1> <p className="text-muted-foreground mt-3">
<p className="text-muted-foreground mt-3"> Zen strikes the perfect balance between privacy and usability, allowing you to browse without compromising your data.
Zen strikes the perfect balance between privacy and usability, allowing you to browse without compromising your data. </p>
</p> <Button className="mt-8 w-fit mx-auto lg:mx-0" onClick={() => window.location.href = "/download"}>Download Zen Browser</Button>
</div>
</div> </div>
<EyeClosedIcon className="mx-auto hidden md:block w-32 h-32" /> <div className={ny("flex flex-col lg:flex-row w-full mt-4 p-5 justify-between items-center w-fit transition-all duration-500 absolute", feature === 2 ? "translate-x-0 opacity-100" : "translate-x-[-100%] opacity-0")}>
</div> <div className="flex flex-col text-center md:text-start max-w-lg">
<div className="flex flex-col lg:flex-row w-full mt-48 p-5 justify-between items-center"> <h1 className="text-5xl lg:text-8xl font-bold">Security is</h1>
<div className="flex flex-col text-center md:text-start max-w-lg"> <SparklesText className="text-5xl lg:!text-8xl" text="important" />
<h1 className="text-5xl font-bold items-center flex-col">Security is <SparklesText className="inline" text="important" /></h1> <p className="text-muted-foreground mt-3">
<p className="text-muted-foreground mt-3"> Zen incorporates advanced security technologies that outshine other Firefox-based browsers, keeping you safe online.
Zen incorporates advanced security technologies that outshine other Firefox-based browsers, keeping you safe online. </p>
</p> <Button className="mt-8 mx-auto lg:mx-0 w-fit" onClick={() => window.location.href = "/download"}>Download Zen Browser</Button>
</div>
</div> </div>
<LockClosedIcon className="mx-auto hidden md:block w-32 h-32" />
</div> </div>
<Image
height={1000}
width={800}
src="/color-preview.png"
className="rounded-xl mt-64 lg:mt-0 lg:ml-52 border-2 border-blue-500 shadow-lg lg:scale-[1.4] hover:scale-105 lg:hover:scale-[1.5] transition-all duration-200"
alt=""
/>
</div> </div>
<div className="my-24 w-full flex items-center justify-center flex-col"> <div className="w-full lg:w-1/2 mx-auto p-5 lg:p-0 mx-auto grid mt-52 lg:grid-cols-2 relative lg:border-2 lg:rounded-xl lg:shadow hover:border-blue-500 transition-all duration-200 hover:scale-105">
<div className="flex flex-col lg:p-20">
<h1 className="text-3xl font-bold">Introducing</h1>
<SparklesText className="!text-3xl" text="Compact Mode" />
<p className="text-muted-foreground mt-3">
Zen{''}s Compact Mode offers a streamlined browsing experience that maximizes your screen space, perfect for smaller screens.
</p>
<Button className="mt-8" onClick={() => window.location.href = "/download"}>Try it now</Button>
</div>
<Image
height={500}
width={300}
src="/compact-mode.png"
className="hidden lg:block absolute right-0 bottom-0 rounded-tl-lg border-t-2 border-l-2"
alt=""
/>
</div>
<div className="mt-48 w-full flex items-center justify-center flex-col">
<h1 className="text-5xl text-center font-bold w-1/2">Want more?</h1> <h1 className="text-5xl text-center font-bold w-1/2">Want more?</h1>
<p className="text-muted-foreground text-center mt-3 w-1/2"> <p className="text-muted-foreground text-center mt-3 w-1/2">
Zen Browser is packed with features designed to revolutionize your browsing. Zen Browser is packed with features designed to revolutionize your browsing.

View file

@ -52,7 +52,7 @@ export default function Header() {
</Link> </Link>
<div <div
ref={ref} ref={ref}
className="animate-fade-up relative mt-32 opacity-0 [--animation-delay:400ms] [perspective:2000px] after:absolute after:inset-0 after:z-50 after:[background:linear-gradient(to_top,hsl(var(--background))_30%,transparent)]" className="animate-fade-up relative mt-32 opacity-0 [--animation-delay:400ms] [perspective:2000px] after:absolute after:inset-0 after:z-50 after:[background:linear-gradient(to_top,hsl(var(--background))_10%,transparent)]"
> >
<div <div
className={`rounded-xl border border-white/10 bg-white bg-opacity-[0.01] before:absolute before:bottom-1/2 before:left-0 before:top-0 before:size-full before:opacity-0 before:[background-image:linear-gradient(to_bottom,var(--color-one),var(--color-one),transparent_40%)] before:[filter:blur(180px)] ${ className={`rounded-xl border border-white/10 bg-white bg-opacity-[0.01] before:absolute before:bottom-1/2 before:left-0 before:top-0 before:size-full before:opacity-0 before:[background-image:linear-gradient(to_bottom,var(--color-one),var(--color-one),transparent_40%)] before:[filter:blur(180px)] ${
@ -68,15 +68,15 @@ export default function Header() {
/> />
<Image <Image
width={1600} width={1500}
height={800} height={700}
src="/browser-dark.png" src="/browser-dark.png"
alt="browser Image" alt="browser Image"
className="relative hidden rounded-[inherit] border object-contain dark:block" className="relative hidden rounded-[inherit] border object-contain dark:block"
/> />
<Image <Image
width={1600} width={1500}
height={800} height={700}
src="/browser-light.png" src="/browser-light.png"
alt="browser Image" alt="browser Image"
className="relative block rounded-[inherit] border object-contain dark:hidden" className="relative block rounded-[inherit] border object-contain dark:hidden"

View file

@ -1,9 +1,24 @@
"use client";
import { ny } from "@/lib/utils";
import Image from "next/image"; import Image from "next/image";
import React from "react";
export const LOGO_COLORS = [
"black", "blue", "brown", "buff", "indigo", "mantis", "orchid", "pink", "tangerine", "turquise", "white", "yellow"
]
export default function Logo({ withText, ...props }: any) { export default function Logo({ withText, ...props }: any) {
const [randomColor, setRandomColor] = React.useState(LOGO_COLORS[Math.floor(Math.random() * LOGO_COLORS.length)]);
React.useEffect(() => {
const interval = setInterval(() => {
setRandomColor(LOGO_COLORS[Math.floor(Math.random() * LOGO_COLORS.length)]);
}, 2000);
return () => clearInterval(interval);
}, []);
return ( return (
<div className="flex items-center m-0" {...props}> <div className="flex items-center m-0" {...props}>
<Image src="/logo.png" alt="Zen Logo" width={50} height={50} /> <Image src={`/logos/zen-${randomColor}.png`} width={40} height={40} alt="Zen Logo" className={ny("transition-all duration-300 hover:scale-110", withText && "mr-2")} />
{withText && <span className="text-2xl font-bold ml-2">Zen</span>} {withText && <span className="text-2xl font-bold ml-2">zen</span>}
</div> </div>
); );
} }

View file

@ -18,13 +18,16 @@ export function MobileNav() {
return ( return (
<Sheet open={open} onOpenChange={setOpen}> <Sheet open={open} onOpenChange={setOpen}>
<SheetTrigger asChild> <SheetTrigger asChild>
<Button <>
variant="ghost" <Logo className="size-6 sm:hidden" />
className="mr-2 px-0 ml-auto text-base hover:bg-transparent focus-visible:bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 sm:hidden" <Button
> variant="ghost"
<SidebarOpen className="size-6" /> className="mr-2 px-0 ml-auto text-base hover:bg-transparent focus-visible:bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 sm:hidden"
<span className="sr-only">Toggle Menu</span> >
</Button> <SidebarOpen className="size-6" />
<span className="sr-only">Toggle Menu</span>
</Button>
</>
</SheetTrigger> </SheetTrigger>
<SheetContent side="left" className="pr-0"> <SheetContent side="left" className="pr-0">
<MobileLink <MobileLink

View file

@ -41,7 +41,7 @@ export function Navigation() {
<div className="bg-background z-40 top-0 left-0 w-full flex fixed border-b border-grey p-2 items-center justify-center"> <div className="bg-background z-40 top-0 left-0 w-full flex fixed border-b border-grey p-2 items-center justify-center">
<MobileNav /> <MobileNav />
<NavigationMenu> <NavigationMenu>
<NavigationMenuList className="w-full hidden sm:flex"> <NavigationMenuList className="w-full hidden py-3 sm:flex">
<NavigationMenuItem className="cursor-pointer mr-20"> <NavigationMenuItem className="cursor-pointer mr-20">
<NavigationMenuLink href="/"> <NavigationMenuLink href="/">
<Logo withText /> <Logo withText />

View file

@ -0,0 +1,57 @@
import { ny } from '@/lib/utils'
export default function OrbitingCircles({
className,
children,
reverse,
duration = 20,
delay = 10,
radius = 50,
path = true,
}: {
className?: string
children?: React.ReactNode
reverse?: boolean
duration?: number
delay?: number
radius?: number
path?: boolean
}) {
return (
<>
{path && (
<svg
xmlns="http://www.w3.org/2000/svg"
version="1.1"
className="pointer-events-none absolute inset-0 size-full"
>
<circle
className="stroke-black/10 stroke-1 dark:stroke-white/10"
cx="50%"
cy="50%"
r={radius}
fill="none"
strokeDasharray="4 4"
/>
</svg>
)}
<div
style={
{
'--duration': duration,
'--radius': radius,
'--delay': -delay,
} as React.CSSProperties
}
className={ny(
'animate-orbit absolute flex size-full transform-gpu items-center justify-center rounded-full border bg-black/10 [animation-delay:calc(var(--delay)*1000ms)] dark:bg-white/10',
{ '[animation-direction:reverse]': reverse },
className,
)}
>
{children}
</div>
</>
)
}

View file

@ -63,6 +63,14 @@ const config = {
sm: 'calc(var(--radius) - 4px)', sm: 'calc(var(--radius) - 4px)',
}, },
keyframes: { keyframes: {
orbit: {
"0%": {
transform: "rotate(0deg) translateY(calc(var(--radius) * 1px)) rotate(0deg)",
},
"100%": {
transform: "rotate(360deg) translateY(calc(var(--radius) * 1px)) rotate(-360deg)",
},
},
"shine-pulse": { "shine-pulse": {
"0%": { "0%": {
"background-position": "0% 0%", "background-position": "0% 0%",
@ -126,6 +134,7 @@ const config = {
}, },
}, },
animation: { animation: {
orbit: "orbit calc(var(--duration)*1s) linear infinite",
'accordion-down': 'accordion-down 0.2s ease-out', 'accordion-down': 'accordion-down 0.2s ease-out',
'accordion-up': 'accordion-up 0.2s ease-out', 'accordion-up': 'accordion-up 0.2s ease-out',
'border-beam': 'border-beam calc(var(--duration)*1s) infinite linear', 'border-beam': 'border-beam calc(var(--duration)*1s) infinite linear',