Merge pull request #596 from zen-browser/refactor/app

This commit is contained in:
mr. m 2025-05-15 14:41:17 +02:00 committed by GitHub
commit bdf9bb81d5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
38 changed files with 453 additions and 351 deletions

View file

@ -20,16 +20,26 @@
"useEditorconfig": true
},
"files": {
"ignore": [
"node_modules",
".git",
"dist"
]
"ignore": ["node_modules", ".git", "dist"]
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"semicolons": "asNeeded"
}
},
"assists": {
"actions": {
"source": {
"sortJsxProps": "on"
}
}
},
"vcs": {
"enabled": true,
"clientKind": "git",
"defaultBranch": "main",
"root": ".",
"useIgnoreFile": true
}
}

View file

@ -10,7 +10,7 @@
"wrangler": "wrangler",
"astro": "astro",
"lint": "biome lint ./src",
"format": "biome format ./src --write",
"format": "biome format ./src",
"prepare": "husky"
},
"dependencies": {
@ -45,8 +45,6 @@
"wrangler": "^3.94.0"
},
"lint-staged": {
"src/**/*.{ts,tsx,astro,js,jsx}": [
"biome check --write ./src"
]
"src/**/*.{ts,tsx,astro,js,jsx}": ["biome check --write ./src"]
}
}

View file

