refactor(website): simplify landing page (helpers, types, data-driven blocks) by Jocs · Pull Request #4350 · marktext/marktext · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions packages/website/src/app/globals.css
8 changes: 4 additions & 4 deletions packages/website/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Metadata, Viewport } from 'next'
import { Geist, Geist_Mono } from 'next/font/google'
import { THEME_STORAGE_KEY } from '@/lib/sections'
import { DEFAULT_THEME, THEME_STORAGE_KEY } from '@/lib/sections'
import './globals.css'

const geistSans = Geist({
Expand Down Expand Up @@ -85,12 +85,12 @@ const jsonLd = {
softwareVersion: 'latest'
}

// Inline before paint to avoid theme flash; mirrors useTheme's storage key.
const themeBootstrap = `(function(){try{var t=localStorage.getItem(${JSON.stringify(THEME_STORAGE_KEY)});if(!t)t='dark';document.documentElement.setAttribute('data-theme',t);}catch(e){document.documentElement.setAttribute('data-theme','dark');}})();`
// Inline before paint to avoid theme flash.
const themeBootstrap = `(function(){try{var t=localStorage.getItem(${JSON.stringify(THEME_STORAGE_KEY)});if(!t)t=${JSON.stringify(DEFAULT_THEME)};document.documentElement.setAttribute('data-theme',t);}catch(e){document.documentElement.setAttribute('data-theme',${JSON.stringify(DEFAULT_THEME)});}})();`

export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" data-theme="dark" className={`${geistSans.variable} ${geistMono.variable}`}>
<html lang="en" data-theme={DEFAULT_THEME} className={`${geistSans.variable} ${geistMono.variable}`}>
<head>
<script dangerouslySetInnerHTML={{ __html: themeBootstrap }} />
</head>
Expand Down
10 changes: 10 additions & 0 deletions packages/website/src/components/Brand.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { SECTIONS, hash } from '@/lib/sections'

export default function Brand() {
return (
<a className="brand" href={hash(SECTIONS.top)}>
<img className="mark" src="/assets/logo.png" alt="MarkText logo" width={28} height={28} />
MarkText
</a>
)
}
48 changes: 22 additions & 26 deletions packages/website/src/components/Download.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,40 @@
import type { ReactNode } from 'react'
import { DOWNLOAD } from '@/lib/downloads'
import { EXT_LINK } from '@/lib/links'
import { SECTIONS } from '@/lib/sections'
import { LinuxIcon, MacIcon, WindowsIcon } from './Icons'

type Platform = { icon: ReactNode; label: string; sub: string }

const PLATFORMS: Platform[] = [
{ icon: <MacIcon />, label: 'macOS', sub: '.dmg · Apple Silicon & Intel' },
{ icon: <WindowsIcon />, label: 'Windows', sub: '.exe · x64 & ARM64' },
{ icon: <LinuxIcon />, label: 'Linux', sub: '.AppImage · .deb · .rpm' }
]

export default function Download() {
return (
<section className="block" id={SECTIONS.download.slice(1)}>
<section className="block" id={SECTIONS.download}>
<div className="wrap">
<div className="cta reveal">
<div className="cta-glow" />
<span className="kicker" style={{ justifyContent: 'center' }}>
Free download
</span>
<span className="kicker kicker--center">Free download</span>
<h2>
Start writing in <span className="grad-text">two minutes</span>.
</h2>
<p>One download. No account, no subscription. Every desktop you write on.</p>
<div className="platforms">
<a className="plat" href={DOWNLOAD.releases} target="_blank" rel="noopener noreferrer">
<MacIcon />
<div>
<b>macOS</b>
<span>.dmg · Apple Silicon &amp; Intel</span>
</div>
</a>
<a className="plat" href={DOWNLOAD.releases} target="_blank" rel="noopener noreferrer">
<WindowsIcon />
<div>
<b>Windows</b>
<span>.exe · x64 &amp; ARM64</span>
</div>
</a>
<a className="plat" href={DOWNLOAD.releases} target="_blank" rel="noopener noreferrer">
<LinuxIcon />
<div>
<b>Linux</b>
<span>.AppImage · .deb · .rpm</span>
</div>
</a>
{PLATFORMS.map((p) => (
<a className="plat" key={p.label} href={DOWNLOAD.releases} {...EXT_LINK}>
{p.icon}
<div>
<b>{p.label}</b>
<span>{p.sub}</span>
</div>
</a>
))}
</div>
<div className="hero-note" style={{ marginTop: 24 }}>
<div className="hero-note hero-note--cta">
<span>
Or install via Homebrew: <code className="inline">brew install --cask mark-text</code>
</span>
Expand Down
8 changes: 4 additions & 4 deletions packages/website/src/components/Extensions.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ReactNode } from 'react'
import { SECTIONS } from '@/lib/sections'
import { SECTIONS, type RevealDelay } from '@/lib/sections'
import FeatureCard from './FeatureCard'
import {
CodeIcon,
Expand All @@ -15,7 +15,7 @@ type Card = {
title: string
description: string
mini: ReactNode
delay?: 'd1' | 'd2'
delay?: RevealDelay
}

const CARDS: Card[] = [
Expand Down Expand Up @@ -113,7 +113,7 @@ const CARDS: Card[] = [

export default function Extensions() {
return (
<section className="block" id={SECTIONS.extensions.slice(1)}>
<section className="block" id={SECTIONS.extensions}>
<div className="wrap">
<div className="sec-head center reveal">
<span className="kicker">Markdown, extended</span>
Expand All @@ -126,10 +126,10 @@ export default function Extensions() {
{CARDS.map((c) => (
<FeatureCard
key={c.title}
className={`card reveal${c.delay ? ` ${c.delay}` : ''}`}
icon={c.icon}
title={c.title}
description={c.description}
delay={c.delay}
>
<div className="mini">{c.mini}</div>
</FeatureCard>
Expand Down
5 changes: 3 additions & 2 deletions packages/website/src/components/FeatItem.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import type { ReactNode } from 'react'
import { revealClass, type RevealDelay } from '@/lib/sections'

type Props = {
icon: ReactNode
title: ReactNode
description: ReactNode
delay?: 'd1' | 'd2' | 'd3' | 'd4'
delay?: RevealDelay
}

export default function FeatItem({ icon, title, description, delay }: Props) {
return (
<div className={`feat-item reveal${delay ? ` ${delay}` : ''}`}>
<div className={revealClass(delay, 'feat-item')}>
<div className="ic">{icon}</div>
<div>
<h4>{title}</h4>
Expand Down
27 changes: 9 additions & 18 deletions packages/website/src/components/FeatureCard.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,22 @@
import type { CSSProperties, ReactNode } from 'react'
import type { ReactNode } from 'react'
import { revealClass, type RevealDelay } from '@/lib/sections'

type Props = {
icon: ReactNode
title: ReactNode
description: ReactNode
className?: string
style?: CSSProperties
titleStyle?: CSSProperties
descStyle?: CSSProperties
delay?: RevealDelay
variant?: 'lg'
children?: ReactNode
}

export default function FeatureCard({
icon,
title,
description,
className = 'card reveal',
style,
titleStyle,
descStyle,
children
}: Props) {
export default function FeatureCard({ icon, title, description, delay, variant, children }: Props) {
const base = variant === 'lg' ? 'card card--lg' : 'card'
return (
<div className={className} style={style}>
<div className={revealClass(delay, base)}>
<div className="ic-lg">{icon}</div>
<h3 style={titleStyle}>{title}</h3>
<p style={descStyle}>{description}</p>
<h3>{title}</h3>
<p>{description}</p>
{children}
</div>
)
Expand Down
29 changes: 9 additions & 20 deletions packages/website/src/components/FocusExport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@ export default function FocusExport() {
return (
<section className="block">
<div className="wrap">
<div className="grid-3" style={{ gridTemplateColumns: '1fr 1fr' }}>
<div className="grid-3 grid-2">
<FeatureCard
className="card reveal"
style={{ padding: 34 }}
variant="lg"
icon={<TargetIcon />}
title="Focus & typewriter mode"
titleStyle={{ fontSize: 21 }}
description="Dim everything but the line you're writing, and keep it locked to center. Distraction-free by design."
descStyle={{ fontSize: 15 }}
>
<div className="mini" style={{ fontSize: 13, lineHeight: 1.8 }}>
<div className="mini mini--lg">
<span style={{ opacity: 0.3 }}>The paragraph above fades back.</span>
<br />
<span style={{ color: 'var(--text)' }}>
Expand All @@ -28,29 +25,21 @@ export default function FocusExport() {
</FeatureCard>

<FeatureCard
className="card reveal d1"
style={{ padding: 34 }}
variant="lg"
delay="d1"
icon={<ExportIcon />}
title="Export anywhere"
titleStyle={{ fontSize: 21 }}
description={
<>
Turn any document into a polished <strong>PDF</strong> or self-contained{' '}
<strong>HTML</strong> file — your theme included.
</>
}
descStyle={{ fontSize: 15 }}
>
<div className="platforms" style={{ justifyContent: 'flex-start', marginTop: 16 }}>
<div className="plat" style={{ minWidth: 0, padding: '12px 18px' }}>
<b style={{ fontSize: 14 }}>PDF</b>
</div>
<div className="plat" style={{ minWidth: 0, padding: '12px 18px' }}>
<b style={{ fontSize: 14 }}>HTML</b>
</div>
<div className="plat" style={{ minWidth: 0, padding: '12px 18px' }}>
<b style={{ fontSize: 14 }}>.md</b>
</div>
<div className="platforms platforms--start">
<div className="plat plat--compact"><b>PDF</b></div>
<div className="plat plat--compact"><b>HTML</b></div>
<div className="plat plat--compact"><b>.md</b></div>
</div>
</FeatureCard>
</div>
Expand Down
47 changes: 15 additions & 32 deletions packages/website/src/components/Footer.tsx
Loading
Loading