mirror of
https://github.com/zen-browser/www.git
synced 2025-07-08 09:20:00 +02:00
feat: Add @radix-ui/react-tabs npm dependency and update header.tsx to include a download link
This commit is contained in:
parent
acebd412e7
commit
80fa3d1842
7 changed files with 230 additions and 3 deletions
60
package-lock.json
generated
60
package-lock.json
generated
|
@ -10,6 +10,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-icons": "^1.3.0",
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/react-navigation-menu": "^1.2.0",
|
"@radix-ui/react-navigation-menu": "^1.2.0",
|
||||||
|
"@radix-ui/react-tabs": "^1.1.0",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cobe": "^0.6.3",
|
"cobe": "^0.6.3",
|
||||||
|
@ -2966,6 +2967,36 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-roving-focus": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/primitive": "1.1.0",
|
||||||
|
"@radix-ui/react-collection": "1.1.0",
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.0",
|
||||||
|
"@radix-ui/react-context": "1.1.0",
|
||||||
|
"@radix-ui/react-direction": "1.1.0",
|
||||||
|
"@radix-ui/react-id": "1.1.0",
|
||||||
|
"@radix-ui/react-primitive": "2.0.0",
|
||||||
|
"@radix-ui/react-use-callback-ref": "1.1.0",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-slot": {
|
"node_modules/@radix-ui/react-slot": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
|
||||||
|
@ -2983,6 +3014,35 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-tabs": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-bZgOKB/LtZIij75FSuPzyEti/XBhJH52ExgtdVqjCIh+Nx/FW+LhnbXtbCzIi34ccyMsyOja8T0thCzoHFXNKA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/primitive": "1.1.0",
|
||||||
|
"@radix-ui/react-context": "1.1.0",
|
||||||
|
"@radix-ui/react-direction": "1.1.0",
|
||||||
|
"@radix-ui/react-id": "1.1.0",
|
||||||
|
"@radix-ui/react-presence": "1.1.0",
|
||||||
|
"@radix-ui/react-primitive": "2.0.0",
|
||||||
|
"@radix-ui/react-roving-focus": "1.1.0",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-use-callback-ref": {
|
"node_modules/@radix-ui/react-use-callback-ref": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz",
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-icons": "^1.3.0",
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/react-navigation-menu": "^1.2.0",
|
"@radix-ui/react-navigation-menu": "^1.2.0",
|
||||||
|
"@radix-ui/react-tabs": "^1.1.0",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cobe": "^0.6.3",
|
"cobe": "^0.6.3",
|
||||||
|
|
14
src/app/download/page.tsx
Normal file
14
src/app/download/page.tsx
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
import DownloadPage from "@/components/download";
|
||||||
|
import Footer from "@/components/footer";
|
||||||
|
import { Navigation } from "@/components/navigation";
|
||||||
|
|
||||||
|
export default function Download() {
|
||||||
|
return (
|
||||||
|
<main className="flex min-h-screen flex-col items-center justify-start">
|
||||||
|
<DownloadPage />
|
||||||
|
<Footer />
|
||||||
|
<Navigation /> {/* At the bottom of the page */}
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
95
src/components/download.tsx
Normal file
95
src/components/download.tsx
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { ny } from "@/lib/utils";
|
||||||
|
import GridPattern from "./ui/grid-pattern";
|
||||||
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./ui/tabs";
|
||||||
|
import { DownloadCloudIcon, DownloadIcon } from "lucide-react";
|
||||||
|
|
||||||
|
const BASE_URL = "https://github.com/zen-browser/desktop/releases/download/latest";
|
||||||
|
|
||||||
|
const releases: any = {
|
||||||
|
Windows: [
|
||||||
|
"zen.win64.zip",
|
||||||
|
],
|
||||||
|
//MacOS: [],
|
||||||
|
Linux: [
|
||||||
|
"zen.linux.tar.bz2",
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
function getDefaultPlatformBasedOnUserAgent() {
|
||||||
|
const userAgent = navigator.userAgent;
|
||||||
|
if (userAgent.includes("Win")) {
|
||||||
|
return "Windows";
|
||||||
|
}
|
||||||
|
if (userAgent.includes("Mac")) {
|
||||||
|
return "MacOS";
|
||||||
|
}
|
||||||
|
if (userAgent.includes("Linux")) {
|
||||||
|
return "Linux";
|
||||||
|
}
|
||||||
|
return "Windows";
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function DownloadPage() {
|
||||||
|
return (
|
||||||
|
<div className="w-full relative h-screen flex items-center justify-center">
|
||||||
|
<div className="w-1/2 relative h-full px-64 flex items-cetner justify-center flex-col">
|
||||||
|
<GridPattern
|
||||||
|
numSquares={30}
|
||||||
|
maxOpacity={0.5}
|
||||||
|
height={50}
|
||||||
|
width={50}
|
||||||
|
duration={3}
|
||||||
|
repeatDelay={1}
|
||||||
|
x={-1}
|
||||||
|
y={-1}
|
||||||
|
strokeDasharray="4 2"
|
||||||
|
className={ny(
|
||||||
|
'[mask-image:radial-gradient(350px_circle_at_center,white,transparent)]',
|
||||||
|
'w-full z-0',
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<h1 className="!text-4xl font-bold tracking-[-0.02em] text-black dark:text-white md:text-7xl md:leading-[5rem]">
|
||||||
|
Download Zen Browser
|
||||||
|
</h1>
|
||||||
|
<p className="!text-md text-muted-foreground !font-medium">
|
||||||
|
Get started with Zen Browser today. Get back to browsing the web with peace of mind.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/2 relative flex items-cetner justify-start">
|
||||||
|
<Tabs defaultValue={getDefaultPlatformBasedOnUserAgent()} className="mx-auto w-fit flex flex-col items-start justify-center">
|
||||||
|
<TabsList>
|
||||||
|
{Object.keys(releases).map((platform) => (
|
||||||
|
<TabsTrigger key={platform} value={platform}>{platform}</TabsTrigger>
|
||||||
|
))}
|
||||||
|
</TabsList>
|
||||||
|
{Object.keys(releases).map((platform) => (
|
||||||
|
<TabsContent key={platform} value={platform} className="border rounded-md p-5 border-gray">
|
||||||
|
<table>
|
||||||
|
<thead className="">
|
||||||
|
<tr>
|
||||||
|
<th className="text-start pb-4 min-w-64">File</th>
|
||||||
|
<th className="text-start pb-4">Download</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{releases[platform].map((release: string) => (
|
||||||
|
<tr key={release} className="relative w-full">
|
||||||
|
<td className="min-w-64">{release}</td>
|
||||||
|
<td className="flex items-center w-full justify-center">
|
||||||
|
<a href={`${BASE_URL}/${release}`} className="text-blue-500">
|
||||||
|
<DownloadIcon size={24} />
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</TabsContent>
|
||||||
|
))}
|
||||||
|
</Tabs>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -26,7 +26,8 @@ export default function Header() {
|
||||||
'w-full z-0',
|
'w-full z-0',
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<div className="z-10 flex mb-10 items-center justify-center">
|
<div className="z-10 flex mb-10 items-center justify-center">
|
||||||
|
<a href="/download">
|
||||||
<AnimatedGradientText>
|
<AnimatedGradientText>
|
||||||
🎉
|
🎉
|
||||||
{' '}
|
{' '}
|
||||||
|
@ -41,6 +42,7 @@ export default function Header() {
|
||||||
</span>
|
</span>
|
||||||
<ChevronRight className="ml-1 size-3 transition-transform duration-300 ease-in-out group-hover:translate-x-0.5" />
|
<ChevronRight className="ml-1 size-3 transition-transform duration-300 ease-in-out group-hover:translate-x-0.5" />
|
||||||
</AnimatedGradientText>
|
</AnimatedGradientText>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<WordPullUp
|
<WordPullUp
|
||||||
className="text-3xl font-bold tracking-[-0.02em] text-black dark:text-white md:text-7xl md:leading-[5rem]"
|
className="text-3xl font-bold tracking-[-0.02em] text-black dark:text-white md:text-7xl md:leading-[5rem]"
|
||||||
|
@ -58,7 +60,7 @@ export default function Header() {
|
||||||
framerProps={{
|
framerProps={{
|
||||||
show: { transition: { delay: 0.2 } },
|
show: { transition: { delay: 0.2 } },
|
||||||
}}
|
}}
|
||||||
text="Fade Up"
|
text="Documentation"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<ShinyButton text="Download now" />
|
<ShinyButton text="Download now" />
|
||||||
|
|
|
@ -30,7 +30,7 @@ const components: { title: string; href: string; description: string }[] = [
|
||||||
|
|
||||||
export function Navigation() {
|
export function Navigation() {
|
||||||
return (
|
return (
|
||||||
<div className="absolute z-10 top-0 left-0 w-full flex fixed border-b border-grey p-2 items-center justify-center">
|
<div className="backdrop-blur fixed z-10 top-0 left-0 w-full flex fixed border-b border-grey p-2 items-center justify-center">
|
||||||
<NavigationMenu>
|
<NavigationMenu>
|
||||||
<NavigationMenuList>
|
<NavigationMenuList>
|
||||||
<NavigationMenuItem>
|
<NavigationMenuItem>
|
||||||
|
|
55
src/components/ui/tabs.tsx
Normal file
55
src/components/ui/tabs.tsx
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import * as React from 'react'
|
||||||
|
import * as TabsPrimitive from '@radix-ui/react-tabs'
|
||||||
|
|
||||||
|
import { ny } from '@/lib/utils'
|
||||||
|
|
||||||
|
const Tabs = TabsPrimitive.Root
|
||||||
|
|
||||||
|
const TabsList = React.forwardRef<
|
||||||
|
React.ElementRef<typeof TabsPrimitive.List>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<TabsPrimitive.List
|
||||||
|
ref={ref}
|
||||||
|
className={ny(
|
||||||
|
'inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TabsList.displayName = TabsPrimitive.List.displayName
|
||||||
|
|
||||||
|
const TabsTrigger = React.forwardRef<
|
||||||
|
React.ElementRef<typeof TabsPrimitive.Trigger>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<TabsPrimitive.Trigger
|
||||||
|
ref={ref}
|
||||||
|
className={ny(
|
||||||
|
'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
|
||||||
|
|
||||||
|
const TabsContent = React.forwardRef<
|
||||||
|
React.ElementRef<typeof TabsPrimitive.Content>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<TabsPrimitive.Content
|
||||||
|
ref={ref}
|
||||||
|
className={ny(
|
||||||
|
'mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TabsContent.displayName = TabsPrimitive.Content.displayName
|
||||||
|
|
||||||
|
export { Tabs, TabsList, TabsTrigger, TabsContent }
|
Loading…
Add table
Add a link
Reference in a new issue