Merge branch 'main' into themecard_size_limit
This commit is contained in:
@@ -10,6 +10,6 @@ Zen Browser Website
|
|||||||
|
|
||||||
This repository contains the source code for the Zen Browser Website. We are thrilled to welcome you to our community. Before you start, please read this document to understand how you can contribute to this project.
|
This repository contains the source code for the Zen Browser Website. We are thrilled to welcome you to our community. Before you start, please read this document to understand how you can contribute to this project.
|
||||||
|
|
||||||
It's built with [Next.js](https://nextjs.org/), [TypeScript](https://www.typescriptlang.org/), and [Tailwind CSS](https://tailwindcss.com/).
|
Zen Browser's website is built with [Next.js](https://nextjs.org/), [TypeScript](https://www.typescriptlang.org/), and [Tailwind CSS](https://tailwindcss.com/).
|
||||||
|
|
||||||
If you are interested in contributing to this project, please read the [Contributing Guidelines](./CONTRIBUTING.md).
|
If you are interested in contributing to this project, please read the [Contributing Guidelines](./CONTRIBUTING.md).
|
||||||
|
|||||||
7601
package-lock.json
generated
7601
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,7 @@
|
|||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cobe": "^0.6.3",
|
"cobe": "^0.6.3",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
|
"feed": "^4.2.2",
|
||||||
"framer-motion": "^11.3.24",
|
"framer-motion": "^11.3.24",
|
||||||
"lucide-react": "^0.400.0",
|
"lucide-react": "^0.400.0",
|
||||||
"next": "14.2.4",
|
"next": "14.2.4",
|
||||||
|
|||||||
110
src/app/feed.xml/route.ts
Normal file
110
src/app/feed.xml/route.ts
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
import { Feed } from "feed";
|
||||||
|
import { releaseNotes } from "@/lib/release-notes";
|
||||||
|
import type { ReleaseNote } from "@/lib/release-notes";
|
||||||
|
|
||||||
|
// Force feed.xml to be cached as static and remain constant for the lifetime of the current site build.
|
||||||
|
// The supplied releaseNotes array is constant per build, so this will always be the latest release notes.
|
||||||
|
export const dynamic = "force-static";
|
||||||
|
|
||||||
|
/** The default number of entries to include in the RSS feed. */
|
||||||
|
const RSS_ENTRY_LIMIT = 20;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the GET request for the `feed.xml` endpoint.
|
||||||
|
* @returns The RSS feed for the Zen Browser release notes.
|
||||||
|
*/
|
||||||
|
export async function GET() {
|
||||||
|
// Just in case the release notes array is empty for whatever reason.
|
||||||
|
const latestDate = releaseNotes.length > 0
|
||||||
|
? formatRssDate(releaseNotes[0].date)
|
||||||
|
: new Date();
|
||||||
|
|
||||||
|
const feed = new Feed({
|
||||||
|
id: "https://www.zen-browser.app/release-notes",
|
||||||
|
link: "https://www.zen-browser.app/release-notes",
|
||||||
|
title: "Zen Browser Release Notes",
|
||||||
|
description: "Release Notes for the Zen Browser",
|
||||||
|
language: "en",
|
||||||
|
favicon: "https://www.zen-browser.app/favicon.ico",
|
||||||
|
copyright: `Zen Browser © ${new Date().getFullYear()} - Made with ❤️ by the Zen team.`,
|
||||||
|
updated: latestDate,
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const releaseNote of releaseNotes.slice(0, RSS_ENTRY_LIMIT)) {
|
||||||
|
feed.addItem({
|
||||||
|
title: `Release notes for version ${releaseNote.version}`,
|
||||||
|
id: `https://www.zen-browser.app/release-notes/${releaseNote.version}`,
|
||||||
|
link: `https://www.zen-browser.app/release-notes/${releaseNote.version}`,
|
||||||
|
date: formatRssDate(releaseNote.date),
|
||||||
|
description: releaseNote.extra,
|
||||||
|
content: formatReleaseNote(releaseNote),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(feed.rss2(), {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/xml; charset=utf-8',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a date string in the format day/month/year.
|
||||||
|
*
|
||||||
|
* Note: If release notes change to ISO format, this will need to be updated.
|
||||||
|
* @param dateStr The date string to format.
|
||||||
|
* @returns The passed in date string as a Date object.
|
||||||
|
*/
|
||||||
|
function formatRssDate(dateStr: string) {
|
||||||
|
const splitDate = dateStr.split("/");
|
||||||
|
if (splitDate.length !== 3) {
|
||||||
|
throw new Error("Invalid date format");
|
||||||
|
}
|
||||||
|
|
||||||
|
const day = Number(splitDate[0]);
|
||||||
|
const month = Number(splitDate[1]) - 1;
|
||||||
|
const year = Number(splitDate[2]);
|
||||||
|
return new Date(year, month, day);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the release note entry for use as the content of the RSS feed.
|
||||||
|
* @param releaseNote The release note to format.
|
||||||
|
* @returns The formatted release note as a HTML string.
|
||||||
|
*/
|
||||||
|
function formatReleaseNote(releaseNote: ReleaseNote) {
|
||||||
|
let content = "<p>If you encounter any issues, please report them on <a href=\"https://github.com/zen-browser/desktop/issues/\">the issues page</a>. Thanks everyone for your feedback! ❤️</p>";
|
||||||
|
|
||||||
|
if (releaseNote.extra) {
|
||||||
|
content += `<p>${releaseNote.extra.replace(/(\n)/g, "<br />")}</p>`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (releaseNote.breakingChanges) {
|
||||||
|
content += `<h2>⚠️ Breaking changes</h2>`
|
||||||
|
content += `<ul>`
|
||||||
|
for (const breakingChange of releaseNote.breakingChanges) {
|
||||||
|
content += `<li>${breakingChange}</li>`
|
||||||
|
}
|
||||||
|
content += `</ul>`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (releaseNote.features) {
|
||||||
|
content += `<h2>⭐ Features</h2>`
|
||||||
|
content += `<ul>`
|
||||||
|
for (const feature of releaseNote.features) {
|
||||||
|
content += `<li>${feature}</li>`
|
||||||
|
}
|
||||||
|
content += `</ul>`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (releaseNote.fixes) {
|
||||||
|
content += `<h2>✓ Fixes</h2>`
|
||||||
|
content += `<ul>`
|
||||||
|
for (const fix of releaseNote.fixes) {
|
||||||
|
content += `<li>${fix.description}</li>`
|
||||||
|
}
|
||||||
|
content += `</ul>`
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ export default function RootLayout({
|
|||||||
<html lang="en" suppressHydrationWarning>
|
<html lang="en" suppressHydrationWarning>
|
||||||
<head>
|
<head>
|
||||||
<link rel="me" href="https://fosstodon.org/@zenbrowser"></link>
|
<link rel="me" href="https://fosstodon.org/@zenbrowser"></link>
|
||||||
|
<link rel="alternate" type="application/rss+xml" title="Zen Browser Release Notes" href="https://www.zen-browser.app/feed.xml" />
|
||||||
</head>
|
</head>
|
||||||
<body className={inter.className}>
|
<body className={inter.className}>
|
||||||
<ThemeProvider
|
<ThemeProvider
|
||||||
|
|||||||
@@ -382,7 +382,7 @@ export default function DownloadPage() {
|
|||||||
<h1 className="text-5xl my-2 opacity-40 dark:opacity-20">
|
<h1 className="text-5xl my-2 opacity-40 dark:opacity-20">
|
||||||
🍏
|
🍏
|
||||||
</h1>
|
</h1>
|
||||||
<h1 className="text-2xl font-semibold my-2">aarch64</h1>
|
<h1 className="text-2xl font-semibold my-2">AArch64</h1>
|
||||||
<p className="text-muted-foreground mx-auto text-center">64-bit ARM architecture, for Apple's M Series Chips</p>
|
<p className="text-muted-foreground mx-auto text-center">64-bit ARM architecture, for Apple's M Series Chips</p>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"use client";
|
'use client';
|
||||||
import Sticky from 'react-sticky-el';
|
import Sticky from 'react-sticky-el';
|
||||||
import {
|
import {
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
SplitSquareHorizontal,
|
SplitSquareHorizontal,
|
||||||
SplitSquareVertical,
|
SplitSquareVertical,
|
||||||
XIcon,
|
XIcon,
|
||||||
} from "lucide-react";
|
} from 'lucide-react';
|
||||||
import {
|
import {
|
||||||
Cross1Icon,
|
Cross1Icon,
|
||||||
EyeClosedIcon,
|
EyeClosedIcon,
|
||||||
@@ -26,13 +26,20 @@ import {
|
|||||||
QuestionMarkIcon,
|
QuestionMarkIcon,
|
||||||
ReloadIcon,
|
ReloadIcon,
|
||||||
UpdateIcon,
|
UpdateIcon,
|
||||||
} from "@radix-ui/react-icons";
|
} from '@radix-ui/react-icons';
|
||||||
import Image from "next/image";
|
import Image from 'next/image';
|
||||||
import Link from "next/link";
|
import Link from 'next/link';
|
||||||
import { Button } from './ui/button';
|
import { Button } from './ui/button';
|
||||||
import { COLORS } from './create-theme';
|
import { COLORS } from './create-theme';
|
||||||
import { Slider } from './ui/slider';
|
import { Slider } from './ui/slider';
|
||||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from './ui/table';
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from './ui/table';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { ny } from '@/lib/utils';
|
import { ny } from '@/lib/utils';
|
||||||
|
|
||||||
@@ -63,7 +70,7 @@ export default function Features() {
|
|||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<div className="relative my-32 mx-auto md:border-2 rounded-md md:w-full xl:w-4/5 2xl:w-3/5">
|
<div className="max-w-[1300px] relative my-32 mx-auto md:border-2 rounded-md md:w-full xl:w-4/5 2xl:w-3/5">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 md:grid-rows-10 w-full">
|
<div className="grid grid-cols-1 md:grid-cols-3 md:grid-rows-10 w-full">
|
||||||
<div className="items-center justify-center flex flex-col p-16">
|
<div className="items-center justify-center flex flex-col p-16">
|
||||||
<div className="rounded-full px-8 py-3 shadow border-2 flex items-center justify-center">
|
<div className="rounded-full px-8 py-3 shadow border-2 flex items-center justify-center">
|
||||||
@@ -74,8 +81,15 @@ export default function Features() {
|
|||||||
Goodbye bad performance
|
Goodbye bad performance
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-center text-sm mt-2 text-muted-foreground">
|
<p className="text-center text-sm mt-2 text-muted-foreground">
|
||||||
We constantly tweak Firefox's engine and settings to make it
|
We are constantly tweak firefox's engine and settings to make it
|
||||||
faster than ever. <a className="text-blue-500" href="https://github.com/zen-browser/desktop/blob/main/docs/performance.md" target='_blank'>Learn more</a>
|
faster than ever.{' '}
|
||||||
|
<a
|
||||||
|
className="text-blue-500"
|
||||||
|
href="https://docs.zen-browser.app/benchmarks"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
Learn more
|
||||||
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -84,12 +98,13 @@ export default function Features() {
|
|||||||
<LockClosedIcon className="mx-auto w-7 h-7" />
|
<LockClosedIcon className="mx-auto w-7 h-7" />
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-10">
|
<div className="mt-10">
|
||||||
<h2 className="text-lg font-bold text-center">
|
<h2 className="text-lg font-bold text-center">Privacy first</h2>
|
||||||
Privacy first
|
|
||||||
</h2>
|
|
||||||
<p className="text-center text-sm mt-2 text-muted-foreground">
|
<p className="text-center text-sm mt-2 text-muted-foreground">
|
||||||
We don't track you. We don't sell your data. We don't even know
|
We don't track you. We don't sell your data. We don't even know
|
||||||
who you are. <a className="text-blue-500" href="/privacy-policy">Learn more</a>
|
who you are.{' '}
|
||||||
|
<a className="text-blue-500" href="/privacy-policy">
|
||||||
|
Learn more
|
||||||
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -98,22 +113,30 @@ export default function Features() {
|
|||||||
<ShieldCheck className="mx-auto w-7 h-7" />
|
<ShieldCheck className="mx-auto w-7 h-7" />
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-10">
|
<div className="mt-10">
|
||||||
<h2 className="text-lg font-bold text-center">
|
<h2 className="text-lg font-bold text-center">Secure by default</h2>
|
||||||
Secure by default
|
|
||||||
</h2>
|
|
||||||
<p className="text-center text-sm mt-2 text-muted-foreground">
|
<p className="text-center text-sm mt-2 text-muted-foreground">
|
||||||
We are always using the latest security features from Firefox to
|
We are always using the latest security features from Firefox to
|
||||||
keep you safe. <a className="text-blue-500" href="https://docs.zen-browser.app/faq#how-do-i-know-zen-is-safe">Learn more</a>
|
keep you safe.{' '}
|
||||||
|
<a
|
||||||
|
className="text-blue-500"
|
||||||
|
href="https://docs.zen-browser.app/faq#how-do-i-know-zen-is-safe"
|
||||||
|
>
|
||||||
|
Learn more
|
||||||
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative md:border-t-2 hidden md:block flex-col p-16 row-span-4 scrollarea">
|
<div className="relative md:border-t-2 hidden md:block flex-col p-16 row-span-4 scrollarea">
|
||||||
<Sticky stickyClassName="mx-auto py-32" hideOnBoundaryHit={false} boundaryElement=".scrollarea" topOffset={-130}>
|
<Sticky
|
||||||
<h2 className="text-3xl font-bold">
|
stickyClassName="mx-auto py-32"
|
||||||
User experience comes first
|
hideOnBoundaryHit={false}
|
||||||
</h2>
|
boundaryElement=".scrollarea"
|
||||||
|
topOffset={-130}
|
||||||
|
>
|
||||||
|
<h2 className="text-3xl font-bold">User experience comes first</h2>
|
||||||
<p className="text-sm mt-2 text-muted-foreground">
|
<p className="text-sm mt-2 text-muted-foreground">
|
||||||
We are always looking for ways to make your experience better. Always looking for feedback and suggestions!
|
We are always looking for ways to make your experience better.
|
||||||
|
Always looking for feedback and suggestions!
|
||||||
</p>
|
</p>
|
||||||
</Sticky>
|
</Sticky>
|
||||||
</div>
|
</div>
|
||||||
@@ -121,27 +144,42 @@ export default function Features() {
|
|||||||
<div className="p-16 md:px-32 h-full md:absolute top-0 left-0 flex flex-col">
|
<div className="p-16 md:px-32 h-full md:absolute top-0 left-0 flex flex-col">
|
||||||
<div className="">
|
<div className="">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-3xl font-bold">
|
<h2 className="text-3xl font-bold">Customization is key</h2>
|
||||||
Customization is key
|
|
||||||
</h2>
|
|
||||||
<p className="text-sm mt-2 text-muted-foreground">
|
<p className="text-sm mt-2 text-muted-foreground">
|
||||||
We are always looking for ways to make your experience better. With stackable themes that can be mixed and matched, you can create a browser that is truly yours. <a className="text-blue-500" href="https://docs.zen-browser.app/themes-store/themes-marketplace">Learn more</a>
|
We are always looking for ways to make your experience better.
|
||||||
|
With stackable themes that can be mixed and matched, you can
|
||||||
|
create a browser that is truly yours.{' '}
|
||||||
|
<a
|
||||||
|
className="text-blue-500"
|
||||||
|
href="https://docs.zen-browser.app/themes-store/themes-marketplace"
|
||||||
|
>
|
||||||
|
Learn more
|
||||||
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Link href="/download"><Button className="mt-4 rounded-full p-5 ml-auto">Download Zen now!</Button></Link>
|
<Link href="/download">
|
||||||
|
<Button className="mt-4 rounded-full p-5 ml-auto">
|
||||||
|
Download Zen now!
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="border rounded-lg shadow-md mt-16 mx-auto p-4 bg-white dark:bg-black flex w-fit transform -translate-x-1/3">
|
<div className="border rounded-lg shadow-md mt-16 mx-auto p-4 bg-white dark:bg-black flex w-fit transform -translate-x-1/3">
|
||||||
{COLORS.map((color) => (
|
{COLORS.map((color) => (
|
||||||
<div key={color} className="w-5 h-5 rounded-full mx-3 " style={{ backgroundColor: color }} />
|
<div
|
||||||
|
key={color}
|
||||||
|
className="w-5 h-5 rounded-full mx-3 "
|
||||||
|
style={{ backgroundColor: color }}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="border w-1/2 rounded-lg shadow-md mt-16 mx-auto p-4 bg-white dark:bg-black flex transform translate-x-[calc(50%-1.5rem)]">
|
<div className="border w-1/2 rounded-lg shadow-md mt-16 mx-auto p-4 bg-white dark:bg-black flex transform translate-x-[calc(50%-1.5rem)]">
|
||||||
<Slider defaultValue={[80]} max={100} />
|
<Slider defaultValue={[80]} max={100} />
|
||||||
</div>
|
</div>
|
||||||
<a href='/themes' className="border-2 w-fit md:w-1/2 lg:w-fit flex items-center justify-center rounded-xl shadow-md mt-16 mx-auto p-4 bg-white dark:bg-black border-blue-500 flex text-muted-foreground">
|
<a
|
||||||
<span>
|
href="/themes"
|
||||||
Checkout our themes store
|
className="border-2 w-fit md:w-1/2 lg:w-fit flex items-center justify-center rounded-xl shadow-md mt-16 mx-auto p-4 bg-white dark:bg-black border-blue-500 flex text-muted-foreground"
|
||||||
</span>
|
>
|
||||||
|
<span>Checkout our themes store</span>
|
||||||
<ChevronRight className="w-5 h-5 ml-2" />
|
<ChevronRight className="w-5 h-5 ml-2" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -149,23 +187,29 @@ export default function Features() {
|
|||||||
<div className="relative md:grid md:border-l-2 border-t-2 md:col-span-2 grid-cols-2 row-span-2">
|
<div className="relative md:grid md:border-l-2 border-t-2 md:col-span-2 grid-cols-2 row-span-2">
|
||||||
<div className="p-16 md:px-32 h-full md:absolute top-0 left-0 flex flex-col">
|
<div className="p-16 md:px-32 h-full md:absolute top-0 left-0 flex flex-col">
|
||||||
<div className="flex flex-col md:flex-row">
|
<div className="flex flex-col md:flex-row">
|
||||||
<div className='relative'>
|
<div className="relative">
|
||||||
<h2 className="text-3xl font-bold">
|
<h2 className="text-3xl font-bold">Compact mode is here!</h2>
|
||||||
Compact mode is here!
|
|
||||||
</h2>
|
|
||||||
<p className="text-sm mt-2 text-muted-foreground">
|
<p className="text-sm mt-2 text-muted-foreground">
|
||||||
With a new compact mode, you can save space and focus on what matters.
|
With a new compact mode, you can save space and focus on what
|
||||||
|
matters.
|
||||||
</p>
|
</p>
|
||||||
<div className="bg-blue-600 p-1 px-2 text-white rounded-md text-xs transform rotate-[10deg] absolute right-0 top-[-10px]">
|
<div className="bg-blue-600 p-1 px-2 text-white rounded-md text-xs transform rotate-[10deg] absolute right-0 top-[-10px]">
|
||||||
Killer feature
|
Killer feature
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Link href="/download"><Button className="mt-4 rounded-full p-5 ml-4">Download Zen now!</Button></Link>
|
<Link href="/download">
|
||||||
|
<Button className="mt-4 rounded-full p-5 ml-4">
|
||||||
|
Download Zen now!
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<img src="/compact-mode.png" className="scale-105 hover:scale-110 transform rotate-[-2deg] transition-all duration-100 rounded-md w-full shadow-md dark:shadow-none dark:border-2 mt-16 border-blue-600" />
|
<img
|
||||||
|
src="/compact-mode.png"
|
||||||
|
className="scale-105 hover:scale-110 transform rotate-[-2deg] transition-all duration-100 rounded-md w-full shadow-md dark:shadow-none dark:border-2 mt-16 border-blue-600"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex flex-col p-5 md:p-16 md:col-span-2 border-t-2 row-span-2'>
|
<div className="flex flex-col p-5 md:p-16 md:col-span-2 border-t-2 row-span-2">
|
||||||
<div className="rounded-full px-8 py-3 shadow border-2 flex items-center">
|
<div className="rounded-full px-8 py-3 shadow border-2 flex items-center">
|
||||||
<div className="font-bold text-md">
|
<div className="font-bold text-md">
|
||||||
What makes Zen Browser different?
|
What makes Zen Browser different?
|
||||||
@@ -173,13 +217,14 @@ export default function Features() {
|
|||||||
<img src="/favicon.ico" className="ml-auto w-7 h-7" />
|
<img src="/favicon.ico" className="ml-auto w-7 h-7" />
|
||||||
</div>
|
</div>
|
||||||
<div className="h-full w-full flex items-center justify-center">
|
<div className="h-full w-full flex items-center justify-center">
|
||||||
<Table className='w-full'>
|
<Table className="w-full">
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow className="!border-none" style={{ pointerEvents: 'none'}}>
|
<TableRow
|
||||||
|
className="!border-none"
|
||||||
|
style={{ pointerEvents: 'none' }}
|
||||||
|
>
|
||||||
<TableHead className="py-2 text-2xl font-bold text-black dark:text-white">
|
<TableHead className="py-2 text-2xl font-bold text-black dark:text-white">
|
||||||
<span className="">
|
<span className="">How Zen compares to other browsers</span>
|
||||||
How Zen compares to other browsers
|
|
||||||
</span>
|
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableHead className="py-2 font-bold text-center">
|
<TableHead className="py-2 font-bold text-center">
|
||||||
<Image
|
<Image
|
||||||
@@ -214,7 +259,7 @@ export default function Features() {
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
<TableRow className='border-none'>
|
<TableRow className="border-none">
|
||||||
<TableCell className="py-3 font-medium">
|
<TableCell className="py-3 font-medium">
|
||||||
Fine-grained security like sandboxing
|
Fine-grained security like sandboxing
|
||||||
</TableCell>
|
</TableCell>
|
||||||
@@ -228,7 +273,7 @@ export default function Features() {
|
|||||||
<Checkmark />
|
<Checkmark />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow className='border-none'>
|
<TableRow className="border-none">
|
||||||
<TableCell className="py-3 font-medium">
|
<TableCell className="py-3 font-medium">
|
||||||
Optimized for peak performance
|
Optimized for peak performance
|
||||||
</TableCell>
|
</TableCell>
|
||||||
@@ -242,7 +287,7 @@ export default function Features() {
|
|||||||
<Cross />
|
<Cross />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow className='border-none'>
|
<TableRow className="border-none">
|
||||||
<TableCell className="py-3 font-medium">
|
<TableCell className="py-3 font-medium">
|
||||||
Based on the latest Firefox
|
Based on the latest Firefox
|
||||||
</TableCell>
|
</TableCell>
|
||||||
@@ -256,7 +301,7 @@ export default function Features() {
|
|||||||
<Checkmark />
|
<Checkmark />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow className='border-none'>
|
<TableRow className="border-none">
|
||||||
<TableCell className="py-3 font-medium">
|
<TableCell className="py-3 font-medium">
|
||||||
Customizable with cutting-edge features
|
Customizable with cutting-edge features
|
||||||
</TableCell>
|
</TableCell>
|
||||||
@@ -274,41 +319,47 @@ export default function Features() {
|
|||||||
</Table>
|
</Table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='border-t-2 md:border-l-2 row-span-3 grid grid-rows-3'>
|
<div className="border-t-2 md:border-l-2 row-span-3 grid grid-rows-3">
|
||||||
<div className="flex items-center flex-col justify-center p-16">
|
<div className="flex items-center flex-col justify-center p-16">
|
||||||
<div className="border-2 shadow-md rounded-full p-8 py-3 flex items-center justify-center">
|
<div className="border-2 shadow-md rounded-full p-8 py-3 flex items-center justify-center">
|
||||||
<Github className="w-8 h-8" />
|
<Github className="w-8 h-8" />
|
||||||
<h2 className="text-lg font-bold ml-4">
|
<h2 className="text-lg font-bold ml-4">Open source</h2>
|
||||||
Open source
|
|
||||||
</h2>
|
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm mt-8 text-muted-foreground text-center">
|
<p className="text-sm mt-8 text-muted-foreground text-center">
|
||||||
Zen Browser is open source and always will be. You can check out
|
Zen Browser is open source and always will be. You can check out
|
||||||
the source code on our <a className="text-blue-500" href="https://github.com/zen-browser">Github</a>!
|
the source code on our{' '}
|
||||||
|
<a
|
||||||
|
className="text-blue-500"
|
||||||
|
href="https://github.com/zen-browser"
|
||||||
|
>
|
||||||
|
Github
|
||||||
|
</a>
|
||||||
|
!
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col items-center justify-center p-16 md:border-t-2">
|
<div className="flex flex-col items-center justify-center p-16 md:border-t-2">
|
||||||
<div className="border-2 shadow-md rounded-full p-8 py-3 flex items-center justify-center">
|
<div className="border-2 shadow-md rounded-full p-8 py-3 flex items-center justify-center">
|
||||||
<ReloadIcon className="w-8 h-8" />
|
<ReloadIcon className="w-8 h-8" />
|
||||||
<h2 className="text-lg font-bold ml-4">
|
<h2 className="text-lg font-bold ml-4">Updated</h2>
|
||||||
Updated
|
|
||||||
</h2>
|
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm mt-8 text-muted-foreground text-center">
|
<p className="text-sm mt-8 text-muted-foreground text-center">
|
||||||
We are always working on new features and improvements. You can
|
We are always working on new features and improvements. You can
|
||||||
expect regular updates to keep your browser up to date.
|
expect regular updates to keep your browser up to date.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col p-16 md:border-t-2">
|
<div className="flex flex-col p-16 md:border-t-2">
|
||||||
<div className="border-2 shadow-md rounded-full p-8 py-3 flex items-center justify-center">
|
<div className="border-2 mt-4 shadow-md rounded-full p-8 py-3 flex items-center justify-center">
|
||||||
<HeartFilledIcon className="w-8 h-8" />
|
<HeartFilledIcon className="w-8 h-8" />
|
||||||
<h2 className="text-lg font-bold ml-4">
|
<h2 className="text-lg font-bold ml-4">Community</h2>
|
||||||
Community
|
|
||||||
</h2>
|
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm mt-8 text-muted-foreground text-center">
|
<p className="text-sm mt-8 text-muted-foreground text-center">
|
||||||
Zen Browser is built by a community of passionate developers and
|
Zen Browser is built by a community of passionate developers and
|
||||||
designers. You can join us on our <a className="text-blue-500" href="https://discord.gg/nnShMQzR4b">Discord</a>!
|
designers. You can join us on our{' '}
|
||||||
|
<a className="text-blue-500" href="https://discord.gg/nnShMQzR4b">
|
||||||
|
Discord
|
||||||
|
</a>
|
||||||
|
!
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -316,21 +367,17 @@ export default function Features() {
|
|||||||
<div className="p-16 border-r-2 flex flex-col items-center justify-center">
|
<div className="p-16 border-r-2 flex flex-col items-center justify-center">
|
||||||
<div className="border-2 shadow-md rounded-full p-8 py-3 flex items-center justify-center">
|
<div className="border-2 shadow-md rounded-full p-8 py-3 flex items-center justify-center">
|
||||||
<EyeClosedIcon className="w-8 h-8" />
|
<EyeClosedIcon className="w-8 h-8" />
|
||||||
<h2 className="text-lg font-bold ml-4">
|
<h2 className="text-lg font-bold ml-4">Your Data</h2>
|
||||||
Your Data
|
|
||||||
</h2>
|
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm mt-8 text-muted-foreground text-center">
|
<p className="text-sm mt-8 text-muted-foreground text-center">
|
||||||
We are always looking for ways to improve your privacy. Zen Browser
|
We are always looking for ways to improve your privacy. Zen
|
||||||
comes with built-in privacy features to keep you safe.
|
Browser comes with built-in privacy features to keep you safe.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-16 flex flex-col items-center justify-center">
|
<div className="p-16 flex flex-col items-center justify-center">
|
||||||
<div className="border-2 shadow-md rounded-full p-8 py-3 flex items-center justify-center">
|
<div className="border-2 shadow-md rounded-full p-8 py-3 flex items-center justify-center">
|
||||||
<UpdateIcon className="w-8 h-8" />
|
<UpdateIcon className="w-8 h-8" />
|
||||||
<h2 className="text-lg font-bold ml-4">
|
<h2 className="text-lg font-bold ml-4">Improvements</h2>
|
||||||
Improvements
|
|
||||||
</h2>
|
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm mt-8 text-muted-foreground text-center">
|
<p className="text-sm mt-8 text-muted-foreground text-center">
|
||||||
We are always looking for ways to make Zen Browser better. You can
|
We are always looking for ways to make Zen Browser better. You can
|
||||||
@@ -343,26 +390,35 @@ export default function Features() {
|
|||||||
<div className="relative w-full h-full flex items-center justify-center">
|
<div className="relative w-full h-full flex items-center justify-center">
|
||||||
<img
|
<img
|
||||||
src="/split-view.png"
|
src="/split-view.png"
|
||||||
className={ny("absolute hover:scale-105 rounded-md w-full shadow-md dark:shadow-none dark:border-2 border-blue-500 transform transition-all duration-300",
|
className={ny(
|
||||||
|
'absolute hover:scale-105 rounded-md w-full shadow-md dark:shadow-none dark:border-2 border-blue-500 transform transition-all duration-300',
|
||||||
feature === 0 ? 'translate-x-0' : '-translate-x-1/4 opacity-0'
|
feature === 0 ? 'translate-x-0' : '-translate-x-1/4 opacity-0'
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
src="/workspaces.png"
|
src="/workspaces.png"
|
||||||
className={ny("absolute hover:scale-105 rounded-md w-full shadow-md dark:shadow-none dark:border-2 border-blue-500 transform transition-all duration-300",
|
className={ny(
|
||||||
|
'absolute hover:scale-105 rounded-md w-full shadow-md dark:shadow-none dark:border-2 border-blue-500 transform transition-all duration-300',
|
||||||
feature === 1 ? 'translate-x-0' : '-translate-x-1/4 opacity-0'
|
feature === 1 ? 'translate-x-0' : '-translate-x-1/4 opacity-0'
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
src="/sidebar.png"
|
src="/sidebar.png"
|
||||||
className={ny("absolute hover:scale-105 rounded-md w-full shadow-md dark:shadow-none dark:border-2 border-blue-500 transform transition-all duration-300",
|
className={ny(
|
||||||
|
'absolute hover:scale-105 rounded-md w-full shadow-md dark:shadow-none dark:border-2 border-blue-500 transform transition-all duration-300',
|
||||||
feature === 2 ? 'translate-x-0' : '-translate-x-1/4 opacity-0'
|
feature === 2 ? 'translate-x-0' : '-translate-x-1/4 opacity-0'
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-16 flex flex-col items-center justify-around row-span-2">
|
<div className="p-16 flex flex-col items-center justify-around row-span-2">
|
||||||
<div className={ny(feature === 0 ? 'opacity-100' : 'opacity-50', "mt-10 md:mt-0 transform transition-all duration-200 cursor-pointer")} onClick={() => setFeature(0)}>
|
<div
|
||||||
|
className={ny(
|
||||||
|
feature === 0 ? 'opacity-100' : 'opacity-50',
|
||||||
|
'mt-10 md:mt-0 transform transition-all duration-200 cursor-pointer'
|
||||||
|
)}
|
||||||
|
onClick={() => setFeature(0)}
|
||||||
|
>
|
||||||
<h2 className="text-lg font-bold ml-4 flex items-center">
|
<h2 className="text-lg font-bold ml-4 flex items-center">
|
||||||
<SplitSquareHorizontal className="w-4 h-4 mr-2" />
|
<SplitSquareHorizontal className="w-4 h-4 mr-2" />
|
||||||
Split view
|
Split view
|
||||||
@@ -371,7 +427,13 @@ export default function Features() {
|
|||||||
Split your browser into two windows to work more efficiently.
|
Split your browser into two windows to work more efficiently.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className={ny(feature === 1 ? 'opacity-100' : 'opacity-50', "mt-10 md:mt-0 transform transition-all duration-200 cursor-pointer")} onClick={() => setFeature(1)}>
|
<div
|
||||||
|
className={ny(
|
||||||
|
feature === 1 ? 'opacity-100' : 'opacity-50',
|
||||||
|
'mt-10 md:mt-0 transform transition-all duration-200 cursor-pointer'
|
||||||
|
)}
|
||||||
|
onClick={() => setFeature(1)}
|
||||||
|
>
|
||||||
<h2 className="text-lg font-bold ml-4 flex items-center">
|
<h2 className="text-lg font-bold ml-4 flex items-center">
|
||||||
<HomeIcon className="w-4 h-4 mr-2" />
|
<HomeIcon className="w-4 h-4 mr-2" />
|
||||||
Workspaces
|
Workspaces
|
||||||
@@ -380,7 +442,13 @@ export default function Features() {
|
|||||||
Organize your tabs into workspaces to keep things tidy.
|
Organize your tabs into workspaces to keep things tidy.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className={ny(feature === 2 ? 'opacity-100' : 'opacity-50', "mt-10 md:mt-0 transform transition-all duration-200 cursor-pointer")} onClick={() => setFeature(2)}>
|
<div
|
||||||
|
className={ny(
|
||||||
|
feature === 2 ? 'opacity-100' : 'opacity-50',
|
||||||
|
'mt-10 md:mt-0 transform transition-all duration-200 cursor-pointer'
|
||||||
|
)}
|
||||||
|
onClick={() => setFeature(2)}
|
||||||
|
>
|
||||||
<h2 className="text-lg font-bold ml-4 flex items-center">
|
<h2 className="text-lg font-bold ml-4 flex items-center">
|
||||||
<SidebarIcon className="w-4 h-4 mr-2" />
|
<SidebarIcon className="w-4 h-4 mr-2" />
|
||||||
Sidebar
|
Sidebar
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { getThemeAuthorLink, ZenTheme } from "@/lib/themes";
|
|||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "./ui/dialog";import { Button } from "./ui/button";
|
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "./ui/dialog";import { Button } from "./ui/button";
|
||||||
|
|
||||||
const ThemeCardWrapepr = styled.div`
|
const ThemeCardWrapper = styled.div`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default function ThemeCard({
|
export default function ThemeCard({
|
||||||
@@ -16,7 +16,7 @@ export default function ThemeCard({
|
|||||||
const maxDescLen = 100;
|
const maxDescLen = 100;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeCardWrapepr onClick={(event) => {
|
<ThemeCardWrapper onClick={(event) => {
|
||||||
if (event.target instanceof HTMLAnchorElement) return;
|
if (event.target instanceof HTMLAnchorElement) return;
|
||||||
window.open(`/themes/${theme.id}`, "_self");
|
window.open(`/themes/${theme.id}`, "_self");
|
||||||
}} className="flex flex-col justify-start p-5 rounded-lg shadow-sm bg-muted dark:bg-muted/50 border border-grey-900 dark:border-muted w-full hover:shadow-lg transition duration-300 ease-in-out hover:bg-muted/100 hover:border-blue-500 cursor-pointer select-none ">
|
}} className="flex flex-col justify-start p-5 rounded-lg shadow-sm bg-muted dark:bg-muted/50 border border-grey-900 dark:border-muted w-full hover:shadow-lg transition duration-300 ease-in-out hover:bg-muted/100 hover:border-blue-500 cursor-pointer select-none ">
|
||||||
|
|||||||
Reference in New Issue
Block a user