Add the CoffeyLabs.org copyright beside the licence link

A Legal component renders "© <year> CoffeyLabs.org · AGPL-3.0 source" with
both linked. It replaces the bare licence link in the sidebar footer and on
the login and setup pages, and sits at the foot of the user menu on phones,
where the sidebar is hidden. The sidebar and menu stack the two halves;
the auth pages keep one centred line. Screenshots retaken.
This commit is contained in:
2026-09-12 23:08:49 -07:00
parent 17a62fdc59
commit bcb9ac2e74
11 changed files with 42 additions and 15 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 73 KiB

+2 -3
View File
@@ -5,6 +5,7 @@ import { useLive } from "../state";
import { Mark } from "./Mark";
import { ThemeToggle } from "./ThemeSwitch";
import { UserMenu } from "./UserMenu";
import { Legal } from "./Legal";
// Account is reached through the user menu, so it is not a nav item.
const groups = [
@@ -87,9 +88,7 @@ export function Layout({ children }: { children: ReactNode }) {
<ThemeToggle />
</div>
<UserMenu placement="up" showName />
<a className="source" href="https://github.com/Coffey-Labs/WGX" target="_blank" rel="noreferrer">
AGPL-3.0 source
</a>
<Legal />
</div>
</aside>
+21
View File
@@ -0,0 +1,21 @@
// Copyright and licence line. Shown wherever the AGPL link used to stand
// alone: the sidebar footer, the auth pages and, on phones, the user menu.
export function Legal({ center = false }: { center?: boolean }) {
const year = new Date().getFullYear();
return (
<p className={`legal${center ? " center" : ""}`}>
<span>
&copy; {year}{" "}
<a href="https://coffeylabs.org" target="_blank" rel="noreferrer">
CoffeyLabs.org
</a>
</span>
<span className="legal-sep" aria-hidden="true">
·
</span>
<a href="https://github.com/Coffey-Labs/WGX" target="_blank" rel="noreferrer">
AGPL-3.0 source
</a>
</p>
);
}
+4
View File
@@ -3,6 +3,7 @@ import { Link } from "wouter";
import { ChevronDown, LogOut, Shield } from "lucide-react";
import { useAuth } from "../state";
import { ThemeSwitch } from "./ThemeSwitch";
import { Legal } from "./Legal";
// The signed-in user: avatar button that opens a small menu with the
// account page, the theme switch and sign out. `placement` says which way
@@ -67,6 +68,9 @@ export function UserMenu({ placement, showName = false }: { placement: "up" | "d
<button type="button" role="menuitem" className="menu-item" onClick={() => void signOut()}>
<LogOut size={16} /> Sign out
</button>
<div className="menu-foot">
<Legal />
</div>
</div>
)}
</div>
+2 -5
View File
@@ -3,6 +3,7 @@ import { api } from "../api";
import { errorMessage, useAuth } from "../state";
import { Field } from "../components/ui";
import { Mark } from "../components/Mark";
import { Legal } from "../components/Legal";
export function Login() {
const { refresh } = useAuth();
@@ -64,11 +65,7 @@ export function Login() {
<button className="btn primary" type="submit" disabled={busy} style={{ width: "100%", justifyContent: "center" }}>
{busy ? "…" : stage === "password" ? "Sign in" : "Verify"}
</button>
<p className="small faint" style={{ textAlign: "center", margin: "14px 0 0" }}>
<a href="https://github.com/Coffey-Labs/WGX" target="_blank" rel="noreferrer">
AGPL-3.0 source
</a>
</p>
<Legal center />
</div>
</form>
</div>
+2 -5
View File
@@ -3,6 +3,7 @@ import { api } from "../api";
import { errorMessage, useAuth } from "../state";
import { Field } from "../components/ui";
import { Mark } from "../components/Mark";
import { Legal } from "../components/Legal";
export function Setup() {
const { refresh } = useAuth();
@@ -61,11 +62,7 @@ export function Setup() {
<button className="btn primary" type="submit" disabled={busy} style={{ width: "100%", justifyContent: "center" }}>
{busy ? "…" : "Create administrator"}
</button>
<p className="small faint" style={{ textAlign: "center", margin: "14px 0 0" }}>
<a href="https://github.com/Coffey-Labs/WGX" target="_blank" rel="noreferrer">
AGPL-3.0 source
</a>
</p>
<Legal center />
</div>
</form>
</div>
+11 -2
View File
@@ -119,8 +119,16 @@ button, input, select, textarea { font: inherit; color: inherit; }
.nav a svg { width: 17px; height: 17px; flex: none; }
.sidebar-foot { margin-top: auto; display: flex; flex-direction: column; gap: 8px; padding-top: 12px; border-top: 1px solid var(--line); }
.sidebar-tools { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 0 2px; }
.source { font-size: 11.5px; color: var(--fg-faint); padding: 0 8px; }
.source:hover { color: var(--accent); }
.legal { display: flex; flex-wrap: wrap; gap: 0 6px; margin: 0; padding: 0 8px; font-size: 11.5px; color: var(--fg-faint); line-height: 1.5; }
.legal.center { justify-content: center; margin-top: 14px; padding: 0; }
.legal a { color: var(--fg-faint); }
.legal a:hover { color: var(--accent); }
.legal-sep { color: var(--line-strong); }
/* The sidebar is too narrow for one line; stack the two halves there. */
.sidebar-foot .legal, .menu-foot .legal { flex-direction: column; gap: 0; }
.sidebar-foot .legal-sep, .menu-foot .legal-sep { display: none; }
.menu-foot { display: none; margin-top: 4px; padding-top: 6px; border-top: 1px solid var(--line); }
.menu-foot .legal { padding: 4px 10px 2px; }
.main { padding: 24px 28px 48px; min-width: 0; }
.page-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 20px; flex-wrap: wrap; }
.page-head p { color: var(--fg-muted); margin: 2px 0 0; }
@@ -204,6 +212,7 @@ button, input, select, textarea { font: inherit; color: inherit; }
.topbar .brand { padding: 4px 6px; gap: 8px; }
.topbar-right { display: flex; align-items: center; gap: 4px; }
.topbar-right .live-pill { margin-right: 4px; }
.menu-foot { display: block; }
.main { padding: 16px 16px calc(var(--tabbar-h) + env(safe-area-inset-bottom) + 24px); }
.tabbar {
position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;