SPB Git forge

spb/fetcha

Public
11commits 1branches 0releases
1.5 MBsize
maindefault branch
16 days agolast push
TypeScript 97.5% SQL 1.4% Python 0.8%
4.7 KB · 87 lines tsx
Raw Blame History
1import * as React from "react";2import Link from "next/link";3import { cn } from "@/lib/utils";45export const LEGAL_VERSION = "2026-09-07";6export const LEGAL_EFFECTIVE = "2026-09-07";78export type LegalSection = { id: string; title: string; body: React.ReactNode };910const OTHER_DOCS: Array<[string, string]> = [11  ["Terms of Service", "/legal/terms"],12  ["Privacy Policy", "/legal/privacy"],13  ["Acceptable Use Policy", "/legal/acceptable-use"],14  ["Data Processing Addendum", "/legal/dpa"],15  ["Cookie Policy", "/legal/cookies"],16];1718/** Prose styling without @tailwindcss/typography. Applied to each section body. */19export const legalProse = cn(20  "text-[15px] leading-[1.7] text-fg-muted",21  "[&_p]:mt-3.5 [&_p:first-child]:mt-0",22  "[&_h3]:mt-6 [&_h3]:text-[15px] [&_h3]:font-semibold [&_h3]:text-fg [&_h3]:tracking-tight",23  "[&_ul]:mt-3.5 [&_ul]:list-disc [&_ul]:pl-5 [&_ol]:mt-3.5 [&_ol]:list-decimal [&_ol]:pl-5 [&_li]:mt-1.5 [&_li]:pl-0.5",24  "[&_a]:text-accent [&_a]:underline-offset-4 hover:[&_a]:underline",25  "[&_strong]:font-semibold [&_strong]:text-fg",26  "[&_code]:rounded-[4px] [&_code]:border [&_code]:border-border [&_code]:bg-bg-muted [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-[0.85em] [&_code]:text-fg",27  "[&_table]:mt-4 [&_table]:w-full [&_table]:text-[13.5px] [&_th]:border-b [&_th]:border-border [&_th]:py-2 [&_th]:pr-4 [&_th]:text-left [&_th]:text-[11.5px] [&_th]:font-medium [&_th]:uppercase [&_th]:tracking-wide [&_th]:text-fg-subtle [&_td]:border-b [&_td]:border-border [&_td]:py-2 [&_td]:pr-4 [&_td]:align-top",28);2930export function LegalLayout({ title, summary, current, sections }: { title: string; summary: string; current: string; sections: LegalSection[] }) {31  return (32    <div className="container-page py-12 sm:py-16">33      <header className="max-w-3xl">34        <p className="text-[11.5px] font-medium uppercase tracking-wide text-fg-subtle">Legal</p>35        <h1 className="mt-2 text-3xl font-semibold tracking-tight sm:text-[36px]">{title}</h1>36        <p className="mt-3 font-mono text-[12.5px] text-fg-subtle">37          Version {LEGAL_VERSION} · Effective {LEGAL_EFFECTIVE}38        </p>39        <p className="mt-5 text-[15.5px] leading-relaxed text-fg-muted">{summary}</p>40      </header>4142      <div className="mt-10 grid gap-10 lg:grid-cols-[220px_minmax(0,1fr)] lg:gap-16">43        <aside className="lg:sticky lg:top-20 lg:self-start">44          <nav aria-label="Table of contents" className="rounded-lg border border-border bg-bg-subtle/60 p-4 lg:border-0 lg:bg-transparent lg:p-0">45            <h2 className="text-[11.5px] font-semibold uppercase tracking-wide text-fg-subtle">On this page</h2>46            <ol className="mt-3 space-y-1.5 text-[13px]">47              {sections.map((s, i) => (48                <li key={s.id} className="flex gap-2">49                  <span className="w-5 shrink-0 font-mono tabular text-fg-subtle">{i + 1}.</span>50                  <a href={`#${s.id}`} className="text-fg-muted transition-colors hover:text-fg">51                    {s.title}52                  </a>53                </li>54              ))}55            </ol>56            <h2 className="mt-6 text-[11.5px] font-semibold uppercase tracking-wide text-fg-subtle">Other documents</h2>57            <ul className="mt-3 space-y-1.5 text-[13px]">58              {OTHER_DOCS.filter(([, href]) => href !== current).map(([label, href]) => (59                <li key={href}>60                  <Link href={href} className="text-fg-muted transition-colors hover:text-fg">61                    {label}62                  </Link>63                </li>64              ))}65            </ul>66          </nav>67        </aside>6869        <article className="min-w-0 max-w-3xl">70          {sections.map((s, i) => (71            <section key={s.id} id={s.id} className="scroll-mt-24 border-t border-border py-8 first:border-t-0 first:pt-0">72              <h2 className="text-[20px] font-semibold tracking-tight text-fg">73                <span className="mr-2 font-mono text-[14px] font-medium text-fg-subtle tabular">{i + 1}.</span>74                {s.title}75              </h2>76              <div className={cn("mt-4", legalProse)}>{s.body}</div>77            </section>78          ))}79          <footer className="mt-4 rounded-lg border border-border bg-bg-subtle/60 p-5 text-[13.5px] leading-relaxed text-fg-muted">80            Questions about this document? Write to <a className="text-accent underline-offset-4 hover:underline" href="mailto:legal@fetcha.co">legal@fetcha.co</a>. Previous versions are available on request. We will post material changes on this page and, for changes that reduce your rights, notify account owners by email at least 30 days before they take effect.81          </footer>82        </article>83      </div>84    </div>85  );86}87