@ -1,68 +1,70 @@
{
"version": "v1.0.0",
"entity": {
"type": "individual",
"role": "owner",
"name": "Mauro",
"email": "funding@zen-browser.com",
"description": "Im the developer of Zen Browser, a web browser that is fast, secure, and easy to use. I am passionate about creating software that makes people's lives easier and more enjoyable.",
"webpageUrl": {
"url": "https://cheff.dev",
"wellKnown": "https://cheff.dev/.well-known/funding-manifest-urls"
}
},
"projects": [{
"guid": "zen-browser",
"name": "Zen",
"description": "Zen is a beautiful, fast, and productive web browser. It is designed to be packed with features that make it easy to use and navigate. Zen is built on the latest Firefox engine, providing speed, privacy, and security.",
"webpageUrl": {
"url": "https://zen-browser.app"
},
"repositoryUrl": {
"url": "https://github.com/zen-browser/desktop",
"wellKnown": "https://github.com/zen-browser/desktop/blob/dev/.well-known/funding-manifest-urls"
},
"licenses": ["MPL-2.0"],
"tags": ["browser", "web", "desktop", "open-source"]
}],
"funding": {
"channels": [
{
"guid": "patreon",
"name": "Patreon",
"description": "Patreon is a membership platform that makes it easy for artists and creators to get paid.",
"url": "https://www.patreon.com/zen_browser",
"type": "other"
},
{
"guid": "ko-fi",
"name": "Ko-fi",
"description": "Ko-fi is a platform that allows creators to receive donations from their fans.",
"url": "https://ko-fi.com/zen_browser",
"type": "other"
}
],
"plans": [
{
"guid": "licenses-and-hosting",
"status": "active",
"name": "Licenses and hosting",
"description": "Help me pay for the licenses and hosting of the project. This includes self-hosting build servers, cloudflare services, and software lienses.",
"amount": 420,
"currency": "EUR",
"frequency": "yearly",
"channels": ["patreon", "ko-fi"]
},
{
"guid": "angel-plan",
"status": "active",
"name": "Goodwill plan",
"description": "Pay anything you wish to show your goodwill for the project.",
"amount": 0,
"currency": "EUR",
"frequency": "one-time",
"channels": ["patreon", "ko-fi"]
}
]
"version": "v1.0.0",
"entity": {
"type": "individual",
"role": "owner",
"name": "Mauro",
"email": "funding@zen-browser.com",
"description": "Im the developer of Zen Browser, a web browser that is fast, secure, and easy to use. I am passionate about creating software that makes people's lives easier and more enjoyable.",
"webpageUrl": {
"url": "https://cheff.dev",
"wellKnown": "https://cheff.dev/.well-known/funding-manifest-urls"
}
},
"projects": [
{
"guid": "zen-browser",
"name": "Zen",
"description": "Zen is a beautiful, fast, and productive web browser. It is designed to be packed with features that make it easy to use and navigate. Zen is built on the latest Firefox engine, providing speed, privacy, and security.",
"webpageUrl": {
"url": "https://zen-browser.app"
},
"repositoryUrl": {
"url": "https://github.com/zen-browser/desktop",
"wellKnown": "https://github.com/zen-browser/desktop/blob/dev/.well-known/funding-manifest-urls"
},
"licenses": ["MPL-2.0"],
"tags": ["browser", "web", "desktop", "open-source"]
}
],
"funding": {
"channels": [
{
"guid": "patreon",
"name": "Patreon",
"description": "Patreon is a membership platform that makes it easy for artists and creators to get paid.",
"url": "https://www.patreon.com/zen_browser",
"type": "other"
},
{
"guid": "ko-fi",
"name": "Ko-fi",
"description": "Ko-fi is a platform that allows creators to receive donations from their fans.",
"url": "https://ko-fi.com/zen_browser",
"type": "other"
}
],
"plans": [
{
"guid": "licenses-and-hosting",
"status": "active",
"name": "Licenses and hosting",
"description": "Help me pay for the licenses and hosting of the project. This includes self-hosting build servers, cloudflare services, and software lienses.",
"amount": 420,
"currency": "EUR",
"frequency": "yearly",
"channels": ["patreon", "ko-fi"]
},
{
"guid": "angel-plan",
"status": "active",
"name": "Goodwill plan",
"description": "Pay anything you wish to show your goodwill for the project.",
"amount": 0,
"currency": "EUR",
"frequency": "one-time",
"channels": ["patreon", "ko-fi"]
}
]
}
}

View file

@ -1,5 +1,5 @@
---
import { ArrowLeft } from 'lucide-astro'
import ArrowLeftIcon from '~/icons/ArrowLeftIcon.astro'
import { getLocale, getUI } from '~/utils/i18n'
const locale = getLocale(Astro)
@ -15,6 +15,6 @@ const {
onclick="window.history.back()"
class="mb-8 flex w-min items-center gap-2"
>
<ArrowLeft class="size-4" />
<ArrowLeftIcon class="size-4" />
{slug.back}
</button>

View file

@ -1,11 +1,12 @@
---
import Image from 'astro/components/Image.astro'
import { Check, Github } from 'lucide-astro'
import { motion } from 'motion/react'
import { getTitleAnimation } from '~/animations'
import ComImage from '~/assets/ComImage.png'
import Button from '~/components/Button.astro'
import Description from '~/components/Description.astro'
import CheckIcon from '~/icons/CheckIcon.astro'
import GitHubIcon from '~/icons/GitHubIcon.astro'
import { getLocale, getUI } from '~/utils/i18n'
const locale = getLocale(Astro)
@ -19,9 +20,9 @@ const {
<section
id="Community"
class="relative flex w-full flex-col items-center px-4 text-start md:px-0 md:text-center lg:pt-36"
class="relative flex w-full flex-col items-center gap-6 py-12 text-start md:text-center lg:py-36"
>
<Description class="mb-2 px-4 text-6xl font-bold">
<Description class="mb-2 text-6xl font-bold">
<motion.span client:load {...getTitleAnimation(0.2)}>
{community.title[0]}
</motion.span>
@ -35,16 +36,14 @@ const {
<motion.p
client:load
{...getTitleAnimation(0.6)}
className="px-4 md:px-24 lg:w-1/2 lg:px-0"
className="lg:w-1/2 lg:px-0"
>
{community.description}
</motion.p>
<div
class="mt-6 flex w-full flex-wrap gap-3 px-4 sm:gap-10 sm:px-0 md:justify-center"
>
<div class="flex w-full flex-wrap gap-3 sm:gap-10 md:justify-center">
<motion.span client:load {...getTitleAnimation(0.8)}>
<Button class:list={['px-4']} href="https://github.com/zen-browser">
<Github class="size-4" />
<GitHubIcon class="size-4" />
<span>{community.lists.freeAndOpenSource.title}</span>
</Button>
</motion.span>
@ -53,7 +52,7 @@ const {
{...getTitleAnimation(1)}
className="flex items-center gap-4"
>
<Check class="size-4" />
<CheckIcon class="size-4" />
<span>{community.lists.simpleYetPowerful.title}</span>
</motion.div>
<motion.div
@ -61,19 +60,19 @@ const {
{...getTitleAnimation(1.2)}
className="flex items-center gap-4"
>
<Check class="size-4" />
<CheckIcon class="size-4" />
<span>{community.lists.privateAndAlwaysUpToDate.title}</span>
</motion.div>
</div>
<motion.span
className="flex max-w-full px-8 lg:max-w-none lg:flex-none lg:px-0"
className="flex max-w-full lg:max-w-none lg:flex-none"
client:load
{...getTitleAnimation(1.4)}
>
<Image
src={ComImage}
alt={community.images.community.alt}
class="my-24 rounded-3xl shadow-md lg:mx-auto lg:w-3/4 dark:opacity-80"
class="rounded-3xl shadow-md lg:mx-auto dark:opacity-80"
/>
</motion.span>
</section>

View file

@ -26,7 +26,7 @@ const descriptions = Object.values(features.featureTabs).map((tab) => tab.descri
<section
id="Features"
class="relative flex w-full flex-col px-4 text-start md:px-24 lg:mx-auto lg:w-3/4 lg:px-0 lg:py-36"
class="relative flex w-full flex-col py-12 text-start lg:py-36"
>
<Description class="mb-2 text-6xl font-bold">
<motion.span client:load {...getTitleAnimation(0.2)}>
@ -42,9 +42,7 @@ const descriptions = Object.values(features.featureTabs).map((tab) => tab.descri
<motion.p client:load {...getTitleAnimation(0.6)} className="lg:w-1/2">
{features.description}
</motion.p>
<div
class="mb-12 mt-6 flex flex-col gap-6 lg:flex-row lg:justify-between lg:gap-2"
>
<div class="mt-6 flex flex-col gap-6 lg:flex-row lg:justify-between lg:gap-2">
<div class="flex w-full flex-col lg:w-1/3">
<!-- Mobile tabs -->
<div class="flex gap-2 overflow-x-auto overflow-y-clip lg:hidden">

View file

@ -1,9 +1,9 @@
---
import { ArrowRight } from 'lucide-astro'
import Button from '~/components/Button.astro'
import Circles from '~/components/Circles.astro'
import Description from '~/components/Description.astro'
import SocialMediaStrip from '~/components/SocialMediaStrip.astro'
import ArrowRightIcon from '~/icons/ArrowRightIcon.astro'
import { getLocale, getPath, getUI } from '~/utils/i18n'
const locale = getLocale(Astro)
@ -15,11 +15,13 @@ const {
<footer
id="footer"
class="relative flex w-full flex-col gap-16 overflow-hidden border-t border-dark bg-dark px-4 py-12 text-paper lg:p-24"
class="relative flex w-full flex-col items-center gap-16 overflow-hidden border-t border-dark bg-dark px-4 py-12 text-paper lg:p-24"
role="contentinfo"
aria-label="Site footer"
>
<div class="flex w-full flex-col items-start justify-between gap-12">
<div
class="container flex w-full flex-col items-start justify-between gap-12"
>
<section
class="w-full text-center lg:w-1/2 lg:text-left"
aria-labelledby="footer-title"
@ -39,7 +41,7 @@ const {
aria-label={footer.download}
>
{footer.download}
<ArrowRight class="size-4" aria-hidden="true" />
<ArrowRightIcon class="size-4" aria-hidden="true" />
</Button>
</section>
<section

View file

@ -1,11 +1,11 @@
---
import { ArrowRight } from 'lucide-astro'
import { motion } from 'motion/react'
import { getTitleAnimation } from '~/animations'
import HomePageVideo from '~/assets/HomePageVideo.webm'
import Button from '~/components/Button.astro'
import Description from '~/components/Description.astro'
import Title from '~/components/Title.astro'
import ArrowRightIcon from '~/icons/ArrowRightIcon.astro'
import { getLocale, getPath, getUI } from '~/utils/i18n'
import SocialMediaStrip from './SocialMediaStrip.astro'
import Video from './Video.astro'
@ -37,7 +37,7 @@ const {
>
<div class="flex h-full flex-col items-center justify-center">
<Title
class="relative px-12 text-center !font-normal !leading-8 leading-[108px] md:!text-7xl lg:px-0 lg:!text-9xl"
class="relative px-12 text-center !font-normal leading-8 md:text-7xl lg:px-0 lg:text-9xl"
>
<motion.span client:load {...getHeroTitleAnimation()}>
{hero.title[0]}
@ -71,7 +71,7 @@ const {
<motion.span client:load {...getHeroTitleAnimation()}>
<Button class="w-full" href={getLocalePath('/download')} isPrimary>
{hero.buttons.beta}
<ArrowRight class="size-4" />
<ArrowRightIcon class="size-4" />
</Button>
</motion.span>
<motion.span client:load {...getHeroTitleAnimation()}>
@ -88,7 +88,7 @@ const {
</div>
</header>
<motion.span
className="flex max-w-full px-8 lg:max-w-none lg:flex-none lg:px-0"
className="flex max-w-full lg:max-w-none lg:flex-none"
client:load
{...getHeroTitleAnimation()}
>
@ -99,6 +99,6 @@ const {
muted
playsinline
preload="none"
class="mb-24 rounded-3xl shadow-md lg:mx-auto lg:w-3/4 dark:opacity-80"
class="mb-24 rounded-3xl shadow-md dark:opacity-80"
/>
</motion.span>

View file

@ -89,36 +89,36 @@ export default function ModsList({ allMods, locale }: ModsListProps) {
return (
<div className="mx-auto mb-12 flex items-center justify-center gap-4 px-8">
<button
type="button"
onClick={() => navigatePage(page - 1)}
className={`px-3 py-2 ${page === 1 ? 'pointer-events-none text-gray-400' : 'text-dark hover:text-gray-600'}`}
onClick={() => navigatePage(page - 1)}
type="button"
>
&lt;
</button>
<form onSubmit={handlePageSubmit} className="flex items-center gap-2">
<form className="flex items-center gap-2" onSubmit={handlePageSubmit}>
{mods.pagination.pagination.split('{input}').map((value, index) => {
if (index === 0) {
return (
<input
aria-label="Page number"
className="w-16 rounded border border-dark bg-transparent px-2 py-1 text-center text-sm"
onInput={handlePageInputChange}
type="text"
value={pageInput}
onInput={handlePageInputChange}
className="w-16 rounded border border-dark bg-transparent px-2 py-1 text-center text-sm"
aria-label="Page number"
/>
)
}
return (
<span key={value} className="text-sm">
<span className="text-sm" key={value}>
{value.replace('{totalPages}', totalPages.toString()).replace('{totalItems}', totalItems.toString())}
</span>
)
})}
</form>
<button
type="button"
onClick={() => navigatePage(page + 1)}
className={`px-3 py-2 ${page === totalPages ? 'pointer-events-none text-gray-400' : 'text-dark hover:text-gray-600'}`}
onClick={() => navigatePage(page + 1)}
type="button"
>
&gt;
</button>
@ -128,24 +128,24 @@ export default function ModsList({ allMods, locale }: ModsListProps) {
return (
<div>
<div className="mx-auto flex flex-col items-start gap-4 px-8 lg:w-1/2">
<div className="flex w-full flex-col items-center gap-6">
<div className="flex flex-col items-center gap-4">
<div className="flex w-full flex-col items-center justify-center gap-6">
<input
type="text"
id="search"
className="w-full rounded-full border-2 border-dark bg-transparent px-6 py-2 text-lg outline-none"
placeholder={mods.search}
value={search}
id="search"
onInput={handleSearch}
placeholder={mods.search}
type="text"
value={search}
/>
</div>
<div className="grid w-full grid-cols-2 place-items-center gap-4 sm:grid-cols-3">
<div className="flex flex-col items-start gap-2">
<button
type="button"
onClick={toggleCreatedSort}
className="flex items-center gap-2 px-4 py-2 font-semibold text-md"
onClick={toggleCreatedSort}
type="button"
>
{mods.sort.lastCreated}
<span
@ -159,9 +159,9 @@ export default function ModsList({ allMods, locale }: ModsListProps) {
<div className="flex flex-col items-center gap-2">
<button
type="button"
onClick={toggleUpdatedSort}
className="flex items-center gap-2 px-4 py-2 font-semibold text-md"
onClick={toggleUpdatedSort}
type="button"
>
{mods.sort.lastUpdated}
<span
@ -174,14 +174,14 @@ export default function ModsList({ allMods, locale }: ModsListProps) {
</div>
<div className="flex items-center gap-2 px-4 py-2">
<label htmlFor="limit" className="font-semibold text-md">
<label className="font-semibold text-md" htmlFor="limit">
{mods.sort.perPage}
</label>
<select
id="limit"
value={limit}
onInput={handleLimitChange}
className="rounded border border-dark bg-transparent px-2 py-1 text-sm [&>option]:text-black"
id="limit"
onInput={handleLimitChange}
value={limit}
>
<option value="12">12</option>
<option value="24">24</option>
@ -192,20 +192,20 @@ export default function ModsList({ allMods, locale }: ModsListProps) {
</div>
</div>
<div className="mx-auto grid grid-cols-1 place-items-start gap-12 p-10 md:grid-cols-2 lg:grid-cols-3 lg:p-24 lg:px-24 2xl:grid-cols-4">
<div className="grid w-full grid-cols-1 place-items-start gap-12 py-6 md:grid-cols-2 xl:grid-cols-3">
{paginatedMods.length > 0 ? (
paginatedMods.map((mod) => (
<a
key={mod.id}
className="flex w-full flex-col gap-4 border-transparent transition-colors duration-100 hover:opacity-90"
href={`/mods/${mod.id}`}
className="flex flex-col gap-4 border-transparent transition-colors duration-100 hover:opacity-90"
key={mod.id}
>
<div className="relative mb-0 block aspect-[1.85/1] h-48 overflow-hidden rounded-md border-2 border-dark object-cover shadow-md">
<img
src={mod.image}
alt={mod.name}
loading="lazy"
className="h-full w-full object-cover transition-transform duration-100 hover:scale-105"
loading="lazy"
src={mod.image}
/>
</div>
<div>

View file

@ -1,8 +1,11 @@
---
import { Astronav, Dropdown, DropdownItems, MenuItems } from 'astro-navbar'
import { ArrowRight, ChevronDown, Download, Menu } from 'lucide-astro'
import { motion } from 'motion/react'
import Button from '~/components/Button.astro'
import ArrowRightIcon from '~/icons/ArrowRightIcon.astro'
import ChevronDownIcon from '~/icons/ChevronDownIcon.astro'
import DownloadIcon from '~/icons/DownloadIcon.astro'
import MenuIcon from '~/icons/MenuIcon.astro'
import { getLocale, getPath, getUI } from '~/utils/i18n'
import { getTitleAnimation } from '../animations.ts'
import Logo from './Logo.astro'
@ -21,7 +24,7 @@ const {
<!-- Desktop Navigation -->
<Astronav>
<MenuItems
class="relative z-20 mx-auto grid w-full grid-cols-2 items-center gap-2 bg-paper px-4 py-3 lg:grid lg:min-w-fit lg:grid-cols-[auto_1fr_auto] lg:p-6 xl:w-3/4"
class="container relative z-20 grid w-full grid-cols-2 items-center gap-2 bg-paper py-3 lg:grid lg:grid-cols-[auto_1fr_auto] lg:py-6"
>
<a
class="flex items-center gap-2 text-lg font-bold"
@ -36,7 +39,7 @@ const {
<Dropdown class="group">
<button class="flex items-center">
<span>{menu.gettingStarted}</span>
<ChevronDown
<ChevronDownIcon
class="size-4 transform transition-transform duration-200 group-open:rotate-180 md:ml-2"
/>
</button>
@ -56,7 +59,7 @@ const {
</div>
<Button isPrimary class="mt-auto">
{menu.tryZenMods}
<ArrowRight class="size-4" />
<ArrowRightIcon class="size-4" />
</Button>
</a>
<a class="dropdown-item" href={getLocalePath('/release-notes')}>
@ -77,7 +80,7 @@ const {
<Dropdown class="group">
<button class="flex items-center">
<span>{menu.usefulLinks}</span>
<ChevronDown
<ChevronDownIcon
class="size-4 transform transition-transform duration-200 group-open:rotate-180 md:ml-2"
/>
</button>
@ -129,10 +132,10 @@ const {
<Button href="/download" class="hidden lg:flex" isPrimary>
<span class="hidden items-center gap-2 lg:flex">
{menu.download}
<ArrowRight class="size-4" />
<ArrowRightIcon class="size-4" />
</span>
<span class="flex items-center gap-2 lg:hidden">
<Download class="size-4" />
<DownloadIcon class="size-4" />
</span>
</Button>
<label
@ -140,7 +143,7 @@ const {
class="cursor-pointer p-2 text-dark lg:hidden"
aria-label="Open menu"
>
<Menu class="h-6 w-6" />
<MenuIcon class="h-6 w-6" />
</label>
</div>
</MenuItems>

View file

@ -1,6 +1,6 @@
---
import { Accordion, AccordionItem } from 'free-astro-components'
import { Info } from 'lucide-astro'
import InfoIcon from '~/icons/InfoIcon.astro'
import { releaseNotes as releaseNotesData } from '~/release-notes'
import { getLocale, getPath, getUI } from '~/utils/i18n'
@ -112,7 +112,7 @@ if (prevReleaseNote && !isTwilight) {
}
</div>
<div class="text-muted-forground mt-6 flex text-sm opacity-70">
{isTwilight ? <Info class="mx-4 my-0 size-6 text-yellow-500" /> : null}
{isTwilight ? <InfoIcon class="mx-4 my-0 size-6 text-yellow-500" /> : null}
<p class="m-0">
{isTwilight ? <>{releaseNoteItem.twilightWarning}</> : null}
<span set:html={releaseNoteItem.reportIssues} />

View file

@ -18,12 +18,10 @@ const {
} = getUI(locale)
---
<section id="sponsors" class:list={['mb-32 px-4', !showSponsors && 'hidden']}>
<div class="mx-auto flex flex-col px-6 text-center">
<section id="sponsors" class:list={['py-12', !showSponsors && 'hidden']}>
<div class="mx-auto flex flex-col text-center">
<motion.span client:load {...getTitleAnimation(0.2)}>
<Description class="mb-2 px-4 text-6xl font-bold"
>Our Sponsors</Description
>
<Description class="mb-2 text-6xl font-bold">Our Sponsors</Description>
</motion.span>
<motion.span client:load {...getTitleAnimation(0.4)}>
<Description set:html={sponsors.description} />

View file

@ -2,18 +2,6 @@
const { class: className } = Astro.props
---
<h1 class:list={['title text-dark', className]}>
<h1 class:list={['text-dark leading-[0.9] mb-[0.4rem] font-junicode font-semibold text-5xl xl:text-6xl', className]}>
<slot />
</h1>
<style>
.title {
line-height: 0.9;
margin-bottom: 0.4rem;
font-family: 'Junicode', serif;
font-weight: 600;
font-style: normal;
font-feature-settings: 'swsh' 1;
@apply text-5xl xl:text-6xl;
}
</style>

View file

@ -85,12 +85,22 @@ import DownloadCard from './ButtonCard.astro'
checksum={releases.universal.checksum}
/>
)}
{releases.x86_64 && 'tarball' in releases.x86_64 && releases.x86_64.tarball && releases.x86_64.tarball.label && (
<DownloadCard
label={releases.x86_64.tarball.label}
href={releases.x86_64.tarball.link}
checksum={releases.x86_64.tarball.checksum}
/>
{releases.x86_64 && (
'tarball' in releases.x86_64
? releases.x86_64.tarball.label && (
<DownloadCard
label={releases.x86_64.tarball.label}
href={releases.x86_64.tarball.link}
checksum={releases.x86_64.tarball.checksum}
/>
)
: releases.x86_64.label && (
<DownloadCard
label={releases.x86_64.label}
href={releases.x86_64.link}
checksum={releases.x86_64.checksum}
/>
)
)}
{releases.arm64 && releases.arm64.label && (
<DownloadCard

View file

@ -144,86 +144,107 @@
}
},
"about": {
"title": "About - Zen Browser",
"title": "About Zen",
"description": "We are simply a group of developers and designers who care about your experience on the web. We believe that the internet should be a place where you can explore, learn, and connect without worrying about your data being collected.",
"littleHelp": "A little help?",
"mainTeam": {
"title": "Main Team",
"description": "This list shows the main team members who are working hard to bring you the best browsing experience.",
"subTitle": {
"browser": "Browser",
"website": "Website and Branding"
},
"members": {
"mauro": {
"name": "Mauro B.",
"description": "Creator, Main Developer",
"link": "https://cheff.dev/"
"browser": {
"mauro": {
"name": "Mauro B.",
"description": "Creator, Main Developer",
"link": "https://cheff.dev/"
},
"jan": {
"name": "Jan Heres",
"description": "Active contributor and helps with MacOS builds",
"link": "https://janheres.eu/"
},
"bryan": {
"name": "Bryan Galdámez",
"description": "Huge contributor on theme functionalities",
"link": "https://josuegalre.netlify.app/"
},
"oscar": {
"name": "Oscar Gonzalez",
"description": "Site Reliability Engineer (SRE) and code signing.",
"link": false
},
"daniel": {
"name": "Daniel García",
"description": "MacOS certificate and app notarization maintainer",
"link": false
},
"brhm": {
"name": "BrhmDev",
"description": "Active contributor with great contributions",
"link": "https://github.com/BrhmDev"
},
"kristijanribaric": {
"name": "Kristijan Ribaric",
"description": "Active contributor",
"link": "https://github.com/kristijanribaric"
},
"larvey": {
"name": "Larvey",
"description": "AUR maintainer",
"link": "https://github.com/LarveyOfficial/"
}
},
"oscar": {
"name": "Oscar Gonzalez",
"description": "Site Reliability Engineer (SRE) and code signing.",
"link": false
},
"jan": {
"name": "Jan Heres",
"description": "Active contributor and helps with MacOS builds",
"link": "https://janheres.eu/"
},
"brhm": {
"name": "BrhmDev",
"description": "Active contributor with great contributions",
"link": "https://github.com/BrhmDev"
},
"canoa": {
"name": "Canoa",
"description": "Active contributor, and very active in issue handling and website management",
"link": "https://thatcanoa.org/"
},
"adam": {
"name": "Adam",
"description": "Branding and design",
"link": "https://cybrneon.xyz/"
},
"kristijanribaric": {
"name": "Kristijan Ribaric",
"description": "Active contributor",
"link": "https://github.com/kristijanribaric"
},
"n7itro": {
"name": "n7itro",
"description": "Active contributor and release notes writer",
"link": "https://github.com/n7itro"
},
"bryan": {
"name": "Bryan Galdámez",
"description": "Huge contributor on theme functionalities",
"link": "https://josuegalre.netlify.app/"
},
"jafeth": {
"name": "Jafeth Garro",
"description": "Documentation writer",
"link": "https://iamjafeth.com/"
},
"larvey": {
"name": "Larvey",
"description": "AUR maintainer",
"link": "https://github.com/LarveyOfficial/"
},
"daniel": {
"name": "Daniel García",
"description": "MacOS certificate and app notarization maintainer",
"link": false
"website": {
"taroj1205": {
"name": "Shintaro Jokagi",
"description": "Core Website Architect, Spearheading Refactoring and Technical Enhancements",
"link": "https://github.com/taroj1205"
},
"jace": {
"name": "Jace",
"description": "Contributes to website design and branding",
"link": "https://x.com/JaceThings"
},
"canoa": {
"name": "Canoa",
"description": "Active contributor, and very active in issue handling and website management",
"link": "https://thatcanoa.org/"
},
"adam": {
"name": "Adam",
"description": "Branding and design",
"link": "https://cybrneon.xyz/"
},
"n7itro": {
"name": "n7itro",
"description": "Active contributor and release notes writer",
"link": "https://github.com/n7itro"
},
"jafeth": {
"name": "Jafeth Garro",
"description": "Documentation writer",
"link": "https://iamjafeth.com/"
}
}
}
},
"contributors": {
"title": "Contributors",
"description": "This list shows the contributors who have helped us to make Zen Browser the best it can be."
"description": "This list shows the contributors who have helped us to make Zen Browser the best it can be.",
"browser": "Browser",
"website": "Website"
}
},
"donate": {
"title": "Donate - Zen Browser",
"title": "Donate",
"description": "We are a small team of developers working hard to bring you the best browsing experience. If you like what we do, please consider supporting us.",
"patreon": {
"title": "Patreon",
"description": "Patreon allows you to support us with a monthly donation. You can choose the level of support that works best for you."
"description": "Patreon allows you to support us with a monthly donation. You can choose the level of support that works best for you.",
"button": "Go to Patreon"
},
"koFi": {
"title": "Ko-fi",
@ -395,7 +416,7 @@
"description": "Stay up to date with the latest changes to Zen Browser! Since the first release till {latestVersion}, we've been working hard to make Zen Browser the best it can be. Thanks everyone for your feedback! ❤️"
},
"about": {
"title": "About - Zen",
"title": "About Zen",
"description": "We are simply a group of developers and designers who care about your experience on the web. We believe that the internet should be a place where you can explore, learn, and connect without worrying about your data being collected."
},
"donate": {

View file

@ -0,0 +1,5 @@
---
const { class: className, ...props } = Astro.props
---
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class:list={["lucide lucide-arrow-left-icon lucide-arrow-left", className]} {...props}><path d="m12 19-7-7 7-7"/><path d="M19 12H5"/></svg>

View file

@ -0,0 +1,5 @@
---
const { class: className, ...props } = Astro.props
---
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class:list={["lucide lucide-arrow-right-icon lucide-arrow-right", className]} {...props}><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>

5
src/icons/ArrowUp.astro Normal file
View file

@ -0,0 +1,5 @@
---
const { class: className, ...props } = Astro.props
---
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class:list={["lucide lucide-arrow-up-icon lucide-arrow-up", className]} {...props}><path d="m5 12 7-7 7 7"/><path d="M12 19V5"/></svg>

View file

@ -0,0 +1,5 @@
---
const { class: className, ...props } = Astro.props
---
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class:list={["lucide lucide-check-icon lucide-check", className]} {...props}><path d="M20 6 9 17l-5-5"/></svg>

View file

@ -0,0 +1,5 @@
---
const { class: className, ...props } = Astro.props
---
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class:list={["lucide lucide-chevron-down-icon lucide-chevron-down", className]} {...props}><path d="m6 9 6 6 6-6"/></svg>

View file

@ -0,0 +1,5 @@
---
const { class: className, ...props } = Astro.props
---
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class:list={["lucide lucide-download-icon lucide-download", className]} {...props}><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" x2="12" y1="15" y2="3"/></svg>

View file

@ -0,0 +1,5 @@
---
const { class: className, ...props } = Astro.props
---
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class:list={["lucide lucide-external-link-icon lucide-external-link", className]} {...props}><path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/></svg>

View file

@ -0,0 +1,5 @@
---
const { class: className, ...props } = Astro.props
---
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class:list={["lucide lucide-github-icon lucide-github", className]} {...props}><path d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"/><path d="M9 18c-4.51 2-5-2-7-2"/></svg>

5
src/icons/InfoIcon.astro Normal file
View file

@ -0,0 +1,5 @@
---
const { class: className, ...props } = Astro.props
---
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class:list={["lucide lucide-info-icon lucide-info", className]} {...props}><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>

5
src/icons/LockIcon.astro Normal file
View file

@ -0,0 +1,5 @@
---
const { class: className, ...props } = Astro.props
---
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class:list={["lucide lucide-lock-icon lucide-lock", className]} {...props}><rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>

5
src/icons/MenuIcon.astro Normal file
View file

@ -0,0 +1,5 @@
---
const { class: className, ...props } = Astro.props
---
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class:list={["lucide lucide-menu-icon lucide-menu", className]} {...props}><path d="M4 12h16"/><path d="M4 18h16"/><path d="M4 6h16"/></svg>

View file

@ -89,7 +89,7 @@ const locale = getLocale(Astro)
<script>
console.log(
'%c✌ Zen-Browser%c\nWelcome to a calmer internet!%c',
'%c✌ Zen-Browser%c\nWelcome to a calmer internet!',
'filter: invert(1); font-size: 28px; font-weight: bolder; font-family: "Rubik"; margin-top: 20px; margin-bottom: 8px;',
'color: #f76f53; font-size: 16px; font-family: "Rubik"; margin-bottom: 20px;'
);
@ -97,7 +97,7 @@ const locale = getLocale(Astro)
</head>
<body
class="overflow-x-hidden bg-paper font-['bricolage-grotesque'] text-dark"
class="overflow-x-hidden bg-paper font-['bricolage-grotesque'] text-dark text-balance"
>
<NavBar />
<slot />

View file

@ -15,17 +15,19 @@ const {
<Layout title={notFound.title}>
<main
class="flex min-h-[70vh] flex-col items-center justify-center py-24 text-center"
class="container flex min-h-[70vh] flex-col items-center justify-center gap-6 py-24 text-center"
>
<Title class="mb-4 text-7xl font-bold text-coral md:text-9xl">404</Title>
<Description class="mb-6 text-xl md:text-2xl">
{notFound.title}
</Description>
<p class="mb-8 max-w-xl text-lg text-gray-500 dark:text-gray-400">
{notFound.description}
</p>
<Button href={getLocalePath('/')} isPrimary>
{notFound.button}
</Button>
<Title class="text-7xl font-bold text-coral md:text-9xl">404</Title>
<div class="flex flex-col items-center gap-6">
<Description class="text-xl md:text-2xl">
{notFound.title}
</Description>
<p class="max-w-xl text-lg text-gray-500 dark:text-gray-400">
{notFound.description}
</p>
<Button href={getLocalePath('/')} isPrimary class="w-fit">
{notFound.button}
</Button>
</div>
</main>
</Layout>

View file

@ -1,9 +1,10 @@
---
import Button from '~/components/Button.astro'
import { Image } from 'astro:assets'
import Description from '~/components/Description.astro'
import Layout from '~/layouts/Layout.astro'
import { getLocale, getUI } from '~/utils/i18n'
export { getStaticPaths } from '~/utils/i18n'
import Button from '~/components/Button.astro'
const locale = getLocale(Astro)
@ -18,65 +19,67 @@ const {
description={layout.about.description}
>
<main
class="relative flex min-h-screen flex-col items-center justify-center py-24"
class="flex min-h-screen flex-col py-24 container w-full gap-24"
>
<div class="mb-24 p-4 text-center lg:w-1/2">
<Description class="text-6xl font-bold">{about.title}</Description>
<Description>
<div class="w-full flex flex-col gap-6">
<Description class="text-6xl font-bold leading-none">{about.title}</Description>
<Description class="max-w-4xl">
{about.description}
</Description>
<Button href="/donate" class="mx-auto mt-4 w-fit" isPrimary
<Button href="/donate" class="w-fit" isPrimary
>{about.littleHelp}</Button
>
</div>
<div
class="relative flex w-full flex-col items-center justify-center lg:flex-row"
>
<div class="flex flex-col p-8 lg:w-1/3 lg:pr-24">
<div class="text-4xl font-bold lg:text-6xl">{about.mainTeam.title}</div>
<div class="flex flex-col gap-4 w-full">
<div class="text-4xl lg:text-5xl font-bold leading-none">{about.mainTeam.title}</div>
<Description>
{about.mainTeam.description}
</Description>
<div class="mt-4">
<ul>
{Object.entries(about.mainTeam.members).map(([_key, member]) => (
<li class="text-sm">
{member.link ? (
<a href={member.link === true ? '' : member.link}>
<strong class="zen-link font-bold">{member.name}</strong>
</a>
<span class="opacity-60"> : {member.description}</span>
) : (
<strong class="font-bold">{member.name}</strong>
<span class="opacity-60"> : {member.description}</span>
)}
</li>
))}
</ul>
<div class="flex flex-col gap-6">
{Object.entries(about.mainTeam.members).map(([team, members]) => (
<div class="flex flex-col gap-2">
<div class="text-3xl font-semibold">{about.mainTeam.subTitle[team as keyof typeof about.mainTeam.subTitle]}</div>
<ul class="flex flex-col gap-2">
{Object.entries(members).map(([_key, member]) => (
<li class="text-sm">
{member.link && typeof member.link === 'string' ? (
<a href={member.link}>
<strong class="zen-link font-bold">{member.name}</strong>
</a>
) : (
<strong class="font-bold">{member.name}</strong>
)}
<span class="opacity-80">: {member.description}</span>
</li>
))}
</ul>
</div>
))}
</div>
</div>
<div class="absolute hidden h-full w-[1px] bg-dark opacity-15 lg:block">
</div>
<div class="flex flex-col p-8 lg:w-1/3 lg:pl-24">
<div class="text-4xl font-bold lg:text-6xl">{about.contributors.title}</div>
<div class="flex flex-col gap-4 w-full">
<div class="text-4xl lg:text-5xl font-bold leading-none">{about.contributors.title}</div>
<Description>
{about.contributors.description}
</Description>
<a href="https://github.com/zen-browser/desktop/graphs/contributors"
><img
<div class="flex flex-col gap-4 w-fit"><Description class="text-3xl font-semibold lg:text-4xl">{about.contributors.browser}</Description>
<a href="https://github.com/zen-browser/desktop/graphs/contributors"
><Image
src="https://contributors-img.web.app/image?repo=zen-browser/desktop"
alt="Contributors"
class="mt-8"
width={500}
height={500}
/></a
>
></div>
<div class="flex flex-col gap-4 w-fit"><Description class="text-3xl font-semibold lg:text-4xl">{about.contributors.website}</Description>
<a href="https://github.com/zen-browser/www/graphs/contributors"
><img
><Image
src="https://contributors-img.web.app/image?repo=zen-browser/www"
alt="Contributors (website)"
class="mt-8"
width={500}
height={500}
/></a
>
</div>
</div>
></div></div>
</main>
</Layout>

View file

@ -1,7 +1,7 @@
---
import { ArrowRight } from 'lucide-astro'
import Button from '~/components/Button.astro'
import Description from '~/components/Description.astro'
import ArrowRightIcon from '~/icons/ArrowRightIcon.astro'
import Layout from '~/layouts/Layout.astro'
import { getLocale, getUI } from '~/utils/i18n'
export { getStaticPaths } from '~/utils/i18n'
@ -14,51 +14,41 @@ const {
---
<Layout title={layout.donate.title} description={layout.donate.description}>
<main class="pb-52 pt-36">
<div
class="relative flex w-full flex-col items-center justify-center gap-12"
>
<div class="px-8 lg:w-2/5 lg:text-center xl:px-0">
<main class="container pb-52 pt-24 flex flex-col items-center gap-12">
<div class="flex flex-col gap-4 lg:text-center">
<Description class="text-6xl font-bold">{donate.title}</Description>
<Description>
<Description class="max-w-3xl">
{donate.description}
</Description>
</div>
<div class="flex w-full flex-col items-center justify-center lg:flex-row">
<div class="flex flex-col p-8 lg:w-1/3 lg:pr-24">
<div
class="grid max-w-5xl grid-cols-1 gap-12 text-center lg:grid-cols-[1fr_1px_1fr]"
>
<div class="flex flex-col items-center gap-4">
<div class="text-6xl font-bold">{donate.patreon.title}</div>
<Description>
{donate.patreon.description}
</Description>
<div class="mt-6">
<Button
isPrimary
href="https://www.patreon.com/zen_browser"
class="w-fit"
>
Go to Patreon
<ArrowRight class="size-4" />
</Button>
</div>
<Button
isPrimary
href="https://www.patreon.com/zen_browser"
class="w-fit"
>
{donate.patreon.button}
<ArrowRightIcon class="size-4" />
</Button>
</div>
<div class="hidden h-72 w-[1px] bg-dark opacity-15 lg:block"></div>
<div class="flex flex-col p-8 lg:w-1/3 lg:pl-24">
<hr class="hidden h-72 w-[1px] bg-dark opacity-15 lg:block" />
<div class="flex flex-col items-center gap-4">
<div class="text-6xl font-bold">{donate.koFi.title}</div>
<Description>
{donate.koFi.description}
</Description>
<div class="mt-6">
<Button
href="https://ko-fi.com/zen_browser"
isPrimary
class="w-fit"
>
{donate.koFi.button}
<ArrowRight class="size-4" />
</Button>
</div>
<Button href="https://ko-fi.com/zen_browser" isPrimary class="w-fit">
{donate.koFi.button}
<ArrowRightIcon class="size-4" />
</Button>
</div>
</div>
</div>
</main>
</Layout>

View file

@ -9,7 +9,8 @@ import { getLocale, getUI } from '~/utils/i18n'
import { icon, library } from '@fortawesome/fontawesome-svg-core'
import { faApple, faGithub, faLinux, faWindows } from '@fortawesome/free-brands-svg-icons'
import { ExternalLink, Lock } from 'lucide-astro'
import ExternalLinkIcon from '~/icons/ExternalLink.astro'
import LockIcon from '~/icons/LockIcon.astro'
export { getStaticPaths } from '~/utils/i18n'
@ -36,7 +37,7 @@ const platformDescriptions = download.platformDescriptions
<Layout title={layout.download.title} description={layout.download.description}>
<main class="flex min-h-screen flex-col px-6 data-[os='windows']:bg-zen-blue">
<div class="container relative mx-auto max-w-5xl py-12">
<div class="container relative mx-auto py-12">
<div class="mb-6 mt-12 flex flex-col gap-4">
<Description id="download-title" class="text-6xl font-bold"
>{download.title}</Description
@ -180,7 +181,7 @@ const platformDescriptions = download.platformDescriptions
<div
class="rounded-xl border border-subtle p-3 transition-all duration-100 hover:bg-coral hover:bg-opacity-10 group-hover:border-coral group-hover:border-opacity-20"
>
<ExternalLink
<ExternalLinkIcon
class="h-5 w-5 transition-all duration-200 group-hover:text-coral"
/>
</div>
@ -194,7 +195,7 @@ const platformDescriptions = download.platformDescriptions
class="bg-opaicty-10 grid grid-cols-[auto,1fr] gap-4 rounded-2xl bg-subtle p-6"
>
<div class="h-fit rounded-xl bg-subtle p-3">
<Lock class="h-5 w-5" />
<LockIcon class="h-5 w-5" />
</div>
<div>

View file

@ -17,7 +17,7 @@ const { layout } = getUI(locale)
description={layout.index.description}
isHome
>
<main>
<main class="container">
<Hero />
<Features />
<Sponsors showSponsors />

View file

@ -1,8 +1,9 @@
---
import { ArrowRight, Info } from 'lucide-astro'
import BackButton from '~/components/BackButton.astro'
import Button from '~/components/Button.astro'
import Description from '~/components/Description.astro'
import ArrowRightIcon from '~/icons/ArrowRightIcon.astro'
import InfoIcon from '~/icons/InfoIcon.astro'
import Layout from '~/layouts/Layout.astro'
import { getAllMods, getAuthorLink, getLocalizedDate } from '~/mods'
import { getUI } from '~/utils/i18n'
@ -64,7 +65,7 @@ const {
class="flex flex-col items-center justify-center gap-2 rounded-xl bg-red-200 p-2 px-4 md:flex-row md:justify-between dark:bg-red-700"
>
<div class="flex items-center gap-2 text-center md:text-left">
<Info />
<InfoIcon />
<p class="text-sm">
{slug.alert.description}
</p>
@ -75,7 +76,7 @@ const {
isAlert
>
{slug.alert.button}
<ArrowRight class="size-4" />
<ArrowRightIcon class="size-4" />
</Button>
</div>
<BackButton />

View file

@ -18,16 +18,12 @@ const allMods = (await getAllMods()) || []
---
<Layout title={layout.mods.title}>
<main class="mx-auto mt-32 max-w-[120rem] 2xl:mt-0">
<header class="mb-10 mt-32 flex w-full flex-col justify-center border-dark">
<div class="mx-auto flex flex-col gap-6 px-8 lg:w-1/2">
<div>
<Description class="text-6xl font-bold">{mods.title}</Description>
<Description>
{mods.description}
</Description>
</div>
</div>
<main class="container mt-32 flex flex-col gap-10 2xl:mt-32">
<header class="flex w-full flex-col gap-8 border-dark">
<Description class="text-6xl font-bold">{mods.title}</Description>
<Description class="max-w-3xl">
{mods.description}
</Description>
</header>
<!-- Importing ModList component -->

View file

@ -1,9 +1,9 @@
---
import { Modal, ModalBody, ModalHeader } from 'free-astro-components'
import { ArrowUp } from 'lucide-astro'
import Button from '~/components/Button.astro'
import Description from '~/components/Description.astro'
import ReleaseNoteItem from '~/components/ReleaseNoteItem.astro'
import ArrowUpIcon from '~/icons/ArrowUp.astro'
import Layout from '~/layouts/Layout.astro'
import { releaseNotes as releaseNotesData, releaseNotesTwilight } from '~/release-notes'
import { getLocale, getUI } from '~/utils/i18n'
@ -19,11 +19,11 @@ const {
<Layout title={layout.releaseNotes.title}>
<main
class="flex h-full min-h-[1000px] flex-1 flex-col items-center justify-center py-4"
class="container flex h-full min-h-[1000px] flex-1 flex-col items-center justify-center py-4"
>
<div
id="release-notes"
class="py-42 flex min-h-screen flex-col justify-center px-10 lg:px-10 xl:px-10 2xl:w-3/5"
class="py-42 flex min-h-screen w-full flex-col justify-center"
>
<Description class="mt-48 text-4xl font-bold">Release Notes</Description>
<p
@ -58,9 +58,9 @@ const {
<Button href="#" id="scroll-top" isPrimary class="fixed bottom-8 right-8">
<p class="hidden items-center gap-2 sm:flex">
{releaseNotes.backToTop}
<ArrowUp aria-hidden="true" class="size-4" />
<ArrowUpIcon aria-hidden="true" class="size-4" />
</p>
<ArrowUp aria-label="Back to the top" class="size-4 sm:hidden" />
<ArrowUpIcon aria-label="Back to the top" class="size-4 sm:hidden" />
</Button>
</Layout>
<Modal id="version-modal" class="m-auto border border-[--zen-dark] !bg-paper">

View file

@ -13,9 +13,7 @@ const {
---
<Layout title={layout.welcome.title} description={layout.welcome.description}>
<main
class="relative mx-auto flex flex-col items-center gap-24 px-6 lg:gap-0 lg:px-24"
>
<main class="container">
<Features
title1={welcome.title[0]}
title2={welcome.title[1]}

View file

@ -1,8 +1,8 @@
---
import { ArrowRight } from 'lucide-astro'
import Button from '~/components/Button.astro'
import Description from '~/components/Description.astro'
import SocialMediaStrip from '~/components/SocialMediaStrip.astro'
import ArrowRightIcon from '~/icons/ArrowRightIcon.astro'
import Layout from '~/layouts/Layout.astro'
import whatsNewVideo from '~/assets/whats-new.mp4'
@ -34,7 +34,7 @@ if (latestVersion.version.split('.').length > 2 && whatsNewText[1] !== latestVer
)}
>
<main
class="relative mx-auto flex flex-col items-center gap-24 px-6 pb-52 pt-36 lg:px-24 xl:flex-row"
class="xl:mt-22 container flex flex-col gap-12 py-12 xl:grid xl:min-h-[calc(100vh-12rem)] xl:grid-cols-[2fr_3fr]"
>
<div class="flex flex-col gap-8">
<div>
@ -51,37 +51,38 @@ if (latestVersion.version.split('.').length > 2 && whatsNewText[1] !== latestVer
<div>
<Fragment set:html={whatsNewText[0].replace(/\n/g, '<br>')} />
</div>
<ul class="hidden flex-col gap-2 md:flex">
<ul class="hidden list-disc flex-col gap-2 xl:container xl:flex">
<a
href="https://github.com/zen-browser/desktop/issues/new/choose"
target="_blank"
>
<li class="ml-3 list-disc">
<Description class="text-base font-bold"
>{whatsNew.reportIssue}</Description
>
<li>
<Description class="text-base font-bold">
{whatsNew.reportIssue}
</Description>
</li>
</a>
<a href="https://discord.gg/zen-browser" target="_blank">
<li class="ml-3 list-disc">
<Description class="text-base font-bold"
>{whatsNew.joinDiscord}</Description
>
<li>
<Description class="text-base font-bold">
{whatsNew.joinDiscord}
</Description>
</li>
</a>
</ul>
<div class="flex flex-col gap-8 md:flex-row">
<div class="flex flex-wrap gap-8 place-self-start xl:place-self-center">
<Button
href={`/release-notes#${latestVersion.version}`}
isPrimary
class="flex w-fit items-center gap-2"
>
<span>{whatsNew.readFullReleaseNotes}</span>
<ArrowRight />
<ArrowRightIcon />
</Button>
<SocialMediaStrip gap="6" />
</div>
</div>
<Video
src={whatsNewVideo}
autoplay
@ -89,7 +90,7 @@ if (latestVersion.version.split('.').length > 2 && whatsNewText[1] !== latestVer
muted
playsinline
preload="none"
class="w-full rounded-3xl object-cover shadow-lg"
class="rounded-3xl object-cover shadow-lg"
/>
</main>
</Layout>

View file

@ -3,6 +3,32 @@ export default {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
darkMode: ['selector', '[data-theme="dark"]'],
theme: {
container: {
screens: {
sm: '100%',
md: '100%',
lg: '1024px',
xl: '1280px',
},
padding: {
DEFAULT: '1rem',
sm: '1.5rem',
md: '1.5rem',
lg: '1.5rem',
xl: '2rem',
},
center: true,
},
fontFamily: {
junicode: [
'Junicode, serif',
{
fontFeatureSettings: {
swsh: 1,
},
},
],
},
extend: {
screens: {
'-sm': '@media (max-width: 639px)',