website: add a GitHub social button to the site's header

This commit is contained in:
Adorian Doran 2025-10-03 19:09:23 +03:00
parent 30f530abdb
commit 7657e17373
4 changed files with 47 additions and 13 deletions

View File

@ -55,7 +55,7 @@ export function SocialButtons({ className, withText }: { className?: string, wit
)
}
function SocialButton({ name, iconSvg, url, withText }: { name: string, iconSvg: string, url: string, withText?: boolean }) {
export function SocialButton({ name, iconSvg, url, withText, counter }: { name: string, iconSvg: string, url: string, withText?: boolean, counter?: string | undefined }) {
return (
<Link
className="social-button"
@ -63,7 +63,9 @@ function SocialButton({ name, iconSvg, url, withText }: { name: string, iconSvg:
title={!withText ? name : undefined}
>
<Icon svg={iconSvg} />
{counter && <span class="counter">{counter}</span>}
{withText && name}
</Link>
)
}

View File

@ -1,12 +1,13 @@
import "./Header.css";
import { Link } from "./Button.js";
import { SocialButtons, SocialButton } from "./Footer.js";
import { useEffect, useMemo, useState } from "preact/hooks";
import { useLocation } from 'preact-iso';
import DownloadButton from './DownloadButton.js';
import { Link } from "./Button.js";
import githubIcon from "../assets/boxicons/bx-github.svg?raw";
import Icon from "./Icon.js";
import logoPath from "../assets/icon-color.svg";
import menuIcon from "../assets/boxicons/bx-menu.svg?raw";
import { useState } from "preact/hooks";
import { SocialButtons } from "./Footer.js";
interface HeaderLink {
url: string;
@ -20,7 +21,7 @@ const HEADER_LINKS: HeaderLink[] = [
{ url: "/support-us/", text: "Support us" }
]
export function Header() {
export function Header(props: {repoStargazersCount: number}) {
const { url } = useLocation();
const [ mobileMenuShown, setMobileMenuShown ] = useState(false);
@ -60,6 +61,16 @@ export function Header() {
</nav>
<DownloadButton />
<div class="desktop-only">
<SocialButton
name="GitHub"
iconSvg={githubIcon}
counter={(props.repoStargazersCount / 1000).toFixed(1) + "K+"}
url="https://github.com/TriliumNext/Trilium"
/>
</div>
</div>
</header>
);

View File

@ -0,0 +1,15 @@
const API_URL = "https://api.github.com/repos/TriliumNext/Trilium";
/** Returns the number of stargazers of the Trilium's GitHub repository. */
export async function getRepoStargazersCount() {
const response = await fetch(API_URL);
if (response.ok) {
const details = await response.json();
if ("stargazers_count" in details) {
return details["stargazers_count"];
}
}
return 31862; // The count as of 2025-10-03
}

View File

@ -1,17 +1,17 @@
import { LocationProvider, Router, Route, hydrate, prerender as ssr } from 'preact-iso';
import './style.css';
import { getRepoStargazersCount } from './github-utils.js';
import { Header } from './components/Header.jsx';
import { Home } from './pages/Home/index.jsx';
import { LocationProvider, Router, Route, hydrate, prerender as ssr } from 'preact-iso';
import { NotFound } from './pages/_404.jsx';
import './style.css';
import Footer from './components/Footer.js';
import GetStarted from './pages/GetStarted/get-started.js';
import SupportUs from './pages/SupportUs/SupportUs.js';
export function App() {
export function App(props: {repoStargazersCount: number}) {
return (
<LocationProvider>
<Header />
<Header repoStargazersCount={props.repoStargazersCount} />
<main>
<Router>
<Route path="/" component={Home} />
@ -26,9 +26,15 @@ export function App() {
}
if (typeof window !== 'undefined') {
hydrate(<App />, document.getElementById('app')!);
hydrate(<App repoStargazersCount={1000} />, document.getElementById('app')!);
}
export async function prerender(data) {
return await ssr(<App {...data} />);
// Fetch the stargazer count of the Trilium's GitHub repo on prerender to pass
// it to the App component for SSR.
// This ensures the GitHub API is not called on every page load in the client.
const stargazersCount = await getRepoStargazersCount();
return await ssr(<App repoStargazersCount={stargazersCount} {...data} />);
}