diff --git a/docs/screenshots/dashboard.jpg b/docs/screenshots/dashboard.jpg index 5c7245a..3aa3fa9 100644 Binary files a/docs/screenshots/dashboard.jpg and b/docs/screenshots/dashboard.jpg differ diff --git a/docs/screenshots/peer-config.jpg b/docs/screenshots/peer-config.jpg index b75cffb..7c68111 100644 Binary files a/docs/screenshots/peer-config.jpg and b/docs/screenshots/peer-config.jpg differ diff --git a/docs/screenshots/peer-overview.jpg b/docs/screenshots/peer-overview.jpg index 277edac..afad6cd 100644 Binary files a/docs/screenshots/peer-overview.jpg and b/docs/screenshots/peer-overview.jpg differ diff --git a/docs/screenshots/peers.jpg b/docs/screenshots/peers.jpg index 14fd020..b35162e 100644 Binary files a/docs/screenshots/peers.jpg and b/docs/screenshots/peers.jpg differ diff --git a/docs/screenshots/settings.jpg b/docs/screenshots/settings.jpg index 2e2c74e..6aa662e 100644 Binary files a/docs/screenshots/settings.jpg and b/docs/screenshots/settings.jpg differ diff --git a/web/src/components/Layout.tsx b/web/src/components/Layout.tsx index 1e4cb74..03bd620 100644 --- a/web/src/components/Layout.tsx +++ b/web/src/components/Layout.tsx @@ -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 }) { - - AGPL-3.0 source - + diff --git a/web/src/components/Legal.tsx b/web/src/components/Legal.tsx new file mode 100644 index 0000000..6e929a0 --- /dev/null +++ b/web/src/components/Legal.tsx @@ -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 ( +

+ + © {year}{" "} + + CoffeyLabs.org + + + + + AGPL-3.0 source + +

+ ); +} diff --git a/web/src/components/UserMenu.tsx b/web/src/components/UserMenu.tsx index 21cd011..3efdba7 100644 --- a/web/src/components/UserMenu.tsx +++ b/web/src/components/UserMenu.tsx @@ -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 +
+ +
)} diff --git a/web/src/pages/Login.tsx b/web/src/pages/Login.tsx index e8c963b..6702055 100644 --- a/web/src/pages/Login.tsx +++ b/web/src/pages/Login.tsx @@ -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() { -

- - AGPL-3.0 source - -

+ diff --git a/web/src/pages/Setup.tsx b/web/src/pages/Setup.tsx index ab1086b..2dcd33b 100644 --- a/web/src/pages/Setup.tsx +++ b/web/src/pages/Setup.tsx @@ -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() { -

- - AGPL-3.0 source - -

+ diff --git a/web/src/styles.css b/web/src/styles.css index 1c89afb..f606865 100644 --- a/web/src/styles.css +++ b/web/src/styles.css @@ -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;