Drop Cookies Settings from the footer, link the Home features that already have pages, and give leftover routes their own descriptions.
230 lines
9.6 KiB
TypeScript
230 lines
9.6 KiB
TypeScript
"use client";
|
|
|
|
import { memo } from "react";
|
|
import { useTranslation } from "../../contexts/MessagesContext";
|
|
import Link from "next/link";
|
|
import Logo from "../asset/Logo";
|
|
import Divider from "../utility/Divider";
|
|
import { getAssetPath, ASSETS } from "../../../lib/assetUtils";
|
|
import { PRODUCTION_SITE_ORIGIN } from "../../../lib/siteMetadata";
|
|
|
|
/**
|
|
* Figma: "Navigation / Footer" (18411-62917).
|
|
* Tiers: smallest viewports (below `md`), `md` through `lg`, `lg` and up.
|
|
* Matches `--breakpoint-md: 640px`, `--breakpoint-lg: 1024px` in `app/tailwind.css`.
|
|
*/
|
|
const Footer = memo(({ siteOrigin = PRODUCTION_SITE_ORIGIN }: { siteOrigin?: string }) => {
|
|
const t = useTranslation("footer");
|
|
const tChrome = useTranslation("controlsChrome");
|
|
|
|
const linkFocusClass =
|
|
"touch-manipulation [-webkit-tap-highlight-color:transparent] hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-primary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity duration-150 ease-out";
|
|
|
|
const bodyTextClass =
|
|
"text-[var(--color-content-default-primary)] text-medium-label lg:text-x-large-label";
|
|
|
|
/** Figma 18411:62925 (1024+): org name is one line, `w-full whitespace-nowrap`. */
|
|
const orgNameClass = `${bodyTextClass} lg:whitespace-nowrap`;
|
|
|
|
const primaryLinkClass = `inline-flex w-fit max-w-full shrink-0 whitespace-nowrap self-start md:ml-auto md:self-end text-left md:text-right md:justify-end text-[var(--color-content-default-primary)] text-medium-label ${linkFocusClass} p-2 -m-2 cursor-pointer lg:text-x-large-label`;
|
|
|
|
/** Figma 18411:62944: 40px gaps, w-[396px] link block; `p-2` on links overruns 396px—tighten x at `md+` row. */
|
|
const legalLinkClass = `inline-flex w-fit max-w-full self-start text-[var(--color-content-default-secondary)] text-small-paragraph ${linkFocusClass} p-2 -m-2 cursor-pointer underline decoration-solid [text-decoration-skip-ink:none] md:self-auto md:px-0 md:py-1 md:mx-0 md:text-x-small-paragraph md:whitespace-nowrap md:no-underline md:text-[var(--color-content-default-primary)] lg:text-small-paragraph lg:text-[var(--color-content-default-primary)]`;
|
|
|
|
// Schema markup for organization information
|
|
const schemaData = {
|
|
"@context": "https://schema.org",
|
|
"@type": "Organization",
|
|
name: t("organization.name"),
|
|
email: t("organization.email"),
|
|
url: siteOrigin,
|
|
sameAs: [
|
|
t("social.bluesky.url"),
|
|
t("social.gitea.url"),
|
|
t("social.mastodon.url"),
|
|
],
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaData) }}
|
|
/>
|
|
<footer className="bg-[var(--color-surface-default-primary)] w-full">
|
|
<div
|
|
className="mx-auto flex max-w-[1920px] flex-col
|
|
gap-[var(--space-1000)]
|
|
px-[var(--space-400)]
|
|
py-[var(--space-1000)]
|
|
md:gap-[var(--space-600)]
|
|
md:px-[var(--space-800)]
|
|
md:py-[var(--space-600)]
|
|
lg:gap-[var(--space-1500)]
|
|
lg:px-[var(--space-1800)]
|
|
lg:py-[var(--space-2400)]"
|
|
>
|
|
<div
|
|
className="flex w-full flex-col
|
|
gap-[var(--space-800)]
|
|
md:gap-[var(--space-1200)]
|
|
lg:gap-[var(--space-1500)]"
|
|
>
|
|
<Logo size="footer" wordmark />
|
|
|
|
<div
|
|
className="flex w-full flex-col
|
|
gap-[var(--space-1200)]
|
|
md:flex-row md:items-start md:justify-between md:gap-0"
|
|
>
|
|
<div
|
|
className="order-2 flex flex-col
|
|
gap-[var(--space-1200)]
|
|
md:order-1 md:max-w-[min(100%,334px)]
|
|
lg:max-w-[min(100%,334px)]
|
|
lg:gap-[var(--space-1800)]"
|
|
>
|
|
<div
|
|
className="flex flex-col
|
|
gap-[var(--space-400)]"
|
|
>
|
|
<div className={orgNameClass}>{t("organization.name")}</div>
|
|
<a
|
|
href={`mailto:${t("organization.email")}`}
|
|
className={`inline-flex w-fit max-w-full ${bodyTextClass} ${linkFocusClass} p-2 -m-2 cursor-pointer`}
|
|
>
|
|
{t("organization.email")}
|
|
</a>
|
|
</div>
|
|
|
|
<div
|
|
className="flex flex-col
|
|
gap-[var(--space-400)]"
|
|
>
|
|
<a
|
|
href={t("social.bluesky.url")}
|
|
className={`group inline-flex w-fit max-w-full items-center gap-[var(--space-150)] ${linkFocusClass} p-2 -m-2 cursor-pointer`}
|
|
aria-label={t("social.bluesky.ariaLabel")}
|
|
>
|
|
{/* eslint-disable-next-line @next/next/no-img-element -- social logo */}
|
|
<img
|
|
src={getAssetPath(ASSETS.BLUESKY_LOGO)}
|
|
alt=""
|
|
width={24}
|
|
height={22}
|
|
className="h-[21px] w-[24px] flex-shrink-0 transition-transform group-hover:scale-110"
|
|
/>
|
|
<div className={bodyTextClass}>{t("social.bluesky.label")}</div>
|
|
</a>
|
|
<a
|
|
href={t("social.gitea.url")}
|
|
className={`group inline-flex w-fit max-w-full items-center gap-[var(--space-150)] ${linkFocusClass} p-2 -m-2 cursor-pointer`}
|
|
aria-label={t("social.gitea.ariaLabel")}
|
|
>
|
|
{/* eslint-disable-next-line @next/next/no-img-element -- social icon */}
|
|
<img
|
|
src={getAssetPath(ASSETS.GITEA_ICON)}
|
|
alt=""
|
|
width={22}
|
|
height={22}
|
|
className="h-5 w-[22px] flex-shrink-0 grayscale transition-transform group-hover:scale-110"
|
|
/>
|
|
<div className={bodyTextClass}>{t("social.gitea.label")}</div>
|
|
</a>
|
|
<a
|
|
href={t("social.mastodon.url")}
|
|
className={`group inline-flex w-fit max-w-full items-center gap-[var(--space-150)] ${linkFocusClass} p-2 -m-2 cursor-pointer`}
|
|
aria-label={t("social.mastodon.ariaLabel")}
|
|
>
|
|
{/* eslint-disable-next-line @next/next/no-img-element -- social icon */}
|
|
<img
|
|
src={getAssetPath(ASSETS.MASTODON_LOGO)}
|
|
alt=""
|
|
width={22}
|
|
height={22}
|
|
className="h-5 w-[22px] flex-shrink-0 grayscale transition-transform group-hover:scale-110"
|
|
/>
|
|
<div className={bodyTextClass}>{t("social.mastodon.label")}</div>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Figma 18411:62937: column on the right, labels text-right at md+. Mobile stays start-aligned. */}
|
|
<nav
|
|
aria-label={tChrome("footerAriaLabel")}
|
|
className="order-1 flex w-full max-w-full flex-col
|
|
items-start
|
|
gap-[var(--space-800)]
|
|
md:order-2 md:ml-auto md:w-auto md:items-end md:text-right
|
|
md:gap-[var(--space-800)]"
|
|
>
|
|
<Link href="/use-cases" className={primaryLinkClass}>
|
|
{t("navigation.useCases")}
|
|
</Link>
|
|
<Link href="/learn" className={primaryLinkClass}>
|
|
{t("navigation.learn")}
|
|
</Link>
|
|
<Link href="/about" className={primaryLinkClass}>
|
|
{t("navigation.about")}
|
|
</Link>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
<Divider />
|
|
|
|
<div
|
|
className="flex w-full flex-col
|
|
gap-[var(--space-800)]
|
|
text-[var(--color-content-default-primary)]
|
|
md:flex-row md:items-start md:justify-between md:gap-[var(--space-1000)]
|
|
md:whitespace-nowrap
|
|
md:text-x-small-paragraph
|
|
lg:text-small-paragraph"
|
|
>
|
|
<p
|
|
className="w-full text-small-paragraph
|
|
text-[var(--color-content-default-secondary)]
|
|
md:w-auto
|
|
md:text-x-small-paragraph
|
|
lg:text-small-paragraph"
|
|
>
|
|
<a
|
|
href={t("license.href")}
|
|
rel="license"
|
|
className={`${linkFocusClass} p-2 -m-2 cursor-pointer`}
|
|
>
|
|
{t("license.label")}
|
|
</a>
|
|
</p>
|
|
<div
|
|
className="flex w-full min-w-0 flex-col flex-wrap
|
|
gap-[var(--space-800)]
|
|
text-small-paragraph
|
|
text-[var(--color-content-default-primary)]
|
|
md:max-w-[min(100%,396px)]
|
|
md:flex-row md:flex-nowrap md:content-center md:items-center md:justify-end
|
|
md:gap-[var(--space-1000)]
|
|
md:text-x-small-paragraph
|
|
lg:max-w-none
|
|
lg:gap-10
|
|
lg:text-small-paragraph"
|
|
>
|
|
<Link href={t("legal.privacyPolicyHref")} className={legalLinkClass}>
|
|
{t("legal.privacyPolicy")}
|
|
</Link>
|
|
<Link href={t("legal.termsOfServiceHref")} className={legalLinkClass}>
|
|
{t("legal.termsOfService")}
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
</>
|
|
);
|
|
});
|
|
|
|
Footer.displayName = "Footer";
|
|
|
|
export default Footer;
|